diff --git a/AUTHORS b/AUTHORS
index 6a4dc8e..8231fc7c 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -808,6 +808,7 @@
 Shanmuga Pandi M <shanmuga.m@samsung.com>
 Shaobo Yan <shaobo.yan@intel.com>
 Shashi Kumar <sk.kumar@samsung.com>
+Shawn Anastasio <shawnanastasio@gmail.com>
 Shen Yu <shenyu.tcv@gmail.com>
 Sherry Mou <wenjinm@amazon.com>
 Shez Baig <sbaig1@bloomberg.net>
diff --git a/BUILD.gn b/BUILD.gn
index b708c27a..c312373 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -723,6 +723,7 @@
   if ((is_linux && !is_chromecast) ||
       (is_win && (use_drfuzz || use_libfuzzer)) || (use_libfuzzer && is_mac)) {
     deps += [
+      "//chrome/services/cups_ipp_parser/public/cpp:fuzzers",
       "//testing/libfuzzer/fuzzers",
       "//third_party/grpc:fuzzers",
       "//third_party/icu/fuzzers",
diff --git a/DEPS b/DEPS
index a15e5c4..f0ef184 100644
--- a/DEPS
+++ b/DEPS
@@ -127,11 +127,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': 'e3b205b1202fe9e53ee98994a6e777816406211e',
+  'skia_revision': '2722083cbe1f694e502288df1a240b07a7f39bda',
   # 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': 'd7d9726de58afdf80af43a04b731ab0247d9a42d',
+  'v8_revision': 'a32d20ab20f5a0416bc1bfab66b142c30269f1c0',
   # 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.
@@ -139,15 +139,15 @@
   # 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': 'f78131dac0763e4c2d1310a9560cbd311e5dea64',
+  'angle_revision': 'fe14b2e503a5991aeb033836bb4d525508475b52',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
-  'swiftshader_revision': '5efe611882433a634d2a9dc662f2940d0dca3d83',
+  'swiftshader_revision': '9b433073ba385393e1afdc873fab2502bcb8b056',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
-  'pdfium_revision': '01e1527e35e2b21c9d6b5434cf2123e1a34dc58b',
+  'pdfium_revision': 'a7e0cc8291d38a63d17ddb0078205801488c0d7e',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling openmax_dl
   # and whatever else without interference from each other.
@@ -190,7 +190,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling catapult
   # and whatever else without interference from each other.
-  'catapult_revision': 'a4323c9b818b66583feb3bd7df786f564ee2b756',
+  'catapult_revision': '85a76645b4e4b3f0872261d2c8773ac4ffe9fe07',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -238,7 +238,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'spv_tools_revision': 'fc3897b5f585b53291c75f5da7060acd7638ef18',
+  'spv_tools_revision': '002ef361cabc486a2f3567d646363334d50cc462',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -254,7 +254,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'dawn_revision': 'b92fa105572a598968764e578b95fe0b693c945b',
+  'dawn_revision': '9b8d2b0bbfad88916b6cef1f060d9047b0dcf7e8',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -727,7 +727,7 @@
 
   # Build tools for Chrome OS. Note: This depends on third_party/pyelftools.
   'src/third_party/chromite': {
-      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '73f6992d34868b8002380c864cd1a3273d2e4ce1',
+      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '16c7224d7b9bf27e08199e542a13db4b9a52749e',
       'condition': 'checkout_linux',
   },
 
@@ -752,7 +752,7 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '18f119bb3a0335fe9fdf8b94e5eebcea527784d9',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'd13a3a7aff05f1e54bbf1307ddb9a3359ed2b3b5',
 
   'src/third_party/devtools-node-modules':
     Var('chromium_git') + '/external/github.com/ChromeDevTools/devtools-node-modules' + '@' + Var('devtools_node_modules_revision'),
@@ -793,7 +793,7 @@
     Var('chromium_git') + '/chromium/deps/flac.git' + '@' + 'af862024c8c8fa0ae07ced05e89013d881b00596',
 
   'src/third_party/flatbuffers/src':
-    Var('chromium_git') + '/external/github.com/google/flatbuffers.git' + '@' + '4f32cbf268a8ad469974b9453924a3582dbf2f30',
+    Var('chromium_git') + '/external/github.com/google/flatbuffers.git' + '@' + '9bf9b18f0a705dfd6d50b98056463a55de6a1bf9',
 
   # Used for embedded builds. CrOS & Linux use the system version.
   'src/third_party/fontconfig/src': {
@@ -802,7 +802,7 @@
   },
 
   'src/third_party/grpc/src': {
-      'url': Var('chromium_git') + '/external/github.com/grpc/grpc.git' + '@' + '318c67782a752a8324233ff95e594a19f85578a7',
+      'url': Var('chromium_git') + '/external/github.com/grpc/grpc.git' + '@' + 'e60c4fc034815ac2cff62da047e7144172237036',
   },
 
   'src/third_party/freetype/src':
@@ -985,7 +985,7 @@
   },
 
   'src/third_party/libvpx/source/libvpx':
-    Var('chromium_git') + '/webm/libvpx.git' + '@' +  '986b2bef7f475543a441cf9aa5a3ca55dd57ccae',
+    Var('chromium_git') + '/webm/libvpx.git' + '@' +  '2d403737b88f76ce8410237a8eb682cc556ac302',
 
   'src/third_party/libwebm/source':
     Var('chromium_git') + '/webm/libwebm.git' + '@' + '51ca718c3adf0ddedacd7df25fe45f67dc5a9ce1',
@@ -1091,7 +1091,7 @@
   },
 
   'src/third_party/perfetto':
-    Var('android_git') + '/platform/external/perfetto.git' + '@' +  'afb82004c0bec36b4a46840bfe58840bacabff17',
+    Var('android_git') + '/platform/external/perfetto.git' + '@' +  'ebeca2a9eb81b045ce58ff7bf049e8b4c79bf002',
 
   'src/third_party/perl': {
       'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + 'ac0d98b5cee6c024b0cffeb4f8f45b6fc5ccdb78',
@@ -1306,7 +1306,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@9eb111e85e7e41b16a1144bc6108f127ba2c3e0d',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@8bb5b647cd02dcd9550c1f0bd3af49e2c87687cf',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/android_webview/browser/aw_content_browser_client.cc b/android_webview/browser/aw_content_browser_client.cc
index 594c9f19..fd58ff6 100644
--- a/android_webview/browser/aw_content_browser_client.cc
+++ b/android_webview/browser/aw_content_browser_client.cc
@@ -111,6 +111,16 @@
 namespace {
 static bool g_should_create_task_scheduler = true;
 
+#if DCHECK_IS_ON()
+// A boolean value to determine if the NetworkContext has been created yet. This
+// exists only to check correctness: g_check_cleartext_permitted may only be set
+// before the NetworkContext has been created (otherwise,
+// g_check_cleartext_permitted won't have any effect).
+bool g_created_network_context_params = false;
+#endif
+// On apps targeting API level O or later, check cleartext is enforced.
+bool g_check_cleartext_permitted = false;
+
 // TODO(sgurun) move this to its own file.
 // This class filters out incoming aw_contents related IPC messages for the
 // renderer process on the IPC thread.
@@ -267,6 +277,14 @@
   return AwBrowserContext::GetDefault();
 }
 
+// static
+void AwContentBrowserClient::set_check_cleartext_permitted(bool permitted) {
+#if DCHECK_IS_ON()
+  DCHECK(!g_created_network_context_params);
+#endif
+  g_check_cleartext_permitted = permitted;
+}
+
 AwContentBrowserClient::AwContentBrowserClient(
     AwFeatureListCreator* aw_feature_list_creator)
     : net_log_(new net::NetLog()),
@@ -343,6 +361,11 @@
 
   // WebView does not support ftp yet.
   context_params->enable_ftp_url_support = false;
+
+#if DCHECK_IS_ON()
+  g_created_network_context_params = true;
+#endif
+  context_params->check_clear_text_permitted = g_check_cleartext_permitted;
   return context_params;
 }
 
diff --git a/android_webview/browser/aw_content_browser_client.h b/android_webview/browser/aw_content_browser_client.h
index 5fa0fce..70eeb6f 100644
--- a/android_webview/browser/aw_content_browser_client.h
+++ b/android_webview/browser/aw_content_browser_client.h
@@ -45,6 +45,11 @@
   // Deprecated: use AwBrowserContext::GetDefault() instead.
   static AwBrowserContext* GetAwBrowserContext();
 
+  // Sets whether the net stack should check the cleartext policy from the
+  // platform. For details, see
+  // https://developer.android.com/reference/android/security/NetworkSecurityPolicy.html#isCleartextTrafficPermitted().
+  static void set_check_cleartext_permitted(bool permitted);
+
   // |aw_feature_list_creator| should not be null.
   explicit AwContentBrowserClient(
       AwFeatureListCreator* aw_feature_list_creator);
diff --git a/android_webview/browser/aw_contents_statics.cc b/android_webview/browser/aw_contents_statics.cc
index 319634f..8574d70 100644
--- a/android_webview/browser/aw_contents_statics.cc
+++ b/android_webview/browser/aw_contents_statics.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "android_webview/browser/aw_browser_context.h"
+#include "android_webview/browser/aw_content_browser_client.h"
 #include "android_webview/browser/aw_contents.h"
 #include "android_webview/browser/aw_contents_io_thread_client.h"
 #include "android_webview/browser/net/aw_url_request_context_getter.h"
@@ -122,6 +123,12 @@
 void JNI_AwContentsStatics_SetCheckClearTextPermitted(
     JNIEnv* env,
     jboolean permitted) {
+  // Notify both the legacy and NS code paths of this setting. We do this
+  // because this method may be called before we initialize the FeatureList
+  // during AwMainDelegate::PostEarlyInitialization (which means we can't
+  // reliably know at this point if we're in the NetworkService or legacy code
+  // path).
+  AwContentBrowserClient::set_check_cleartext_permitted(permitted);
   AwURLRequestContextGetter::set_check_cleartext_permitted(permitted);
 }
 
diff --git a/android_webview/system_webview_apk_tmpl.gni b/android_webview/system_webview_apk_tmpl.gni
index b11550a..75e8d20 100644
--- a/android_webview/system_webview_apk_tmpl.gni
+++ b/android_webview/system_webview_apk_tmpl.gni
@@ -32,8 +32,18 @@
 
     if (!_use_trichrome_library) {
       shared_libraries = [ "//android_webview:libwebviewchromium" ]
+      deps += [
+        "//third_party/crashpad/crashpad/handler:crashpad_handler_trampoline",
+      ]
+      loadable_modules = [ "$root_out_dir/libcrashpad_handler_trampoline.so" ]
+
       if (build_apk_secondary_abi && android_64bit_target_cpu) {
         secondary_abi_shared_libraries = [ "//android_webview:libwebviewchromium($android_secondary_abi_toolchain)" ]
+        _trampoline = "//third_party/crashpad/crashpad/handler:crashpad_handler_trampoline($android_secondary_abi_toolchain)"
+        deps += [ _trampoline ]
+        _secondary_out_dir = get_label_info(_trampoline, "root_out_dir")
+        secondary_abi_loadable_modules =
+            [ "$_secondary_out_dir/libcrashpad_handler_trampoline.so" ]
       }
     } else {
       uncompress_shared_libraries = true
@@ -42,6 +52,11 @@
       # architecture.
       if (android_64bit_target_cpu) {
         shared_libraries = [ "//android_webview:monochrome" ]
+        deps += [
+          "//third_party/crashpad/crashpad/handler:crashpad_handler_trampoline",
+        ]
+        loadable_modules = [ "$root_out_dir/libcrashpad_handler_trampoline.so" ]
+
         if (build_apk_secondary_abi) {
           secondary_native_lib_placeholders = [ "libdummy.so" ]
         }
diff --git a/apps/launcher.cc b/apps/launcher.cc
index d248c6e..c4f8f75 100644
--- a/apps/launcher.cc
+++ b/apps/launcher.cc
@@ -160,8 +160,8 @@
         FROM_HERE,
         {base::TaskPriority::USER_VISIBLE, base::MayBlock(),
          base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
-        base::Bind(&PlatformAppPathLauncher::MakePathAbsolute, this,
-                   current_directory));
+        base::BindOnce(&PlatformAppPathLauncher::MakePathAbsolute, this,
+                       current_directory));
   }
 
  private:
@@ -184,7 +184,7 @@
 
     base::PostTaskWithTraits(
         FROM_HERE, {BrowserThread::UI},
-        base::Bind(&PlatformAppPathLauncher::Launch, this));
+        base::BindOnce(&PlatformAppPathLauncher::Launch, this));
   }
 
   void OnFilesValid(std::unique_ptr<std::set<base::FilePath>> directory_paths) {
diff --git a/ash/accessibility/accessibility_focus_ring_group.cc b/ash/accessibility/accessibility_focus_ring_group.cc
index ffd7811..c8a5f2a 100644
--- a/ash/accessibility/accessibility_focus_ring_group.cc
+++ b/ash/accessibility/accessibility_focus_ring_group.cc
@@ -52,7 +52,7 @@
       base::TimeDelta::FromMilliseconds(kFocusFadeOutTimeMilliseconds);
 }
 
-AccessibilityFocusRingGroup::~AccessibilityFocusRingGroup(){};
+AccessibilityFocusRingGroup::~AccessibilityFocusRingGroup() {}
 
 void AccessibilityFocusRingGroup::SetColor(
     SkColor color,
diff --git a/ash/accessibility/accessibility_layer.h b/ash/accessibility/accessibility_layer.h
index 1a5f30d..27291511 100644
--- a/ash/accessibility/accessibility_layer.h
+++ b/ash/accessibility/accessibility_layer.h
@@ -32,7 +32,7 @@
   virtual void OnAnimationStep(base::TimeTicks timestamp) = 0;
 
  protected:
-  virtual ~AccessibilityLayerDelegate(){};
+  virtual ~AccessibilityLayerDelegate() {}
 };
 
 // AccessibilityLayer manages a global always-on-top layer used to
diff --git a/ash/app_list/app_list_controller_impl.cc b/ash/app_list/app_list_controller_impl.cc
index 31254ce..21c15656 100644
--- a/ash/app_list/app_list_controller_impl.cc
+++ b/ash/app_list/app_list_controller_impl.cc
@@ -999,6 +999,13 @@
   return Shell::Get()->assistant_controller()->view_delegate();
 }
 
+void AppListControllerImpl::OnSearchResultVisibilityChanged(
+    const std::string& id,
+    bool visibility) {
+  if (client_)
+    client_->OnSearchResultVisibilityChanged(id, visibility);
+}
+
 void AppListControllerImpl::AddObserver(AppListControllerObserver* observer) {
   observers_.AddObserver(observer);
 }
diff --git a/ash/app_list/app_list_controller_impl.h b/ash/app_list/app_list_controller_impl.h
index 3c243c8c..03d6825f 100644
--- a/ash/app_list/app_list_controller_impl.h
+++ b/ash/app_list/app_list_controller_impl.h
@@ -195,6 +195,8 @@
   void GetNavigableContentsFactory(
       content::mojom::NavigableContentsFactoryRequest request) override;
   ash::AssistantViewDelegate* GetAssistantViewDelegate() override;
+  void OnSearchResultVisibilityChanged(const std::string& id,
+                                       bool visibility) override;
 
   void AddObserver(AppListControllerObserver* observer);
   void RemoveObserver(AppListControllerObserver* obsever);
diff --git a/ash/app_list/app_list_view_delegate.h b/ash/app_list/app_list_view_delegate.h
index 705a012..79cbe0070 100644
--- a/ash/app_list/app_list_view_delegate.h
+++ b/ash/app_list/app_list_view_delegate.h
@@ -137,6 +137,11 @@
 
   // Returns the AssistantViewDelegate.
   virtual ash::AssistantViewDelegate* GetAssistantViewDelegate() = 0;
+
+  // Called if a search result has its visibility updated and wants to
+  // be notified (i.e. its notify_visibility_change() returns true).
+  virtual void OnSearchResultVisibilityChanged(const std::string& id,
+                                               bool visibility) = 0;
 };
 
 }  // namespace app_list
diff --git a/ash/app_list/model/search/search_result.h b/ash/app_list/model/search/search_result.h
index d3255cc..0e0ed94e 100644
--- a/ash/app_list/model/search/search_result.h
+++ b/ash/app_list/model/search/search_result.h
@@ -121,6 +121,14 @@
   int percent_downloaded() const { return percent_downloaded_; }
   void SetPercentDownloaded(int percent_downloaded);
 
+  bool notify_visibility_change() const {
+    return metadata_->notify_visibility_change;
+  }
+
+  void set_notify_visibility_change(bool notify_visibility_change) {
+    metadata_->notify_visibility_change = notify_visibility_change;
+  }
+
   bool is_omnibox_search() const { return metadata_->is_omnibox_search; }
   void set_is_omnibox_search(bool is_omnibox_search) {
     metadata_->is_omnibox_search = is_omnibox_search;
diff --git a/ash/app_list/test/app_list_test_view_delegate.cc b/ash/app_list/test/app_list_test_view_delegate.cc
index a27f88a9..9715d6a 100644
--- a/ash/app_list/test/app_list_test_view_delegate.cc
+++ b/ash/app_list/test/app_list_test_view_delegate.cc
@@ -120,6 +120,10 @@
   return nullptr;
 }
 
+void AppListTestViewDelegate::OnSearchResultVisibilityChanged(
+    const std::string& id,
+    bool visibility) {}
+
 bool AppListTestViewDelegate::IsCommandIdChecked(int command_id) const {
   return true;
 }
diff --git a/ash/app_list/test/app_list_test_view_delegate.h b/ash/app_list/test/app_list_test_view_delegate.h
index 3b2dcfeb..3202007 100644
--- a/ash/app_list/test/app_list_test_view_delegate.h
+++ b/ash/app_list/test/app_list_test_view_delegate.h
@@ -90,6 +90,8 @@
   void GetNavigableContentsFactory(
       content::mojom::NavigableContentsFactoryRequest request) override;
   ash::AssistantViewDelegate* GetAssistantViewDelegate() override;
+  void OnSearchResultVisibilityChanged(const std::string& id,
+                                       bool visibility) override;
 
   // Do a bulk replacement of the items in the model.
   void ReplaceTestModel(int item_count);
diff --git a/ash/app_list/test/test_app_list_client.h b/ash/app_list/test/test_app_list_client.h
index 28752b90..8bb67df 100644
--- a/ash/app_list/test/test_app_list_client.h
+++ b/ash/app_list/test/test_app_list_client.h
@@ -55,6 +55,8 @@
   void OnPageBreakItemDeleted(const std::string& id) override {}
   void GetNavigableContentsFactory(
       content::mojom::NavigableContentsFactoryRequest request) override {}
+  void OnSearchResultVisibilityChanged(const std::string& id,
+                                       bool visibility) override {}
 
  private:
   mojo::Binding<mojom::AppListClient> binding_;
diff --git a/ash/app_list/views/search_result_answer_card_view.cc b/ash/app_list/views/search_result_answer_card_view.cc
index 709cd4a..ea74d00 100644
--- a/ash/app_list/views/search_result_answer_card_view.cc
+++ b/ash/app_list/views/search_result_answer_card_view.cc
@@ -317,7 +317,8 @@
 
 SearchResultAnswerCardView::SearchResultAnswerCardView(
     AppListViewDelegate* view_delegate)
-    : search_answer_container_view_(
+    : SearchResultContainerView(view_delegate),
+      search_answer_container_view_(
           new AnswerCardResultView(this, view_delegate)) {
   AddChildView(search_answer_container_view_);
   AddObservedResultView(search_answer_container_view_);
diff --git a/ash/app_list/views/search_result_container_view.cc b/ash/app_list/views/search_result_container_view.cc
index 1203e2fd..0e20393 100644
--- a/ash/app_list/views/search_result_container_view.cc
+++ b/ash/app_list/views/search_result_container_view.cc
@@ -12,7 +12,11 @@
 
 namespace app_list {
 
-SearchResultContainerView::SearchResultContainerView() = default;
+SearchResultContainerView::SearchResultContainerView(
+    AppListViewDelegate* view_delegate)
+    : view_delegate_(view_delegate) {
+  DCHECK(view_delegate);
+}
 
 SearchResultContainerView::~SearchResultContainerView() {
   if (results_)
@@ -97,6 +101,16 @@
   return nullptr;
 }
 
+void SearchResultContainerView::SetShown(bool shown) {
+  if (shown_ == shown) {
+    return;
+  }
+  shown_ = shown;
+  OnShownChanged();
+}
+
+void SearchResultContainerView::OnShownChanged() {}
+
 void SearchResultContainerView::ScheduleUpdate() {
   // When search results are added one by one, each addition generates an update
   // request. Consolidates those update requests into one Update call.
diff --git a/ash/app_list/views/search_result_container_view.h b/ash/app_list/views/search_result_container_view.h
index 95c16b58..9e9dfeea 100644
--- a/ash/app_list/views/search_result_container_view.h
+++ b/ash/app_list/views/search_result_container_view.h
@@ -8,6 +8,7 @@
 #include <stddef.h>
 
 #include "ash/app_list/app_list_export.h"
+#include "ash/app_list/app_list_view_delegate.h"
 #include "ash/app_list/model/app_list_model.h"
 #include "ash/app_list/model/search/search_model.h"
 #include "base/macros.h"
@@ -38,7 +39,7 @@
     virtual void OnSearchResultContainerResultFocused(
         SearchResultBaseView* focused_result_view) = 0;
   };
-  SearchResultContainerView();
+  explicit SearchResultContainerView(AppListViewDelegate* view_delegate);
   ~SearchResultContainerView() override;
 
   void set_delegate(Delegate* delegate) { delegate_ = delegate; }
@@ -87,6 +88,14 @@
   // exist.
   virtual SearchResultBaseView* GetFirstResultView();
 
+  // Called from SearchResultPageView OnShown/OnHidden
+  void SetShown(bool shown);
+  bool shown() const { return shown_; }
+  // Called when SetShowing has changed a result.
+  virtual void OnShownChanged();
+
+  AppListViewDelegate* view_delegate() const { return view_delegate_; }
+
  private:
   // Schedules an Update call using |update_factory_|. Do nothing if there is a
   // pending call.
@@ -103,6 +112,10 @@
 
   SearchModel::SearchResults* results_ = nullptr;  // Owned by SearchModel.
 
+  // view delegate for notifications.
+  bool shown_ = false;
+  AppListViewDelegate* const view_delegate_;
+
   ScopedObserver<SearchResultBaseView, ViewObserver> result_view_observer_{
       this};
 
diff --git a/ash/app_list/views/search_result_list_view.cc b/ash/app_list/views/search_result_list_view.cc
index c4ac1708..787d0e8 100644
--- a/ash/app_list/views/search_result_list_view.cc
+++ b/ash/app_list/views/search_result_list_view.cc
@@ -33,7 +33,8 @@
 
 SearchResultListView::SearchResultListView(AppListMainView* main_view,
                                            AppListViewDelegate* view_delegate)
-    : main_view_(main_view),
+    : SearchResultContainerView(view_delegate),
+      main_view_(main_view),
       view_delegate_(view_delegate),
       results_container_(new views::View) {
   results_container_->SetLayoutManager(
diff --git a/ash/app_list/views/search_result_page_view.cc b/ash/app_list/views/search_result_page_view.cc
index f5e2d12..fa1dcc0 100644
--- a/ash/app_list/views/search_result_page_view.cc
+++ b/ash/app_list/views/search_result_page_view.cc
@@ -346,7 +346,18 @@
 void SearchResultPageView::OnHidden() {
   // Hide the search results page when it is behind search box to avoid focus
   // being moved onto suggested apps when zero state is enabled.
+  AppListPage::OnHidden();
   SetVisible(false);
+  for (auto* container_view : result_container_views_) {
+    container_view->SetShown(false);
+  }
+}
+
+void SearchResultPageView::OnShown() {
+  AppListPage::OnShown();
+  for (auto* container_view : result_container_views_) {
+    container_view->SetShown(true);
+  }
 }
 
 gfx::Rect SearchResultPageView::GetPageBoundsForState(
diff --git a/ash/app_list/views/search_result_page_view.h b/ash/app_list/views/search_result_page_view.h
index b3740e4..ba51636 100644
--- a/ash/app_list/views/search_result_page_view.h
+++ b/ash/app_list/views/search_result_page_view.h
@@ -44,6 +44,8 @@
 
   // AppListPage overrides:
   void OnHidden() override;
+  void OnShown() override;
+
   gfx::Rect GetPageBoundsForState(ash::AppListState state) const override;
   void OnAnimationUpdated(double progress,
                           ash::AppListState from_state,
diff --git a/ash/app_list/views/search_result_tile_item_list_view.cc b/ash/app_list/views/search_result_tile_item_list_view.cc
index 4567fba..ca6e01e 100644
--- a/ash/app_list/views/search_result_tile_item_list_view.cc
+++ b/ash/app_list/views/search_result_tile_item_list_view.cc
@@ -8,6 +8,8 @@
 
 #include <algorithm>
 #include <memory>
+#include <set>
+#include <string>
 
 #include "ash/app_list/app_list_util.h"
 #include "ash/app_list/app_list_view_delegate.h"
@@ -20,6 +22,7 @@
 #include "base/bind.h"
 #include "base/callback.h"
 #include "base/i18n/rtl.h"
+#include "base/stl_util.h"
 #include "ui/gfx/color_palette.h"
 #include "ui/gfx/geometry/insets.h"
 #include "ui/views/background.h"
@@ -50,7 +53,8 @@
     SearchResultPageView* search_result_page_view,
     views::Textfield* search_box,
     AppListViewDelegate* view_delegate)
-    : search_result_page_view_(search_result_page_view),
+    : SearchResultContainerView(view_delegate),
+      search_result_page_view_(search_result_page_view),
       search_box_(search_box),
       is_play_store_app_search_enabled_(
           app_list_features::IsPlayStoreAppSearchEnabled()),
@@ -109,16 +113,27 @@
   ash::SearchResultDisplayType previous_display_type =
       ash::SearchResultDisplayType::kNone;
 
+  std::set<std::string> result_id_removed, result_id_added;
   for (size_t i = 0; i < kMaxNumSearchResultTiles; ++i) {
+    // If the current result at i exists, wants to be notified and is a
+    // different id, notify it that it is being hidden.
+    SearchResult* current_result = tile_views_[i]->result();
+    if (current_result != nullptr) {
+      result_id_removed.insert(current_result->id());
+    }
+
     if (i >= display_results.size()) {
       if (is_play_store_app_search_enabled_)
         separator_views_[i]->SetVisible(false);
+
       tile_views_[i]->SetResult(nullptr);
       continue;
     }
 
     SearchResult* item = display_results[i];
+
     tile_views_[i]->SetResult(item);
+    result_id_added.insert(item->id());
 
     if (is_play_store_app_search_enabled_ ||
         is_app_reinstall_recommendation_enabled_) {
@@ -139,6 +154,33 @@
     previous_display_type = item->display_type();
   }
 
+  // notify visibility changes, if needed.
+  std::set<std::string> actual_added_ids =
+      base::STLSetDifference<std::set<std::string>>(result_id_added,
+                                                    result_id_removed);
+
+  for (const std::string& added_id : actual_added_ids) {
+    SearchResult* added =
+        view_delegate()->GetSearchModel()->FindSearchResult(added_id);
+    if (added != nullptr && added->notify_visibility_change()) {
+      view_delegate()->OnSearchResultVisibilityChanged(added->id(), shown());
+    }
+  }
+  if (shown() != false) {
+    std::set<std::string> actual_removed_ids =
+        base::STLSetDifference<std::set<std::string>>(result_id_removed,
+                                                      result_id_added);
+    // we only notify removed items if we're in the middle of showing.
+    for (const std::string& removed_id : actual_removed_ids) {
+      SearchResult* removed =
+          view_delegate()->GetSearchModel()->FindSearchResult(removed_id);
+      if (removed != nullptr && removed->notify_visibility_change()) {
+        view_delegate()->OnSearchResultVisibilityChanged(removed->id(),
+                                                         false /*=shown*/);
+      }
+    }
+  }
+
   set_container_score(
       display_results.empty() ? 0 : display_results.front()->display_score());
 
@@ -231,4 +273,37 @@
   return "SearchResultTileItemListView";
 }
 
+void SearchResultTileItemListView::OnShownChanged() {
+  SearchResultContainerView::OnShownChanged();
+  for (const auto* tile_view : tile_views_) {
+    SearchResult* result = tile_view->result();
+    if (result == nullptr) {
+      continue;
+    }
+    if (result->notify_visibility_change()) {
+      view_delegate()->OnSearchResultVisibilityChanged(result->id(), shown());
+    }
+  }
+}
+
+void SearchResultTileItemListView::VisibilityChanged(View* starting_from,
+                                                     bool is_visible) {
+  SearchResultContainerView::VisibilityChanged(starting_from, is_visible);
+  // We only do this work when is_visible is false, since this is how we
+  // receive the event. We filter and only run when shown.
+  if (is_visible && shown()) {
+    return;
+  }
+  for (const auto* tile_view : tile_views_) {
+    SearchResult* result = tile_view->result();
+    if (result == nullptr) {
+      continue;
+    }
+    if (result->notify_visibility_change()) {
+      view_delegate()->OnSearchResultVisibilityChanged(result->id(),
+                                                       false /*=visible*/);
+    }
+  }
+}
+
 }  // namespace app_list
diff --git a/ash/app_list/views/search_result_tile_item_list_view.h b/ash/app_list/views/search_result_tile_item_list_view.h
index 27cd79f..27faa06 100644
--- a/ash/app_list/views/search_result_tile_item_list_view.h
+++ b/ash/app_list/views/search_result_tile_item_list_view.h
@@ -43,6 +43,13 @@
     return tile_views_;
   }
 
+  // Overridden from SearchResultContainerView:
+  void OnShownChanged() override;
+
+ protected:
+  // View overrides:
+  void VisibilityChanged(View* starting_from, bool is_visible) override;
+
  private:
   // Overridden from SearchResultContainerView:
   int DoUpdate() override;
diff --git a/ash/app_list/views/suggestion_chip_container_view.cc b/ash/app_list/views/suggestion_chip_container_view.cc
index b77c84dc..f068866 100644
--- a/ash/app_list/views/suggestion_chip_container_view.cc
+++ b/ash/app_list/views/suggestion_chip_container_view.cc
@@ -31,13 +31,15 @@
 
 SuggestionChipContainerView::SuggestionChipContainerView(
     ContentsView* contents_view)
-    : contents_view_(contents_view) {
+    : SearchResultContainerView(
+          contents_view != nullptr
+              ? contents_view->GetAppListMainView()->view_delegate()
+              : nullptr),
+      contents_view_(contents_view) {
   SetPaintToLayer();
   layer()->SetFillsBoundsOpaquely(false);
 
   DCHECK(contents_view);
-  view_delegate_ = contents_view_->GetAppListMainView()->view_delegate();
-
   views::BoxLayout* layout_manager =
       SetLayoutManager(std::make_unique<views::BoxLayout>(
           views::BoxLayout::Orientation::kHorizontal, gfx::Insets(),
@@ -49,7 +51,7 @@
                              AppListConfig::instance().num_start_page_tiles());
        ++i) {
     SearchResultSuggestionChipView* chip =
-        new SearchResultSuggestionChipView(view_delegate_);
+        new SearchResultSuggestionChipView(view_delegate());
     chip->SetVisible(false);
     chip->SetIndexInSuggestionChipContainer(i);
     suggestion_chip_views_.emplace_back(chip);
diff --git a/ash/app_list/views/suggestion_chip_container_view.h b/ash/app_list/views/suggestion_chip_container_view.h
index 1ce59ce..546d5d8 100644
--- a/ash/app_list/views/suggestion_chip_container_view.h
+++ b/ash/app_list/views/suggestion_chip_container_view.h
@@ -12,7 +12,6 @@
 
 namespace app_list {
 
-class AppListViewDelegate;
 class ContentsView;
 class SearchResultSuggestionChipView;
 
@@ -42,7 +41,6 @@
   bool IgnoreUpdateAndLayout() const;
 
   ContentsView* contents_view_ = nullptr;  // Not owned
-  AppListViewDelegate* view_delegate_ = nullptr;
 
   std::vector<SearchResultSuggestionChipView*> suggestion_chip_views_;  // Owned
 
diff --git a/ash/assistant/model/assistant_cache_model.cc b/ash/assistant/model/assistant_cache_model.cc
index b3ff4749..6b301c0d 100644
--- a/ash/assistant/model/assistant_cache_model.cc
+++ b/ash/assistant/model/assistant_cache_model.cc
@@ -48,7 +48,7 @@
     conversation_starters[id++] = starter.get();
 
   return conversation_starters;
-};
+}
 
 void AssistantCacheModel::NotifyConversationStartersChanged() {
   const std::map<int, const AssistantSuggestion*> conversation_starters =
diff --git a/ash/assistant/model/assistant_query.cc b/ash/assistant/model/assistant_query.cc
index 3aa720a..8b17210 100644
--- a/ash/assistant/model/assistant_query.cc
+++ b/ash/assistant/model/assistant_query.cc
@@ -16,7 +16,7 @@
 
 bool AssistantTextQuery::Empty() const {
   return text_.empty();
-};
+}
 
 // AssistantVoiceQuery ---------------------------------------------------------
 
diff --git a/ash/assistant/test/test_assistant_service.h b/ash/assistant/test/test_assistant_service.h
index 725b7d2..769f5ce 100644
--- a/ash/assistant/test/test_assistant_service.h
+++ b/ash/assistant/test/test_assistant_service.h
@@ -38,7 +38,7 @@
   void DismissNotification(chromeos::assistant::mojom::AssistantNotificationPtr
                                notification) override {}
   void CacheScreenContext(CacheScreenContextCallback callback) override;
-  void ClearScreenContextCache() override{};
+  void ClearScreenContextCache() override {}
   void OnAccessibilityStatusChanged(bool spoken_feedback_enabled) override {}
   void SendAssistantFeedback(
       chromeos::assistant::mojom::AssistantFeedbackPtr feedback) override {}
diff --git a/ash/assistant/ui/assistant_notification_overlay.cc b/ash/assistant/ui/assistant_notification_overlay.cc
index 83c69fc..8c95eb72 100644
--- a/ash/assistant/ui/assistant_notification_overlay.cc
+++ b/ash/assistant/ui/assistant_notification_overlay.cc
@@ -89,4 +89,4 @@
   layer()->SetFillsBoundsOpaquely(false);
 }
 
-};  // namespace ash
+}  // namespace ash
diff --git a/ash/autoclick/autoclick_unittest.cc b/ash/autoclick/autoclick_unittest.cc
index 43ffdeb..62ab94a 100644
--- a/ash/autoclick/autoclick_unittest.cc
+++ b/ash/autoclick/autoclick_unittest.cc
@@ -81,7 +81,7 @@
     scoped_task_environment_ =
         std::make_unique<base::test::ScopedTaskEnvironment>(
             base::test::ScopedTaskEnvironment::MainThreadType::UI_MOCK_TIME);
-  };
+  }
   ~AutoclickTest() override = default;
 
   void SetUp() override {
@@ -515,7 +515,8 @@
   EXPECT_TRUE(ui::EF_RIGHT_MOUSE_BUTTON & events[1].flags());
 }
 
-TEST_F(AutoclickTest, WaitsToDrawAnimationAfterDwellBegins) {
+// TODO(crbug.com/935651): The test has flaky crashes.
+TEST_F(AutoclickTest, DISABLED_WaitsToDrawAnimationAfterDwellBegins) {
   float ratio = GetAutoclickController()->GetStartGestureDelayRatioForTesting();
   int full_delay = ceil(1.0 / ratio) * 5;
   int animation_delay = 5;
@@ -625,8 +626,9 @@
   Shell::Get()->accessibility_controller()->SetAutoclickEnabled(false);
 }
 
-TEST_F(AutoclickTest,
-       StartsGestureOnTrayButtonButDoesNotClickIfMouseMovedWhenPaused) {
+TEST_F(
+    AutoclickTest,
+    DISABLED_StartsGestureOnTrayButtonButDoesNotClickIfMouseMovedWhenPaused) {
   Shell::Get()->accessibility_controller()->SetAutoclickEnabled(true);
   GetAutoclickController()->set_revert_to_left_click(false);
   GetAutoclickController()->SetAutoclickEventType(
diff --git a/ash/display/cros_display_config_unittest.cc b/ash/display/cros_display_config_unittest.cc
index 8bbd53cb..91ecf39 100644
--- a/ash/display/cros_display_config_unittest.cc
+++ b/ash/display/cros_display_config_unittest.cc
@@ -72,7 +72,7 @@
 class CrosDisplayConfigTest : public AshTestBase {
  public:
   CrosDisplayConfigTest() {}
-  ~CrosDisplayConfigTest() override{};
+  ~CrosDisplayConfigTest() override {}
 
   void SetUp() override {
     base::CommandLine::ForCurrentProcess()->AppendSwitch(
diff --git a/ash/display/display_color_manager.cc b/ash/display/display_color_manager.cc
index 1c8178c..b72a11a 100644
--- a/ash/display/display_color_manager.cc
+++ b/ash/display/display_color_manager.cc
@@ -420,7 +420,7 @@
 }
 
 DisplayColorManager::ColorCalibrationData::ColorCalibrationData()
-    : correction_matrix{1, 0, 0, 0, 1, 0, 0, 0, 1} {};
+    : correction_matrix{1, 0, 0, 0, 1, 0, 0, 0, 1} {}
 
 DisplayColorManager::ColorCalibrationData::~ColorCalibrationData() = default;
 
diff --git a/ash/display/screen_orientation_controller.h b/ash/display/screen_orientation_controller.h
index ce18117..af4cb31 100644
--- a/ash/display/screen_orientation_controller.h
+++ b/ash/display/screen_orientation_controller.h
@@ -76,7 +76,7 @@
 
   OrientationLockType natural_orientation() const {
     return natural_orientation_;
-  };
+  }
 
   // Add/Remove observers.
   void AddObserver(Observer* observer);
diff --git a/ash/focus_cycler_unittest.cc b/ash/focus_cycler_unittest.cc
index 1638d2b1..5632c93 100644
--- a/ash/focus_cycler_unittest.cc
+++ b/ash/focus_cycler_unittest.cc
@@ -44,7 +44,7 @@
     std::copy(accessible_panes_.begin(), accessible_panes_.end(),
               std::back_inserter(*panes));
   }
-  views::Widget* GetWidget() override { return widget_; };
+  views::Widget* GetWidget() override { return widget_; }
   const views::Widget* GetWidget() const override { return widget_; }
 
  private:
diff --git a/ash/keyboard/ash_keyboard_controller_unittest.cc b/ash/keyboard/ash_keyboard_controller_unittest.cc
index 0a03f43f..c02c96a 100644
--- a/ash/keyboard/ash_keyboard_controller_unittest.cc
+++ b/ash/keyboard/ash_keyboard_controller_unittest.cc
@@ -161,7 +161,7 @@
 
 class TestContainerBehavior : public keyboard::ContainerBehavior {
  public:
-  TestContainerBehavior() : keyboard::ContainerBehavior(nullptr){};
+  TestContainerBehavior() : keyboard::ContainerBehavior(nullptr) {}
   ~TestContainerBehavior() override = default;
 
   // keyboard::ContainerBehavior
diff --git a/ash/login/ui/lock_contents_view.h b/ash/login/ui/lock_contents_view.h
index 465d626..18cf104d 100644
--- a/ash/login/ui/lock_contents_view.h
+++ b/ash/login/ui/lock_contents_view.h
@@ -193,7 +193,7 @@
   // views::StyledLabelListener:
   void StyledLabelLinkClicked(views::StyledLabel* label,
                               const gfx::Range& range,
-                              int event_flags) override{};
+                              int event_flags) override {}
   // SessionObserver:
   void OnLockStateChanged(bool locked) override;
 
diff --git a/ash/login/ui/login_base_bubble_view.h b/ash/login/ui/login_base_bubble_view.h
index a93e3daf..12a9f92 100644
--- a/ash/login/ui/login_base_bubble_view.h
+++ b/ash/login/ui/login_base_bubble_view.h
@@ -46,9 +46,9 @@
 
   // ui::LayerAnimationObserver:
   void OnLayerAnimationEnded(ui::LayerAnimationSequence* sequence) override;
-  void OnLayerAnimationAborted(ui::LayerAnimationSequence* sequence) override{};
+  void OnLayerAnimationAborted(ui::LayerAnimationSequence* sequence) override {}
   void OnLayerAnimationScheduled(
-      ui::LayerAnimationSequence* sequence) override{};
+      ui::LayerAnimationSequence* sequence) override {}
 
   // views::View:
   gfx::Size CalculatePreferredSize() const override;
diff --git a/ash/public/cpp/default_frame_header.h b/ash/public/cpp/default_frame_header.h
index 3472e7f..1a3e6c76 100644
--- a/ash/public/cpp/default_frame_header.h
+++ b/ash/public/cpp/default_frame_header.h
@@ -58,7 +58,7 @@
     ~ColorAnimator();
 
     void SetTargetColor(SkColor target);
-    SkColor target_color() const { return target_color_; };
+    SkColor target_color() const { return target_color_; }
     SkColor GetCurrentColor();
     float get_value() const { return animation_.GetCurrentValue(); }
 
diff --git a/ash/public/interfaces/app_list.mojom b/ash/public/interfaces/app_list.mojom
index 82a731276..de7c7c3 100644
--- a/ash/public/interfaces/app_list.mojom
+++ b/ash/public/interfaces/app_list.mojom
@@ -82,6 +82,9 @@
                                     // indicates its type, e.g. installable from
                                     // PlayStore, installable from WebStore,
                                     // etc.
+  // If set to true, whether or not to send visibility updates through to to
+  // the chrome side when this result is set visible/invisible.
+  bool notify_visibility_change;
 };
 
 // All possible states of the app list.
@@ -369,6 +372,10 @@
   // Invoked when a "page break" item with |id| is deleted.
   OnPageBreakItemDeleted(string id);
 
+  // Updated when item with |id| is set to |visible|. Only sent if
+  // |notify_visibility_change| was set on the SearchResultMetadata.
+  OnSearchResultVisibilityChanged(string id, bool visibility);
+
   // Acquires a NavigableContentsFactory (indirectly) from the Content Service
   // to allow the app list to display embedded web contents. Currently used only
   // for answer card search results.
diff --git a/ash/shelf/assistant_overlay.cc b/ash/shelf/assistant_overlay.cc
index e78d9fa..1a3a752 100644
--- a/ash/shelf/assistant_overlay.cc
+++ b/ash/shelf/assistant_overlay.cc
@@ -278,7 +278,6 @@
       AddPaintLayer(static_cast<PaintedShape>(i));
   }
   ~AssistantIconBackground() override = default;
-  ;
 
   void MoveLargeShadow(const gfx::PointF& new_center) {
     gfx::Transform transform;
diff --git a/ash/shelf/shelf.cc b/ash/shelf/shelf.cc
index a2a91716..14b9c50 100644
--- a/ash/shelf/shelf.cc
+++ b/ash/shelf/shelf.cc
@@ -304,19 +304,16 @@
 }
 
 gfx::Rect Shelf::GetSystemTrayAnchorRect() const {
-  gfx::Rect workspace_bounds = GetUserWorkAreaBounds();
+  gfx::Rect work_area = GetUserWorkAreaBounds();
   switch (alignment_) {
     case SHELF_ALIGNMENT_BOTTOM:
     case SHELF_ALIGNMENT_BOTTOM_LOCKED:
-      return gfx::Rect(base::i18n::IsRTL() ? workspace_bounds.x()
-                                           : (workspace_bounds.right() - 1),
-                       workspace_bounds.bottom() - 1, 0, 0);
+      return gfx::Rect(base::i18n::IsRTL() ? work_area.x() : work_area.right(),
+                       work_area.bottom(), 0, 0);
     case SHELF_ALIGNMENT_LEFT:
-      return gfx::Rect(workspace_bounds.x(), workspace_bounds.bottom() - 1, 0,
-                       0);
+      return gfx::Rect(work_area.x(), work_area.bottom(), 0, 0);
     case SHELF_ALIGNMENT_RIGHT:
-      return gfx::Rect(workspace_bounds.right() - 1,
-                       workspace_bounds.bottom() - 1, 0, 0);
+      return gfx::Rect(work_area.right(), work_area.bottom(), 0, 0);
   }
   NOTREACHED();
   return gfx::Rect();
diff --git a/ash/shelf/shelf_bubble.h b/ash/shelf/shelf_bubble.h
index d7e43b8..e0f800b8 100644
--- a/ash/shelf/shelf_bubble.h
+++ b/ash/shelf/shelf_bubble.h
@@ -34,7 +34,7 @@
   virtual bool ShouldCloseOnMouseExit() = 0;
 
  protected:
-  void set_border_radius(int radius) { border_radius_ = radius; };
+  void set_border_radius(int radius) { border_radius_ = radius; }
 
   // Performs the actual bubble creation.
   void CreateBubble();
diff --git a/ash/shelf/shelf_widget_unittest.cc b/ash/shelf/shelf_widget_unittest.cc
index b813596..e075bd88 100644
--- a/ash/shelf/shelf_widget_unittest.cc
+++ b/ash/shelf/shelf_widget_unittest.cc
@@ -440,7 +440,7 @@
     ASSERT_NE(nullptr, primary_shelf_widget_);
     secondary_shelf_widget_ = Shelf::ForWindow(root_windows[1])->shelf_widget();
     ASSERT_NE(nullptr, secondary_shelf_widget_);
-  };
+  }
 
   void ExpectVisible(session_manager::SessionState state,
                      ShelfVisibility primary_shelf_visibility,
diff --git a/ash/system/message_center/ash_popup_alignment_delegate.cc b/ash/system/message_center/ash_popup_alignment_delegate.cc
index fa314ce..b17a8a9 100644
--- a/ash/system/message_center/ash_popup_alignment_delegate.cc
+++ b/ash/system/message_center/ash_popup_alignment_delegate.cc
@@ -84,8 +84,7 @@
 }
 
 int AshPopupAlignmentDelegate::GetBaseline() const {
-  return work_area_.bottom() - kUnifiedMenuVerticalPadding -
-         tray_bubble_height_;
+  return work_area_.bottom() - kUnifiedMenuPadding - tray_bubble_height_;
 }
 
 gfx::Rect AshPopupAlignmentDelegate::GetWorkArea() const {
diff --git a/ash/system/message_center/message_center_ui_delegate.h b/ash/system/message_center/message_center_ui_delegate.h
index be2cc4d3..826f8c52 100644
--- a/ash/system/message_center/message_center_ui_delegate.h
+++ b/ash/system/message_center/message_center_ui_delegate.h
@@ -12,7 +12,7 @@
 // Implementations are platform specific.
 class MessageCenterUiDelegate {
  public:
-  virtual ~MessageCenterUiDelegate(){};
+  virtual ~MessageCenterUiDelegate() {}
 
   // Called whenever a change to the visible UI has occurred.
   virtual void OnMessageCenterContentsChanged() = 0;
diff --git a/ash/system/message_center/unified_message_center_view.cc b/ash/system/message_center/unified_message_center_view.cc
index a9aa4b6..818e79d 100644
--- a/ash/system/message_center/unified_message_center_view.cc
+++ b/ash/system/message_center/unified_message_center_view.cc
@@ -286,7 +286,6 @@
 void UnifiedMessageCenterView::ListPreferredSizeChanged() {
   UpdateVisibility();
   PreferredSizeChanged();
-  ScrollToTarget();
   Layout();
 
   if (GetWidget() && !GetWidget()->IsClosed())
@@ -372,6 +371,9 @@
 
 void UnifiedMessageCenterView::OnDidChangeFocus(views::View* before,
                                                 views::View* now) {
+  if (message_list_view_->is_deleting_removed_notifications())
+    return;
+
   OnMessageCenterScrolled();
 }
 
diff --git a/ash/system/message_center/unified_message_center_view_unittest.cc b/ash/system/message_center/unified_message_center_view_unittest.cc
index 59eb9684..a0979d5 100644
--- a/ash/system/message_center/unified_message_center_view_unittest.cc
+++ b/ash/system/message_center/unified_message_center_view_unittest.cc
@@ -17,7 +17,6 @@
 #include "base/macros.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/test/scoped_feature_list.h"
 #include "components/prefs/pref_service.h"
 #include "ui/message_center/message_center.h"
 #include "ui/message_center/views/message_view.h"
@@ -144,7 +143,7 @@
     return message_center_view()->scroller_->contents();
   }
 
-  StackingNotificationCounterView* GetStackingCounter() {
+  views::View* GetStackingCounter() {
     return message_center_view()->stacking_counter_;
   }
 
@@ -156,6 +155,27 @@
     return message_center_view()->stacking_counter_->clear_all_button_;
   }
 
+  message_center::MessageView* ToggleFocusToMessageView(int index,
+                                                        bool reverse) {
+    auto* focus_manager = message_center_view()->GetFocusManager();
+    if (!focus_manager)
+      return nullptr;
+
+    message_center::MessageView* focused_message_view = nullptr;
+    const int max_focus_toggles = 30;
+    for (int i = 0; i < max_focus_toggles; ++i) {
+      focus_manager->AdvanceFocus(reverse);
+      auto* focused_view = focus_manager->GetFocusedView();
+      // The MessageView is wrapped in container view in the MessageList.
+      if (focused_view->parent() == GetMessageListView()->child_at(index)) {
+        focused_message_view =
+            static_cast<message_center::MessageView*>(focused_view);
+        break;
+      }
+    }
+    return focused_message_view;
+  }
+
   TestUnifiedMessageCenterView* message_center_view() {
     return message_center_view_.get();
   }
diff --git a/ash/system/message_center/unified_message_list_view.cc b/ash/system/message_center/unified_message_list_view.cc
index b92c66b..95cbeb9 100644
--- a/ash/system/message_center/unified_message_list_view.cc
+++ b/ash/system/message_center/unified_message_list_view.cc
@@ -483,9 +483,12 @@
       removed_views.push_back(view);
   }
 
-  for (auto* view : removed_views) {
-    model_->RemoveNotificationExpanded(view->GetNotificationId());
-    delete view;
+  {
+    base::AutoReset<bool> auto_reset(&is_deleting_removed_notifications_, true);
+    for (auto* view : removed_views) {
+      model_->RemoveNotificationExpanded(view->GetNotificationId());
+      delete view;
+    }
   }
 
   UpdateBorders();
diff --git a/ash/system/message_center/unified_message_list_view.h b/ash/system/message_center/unified_message_list_view.h
index 1bdce67..b5e59d43 100644
--- a/ash/system/message_center/unified_message_list_view.h
+++ b/ash/system/message_center/unified_message_list_view.h
@@ -84,6 +84,10 @@
   void AnimationProgressed(const gfx::Animation* animation) override;
   void AnimationCanceled(const gfx::Animation* animation) override;
 
+  bool is_deleting_removed_notifications() const {
+    return is_deleting_removed_notifications_;
+  }
+
  protected:
   // Virtual for testing.
   virtual message_center::MessageView* CreateMessageView(
@@ -183,6 +187,11 @@
   // as height().
   int ideal_height_ = 0;
 
+  // True if the UnifiedMessageListView is currently deleting notifications
+  // marked for removal. This check is needed to prevent re-entrancing issues
+  // (e.g. crbug.com/933327) caused by the View destructor.
+  bool is_deleting_removed_notifications_ = false;
+
   DISALLOW_COPY_AND_ASSIGN(UnifiedMessageListView);
 };
 
diff --git a/ash/system/tray/tray_bubble_view.cc b/ash/system/tray/tray_bubble_view.cc
index dca2579..51af065 100644
--- a/ash/system/tray/tray_bubble_view.cc
+++ b/ash/system/tray/tray_bubble_view.cc
@@ -236,6 +236,8 @@
   if (init_params.anchor_mode == AnchorMode::kRect) {
     SetAnchorView(nullptr);
     SetAnchorRect(init_params.anchor_rect);
+    if (init_params.insets.has_value())
+      bubble_border_->set_insets(init_params.insets.value());
   }
 }
 
diff --git a/ash/system/tray/tray_bubble_view.h b/ash/system/tray/tray_bubble_view.h
index cd967d6..2df5d73 100644
--- a/ash/system/tray/tray_bubble_view.h
+++ b/ash/system/tray/tray_bubble_view.h
@@ -12,6 +12,7 @@
 #include "base/optional.h"
 #include "ui/accessibility/ax_enums.mojom.h"
 #include "ui/events/event.h"
+#include "ui/gfx/geometry/insets.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/native_widget_types.h"
 #include "ui/views/bubble/bubble_dialog_delegate_view.h"
@@ -109,6 +110,7 @@
     // If not provided, the bg color will be derived from the NativeTheme.
     base::Optional<SkColor> bg_color;
     base::Optional<int> corner_radius;
+    base::Optional<gfx::Insets> insets;
     bool has_shadow = true;
   };
 
diff --git a/ash/system/tray/tray_constants.h b/ash/system/tray/tray_constants.h
index d4079c8..50e205af 100644
--- a/ash/system/tray/tray_constants.h
+++ b/ash/system/tray/tray_constants.h
@@ -174,7 +174,7 @@
 constexpr gfx::Insets kUnifiedMenuItemPadding(0, 16, 16, 16);
 constexpr gfx::Insets kUnifiedSliderPadding(0, 16);
 
-constexpr int kUnifiedMenuVerticalPadding = 8;
+constexpr int kUnifiedMenuPadding = 8;
 constexpr int kUnifiedNotificationCenterSpacing = 16;
 constexpr int kUnifiedTrayIconSize = 20;
 constexpr int kUnifiedTraySpacingBetweenIcons = 6;
diff --git a/ash/system/unified/unified_slider_bubble_controller.cc b/ash/system/unified/unified_slider_bubble_controller.cc
index 965e341..3d71cf5a 100644
--- a/ash/system/unified/unified_slider_bubble_controller.cc
+++ b/ash/system/unified/unified_slider_bubble_controller.cc
@@ -165,8 +165,10 @@
   init_params.max_width = kTrayMenuWidth;
   init_params.delegate = this;
   init_params.parent_window = tray_->GetBubbleWindowContainer();
-  init_params.anchor_view =
-      tray_->shelf()->GetSystemTrayAnchorView()->GetBubbleAnchor();
+  init_params.anchor_view = nullptr;
+  init_params.anchor_mode = TrayBubbleView::AnchorMode::kRect;
+  init_params.anchor_rect = tray_->shelf()->GetSystemTrayAnchorRect();
+  init_params.insets = gfx::Insets(kUnifiedMenuPadding, kUnifiedMenuPadding);
   init_params.corner_radius = kUnifiedTrayCornerRadius;
   init_params.has_shadow = false;
 
@@ -177,8 +179,6 @@
   bubble_view_->AddChildView(slider_view);
   bubble_view_->set_color(SK_ColorTRANSPARENT);
   bubble_view_->layer()->SetFillsBoundsOpaquely(false);
-  bubble_view_->set_anchor_view_insets(
-      UnifiedSystemTrayBubble::GetAdjustedAnchorInsets(tray_, bubble_view_));
 
   bubble_widget_ = views::BubbleDialogDelegateView::CreateBubble(bubble_view_);
 
diff --git a/ash/system/unified/unified_system_tray_bubble.cc b/ash/system/unified/unified_system_tray_bubble.cc
index 0928ba69..115ede03 100644
--- a/ash/system/unified/unified_system_tray_bubble.cc
+++ b/ash/system/unified/unified_system_tray_bubble.cc
@@ -61,24 +61,6 @@
 
 }  // namespace
 
-// static
-gfx::Insets UnifiedSystemTrayBubble::GetAdjustedAnchorInsets(
-    UnifiedSystemTray* tray,
-    TrayBubbleView* bubble_view) {
-  gfx::Insets anchor_insets =
-      tray->shelf()->GetSystemTrayAnchorView()->GetBubbleAnchorInsets();
-  gfx::Insets bubble_insets = bubble_view->GetBorderInsets();
-  if (tray->shelf()->IsHorizontalAlignment()) {
-    anchor_insets -=
-        gfx::Insets(kUnifiedMenuVerticalPadding - bubble_insets.bottom(), 0, 0,
-                    bubble_insets.right() + anchor_insets.right());
-  } else {
-    anchor_insets -=
-        gfx::Insets(0, 0, bubble_insets.bottom() + anchor_insets.bottom(), 0);
-  }
-  return anchor_insets;
-}
-
 UnifiedSystemTrayBubble::UnifiedSystemTrayBubble(UnifiedSystemTray* tray,
                                                  bool show_by_click)
     : controller_(
@@ -96,6 +78,7 @@
   init_params.anchor_view = nullptr;
   init_params.anchor_mode = TrayBubbleView::AnchorMode::kRect;
   init_params.anchor_rect = tray->shelf()->GetSystemTrayAnchorRect();
+  init_params.insets = gfx::Insets(kUnifiedMenuPadding, kUnifiedMenuPadding);
   init_params.corner_radius = kUnifiedTrayCornerRadius;
   init_params.has_shadow = false;
   init_params.show_by_click = show_by_click;
@@ -111,8 +94,6 @@
   bubble_view_->SetMaxHeight(max_height);
   bubble_view_->AddChildView(new ContainerView(unified_view_));
 
-  bubble_view_->set_anchor_view_insets(
-      GetAdjustedAnchorInsets(tray, bubble_view_));
   bubble_view_->set_color(SK_ColorTRANSPARENT);
   bubble_view_->layer()->SetFillsBoundsOpaquely(false);
 
@@ -249,7 +230,7 @@
                                                        : anchor_bounds.bottom();
   int free_space_height_above_anchor =
       bottom - tray_->shelf()->GetUserWorkAreaBounds().y();
-  return free_space_height_above_anchor - kUnifiedMenuVerticalPadding * 2;
+  return free_space_height_above_anchor - kUnifiedMenuPadding * 2;
 }
 
 void UnifiedSystemTrayBubble::OnDisplayConfigurationChanged() {
diff --git a/ash/system/unified/unified_system_tray_bubble.h b/ash/system/unified/unified_system_tray_bubble.h
index a8c62755..fdcc966 100644
--- a/ash/system/unified/unified_system_tray_bubble.h
+++ b/ash/system/unified/unified_system_tray_bubble.h
@@ -44,10 +44,6 @@
                                 public TimeToClickRecorder::Delegate,
                                 public TabletModeObserver {
  public:
-  // Return adjusted anchor insets that take into account shelf alignment and
-  // bubble insets.
-  static gfx::Insets GetAdjustedAnchorInsets(UnifiedSystemTray* tray,
-                                             TrayBubbleView* bubble_view);
 
   explicit UnifiedSystemTrayBubble(UnifiedSystemTray* tray, bool show_by_click);
   ~UnifiedSystemTrayBubble() override;
diff --git a/ash/system/unified/user_chooser_view.cc b/ash/system/unified/user_chooser_view.cc
index f0085286..8f8cf90 100644
--- a/ash/system/unified/user_chooser_view.cc
+++ b/ash/system/unified/user_chooser_view.cc
@@ -77,8 +77,6 @@
   auto* icon = new views::ImageView;
   icon->SetImage(
       gfx::CreateVectorIcon(kSystemMenuNewUserIcon, kUnifiedMenuIconColor));
-  icon->set_tooltip_text(
-      l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_SIGN_IN_ANOTHER_ACCOUNT));
   AddChildView(icon);
 
   auto* label = new views::Label(
diff --git a/ash/wm/splitview/split_view_controller.cc b/ash/wm/splitview/split_view_controller.cc
index 31f7a6c..b8d8131 100644
--- a/ash/wm/splitview/split_view_controller.cc
+++ b/ash/wm/splitview/split_view_controller.cc
@@ -114,7 +114,7 @@
     minimum_width = is_landscape ? minimum_size.width() : minimum_size.height();
   }
   return minimum_width;
-};
+}
 
 // Returns true if |window| is currently snapped.
 bool IsSnapped(aura::Window* window) {
diff --git a/ash/wm/system_gesture_event_filter_unittest.cc b/ash/wm/system_gesture_event_filter_unittest.cc
index cf89dc81..2705ff1 100644
--- a/ash/wm/system_gesture_event_filter_unittest.cc
+++ b/ash/wm/system_gesture_event_filter_unittest.cc
@@ -60,12 +60,12 @@
 
  private:
   gfx::Size GetMaximumSize() const override { return gfx::Size(200, 200); }
-  gfx::Rect GetBoundsForClientView() const override { return gfx::Rect(); };
+  gfx::Rect GetBoundsForClientView() const override { return gfx::Rect(); }
 
   gfx::Rect GetWindowBoundsForClientBounds(
       const gfx::Rect& client_bounds) const override {
     return gfx::Rect();
-  };
+  }
 
   // This function must ask the ClientView to do a hittest.  We don't do this in
   // the parent NonClientView because that makes it more difficult to calculate
diff --git a/base/android/build_info.cc b/base/android/build_info.cc
index 3b7c2b8..af3dc2f 100644
--- a/base/android/build_info.cc
+++ b/base/android/build_info.cc
@@ -75,7 +75,8 @@
       firebase_app_id_(StrDupParam(params, 18)),
       custom_themes_(StrDupParam(params, 19)),
       resources_version_(StrDupParam(params, 20)),
-      extracted_file_suffix_(params[21]) {}
+      extracted_file_suffix_(params[21]),
+      is_at_least_q_(GetIntParam(params, 22)) {}
 
 // static
 BuildInfo* BuildInfo::GetInstance() {
diff --git a/base/android/build_info.h b/base/android/build_info.h
index 9eec5aa..96be7ee 100644
--- a/base/android/build_info.h
+++ b/base/android/build_info.h
@@ -122,6 +122,8 @@
     return sdk_int_;
   }
 
+  bool is_at_least_q() const { return is_at_least_q_; }
+
  private:
   friend struct BuildInfoSingletonTraits;
 
@@ -154,6 +156,7 @@
   const char* const resources_version_;
   // Not needed by breakpad.
   const std::string extracted_file_suffix_;
+  const bool is_at_least_q_;
 
   DISALLOW_COPY_AND_ASSIGN(BuildInfo);
 };
diff --git a/base/android/java/src/org/chromium/base/BuildInfo.java b/base/android/java/src/org/chromium/base/BuildInfo.java
index 3ad002d..df0034f 100644
--- a/base/android/java/src/org/chromium/base/BuildInfo.java
+++ b/base/android/java/src/org/chromium/base/BuildInfo.java
@@ -57,13 +57,29 @@
         BuildInfo buildInfo = getInstance();
         String hostPackageName = ContextUtils.getApplicationContext().getPackageName();
         return new String[] {
-                Build.BRAND, Build.DEVICE, Build.ID, Build.MANUFACTURER, Build.MODEL,
-                String.valueOf(Build.VERSION.SDK_INT), Build.TYPE, Build.BOARD, hostPackageName,
-                String.valueOf(buildInfo.hostVersionCode), buildInfo.hostPackageLabel,
-                buildInfo.packageName, String.valueOf(buildInfo.versionCode), buildInfo.versionName,
-                buildInfo.androidBuildFingerprint, buildInfo.gmsVersionCode,
-                buildInfo.installerPackageName, buildInfo.abiString, BuildConfig.FIREBASE_APP_ID,
-                buildInfo.customThemes, buildInfo.resourcesVersion, buildInfo.extractedFileSuffix,
+                Build.BRAND,
+                Build.DEVICE,
+                Build.ID,
+                Build.MANUFACTURER,
+                Build.MODEL,
+                String.valueOf(Build.VERSION.SDK_INT),
+                Build.TYPE,
+                Build.BOARD,
+                hostPackageName,
+                String.valueOf(buildInfo.hostVersionCode),
+                buildInfo.hostPackageLabel,
+                buildInfo.packageName,
+                String.valueOf(buildInfo.versionCode),
+                buildInfo.versionName,
+                buildInfo.androidBuildFingerprint,
+                buildInfo.gmsVersionCode,
+                buildInfo.installerPackageName,
+                buildInfo.abiString,
+                BuildConfig.FIREBASE_APP_ID,
+                buildInfo.customThemes,
+                buildInfo.resourcesVersion,
+                buildInfo.extractedFileSuffix,
+                isAtLeastQ() ? "1" : "0",
         };
     }
 
diff --git a/base/profiler/native_stack_sampler.h b/base/profiler/native_stack_sampler.h
index 3114f6b6..0ff7992 100644
--- a/base/profiler/native_stack_sampler.h
+++ b/base/profiler/native_stack_sampler.h
@@ -61,9 +61,6 @@
   // The following functions are all called on the SamplingThread (not the
   // thread being sampled).
 
-  // Notifies the sampler that we're starting to record a new profile.
-  virtual void ProfileRecordingStarting() = 0;
-
   // Records a set of frames and returns them.
   virtual std::vector<StackSamplingProfiler::Frame> RecordStackFrames(
       StackBuffer* stackbuffer,
@@ -96,4 +93,3 @@
 }  // namespace base
 
 #endif  // BASE_PROFILER_NATIVE_STACK_SAMPLER_H_
-
diff --git a/base/profiler/native_stack_sampler_mac.cc b/base/profiler/native_stack_sampler_mac.cc
index 162fc2d..7d74166e 100644
--- a/base/profiler/native_stack_sampler_mac.cc
+++ b/base/profiler/native_stack_sampler_mac.cc
@@ -269,7 +269,6 @@
   ~NativeStackSamplerMac() override;
 
   // StackSamplingProfiler::NativeStackSampler:
-  void ProfileRecordingStarting() override;
   std::vector<Frame> RecordStackFrames(
       StackBuffer* stack_buffer,
       ProfileBuilder* profile_builder) override;
@@ -329,9 +328,6 @@
 
 NativeStackSamplerMac::~NativeStackSamplerMac() {}
 
-void NativeStackSamplerMac::ProfileRecordingStarting() {
-}
-
 std::vector<Frame> NativeStackSamplerMac::RecordStackFrames(
     StackBuffer* stack_buffer,
     ProfileBuilder* profile_builder) {
@@ -446,7 +442,7 @@
     // address in the wrong place. This check should ensure that we bail before
     // trying to deref a bad IP obtained this way in the previous frame.
     const ModuleCache::Module* module = module_cache_->GetModuleForAddress(rip);
-    if (!module->is_valid)
+    if (!module)
       return false;
 
     callback(static_cast<uintptr_t>(rip), module);
diff --git a/base/profiler/native_stack_sampler_win.cc b/base/profiler/native_stack_sampler_win.cc
index ebf449c6..0a32704 100644
--- a/base/profiler/native_stack_sampler_win.cc
+++ b/base/profiler/native_stack_sampler_win.cc
@@ -416,7 +416,6 @@
   ~NativeStackSamplerWin() override;
 
   // StackSamplingProfiler::NativeStackSampler:
-  void ProfileRecordingStarting() override;
   std::vector<Frame> RecordStackFrames(
       StackBuffer* stack_buffer,
       ProfileBuilder* profile_builder) override;
@@ -449,9 +448,6 @@
 
 NativeStackSamplerWin::~NativeStackSamplerWin() {}
 
-void NativeStackSamplerWin::ProfileRecordingStarting() {
-}
-
 std::vector<Frame> NativeStackSamplerWin::RecordStackFrames(
     StackBuffer* stack_buffer,
     ProfileBuilder* profile_builder) {
diff --git a/base/profiler/stack_sampling_profiler.cc b/base/profiler/stack_sampling_profiler.cc
index c077557..5a0acd9 100644
--- a/base/profiler/stack_sampling_profiler.cc
+++ b/base/profiler/stack_sampling_profiler.cc
@@ -523,7 +523,6 @@
   if (collection->sample_count == 0) {
     collection->profile_start_time = Time::Now();
     collection->next_sample_time = Time::Now();
-    collection->native_sampler->ProfileRecordingStarting();
   }
 
   // Record a single sample.
diff --git a/base/profiler/stack_sampling_profiler_unittest.cc b/base/profiler/stack_sampling_profiler_unittest.cc
index 3c57921..2d808c92 100644
--- a/base/profiler/stack_sampling_profiler_unittest.cc
+++ b/base/profiler/stack_sampling_profiler_unittest.cc
@@ -770,7 +770,7 @@
 
   // Check that all the modules are valid.
   for (const auto& frame : frames)
-    EXPECT_TRUE(frame.module->is_valid);
+    EXPECT_NE(nullptr, frame.module);
 
   // Check that the stack contains a frame for
   // TargetThread::SignalAndWaitUntilSignaled().
diff --git a/base/sampling_heap_profiler/module_cache.cc b/base/sampling_heap_profiler/module_cache.cc
index d1e03c1..b39168ef 100644
--- a/base/sampling_heap_profiler/module_cache.cc
+++ b/base/sampling_heap_profiler/module_cache.cc
@@ -6,12 +6,8 @@
 
 #include <utility>
 
-#include "base/no_destructor.h"
-
 namespace base {
 
-ModuleCache::Module::Module() : is_valid(false) {}
-
 ModuleCache::Module::Module(uintptr_t base_address,
                             const std::string& id,
                             const FilePath& filename)
@@ -24,7 +20,6 @@
     : base_address(base_address),
       id(id),
       filename(filename),
-      is_valid(true),
       size(size) {}
 
 ModuleCache::Module::~Module() = default;
@@ -33,7 +28,6 @@
 ModuleCache::~ModuleCache() = default;
 
 const ModuleCache::Module* ModuleCache::GetModuleForAddress(uintptr_t address) {
-  static NoDestructor<Module> invalid_module;
   auto it = modules_cache_map_.upper_bound(address);
   if (it != modules_cache_map_.begin()) {
     DCHECK(!modules_cache_map_.empty());
@@ -44,8 +38,8 @@
   }
 
   std::unique_ptr<Module> module = CreateModuleForAddress(address);
-  if (!module->is_valid)
-    return invalid_module.get();
+  if (!module)
+    return nullptr;
   return modules_cache_map_.emplace(module->base_address, std::move(module))
       .first->second.get();
 }
diff --git a/base/sampling_heap_profiler/module_cache.h b/base/sampling_heap_profiler/module_cache.h
index b7d6d94..a3bd1c7 100644
--- a/base/sampling_heap_profiler/module_cache.h
+++ b/base/sampling_heap_profiler/module_cache.h
@@ -22,11 +22,9 @@
 
 class BASE_EXPORT ModuleCache {
  public:
-  // Module represents the module (DLL or exe) and its validness state.
-  // This struct is used for sampling data transfer from NativeStackSampler
-  // to ProfileBuilder as well as by SamplingHeapProfiler.
+  // Module represents a binary module (executable or library) and its
+  // associated state.
   struct BASE_EXPORT Module {
-    Module();
     Module(uintptr_t base_address,
            const std::string& id,
            const FilePath& filename);
@@ -54,9 +52,6 @@
     // The filename of the module.
     FilePath filename;
 
-    // The validness of the module.
-    bool is_valid;
-
     // Size of the module.
     size_t size;
   };
@@ -64,9 +59,9 @@
   ModuleCache();
   ~ModuleCache();
 
-  // Gets the module containing |address| or an invalid module if |address| is
-  // not within a module. The returned module remains owned by and has the same
-  // lifetime as the ModuleCache object.
+  // Gets the module containing |address| or nullptr if |address| is not within
+  // a module. The returned module remains owned by and has the same lifetime as
+  // the ModuleCache object.
   const Module* GetModuleForAddress(uintptr_t address);
   std::vector<const Module*> GetModules() const;
 
@@ -74,8 +69,8 @@
   // TODO(alph): Refactor corresponding functions to use public API instead,
   // and drop friends.
 
-  // Creates a Module object for the specified memory address. If the address
-  // does not belong to a module returns an invalid module.
+  // Creates a Module object for the specified memory address. Returns null if
+  // the address does not belong to a module.
   static std::unique_ptr<Module> CreateModuleForAddress(uintptr_t address);
   friend class NativeStackSamplerMac;
 
diff --git a/base/sampling_heap_profiler/module_cache_mac.cc b/base/sampling_heap_profiler/module_cache_mac.cc
index 96b24ab..7571098f 100644
--- a/base/sampling_heap_profiler/module_cache_mac.cc
+++ b/base/sampling_heap_profiler/module_cache_mac.cc
@@ -68,7 +68,7 @@
     uintptr_t address) {
   Dl_info inf;
   if (!dladdr(reinterpret_cast<const void*>(address), &inf))
-    return std::make_unique<Module>();
+    return nullptr;
   auto base_module_address = reinterpret_cast<uintptr_t>(inf.dli_fbase);
   return std::make_unique<Module>(
       base_module_address, GetUniqueId(inf.dli_fbase), FilePath(inf.dli_fname),
diff --git a/base/sampling_heap_profiler/module_cache_posix.cc b/base/sampling_heap_profiler/module_cache_posix.cc
index a82c27e..6950e54 100644
--- a/base/sampling_heap_profiler/module_cache_posix.cc
+++ b/base/sampling_heap_profiler/module_cache_posix.cc
@@ -10,7 +10,7 @@
 std::unique_ptr<ModuleCache::Module> ModuleCache::CreateModuleForAddress(
     uintptr_t address) {
   // TODO(alph): Implement it.
-  return std::make_unique<Module>();
+  return nullptr;
 }
 
 }  // namespace base
diff --git a/base/sampling_heap_profiler/module_cache_unittest.cc b/base/sampling_heap_profiler/module_cache_unittest.cc
index a9e3a62..d216aed 100644
--- a/base/sampling_heap_profiler/module_cache_unittest.cc
+++ b/base/sampling_heap_profiler/module_cache_unittest.cc
@@ -31,7 +31,7 @@
   const ModuleCache::Module* module1 = cache.GetModuleForAddress(ptr1);
   const ModuleCache::Module* module2 = cache.GetModuleForAddress(ptr2);
   EXPECT_EQ(module1, module2);
-  EXPECT_TRUE(module1->is_valid);
+  EXPECT_NE(nullptr, module1);
   EXPECT_GT(module1->size, 0u);
   EXPECT_LE(module1->base_address, ptr1);
   EXPECT_GT(module1->base_address + module1->size, ptr2);
@@ -41,15 +41,14 @@
   ModuleCache cache;
   uintptr_t ptr = reinterpret_cast<uintptr_t>(&AFunctionForTest);
   const ModuleCache::Module* module = cache.GetModuleForAddress(ptr);
-  EXPECT_TRUE(module->is_valid);
+  EXPECT_NE(nullptr, module);
   EXPECT_EQ(1u, cache.GetModules().size());
   EXPECT_EQ(module, cache.GetModules().front());
 }
 
 TEST_F(ModuleCacheTest, InvalidModule) {
   ModuleCache cache;
-  const ModuleCache::Module* invalid_module = cache.GetModuleForAddress(1);
-  EXPECT_FALSE(invalid_module->is_valid);
+  EXPECT_EQ(nullptr, cache.GetModuleForAddress(1));
 }
 
 }  // namespace
diff --git a/base/sampling_heap_profiler/module_cache_win.cc b/base/sampling_heap_profiler/module_cache_win.cc
index ca79f17b..954cef0 100644
--- a/base/sampling_heap_profiler/module_cache_win.cc
+++ b/base/sampling_heap_profiler/module_cache_win.cc
@@ -7,7 +7,6 @@
 #include <objbase.h>
 #include <psapi.h>
 
-#include "base/no_destructor.h"
 #include "base/process/process_handle.h"
 #include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
@@ -74,7 +73,7 @@
                            reinterpret_cast<LPCTSTR>(address),
                            &module_handle)) {
     DCHECK_EQ(ERROR_MOD_NOT_FOUND, static_cast<int>(::GetLastError()));
-    return std::make_unique<Module>();
+    return nullptr;
   }
   std::unique_ptr<Module> module = CreateModuleForHandle(module_handle);
   ::CloseHandle(module_handle);
@@ -83,10 +82,8 @@
 
 const ModuleCache::Module* ModuleCache::GetModuleForHandle(
     HMODULE module_handle) {
-  static NoDestructor<ModuleCache::Module> invalid_module;
-
   if (!module_handle)
-    return invalid_module.get();
+    return nullptr;
 
   auto loc = win_module_cache_.find(module_handle);
   if (loc != win_module_cache_.end())
@@ -94,12 +91,12 @@
 
   std::unique_ptr<ModuleCache::Module> module =
       ModuleCache::CreateModuleForHandle(module_handle);
-  if (module->is_valid) {
-    const auto result = win_module_cache_.insert(
-        std::make_pair(module_handle, std::move(module)));
-    return result.first->second.get();
-  }
-  return invalid_module.get();
+  if (!module)
+    return nullptr;
+
+  const auto result = win_module_cache_.insert(
+      std::make_pair(module_handle, std::move(module)));
+  return result.first->second.get();
 }
 
 // static
@@ -109,12 +106,12 @@
   std::string build_id;
   GetDebugInfoForModule(module_handle, &build_id, &pdb_name);
   if (build_id.empty())
-    return std::make_unique<Module>();
+    return nullptr;
 
   MODULEINFO module_info;
   if (!::GetModuleInformation(GetCurrentProcessHandle(), module_handle,
                               &module_info, sizeof(module_info))) {
-    return std::make_unique<Module>();
+    return nullptr;
   }
 
   return std::make_unique<Module>(
diff --git a/build/android/gyp/apkbuilder.py b/build/android/gyp/apkbuilder.py
index 9ffb137e..310a192 100755
--- a/build/android/gyp/apkbuilder.py
+++ b/build/android/gyp/apkbuilder.py
@@ -208,7 +208,7 @@
     if (uncompress and os.path.splitext(basename)[1] == '.so'
         and 'android_linker' not in basename
         and (not has_crazy_linker or 'clang_rt' not in basename)
-        and 'crashpad_handler' not in basename):
+        and (not has_crazy_linker or 'crashpad_handler' not in basename)):
       compress = False
       # Add prefix to prevent android install from extracting upon install.
       if has_crazy_linker:
diff --git a/build/android/gyp/generate_linker_version_script.py b/build/android/gyp/generate_linker_version_script.py
index 5ffff03..34c72eb8 100755
--- a/build/android/gyp/generate_linker_version_script.py
+++ b/build/android/gyp/generate_linker_version_script.py
@@ -42,7 +42,9 @@
   options = parser.parse_args()
 
   # JNI_OnLoad is always exported.
-  symbol_list = ['JNI_OnLoad']
+  # CrashpadHandlerMain() is the entry point to the Crashpad handler, required
+  # for libcrashpad_handler_trampoline.so.
+  symbol_list = ['CrashpadHandlerMain', 'JNI_OnLoad']
 
   if options.export_java_symbols:
     symbol_list.append('Java_*')
diff --git a/build/config/ios/rules.gni b/build/config/ios/rules.gni
index b0aaabb..f3642f5 100644
--- a/build/config/ios/rules.gni
+++ b/build/config/ios/rules.gni
@@ -1827,19 +1827,10 @@
     # Xcode needs those two framework installed in the application (and signed)
     # for the XCTest to run, so install them using extra_system_frameworks.
     _ios_platform_library = "$ios_sdk_platform_path/Developer/Library"
-    extra_system_frameworks =
-        [ "$_ios_platform_library/Frameworks/XCTest.framework" ]
-
-    # TODO: Remove this once support for Xcode 9.x is dropped.
-    if (xcode_version_int >= 1000) {
-      extra_system_frameworks += [
-        "$ios_sdk_platform_path/Developer/usr/lib/libXCTestBundleInject.dylib",
-      ]
-    } else {
-      extra_system_frameworks += [
-        "$_ios_platform_library/PrivateFrameworks/IDEBundleInjection.framework",
-      ]
-    }
+    extra_system_frameworks = [
+      "$_ios_platform_library/Frameworks/XCTest.framework",
+      "$ios_sdk_platform_path/Developer/usr/lib/libXCTestBundleInject.dylib",
+    ]
 
     _xctest_bundle = _xctest_target + "_bundle"
     if (current_toolchain == default_toolchain) {
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1
index 49e638c..0fca1e1 100644
--- a/build/fuchsia/linux.sdk.sha1
+++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@
-d5a51eb15454dffbf0681c781110972adfc11828
+aa16bb73350c27311aefa9a6cf17592003f67b5e
\ No newline at end of file
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1
index 88a1eeff..03c4fcd 100644
--- a/build/fuchsia/mac.sdk.sha1
+++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@
-593fe7d6266722a0c13e9b71ac68ea0ca34e2a59
+16540691aa6faefad8f5a967ae0d23a80349a827
\ No newline at end of file
diff --git a/build/toolchain/linux/BUILD.gn b/build/toolchain/linux/BUILD.gn
index 1b0f2205..fa8b17e 100644
--- a/build/toolchain/linux/BUILD.gn
+++ b/build/toolchain/linux/BUILD.gn
@@ -5,6 +5,14 @@
 import("//build/config/sysroot.gni")
 import("//build/toolchain/gcc_toolchain.gni")
 
+clang_toolchain("clang_ppc64") {
+  enable_linker_map = true
+  toolchain_args = {
+    current_cpu = "ppc64"
+    current_os = "linux"
+  }
+}
+
 clang_toolchain("clang_arm") {
   toolprefix = "arm-linux-gnueabihf-"
   toolchain_args = {
diff --git a/chrome/android/chrome_public_apk_tmpl.gni b/chrome/android/chrome_public_apk_tmpl.gni
index 3a28317..5b66857 100644
--- a/chrome/android/chrome_public_apk_tmpl.gni
+++ b/chrome/android/chrome_public_apk_tmpl.gni
@@ -348,6 +348,30 @@
     if (!defined(deps)) {
       deps = []
     }
+    if (!defined(loadable_modules)) {
+      loadable_modules = []
+    }
+    if (!defined(secondary_abi_loadable_modules)) {
+      secondary_abi_loadable_modules = []
+    }
+
+    if (!is_trichrome) {
+      deps += [
+        "//third_party/crashpad/crashpad/handler:crashpad_handler_trampoline",
+      ]
+      loadable_modules += [ "$root_out_dir/libcrashpad_handler_trampoline.so" ]
+
+      if (android_64bit_target_cpu && build_apk_secondary_abi &&
+          (!defined(invoker.is_64_bit_browser) || !invoker.is_64_bit_browser ||
+           invoker.include_32_bit_webview)) {
+        _trampoline = "//third_party/crashpad/crashpad/handler:crashpad_handler_trampoline($android_secondary_abi_toolchain)"
+        deps += [ _trampoline ]
+        _secondary_out_dir = get_label_info(_trampoline, "root_out_dir")
+        secondary_abi_loadable_modules +=
+            [ "$_secondary_out_dir/libcrashpad_handler_trampoline.so" ]
+      }
+    }
+
     deps += [
       "//chrome/android:chrome_public_non_pak_assets",
       "//components/crash/android:handler_java",
@@ -403,11 +427,11 @@
 
       # We store this as a separate .so in the APK and only load as needed.
       if (android_64bit_target_cpu && build_apk_secondary_abi) {
-        secondary_abi_loadable_modules = [ "$root_gen_dir/third_party/android_deps/com_google_ar_core_java/jni/armeabi-v7a/libarcore_sdk_c.so" ]
+        secondary_abi_loadable_modules += [ "$root_gen_dir/third_party/android_deps/com_google_ar_core_java/jni/armeabi-v7a/libarcore_sdk_c.so" ]
       } else if (android_64bit_target_cpu && !build_apk_secondary_abi) {
-        loadable_modules = [ "$root_gen_dir/third_party/android_deps/com_google_ar_core_java/jni/armeabi-v7a/libarcore_sdk_c.so" ]
+        loadable_modules += [ "$root_gen_dir/third_party/android_deps/com_google_ar_core_java/jni/armeabi-v7a/libarcore_sdk_c.so" ]
       } else {
-        loadable_modules = [ "$root_gen_dir/third_party/android_deps/com_google_ar_core_java/jni/armeabi-v7a/libarcore_sdk_c.so" ]
+        loadable_modules += [ "$root_gen_dir/third_party/android_deps/com_google_ar_core_java/jni/armeabi-v7a/libarcore_sdk_c.so" ]
       }
     }
   }
diff --git a/chrome/android/java/res_download/layout/download_rename_custom_dialog.xml b/chrome/android/java/res_download/layout/download_rename_custom_dialog.xml
new file mode 100644
index 0000000..923a53c
--- /dev/null
+++ b/chrome/android/java/res_download/layout/download_rename_custom_dialog.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2019 The Chromium Authors. All rights reserved.
+     Use of this source code is governed by a BSD-style license that can be
+     found in the LICENSE file. -->
+
+<org.chromium.chrome.browser.download.home.rename.RenameDialogCustomView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content" >
+
+    <LinearLayout
+        android:orientation="vertical"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        style="@style/AlertDialogContent">
+
+        <TextView
+            android:id="@+id/subtitle"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginBottom="16dp"
+            android:visibility="gone"/>
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="horizontal">
+
+            <org.chromium.ui.widget.ChromeImageView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                app:srcCompat="@drawable/ic_drive_file_24dp"
+                app:tint="@color/default_icon_color"
+                style="@style/ListItemStartIcon" />
+
+            <org.chromium.chrome.browser.widget.AlertDialogEditText
+                android:id="@+id/file_name"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:singleLine="true" />
+
+        </LinearLayout>
+
+    </LinearLayout>
+
+</org.chromium.chrome.browser.download.home.rename.RenameDialogCustomView>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/background_sync/BackgroundSyncBackgroundTaskScheduler.java b/chrome/android/java/src/org/chromium/chrome/browser/background_sync/BackgroundSyncBackgroundTaskScheduler.java
index 09c481d..48c5137b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/background_sync/BackgroundSyncBackgroundTaskScheduler.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/background_sync/BackgroundSyncBackgroundTaskScheduler.java
@@ -5,6 +5,7 @@
 package org.chromium.chrome.browser.background_sync;
 
 import android.os.Bundle;
+import android.text.format.DateUtils;
 
 import org.chromium.base.ContextUtils;
 import org.chromium.base.VisibleForTesting;
@@ -13,8 +14,6 @@
 import org.chromium.components.background_task_scheduler.TaskIds;
 import org.chromium.components.background_task_scheduler.TaskInfo;
 
-import java.util.concurrent.TimeUnit;
-
 /**
  * The {@link BackgroundSyncBackgroundTaskScheduler} singleton is responsible
  * for scheduling and cancelling background tasks to wake Chrome up so that
@@ -25,7 +24,7 @@
 public class BackgroundSyncBackgroundTaskScheduler {
     // Keep in sync with the default min_sync_recovery_time of
     // BackgroundSyncParameters.
-    private static final long MIN_SYNC_RECOVERY_TIME = TimeUnit.MINUTES.toMillis(6);
+    private static final long MIN_SYNC_RECOVERY_TIME = DateUtils.MINUTE_IN_MILLIS * 6;
 
     // Bundle key for the timestamp of the soonest wakeup time expected for
     // this task.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanel.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanel.java
index 744a9b0..9fba660 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanel.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanel.java
@@ -52,13 +52,19 @@
     private static final long HIDE_PROGRESS_BAR_DELAY_MS = 1000 / 60 * 4;
 
     /** State of the Overlay Panel. */
-    public static enum PanelState {
+    @IntDef({PanelState.UNDEFINED, PanelState.CLOSED, PanelState.PEEKED, PanelState.EXPANDED,
+            PanelState.MAXIMIZED})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface PanelState {
+        // Values can't have gaps and should be numerated from 0.
+        // Values CLOSED - MAXIMIZED are sorted and show next states.
         // TODO(pedrosimonetti): consider removing the UNDEFINED state
-        UNDEFINED,
-        CLOSED,
-        PEEKED,
-        EXPANDED,
-        MAXIMIZED
+        int UNDEFINED = 0;
+        int CLOSED = 1;
+        int PEEKED = 2;
+        int EXPANDED = 3;
+        int MAXIMIZED = 4;
+        int NUM_ENTRIES = 5;
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelAnimation.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelAnimation.java
index 142abf5..63fa8b6 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelAnimation.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelAnimation.java
@@ -6,6 +6,7 @@
 
 import android.animation.Animator;
 import android.content.Context;
+import android.support.annotation.Nullable;
 
 import org.chromium.base.VisibleForTesting;
 import org.chromium.chrome.browser.compositor.animation.CompositorAnimationHandler;
@@ -36,7 +37,7 @@
     private static final float INITIAL_ANIMATION_VELOCITY_DP_PER_SECOND = 1750f;
 
     /** The PanelState to which the Panel is being animated. */
-    private PanelState mAnimatingState;
+    private @Nullable @PanelState Integer mAnimatingState;
 
     /** The StateChangeReason for which the Panel is being animated. */
     private @StateChangeReason int mAnimatingStateReason;
@@ -139,9 +140,9 @@
         // before the panel is notified of the size change, resulting in the panel's
         // ContentView being laid out incorrectly.
         if (isPanelResizeSupported) {
-            if (mAnimatingState != PanelState.UNDEFINED) {
-                // If the size changes when an animation is happening, then we need to restart the
-                // animation, because the size of the Panel might have changed as well.
+            if (mAnimatingState == null || mAnimatingState != PanelState.UNDEFINED) {
+                // If the size changes when an animation is happening, then we need to restart
+                // the animation, because the size of the Panel might have changed as well.
                 animatePanelToState(mAnimatingState, mAnimatingStateReason);
             } else {
                 updatePanelForSizeChange();
@@ -176,7 +177,8 @@
      * @param state The state to animate to.
      * @param reason The reason for the change of panel state.
      */
-    private void animatePanelToState(PanelState state, @StateChangeReason int reason) {
+    private void animatePanelToState(
+            @Nullable @PanelState Integer state, @StateChangeReason int reason) {
         animatePanelToState(state, reason, BASE_ANIMATION_DURATION_MS);
     }
 
@@ -188,7 +190,7 @@
      * @param duration The animation duration in milliseconds.
      */
     protected void animatePanelToState(
-            PanelState state, @StateChangeReason int reason, long duration) {
+            @Nullable @PanelState Integer state, @StateChangeReason int reason, long duration) {
         mAnimatingState = state;
         mAnimatingStateReason = reason;
 
@@ -202,7 +204,7 @@
      * @param state The state to resize to.
      * @param reason The reason for the change of panel state.
      */
-    protected void resizePanelToState(PanelState state, @StateChangeReason int reason) {
+    protected void resizePanelToState(@PanelState int state, @StateChangeReason int reason) {
         cancelHeightAnimation();
 
         final float height = getPanelHeightFromState(state);
@@ -222,7 +224,7 @@
         // Calculate the nearest state from the current position, and then calculate the duration
         // of the animation that will start with a desired initial velocity and move the desired
         // amount of dps (displacement).
-        final PanelState nearestState = findNearestPanelStateFromHeight(getHeight(), 0.0f);
+        final @PanelState int nearestState = findNearestPanelStateFromHeight(getHeight(), 0.0f);
         final float displacement = getPanelHeightFromState(nearestState) - getHeight();
         final long duration = calculateAnimationDuration(
                 INITIAL_ANIMATION_VELOCITY_DP_PER_SECOND, displacement);
@@ -236,7 +238,8 @@
      * @param velocity The velocity of the gesture in dps per second.
      */
     protected void animateToProjectedState(float velocity) {
-        PanelState projectedState = getProjectedState(velocity);
+        @PanelState
+        int projectedState = getProjectedState(velocity);
 
         final float displacement = getPanelHeightFromState(projectedState) - getHeight();
         final long duration = calculateAnimationDuration(velocity, displacement);
@@ -248,13 +251,14 @@
      * @param velocity The given velocity.
      * @return The projected state the Panel will be if the given velocity is applied.
      */
-    protected PanelState getProjectedState(float velocity) {
+    protected @PanelState int getProjectedState(float velocity) {
         final float kickY = calculateAnimationDisplacement(velocity, BASE_ANIMATION_DURATION_MS);
         final float projectedHeight = getHeight() - kickY;
 
         // Calculate the projected state the Panel will be at the end of the fling movement and the
         // duration of the animation given the current velocity and the projected displacement.
-        PanelState projectedState = findNearestPanelStateFromHeight(projectedHeight, velocity);
+        @PanelState
+        int projectedState = findNearestPanelStateFromHeight(projectedHeight, velocity);
 
         return projectedState;
     }
@@ -369,7 +373,7 @@
         // be checked.
         if (mAnimatingState != null && mAnimatingState != PanelState.UNDEFINED
                 && MathUtils.areFloatsEqual(
-                           getHeight(), getPanelHeightFromState(mAnimatingState))) {
+                        getHeight(), getPanelHeightFromState(mAnimatingState))) {
             setPanelState(mAnimatingState, mAnimatingStateReason);
         }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelBase.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelBase.java
index 60d75397..8a2ac56 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelBase.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelBase.java
@@ -18,10 +18,6 @@
 import org.chromium.ui.base.LocalizationUtils;
 import org.chromium.ui.resources.dynamics.DynamicResourceLoader;
 
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-
 /**
  * Base abstract class for the Overlay Panel.
  */
@@ -116,20 +112,7 @@
     protected final Context mContext;
 
     /** The current state of the Overlay Panel. */
-    private PanelState mPanelState = PanelState.UNDEFINED;
-
-    /**
-     * Valid previous states for the Panel.
-     */
-    protected static final Map<PanelState, PanelState> PREVIOUS_STATES;
-    static {
-        Map<PanelState, PanelState> states = new HashMap<>();
-        // Pairs are of the form <Current, Previous>.
-        states.put(PanelState.PEEKED, PanelState.CLOSED);
-        states.put(PanelState.EXPANDED, PanelState.PEEKED);
-        states.put(PanelState.MAXIMIZED, PanelState.EXPANDED);
-        PREVIOUS_STATES = Collections.unmodifiableMap(states);
-    }
+    private @PanelState int mPanelState = PanelState.UNDEFINED;
 
     // ============================================================================================
     // Constructor
@@ -567,7 +550,7 @@
     /**
      * @return The panel's state.
      */
-    public PanelState getPanelState() {
+    public @PanelState int getPanelState() {
         return mPanelState;
     }
 
@@ -576,7 +559,7 @@
      * @param state The panel state to transition to.
      * @param reason The reason for a change in the panel's state.
      */
-    protected void setPanelState(PanelState state, @StateChangeReason int reason) {
+    protected void setPanelState(@PanelState int state, @StateChangeReason int reason) {
         if (state == PanelState.CLOSED) {
             mHeight = 0;
             onClosed(reason);
@@ -596,7 +579,7 @@
      * @param state A given state.
      * @return Whether the panel supports a given state.
      */
-    protected boolean isSupportedState(PanelState state) {
+    protected boolean isSupportedState(@PanelState int state) {
         return true;
     }
 
@@ -606,7 +589,7 @@
      * @param state The given state.
      * @return Whether the state is valid.
      */
-    private boolean isValidUiState(PanelState state) {
+    private boolean isValidUiState(@PanelState int state) {
         // TODO(pedrosimonetti): consider removing the UNDEFINED state
         // which would allow removing this method.
         return isSupportedState(state) && state != PanelState.UNDEFINED;
@@ -615,7 +598,7 @@
     /**
      * @return The maximum state supported by the panel.
      */
-    private PanelState getMaximumSupportedState() {
+    private @PanelState int getMaximumSupportedState() {
         if (isSupportedState(PanelState.MAXIMIZED)) {
             return PanelState.MAXIMIZED;
         } else if (isSupportedState(PanelState.EXPANDED)) {
@@ -628,10 +611,15 @@
     /**
      * @return The {@code PanelState} that is before the |state| in the order of states.
      */
-    private PanelState getPreviousPanelState(PanelState state) {
-        PanelState prevState = PREVIOUS_STATES.get(state);
+    private @PanelState int getPreviousPanelState(@PanelState int state) {
+        @Nullable
+        @PanelState
+        Integer prevState =
+                state >= PanelState.PEEKED && state <= PanelState.MAXIMIZED ? state - 1 : null;
         if (!isSupportedState(PanelState.EXPANDED)) {
-            prevState = PREVIOUS_STATES.get(prevState);
+            prevState = prevState >= PanelState.PEEKED && prevState <= PanelState.MAXIMIZED
+                    ? prevState - 1
+                    : null;
         }
         return prevState != null ? prevState : PanelState.UNDEFINED;
     }
@@ -646,8 +634,10 @@
      * @param state The state whose height will be calculated.
      * @return The height of the Overlay Panel in dps for a given |state|.
      */
-    public float getPanelHeightFromState(@Nullable PanelState state) {
-        if (state == PanelState.PEEKED) {
+    public float getPanelHeightFromState(@Nullable @PanelState Integer state) {
+        if (state == null) {
+            return 0;
+        } else if (state == PanelState.PEEKED) {
             return getPeekedHeight();
         } else if (state == PanelState.EXPANDED) {
             return getExpandedHeight();
@@ -712,14 +702,17 @@
      * @param velocity The velocity of the swipe if applicable. The swipe is upward if less than 0.
      * @return The nearest panel state.
      */
-    protected PanelState findNearestPanelStateFromHeight(float desiredPanelHeight, float velocity) {
+    protected @PanelState int findNearestPanelStateFromHeight(
+            float desiredPanelHeight, float velocity) {
         // If the panel was flung hard enough to make the desired height negative, it's closed.
         if (desiredPanelHeight < 0) return PanelState.CLOSED;
 
         // First, find the two states that the desired panel height is between.
-        PanelState nextState = PanelState.values()[0];
-        PanelState prevState = nextState;
-        for (PanelState state : PanelState.values()) {
+        @PanelState
+        int nextState = PanelState.UNDEFINED;
+        @PanelState
+        int prevState = nextState;
+        for (@PanelState int state = 0; state < PanelState.NUM_ENTRIES; state++) {
             if (!isValidUiState(state)) continue;
             prevState = nextState;
             nextState = state;
@@ -769,7 +762,7 @@
      * @param state The Panel state.
      * @return Whether the Panel height matches the one from the given state.
      */
-    protected boolean doesPanelHeightMatchState(PanelState state) {
+    protected boolean doesPanelHeightMatchState(@PanelState int state) {
         return state == getPanelState()
                 && MathUtils.areFloatsEqual(getHeight(), getPanelHeightFromState(state));
     }
@@ -784,8 +777,10 @@
      * @param height The Overlay Panel height.
      */
     private void updatePanelForHeight(float height) {
-        PanelState endState = findLargestPanelStateFromHeight(height);
-        PanelState startState = getPreviousPanelState(endState);
+        @PanelState
+        int endState = findLargestPanelStateFromHeight(height);
+        @PanelState
+        int startState = getPreviousPanelState(endState);
         float percentage = getStateCompletion(height, startState, endState);
 
         updatePanelSize(height);
@@ -825,12 +820,13 @@
      * @param panelHeight The height to compare to.
      * @return The panel state which is being transitioned to/from.
      */
-    private PanelState findLargestPanelStateFromHeight(float panelHeight) {
-        PanelState stateFound = PanelState.CLOSED;
+    private @PanelState int findLargestPanelStateFromHeight(float panelHeight) {
+        @PanelState
+        int stateFound = PanelState.CLOSED;
 
         // Iterate over all states and find the largest one which is being
         // transitioned to/from.
-        for (PanelState state : PanelState.values()) {
+        for (@PanelState int state = 0; state < PanelState.NUM_ENTRIES; state++) {
             if (!isValidUiState(state)) continue;
             if (panelHeight <= getPanelHeightFromState(state)) {
                 stateFound = state;
@@ -851,7 +847,8 @@
      * @param endState The final state of the Panel.
      * @return The completion percentage.
      */
-    private float getStateCompletion(float height, PanelState startState, PanelState endState) {
+    private float getStateCompletion(
+            float height, @PanelState int startState, @PanelState int endState) {
         float startSize = getPanelHeightFromState(startState);
         float endSize = getPanelHeightFromState(endState);
         // NOTE(pedrosimonetti): Handle special case from PanelState.UNDEFINED
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanel.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanel.java
index 4f14d44c..bb50c39 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanel.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanel.java
@@ -170,8 +170,9 @@
     // ============================================================================================
 
     @Override
-    public void setPanelState(PanelState toState, @StateChangeReason int reason) {
-        PanelState fromState = getPanelState();
+    public void setPanelState(@PanelState int toState, @StateChangeReason int reason) {
+        @PanelState
+        int fromState = getPanelState();
 
         mPanelMetrics.onPanelStateChanged(
                 fromState, toState, reason, Profile.getLastUsedProfile().getOriginalProfile());
@@ -193,7 +194,7 @@
     }
 
     @Override
-    protected boolean isSupportedState(PanelState state) {
+    protected boolean isSupportedState(@PanelState int state) {
         return canDisplayContentInPanel() || state != PanelState.MAXIMIZED;
     }
 
@@ -207,8 +208,9 @@
     }
 
     @Override
-    protected PanelState getProjectedState(float velocity) {
-        PanelState projectedState = super.getProjectedState(velocity);
+    protected @PanelState int getProjectedState(float velocity) {
+        @PanelState
+        int projectedState = super.getProjectedState(velocity);
 
         // Prevent the fling gesture from moving the Panel from PEEKED to MAXIMIZED. This is to
         // make sure the Promo will be visible, considering that the EXPANDED state is the only
@@ -522,7 +524,7 @@
     }
 
     @Override
-    public PanelState getPanelState() {
+    public @PanelState int getPanelState() {
         // NOTE(pedrosimonetti): exposing superclass method to the interface.
         return super.getPanelState();
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanelMetrics.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanelMetrics.java
index 3890a16a..5bc5642 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanelMetrics.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanelMetrics.java
@@ -68,7 +68,7 @@
      * @param reason The reason for the state change.
      * @param profile The current {@link Profile}.
      */
-    public void onPanelStateChanged(PanelState fromState, PanelState toState,
+    public void onPanelStateChanged(@PanelState int fromState, @PanelState int toState,
             @StateChangeReason int reason, Profile profile) {
         // Note: the logging within this function includes the promo, unless specifically
         // excluded.
@@ -368,7 +368,7 @@
      * @return Whether a new contextual search is starting.
      */
     private boolean isStartingNewContextualSearch(
-            PanelState toState, @StateChangeReason int reason) {
+            @PanelState int toState, @StateChangeReason int reason) {
         return toState == PanelState.PEEKED
                 && (reason == StateChangeReason.TEXT_SELECT_TAP
                         || reason == StateChangeReason.TEXT_SELECT_LONG_PRESS);
@@ -381,8 +381,8 @@
      * @param isStartingSearch Whether a new contextual search is starting.
      * @return Whether a contextual search is ending.
      */
-    private boolean isEndingContextualSearch(PanelState fromState, PanelState toState,
-            boolean isStartingSearch) {
+    private boolean isEndingContextualSearch(
+            @PanelState int fromState, @PanelState int toState, boolean isStartingSearch) {
         return isOngoingContextualSearch(fromState)
                 && (toState == PanelState.CLOSED || isStartingSearch);
     }
@@ -391,8 +391,7 @@
      * @param fromState The state the panel is transitioning from.
      * @return Whether there is an ongoing contextual search.
      */
-    private boolean isOngoingContextualSearch(PanelState fromState) {
+    private boolean isOngoingContextualSearch(@PanelState int fromState) {
         return fromState != PanelState.UNDEFINED && fromState != PanelState.CLOSED;
     }
 }
-
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/ephemeraltab/EphemeralTabPanel.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/ephemeraltab/EphemeralTabPanel.java
index fae8ab9..c3fa0b9 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/ephemeraltab/EphemeralTabPanel.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/ephemeraltab/EphemeralTabPanel.java
@@ -109,7 +109,7 @@
     }
 
     @Override
-    public void setPanelState(PanelState toState, @StateChangeReason int reason) {
+    public void setPanelState(@PanelState int toState, @StateChangeReason int reason) {
         super.setPanelState(toState, reason);
         if (toState == PanelState.CLOSED) {
             RecordHistogram.recordBooleanHistogram("EphemeralTab.Ctr", mWasPanelOpened);
@@ -175,7 +175,7 @@
     }
 
     @Override
-    protected boolean isSupportedState(PanelState state) {
+    protected boolean isSupportedState(@PanelState int state) {
         return state != PanelState.EXPANDED;
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManager.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManager.java
index 314b1353..4cc0dc2 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManager.java
@@ -90,9 +90,12 @@
     // External Dependencies
     private TabModelSelector mTabModelSelector;
 
-    private TabModelObserver mTabModelObserver;
     private TabModelSelectorObserver mTabModelSelectorObserver;
     private TabModelSelectorTabObserver mTabModelSelectorTabObserver;
+
+    // An observer for watching TabModelFilters changes events.
+    private TabModelObserver mTabModelFilterObserver;
+
     private ViewGroup mContentContainer;
 
     // External Observers
@@ -442,8 +445,9 @@
         selector.addObserver(mTabModelSelectorObserver);
         selector.setCloseAllTabsDelegate(this);
 
-        mTabModelObserver = createTabModelObserver();
-        for (TabModel model : selector.getModels()) model.addObserver(mTabModelObserver);
+        mTabModelFilterObserver = createTabModelObserver();
+        getTabModelSelector().getTabModelFilterProvider().addTabModelFilterObserver(
+                mTabModelFilterObserver);
     }
 
     /**
@@ -458,10 +462,9 @@
         if (mTabModelSelectorObserver != null) {
             getTabModelSelector().removeObserver(mTabModelSelectorObserver);
         }
-        if (mTabModelObserver != null) {
-            for (TabModel model : getTabModelSelector().getModels()) {
-                model.removeObserver(mTabModelObserver);
-            }
+        if (mTabModelFilterObserver != null) {
+            getTabModelSelector().getTabModelFilterProvider().removeTabModelFilterObserver(
+                    mTabModelFilterObserver);
         }
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChrome.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChrome.java
index 29608710..950d0482 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChrome.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChrome.java
@@ -107,16 +107,18 @@
             TabContentManager content, ViewGroup androidContentContainer,
             ContextualSearchManagementDelegate contextualSearchDelegate,
             DynamicResourceLoader dynamicResourceLoader) {
+        super.init(selector, creator, content, androidContentContainer, contextualSearchDelegate,
+                dynamicResourceLoader);
+
         // TODO: TitleCache should be a part of the ResourceManager.
         mTitleCache = mHost.getTitleCache();
 
         // Initialize Layouts
         mToolbarSwipeLayout.setTabModelSelector(selector, content);
         mOverviewListLayout.setTabModelSelector(selector, content);
-        if (mOverviewLayout != null) mOverviewLayout.setTabModelSelector(selector, content);
-
-        super.init(selector, creator, content, androidContentContainer, contextualSearchDelegate,
-                dynamicResourceLoader);
+        if (mOverviewLayout != null) {
+            mOverviewLayout.setTabModelSelector(selector, content);
+        }
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChromePhone.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChromePhone.java
index 5757727..4a7bb4f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChromePhone.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChromePhone.java
@@ -49,11 +49,11 @@
             TabContentManager content, ViewGroup androidContentContainer,
             ContextualSearchManagementDelegate contextualSearchDelegate,
             DynamicResourceLoader dynamicResourceLoader) {
-        // Initialize Layouts
-        mSimpleAnimationLayout.setTabModelSelector(selector, content);
-
         super.init(selector, creator, content, androidContentContainer, contextualSearchDelegate,
                 dynamicResourceLoader);
+
+        // Initialize Layouts
+        mSimpleAnimationLayout.setTabModelSelector(selector, content);
     }
 
     @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/StackLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/StackLayout.java
index 5d50055..ac323ba 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/StackLayout.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/StackLayout.java
@@ -53,8 +53,8 @@
     public void setTabModelSelector(TabModelSelector modelSelector, TabContentManager manager) {
         super.setTabModelSelector(modelSelector, manager);
         ArrayList<TabList> tabLists = new ArrayList<TabList>();
-        tabLists.add(modelSelector.getModel(false));
-        tabLists.add(modelSelector.getModel(true));
+        tabLists.add(modelSelector.getTabModelFilterProvider().getTabModelFilter(false));
+        tabLists.add(modelSelector.getTabModelFilterProvider().getTabModelFilter(true));
         setTabLists(tabLists);
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java
index e30dbf8..1da7a5f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java
@@ -469,7 +469,8 @@
 
         // If the user is jumping from one unseen search to another search, remove the last search
         // from history.
-        PanelState state = mSearchPanel.getPanelState();
+        @PanelState
+        int state = mSearchPanel.getPanelState();
         if (!mWereSearchResultsSeen && mLoadedSearchUrlTimeMs != 0L
                 && state != PanelState.UNDEFINED && state != PanelState.CLOSED) {
             removeLastSearchVisit();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchUma.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchUma.java
index 83e23f8c..6ec6770 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchUma.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchUma.java
@@ -339,14 +339,14 @@
      * Key used in maps from {state, reason} to state entry (exit) logging code.
      */
     static class StateChangeKey {
-        final PanelState mState;
+        final @PanelState int mState;
         final @StateChangeReason int mReason;
         final int mHashCode;
 
-        StateChangeKey(PanelState state, @StateChangeReason int reason) {
+        StateChangeKey(@PanelState int state, @StateChangeReason int reason) {
             mState = state;
             mReason = reason;
-            mHashCode = 31 * state.hashCode() + reason;
+            mHashCode = 31 * state + reason;
         }
 
         @Override
@@ -354,7 +354,7 @@
             if (!(obj instanceof StateChangeKey)) return false;
             if (obj == this) return true;
             StateChangeKey other = (StateChangeKey) obj;
-            return mState.equals(other.mState) && mReason == other.mReason;
+            return mState == other.mState && mReason == other.mReason;
         }
 
         @Override
@@ -1152,28 +1152,28 @@
      * @param reason The reason for the state transition.
      */
     public static void logFirstStateEntry(
-            PanelState fromState, PanelState toState, @StateChangeReason int reason) {
+            @PanelState int fromState, @PanelState int toState, @StateChangeReason int reason) {
         int code;
         switch (toState) {
-            case CLOSED:
+            case PanelState.CLOSED:
                 code = getStateChangeCode(
                         fromState, reason, ENTER_CLOSED_STATE_CHANGE_CODES, EnterClosedFrom.OTHER);
                 RecordHistogram.recordEnumeratedHistogram(
                         "Search.ContextualSearchEnterClosed", code, EnterClosedFrom.NUM_ENTRIES);
                 break;
-            case PEEKED:
+            case PanelState.PEEKED:
                 code = getStateChangeCode(
                         fromState, reason, ENTER_PEEKED_STATE_CHANGE_CODES, EnterPeekedFrom.OTHER);
                 RecordHistogram.recordEnumeratedHistogram(
                         "Search.ContextualSearchEnterPeeked", code, EnterPeekedFrom.NUM_ENTRIES);
                 break;
-            case EXPANDED:
+            case PanelState.EXPANDED:
                 code = getStateChangeCode(fromState, reason, ENTER_EXPANDED_STATE_CHANGE_CODES,
                         EnterExpandedFrom.OTHER);
                 RecordHistogram.recordEnumeratedHistogram("Search.ContextualSearchEnterExpanded",
                         code, EnterExpandedFrom.NUM_ENTRIES);
                 break;
-            case MAXIMIZED:
+            case PanelState.MAXIMIZED:
                 code = getStateChangeCode(fromState, reason, ENTER_MAXIMIZED_STATE_CHANGE_CODES,
                         EnterMaximizedFrom.OTHER);
                 RecordHistogram.recordEnumeratedHistogram("Search.ContextualSearchEnterMaximized",
@@ -1189,9 +1189,10 @@
      * @param toState The state to transition to.
      * @param reason The reason for the state transition.
      */
-    public static void logPanelStateUserAction(PanelState toState, @StateChangeReason int reason) {
+    public static void logPanelStateUserAction(
+            @PanelState int toState, @StateChangeReason int reason) {
         switch (toState) {
-            case CLOSED:
+            case PanelState.CLOSED:
                 if (reason == StateChangeReason.BACK_PRESS) {
                     RecordUserAction.record("ContextualSearch.BackPressClose");
                 } else if (reason == StateChangeReason.CLOSE_BUTTON) {
@@ -1212,7 +1213,7 @@
                     RecordUserAction.record("ContextualSearch.UncommonClose");
                 }
                 break;
-            case PEEKED:
+            case PanelState.PEEKED:
                 if (reason == StateChangeReason.TEXT_SELECT_TAP) {
                     RecordUserAction.record("ContextualSearch.TapPeek");
                 } else if (reason == StateChangeReason.SWIPE || reason == StateChangeReason.FLING) {
@@ -1221,14 +1222,14 @@
                     RecordUserAction.record("ContextualSearch.LongpressPeek");
                 }
                 break;
-            case EXPANDED:
+            case PanelState.EXPANDED:
                 if (reason == StateChangeReason.SWIPE || reason == StateChangeReason.FLING) {
                     RecordUserAction.record("ContextualSearch.SwipeOrFlingExpand");
                 } else if (reason == StateChangeReason.SEARCH_BAR_TAP) {
                     RecordUserAction.record("ContextualSearch.SearchBarTapExpand");
                 }
                 break;
-            case MAXIMIZED:
+            case PanelState.MAXIMIZED:
                 if (reason == StateChangeReason.SWIPE || reason == StateChangeReason.FLING) {
                     RecordUserAction.record("ContextualSearch.SwipeOrFlingMaximize");
                 } else if (reason == StateChangeReason.SERP_NAVIGATION) {
@@ -1247,29 +1248,29 @@
      * @param reason The reason for the state transition.
      */
     public static void logFirstStateExit(
-            PanelState fromState, PanelState toState, @StateChangeReason int reason) {
+            @PanelState int fromState, @PanelState int toState, @StateChangeReason int reason) {
         int code;
         switch (fromState) {
-            case UNDEFINED:
-            case CLOSED:
+            case PanelState.UNDEFINED:
+            case PanelState.CLOSED:
                 code = getStateChangeCode(
                         toState, reason, EXIT_CLOSED_TO_STATE_CHANGE_CODES, ExitClosedTo.OTHER);
                 RecordHistogram.recordEnumeratedHistogram(
                         "Search.ContextualSearchExitClosed", code, ExitClosedTo.NUM_ENTRIES);
                 break;
-            case PEEKED:
+            case PanelState.PEEKED:
                 code = getStateChangeCode(
                         toState, reason, EXIT_PEEKED_TO_STATE_CHANGE_CODES, ExitPeekedTo.OTHER);
                 RecordHistogram.recordEnumeratedHistogram(
                         "Search.ContextualSearchExitPeeked", code, ExitPeekedTo.NUM_ENTRIES);
                 break;
-            case EXPANDED:
+            case PanelState.EXPANDED:
                 code = getStateChangeCode(
                         toState, reason, EXIT_EXPANDED_TO_STATE_CHANGE_CODES, ExitExpandedTo.OTHER);
                 RecordHistogram.recordEnumeratedHistogram(
                         "Search.ContextualSearchExitExpanded", code, ExitExpandedTo.NUM_ENTRIES);
                 break;
-            case MAXIMIZED:
+            case PanelState.MAXIMIZED:
                 code = getStateChangeCode(toState, reason, EXIT_MAXIMIZED_TO_STATE_CHANGE_CODES,
                         ExitMaximizedTo.OTHER);
                 RecordHistogram.recordEnumeratedHistogram(
@@ -1543,7 +1544,7 @@
      * @param defaultCode The code to return if the given values are not found in the map.
      * @return The code to write into an enum histogram, based on the given map.
      */
-    private static int getStateChangeCode(PanelState state, @StateChangeReason int reason,
+    private static int getStateChangeCode(@PanelState int state, @StateChangeReason int reason,
             Map<StateChangeKey, Integer> stateChangeCodes, int defaultCode) {
         Integer code = stateChangeCodes.get(new StateChangeKey(state, reason));
         return code != null ? code : defaultCode;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadActivity.java
index ffe159a8..7ab86f5 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadActivity.java
@@ -17,9 +17,11 @@
 import org.chromium.chrome.browser.download.home.DownloadManagerUiConfig;
 import org.chromium.chrome.browser.download.items.OfflineContentAggregatorNotificationBridgeUiFactory;
 import org.chromium.chrome.browser.download.ui.DownloadManagerUi;
+import org.chromium.chrome.browser.modaldialog.AppModalPresenter;
 import org.chromium.chrome.browser.util.IntentUtils;
 import org.chromium.ui.base.ActivityAndroidPermissionDelegate;
 import org.chromium.ui.base.AndroidPermissionDelegate;
+import org.chromium.ui.modaldialog.ModalDialogManager;
 
 import java.lang.ref.WeakReference;
 
@@ -32,6 +34,7 @@
     private DownloadManagerCoordinator mDownloadCoordinator;
     private boolean mIsOffTheRecord;
     private AndroidPermissionDelegate mPermissionDelegate;
+    private ModalDialogManager mModalDialogManager;
 
     /** Caches the current URL for the filter being applied. */
     private String mCurrentUrl;
@@ -59,8 +62,11 @@
                                                  .setIsOffTheRecord(isOffTheRecord)
                                                  .setIsSeparateActivity(true)
                                                  .build();
+
+        mModalDialogManager = new ModalDialogManager(
+                new AppModalPresenter(this), ModalDialogManager.ModalDialogType.APP);
         mDownloadCoordinator = DownloadManagerCoordinatorFactory.create(
-                this, config, getSnackbarManager(), parentComponent);
+                this, config, getSnackbarManager(), parentComponent, mModalDialogManager);
         setContentView(mDownloadCoordinator.getView());
         mIsOffTheRecord = isOffTheRecord;
         mDownloadCoordinator.addObserver(mUiObserver);
@@ -95,6 +101,7 @@
     protected void onDestroy() {
         mDownloadCoordinator.removeObserver(mUiObserver);
         mDownloadCoordinator.destroy();
+        mModalDialogManager.destroy();
         super.onDestroy();
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadPage.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadPage.java
index f1f1255..b3bd28c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadPage.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadPage.java
@@ -47,7 +47,8 @@
                                                  .setIsSeparateActivity(false)
                                                  .build();
         mDownloadCoordinator = DownloadManagerCoordinatorFactory.create(activity, config,
-                ((SnackbarManageable) activity).getSnackbarManager(), activity.getComponentName());
+                ((SnackbarManageable) activity).getSnackbarManager(), activity.getComponentName(),
+                activity.getModalDialogManager());
 
         mDownloadCoordinator.addObserver(this);
         mTitle = activity.getString(R.string.menu_downloads);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/DownloadManagerCoordinatorFactory.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/DownloadManagerCoordinatorFactory.java
index 6b333cf..49034b0a 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/DownloadManagerCoordinatorFactory.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/DownloadManagerCoordinatorFactory.java
@@ -11,6 +11,7 @@
 import org.chromium.chrome.browser.download.ui.DownloadManagerUi;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.snackbar.SnackbarManager;
+import org.chromium.ui.modaldialog.ModalDialogManager;
 
 /** A helper class to build and return an {@link DownloadManagerCoordinator}. */
 public class DownloadManagerCoordinatorFactory {
@@ -20,14 +21,15 @@
      * @param config             A {@link DownloadManagerUiConfig} to provide configuration params.
      * @param parentComponent    The parent component.
      * @param snackbarManager    The {@link SnackbarManager} that should be used to show snackbars.
+     * @param modalDialogManager The {@link ModalDialogManager} that should be used to show dialog.
      * @return                   A new {@link DownloadManagerCoordinator} instance.
      */
     public static DownloadManagerCoordinator create(Activity activity,
             DownloadManagerUiConfig config, SnackbarManager snackbarManager,
-            ComponentName parentComponent) {
+            ComponentName parentComponent, ModalDialogManager modalDialogManager) {
         if (ChromeFeatureList.isEnabled(ChromeFeatureList.DOWNLOAD_HOME_V2)) {
-            return new DownloadManagerCoordinatorImpl(
-                    Profile.getLastUsedProfile(), activity, config, snackbarManager);
+            return new DownloadManagerCoordinatorImpl(Profile.getLastUsedProfile(), activity,
+                    config, snackbarManager, modalDialogManager);
         } else {
             return new DownloadManagerUi(activity, config.isOffTheRecord, parentComponent,
                     config.isSeparateActivity, snackbarManager);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/DownloadManagerCoordinatorImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/DownloadManagerCoordinatorImpl.java
index a71250c5..400965b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/DownloadManagerCoordinatorImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/DownloadManagerCoordinatorImpl.java
@@ -27,6 +27,7 @@
 import org.chromium.chrome.browser.snackbar.SnackbarManager;
 import org.chromium.chrome.browser.widget.selection.SelectionDelegate;
 import org.chromium.chrome.download.R;
+import org.chromium.ui.modaldialog.ModalDialogManager;
 
 import java.io.Closeable;
 
@@ -52,14 +53,15 @@
 
     /** Builds a {@link DownloadManagerCoordinatorImpl} instance. */
     public DownloadManagerCoordinatorImpl(Profile profile, Activity activity,
-            DownloadManagerUiConfig config, SnackbarManager snackbarManager) {
+            DownloadManagerUiConfig config, SnackbarManager snackbarManager,
+            ModalDialogManager modalDialogManager) {
         mActivity = activity;
         mDeleteCoordinator = new DeleteUndoCoordinator(snackbarManager);
         mSelectionDelegate = new SelectionDelegate<ListItem>();
         mListCoordinator = new DateOrderedListCoordinator(mActivity, config,
                 OfflineContentAggregatorFactory.forProfile(profile),
-                mDeleteCoordinator::showSnackbar, mSelectionDelegate, this ::notifyFilterChanged,
-                createDateOrderedListObserver());
+                mDeleteCoordinator::showSnackbar, mSelectionDelegate, this::notifyFilterChanged,
+                createDateOrderedListObserver(), modalDialogManager);
         mToolbarCoordinator = new ToolbarCoordinator(mActivity, this, mListCoordinator,
                 mSelectionDelegate, config.isSeparateActivity, profile);
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/glue/OfflineContentProviderGlue.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/glue/OfflineContentProviderGlue.java
index 29563901..50f7f82 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/glue/OfflineContentProviderGlue.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/glue/OfflineContentProviderGlue.java
@@ -4,6 +4,9 @@
 
 package org.chromium.chrome.browser.download.home.glue;
 
+import android.os.Handler;
+import android.os.Looper;
+
 import org.chromium.base.Callback;
 import org.chromium.base.ObserverList;
 import org.chromium.chrome.browser.download.home.DownloadManagerUiConfig;
@@ -13,6 +16,7 @@
 import org.chromium.components.offline_items_collection.LegacyHelpers;
 import org.chromium.components.offline_items_collection.OfflineContentProvider;
 import org.chromium.components.offline_items_collection.OfflineItem;
+import org.chromium.components.offline_items_collection.RenameResult;
 import org.chromium.components.offline_items_collection.ShareCallback;
 import org.chromium.components.offline_items_collection.VisualsCallback;
 
@@ -77,6 +81,13 @@
         }
     }
 
+    /** @see OfflineContentProvider#renameItem(ContentId, String, Callback) */
+    public void renameItem(
+            OfflineItem item, String targetName, Callback</*RenameResult*/ Integer> callback) {
+        // TODO(hesen):Implement glue.
+        new Handler(Looper.getMainLooper()).post(() -> callback.onResult(RenameResult.SUCCESS));
+    }
+
     /** @see OfflineContentProvider#cancelDownload(ContentId) */
     public void cancelDownload(OfflineItem item) {
         if (mDownloadProvider != null && LegacyHelpers.isLegacyDownload(item.id)) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/DateOrderedListCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/DateOrderedListCoordinator.java
index 0e6c5c1d..aa57e30 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/DateOrderedListCoordinator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/DateOrderedListCoordinator.java
@@ -21,11 +21,13 @@
 import org.chromium.chrome.browser.download.home.filter.Filters.FilterType;
 import org.chromium.chrome.browser.download.home.list.ListItem.ViewListItem;
 import org.chromium.chrome.browser.download.home.metrics.FilterChangeLogger;
+import org.chromium.chrome.browser.download.home.rename.RenameDialogCoordinator;
 import org.chromium.chrome.browser.download.home.storage.StorageCoordinator;
 import org.chromium.chrome.browser.download.home.toolbar.ToolbarCoordinator;
 import org.chromium.chrome.browser.widget.selection.SelectionDelegate;
 import org.chromium.components.offline_items_collection.OfflineContentProvider;
 import org.chromium.components.offline_items_collection.OfflineItem;
+import org.chromium.ui.modaldialog.ModalDialogManager;
 
 import java.util.List;
 
@@ -78,6 +80,7 @@
     private final EmptyCoordinator mEmptyCoordinator;
     private final DateOrderedListMediator mMediator;
     private final DateOrderedListView mListView;
+    private final RenameDialogCoordinator mRenameDialogCoordinator;
     private ViewGroup mMainView;
 
     /**
@@ -96,15 +99,18 @@
             OfflineContentProvider provider, DeleteController deleteController,
             SelectionDelegate<ListItem> selectionDelegate,
             FilterCoordinator.Observer filterObserver,
-            DateOrderedListObserver dateOrderedListObserver) {
+            DateOrderedListObserver dateOrderedListObserver,
+            ModalDialogManager modalDialogManager) {
         mContext = context;
 
         ListItemModel model = new ListItemModel();
         DecoratedListItemModel decoratedModel = new DecoratedListItemModel(model);
         mListView =
                 new DateOrderedListView(context, config, decoratedModel, dateOrderedListObserver);
-        mMediator = new DateOrderedListMediator(provider, this ::startShareIntent, deleteController,
-                selectionDelegate, config, dateOrderedListObserver, model);
+        mRenameDialogCoordinator = new RenameDialogCoordinator(context, modalDialogManager);
+
+        mMediator = new DateOrderedListMediator(provider, this::startShareIntent, deleteController,
+                this::startRename, selectionDelegate, config, dateOrderedListObserver, model);
 
         mEmptyCoordinator = new EmptyCoordinator(context, mMediator.getEmptySource());
 
@@ -144,6 +150,7 @@
     /** Tears down this coordinator. */
     public void destroy() {
         mMediator.destroy();
+        mRenameDialogCoordinator.destroy();
     }
 
     /** @return The {@link View} representing downloads home. */
@@ -182,4 +189,8 @@
         mContext.startActivity(Intent.createChooser(
                 intent, mContext.getString(R.string.share_link_chooser_title)));
     }
+
+    private void startRename(String name, DateOrderedListMediator.RenameCallback callback) {
+        mRenameDialogCoordinator.startRename(name, callback::tryToRename);
+    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/DateOrderedListMediator.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/DateOrderedListMediator.java
index b49dd403..5e28f18 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/DateOrderedListMediator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/DateOrderedListMediator.java
@@ -9,6 +9,7 @@
 import android.support.annotation.Nullable;
 import android.support.v4.util.Pair;
 
+import org.chromium.base.Callback;
 import org.chromium.base.CollectionUtil;
 import org.chromium.base.ContextUtils;
 import org.chromium.chrome.browser.ChromeApplication;
@@ -62,12 +63,38 @@
         void share(Intent intent);
     }
 
+    /**
+     * Helper interface for handling rename requests by the UI, allows implementers of the
+     * RenameController to finish the asynchronous rename operation.
+     */
+    @FunctionalInterface
+    public interface RenameCallback {
+        /**
+         * Calling this will asynchronously attempt to commit a new name.
+         * @param newName String representing the new name user designated to rename the item.
+         * @param callback A callback that will pass to the backend to determine the validation
+         *         result.
+         */
+        void tryToRename(String newName, Callback</*RenameResult*/ Integer> callback);
+    }
+
+    /** Helper interface for handling rename requests by the UI. */
+    @FunctionalInterface
+    public interface RenameController {
+        /**
+         * Will be called whenever {@link OfflineItem}s are being requested to be renamed by the UI.
+         * @param name representing new name user designated to rename the item.
+         */
+        void rename(String name, RenameCallback result);
+    }
+
     private final Handler mHandler = new Handler();
 
     private final OfflineContentProviderGlue mProvider;
     private final ShareController mShareController;
     private final ListItemModel mModel;
     private final DeleteController mDeleteController;
+    private final RenameController mRenameController;
 
     private final OfflineItemSource mSource;
     private final DateOrderedListMutator mListMutator;
@@ -122,9 +149,9 @@
      * @param model                   The {@link ListItemModel} to push {@code provider} into.
      */
     public DateOrderedListMediator(OfflineContentProvider provider, ShareController shareController,
-            DeleteController deleteController, SelectionDelegate<ListItem> selectionDelegate,
-            DownloadManagerUiConfig config, DateOrderedListObserver dateOrderedListObserver,
-            ListItemModel model) {
+            DeleteController deleteController, RenameController renameController,
+            SelectionDelegate<ListItem> selectionDelegate, DownloadManagerUiConfig config,
+            DateOrderedListObserver dateOrderedListObserver, ListItemModel model) {
         // Build a chain from the data source to the model.  The chain will look like:
         // [OfflineContentProvider] ->
         //     [OfflineItemSource] ->
@@ -140,6 +167,7 @@
         mShareController = shareController;
         mModel = model;
         mDeleteController = deleteController;
+        mRenameController = renameController;
         mSelectionDelegate = selectionDelegate;
         mUiConfig = config;
 
@@ -171,6 +199,7 @@
         mModel.getProperties().set(ListProperties.CALLBACK_REMOVE_ALL, this ::onDeleteItems);
         mModel.getProperties().set(ListProperties.PROVIDER_VISUALS, this ::getVisuals);
         mModel.getProperties().set(ListProperties.CALLBACK_SELECTION, this ::onSelection);
+        mModel.getProperties().set(ListProperties.CALLBACK_RENAME, this::onRenameItem);
         mModel.getProperties().set(
                 ListProperties.CALLBACK_START_SELECTION, this ::onStartSelection);
     }
@@ -308,6 +337,13 @@
         deleteItemsInternal(items);
     }
 
+    private void onRenameItem(OfflineItem item) {
+        // TODO(hesen): Add sanity check canRename for item, and add uma stats.
+        mRenameController.rename(item.title, (newName, renameCallback) -> {
+            mProvider.renameItem(item, newName, renameCallback);
+        });
+    }
+
     /**
      * Deletes a given list of items. If the items are not completed yet, they would be cancelled.
      * @param items The list of items to delete.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/ListProperties.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/ListProperties.java
index 5b38d72..7ac8b30 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/ListProperties.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/ListProperties.java
@@ -69,6 +69,10 @@
     WritableObjectPropertyKey < Callback < List<OfflineItem>>> CALLBACK_REMOVE_ALL =
             new WritableObjectPropertyKey<>();
 
+    /** The callback for when a UI action should rename a {@link OfflineItem}. */
+    WritableObjectPropertyKey<Callback<OfflineItem>> CALLBACK_RENAME =
+            new WritableObjectPropertyKey<>();
+
     /** The provider to retrieve expensive assets for a {@link OfflineItem}. */
     WritableObjectPropertyKey<VisualsProvider> PROVIDER_VISUALS = new WritableObjectPropertyKey<>();
 
@@ -89,6 +93,6 @@
 
     PropertyKey[] ALL_KEYS = new PropertyKey[] {ENABLE_ITEM_ANIMATIONS, CALLBACK_OPEN,
             CALLBACK_PAUSE, CALLBACK_RESUME, CALLBACK_CANCEL, CALLBACK_SHARE, CALLBACK_SHARE_ALL,
-            CALLBACK_REMOVE, CALLBACK_REMOVE_ALL, PROVIDER_VISUALS, CALLBACK_SELECTION,
-            SELECTION_MODE_ACTIVE, CALLBACK_START_SELECTION};
+            CALLBACK_REMOVE, CALLBACK_REMOVE_ALL, CALLBACK_RENAME, PROVIDER_VISUALS,
+            CALLBACK_SELECTION, SELECTION_MODE_ACTIVE, CALLBACK_START_SELECTION};
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/ListPropertyViewBinder.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/ListPropertyViewBinder.java
index c84b90b..ec180673 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/ListPropertyViewBinder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/ListPropertyViewBinder.java
@@ -35,6 +35,7 @@
                 || propertyKey == ListProperties.CALLBACK_REMOVE
                 || propertyKey == ListProperties.PROVIDER_VISUALS
                 || propertyKey == ListProperties.CALLBACK_SELECTION
+                || propertyKey == ListProperties.CALLBACK_RENAME
                 || propertyKey == ListProperties.SELECTION_MODE_ACTIVE) {
             view.getAdapter().notifyItemRangeChanged(0, view.getAdapter().getItemCount());
         }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/OfflineItemViewHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/OfflineItemViewHolder.java
index 47d8b8c..bd702916 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/OfflineItemViewHolder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/holder/OfflineItemViewHolder.java
@@ -37,6 +37,10 @@
     // Persisted 'More' button properties.
     private Runnable mShareCallback;
     private Runnable mDeleteCallback;
+    private Runnable mRenameCallback;
+
+    // flag to hide rename list menu option for offline pages
+    private boolean mCanRename;
 
     /**
      * Creates a new instance of a {@link MoreButtonViewHolder}.
@@ -76,7 +80,8 @@
                     () -> properties.get(ListProperties.CALLBACK_SHARE).onResult(offlineItem);
             mDeleteCallback =
                     () -> properties.get(ListProperties.CALLBACK_REMOVE).onResult(offlineItem);
-
+            mRenameCallback =
+                    () -> properties.get(ListProperties.CALLBACK_RENAME).onResult(offlineItem);
             mMore.setClickable(!properties.get(ListProperties.SELECTION_MODE_ACTIVE));
         }
 
@@ -97,6 +102,7 @@
                         });
             }, offlineItem.id);
         }
+        // TODO(hesen): Add a new property in OfflineItem, set false for now.
     }
 
     @Override
@@ -123,9 +129,16 @@
     // ListMenuButton.Delegate implementation.
     @Override
     public ListMenuButton.Item[] getItems() {
-        return new ListMenuButton.Item[] {
-                new ListMenuButton.Item(itemView.getContext(), R.string.share, true),
-                new ListMenuButton.Item(itemView.getContext(), R.string.delete, true)};
+        if (mCanRename) {
+            return new ListMenuButton.Item[] {
+                    new ListMenuButton.Item(itemView.getContext(), R.string.share, true),
+                    new ListMenuButton.Item(itemView.getContext(), R.string.rename, true),
+                    new ListMenuButton.Item(itemView.getContext(), R.string.delete, true)};
+        } else {
+            return new ListMenuButton.Item[] {
+                    new ListMenuButton.Item(itemView.getContext(), R.string.share, true),
+                    new ListMenuButton.Item(itemView.getContext(), R.string.delete, true)};
+        }
     }
 
     @Override
@@ -134,6 +147,8 @@
             if (mShareCallback != null) mShareCallback.run();
         } else if (item.getTextId() == R.string.delete) {
             if (mDeleteCallback != null) mDeleteCallback.run();
+        } else if (item.getTextId() == R.string.rename) {
+            if (mRenameCallback != null) mRenameCallback.run();
         }
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/rename/RenameDialogCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/rename/RenameDialogCoordinator.java
new file mode 100644
index 0000000..03bcc7b
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/rename/RenameDialogCoordinator.java
@@ -0,0 +1,106 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+package org.chromium.chrome.browser.download.home.rename;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+
+import org.chromium.base.Callback;
+import org.chromium.components.offline_items_collection.RenameResult;
+import org.chromium.ui.modaldialog.DialogDismissalCause;
+import org.chromium.ui.modaldialog.ModalDialogManager;
+import org.chromium.ui.modaldialog.ModalDialogProperties;
+import org.chromium.ui.modelutil.PropertyModel;
+
+/**
+ * A class to manage Rename Dialog UI.
+ */
+public class RenameDialogCoordinator {
+    /**
+     * Helper interface for handling rename attempts by the UI, must be called when user click
+     * submit and make the attempt to rename the download item, allows the UI to
+     * response to result of a rename attempt from the backend.
+     */
+    @FunctionalInterface
+    public interface RenameCallback {
+        void attemptRename(String name, Callback</*@RenameResult*/ Integer> callback);
+    }
+
+    private final ModalDialogManager mModalDialogManager;
+    private final PropertyModel mRenameDialogModel;
+    private final RenameDialogCustomView mRenameDialogCustomView;
+
+    private String mOriginalName;
+    private RenameCallback mRenameCallback;
+
+    public RenameDialogCoordinator(Context context, ModalDialogManager modalDialogManager) {
+        mModalDialogManager = modalDialogManager;
+        mRenameDialogCustomView = (RenameDialogCustomView) LayoutInflater.from(context).inflate(
+                org.chromium.chrome.download.R.layout.download_rename_custom_dialog, null);
+        mRenameDialogModel =
+                new PropertyModel.Builder(ModalDialogProperties.ALL_KEYS)
+                        .with(ModalDialogProperties.CONTROLLER, new RenameDialogController())
+                        .with(ModalDialogProperties.TITLE,
+                                context.getString(org.chromium.chrome.download.R.string.rename))
+                        .with(ModalDialogProperties.CUSTOM_VIEW, mRenameDialogCustomView)
+                        .with(ModalDialogProperties.POSITIVE_BUTTON_TEXT, context.getResources(),
+                                org.chromium.chrome.download.R.string.ok)
+                        .with(ModalDialogProperties.NEGATIVE_BUTTON_TEXT, context.getResources(),
+                                org.chromium.chrome.download.R.string.cancel)
+                        .build();
+    }
+
+    /**
+     * Function that will be triggered by UI to show a rename dialog showing {@code originalName}.
+     * @param originalName the Original Name for the download item.
+     * @param callback  the callback that talks to the backend.
+     */
+    public void startRename(String originalName, RenameCallback callback) {
+        mRenameCallback = callback;
+        mOriginalName = originalName;
+        mRenameDialogCustomView.initializeView(originalName);
+        mModalDialogManager.showDialog(mRenameDialogModel, ModalDialogManager.ModalDialogType.APP);
+    }
+
+    public void destroy() {
+        if (mModalDialogManager != null) {
+            mModalDialogManager.dismissDialog(
+                    mRenameDialogModel, DialogDismissalCause.ACTIVITY_DESTROYED);
+        }
+    }
+
+    private class RenameDialogController implements ModalDialogProperties.Controller {
+        @Override
+        public void onDismiss(PropertyModel model, int dismissalCause) {}
+
+        @Override
+        public void onClick(PropertyModel model, int buttonType) {
+            switch (buttonType) {
+                case ModalDialogProperties.ButtonType.POSITIVE:
+                    String targetName = mRenameDialogCustomView.getTargetName();
+
+                    if (targetName.equals(mOriginalName)) {
+                        mModalDialogManager.dismissDialog(
+                                model, DialogDismissalCause.ACTION_ON_CONTENT);
+                        return;
+                    }
+
+                    mRenameCallback.attemptRename(targetName, result -> {
+                        if (result == RenameResult.SUCCESS) {
+                            mModalDialogManager.dismissDialog(
+                                    model, DialogDismissalCause.POSITIVE_BUTTON_CLICKED);
+                        } else {
+                            mRenameDialogCustomView.updateSubtitleView(result);
+                        }
+                    });
+                    break;
+                case ModalDialogProperties.ButtonType.NEGATIVE:
+                    mModalDialogManager.dismissDialog(
+                            model, DialogDismissalCause.NEGATIVE_BUTTON_CLICKED);
+                    break;
+                default:
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/rename/RenameDialogCustomView.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/rename/RenameDialogCustomView.java
new file mode 100644
index 0000000..7e3489d1
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/rename/RenameDialogCustomView.java
@@ -0,0 +1,75 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.download.home.rename;
+
+import android.content.Context;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.ScrollView;
+import android.widget.TextView;
+
+import org.chromium.chrome.browser.widget.AlertDialogEditText;
+import org.chromium.chrome.download.R;
+import org.chromium.components.offline_items_collection.RenameResult;
+
+/**
+ * Content View of dialog in Download Home that allows users to rename a downloaded file
+ */
+public class RenameDialogCustomView extends ScrollView {
+    private TextView mSubtitleView;
+    private AlertDialogEditText mFileName;
+
+    public RenameDialogCustomView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    // ScrollView Implementation
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        mSubtitleView = findViewById(R.id.subtitle);
+        mFileName = findViewById(R.id.file_name);
+    }
+
+    /**
+     * @param suggestedName The suggested file name to fill the initialized edit text.
+     */
+    public void initializeView(String suggestedName) {
+        if (TextUtils.isEmpty(suggestedName)) return;
+        mFileName.setText(suggestedName);
+        mSubtitleView.setVisibility(View.GONE);
+    }
+
+    /**
+     * @param renameResult RenameResult to distinguish dialog type, used for updating the subtitle
+     *         view.
+     */
+    public void updateSubtitleView(@RenameResult int renameResult) {
+        if (renameResult == RenameResult.SUCCESS) return;
+
+        mSubtitleView.setVisibility(View.VISIBLE);
+        switch (renameResult) {
+            case RenameResult.FAILURE_NAME_CONFLICT:
+                mSubtitleView.setText(R.string.rename_failure_name_conflict);
+                break;
+            case RenameResult.FAILURE_NAME_TOO_LONG:
+                mSubtitleView.setText(R.string.rename_failure_name_too_long);
+                break;
+            case RenameResult.FAILURE_UNKNOWN:
+                mSubtitleView.setText(R.string.rename_failure_name_unavailable);
+                break;
+            default:
+                break;
+        }
+    }
+
+    /**
+     * @return a string from user input for the target name.
+     */
+    public String getTargetName() {
+        return mFileName.getText().toString();
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabUma.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabUma.java
index f2587bc..48302ee 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabUma.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabUma.java
@@ -6,6 +6,7 @@
 
 import android.os.SystemClock;
 import android.support.annotation.IntDef;
+import android.text.format.DateUtils;
 
 import org.chromium.base.UserData;
 import org.chromium.base.metrics.RecordHistogram;
@@ -330,12 +331,12 @@
         if (mLastShownTimestamp == -1 && previousTimestampMillis > 0) {
             if (isOnBrowserStartup) {
                 RecordHistogram.recordCountHistogram("Tabs.ForegroundTabAgeAtStartup",
-                        (int) millisecondsToMinutes(System.currentTimeMillis()
-                                                             - previousTimestampMillis));
+                        (int) ((System.currentTimeMillis() - previousTimestampMillis)
+                                / DateUtils.MINUTE_IN_MILLIS));
             } else if (selectionType == TabSelectionType.FROM_USER) {
                 RecordHistogram.recordCountHistogram("Tab.AgeUponRestoreFromColdStart",
-                        (int) millisecondsToMinutes(System.currentTimeMillis()
-                                                             - previousTimestampMillis));
+                        (int) ((System.currentTimeMillis() - previousTimestampMillis)
+                                / DateUtils.MINUTE_IN_MILLIS));
             }
         }
 
@@ -445,8 +446,4 @@
     private static void increaseTabShowCount() {
         sAllTabsShowCount++;
     }
-
-    private static long millisecondsToMinutes(long msec) {
-        return msec / 1000 / 60;
-    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/IncognitoTabModel.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/IncognitoTabModel.java
index 94dfdb2..bcd0d91 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/IncognitoTabModel.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/IncognitoTabModel.java
@@ -30,6 +30,13 @@
 
         /** @return Whether Incognito Tabs exist. */
         boolean doIncognitoTabsExist();
+
+        /**
+         * @param model {@link TabModel} to act on.
+         * @return Whether the provided {@link TabModel} is currently selected in the corresponding
+         * {@link IncognitoTabModelDelegate}.
+         */
+        boolean isCurrentModel(TabModel model);
     }
 
     private final IncognitoTabModelDelegate mDelegate;
@@ -166,7 +173,7 @@
 
     @Override
     public boolean isCurrentModel() {
-        return mDelegateModel.isCurrentModel();
+        return mDelegate.isCurrentModel(this);
     }
 
     @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/IncognitoTabModelImplCreator.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/IncognitoTabModelImplCreator.java
index d3bb5fc8..8eb2d2f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/IncognitoTabModelImplCreator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/IncognitoTabModelImplCreator.java
@@ -59,4 +59,9 @@
     public boolean doIncognitoTabsExist() {
         return IncognitoUtils.doIncognitoTabsExist();
     }
+
+    @Override
+    public boolean isCurrentModel(TabModel model) {
+        return mModelDelegate.isCurrentModel(model);
+    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelFilter.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelFilter.java
index 0f594fda..3d4dd08 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelFilter.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelFilter.java
@@ -25,7 +25,7 @@
     private static final List<Tab> sEmptyRelatedTabList =
             Collections.unmodifiableList(new ArrayList<Tab>());
     private TabModel mTabModel;
-    protected ObserverList<TabModelFilterObserver> mFilteredObservers = new ObserverList<>();
+    protected ObserverList<TabModelObserver> mFilteredObservers = new ObserverList<>();
 
     public TabModelFilter(TabModel tabModel) {
         mTabModel = tabModel;
@@ -33,21 +33,33 @@
     }
 
     /**
-     * Adds a {@link TabModelFilterObserver} to be notified on {@link TabModelFilter} changes.
-     * @param observer The {@link TabModelFilterObserver} to add.
+     * Adds a {@link TabModelObserver} to be notified on {@link TabModelFilter} changes.
+     * @param observer The {@link TabModelObserver} to add.
      */
-    public void addObserver(TabModelFilterObserver observer) {
+    public void addObserver(TabModelObserver observer) {
         mFilteredObservers.addObserver(observer);
     }
 
     /**
-     * Removes a {@link TabModelFilterObserver}.
-     * @param observer The {@link TabModelFilterObserver} to remove.
+     * Removes a {@link TabModelObserver}.
+     * @param observer The {@link TabModelObserver} to remove.
      */
-    public void removeObserver(TabModelFilterObserver observer) {
+    public void removeObserver(TabModelObserver observer) {
         mFilteredObservers.removeObserver(observer);
     }
 
+    public boolean isCurrentlySelectedFilter() {
+        return mTabModel.isCurrentModel();
+    }
+
+    /**
+     * To be called when this filter should be destroyed. This filter should no longer be used after
+     * this.
+     */
+    public void destroy() {
+        mFilteredObservers.clear();
+    }
+
     /**
      * @return The {@link TabModel} that the filter is acting on.
      */
@@ -88,38 +100,92 @@
      */
     protected abstract void selectTab(Tab tab);
 
-    // TabModelObserver implementation
-    // TODO(meiliang): All these implementations should notify each individual listener, after they
-    // had added to TabModelFilterObserver.
+    // TabModelObserver implementation.
     @Override
     public void didSelectTab(Tab tab, int type, int lastId) {
         selectTab(tab);
-        for (TabModelFilterObserver observer : mFilteredObservers) {
-            observer.update();
+        for (TabModelObserver observer : mFilteredObservers) {
+            observer.didSelectTab(tab, type, lastId);
         }
     }
 
     @Override
     public void willCloseTab(Tab tab, boolean animate) {
         closeTab(tab);
-        for (TabModelFilterObserver observer : mFilteredObservers) {
-            observer.update();
+        for (TabModelObserver observer : mFilteredObservers) {
+            observer.willCloseTab(tab, animate);
+        }
+    }
+
+    @Override
+    public void didCloseTab(int tabId, boolean incognito) {
+        for (TabModelObserver observer : mFilteredObservers) {
+            observer.didCloseTab(tabId, incognito);
+        }
+    }
+
+    @Override
+    public void willAddTab(Tab tab, int type) {
+        for (TabModelObserver observer : mFilteredObservers) {
+            observer.willAddTab(tab, type);
         }
     }
 
     @Override
     public void didAddTab(Tab tab, int type) {
         addTab(tab);
-        for (TabModelFilterObserver observer : mFilteredObservers) {
-            observer.update();
+        for (TabModelObserver observer : mFilteredObservers) {
+            observer.didAddTab(tab, type);
+        }
+    }
+
+    @Override
+    public void didMoveTab(Tab tab, int newIndex, int curIndex) {
+        for (TabModelObserver observer : mFilteredObservers) {
+            observer.didMoveTab(tab, newIndex, curIndex);
+        }
+    }
+
+    @Override
+    public void tabPendingClosure(Tab tab) {
+        for (TabModelObserver observer : mFilteredObservers) {
+            observer.tabPendingClosure(tab);
         }
     }
 
     @Override
     public void tabClosureUndone(Tab tab) {
         addTab(tab);
-        for (TabModelFilterObserver observer : mFilteredObservers) {
-            observer.update();
+        for (TabModelObserver observer : mFilteredObservers) {
+            observer.tabClosureUndone(tab);
+        }
+    }
+
+    @Override
+    public void tabClosureCommitted(Tab tab) {
+        for (TabModelObserver observer : mFilteredObservers) {
+            observer.tabClosureCommitted(tab);
+        }
+    }
+
+    @Override
+    public void allTabsPendingClosure(List<Tab> tabs) {
+        for (TabModelObserver observer : mFilteredObservers) {
+            observer.allTabsPendingClosure(tabs);
+        }
+    }
+
+    @Override
+    public void allTabsClosureCommitted() {
+        for (TabModelObserver observer : mFilteredObservers) {
+            observer.allTabsClosureCommitted();
+        }
+    }
+
+    @Override
+    public void tabRemoved(Tab tab) {
+        for (TabModelObserver observer : mFilteredObservers) {
+            observer.tabRemoved(tab);
         }
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelFilterObserver.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelFilterObserver.java
deleted file mode 100644
index 37655fe..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelFilterObserver.java
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.chrome.browser.tabmodel;
-
-/**
- * An interface to be notified about changes to a {@linkt TabModelFilter}.
- */
-public interface TabModelFilterObserver {
-    // TODO(meiliang): Add individual update listener, like addTab, closeTab, etc.
-
-    /**
-     * Called whenever {@link TabModelFilter} changes.
-     */
-    void update();
-}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelFilterProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelFilterProvider.java
new file mode 100644
index 0000000..8dd9ab3
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelFilterProvider.java
@@ -0,0 +1,95 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.tabmodel;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * This class is responsible for creating {@link TabModelFilter}s to be applied on the
+ * {@link TabModel}s. It always owns two {@link TabModelFilter}s, one for normal {@link TabModel}
+ * and one for incognito {@link TabModel}.
+ */
+public class TabModelFilterProvider {
+    private List<TabModelFilter> mTabModelFilterList = Collections.emptyList();
+
+    TabModelFilterProvider() {}
+
+    TabModelFilterProvider(List<TabModel> tabModels) {
+        List<TabModelFilter> filters = new ArrayList<>();
+        for (int i = 0; i < tabModels.size(); i++) {
+            filters.add(createTabModelFilter(tabModels.get(i)));
+        }
+
+        mTabModelFilterList = Collections.unmodifiableList(filters);
+    }
+
+    /**
+     * This method adds {@link TabModelObserver} to both {@link TabModelFilter}s.
+     * @param observer {@link TabModelObserver} to add.
+     */
+    public void addTabModelFilterObserver(TabModelObserver observer) {
+        for (int i = 0; i < mTabModelFilterList.size(); i++) {
+            mTabModelFilterList.get(i).addObserver(observer);
+        }
+    }
+
+    /**
+     * This method removes {@link TabModelObserver} from both {@link TabModelFilter}s.
+     * @param observer {@link TabModelObserver} to remove.
+     */
+    public void removeTabModelFilterObserver(TabModelObserver observer) {
+        for (int i = 0; i < mTabModelFilterList.size(); i++) {
+            mTabModelFilterList.get(i).removeObserver(observer);
+        }
+    }
+
+    /**
+     * This method returns a specific {@link TabModelFilter}.
+     * @param isIncognito Use to indicate which {@link TabModelFilter} to return.
+     * @return A {@link TabModelFilter}. This returns null, if this called before native library is
+     * initialized.
+     */
+    public TabModelFilter getTabModelFilter(boolean isIncognito) {
+        for (int i = 0; i < mTabModelFilterList.size(); i++) {
+            if (mTabModelFilterList.get(i).isIncognito() == isIncognito)
+                return mTabModelFilterList.get(i);
+        }
+        return null;
+    }
+
+    /**
+     * This method returns the current {@link TabModelFilter}.
+     * @return The current {@link TabModelFilter}. This returns null, if this called before native
+     * library is initialized.
+     */
+    public TabModelFilter getCurrentTabModelFilter() {
+        for (int i = 0; i < mTabModelFilterList.size(); i++) {
+            if (mTabModelFilterList.get(i).isCurrentlySelectedFilter())
+                return mTabModelFilterList.get(i);
+        }
+        return null;
+    }
+
+    /**
+     * This method destroys all owned {@link TabModelFilter}.
+     */
+    public void destroy() {
+        for (int i = 0; i < mTabModelFilterList.size(); i++) {
+            mTabModelFilterList.get(i).destroy();
+        }
+    }
+
+    /**
+     * Return a {@link TabModelFilter} based on feature flags.
+     * @param model The {@link TabModel} that the {@link TabModelFilter} acts on.
+     * @return a {@link TabModelFilter}.
+     */
+    private TabModelFilter createTabModelFilter(TabModel model) {
+        // TODO(meiliang): build based on chrome feature.
+        return new EmptyTabModelFilter(model);
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelector.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelector.java
index d77379b..0deb20e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelector.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelector.java
@@ -44,6 +44,12 @@
     TabModel getModel(boolean incognito);
 
     /**
+     * Get the {@link TabModelFilterProvider} that provides {@link TabModelFilter}.
+     * @return  Never returns null. Returns a stub when real model is uninitialized.
+     */
+    TabModelFilterProvider getTabModelFilterProvider();
+
+    /**
      * @return a list for the underlying models
      */
     List<TabModel> getModels();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorBase.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorBase.java
index 7f68ce4..ead8f357 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorBase.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorBase.java
@@ -22,6 +22,13 @@
     private static TabModelSelectorObserver sObserver;
 
     private List<TabModel> mTabModels = Collections.emptyList();
+
+    /**
+     * This is a dummy implementation intended to stub out TabModelFilterProvider before native is
+     * ready.
+     */
+    private TabModelFilterProvider mTabModelFilterProvider = new TabModelFilterProvider();
+
     private int mActiveModelIndex = NORMAL_TAB_MODEL_INDEX;
     private final ObserverList<TabModelSelectorObserver> mObservers =
             new ObserverList<TabModelSelectorObserver>();
@@ -41,6 +48,7 @@
         }
         mActiveModelIndex = startIncognito ? INCOGNITO_TAB_MODEL_INDEX : NORMAL_TAB_MODEL_INDEX;
         mTabModels = Collections.unmodifiableList(tabModels);
+        mTabModelFilterProvider = new TabModelFilterProvider(mTabModels);
 
         TabModelObserver tabModelObserver = new EmptyTabModelObserver() {
             @Override
@@ -133,6 +141,11 @@
     }
 
     @Override
+    public TabModelFilterProvider getTabModelFilterProvider() {
+        return mTabModelFilterProvider;
+    }
+
+    @Override
     public boolean isIncognitoSelected() {
         return mActiveModelIndex == INCOGNITO_TAB_MODEL_INDEX;
     }
@@ -222,6 +235,7 @@
 
     @Override
     public void destroy() {
+        mTabModelFilterProvider.destroy();
         for (int i = 0; i < getModels().size(); i++) getModelAt(i).destroy();
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/document/DocumentTabModelSelector.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/document/DocumentTabModelSelector.java
index e131690..5803520 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/document/DocumentTabModelSelector.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/document/DocumentTabModelSelector.java
@@ -108,6 +108,13 @@
                 //                    Revisit this when we have a Samsung L multi-instance device.
                 return mIncognitoTabModel.getCount() > 0;
             }
+
+            @Override
+            public boolean isCurrentModel(TabModel model) {
+                return DocumentTabModelSelector.this.isCurrentModel(model);
+            }
+
+
         }, mActivityDelegate);
         initializeTabIdCounter();
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/TabCountProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/TabCountProvider.java
index b1043e9..e63a92fd 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/TabCountProvider.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/TabCountProvider.java
@@ -6,12 +6,13 @@
 
 import org.chromium.base.ObserverList;
 import org.chromium.chrome.browser.tab.Tab;
+import org.chromium.chrome.browser.tabmodel.EmptyTabModelObserver;
 import org.chromium.chrome.browser.tabmodel.EmptyTabModelSelectorObserver;
 import org.chromium.chrome.browser.tabmodel.TabLaunchType;
 import org.chromium.chrome.browser.tabmodel.TabModel;
+import org.chromium.chrome.browser.tabmodel.TabModelObserver;
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
 import org.chromium.chrome.browser.tabmodel.TabModelSelectorObserver;
-import org.chromium.chrome.browser.tabmodel.TabModelSelectorTabModelObserver;
 
 import java.util.List;
 
@@ -35,11 +36,8 @@
     /** The {@link TabModelSelectorObserver} that observes when the tab count may have changed. */
     private TabModelSelectorObserver mTabModelSelectorObserver;
 
-    /**
-     *  The {@link TabModelSelectorTabModelObserver} that observes when the tab count may have
-     *  changed.
-     */
-    private TabModelSelectorTabModelObserver mTabModelSelectorTabModelObserver;
+    /** The {@link TabModelObserver} that observes when the tab count may have changed. */
+    private TabModelObserver mTabModelFilterObserver;
 
     private int mTabCount;
 
@@ -65,7 +63,9 @@
         addObserver(observer);
 
         if (mTabModelSelector != null) {
-            observer.onTabCountChanged(mTabModelSelector.getCurrentModel().getCount(),
+            observer.onTabCountChanged(mTabModelSelector.getTabModelFilterProvider()
+                                               .getCurrentTabModelFilter()
+                                               .getCount(),
                     mTabModelSelector.isIncognitoSelected());
         }
     }
@@ -97,39 +97,40 @@
         };
         mTabModelSelector.addObserver(mTabModelSelectorObserver);
 
-        mTabModelSelectorTabModelObserver =
-                new TabModelSelectorTabModelObserver(mTabModelSelector) {
-                    @Override
-                    public void didAddTab(Tab tab, @TabLaunchType int type) {
-                        updateTabCount();
-                    }
+        mTabModelFilterObserver = new EmptyTabModelObserver() {
+            @Override
+            public void didAddTab(Tab tab, @TabLaunchType int type) {
+                updateTabCount();
+            }
 
-                    @Override
-                    public void tabClosureUndone(Tab tab) {
-                        updateTabCount();
-                    }
+            @Override
+            public void tabClosureUndone(Tab tab) {
+                updateTabCount();
+            }
 
-                    @Override
-                    public void didCloseTab(int tabId, boolean incognito) {
-                        updateTabCount();
-                    }
+            @Override
+            public void didCloseTab(int tabId, boolean incognito) {
+                updateTabCount();
+            }
 
-                    @Override
-                    public void tabPendingClosure(Tab tab) {
-                        updateTabCount();
-                    }
+            @Override
+            public void tabPendingClosure(Tab tab) {
+                updateTabCount();
+            }
 
-                    @Override
-                    public void allTabsPendingClosure(List<Tab> tabs) {
-                        updateTabCount();
-                    }
+            @Override
+            public void allTabsPendingClosure(List<Tab> tabs) {
+                updateTabCount();
+            }
 
-                    @Override
-                    public void tabRemoved(Tab tab) {
-                        updateTabCount();
-                    }
-                };
+            @Override
+            public void tabRemoved(Tab tab) {
+                updateTabCount();
+            }
+        };
 
+        mTabModelSelector.getTabModelFilterProvider().addTabModelFilterObserver(
+                mTabModelFilterObserver);
         updateTabCount();
     }
 
@@ -137,19 +138,21 @@
      * Clean up any state when the TabCountProvider is destroyed.
      */
     void destroy() {
+        if (mTabModelFilterObserver != null) {
+            mTabModelSelector.getTabModelFilterProvider().removeTabModelFilterObserver(
+                    mTabModelFilterObserver);
+        }
+
         if (mTabModelSelector != null) {
             mTabModelSelector.removeObserver(mTabModelSelectorObserver);
             mTabModelSelector = null;
         }
-        if (mTabModelSelectorTabModelObserver != null) {
-            mTabModelSelectorTabModelObserver.destroy();
-            mTabModelSelectorTabModelObserver = null;
-        }
         mTabCountObservers.clear();
     }
 
     private void updateTabCount() {
-        final int tabCount = mTabModelSelector.getCurrentModel().getCount();
+        final int tabCount =
+                mTabModelSelector.getTabModelFilterProvider().getCurrentTabModelFilter().getCount();
         final boolean isIncognito = mTabModelSelector.isIncognitoSelected();
 
         if (mTabCount == tabCount && mIsIncognito == isIncognito) return;
diff --git a/chrome/android/java/strings/android_chrome_strings.grd b/chrome/android/java/strings/android_chrome_strings.grd
index dff2fd8..95c2f95 100644
--- a/chrome/android/java/strings/android_chrome_strings.grd
+++ b/chrome/android/java/strings/android_chrome_strings.grd
@@ -1459,6 +1459,18 @@
       <message name="IDS_DOWNLOAD_SETTINGS_ENABLE_PREFETCH_DESCRIPTION" desc="Description for preference that describes that prefetching of articles only happens when connected to Wi-Fi.">
         Download occurs only on Wi-Fi
       </message>
+      <message name="IDS_RENAME" desc="Label for the option to rename items.">
+        Rename
+      </message>
+      <message name="IDS_RENAME_FAILURE_NAME_CONFLICT" desc="Subtitle for rename dialog in the case that rename attempt failed because the target name already exists.">
+       Name already exists
+      </message>
+      <message name="IDS_RENAME_FAILURE_NAME_TOO_LONG" desc="Subtitle for rename dialog in the case that rename attempt failed because the target name is too long.">
+       Name is too long
+      </message>
+      <message name="IDS_RENAME_FAILURE_NAME_UNAVAILABLE" desc="Subtitle for rename dialog in the case that rename attempt failed because the target name is unavailable.">
+       Name is unavailable
+      </message>
 
       <!-- About Chrome preferences -->
       <message name="IDS_PREFS_ABOUT_CHROME" desc="Title for the About Chrome page. [CHAR-LIMIT=32]">
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni
index f02a9b9..deeedc8 100644
--- a/chrome/android/java_sources.gni
+++ b/chrome/android/java_sources.gni
@@ -642,6 +642,8 @@
   "java/src/org/chromium/chrome/browser/download/home/metrics/FilterChangeLogger.java",
   "java/src/org/chromium/chrome/browser/download/home/metrics/OfflineItemStartupLogger.java",
   "java/src/org/chromium/chrome/browser/download/home/metrics/UmaUtils.java",
+  "java/src/org/chromium/chrome/browser/download/home/rename/RenameDialogCoordinator.java",
+  "java/src/org/chromium/chrome/browser/download/home/rename/RenameDialogCustomView.java",
   "java/src/org/chromium/chrome/browser/download/home/snackbars/DeleteUndoCoordinator.java",
   "java/src/org/chromium/chrome/browser/download/home/snackbars/UndoUiUtils.java",
   "java/src/org/chromium/chrome/browser/download/home/storage/StorageCoordinator.java",
@@ -1592,7 +1594,7 @@
   "java/src/org/chromium/chrome/browser/tabmodel/TabModel.java",
   "java/src/org/chromium/chrome/browser/tabmodel/TabModelDelegate.java",
   "java/src/org/chromium/chrome/browser/tabmodel/TabModelFilter.java",
-  "java/src/org/chromium/chrome/browser/tabmodel/TabModelFilterObserver.java",
+  "java/src/org/chromium/chrome/browser/tabmodel/TabModelFilterProvider.java",
   "java/src/org/chromium/chrome/browser/tabmodel/TabModelImpl.java",
   "java/src/org/chromium/chrome/browser/tabmodel/TabModelJniBridge.java",
   "java/src/org/chromium/chrome/browser/tabmodel/TabModelObserver.java",
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelBaseTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelBaseTest.java
index 13ab772..dce691c 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelBaseTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelBaseTest.java
@@ -5,6 +5,7 @@
 package org.chromium.chrome.browser.compositor.bottombar;
 
 import android.content.Context;
+import android.support.annotation.Nullable;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.annotation.UiThreadTest;
 import android.support.test.filters.SmallTest;
@@ -50,7 +51,8 @@
          * Expose protected super method as public.
          */
         @Override
-        public PanelState findNearestPanelStateFromHeight(float desiredHeight, float velocity) {
+        public @PanelState int findNearestPanelStateFromHeight(
+                float desiredHeight, float velocity) {
             return super.findNearestPanelStateFromHeight(desiredHeight, velocity);
         }
 
@@ -58,13 +60,13 @@
          * Override to return arbitrary test heights.
          */
         @Override
-        public float getPanelHeightFromState(PanelState state) {
+        public float getPanelHeightFromState(@Nullable @PanelState Integer state) {
             switch (state) {
-                case PEEKED:
+                case PanelState.PEEKED:
                     return MOCK_PEEKED_HEIGHT;
-                case EXPANDED:
+                case PanelState.EXPANDED:
                     return MOCK_EXPANDED_HEIGHT;
-                case MAXIMIZED:
+                case PanelState.MAXIMIZED:
                     return MOCK_MAXIMIZED_HEIGHT;
                 default:
                     return 0.0f;
@@ -87,7 +89,7 @@
         }
 
         @Override
-        protected boolean isSupportedState(PanelState state) {
+        protected boolean isSupportedState(@PanelState int state) {
             return state != PanelState.EXPANDED;
         }
     }
@@ -118,8 +120,9 @@
         final float maxToPeekBound = (1.0f - threshold) * height + MOCK_PEEKED_HEIGHT;
 
         // Between PEEKING and MAXIMIZED past the threshold in the up direction.
-        PanelState nextState = mNoExpandPanel.findNearestPanelStateFromHeight(
-                peekToMaxBound + 1, UPWARD_VELOCITY);
+        @PanelState
+        int nextState =
+                mNoExpandPanel.findNearestPanelStateFromHeight(peekToMaxBound + 1, UPWARD_VELOCITY);
         Assert.assertTrue(nextState == PanelState.MAXIMIZED);
 
         // Between PEEKING and MAXIMIZED before the threshold in the up direction.
@@ -164,8 +167,9 @@
         final float maxToExpBound = (1.0f - threshold) * expToMaxHeight + MOCK_EXPANDED_HEIGHT;
 
         // Between PEEKING and EXPANDED past the threshold in the up direction.
-        PanelState nextState = mExpandPanel.findNearestPanelStateFromHeight(
-                peekToExpBound + 1, UPWARD_VELOCITY);
+        @PanelState
+        int nextState =
+                mExpandPanel.findNearestPanelStateFromHeight(peekToExpBound + 1, UPWARD_VELOCITY);
         Assert.assertTrue(nextState == PanelState.EXPANDED);
 
         // Between PEEKING and EXPANDED before the threshold in the up direction.
@@ -214,8 +218,8 @@
     public void testNegativeHeightClosesPanel() {
         final float belowPeek = MOCK_PEEKED_HEIGHT - 1000;
 
-        PanelState nextState =
-                mExpandPanel.findNearestPanelStateFromHeight(belowPeek, DOWNWARD_VELOCITY);
+        @PanelState
+        int nextState = mExpandPanel.findNearestPanelStateFromHeight(belowPeek, DOWNWARD_VELOCITY);
         Assert.assertTrue(nextState == PanelState.CLOSED);
 
         nextState = mNoExpandPanel.findNearestPanelStateFromHeight(belowPeek, DOWNWARD_VELOCITY);
@@ -239,8 +243,8 @@
     public void testLargeDesiredHeightIsMaximized() {
         final float aboveMax = MOCK_MAXIMIZED_HEIGHT + 1000;
 
-        PanelState nextState =
-                mExpandPanel.findNearestPanelStateFromHeight(aboveMax, UPWARD_VELOCITY);
+        @PanelState
+        int nextState = mExpandPanel.findNearestPanelStateFromHeight(aboveMax, UPWARD_VELOCITY);
         Assert.assertTrue(nextState == PanelState.MAXIMIZED);
 
         nextState = mNoExpandPanel.findNearestPanelStateFromHeight(aboveMax, UPWARD_VELOCITY);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java
index 10da0b5..0d91730 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManagerTest.java
@@ -697,7 +697,8 @@
         if (mPanel == null) {
             success = true;
         } else {
-            PanelState panelState = mPanel.getPanelState();
+            @PanelState
+            int panelState = mPanel.getPanelState();
             success = panelState == PanelState.CLOSED || panelState == PanelState.UNDEFINED;
         }
         Assert.assertTrue(success);
@@ -818,7 +819,7 @@
      * Waits for the Search Panel to enter the given {@code PanelState} and assert.
      * @param state The {@link PanelState} to wait for.
      */
-    private void waitForPanelToEnterState(final PanelState state) {
+    private void waitForPanelToEnterState(final @PanelState int state) {
         CriteriaHelper.pollUiThread(new Criteria() {
             @Override
             public boolean isSatisfied() {
@@ -842,7 +843,7 @@
      *        should not change the panel state.
      * @throws InterruptedException
      */
-    private void assertPanelStillInState(final PanelState initialState)
+    private void assertPanelStillInState(final @PanelState int initialState)
             throws InterruptedException {
         boolean didChangeState = false;
         long startTime = SystemClock.uptimeMillis();
@@ -1617,7 +1618,8 @@
         CriteriaHelper.pollInstrumentationThread(new Criteria(){
             @Override
             public boolean isSatisfied() {
-                PanelState panelState = mPanel.getPanelState();
+                @PanelState
+                int panelState = mPanel.getPanelState();
                 return panelState != PanelState.PEEKED;
             }
         });
@@ -1716,7 +1718,8 @@
     @SmallTest
     @Feature({"ContextualSearch"})
     public void testTapOnRoleIgnored() throws InterruptedException, TimeoutException {
-        PanelState initialState = mPanel.getPanelState();
+        @PanelState
+        int initialState = mPanel.getPanelState();
         clickNode("role");
         assertPanelStillInState(initialState);
     }
@@ -1729,7 +1732,8 @@
     @SmallTest
     @Feature({"ContextualSearch"})
     public void testTapOnARIAIgnored() throws InterruptedException, TimeoutException {
-        PanelState initialState = mPanel.getPanelState();
+        @PanelState
+        int initialState = mPanel.getPanelState();
         clickNode("aria");
         assertPanelStillInState(initialState);
     }
@@ -1741,7 +1745,8 @@
     @SmallTest
     @Feature({"ContextualSearch"})
     public void testTapOnFocusableIgnored() throws InterruptedException, TimeoutException {
-        PanelState initialState = mPanel.getPanelState();
+        @PanelState
+        int initialState = mPanel.getPanelState();
         clickNode("focusable");
         assertPanelStillInState(initialState);
     }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/download/home/DownloadActivityV2Test.java b/chrome/android/javatests/src/org/chromium/chrome/browser/download/home/DownloadActivityV2Test.java
index f544ea7..84c7e32 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/download/home/DownloadActivityV2Test.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/download/home/DownloadActivityV2Test.java
@@ -35,6 +35,7 @@
 import org.chromium.chrome.test.ui.DummyUiActivityTestCase;
 import org.chromium.components.feature_engagement.Tracker;
 import org.chromium.components.offline_items_collection.OfflineItem;
+import org.chromium.ui.modaldialog.ModalDialogManager;
 import org.chromium.ui.test.util.UiRestriction;
 
 import java.util.HashMap;
@@ -50,6 +51,10 @@
     private Tracker mTracker;
     @Mock
     private SnackbarManager mSnackbarManager;
+    @Mock
+    private ModalDialogManager.Presenter mAppModalPresenter;
+
+    private ModalDialogManager mModalDialogManager;
 
     private DownloadManagerCoordinator mDownloadCoordinator;
 
@@ -98,8 +103,12 @@
                                                  .setUseNewDownloadPath(true)
                                                  .setUseNewDownloadPathThumbnails(true)
                                                  .build();
+
+        mModalDialogManager =
+                new ModalDialogManager(mAppModalPresenter, ModalDialogManager.ModalDialogType.APP);
+
         mDownloadCoordinator = new DownloadManagerCoordinatorImpl(
-                mProfile, getActivity(), config, mSnackbarManager);
+                mProfile, getActivity(), config, mSnackbarManager, mModalDialogManager);
         getActivity().setContentView(mDownloadCoordinator.getView());
 
         mDownloadCoordinator.updateForUrl(UrlConstants.DOWNLOADS_URL);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageAutoFetchTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageAutoFetchTest.java
index 67aec46f..1eb2cfb 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageAutoFetchTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageAutoFetchTest.java
@@ -22,7 +22,6 @@
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.test.util.CallbackHelper;
 import org.chromium.base.test.util.CommandLineFlags;
-import org.chromium.base.test.util.DisabledTest;
 import org.chromium.base.test.util.Feature;
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.ChromeSwitches;
@@ -263,7 +262,6 @@
     @Test
     @MediumTest
     @Feature({"OfflineAutoFetch"})
-    @DisabledTest(message = "Flaky: https://crbug.com/883486#c20")
     public void testAutoFetchRequestRetainedOnOtherTabClosed() throws Exception {
         startWebServer();
         final String testUrl = mWebServer.getBaseUrl();
diff --git a/chrome/android/static_initializers.gni b/chrome/android/static_initializers.gni
index c97f976..48ac0f80 100644
--- a/chrome/android/static_initializers.gni
+++ b/chrome/android/static_initializers.gni
@@ -13,8 +13,8 @@
     (!is_debug && !using_sanitizer && proprietary_codecs)) {
   # Define expectations only for target_cpu covered by trybots.
   if (target_cpu == "arm") {
-    expected_static_initializer_count = 4
+    expected_static_initializer_count = 6
   } else if (target_cpu == "arm64") {
-    expected_static_initializer_count = 3
+    expected_static_initializer_count = 5
   }
 }
diff --git a/chrome/android/trichrome.gni b/chrome/android/trichrome.gni
index 3afc7aa..cf22063a 100644
--- a/chrome/android/trichrome.gni
+++ b/chrome/android/trichrome.gni
@@ -82,9 +82,19 @@
       if (build_apk_secondary_abi) {
         secondary_abi_shared_libraries =
             [ "//chrome/android:monochrome_secondary_abi_lib" ]
+
+        _trampoline = "//third_party/crashpad/crashpad/handler:crashpad_handler_trampoline($android_secondary_abi_toolchain)"
+        deps += [ _trampoline ]
+        _secondary_out_dir = get_label_info(_trampoline, "root_out_dir")
+        secondary_abi_loadable_modules =
+            [ "$_secondary_out_dir/libcrashpad_handler_trampoline.so" ]
       }
     } else {
       shared_libraries = [ "//chrome/android:monochrome" ]
+      deps += [
+        "//third_party/crashpad/crashpad/handler:crashpad_handler_trampoline",
+      ]
+      loadable_modules = [ "$root_out_dir/libcrashpad_handler_trampoline.so" ]
     }
 
     if (!is_java_debug) {
diff --git a/chrome/app/chrome_packaged_service_manifests.cc b/chrome/app/chrome_packaged_service_manifests.cc
index 91da8e9..ebcb8717 100644
--- a/chrome/app/chrome_packaged_service_manifests.cc
+++ b/chrome/app/chrome_packaged_service_manifests.cc
@@ -26,7 +26,7 @@
 #include "ash/components/tap_visualizer/public/cpp/manifest.h"
 #include "ash/public/cpp/manifest.h"
 #include "chrome/browser/chromeos/prefs/ash_pref_connector_manifest.h"
-#include "chrome/services/cups_ipp_parser/public/cpp/manifest.h"
+#include "chrome/services/cups_ipp_parser/public/cpp/manifest.h"  // nogncheck
 #include "chromeos/services/ime/public/cpp/manifest.h"
 #include "chromeos/services/secure_channel/public/cpp/manifest.h"
 #include "services/ws/public/mojom/input_devices/input_device_controller.mojom.h"
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp
index 945a1b6..e5fa4d7 100644
--- a/chrome/app/settings_strings.grdp
+++ b/chrome/app/settings_strings.grdp
@@ -516,10 +516,10 @@
       Linux
     </message>
     <message name="IDS_SETTINGS_CROSTINI_SUBTEXT" desc="Description for the section for enabling and managing Crostini.">
-      Run Linux tools, editors, and IDEs on your Chromebook. &lt;a target="_blank" href="<ph name="URL">$1<ex>https://google.com/</ex></ph>"&gt;Learn more&lt;/a&gt;
+      Run Linux tools, editors, and IDEs on your <ph name="DEVICE_TYPE">$1<ex>Chromebook</ex></ph>. &lt;a target="_blank" href="<ph name="URL">$2<ex>https://google.com/</ex></ph>"&gt;Learn more&lt;/a&gt;
     </message>
     <message name="IDS_SETTINGS_CROSTINI_REMOVE" desc="Label for the row to open a dialog confirming removal of Crostini.">
-      Remove Linux Apps for Chromebook
+      Remove Linux Apps for <ph name="DEVICE_TYPE">$1<ex>Chromebook</ex></ph>
     </message>
     <message name="IDS_SETTINGS_CROSTINI_SHARED_PATHS" desc="Label for managing shared folders in Crostini.">
       Manage shared files &amp; folders
diff --git a/chrome/app/theme/default_100_percent/common/favicon_management.png b/chrome/app/theme/default_100_percent/common/favicon_management.png
new file mode 100644
index 0000000..c0a4ca10
--- /dev/null
+++ b/chrome/app/theme/default_100_percent/common/favicon_management.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/favicon_management.png b/chrome/app/theme/default_200_percent/common/favicon_management.png
new file mode 100644
index 0000000..477ada1
--- /dev/null
+++ b/chrome/app/theme/default_200_percent/common/favicon_management.png
Binary files differ
diff --git a/chrome/app/theme/theme_resources.grd b/chrome/app/theme/theme_resources.grd
index 6da9663b..1119bf6a 100644
--- a/chrome/app/theme/theme_resources.grd
+++ b/chrome/app/theme/theme_resources.grd
@@ -222,6 +222,7 @@
         <structure type="chrome_scaled_image" name="IDR_SECONDARY_USER_SETTINGS" file="cros/secondary_user_settings.png" />
       </if>
       <structure type="chrome_scaled_image" name="IDR_SETTINGS_FAVICON" file="common/favicon_settings.png" />
+      <structure type="chrome_scaled_image" name="IDR_MANAGEMENT_FAVICON" file="common/favicon_management.png" />
       <structure type="chrome_scaled_image" name="IDR_SHOW_PASSWORD_HOVER" file="common/show_password_hover.png" />
       <if expr="chromeos">
         <structure type="chrome_scaled_image" name="IDR_SMB_ICON" file="cros/smb_icon.png" />
diff --git a/chrome/browser/DEPS b/chrome/browser/DEPS
index 10be6a72..ecda0f5 100644
--- a/chrome/browser/DEPS
+++ b/chrome/browser/DEPS
@@ -265,4 +265,8 @@
     # The following is used to build FakeSigninManager instances for testing.
     "+components/signin/core/browser/fake_signin_manager.h",
   ],
+  # To share values of UMA enums between product code and tests.
+  "translate_manager_browsertest.cc": [
+    "+services/network/initiator_lock_compatibility.h",
+  ],
 }
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index cf820e79..250c129 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -2415,14 +2415,6 @@
      FEATURE_VALUE_TYPE(
          offline_pages::kOfflinePagesCTSuppressNotificationsFeature)},
 #endif  // OS_ANDROID
-    {"protect-sync-credential", flag_descriptions::kProtectSyncCredentialName,
-     flag_descriptions::kProtectSyncCredentialDescription, kOsAll,
-     FEATURE_VALUE_TYPE(password_manager::features::kProtectSyncCredential)},
-    {"ProtectSyncCredentialOnReauth",
-     flag_descriptions::kProtectSyncCredentialOnReauthName,
-     flag_descriptions::kProtectSyncCredentialOnReauthDescription, kOsAll,
-     FEATURE_VALUE_TYPE(
-         password_manager::features::kProtectSyncCredentialOnReauth)},
     {"PasswordImport", flag_descriptions::kPasswordImportName,
      flag_descriptions::kPasswordImportDescription, kOsAll,
      FEATURE_VALUE_TYPE(password_manager::features::kPasswordImport)},
diff --git a/chrome/browser/accessibility/accessibility_labels_service.cc b/chrome/browser/accessibility/accessibility_labels_service.cc
index 9db9276..e3734fa 100644
--- a/chrome/browser/accessibility/accessibility_labels_service.cc
+++ b/chrome/browser/accessibility/accessibility_labels_service.cc
@@ -7,6 +7,7 @@
 #include "base/command_line.h"
 #include "base/metrics/histogram_functions.h"
 #include "build/build_config.h"
+#include "chrome/browser/accessibility/accessibility_state_utils.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_finder.h"
@@ -58,7 +59,8 @@
 
   // Hidden behind a feature flag.
   base::CommandLine& cmd = *base::CommandLine::ForCurrentProcess();
-  if (cmd.HasSwitch(::switches::kEnableExperimentalAccessibilityLabels)) {
+  if (cmd.HasSwitch(::switches::kEnableExperimentalAccessibilityLabels) &&
+      accessibility_state_utils::IsScreenReaderEnabled()) {
     bool enabled = profile_->GetPrefs()->GetBoolean(
         prefs::kAccessibilityImageLabelsEnabled);
     ax_mode.set_mode(ui::AXMode::kLabelImages, enabled);
@@ -68,6 +70,10 @@
 }
 
 void AccessibilityLabelsService::EnableLabelsServiceOnce() {
+  if (!accessibility_state_utils::IsScreenReaderEnabled()) {
+    return;
+  }
+
   // TODO(crbug.com/905419): Implement for Android, which does not support
   // BrowserList::GetInstance.
 #if !defined(OS_ANDROID)
@@ -90,8 +96,9 @@
   // TODO(dmazzoni) Implement for Android, which doesn't support
   // AllTabContentses(). crbug.com/905419
 #if !defined(OS_ANDROID)
-  bool enabled =
-      profile_->GetPrefs()->GetBoolean(prefs::kAccessibilityImageLabelsEnabled);
+  bool enabled = profile_->GetPrefs()->GetBoolean(
+                     prefs::kAccessibilityImageLabelsEnabled) &&
+                 accessibility_state_utils::IsScreenReaderEnabled();
 
   for (auto* web_contents : AllTabContentses()) {
     if (web_contents->GetBrowserContext() != profile_)
diff --git a/chrome/browser/accessibility/accessibility_labels_service_browsertest.cc b/chrome/browser/accessibility/accessibility_labels_service_browsertest.cc
index 6abf7cb0..b1a696f 100644
--- a/chrome/browser/accessibility/accessibility_labels_service_browsertest.cc
+++ b/chrome/browser/accessibility/accessibility_labels_service_browsertest.cc
@@ -13,6 +13,11 @@
 #include "components/prefs/pref_service.h"
 #include "content/public/browser/browser_accessibility_state.h"
 #include "ui/accessibility/accessibility_switches.h"
+#if defined(OS_CHROMEOS)
+#include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
+#else
+#include "content/public/browser/browser_accessibility_state.h"
+#endif  // defined(OS_CHROMEOS)
 
 class AccessibilityLabelsBrowserTest : public InProcessBrowserTest {
  public:
@@ -24,11 +29,30 @@
     command_line->AppendSwitch(
         switches::kEnableExperimentalAccessibilityLabels);
   }
+
+  void TearDownOnMainThread() override { EnableScreenReader(false); }
+
+  void EnableScreenReader(bool enabled) {
+#if defined(OS_CHROMEOS)
+    // Enable Chromevox.
+    chromeos::AccessibilityManager::Get()->EnableSpokenFeedback(enabled);
+#else
+    // Spoof a screen reader.
+    if (enabled) {
+      content::BrowserAccessibilityState::GetInstance()
+          ->AddAccessibilityModeFlags(ui::AXMode::kScreenReader);
+    } else {
+      content::BrowserAccessibilityState::GetInstance()
+          ->RemoveAccessibilityModeFlags(ui::AXMode::kScreenReader);
+    }
+#endif  // defined(OS_CHROMEOS)
+  }
 };
 
 // Changing the kAccessibilityImageLabelsEnabled pref should affect the
 // accessibility mode of a new WebContents for this profile.
 IN_PROC_BROWSER_TEST_F(AccessibilityLabelsBrowserTest, NewWebContents) {
+  EnableScreenReader(true);
   ui::AXMode ax_mode =
       content::BrowserAccessibilityState::GetInstance()->GetAccessibilityMode();
   EXPECT_FALSE(ax_mode.has_mode(ui::AXMode::kLabelImages));
@@ -59,6 +83,7 @@
 // Changing the kAccessibilityImageLabelsEnabled pref should affect the
 // accessibility mode of existing WebContents in this profile.
 IN_PROC_BROWSER_TEST_F(AccessibilityLabelsBrowserTest, ExistingWebContents) {
+  EnableScreenReader(true);
   content::WebContents* web_contents =
       browser()->tab_strip_model()->GetActiveWebContents();
   ui::AXMode ax_mode = web_contents->GetAccessibilityMode();
@@ -76,3 +101,22 @@
   ax_mode = web_contents->GetAccessibilityMode();
   EXPECT_FALSE(ax_mode.has_mode(ui::AXMode::kLabelImages));
 }
+
+IN_PROC_BROWSER_TEST_F(AccessibilityLabelsBrowserTest,
+                       NotEnabledWithoutScreenReader) {
+  EnableScreenReader(false);
+  content::WebContents* web_contents =
+      browser()->tab_strip_model()->GetActiveWebContents();
+  ui::AXMode ax_mode = web_contents->GetAccessibilityMode();
+  EXPECT_FALSE(ax_mode.has_mode(ui::AXMode::kLabelImages));
+
+  browser()->profile()->GetPrefs()->SetBoolean(
+      prefs::kAccessibilityImageLabelsEnabled, true);
+
+  ax_mode = web_contents->GetAccessibilityMode();
+  EXPECT_FALSE(ax_mode.has_mode(ui::AXMode::kLabelImages));
+
+  // Reset state.
+  browser()->profile()->GetPrefs()->SetBoolean(
+      prefs::kAccessibilityImageLabelsEnabled, false);
+}
diff --git a/chrome/browser/android/chrome_feature_list.cc b/chrome/browser/android/chrome_feature_list.cc
index f889321e..62f22196 100644
--- a/chrome/browser/android/chrome_feature_list.cc
+++ b/chrome/browser/android/chrome_feature_list.cc
@@ -377,7 +377,7 @@
 
 const base::Feature kIntentBlockExternalFormRedirectsNoGesture{
     "IntentBlockExternalFormRedirectsNoGesture",
-    base::FEATURE_ENABLED_BY_DEFAULT};
+    base::FEATURE_DISABLED_BY_DEFAULT};
 
 const base::Feature kJellyBeanSupported{"JellyBeanSupported",
                                         base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/chrome/browser/apps/guest_view/web_view_browsertest.cc b/chrome/browser/apps/guest_view/web_view_browsertest.cc
index e71944a..106f889 100644
--- a/chrome/browser/apps/guest_view/web_view_browsertest.cc
+++ b/chrome/browser/apps/guest_view/web_view_browsertest.cc
@@ -3361,7 +3361,8 @@
   TestHelper("testPerOriginZoomMode", "web_view/shim", NO_TEST_SERVER);
 }
 
-IN_PROC_BROWSER_TEST_F(WebViewTest, Shim_TestPerViewZoomMode) {
+// TODO(crbug.com/935665): Test has flaky failures on all platforms.
+IN_PROC_BROWSER_TEST_F(WebViewTest, DISABLED_Shim_TestPerViewZoomMode) {
   TestHelper("testPerViewZoomMode", "web_view/shim", NO_TEST_SERVER);
 }
 
diff --git a/chrome/browser/banners/app_banner_manager.cc b/chrome/browser/banners/app_banner_manager.cc
index 5a8d74d9..92d33b6 100644
--- a/chrome/browser/banners/app_banner_manager.cc
+++ b/chrome/browser/banners/app_banner_manager.cc
@@ -602,6 +602,13 @@
   return manager->GetAppName();
 }
 
+// static
+bool AppBannerManager::IsWebContentsInstallable(
+    content::WebContents* web_contents) {
+  AppBannerManager* manager = FromWebContents(web_contents);
+  return manager && manager->installable_ == Installable::INSTALLABLE_YES;
+}
+
 void AppBannerManager::RecordCouldShowBanner() {
   content::WebContents* contents = web_contents();
   DCHECK(contents);
diff --git a/chrome/browser/banners/app_banner_manager.h b/chrome/browser/banners/app_banner_manager.h
index aa4ed56..9efc40e 100644
--- a/chrome/browser/banners/app_banner_manager.h
+++ b/chrome/browser/banners/app_banner_manager.h
@@ -116,11 +116,19 @@
   // Returns whether the new experimental flow and UI is enabled.
   static bool IsExperimentalAppBannersEnabled();
 
+  // TODO(https://crbug.com/930612): Move |GetInstallableAppName| and
+  // |IsWebContentsInstallable| out into a more general purpose installability
+  // check class.
+
   // Returns the app name if the current page is installable, otherwise returns
   // the empty string.
   static base::string16 GetInstallableAppName(
       content::WebContents* web_contents);
 
+  // Returns whether the |web_contents| has passed installability checks (e.g.
+  // having a service worker fetch event).
+  static bool IsWebContentsInstallable(content::WebContents* web_contents);
+
   // Requests an app banner. If |is_debug_mode| is true, any failure in the
   // pipeline will be reported to the devtools console.
   virtual void RequestAppBanner(const GURL& validated_url, bool is_debug_mode);
diff --git a/chrome/browser/banners/test_app_banner_manager_desktop.cc b/chrome/browser/banners/test_app_banner_manager_desktop.cc
new file mode 100644
index 0000000..e2b6042
--- /dev/null
+++ b/chrome/browser/banners/test_app_banner_manager_desktop.cc
@@ -0,0 +1,67 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/banners/test_app_banner_manager_desktop.h"
+
+#include <memory>
+#include <utility>
+
+#include "base/run_loop.h"
+#include "chrome/browser/installable/installable_logging.h"
+#include "content/public/browser/web_contents.h"
+
+namespace banners {
+
+TestAppBannerManagerDesktop::TestAppBannerManagerDesktop(
+    content::WebContents* web_contents)
+    : AppBannerManagerDesktop(web_contents) {}
+
+TestAppBannerManagerDesktop::~TestAppBannerManagerDesktop() = default;
+
+TestAppBannerManagerDesktop* TestAppBannerManagerDesktop::CreateForWebContents(
+    content::WebContents* web_contents) {
+  auto banner_manager =
+      std::make_unique<TestAppBannerManagerDesktop>(web_contents);
+  TestAppBannerManagerDesktop* result = banner_manager.get();
+  web_contents->SetUserData(UserDataKey(), std::move(banner_manager));
+  return result;
+}
+
+bool TestAppBannerManagerDesktop::WaitForInstallableCheck() {
+  DCHECK(IsExperimentalAppBannersEnabled());
+
+  if (!installable_.has_value()) {
+    base::RunLoop run_loop;
+    quit_closure_ = run_loop.QuitClosure();
+    run_loop.Run();
+  }
+  bool installable = *installable_;
+  installable_.reset();
+  return installable;
+}
+
+void TestAppBannerManagerDesktop::OnDidGetManifest(
+    const InstallableData& result) {
+  AppBannerManagerDesktop::OnDidGetManifest(result);
+
+  // AppBannerManagerDesktop does not call |OnDidPerformInstallableCheck| to
+  // complete the installability check in this case, instead it early exits
+  // with failure.
+  if (result.error_code != NO_ERROR_DETECTED)
+    SetInstallable(false);
+}
+void TestAppBannerManagerDesktop::OnDidPerformInstallableCheck(
+    const InstallableData& result) {
+  AppBannerManagerDesktop::OnDidPerformInstallableCheck(result);
+  SetInstallable(result.error_code == NO_ERROR_DETECTED);
+}
+
+void TestAppBannerManagerDesktop::SetInstallable(bool installable) {
+  DCHECK(!installable_.has_value());
+  installable_ = installable;
+  if (quit_closure_)
+    std::move(quit_closure_).Run();
+}
+
+}  // namespace banners
diff --git a/chrome/browser/banners/test_app_banner_manager_desktop.h b/chrome/browser/banners/test_app_banner_manager_desktop.h
new file mode 100644
index 0000000..a17bc43
--- /dev/null
+++ b/chrome/browser/banners/test_app_banner_manager_desktop.h
@@ -0,0 +1,47 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_BANNERS_TEST_APP_BANNER_MANAGER_DESKTOP_H_
+#define CHROME_BROWSER_BANNERS_TEST_APP_BANNER_MANAGER_DESKTOP_H_
+
+#include "chrome/browser/banners/app_banner_manager_desktop.h"
+
+#include "base/macros.h"
+#include "base/optional.h"
+
+namespace content {
+class WebContents;
+}
+
+namespace banners {
+
+// Provides the ability to await the results of the installability check that
+// happens for every page load.
+class TestAppBannerManagerDesktop : public AppBannerManagerDesktop {
+ public:
+  explicit TestAppBannerManagerDesktop(content::WebContents* web_contents);
+  ~TestAppBannerManagerDesktop() override;
+
+  static TestAppBannerManagerDesktop* CreateForWebContents(
+      content::WebContents* web_contents);
+
+  // Returns whether the installable check passed.
+  bool WaitForInstallableCheck();
+
+  // AppBannerManager:
+  void OnDidGetManifest(const InstallableData& result) override;
+  void OnDidPerformInstallableCheck(const InstallableData& result) override;
+
+ private:
+  void SetInstallable(bool installable);
+
+  base::Optional<bool> installable_;
+  base::OnceClosure quit_closure_;
+
+  DISALLOW_COPY_AND_ASSIGN(TestAppBannerManagerDesktop);
+};
+
+}  // namespace banners
+
+#endif  // CHROME_BROWSER_BANNERS_TEST_APP_BANNER_MANAGER_DESKTOP_H_
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn
index 6d352aea..39ca3c3 100644
--- a/chrome/browser/chromeos/BUILD.gn
+++ b/chrome/browser/chromeos/BUILD.gn
@@ -508,8 +508,8 @@
     "arc/input_method_manager/input_connection_impl.h",
     "arc/intent_helper/arc_external_protocol_dialog.cc",
     "arc/intent_helper/arc_external_protocol_dialog.h",
-    "arc/intent_helper/arc_navigation_throttle.cc",
-    "arc/intent_helper/arc_navigation_throttle.h",
+    "arc/intent_helper/arc_intent_picker_app_fetcher.cc",
+    "arc/intent_helper/arc_intent_picker_app_fetcher.h",
     "arc/intent_helper/arc_settings_service.cc",
     "arc/intent_helper/arc_settings_service.h",
     "arc/intent_helper/intent_picker_controller.cc",
@@ -2107,9 +2107,8 @@
     "login/screens/mock_update_screen.h",
     "login/screens/mock_welcome_screen.cc",
     "login/screens/mock_welcome_screen.h",
+    "login/test/test_condition_waiter.cc",
     "login/test/test_condition_waiter.h",
-    "login/test/test_predicate_waiter.cc",
-    "login/test/test_predicate_waiter.h",
     "scoped_set_running_on_chromeos_for_testing.cc",
     "scoped_set_running_on_chromeos_for_testing.h",
     "settings/scoped_testing_cros_settings.cc",
@@ -2197,7 +2196,7 @@
     "arc/input_method_manager/test_input_method_manager_bridge.cc",
     "arc/input_method_manager/test_input_method_manager_bridge.h",
     "arc/intent_helper/arc_external_protocol_dialog_unittest.cc",
-    "arc/intent_helper/arc_navigation_throttle_unittest.cc",
+    "arc/intent_helper/arc_intent_picker_app_fetcher_unittest.cc",
     "arc/intent_helper/arc_settings_service_unittest.cc",
     "arc/intent_helper/open_with_menu_unittest.cc",
     "arc/kiosk/arc_kiosk_bridge_unittest.cc",
diff --git a/chrome/browser/chromeos/accessibility/spoken_feedback_browsertest.cc b/chrome/browser/chromeos/accessibility/spoken_feedback_browsertest.cc
index 6dfdfd9..6111c088 100644
--- a/chrome/browser/chromeos/accessibility/spoken_feedback_browsertest.cc
+++ b/chrome/browser/chromeos/accessibility/spoken_feedback_browsertest.cc
@@ -22,6 +22,7 @@
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
 #include "chrome/browser/chromeos/login/login_manager_test.h"
+#include "chrome/browser/chromeos/login/test/js_checker.h"
 #include "chrome/browser/chromeos/login/ui/login_display_host.h"
 #include "chrome/browser/chromeos/login/ui/webui_login_view.h"
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
diff --git a/chrome/browser/chromeos/apps/intent_helper/apps_navigation_throttle.cc b/chrome/browser/chromeos/apps/intent_helper/apps_navigation_throttle.cc
index f47df597..f968bce6 100644
--- a/chrome/browser/chromeos/apps/intent_helper/apps_navigation_throttle.cc
+++ b/chrome/browser/chromeos/apps/intent_helper/apps_navigation_throttle.cc
@@ -16,7 +16,7 @@
 #include "chrome/browser/chromeos/apps/intent_helper/page_transition_util.h"
 #include "chrome/browser/chromeos/arc/arc_util.h"
 #include "chrome/browser/chromeos/arc/arc_web_contents_data.h"
-#include "chrome/browser/chromeos/arc/intent_helper/arc_navigation_throttle.h"
+#include "chrome/browser/chromeos/arc/intent_helper/arc_intent_picker_app_fetcher.h"
 #include "chrome/browser/extensions/extension_util.h"
 #include "chrome/browser/extensions/menu_manager.h"
 #include "chrome/browser/prerender/prerender_contents.h"
@@ -168,7 +168,7 @@
     content::WebContents* web_contents,
     IntentPickerAutoDisplayService* ui_auto_display_service,
     const GURL& url) {
-  arc::ArcNavigationThrottle::GetArcAppsForPicker(
+  arc::ArcIntentPickerAppFetcher::GetArcAppsForPicker(
       web_contents, url,
       base::BindOnce(
           &AppsNavigationThrottle::FindPwaForUrlAndShowIntentPickerForApps,
@@ -199,7 +199,7 @@
       }
       break;
     case apps::mojom::AppType::kArc:
-      if (arc::ArcNavigationThrottle::MaybeLaunchOrPersistArcApp(
+      if (arc::ArcIntentPickerAppFetcher::MaybeLaunchOrPersistArcApp(
               url, launch_name, should_launch_app, should_persist)) {
         CloseOrGoBack(web_contents);
       } else {
@@ -212,7 +212,7 @@
       // since chrome browser is neither a PWA or ARC app.
       if (close_reason == chromeos::IntentPickerCloseReason::STAY_IN_CHROME &&
           should_persist) {
-        arc::ArcNavigationThrottle::MaybeLaunchOrPersistArcApp(
+        arc::ArcIntentPickerAppFetcher::MaybeLaunchOrPersistArcApp(
             url, launch_name, /*should_launch_app=*/false,
             /*should_persist=*/true);
       }
@@ -535,15 +535,16 @@
     return content::NavigationThrottle::PROCEED;
 
   if (arc_enabled_ &&
-      arc::ArcNavigationThrottle::WillGetArcAppsForNavigation(
+      arc::ArcIntentPickerAppFetcher::WillGetArcAppsForNavigation(
           handle,
           base::BindOnce(&AppsNavigationThrottle::OnDeferredNavigationProcessed,
                          weak_factory_.GetWeakPtr()))) {
-    // Handling is now deferred to ArcNavigationThrottle, which asynchronously
-    // queries ARC for apps, and runs OnDeferredNavigationProcessed() with an
-    // action based on whether an acceptable app was found and user consent to
-    // open received. We assume the UI is shown or a preferred app was found;
-    // reset to false if we resume the navigation.
+    // Handling is now deferred to ArcIntentPickerAppFetcher, which
+    // asynchronously queries ARC for apps, and runs
+    // OnDeferredNavigationProcessed() with an action based on whether an
+    // acceptable app was found and user consent to open received. We assume the
+    // UI is shown or a preferred app was found; reset to false if we resume the
+    // navigation.
     ui_displayed_ = true;
     return content::NavigationThrottle::DEFER;
   }
diff --git a/chrome/browser/chromeos/arc/accessibility/arc_accessibility_helper_bridge_unittest.cc b/chrome/browser/chromeos/arc/accessibility/arc_accessibility_helper_bridge_unittest.cc
index b042e9b..a2733e5 100644
--- a/chrome/browser/chromeos/arc/accessibility/arc_accessibility_helper_bridge_unittest.cc
+++ b/chrome/browser/chromeos/arc/accessibility/arc_accessibility_helper_bridge_unittest.cc
@@ -79,11 +79,11 @@
    public:
     void AddObserver(Observer* observer) override {
       observers_.AddObserver(observer);
-    };
+    }
 
     void RemoveObserver(Observer* observer) override {
       observers_.RemoveObserver(observer);
-    };
+    }
 
     ArcNotificationSurface* GetArcSurface(
         const std::string& notification_key) const override {
diff --git a/chrome/browser/chromeos/arc/intent_helper/arc_external_protocol_dialog.cc b/chrome/browser/chromeos/arc/intent_helper/arc_external_protocol_dialog.cc
index 6d78f9ca..ce9d4e5ca 100644
--- a/chrome/browser/chromeos/arc/intent_helper/arc_external_protocol_dialog.cc
+++ b/chrome/browser/chromeos/arc/intent_helper/arc_external_protocol_dialog.cc
@@ -13,7 +13,7 @@
 #include "chrome/browser/chromeos/apps/intent_helper/apps_navigation_types.h"
 #include "chrome/browser/chromeos/apps/intent_helper/page_transition_util.h"
 #include "chrome/browser/chromeos/arc/arc_web_contents_data.h"
-#include "chrome/browser/chromeos/arc/intent_helper/arc_navigation_throttle.h"
+#include "chrome/browser/chromeos/arc/intent_helper/arc_intent_picker_app_fetcher.h"
 #include "chrome/browser/chromeos/external_protocol_dialog.h"
 #include "chrome/browser/tab_contents/tab_util.h"
 #include "chrome/browser/ui/browser.h"
@@ -377,7 +377,7 @@
   // If the user selected an app to continue the navigation, confirm that the
   // |package_name| matches a valid option and return the index.
   const size_t selected_app_index =
-      ArcNavigationThrottle::GetAppIndex(handlers, selected_app_package);
+      ArcIntentPickerAppFetcher::GetAppIndex(handlers, selected_app_package);
 
   // Make sure that the instance at least supports HandleUrl.
   auto* arc_service_manager = ArcServiceManager::Get();
diff --git a/chrome/browser/chromeos/arc/intent_helper/arc_navigation_throttle.cc b/chrome/browser/chromeos/arc/intent_helper/arc_intent_picker_app_fetcher.cc
similarity index 83%
rename from chrome/browser/chromeos/arc/intent_helper/arc_navigation_throttle.cc
rename to chrome/browser/chromeos/arc/intent_helper/arc_intent_picker_app_fetcher.cc
index ced1e8d7..d80536ad 100644
--- a/chrome/browser/chromeos/arc/intent_helper/arc_navigation_throttle.cc
+++ b/chrome/browser/chromeos/arc/intent_helper/arc_intent_picker_app_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 "chrome/browser/chromeos/arc/intent_helper/arc_navigation_throttle.h"
+#include "chrome/browser/chromeos/arc/intent_helper/arc_intent_picker_app_fetcher.h"
 
 #include <utility>
 
@@ -49,7 +49,7 @@
 }  // namespace
 
 // static
-void ArcNavigationThrottle::GetArcAppsForPicker(
+void ArcIntentPickerAppFetcher::GetArcAppsForPicker(
     content::WebContents* web_contents,
     const GURL& url,
     chromeos::GetAppsCallback callback) {
@@ -69,13 +69,14 @@
     return;
   }
 
-  // |throttle| will delete itself when it is finished.
-  ArcNavigationThrottle* throttle = new ArcNavigationThrottle(web_contents);
-  throttle->GetArcAppsForPicker(instance, url, std::move(callback));
+  // |app_fetcher| will delete itself when it is finished.
+  ArcIntentPickerAppFetcher* app_fetcher =
+      new ArcIntentPickerAppFetcher(web_contents);
+  app_fetcher->GetArcAppsForPicker(instance, url, std::move(callback));
 }
 
 // static
-bool ArcNavigationThrottle::WillGetArcAppsForNavigation(
+bool ArcIntentPickerAppFetcher::WillGetArcAppsForNavigation(
     content::NavigationHandle* handle,
     chromeos::AppsNavigationCallback callback) {
   ArcServiceManager* arc_service_manager = ArcServiceManager::Get();
@@ -101,8 +102,9 @@
   if (!instance)
     return false;
 
-  // |throttle| will delete itself when it is finished.
-  ArcNavigationThrottle* throttle = new ArcNavigationThrottle(web_contents);
+  // |app_fetcher| will delete itself when it is finished.
+  ArcIntentPickerAppFetcher* app_fetcher =
+      new ArcIntentPickerAppFetcher(web_contents);
 
   // Return true to defer the navigation until we asynchronously hear back from
   // ARC whether a preferred app should be launched. This makes it safe to bind
@@ -111,12 +113,12 @@
   // prior to this asynchronous method finishing, it is safe to not run
   // |callback| since it will not matter what we do with the deferred navigation
   // for a now-closed tab.
-  throttle->GetArcAppsForNavigation(instance, url, std::move(callback));
+  app_fetcher->GetArcAppsForNavigation(instance, url, std::move(callback));
   return true;
 }
 
 // static
-bool ArcNavigationThrottle::MaybeLaunchOrPersistArcApp(
+bool ArcIntentPickerAppFetcher::MaybeLaunchOrPersistArcApp(
     const GURL& url,
     const std::string& package_name,
     bool should_launch,
@@ -151,7 +153,7 @@
 }
 
 // static
-size_t ArcNavigationThrottle::GetAppIndex(
+size_t ArcIntentPickerAppFetcher::GetAppIndex(
     const std::vector<mojom::IntentHandlerInfoPtr>& app_candidates,
     const std::string& selected_app_package) {
   for (size_t i = 0; i < app_candidates.size(); ++i) {
@@ -162,7 +164,7 @@
 }
 
 // static
-bool ArcNavigationThrottle::IsAppAvailable(
+bool ArcIntentPickerAppFetcher::IsAppAvailable(
     const std::vector<mojom::IntentHandlerInfoPtr>& app_candidates) {
   return app_candidates.size() > 1 ||
          (app_candidates.size() == 1 &&
@@ -171,23 +173,24 @@
 }
 
 // static
-bool ArcNavigationThrottle::IsAppAvailableForTesting(
+bool ArcIntentPickerAppFetcher::IsAppAvailableForTesting(
     const std::vector<mojom::IntentHandlerInfoPtr>& app_candidates) {
   return IsAppAvailable(app_candidates);
 }
 
 // static
-size_t ArcNavigationThrottle::FindPreferredAppForTesting(
+size_t ArcIntentPickerAppFetcher::FindPreferredAppForTesting(
     const std::vector<mojom::IntentHandlerInfoPtr>& app_candidates) {
   return FindPreferredApp(app_candidates, GURL());
 }
 
-ArcNavigationThrottle::~ArcNavigationThrottle() = default;
+ArcIntentPickerAppFetcher::~ArcIntentPickerAppFetcher() = default;
 
-ArcNavigationThrottle::ArcNavigationThrottle(content::WebContents* web_contents)
+ArcIntentPickerAppFetcher::ArcIntentPickerAppFetcher(
+    content::WebContents* web_contents)
     : content::WebContentsObserver(web_contents), weak_ptr_factory_(this) {}
 
-void ArcNavigationThrottle::GetArcAppsForNavigation(
+void ArcIntentPickerAppFetcher::GetArcAppsForNavigation(
     mojom::IntentHelperInstance* instance,
     const GURL& url,
     chromeos::AppsNavigationCallback callback) {
@@ -196,11 +199,11 @@
   instance->RequestUrlHandlerList(
       url.spec(),
       base::BindOnce(
-          &ArcNavigationThrottle::OnAppCandidatesReceivedForNavigation,
+          &ArcIntentPickerAppFetcher::OnAppCandidatesReceivedForNavigation,
           weak_ptr_factory_.GetWeakPtr(), url, std::move(callback)));
 }
 
-void ArcNavigationThrottle::GetArcAppsForPicker(
+void ArcIntentPickerAppFetcher::GetArcAppsForPicker(
     mojom::IntentHelperInstance* instance,
     const GURL& url,
     chromeos::GetAppsCallback callback) {
@@ -208,20 +211,21 @@
 
   instance->RequestUrlHandlerList(
       url.spec(),
-      base::BindOnce(&ArcNavigationThrottle::OnAppCandidatesReceivedForPicker,
-                     weak_ptr_factory_.GetWeakPtr(), url, std::move(callback)));
+      base::BindOnce(
+          &ArcIntentPickerAppFetcher::OnAppCandidatesReceivedForPicker,
+          weak_ptr_factory_.GetWeakPtr(), url, std::move(callback)));
 }
 
-void ArcNavigationThrottle::OnAppCandidatesReceivedForNavigation(
+void ArcIntentPickerAppFetcher::OnAppCandidatesReceivedForNavigation(
     const GURL& url,
     chromeos::AppsNavigationCallback callback,
     std::vector<mojom::IntentHandlerInfoPtr> app_candidates) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
-  std::unique_ptr<ArcNavigationThrottle> deleter(this);
+  std::unique_ptr<ArcIntentPickerAppFetcher> deleter(this);
   if (!IsAppAvailable(app_candidates)) {
-    // This scenario shouldn't be accessed as ArcNavigationThrottle is created
-    // iff there are ARC apps which can actually handle the given URL.
+    // This scenario shouldn't be accessed as ArcIntentPickerAppFetcher is
+    // created iff there are ARC apps which can actually handle the given URL.
     DVLOG(1) << "There are no app candidates for this URL: " << url;
     chromeos::AppsNavigationThrottle::RecordUma(
         std::string(), apps::mojom::AppType::kUnknown,
@@ -257,13 +261,13 @@
                                 chromeos::AppsNavigationAction::RESUME));
 }
 
-void ArcNavigationThrottle::OnAppCandidatesReceivedForPicker(
+void ArcIntentPickerAppFetcher::OnAppCandidatesReceivedForPicker(
     const GURL& url,
     chromeos::GetAppsCallback callback,
     std::vector<arc::mojom::IntentHandlerInfoPtr> app_candidates) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
-  std::unique_ptr<ArcNavigationThrottle> deleter(this);
+  std::unique_ptr<ArcIntentPickerAppFetcher> deleter(this);
   if (!IsAppAvailable(app_candidates)) {
     DVLOG(1) << "There are no app candidates for this URL";
     std::move(callback).Run({});
@@ -274,7 +278,7 @@
   GetArcAppIcons(url, std::move(app_candidates), std::move(callback));
 }
 
-chromeos::PreferredPlatform ArcNavigationThrottle::DidLaunchPreferredArcApp(
+chromeos::PreferredPlatform ArcIntentPickerAppFetcher::DidLaunchPreferredArcApp(
     const GURL& url,
     const std::vector<mojom::IntentHandlerInfoPtr>& app_candidates) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
@@ -316,11 +320,11 @@
   return preferred_platform;
 }
 
-void ArcNavigationThrottle::GetArcAppIcons(
+void ArcIntentPickerAppFetcher::GetArcAppIcons(
     const GURL& url,
     std::vector<mojom::IntentHandlerInfoPtr> app_candidates,
     chromeos::GetAppsCallback callback) {
-  std::unique_ptr<ArcNavigationThrottle> deleter(this);
+  std::unique_ptr<ArcIntentPickerAppFetcher> deleter(this);
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
   auto* intent_helper_bridge = ArcIntentHelperBridge::GetForBrowserContext(
@@ -340,19 +344,19 @@
   deleter.release();
   intent_helper_bridge->GetActivityIcons(
       activities,
-      base::BindOnce(&ArcNavigationThrottle::OnAppIconsReceived,
+      base::BindOnce(&ArcIntentPickerAppFetcher::OnAppIconsReceived,
                      weak_ptr_factory_.GetWeakPtr(), url,
                      std::move(app_candidates), std::move(callback)));
 }
 
-void ArcNavigationThrottle::OnAppIconsReceived(
+void ArcIntentPickerAppFetcher::OnAppIconsReceived(
     const GURL& url,
     std::vector<arc::mojom::IntentHandlerInfoPtr> app_candidates,
     chromeos::GetAppsCallback callback,
     std::unique_ptr<arc::ArcIntentHelperBridge::ActivityToIconsMap> icons) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
-  std::unique_ptr<ArcNavigationThrottle> deleter(this);
+  std::unique_ptr<ArcIntentPickerAppFetcher> deleter(this);
   std::vector<chromeos::IntentPickerAppInfo> app_info;
 
   for (const auto& candidate : app_candidates) {
@@ -371,7 +375,7 @@
   std::move(callback).Run(std::move(app_info));
 }
 
-void ArcNavigationThrottle::WebContentsDestroyed() {
+void ArcIntentPickerAppFetcher::WebContentsDestroyed() {
   delete this;
 }
 
diff --git a/chrome/browser/chromeos/arc/intent_helper/arc_navigation_throttle.h b/chrome/browser/chromeos/arc/intent_helper/arc_intent_picker_app_fetcher.h
similarity index 90%
rename from chrome/browser/chromeos/arc/intent_helper/arc_navigation_throttle.h
rename to chrome/browser/chromeos/arc/intent_helper/arc_intent_picker_app_fetcher.h
index 5e8a0c9..92d3e4e 100644
--- a/chrome/browser/chromeos/arc/intent_helper/arc_navigation_throttle.h
+++ b/chrome/browser/chromeos/arc/intent_helper/arc_intent_picker_app_fetcher.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_CHROMEOS_ARC_INTENT_HELPER_ARC_NAVIGATION_THROTTLE_H_
-#define CHROME_BROWSER_CHROMEOS_ARC_INTENT_HELPER_ARC_NAVIGATION_THROTTLE_H_
+#ifndef CHROME_BROWSER_CHROMEOS_ARC_INTENT_HELPER_ARC_INTENT_PICKER_APP_FETCHER_H_
+#define CHROME_BROWSER_CHROMEOS_ARC_INTENT_HELPER_ARC_INTENT_PICKER_APP_FETCHER_H_
 
 #include <memory>
 #include <string>
@@ -26,7 +26,7 @@
 
 // A class that allow us to retrieve installed ARC apps which can handle
 // a particular URL.
-class ArcNavigationThrottle : content::WebContentsObserver {
+class ArcIntentPickerAppFetcher : content::WebContentsObserver {
  public:
   // Retrieves ARC apps which can handle |url| for |web_contents|, and runs
   // |callback| when complete. Does not attempt to open preferred apps.
@@ -70,10 +70,10 @@
   static size_t FindPreferredAppForTesting(
       const std::vector<mojom::IntentHandlerInfoPtr>& app_candidates);
 
-  ~ArcNavigationThrottle() override;
+  ~ArcIntentPickerAppFetcher() override;
 
  private:
-  explicit ArcNavigationThrottle(content::WebContents* web_contents);
+  explicit ArcIntentPickerAppFetcher(content::WebContents* web_contents);
 
   // Asychronously queries ARC for apps which can handle |url|. Runs |callback|
   // with RESUME/CANCEL for the deferred navigation and (if applicable) the list
@@ -130,11 +130,11 @@
   void WebContentsDestroyed() override;
 
   // This has to be the last member of the class.
-  base::WeakPtrFactory<ArcNavigationThrottle> weak_ptr_factory_;
+  base::WeakPtrFactory<ArcIntentPickerAppFetcher> weak_ptr_factory_;
 
-  DISALLOW_COPY_AND_ASSIGN(ArcNavigationThrottle);
+  DISALLOW_COPY_AND_ASSIGN(ArcIntentPickerAppFetcher);
 };
 
 }  // namespace arc
 
-#endif  // CHROME_BROWSER_CHROMEOS_ARC_INTENT_HELPER_ARC_NAVIGATION_THROTTLE_H_
+#endif  // CHROME_BROWSER_CHROMEOS_ARC_INTENT_HELPER_ARC_INTENT_PICKER_APP_FETCHER_H_
diff --git a/chrome/browser/chromeos/arc/intent_helper/arc_intent_picker_app_fetcher_unittest.cc b/chrome/browser/chromeos/arc/intent_helper/arc_intent_picker_app_fetcher_unittest.cc
new file mode 100644
index 0000000..20a4117
--- /dev/null
+++ b/chrome/browser/chromeos/arc/intent_helper/arc_intent_picker_app_fetcher_unittest.cc
@@ -0,0 +1,104 @@
+// 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 <utility>
+
+#include "chrome/browser/chromeos/arc/intent_helper/arc_intent_picker_app_fetcher.h"
+#include "components/arc/intent_helper/arc_intent_helper_bridge.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace arc {
+
+namespace {
+
+// Creates an array with |num_elements| handlers and makes |chrome_index|-th
+// handler "Chrome". If Chrome is not necessary, set |chrome_index| to
+// |num_elements|.
+std::vector<mojom::IntentHandlerInfoPtr> CreateArray(size_t num_elements,
+                                                     size_t chrome_index) {
+  std::vector<mojom::IntentHandlerInfoPtr> handlers;
+  for (size_t i = 0; i < num_elements; ++i) {
+    mojom::IntentHandlerInfoPtr handler = mojom::IntentHandlerInfo::New();
+    handler->name = "Name";
+    if (i == chrome_index) {
+      handler->package_name =
+          ArcIntentHelperBridge::kArcIntentHelperPackageName;
+    } else {
+      handler->package_name = "com.package";
+    }
+    handlers.push_back(std::move(handler));
+  }
+  return handlers;
+}
+
+}  // namespace
+
+TEST(ArcIntentPickerAppFetcherTest, TestIsAppAvailable) {
+  // Test an empty array.
+  EXPECT_FALSE(
+      ArcIntentPickerAppFetcher::IsAppAvailableForTesting(CreateArray(0, 0)));
+  // Chrome only.
+  EXPECT_FALSE(
+      ArcIntentPickerAppFetcher::IsAppAvailableForTesting(CreateArray(1, 0)));
+  // Chrome and another app.
+  EXPECT_TRUE(
+      ArcIntentPickerAppFetcher::IsAppAvailableForTesting(CreateArray(2, 0)));
+  EXPECT_TRUE(
+      ArcIntentPickerAppFetcher::IsAppAvailableForTesting(CreateArray(2, 1)));
+  // App(s) only. This doesn't happen on production though.
+  EXPECT_TRUE(
+      ArcIntentPickerAppFetcher::IsAppAvailableForTesting(CreateArray(1, 1)));
+  EXPECT_TRUE(
+      ArcIntentPickerAppFetcher::IsAppAvailableForTesting(CreateArray(2, 2)));
+}
+
+TEST(ArcIntentPickerAppFetcherTest, TestFindPreferredApp) {
+  // Test an empty array.
+  EXPECT_EQ(0u, ArcIntentPickerAppFetcher::FindPreferredAppForTesting(
+                    CreateArray(0, 0)));
+  // Test no-preferred-app cases.
+  EXPECT_EQ(1u, ArcIntentPickerAppFetcher::FindPreferredAppForTesting(
+                    CreateArray(1, 0)));
+  EXPECT_EQ(2u, ArcIntentPickerAppFetcher::FindPreferredAppForTesting(
+                    CreateArray(2, 1)));
+  EXPECT_EQ(3u, ArcIntentPickerAppFetcher::FindPreferredAppForTesting(
+                    CreateArray(3, 2)));
+  // Add a preferred app and call the function.
+  for (size_t i = 0; i < 3; ++i) {
+    std::vector<mojom::IntentHandlerInfoPtr> handlers = CreateArray(3, 0);
+    handlers[i]->is_preferred = true;
+    EXPECT_EQ(i,
+              ArcIntentPickerAppFetcher::FindPreferredAppForTesting(handlers))
+        << i;
+  }
+}
+
+TEST(ArcIntentPickerAppFetcherTest, TestGetAppIndex) {
+  const std::string package_name =
+      ArcIntentHelperBridge::kArcIntentHelperPackageName;
+  // Test an empty array.
+  EXPECT_EQ(0u, ArcIntentPickerAppFetcher::GetAppIndex(CreateArray(0, 0),
+                                                       package_name));
+  // Test Chrome-only case.
+  EXPECT_EQ(0u, ArcIntentPickerAppFetcher::GetAppIndex(CreateArray(1, 0),
+                                                       package_name));
+  // Test not-found cases.
+  EXPECT_EQ(1u, ArcIntentPickerAppFetcher::GetAppIndex(CreateArray(1, 1),
+                                                       package_name));
+  EXPECT_EQ(2u, ArcIntentPickerAppFetcher::GetAppIndex(CreateArray(2, 2),
+                                                       package_name));
+  // Test other cases.
+  EXPECT_EQ(0u, ArcIntentPickerAppFetcher::GetAppIndex(CreateArray(2, 0),
+                                                       package_name));
+  EXPECT_EQ(1u, ArcIntentPickerAppFetcher::GetAppIndex(CreateArray(2, 1),
+                                                       package_name));
+  EXPECT_EQ(0u, ArcIntentPickerAppFetcher::GetAppIndex(CreateArray(3, 0),
+                                                       package_name));
+  EXPECT_EQ(1u, ArcIntentPickerAppFetcher::GetAppIndex(CreateArray(3, 1),
+                                                       package_name));
+  EXPECT_EQ(2u, ArcIntentPickerAppFetcher::GetAppIndex(CreateArray(3, 2),
+                                                       package_name));
+}
+
+}  // namespace arc
diff --git a/chrome/browser/chromeos/arc/intent_helper/arc_navigation_throttle_unittest.cc b/chrome/browser/chromeos/arc/intent_helper/arc_navigation_throttle_unittest.cc
deleted file mode 100644
index 738ff59..0000000
--- a/chrome/browser/chromeos/arc/intent_helper/arc_navigation_throttle_unittest.cc
+++ /dev/null
@@ -1,103 +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 <utility>
-
-#include "chrome/browser/chromeos/arc/intent_helper/arc_navigation_throttle.h"
-#include "components/arc/intent_helper/arc_intent_helper_bridge.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace arc {
-
-namespace {
-
-// Creates an array with |num_elements| handlers and makes |chrome_index|-th
-// handler "Chrome". If Chrome is not necessary, set |chrome_index| to
-// |num_elements|.
-std::vector<mojom::IntentHandlerInfoPtr> CreateArray(size_t num_elements,
-                                                     size_t chrome_index) {
-  std::vector<mojom::IntentHandlerInfoPtr> handlers;
-  for (size_t i = 0; i < num_elements; ++i) {
-    mojom::IntentHandlerInfoPtr handler = mojom::IntentHandlerInfo::New();
-    handler->name = "Name";
-    if (i == chrome_index) {
-      handler->package_name =
-          ArcIntentHelperBridge::kArcIntentHelperPackageName;
-    } else {
-      handler->package_name = "com.package";
-    }
-    handlers.push_back(std::move(handler));
-  }
-  return handlers;
-}
-
-}  // namespace
-
-TEST(ArcNavigationThrottleTest, TestIsAppAvailable) {
-  // Test an empty array.
-  EXPECT_FALSE(
-      ArcNavigationThrottle::IsAppAvailableForTesting(CreateArray(0, 0)));
-  // Chrome only.
-  EXPECT_FALSE(
-      ArcNavigationThrottle::IsAppAvailableForTesting(CreateArray(1, 0)));
-  // Chrome and another app.
-  EXPECT_TRUE(
-      ArcNavigationThrottle::IsAppAvailableForTesting(CreateArray(2, 0)));
-  EXPECT_TRUE(
-      ArcNavigationThrottle::IsAppAvailableForTesting(CreateArray(2, 1)));
-  // App(s) only. This doesn't happen on production though.
-  EXPECT_TRUE(
-      ArcNavigationThrottle::IsAppAvailableForTesting(CreateArray(1, 1)));
-  EXPECT_TRUE(
-      ArcNavigationThrottle::IsAppAvailableForTesting(CreateArray(2, 2)));
-}
-
-TEST(ArcNavigationThrottleTest, TestFindPreferredApp) {
-  // Test an empty array.
-  EXPECT_EQ(
-      0u, ArcNavigationThrottle::FindPreferredAppForTesting(CreateArray(0, 0)));
-  // Test no-preferred-app cases.
-  EXPECT_EQ(
-      1u, ArcNavigationThrottle::FindPreferredAppForTesting(CreateArray(1, 0)));
-  EXPECT_EQ(
-      2u, ArcNavigationThrottle::FindPreferredAppForTesting(CreateArray(2, 1)));
-  EXPECT_EQ(
-      3u, ArcNavigationThrottle::FindPreferredAppForTesting(CreateArray(3, 2)));
-  // Add a preferred app and call the function.
-  for (size_t i = 0; i < 3; ++i) {
-    std::vector<mojom::IntentHandlerInfoPtr> handlers = CreateArray(3, 0);
-    handlers[i]->is_preferred = true;
-    EXPECT_EQ(i, ArcNavigationThrottle::FindPreferredAppForTesting(handlers))
-        << i;
-  }
-}
-
-TEST(ArcNavigationThrottleTest, TestGetAppIndex) {
-  const std::string package_name =
-      ArcIntentHelperBridge::kArcIntentHelperPackageName;
-  // Test an empty array.
-  EXPECT_EQ(
-      0u, ArcNavigationThrottle::GetAppIndex(CreateArray(0, 0), package_name));
-  // Test Chrome-only case.
-  EXPECT_EQ(
-      0u, ArcNavigationThrottle::GetAppIndex(CreateArray(1, 0), package_name));
-  // Test not-found cases.
-  EXPECT_EQ(
-      1u, ArcNavigationThrottle::GetAppIndex(CreateArray(1, 1), package_name));
-  EXPECT_EQ(
-      2u, ArcNavigationThrottle::GetAppIndex(CreateArray(2, 2), package_name));
-  // Test other cases.
-  EXPECT_EQ(
-      0u, ArcNavigationThrottle::GetAppIndex(CreateArray(2, 0), package_name));
-  EXPECT_EQ(
-      1u, ArcNavigationThrottle::GetAppIndex(CreateArray(2, 1), package_name));
-  EXPECT_EQ(
-      0u, ArcNavigationThrottle::GetAppIndex(CreateArray(3, 0), package_name));
-  EXPECT_EQ(
-      1u, ArcNavigationThrottle::GetAppIndex(CreateArray(3, 1), package_name));
-  EXPECT_EQ(
-      2u, ArcNavigationThrottle::GetAppIndex(CreateArray(3, 2), package_name));
-}
-
-}  // namespace arc
diff --git a/chrome/browser/chromeos/child_accounts/screen_time_controller_browsertest.cc b/chrome/browser/chromeos/child_accounts/screen_time_controller_browsertest.cc
index 4a00d5e..1a6e086 100644
--- a/chrome/browser/chromeos/child_accounts/screen_time_controller_browsertest.cc
+++ b/chrome/browser/chromeos/child_accounts/screen_time_controller_browsertest.cc
@@ -29,6 +29,7 @@
 #include "components/prefs/pref_service.h"
 #include "components/session_manager/core/session_manager.h"
 #include "content/public/browser/notification_service.h"
+#include "content/public/test/test_utils.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace chromeos {
diff --git a/chrome/browser/chromeos/crostini/crostini_manager.cc b/chrome/browser/chromeos/crostini/crostini_manager.cc
index 5df8f3a..afda168 100644
--- a/chrome/browser/chromeos/crostini/crostini_manager.cc
+++ b/chrome/browser/chromeos/crostini/crostini_manager.cc
@@ -1351,6 +1351,32 @@
                      weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
 }
 
+void CrostiniManager::SetInstallerViewStatus(bool open) {
+  installer_view_status_ = open;
+  for (auto& observer : installer_view_status_observers_) {
+    observer.OnCrostiniInstallerViewStatusChanged(open);
+  }
+}
+
+bool CrostiniManager::GetInstallerViewStatus() const {
+  return installer_view_status_;
+}
+
+void CrostiniManager::AddInstallerViewStatusObserver(
+    InstallerViewStatusObserver* observer) {
+  installer_view_status_observers_.AddObserver(observer);
+}
+
+void CrostiniManager::RemoveInstallerViewStatusObserver(
+    InstallerViewStatusObserver* observer) {
+  installer_view_status_observers_.RemoveObserver(observer);
+}
+
+bool CrostiniManager::HasInstallerViewStatusObserver(
+    InstallerViewStatusObserver* observer) {
+  return installer_view_status_observers_.HasObserver(observer);
+}
+
 void CrostiniManager::AttachUsbDevice(const std::string& vm_name,
                                       device::mojom::UsbDeviceInfoPtr device,
                                       AttachUsbDeviceCallback callback) {
diff --git a/chrome/browser/chromeos/crostini/crostini_manager.h b/chrome/browser/chromeos/crostini/crostini_manager.h
index 29ab73c..76bd4df 100644
--- a/chrome/browser/chromeos/crostini/crostini_manager.h
+++ b/chrome/browser/chromeos/crostini/crostini_manager.h
@@ -14,6 +14,7 @@
 #include "base/files/file_path.h"
 #include "base/memory/singleton.h"
 #include "base/memory/weak_ptr.h"
+#include "base/observer_list.h"
 #include "base/optional.h"
 #include "chrome/browser/chromeos/crostini/crostini_util.h"
 #include "chrome/browser/component_updater/cros_component_installer_chromeos.h"
@@ -191,6 +192,12 @@
                                          uint64_t progress_speed) = 0;
 };
 
+class InstallerViewStatusObserver : public base::CheckedObserver {
+ public:
+  // Called when the CrostiniInstallerView is opened or closed.
+  virtual void OnCrostiniInstallerViewStatusChanged(bool open) = 0;
+};
+
 // CrostiniManager is a singleton which is used to check arguments for
 // ConciergeClient and CiceroneClient. ConciergeClient is dedicated to
 // communication with the Concierge service, CiceroneClient is dedicated to
@@ -625,6 +632,12 @@
 
   void SetUsbManagerForTesting(device::mojom::UsbDeviceManagerPtr usb_manager);
 
+  void SetInstallerViewStatus(bool open);
+  bool GetInstallerViewStatus() const;
+  void AddInstallerViewStatusObserver(InstallerViewStatusObserver* observer);
+  void RemoveInstallerViewStatusObserver(InstallerViewStatusObserver* observer);
+  bool HasInstallerViewStatusObserver(InstallerViewStatusObserver* observer);
+
  private:
   class CrostiniRestarter;
 
@@ -907,6 +920,10 @@
 
   device::mojom::UsbDeviceManagerPtr usb_manager_;
 
+  bool installer_view_status_;
+  base::ObserverList<InstallerViewStatusObserver>
+      installer_view_status_observers_;
+
   // Note: This should remain the last member so it'll be destroyed and
   // invalidate its weak pointers before any other members are destroyed.
   base::WeakPtrFactory<CrostiniManager> weak_ptr_factory_;
diff --git a/chrome/browser/chromeos/dbus/metrics_event_service_provider.cc b/chrome/browser/chromeos/dbus/metrics_event_service_provider.cc
index c3d5398..5a7cce1 100644
--- a/chrome/browser/chromeos/dbus/metrics_event_service_provider.cc
+++ b/chrome/browser/chromeos/dbus/metrics_event_service_provider.cc
@@ -6,6 +6,7 @@
 
 #include <time.h>
 
+#include "base/time/time.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/resource_coordinator/tab_manager.h"
 #include "dbus/message.h"
@@ -54,7 +55,7 @@
     PLOG(DFATAL) << "clock_gettime";
     return;
   }
-  int64_t now_ms = timespec.tv_sec * 1000 + timespec.tv_nsec / (1000 * 1000);
+  int64_t now_ms = base::TimeDelta::FromTimeSpec(timespec).InMilliseconds();
 
   dbus::MessageWriter writer(&signal);
   payload.set_type(type);
diff --git a/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc b/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc
index aa05209..c6cc6e6 100644
--- a/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc
+++ b/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc
@@ -8,6 +8,7 @@
 #include <sstream>
 #include <utility>
 
+#include "ash/public/cpp/ash_pref_names.h"
 #include "ash/public/interfaces/ash_message_center_controller.mojom.h"
 #include "ash/public/interfaces/constants.mojom.h"
 #include "ash/shell.h"
@@ -181,6 +182,8 @@
         ash::mojom::AssistantAllowedState::ALLOWED) {
       return "Assistant is not available for the current user";
     }
+  } else if (pref_name == ash::prefs::kAccessibilityVirtualKeyboardEnabled) {
+    DCHECK(value.is_bool());
   } else {
     return "The pref " + pref_name + "is not whitelisted.";
   }
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.cc b/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.cc
index f51fd02..126a291 100644
--- a/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.cc
@@ -344,44 +344,53 @@
 
 }  // namespace
 
-void FileWatchFunctionBase::Respond(bool success) {
+void FileWatchFunctionBase::RespondWith(bool success) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-
-  SetResult(std::make_unique<base::Value>(success));
-  SendResponse(success);
+  auto result_value = std::make_unique<base::Value>(success);
+  if (success) {
+    Respond(OneArgument(std::move(result_value)));
+  } else {
+    auto result_list = std::make_unique<base::ListValue>();
+    result_list->Append(std::move(result_value));
+    Respond(ErrorWithArguments(std::move(result_list), ""));
+  }
 }
 
-bool FileWatchFunctionBase::RunAsync() {
+ExtensionFunction::ResponseAction FileWatchFunctionBase::Run() {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   if (!render_frame_host() || !render_frame_host()->GetProcess())
-    return false;
+    return RespondNow(Error("Invalid state"));
 
   // First param is url of a file to watch.
   std::string url;
   if (!args_->GetString(0, &url) || url.empty())
-    return false;
+    return RespondNow(Error("Empty watch URL"));
 
+  const ChromeExtensionFunctionDetails chrome_details(this);
   scoped_refptr<storage::FileSystemContext> file_system_context =
       file_manager::util::GetFileSystemContextForRenderFrameHost(
-          GetProfile(), render_frame_host());
+          chrome_details.GetProfile(), render_frame_host());
 
   const FileSystemURL file_system_url =
       file_system_context->CrackURL(GURL(url));
   if (file_system_url.path().empty()) {
-    Respond(false);
-    return true;
+    auto result_list = std::make_unique<base::ListValue>();
+    result_list->Append(std::make_unique<base::Value>(false));
+    return RespondNow(
+        ErrorWithArguments(std::move(result_list), "Invalid URL"));
   }
 
   file_manager::EventRouter* const event_router =
-      file_manager::EventRouterFactory::GetForProfile(GetProfile());
+      file_manager::EventRouterFactory::GetForProfile(
+          chrome_details.GetProfile());
 
   base::PostTaskWithTraits(
       FROM_HERE, {BrowserThread::IO},
       base::BindOnce(&FileWatchFunctionBase::RunAsyncOnIOThread, this,
                      file_system_context, file_system_url,
                      event_router->GetWeakPtr()));
-  return true;
+  return RespondLater();
 }
 
 void FileWatchFunctionBase::RunAsyncOnIOThread(
@@ -416,9 +425,10 @@
 
   watcher_manager->AddWatcher(
       file_system_url, false /* recursive */,
-      base::Bind(&StatusCallbackToResponseCallback,
-                 base::Bind(&PostResponseCallbackTaskToUIThread,
-                            base::Bind(&FileWatchFunctionBase::Respond, this))),
+      base::Bind(
+          &StatusCallbackToResponseCallback,
+          base::Bind(&PostResponseCallbackTaskToUIThread,
+                     base::Bind(&FileWatchFunctionBase::RespondWith, this))),
       base::Bind(
           &PostNotificationCallbackTaskToUIThread,
           base::Bind(&file_manager::EventRouter::OnWatcherManagerNotification,
@@ -433,9 +443,9 @@
   DCHECK(event_router);
 
   // Obsolete. Fallback code if storage::WatcherManager is not implemented.
-  event_router->AddFileWatch(file_system_url.path(),
-                             file_system_url.virtual_path(), extension_id(),
-                             base::Bind(&FileWatchFunctionBase::Respond, this));
+  event_router->AddFileWatch(
+      file_system_url.path(), file_system_url.virtual_path(), extension_id(),
+      base::Bind(&FileWatchFunctionBase::RespondWith, this));
 }
 
 void FileManagerPrivateInternalRemoveFileWatchFunction::
@@ -451,7 +461,7 @@
       base::Bind(
           &StatusCallbackToResponseCallback,
           base::Bind(&PostResponseCallbackTaskToUIThread,
-                     base::Bind(&FileWatchFunctionBase::Respond, this))));
+                     base::Bind(&FileWatchFunctionBase::RespondWith, this))));
 }
 
 void FileManagerPrivateInternalRemoveFileWatchFunction::
@@ -463,35 +473,37 @@
 
   // Obsolete. Fallback code if storage::WatcherManager is not implemented.
   event_router->RemoveFileWatch(file_system_url.path(), extension_id());
-  Respond(true);
+  RespondWith(true);
 }
 
-bool FileManagerPrivateGetSizeStatsFunction::RunAsync() {
+ExtensionFunction::ResponseAction
+FileManagerPrivateGetSizeStatsFunction::Run() {
   using extensions::api::file_manager_private::GetSizeStats::Params;
   const std::unique_ptr<Params> params(Params::Create(*args_));
   EXTENSION_FUNCTION_VALIDATE(params);
 
   using file_manager::VolumeManager;
   using file_manager::Volume;
-  VolumeManager* const volume_manager = VolumeManager::Get(GetProfile());
+  const ChromeExtensionFunctionDetails chrome_details(this);
+  VolumeManager* const volume_manager =
+      VolumeManager::Get(chrome_details.GetProfile());
   if (!volume_manager)
-    return false;
+    return RespondNow(Error("Invalid state"));
 
   base::WeakPtr<Volume> volume =
       volume_manager->FindVolumeById(params->volume_id);
   if (!volume.get())
-    return false;
+    return RespondNow(Error("Volume not found"));
 
   if (volume->type() == file_manager::VOLUME_TYPE_GOOGLE_DRIVE &&
       !base::FeatureList::IsEnabled(chromeos::features::kDriveFs)) {
     drive::FileSystemInterface* file_system =
-        drive::util::GetFileSystemByProfile(GetProfile());
+        drive::util::GetFileSystemByProfile(chrome_details.GetProfile());
     if (!file_system) {
       // |file_system| is NULL if Drive is disabled.
       // If stats couldn't be gotten for drive, result should be left
       // undefined. See comments in GetDriveAvailableSpaceCallback().
-      SendResponse(true);
-      return true;
+      return RespondNow(NoArguments());
     }
 
     file_system->GetAvailableSpace(base::BindOnce(
@@ -525,7 +537,7 @@
                        this, base::Owned(total_size),
                        base::Owned(remaining_size)));
   }
-  return true;
+  return RespondLater();
 }
 
 void FileManagerPrivateGetSizeStatsFunction::OnGetDriveAvailableSpace(
@@ -540,7 +552,7 @@
     OnGetSizeStats(&bytes_total_unsigned, &bytes_remaining_unsigned);
   } else {
     // If stats couldn't be gotten for drive, result should be left undefined.
-    SendResponse(true);
+    Respond(NoArguments());
   }
 }
 
@@ -550,7 +562,7 @@
   if (error) {
     // If stats couldn't be gotten from MTP volume, result should be left
     // undefined same as we do for Drive.
-    SendResponse(true);
+    Respond(NoArguments());
     return;
   }
 
@@ -567,30 +579,29 @@
   sizes->SetDouble("totalSize", static_cast<double>(*total_size));
   sizes->SetDouble("remainingSize", static_cast<double>(*remaining_size));
 
-  SetResult(std::move(sizes));
-  SendResponse(true);
+  Respond(OneArgument(std::move(sizes)));
 }
 
-bool FileManagerPrivateInternalValidatePathNameLengthFunction::RunAsync() {
+ExtensionFunction::ResponseAction
+FileManagerPrivateInternalValidatePathNameLengthFunction::Run() {
   using extensions::api::file_manager_private_internal::ValidatePathNameLength::
       Params;
   const std::unique_ptr<Params> params(Params::Create(*args_));
   EXTENSION_FUNCTION_VALIDATE(params);
 
+  const ChromeExtensionFunctionDetails chrome_details(this);
   scoped_refptr<storage::FileSystemContext> file_system_context =
       file_manager::util::GetFileSystemContextForRenderFrameHost(
-          GetProfile(), render_frame_host());
+          chrome_details.GetProfile(), render_frame_host());
 
   const storage::FileSystemURL file_system_url(
       file_system_context->CrackURL(GURL(params->parent_url)));
   if (!chromeos::FileSystemBackend::CanHandleURL(file_system_url))
-    return false;
+    return RespondNow(Error("Invalid URL"));
 
   // No explicit limit on the length of Drive file names.
   if (file_system_url.type() == storage::kFileSystemTypeDrive) {
-    SetResult(std::make_unique<base::Value>(true));
-    SendResponse(true);
-    return true;
+    return RespondNow(OneArgument(std::make_unique<base::Value>(true)));
   }
 
   base::PostTaskWithTraitsAndReplyWithResult(
@@ -600,57 +611,61 @@
       base::BindOnce(&FileManagerPrivateInternalValidatePathNameLengthFunction::
                          OnFilePathLimitRetrieved,
                      this, params->name.size()));
-  return true;
+  return RespondLater();
 }
 
 void FileManagerPrivateInternalValidatePathNameLengthFunction::
     OnFilePathLimitRetrieved(size_t current_length, size_t max_length) {
-  SetResult(std::make_unique<base::Value>(current_length <= max_length));
-  SendResponse(true);
+  Respond(
+      OneArgument(std::make_unique<base::Value>(current_length <= max_length)));
 }
 
-bool FileManagerPrivateFormatVolumeFunction::RunAsync() {
+ExtensionFunction::ResponseAction
+FileManagerPrivateFormatVolumeFunction::Run() {
   using extensions::api::file_manager_private::FormatVolume::Params;
   const std::unique_ptr<Params> params(Params::Create(*args_));
   EXTENSION_FUNCTION_VALIDATE(params);
 
   using file_manager::VolumeManager;
   using file_manager::Volume;
-  VolumeManager* const volume_manager = VolumeManager::Get(GetProfile());
+  const ChromeExtensionFunctionDetails chrome_details(this);
+  VolumeManager* const volume_manager =
+      VolumeManager::Get(chrome_details.GetProfile());
   if (!volume_manager)
-    return false;
+    return RespondNow(Error("Invalid state"));
 
   base::WeakPtr<Volume> volume =
       volume_manager->FindVolumeById(params->volume_id);
   if (!volume)
-    return false;
+    return RespondNow(Error("Volume not found"));
 
   DiskMountManager::GetInstance()->FormatMountedDevice(
       volume->mount_path().AsUTF8Unsafe());
-  SendResponse(true);
-  return true;
+  return RespondNow(NoArguments());
 }
 
-bool FileManagerPrivateRenameVolumeFunction::RunAsync() {
+ExtensionFunction::ResponseAction
+FileManagerPrivateRenameVolumeFunction::Run() {
   using extensions::api::file_manager_private::RenameVolume::Params;
   const std::unique_ptr<Params> params(Params::Create(*args_));
   EXTENSION_FUNCTION_VALIDATE(params);
 
   using file_manager::VolumeManager;
   using file_manager::Volume;
-  VolumeManager* const volume_manager = VolumeManager::Get(GetProfile());
+  const ChromeExtensionFunctionDetails chrome_details(this);
+  VolumeManager* const volume_manager =
+      VolumeManager::Get(chrome_details.GetProfile());
   if (!volume_manager)
-    return false;
+    return RespondNow(Error("Invalid state"));
 
   base::WeakPtr<Volume> volume =
       volume_manager->FindVolumeById(params->volume_id);
   if (!volume)
-    return false;
+    return RespondNow(Error("Volume not found"));
 
   DiskMountManager::GetInstance()->RenameMountedDevice(
       volume->mount_path().AsUTF8Unsafe(), params->new_name);
-  SendResponse(true);
-  return true;
+  return RespondNow(NoArguments());
 }
 
 namespace {
@@ -677,7 +692,12 @@
 
 }  // namespace
 
-bool FileManagerPrivateInternalStartCopyFunction::RunAsync() {
+FileManagerPrivateInternalStartCopyFunction::
+    FileManagerPrivateInternalStartCopyFunction()
+    : chrome_details_(this) {}
+
+ExtensionFunction::ResponseAction
+FileManagerPrivateInternalStartCopyFunction::Run() {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   using extensions::api::file_manager_private_internal::StartCopy::Params;
@@ -687,13 +707,12 @@
   if (params->url.empty() || params->parent_url.empty() ||
       params->new_name.empty()) {
     // Error code in format of DOMError.name.
-    SetError("EncodingError");
-    return false;
+    return RespondNow(Error("EncodingError"));
   }
 
   scoped_refptr<storage::FileSystemContext> file_system_context =
       file_manager::util::GetFileSystemContextForRenderFrameHost(
-          GetProfile(), render_frame_host());
+          chrome_details_.GetProfile(), render_frame_host());
 
   // |parent| may have a trailing slash if it is a root directory.
   std::string destination_url_string = params->parent_url;
@@ -707,12 +726,11 @@
 
   if (!source_url_.is_valid() || !destination_url_.is_valid()) {
     // Error code in format of DOMError.name.
-    SetError("EncodingError");
-    return false;
+    return RespondNow(Error("EncodingError"));
   }
 
   // Check how much space we need for the copy operation.
-  return base::PostTaskWithTraits(
+  base::PostTaskWithTraits(
       FROM_HERE, {BrowserThread::IO},
       base::BindOnce(
           &GetFileMetadataOnIOThread, file_system_context, source_url_,
@@ -721,6 +739,7 @@
           base::BindOnce(&FileManagerPrivateInternalStartCopyFunction::
                              RunAfterGetFileMetadata,
                          this)));
+  return RespondLater();
 }
 
 void FileManagerPrivateInternalStartCopyFunction::RunAfterGetFileMetadata(
@@ -729,17 +748,18 @@
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   if (result != base::File::FILE_OK) {
-    SetError("NotFoundError");
-    SendResponse(false);
+    Respond(Error("NotFoundError"));
     return;
   }
 
   base::FilePath destination_dir;
   if (destination_url_.filesystem_id() ==
-      drive::util::GetDriveMountPointPath(GetProfile()).BaseName().value()) {
+      drive::util::GetDriveMountPointPath(chrome_details_.GetProfile())
+          .BaseName()
+          .value()) {
     // Google Drive's cache is limited by the available space on the local disk.
-    destination_dir =
-        file_manager::util::GetMyFilesFolderForProfile(GetProfile());
+    destination_dir = file_manager::util::GetMyFilesFolderForProfile(
+        chrome_details_.GetProfile());
   } else {
     destination_dir = destination_url_.path().DirName();
   }
@@ -760,9 +780,11 @@
     // enough space.
     RunAfterFreeDiskSpace(true);
   } else if (destination_url_.filesystem_id() ==
-                 file_manager::util::GetDownloadsMountPointName(GetProfile()) ||
+                 file_manager::util::GetDownloadsMountPointName(
+                     chrome_details_.GetProfile()) ||
              destination_url_.filesystem_id() ==
-                 drive::util::GetDriveMountPointPath(GetProfile())
+                 drive::util::GetDriveMountPointPath(
+                     chrome_details_.GetProfile())
                      .BaseName()
                      .value()) {
     // If the destination directory is local hard drive or Google Drive we
@@ -772,7 +794,7 @@
     } else {
       // Also we can try to secure needed space by freeing Drive caches.
       drive::FileSystemInterface* const drive_file_system =
-          drive::util::GetFileSystemByProfile(GetProfile());
+          drive::util::GetFileSystemByProfile(chrome_details_.GetProfile());
       if (!drive_file_system) {
         RunAfterFreeDiskSpace(false);
       } else {
@@ -793,51 +815,47 @@
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   if (!available) {
-    SetError("QuotaExceededError");
-    SendResponse(false);
+    Respond(Error("QuotaExceededError"));
     return;
   }
 
   scoped_refptr<storage::FileSystemContext> file_system_context =
       file_manager::util::GetFileSystemContextForRenderFrameHost(
-          GetProfile(), render_frame_host());
-  const bool result = base::PostTaskWithTraitsAndReplyWithResult(
+          chrome_details_.GetProfile(), render_frame_host());
+  base::PostTaskWithTraitsAndReplyWithResult(
       FROM_HERE, {BrowserThread::IO},
-      base::BindOnce(&StartCopyOnIOThread, GetProfile(), file_system_context,
-                     source_url_, destination_url_),
+      base::BindOnce(&StartCopyOnIOThread, chrome_details_.GetProfile(),
+                     file_system_context, source_url_, destination_url_),
       base::BindOnce(
           &FileManagerPrivateInternalStartCopyFunction::RunAfterStartCopy,
           this));
-  if (!result)
-    SendResponse(false);
 }
 
 void FileManagerPrivateInternalStartCopyFunction::RunAfterStartCopy(
     int operation_id) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
-  SetResult(std::make_unique<base::Value>(operation_id));
-  SendResponse(true);
+  Respond(OneArgument(std::make_unique<base::Value>(operation_id)));
 }
 
-bool FileManagerPrivateCancelCopyFunction::RunAsync() {
+ExtensionFunction::ResponseAction FileManagerPrivateCancelCopyFunction::Run() {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   using extensions::api::file_manager_private::CancelCopy::Params;
   const std::unique_ptr<Params> params(Params::Create(*args_));
   EXTENSION_FUNCTION_VALIDATE(params);
 
+  const ChromeExtensionFunctionDetails chrome_details(this);
   scoped_refptr<storage::FileSystemContext> file_system_context =
       file_manager::util::GetFileSystemContextForRenderFrameHost(
-          GetProfile(), render_frame_host());
+          chrome_details.GetProfile(), render_frame_host());
 
   // We don't much take care about the result of cancellation.
   base::PostTaskWithTraits(
       FROM_HERE, {BrowserThread::IO},
       base::BindOnce(&CancelCopyOnIOThread, file_system_context,
                      params->copy_id));
-  SendResponse(true);
-  return true;
+  return RespondNow(NoArguments());
 }
 
 ExtensionFunction::ResponseAction
@@ -917,26 +935,26 @@
 FileManagerPrivateInternalComputeChecksumFunction::
     ~FileManagerPrivateInternalComputeChecksumFunction() = default;
 
-bool FileManagerPrivateInternalComputeChecksumFunction::RunAsync() {
+ExtensionFunction::ResponseAction
+FileManagerPrivateInternalComputeChecksumFunction::Run() {
   using extensions::api::file_manager_private_internal::ComputeChecksum::Params;
   using drive::util::FileStreamMd5Digester;
   const std::unique_ptr<Params> params(Params::Create(*args_));
   EXTENSION_FUNCTION_VALIDATE(params);
 
   if (params->url.empty()) {
-    SetError("File URL must be provided.");
-    return false;
+    return RespondNow(Error("File URL must be provided."));
   }
 
+  const ChromeExtensionFunctionDetails chrome_details(this);
   scoped_refptr<storage::FileSystemContext> file_system_context =
       file_manager::util::GetFileSystemContextForRenderFrameHost(
-          GetProfile(), render_frame_host());
+          chrome_details.GetProfile(), render_frame_host());
 
   FileSystemURL file_system_url(
       file_system_context->CrackURL(GURL(params->url)));
   if (!file_system_url.is_valid()) {
-    SetError("File URL was invalid");
-    return false;
+    return RespondNow(Error("File URL was invalid"));
   }
 
   std::unique_ptr<storage::FileStreamReader> reader =
@@ -945,25 +963,30 @@
 
   FileStreamMd5Digester::ResultCallback result_callback = base::Bind(
       &ComputeChecksumRespondOnUIThread,
-      base::Bind(&FileManagerPrivateInternalComputeChecksumFunction::Respond,
-                 this));
+      base::Bind(
+          &FileManagerPrivateInternalComputeChecksumFunction::RespondWith,
+          this));
   base::PostTaskWithTraits(
       FROM_HERE, {BrowserThread::IO},
       base::BindOnce(&FileStreamMd5Digester::GetMd5Digest,
                      base::Unretained(digester_.get()), base::Passed(&reader),
                      result_callback));
 
-  return true;
+  return RespondLater();
 }
 
-void FileManagerPrivateInternalComputeChecksumFunction::Respond(
+void FileManagerPrivateInternalComputeChecksumFunction::RespondWith(
     const std::string& hash) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  SetResult(std::make_unique<base::Value>(hash));
-  SendResponse(true);
+  Respond(OneArgument(std::make_unique<base::Value>(hash)));
 }
 
-bool FileManagerPrivateSearchFilesByHashesFunction::RunAsync() {
+FileManagerPrivateSearchFilesByHashesFunction::
+    FileManagerPrivateSearchFilesByHashesFunction()
+    : chrome_details_(this) {}
+
+ExtensionFunction::ResponseAction
+FileManagerPrivateSearchFilesByHashesFunction::Run() {
   using api::file_manager_private::SearchFilesByHashes::Params;
   const std::unique_ptr<Params> params(Params::Create(*args_));
   EXTENSION_FUNCTION_VALIDATE(params);
@@ -972,7 +995,7 @@
   // than Drive.
 
   drive::EventLogger* const logger =
-      file_manager::util::GetLogger(GetProfile());
+      file_manager::util::GetLogger(chrome_details_.GetProfile());
   if (logger) {
     logger->Log(logging::LOG_INFO,
                 "%s[%d] called. (volume id: %s, number of hashes: %zd)", name(),
@@ -982,17 +1005,17 @@
   set_log_on_completion(true);
 
   drive::DriveIntegrationService* integration_service =
-      drive::util::GetIntegrationServiceByProfile(GetProfile());
+      drive::util::GetIntegrationServiceByProfile(chrome_details_.GetProfile());
   if (!integration_service) {
     // |integration_service| is NULL if Drive is disabled or not mounted.
-    return false;
+    return RespondNow(Error("Drive not available"));
   }
 
   std::set<std::string> hashes(params->hash_list.begin(),
                                params->hash_list.end());
 
   drive::FileSystemInterface* const file_system =
-      drive::util::GetFileSystemByProfile(GetProfile());
+      drive::util::GetFileSystemByProfile(chrome_details_.GetProfile());
   if (file_system) {
     file_system->SearchByHashes(
         hashes,
@@ -1010,13 +1033,13 @@
             this, hashes,
             integration_service->GetMountPointPath().Append(
                 drive::util::kDriveMyDriveRootDirName),
-            drive::util::GetDriveMountPointPath(GetProfile())),
+            drive::util::GetDriveMountPointPath(chrome_details_.GetProfile())),
         base::BindOnce(
             &FileManagerPrivateSearchFilesByHashesFunction::OnSearchByAttribute,
             this, hashes));
   }
 
-  return true;
+  return RespondLater();
 }
 
 std::vector<drive::HashAndFilePath>
@@ -1062,7 +1085,7 @@
     drive::FileError error,
     const std::vector<drive::HashAndFilePath>& search_results) {
   if (error != drive::FileError::FILE_ERROR_OK) {
-    SendResponse(false);
+    Respond(Error(drive::FileErrorToString(error)));
     return;
   }
 
@@ -1077,10 +1100,10 @@
     result->GetListWithoutPathExpansion(hashAndPath.hash, &list);
     list->AppendString(
         file_manager::util::ConvertDrivePathToFileSystemUrl(
-            GetProfile(), hashAndPath.path, extension_id()).spec());
+            chrome_details_.GetProfile(), hashAndPath.path, extension_id())
+            .spec());
   }
-  SetResult(std::move(result));
-  SendResponse(true);
+  Respond(OneArgument(std::move(result)));
 }
 
 ExtensionFunction::ResponseAction
@@ -1147,37 +1170,37 @@
                                          : Error("Failed to set a tag."));
 }
 
-bool FileManagerPrivateInternalGetDirectorySizeFunction::RunAsync() {
+ExtensionFunction::ResponseAction
+FileManagerPrivateInternalGetDirectorySizeFunction::Run() {
   using extensions::api::file_manager_private_internal::GetDirectorySize::
       Params;
   const std::unique_ptr<Params> params(Params::Create(*args_));
   EXTENSION_FUNCTION_VALIDATE(params);
 
   if (params->url.empty()) {
-    SetError("File URL must be provided.");
-    return false;
+    return RespondNow(Error("File URL must be provided."));
   }
 
+  const ChromeExtensionFunctionDetails chrome_details(this);
   scoped_refptr<storage::FileSystemContext> file_system_context =
       file_manager::util::GetFileSystemContextForRenderFrameHost(
-          GetProfile(), render_frame_host());
+          chrome_details.GetProfile(), render_frame_host());
   const storage::FileSystemURL file_system_url(
       file_system_context->CrackURL(GURL(params->url)));
   if (!chromeos::FileSystemBackend::CanHandleURL(file_system_url)) {
-    SetError("FileSystemBackend failed to handle the entry's url.");
-    return false;
+    return RespondNow(
+        Error("FileSystemBackend failed to handle the entry's url."));
   }
   if (file_system_url.type() != storage::kFileSystemTypeNativeLocal &&
       file_system_url.type() != storage::kFileSystemTypeDriveFs) {
-    SetError("Only local directories are supported.");
-    return false;
+    return RespondNow(Error("Only local directories are supported."));
   }
 
   const base::FilePath root_path = file_manager::util::GetLocalPathFromURL(
-      render_frame_host(), GetProfile(), GURL(params->url));
+      render_frame_host(), chrome_details.GetProfile(), GURL(params->url));
   if (root_path.empty()) {
-    SetError("Failed to get a local path from the entry's url.");
-    return false;
+    return RespondNow(
+        Error("Failed to get a local path from the entry's url."));
   }
 
   base::PostTaskWithTraitsAndReplyWithResult(
@@ -1186,13 +1209,13 @@
       base::BindOnce(&FileManagerPrivateInternalGetDirectorySizeFunction::
                          OnDirectorySizeRetrieved,
                      this));
-  return true;
+  return RespondLater();
 }
 
 void FileManagerPrivateInternalGetDirectorySizeFunction::
     OnDirectorySizeRetrieved(int64_t size) {
-  SetResult(std::make_unique<base::Value>(static_cast<double>(size)));
-  SendResponse(true);
+  Respond(
+      OneArgument(std::make_unique<base::Value>(static_cast<double>(size))));
 }
 
 }  // namespace extensions
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.h b/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.h
index dfff1fd9..076da15 100644
--- a/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.h
+++ b/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.h
@@ -19,7 +19,6 @@
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "chrome/browser/chromeos/extensions/file_manager/private_api_base.h"
-#include "chrome/browser/extensions/chrome_extension_function.h"
 #include "chrome/browser/extensions/chrome_extension_function_details.h"
 #include "components/drive/file_errors.h"
 #include "extensions/browser/extension_function.h"
@@ -87,12 +86,12 @@
 // "FileWatch",
 // the class and its sub classes are used only for watching changes in
 // directories.
-class FileWatchFunctionBase : public LoggedAsyncExtensionFunction {
+class FileWatchFunctionBase : public LoggedUIThreadExtensionFunction {
  public:
   using ResponseCallback = base::Callback<void(bool success)>;
 
-  // Calls SendResponse() with |success| converted to base::Value.
-  void Respond(bool success);
+  // Calls Respond() with |success| converted to base::Value.
+  void RespondWith(bool success);
 
  protected:
   ~FileWatchFunctionBase() override = default;
@@ -112,8 +111,8 @@
       const storage::FileSystemURL& file_system_url,
       base::WeakPtr<file_manager::EventRouter> event_router) = 0;
 
-  // ChromeAsyncExtensionFunction overrides.
-  bool RunAsync() override;
+  // ExtensionFunction overrides.
+  ResponseAction Run() override;
 
  private:
   void RunAsyncOnIOThread(
@@ -169,7 +168,7 @@
 
 // Implements the chrome.fileManagerPrivate.getSizeStats method.
 class FileManagerPrivateGetSizeStatsFunction
-    : public LoggedAsyncExtensionFunction {
+    : public LoggedUIThreadExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("fileManagerPrivate.getSizeStats",
                              FILEMANAGERPRIVATE_GETSIZESTATS)
@@ -177,8 +176,8 @@
  protected:
   ~FileManagerPrivateGetSizeStatsFunction() override = default;
 
-  // ChromeAsyncExtensionFunction overrides.
-  bool RunAsync() override;
+  // ExtensionFunction overrides.
+  ResponseAction Run() override;
 
  private:
   void OnGetDriveAvailableSpace(drive::FileError error,
@@ -194,7 +193,7 @@
 
 // Implements the chrome.fileManagerPrivate.validatePathNameLength method.
 class FileManagerPrivateInternalValidatePathNameLengthFunction
-    : public LoggedAsyncExtensionFunction {
+    : public LoggedUIThreadExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION(
       "fileManagerPrivateInternal.validatePathNameLength",
@@ -206,14 +205,14 @@
 
   void OnFilePathLimitRetrieved(size_t current_length, size_t max_length);
 
-  // ChromeAsyncExtensionFunction overrides.
-  bool RunAsync() override;
+  // ExtensionFunction overrides.
+  ResponseAction Run() override;
 };
 
 // Implements the chrome.fileManagerPrivate.formatVolume method.
 // Formats Volume given its mount path.
 class FileManagerPrivateFormatVolumeFunction
-    : public LoggedAsyncExtensionFunction {
+    : public LoggedUIThreadExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("fileManagerPrivate.formatVolume",
                              FILEMANAGERPRIVATE_FORMATVOLUME)
@@ -221,14 +220,14 @@
  protected:
   ~FileManagerPrivateFormatVolumeFunction() override = default;
 
-  // ChromeAsyncExtensionFunction overrides.
-  bool RunAsync() override;
+  // ExtensionFunction overrides.
+  ResponseAction Run() override;
 };
 
 // Implements the chrome.fileManagerPrivate.renameVolume method.
 // Renames Volume given its mount path and new Volume name.
 class FileManagerPrivateRenameVolumeFunction
-    : public LoggedAsyncExtensionFunction {
+    : public LoggedUIThreadExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("fileManagerPrivate.renameVolume",
                              FILEMANAGERPRIVATE_RENAMEVOLUME)
@@ -236,22 +235,24 @@
  protected:
   ~FileManagerPrivateRenameVolumeFunction() override = default;
 
-  // ChromeAsyncExtensionFunction overrides.
-  bool RunAsync() override;
+  // ExtensionFunction overrides.
+  ResponseAction Run() override;
 };
 
 // Implements the chrome.fileManagerPrivate.startCopy method.
 class FileManagerPrivateInternalStartCopyFunction
-    : public LoggedAsyncExtensionFunction {
+    : public LoggedUIThreadExtensionFunction {
  public:
+  FileManagerPrivateInternalStartCopyFunction();
+
   DECLARE_EXTENSION_FUNCTION("fileManagerPrivateInternal.startCopy",
                              FILEMANAGERPRIVATEINTERNAL_STARTCOPY)
 
  protected:
   ~FileManagerPrivateInternalStartCopyFunction() override = default;
 
-  // ChromeAsyncExtensionFunction overrides.
-  bool RunAsync() override;
+  // ExtensionFunction overrides.
+  ResponseAction Run() override;
 
  private:
   void RunAfterGetFileMetadata(base::File::Error result,
@@ -270,11 +271,12 @@
 
   storage::FileSystemURL source_url_;
   storage::FileSystemURL destination_url_;
+  const ChromeExtensionFunctionDetails chrome_details_;
 };
 
 // Implements the chrome.fileManagerPrivate.cancelCopy method.
 class FileManagerPrivateCancelCopyFunction
-    : public LoggedAsyncExtensionFunction {
+    : public LoggedUIThreadExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("fileManagerPrivate.cancelCopy",
                              FILEMANAGERPRIVATE_CANCELCOPY)
@@ -282,8 +284,8 @@
  protected:
   ~FileManagerPrivateCancelCopyFunction() override = default;
 
-  // ChromeAsyncExtensionFunction overrides.
-  bool RunAsync() override;
+  // ExtensionFunction overrides.
+  ResponseAction Run() override;
 };
 
 // Implements the chrome.fileManagerPrivateInternal.resolveIsolatedEntries
@@ -309,7 +311,7 @@
 };
 
 class FileManagerPrivateInternalComputeChecksumFunction
-    : public LoggedAsyncExtensionFunction {
+    : public LoggedUIThreadExtensionFunction {
  public:
   FileManagerPrivateInternalComputeChecksumFunction();
 
@@ -319,20 +321,22 @@
  protected:
   ~FileManagerPrivateInternalComputeChecksumFunction() override;
 
-  // ChromeAsyncExtensionFunction overrides.
-  bool RunAsync() override;
+  // ExtensionFunction overrides.
+  ResponseAction Run() override;
 
  private:
   std::unique_ptr<drive::util::FileStreamMd5Digester> digester_;
 
-  void Respond(const std::string& hash);
+  void RespondWith(const std::string& hash);
 };
 
 // Implements the chrome.fileManagerPrivate.searchFilesByHashes method.
 // TODO(b/883628): Write some tests maybe?
 class FileManagerPrivateSearchFilesByHashesFunction
-    : public LoggedAsyncExtensionFunction {
+    : public LoggedUIThreadExtensionFunction {
  public:
+  FileManagerPrivateSearchFilesByHashesFunction();
+
   DECLARE_EXTENSION_FUNCTION("fileManagerPrivate.searchFilesByHashes",
                              FILEMANAGERPRIVATE_SEARCHFILESBYHASHES)
 
@@ -340,8 +344,8 @@
   ~FileManagerPrivateSearchFilesByHashesFunction() override = default;
 
  private:
-  // ChromeAsyncExtensionFunction overrides.
-  bool RunAsync() override;
+  // ExtensionFunction overrides.
+  ResponseAction Run() override;
 
   // Fallback to walking the filesystem and checking file attributes.
   std::vector<drive::HashAndFilePath> SearchByAttribute(
@@ -355,6 +359,8 @@
   void OnSearchByHashes(const std::set<std::string>& hashes,
                         drive::FileError error,
                         const std::vector<drive::HashAndFilePath>& results);
+
+  const ChromeExtensionFunctionDetails chrome_details_;
 };
 
 // Implements the chrome.fileManagerPrivate.isUMAEnabled method.
@@ -394,7 +400,7 @@
 
 // Implements the chrome.fileManagerPrivate.getDirectorySize method.
 class FileManagerPrivateInternalGetDirectorySizeFunction
-    : public LoggedAsyncExtensionFunction {
+    : public LoggedUIThreadExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("fileManagerPrivateInternal.getDirectorySize",
                              FILEMANAGERPRIVATEINTERNAL_GETDIRECTORYSIZE)
@@ -404,8 +410,8 @@
 
   void OnDirectorySizeRetrieved(int64_t size);
 
-  // ChromeAsyncExtensionFunction overrides
-  bool RunAsync() override;
+  // ExtensionFunction overrides
+  ResponseAction Run() override;
 };
 
 }  // namespace extensions
diff --git a/chrome/browser/chromeos/extensions/permissions_updater_delegate_chromeos_unittest.cc b/chrome/browser/chromeos/extensions/permissions_updater_delegate_chromeos_unittest.cc
index 4cd2d9a..ea0164e 100644
--- a/chrome/browser/chromeos/extensions/permissions_updater_delegate_chromeos_unittest.cc
+++ b/chrome/browser/chromeos/extensions/permissions_updater_delegate_chromeos_unittest.cc
@@ -53,7 +53,8 @@
   URLPatternSet scriptable_hosts({
     URLPattern(URLPattern::SCHEME_ALL, "http://www.wikipedia.com/*")});
   auto permissions = std::make_unique<const PermissionSet>(
-      std::move(apis), std::move(manifest), explicit_hosts, scriptable_hosts);
+      std::move(apis), std::move(manifest), std::move(explicit_hosts),
+      std::move(scriptable_hosts));
   return permissions;
 }
 
diff --git a/chrome/browser/chromeos/file_manager/video_player_browsertest.cc b/chrome/browser/chromeos/file_manager/video_player_browsertest.cc
index 4240f9f..e4fcd0f 100644
--- a/chrome/browser/chromeos/file_manager/video_player_browsertest.cc
+++ b/chrome/browser/chromeos/file_manager/video_player_browsertest.cc
@@ -75,6 +75,11 @@
   StartTest();
 }
 
+IN_PROC_BROWSER_TEST_F(VideoPlayerBrowserTest, OpenMultipleVideosOnDownloads) {
+  set_test_case_name("openMultipleVideosOnDownloads");
+  StartTest();
+}
+
 IN_PROC_BROWSER_TEST_F(VideoPlayerBrowserTest, CheckInitialElements) {
   set_test_case_name("checkInitialElements");
   StartTest();
diff --git a/chrome/browser/chromeos/login/demo_mode/demo_setup_browsertest.cc b/chrome/browser/chromeos/login/demo_mode/demo_setup_browsertest.cc
index dd2dec1..fac7f136 100644
--- a/chrome/browser/chromeos/login/demo_mode/demo_setup_browsertest.cc
+++ b/chrome/browser/chromeos/login/demo_mode/demo_setup_browsertest.cc
@@ -127,7 +127,13 @@
 
 // Waits for js condition to be fulfilled.
 void WaitForJsCondition(const std::string& js_condition) {
-  test::OobeJS().CreateWaiter(js_condition)->Wait();
+  return test::TestConditionWaiter(base::BindRepeating(
+                                       [](const std::string& js_condition) {
+                                         return test::OobeJS().GetBool(
+                                             js_condition);
+                                       },
+                                       js_condition))
+      .Wait();
 }
 
 }  // namespace
diff --git a/chrome/browser/chromeos/login/demo_mode/demo_setup_controller.cc b/chrome/browser/chromeos/login/demo_mode/demo_setup_controller.cc
index a85aeba..9312f560 100644
--- a/chrome/browser/chromeos/login/demo_mode/demo_setup_controller.cc
+++ b/chrome/browser/chromeos/login/demo_mode/demo_setup_controller.cc
@@ -9,6 +9,7 @@
 #include "base/bind.h"
 #include "base/callback.h"
 #include "base/command_line.h"
+#include "base/containers/flat_map.h"
 #include "base/files/file_util.h"
 #include "base/logging.h"
 #include "base/strings/stringprintf.h"
@@ -205,6 +206,24 @@
       ErrorCode::kUnexpectedError, RecoveryMethod::kUnknown, debug_message);
 }
 
+// If the current country requires customization, returns an user email that
+// corresponds to the sub organization the device should be enrolled into.
+// Otherwise, returns an empty string.
+std::string GetSubOrganizationEmail() {
+  if (!base::FeatureList::IsEnabled(
+          switches::kSupportCountryCustomizationInDemoMode)) {
+    return std::string();
+  }
+  // TODO(wzang): Get the country code from Local State, which should be set
+  // during demo setup.
+  const std::string country = "fr";
+  const base::flat_set<std::string> kCountriesWithCustomization(
+      {"dk", "fi", "fr", "nl", "no", "se"});
+  if (kCountriesWithCustomization.contains(country))
+    return "admin-" + country + "@" + DemoSetupController::kDemoModeDomain;
+  return std::string();
+}
+
 }  //  namespace
 
 // static
@@ -441,6 +460,10 @@
     policy::DeviceCloudPolicyManagerChromeOS* policy_manager) {
   if (policy_manager->GetDeviceRequisition() == kDemoRequisition) {
     policy_manager->SetDeviceRequisition(std::string());
+    // If device requisition is |kDemoRequisition|, it means the sub
+    // organization was also set by the demo setup controller, so remove it as
+    // well.
+    policy_manager->SetSubOrganization(std::string());
   }
 }
 
@@ -557,6 +580,7 @@
           ->GetDeviceCloudPolicyManager();
   DCHECK(policy_manager->GetDeviceRequisition().empty());
   policy_manager->SetDeviceRequisition(kDemoRequisition);
+  policy_manager->SetSubOrganization(GetSubOrganizationEmail());
   policy::EnrollmentConfig config;
   config.mode = policy::EnrollmentConfig::MODE_ATTESTATION;
   config.management_domain = DemoSetupController::kDemoModeDomain;
diff --git a/chrome/browser/chromeos/login/demo_mode/demo_setup_test_utils.cc b/chrome/browser/chromeos/login/demo_mode/demo_setup_test_utils.cc
index c97001f..94aa37a 100644
--- a/chrome/browser/chromeos/login/demo_mode/demo_setup_test_utils.cc
+++ b/chrome/browser/chromeos/login/demo_mode/demo_setup_test_utils.cc
@@ -62,7 +62,7 @@
         }
       }));
   EnterpriseEnrollmentHelper::SetEnrollmentHelperMock(std::move(mock));
-};
+}
 
 void SetupMockDemoModeOfflineEnrollmentHelper(DemoModeSetupResult result) {
   std::unique_ptr<EnterpriseEnrollmentHelperMock> mock =
@@ -91,7 +91,7 @@
         }
       }));
   EnterpriseEnrollmentHelper::SetEnrollmentHelperMock(std::move(mock));
-};
+}
 
 bool SetupDummyOfflinePolicyDir(const std::string& account_id,
                                 base::ScopedTempDir* temp_dir) {
diff --git a/chrome/browser/chromeos/login/enable_debugging_browsertest.cc b/chrome/browser/chromeos/login/enable_debugging_browsertest.cc
index 2859f0c5..8be9c73 100644
--- a/chrome/browser/chromeos/login/enable_debugging_browsertest.cc
+++ b/chrome/browser/chromeos/login/enable_debugging_browsertest.cc
@@ -15,6 +15,7 @@
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chromeos/login/login_manager_test.h"
 #include "chrome/browser/chromeos/login/startup_utils.h"
+#include "chrome/browser/chromeos/login/test/js_checker.h"
 #include "chrome/browser/chromeos/login/test/oobe_screen_waiter.h"
 #include "chrome/browser/chromeos/login/ui/login_display_host.h"
 #include "chrome/browser/chromeos/login/ui/webui_login_view.h"
diff --git a/chrome/browser/chromeos/login/eula_browsertest.cc b/chrome/browser/chromeos/login/eula_browsertest.cc
index 8934ce0..8092a60 100644
--- a/chrome/browser/chromeos/login/eula_browsertest.cc
+++ b/chrome/browser/chromeos/login/eula_browsertest.cc
@@ -12,6 +12,7 @@
 #include "base/run_loop.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
+#include "chrome/browser/chromeos/login/test/js_checker.h"
 #include "chrome/browser/chromeos/login/test/oobe_base_test.h"
 #include "chrome/browser/chromeos/login/test/oobe_screen_waiter.h"
 #include "chrome/browser/chromeos/login/ui/login_display_host.h"
diff --git a/chrome/browser/chromeos/login/kiosk_browsertest.cc b/chrome/browser/chromeos/login/kiosk_browsertest.cc
index a3b4d81f..24423be 100644
--- a/chrome/browser/chromeos/login/kiosk_browsertest.cc
+++ b/chrome/browser/chromeos/login/kiosk_browsertest.cc
@@ -25,6 +25,8 @@
 #include "chrome/browser/chromeos/file_manager/fake_disk_mount_manager.h"
 #include "chrome/browser/chromeos/login/app_launch_controller.h"
 #include "chrome/browser/chromeos/login/startup_utils.h"
+#include "chrome/browser/chromeos/login/test/fake_gaia_mixin.h"
+#include "chrome/browser/chromeos/login/test/js_checker.h"
 #include "chrome/browser/chromeos/login/test/oobe_base_test.h"
 #include "chrome/browser/chromeos/login/test/oobe_screen_waiter.h"
 #include "chrome/browser/chromeos/login/test/test_condition_waiter.h"
@@ -62,6 +64,7 @@
 #include "content/public/browser/notification_service.h"
 #include "content/public/browser/web_ui.h"
 #include "content/public/test/browser_test_utils.h"
+#include "content/public/test/test_utils.h"
 #include "extensions/browser/app_window/app_window.h"
 #include "extensions/browser/app_window/app_window_registry.h"
 #include "extensions/browser/app_window/native_app_window.h"
@@ -316,6 +319,17 @@
   DISALLOW_COPY_AND_ASSIGN(ScopedCanConfigureNetwork);
 };
 
+// Waits for js condition to be fulfilled.
+void WaitForJsCondition(const std::string& js_condition) {
+  return test::TestConditionWaiter(base::BindRepeating(
+                                       [](const std::string& js_condition) {
+                                         return test::OobeJS().GetBool(
+                                             js_condition);
+                                       },
+                                       js_condition))
+      .Wait();
+}
+
 class KioskFakeDiskMountManager : public file_manager::FakeDiskMountManager {
  public:
   KioskFakeDiskMountManager() {}
@@ -982,10 +996,8 @@
   LaunchApp(kTestKioskApp, true);
 
   bool new_kiosk_ui = KioskAppMenuHandler::EnableNewKioskUI();
-  test::OobeJS()
-      .CreateWaiter(new_kiosk_ui ? kCheckDiagnosticModeNewAPI
-                                 : kCheckDiagnosticModeOldAPI)
-      ->Wait();
+  WaitForJsCondition(new_kiosk_ui ? kCheckDiagnosticModeNewAPI
+                                  : kCheckDiagnosticModeOldAPI);
 
   std::string diagnosticMode(new_kiosk_ui ?
       kCheckDiagnosticModeNewAPI : kCheckDiagnosticModeOldAPI);
@@ -2135,14 +2147,16 @@
         "https://www.googleapis.com/auth/userinfo.email");
     userinfo_token_info.audience = gaia_urls->oauth2_chrome_client_id();
     userinfo_token_info.email = kTestEnterpriseServiceAccountId;
-    fake_gaia_->IssueOAuthToken(kTestRefreshToken, userinfo_token_info);
+    fake_gaia_.fake_gaia()->IssueOAuthToken(kTestRefreshToken,
+                                            userinfo_token_info);
 
     // The any-api access token for accessing the token minting endpoint.
     FakeGaia::AccessTokenInfo login_token_info;
     login_token_info.token = kTestLoginToken;
     login_token_info.scopes.insert(GaiaConstants::kAnyApiOAuth2Scope);
     login_token_info.audience = gaia_urls->oauth2_chrome_client_id();
-    fake_gaia_->IssueOAuthToken(kTestRefreshToken, login_token_info);
+    fake_gaia_.fake_gaia()->IssueOAuthToken(kTestRefreshToken,
+                                            login_token_info);
 
     // This is the access token requested by the app via the identity API.
     FakeGaia::AccessTokenInfo access_token_info;
@@ -2150,7 +2164,7 @@
     access_token_info.scopes.insert(kTestAppScope);
     access_token_info.audience = kTestClientId;
     access_token_info.email = kTestEnterpriseServiceAccountId;
-    fake_gaia_->IssueOAuthToken(kTestLoginToken, access_token_info);
+    fake_gaia_.fake_gaia()->IssueOAuthToken(kTestLoginToken, access_token_info);
 
     DeviceOAuth2TokenService* token_service =
         DeviceOAuth2TokenServiceFactory::Get();
@@ -2176,6 +2190,8 @@
   }
 
  private:
+  FakeGaiaMixin fake_gaia_{&mixin_host_, embedded_test_server()};
+
   DISALLOW_COPY_AND_ASSIGN(KioskEnterpriseTest);
 };
 
diff --git a/chrome/browser/chromeos/login/login_manager_test.cc b/chrome/browser/chromeos/login/login_manager_test.cc
index db47dbd..6018823f 100644
--- a/chrome/browser/chromeos/login/login_manager_test.cc
+++ b/chrome/browser/chromeos/login/login_manager_test.cc
@@ -12,64 +12,45 @@
 #include "base/command_line.h"
 #include "base/files/file_path.h"
 #include "base/path_service.h"
-#include "base/run_loop.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/chromeos/login/existing_user_controller.h"
 #include "chrome/browser/chromeos/login/session/user_session_manager.h"
 #include "chrome/browser/chromeos/login/session/user_session_manager_test_api.h"
+#include "chrome/browser/chromeos/login/test/fake_gaia_mixin.h"
 #include "chrome/browser/chromeos/login/ui/login_display_host_webui.h"
-#include "chrome/browser/chromeos/login/ui/webui_login_view.h"
 #include "chrome/common/chrome_paths.h"
 #include "chromeos/constants/chromeos_switches.h"
 #include "chromeos/login/auth/key.h"
 #include "chromeos/login/auth/user_context.h"
 #include "components/account_id/account_id.h"
-#include "components/prefs/scoped_user_pref_update.h"
 #include "components/user_manager/known_user.h"
 #include "components/user_manager/user.h"
 #include "components/user_manager/user_manager.h"
 #include "content/public/browser/notification_service.h"
-#include "content/public/browser/web_contents.h"
 #include "content/public/test/test_utils.h"
-#include "google_apis/gaia/gaia_constants.h"
-#include "google_apis/gaia/gaia_switches.h"
-#include "google_apis/gaia/gaia_urls.h"
 #include "net/dns/mock_host_resolver.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
-#include "net/test/embedded_test_server/http_request.h"
-#include "net/test/embedded_test_server/http_response.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace chromeos {
 
 namespace {
 
-constexpr char kGAIAHost[] = "accounts.google.com";
-constexpr char kTestUserinfoToken1[] = "fake-userinfo-token-1";
-constexpr char kTestRefreshToken1[] = "fake-refresh-token-1";
-constexpr char kTestUserinfoToken2[] = "fake-userinfo-token-2";
-constexpr char kTestRefreshToken2[] = "fake-refresh-token-2";
-
 UserContext CreateUserContext(const AccountId& account_id) {
   UserContext user_context(user_manager::UserType::USER_TYPE_REGULAR,
                            account_id);
   user_context.SetKey(Key("password"));
-  if (account_id.GetUserEmail() == LoginManagerTest::kEnterpriseUser1) {
-    user_context.SetRefreshToken(kTestRefreshToken1);
-  } else if (account_id.GetUserEmail() == LoginManagerTest::kEnterpriseUser2) {
-    user_context.SetRefreshToken(kTestRefreshToken2);
+  if (account_id.GetUserEmail() == FakeGaiaMixin::kEnterpriseUser1) {
+    user_context.SetRefreshToken(FakeGaiaMixin::kTestRefreshToken1);
+  } else if (account_id.GetUserEmail() == FakeGaiaMixin::kEnterpriseUser2) {
+    user_context.SetRefreshToken(FakeGaiaMixin::kTestRefreshToken2);
   }
   return user_context;
 }
 
 }  // namespace
 
-constexpr char LoginManagerTest::kEnterpriseUser1[] = "user-1@example.com";
-constexpr char LoginManagerTest::kEnterpriseUser1GaiaId[] = "0000111111";
-constexpr char LoginManagerTest::kEnterpriseUser2[] = "user-2@example.com";
-constexpr char LoginManagerTest::kEnterpriseUser2GaiaId[] = "0000222222";
-
 LoginManagerTest::LoginManagerTest(bool should_launch_browser,
                                    bool should_initialize_webui)
     : should_launch_browser_(should_launch_browser),
@@ -84,18 +65,10 @@
   base::PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir);
   embedded_test_server()->ServeFilesFromDirectory(test_data_dir);
 
-  embedded_test_server()->RegisterRequestHandler(
-      base::Bind(&FakeGaia::HandleRequest, base::Unretained(&fake_gaia_)));
-
   // Don't spin up the IO thread yet since no threads are allowed while
   // spawning sandbox host process. See crbug.com/322732.
   ASSERT_TRUE(embedded_test_server()->InitializeAndListen());
 
-  // Start https wrapper here so that the URLs can be pointed at it in
-  // SetUpCommandLine().
-  ASSERT_TRUE(gaia_https_forwarder_.Initialize(
-      kGAIAHost, embedded_test_server()->base_url()));
-
   MixinBasedInProcessBrowserTest::SetUp();
 }
 
@@ -110,13 +83,6 @@
   command_line->AppendSwitch(chromeos::switches::kLoginManager);
   command_line->AppendSwitch(chromeos::switches::kForceLoginManagerInTests);
 
-  const GURL gaia_url = gaia_https_forwarder_.GetURLForSSLHost(std::string());
-  command_line->AppendSwitchASCII(::switches::kGaiaUrl, gaia_url.spec());
-  command_line->AppendSwitchASCII(::switches::kLsoUrl, gaia_url.spec());
-  command_line->AppendSwitchASCII(::switches::kGoogleApisUrl, gaia_url.spec());
-
-  fake_gaia_.Initialize();
-
   MixinBasedInProcessBrowserTest::SetUpCommandLine(command_line);
 }
 
@@ -128,19 +94,6 @@
   host_resolver()->AddRule("*", "127.0.0.1");
   embedded_test_server()->StartAcceptingConnections();
 
-  FakeGaia::AccessTokenInfo token_info;
-  token_info.scopes.insert(GaiaConstants::kDeviceManagementServiceOAuth);
-  token_info.scopes.insert(GaiaConstants::kOAuthWrapBridgeUserInfoScope);
-  token_info.audience = GaiaUrls::GetInstance()->oauth2_chrome_client_id();
-
-  token_info.token = kTestUserinfoToken1;
-  token_info.email = kEnterpriseUser1;
-  fake_gaia_.IssueOAuthToken(kTestRefreshToken1, token_info);
-
-  token_info.token = kTestUserinfoToken2;
-  token_info.email = kEnterpriseUser2;
-  fake_gaia_.IssueOAuthToken(kTestRefreshToken2, token_info);
-
   if (should_initialize_webui_) {
     content::WindowedNotificationObserver(
         chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE,
diff --git a/chrome/browser/chromeos/login/login_manager_test.h b/chrome/browser/chromeos/login/login_manager_test.h
index 45742d5..a7d3911 100644
--- a/chrome/browser/chromeos/login/login_manager_test.h
+++ b/chrome/browser/chromeos/login/login_manager_test.h
@@ -9,9 +9,6 @@
 
 #include "base/macros.h"
 #include "chrome/browser/chromeos/login/mixin_based_in_process_browser_test.h"
-#include "chrome/browser/chromeos/login/test/https_forwarder.h"
-#include "chrome/browser/chromeos/login/test/js_checker.h"
-#include "google_apis/gaia/fake_gaia.h"
 
 class AccountId;
 
@@ -61,23 +58,6 @@
   // Add user with |user_id| to session.
   void AddUser(const AccountId& user_id);
 
-  // For obviously consumer users (that have e.g. @gmail.com e-mail) policy
-  // fetching code is skipped. This code is executed only for users that may be
-  // enterprise users. Thus if you derive from this class and don't need
-  // policies, please use @gmail.com e-mail for login. But if you need policies
-  // for your test, you must use e-mail addresses that a) have a potentially
-  // enterprise domain and b) have been registered with |fake_gaia_|.
-  // For your convenience, the e-mail addresses for users that have been set up
-  // in this way are provided below.
-  static const char kEnterpriseUser1[];
-  static const char kEnterpriseUser1GaiaId[];
-  static const char kEnterpriseUser2[];
-  static const char kEnterpriseUser2GaiaId[];
-
- protected:
-  FakeGaia fake_gaia_;
-  HTTPSForwarder gaia_https_forwarder_;
-
  private:
   const bool should_launch_browser_;
   const bool should_initialize_webui_;
diff --git a/chrome/browser/chromeos/login/login_ui_browsertest.cc b/chrome/browser/chromeos/login/login_ui_browsertest.cc
index af44f5b..43ffb79a 100644
--- a/chrome/browser/chromeos/login/login_ui_browsertest.cc
+++ b/chrome/browser/chromeos/login/login_ui_browsertest.cc
@@ -11,6 +11,7 @@
 #include "chrome/browser/chromeos/login/screenshot_testing/login_screen_areas.h"
 #include "chrome/browser/chromeos/login/screenshot_testing/screenshot_testing_mixin.h"
 #include "chrome/browser/chromeos/login/startup_utils.h"
+#include "chrome/browser/chromeos/login/test/js_checker.h"
 #include "chrome/browser/chromeos/login/test/oobe_screen_waiter.h"
 #include "chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h"
 #include "chrome/common/pref_names.h"
diff --git a/chrome/browser/chromeos/login/login_ui_keyboard_browsertest.cc b/chrome/browser/chromeos/login/login_ui_keyboard_browsertest.cc
index bd1f661..199241e 100644
--- a/chrome/browser/chromeos/login/login_ui_keyboard_browsertest.cc
+++ b/chrome/browser/chromeos/login/login_ui_keyboard_browsertest.cc
@@ -13,6 +13,7 @@
 #include "chrome/browser/chromeos/language_preferences.h"
 #include "chrome/browser/chromeos/login/login_manager_test.h"
 #include "chrome/browser/chromeos/login/startup_utils.h"
+#include "chrome/browser/chromeos/login/test/js_checker.h"
 #include "chrome/browser/chromeos/login/test/oobe_screen_waiter.h"
 #include "chrome/browser/chromeos/login/ui/login_display_host.h"
 #include "chrome/browser/chromeos/settings/scoped_testing_cros_settings.h"
diff --git a/chrome/browser/chromeos/login/login_utils_browsertest.cc b/chrome/browser/chromeos/login/login_utils_browsertest.cc
index cef0e09..b3541f6 100644
--- a/chrome/browser/chromeos/login/login_utils_browsertest.cc
+++ b/chrome/browser/chromeos/login/login_utils_browsertest.cc
@@ -14,6 +14,7 @@
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/chromeos/login/screens/gaia_view.h"
+#include "chrome/browser/chromeos/login/test/fake_gaia_mixin.h"
 #include "chrome/browser/chromeos/login/test/oobe_base_test.h"
 #include "chrome/browser/chromeos/login/ui/login_display_host.h"
 #include "chrome/browser/chromeos/login/wizard_controller.h"
@@ -66,7 +67,8 @@
 
 class LoginUtilsTest : public OobeBaseTest {
  public:
-  LoginUtilsTest() {}
+  LoginUtilsTest() = default;
+  ~LoginUtilsTest() override = default;
 
   void RunUntilIdle() { base::RunLoop().RunUntilIdle(); }
 
@@ -88,6 +90,8 @@
   }
 
  private:
+  FakeGaiaMixin fake_gaia_{&mixin_host_, embedded_test_server()};
+
   DISALLOW_COPY_AND_ASSIGN(LoginUtilsTest);
 };
 
diff --git a/chrome/browser/chromeos/login/oobe_browsertest.cc b/chrome/browser/chromeos/login/oobe_browsertest.cc
index 06a176e..733678e1 100644
--- a/chrome/browser/chromeos/login/oobe_browsertest.cc
+++ b/chrome/browser/chromeos/login/oobe_browsertest.cc
@@ -10,6 +10,7 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/chromeos/login/screens/gaia_view.h"
+#include "chrome/browser/chromeos/login/test/fake_gaia_mixin.h"
 #include "chrome/browser/chromeos/login/test/oobe_base_test.h"
 #include "chrome/browser/chromeos/login/test/oobe_screen_waiter.h"
 #include "chrome/browser/chromeos/login/ui/login_display_host_webui.h"
@@ -34,8 +35,8 @@
 
 class OobeTest : public OobeBaseTest {
  public:
-  OobeTest() {}
-  ~OobeTest() override {}
+  OobeTest() = default;
+  ~OobeTest() override = default;
 
   void SetUpCommandLine(base::CommandLine* command_line) override {
     command_line->AppendSwitch(switches::kOobeSkipPostLogin);
@@ -64,6 +65,8 @@
   }
 
  private:
+  FakeGaiaMixin fake_gaia_{&mixin_host_, embedded_test_server()};
+
   DISALLOW_COPY_AND_ASSIGN(OobeTest);
 };
 
@@ -77,9 +80,9 @@
   LoginDisplayHost::default_host()
       ->GetOobeUI()
       ->GetGaiaScreenView()
-      ->ShowSigninScreenForTest(OobeBaseTest::kFakeUserEmail,
-                                OobeBaseTest::kFakeUserPassword,
-                                OobeBaseTest::kEmptyUserServices);
+      ->ShowSigninScreenForTest(FakeGaiaMixin::kFakeUserEmail,
+                                FakeGaiaMixin::kFakeUserPassword,
+                                FakeGaiaMixin::kEmptyUserServices);
 
   session_start_waiter.Wait();
 }
diff --git a/chrome/browser/chromeos/login/oobe_interactive_ui_test.cc b/chrome/browser/chromeos/login/oobe_interactive_ui_test.cc
index 1f26d61a..c13b1245 100644
--- a/chrome/browser/chromeos/login/oobe_interactive_ui_test.cc
+++ b/chrome/browser/chromeos/login/oobe_interactive_ui_test.cc
@@ -13,9 +13,10 @@
 #include "chrome/browser/chromeos/login/screens/gaia_view.h"
 #include "chrome/browser/chromeos/login/screens/sync_consent_screen.h"
 #include "chrome/browser/chromeos/login/screens/update_screen.h"
+#include "chrome/browser/chromeos/login/test/fake_gaia_mixin.h"
 #include "chrome/browser/chromeos/login/test/js_checker.h"
 #include "chrome/browser/chromeos/login/test/oobe_base_test.h"
-#include "chrome/browser/chromeos/login/test/test_predicate_waiter.h"
+#include "chrome/browser/chromeos/login/test/test_condition_waiter.h"
 #include "chrome/browser/chromeos/login/ui/login_display_host.h"
 #include "chrome/browser/chromeos/login/wizard_controller.h"
 #include "chrome/browser/lifetime/application_lifetime.h"
@@ -24,10 +25,40 @@
 #include "chromeos/constants/chromeos_switches.h"
 #include "chromeos/dbus/update_engine_client.h"
 #include "content/public/browser/notification_service.h"
+#include "content/public/test/test_utils.h"
 
 namespace chromeos {
 namespace {
 
+enum class JsWaitOptions {
+  kNone,
+  kSatisfyIfOobeDestroyed,
+};
+
+// If |options| is kSatisfyIfOobeDestroyed, we are waiting for the end
+// condition, so it is automatically fullfilled if LoginDisplayHost is already
+// destroyed.
+void WaitForJsCondition(const std::string& js_condition,
+                        JsWaitOptions options) {
+  if (options == JsWaitOptions::kSatisfyIfOobeDestroyed) {
+    return test::TestConditionWaiter(
+               base::BindRepeating(
+                   [](const std::string& js_condition) {
+                     return !LoginDisplayHost::default_host() ||
+                            test::OobeJS().GetBool(js_condition);
+                   },
+                   js_condition))
+        .Wait();
+  }
+  return test::TestConditionWaiter(base::BindRepeating(
+                                       [](const std::string& js_condition) {
+                                         return test::OobeJS().GetBool(
+                                             js_condition);
+                                       },
+                                       js_condition))
+      .Wait();
+}
+
 class ScopedQuickUnlockPrivateGetAuthTokenFunctionObserver {
  public:
   explicit ScopedQuickUnlockPrivateGetAuthTokenFunctionObserver(
@@ -116,7 +147,7 @@
 
     LOG(INFO)
         << "OobeInteractiveUITest: Waiting for LoginDisplayHost to shut down.";
-    test::TestPredicateWaiter(base::BindRepeating([]() {
+    test::TestConditionWaiter(base::BindRepeating([]() {
       return !LoginDisplayHost::default_host();
     })).Wait();
     LOG(INFO) << "OobeInteractiveUITest: LoginDisplayHost is down.";
@@ -128,9 +159,8 @@
         content::NotificationService::AllSources());
     observer.Wait();
 
-    test::OobeJS()
-        .CreateWaiter("Oobe.getInstance().currentScreen.id == 'connect'")
-        ->Wait();
+    WaitForJsCondition("Oobe.getInstance().currentScreen.id == 'connect'",
+                       JsWaitOptions::kNone);
   }
 
   void RunWelcomeScreenChecks() {
@@ -159,10 +189,9 @@
   }
 
   void WaitForNetworkSelectionScreen() {
-    test::OobeJS()
-        .CreateWaiter(
-            "Oobe.getInstance().currentScreen.id == 'network-selection'")
-        ->Wait();
+    WaitForJsCondition(
+        "Oobe.getInstance().currentScreen.id == 'network-selection'",
+        JsWaitOptions::kNone);
     LOG(INFO)
         << "OobeInteractiveUITest: Switched to 'network-selection' screen.";
   }
@@ -180,17 +209,15 @@
   }
 
   void WaitForEulaScreen() {
-    test::OobeJS()
-        .CreateWaiter("Oobe.getInstance().currentScreen.id == 'eula'")
-        ->Wait();
+    WaitForJsCondition("Oobe.getInstance().currentScreen.id == 'eula'",
+                       JsWaitOptions::kNone);
     LOG(INFO) << "OobeInteractiveUITest: Switched to 'eula' screen.";
   }
 
   void RunEulaScreenChecks() {
     // Wait for actual EULA to appear.
-    test::OobeJS()
-        .CreateWaiter("!$('oobe-eula-md').$.eulaDialog.hidden")
-        ->Wait();
+    WaitForJsCondition("!$('oobe-eula-md').$.eulaDialog.hidden",
+                       JsWaitOptions::kNone);
     test::OobeJS().ExpectTrue("!$('oobe-eula-md').$.acceptButton.disabled");
   }
 
@@ -199,10 +226,9 @@
   }
 
   void WaitForUpdateScreen() {
-    test::OobeJS()
-        .CreateWaiter("Oobe.getInstance().currentScreen.id == 'update'")
-        ->Wait();
-    test::OobeJS().CreateWaiter("!$('update').hidden")->Wait();
+    WaitForJsCondition("Oobe.getInstance().currentScreen.id == 'update'",
+                       JsWaitOptions::kNone);
+    WaitForJsCondition("!$('update').hidden", JsWaitOptions::kNone);
 
     LOG(INFO) << "OobeInteractiveUITest: Switched to 'update' screen.";
   }
@@ -217,9 +243,8 @@
   }
 
   void WaitForGaiaSignInScreen() {
-    test::OobeJS()
-        .CreateWaiter("Oobe.getInstance().currentScreen.id == 'gaia-signin'")
-        ->Wait();
+    WaitForJsCondition("Oobe.getInstance().currentScreen.id == 'gaia-signin'",
+                       JsWaitOptions::kNone);
     LOG(INFO) << "OobeInteractiveUITest: Switched to 'gaia-signin' screen.";
   }
 
@@ -227,17 +252,16 @@
     LoginDisplayHost::default_host()
         ->GetOobeUI()
         ->GetGaiaScreenView()
-        ->ShowSigninScreenForTest(OobeBaseTest::kFakeUserEmail,
-                                  OobeBaseTest::kFakeUserPassword,
-                                  OobeBaseTest::kEmptyUserServices);
+        ->ShowSigninScreenForTest(FakeGaiaMixin::kFakeUserEmail,
+                                  FakeGaiaMixin::kFakeUserPassword,
+                                  FakeGaiaMixin::kEmptyUserServices);
     LOG(INFO) << "OobeInteractiveUITest: Logged in.";
   }
 
   void WaitForSyncConsentScreen() {
     LOG(INFO) << "OobeInteractiveUITest: Waiting for 'sync-consent' screen.";
-    test::OobeJS()
-        .CreateWaiter("Oobe.getInstance().currentScreen.id == 'sync-consent'")
-        ->Wait();
+    WaitForJsCondition("Oobe.getInstance().currentScreen.id == 'sync-consent'",
+                       JsWaitOptions::kNone);
   }
 
   void ExitScreenSyncConsent() {
@@ -249,29 +273,27 @@
     screen->OnStateChanged(nullptr);
     LOG(INFO) << "OobeInteractiveUITest: Waiting for 'sync-consent' screen "
                  "to close.";
-    test::CreatePredicateOrOobeDestroyedWaiter(
-        "Oobe.getInstance().currentScreen.id != 'sync-consent'")
-        ->Wait();
+    WaitForJsCondition("Oobe.getInstance().currentScreen.id != 'sync-consent'",
+                       JsWaitOptions::kSatisfyIfOobeDestroyed);
   }
 
   void WaitForFingerprintScreen() {
     LOG(INFO)
         << "OobeInteractiveUITest: Waiting for 'fingerprint-setup' screen.";
-    test::OobeJS()
-        .CreateWaiter(
-            "Oobe.getInstance().currentScreen.id == 'fingerprint-setup'")
-        ->Wait();
+    WaitForJsCondition(
+        "Oobe.getInstance().currentScreen.id == 'fingerprint-setup'",
+        JsWaitOptions::kNone);
     LOG(INFO) << "OobeInteractiveUITest: Waiting for fingerprint setup screen "
                  "to show.";
-    test::OobeJS().CreateWaiter("!$('fingerprint-setup').hidden")->Wait();
+    WaitForJsCondition("!$('fingerprint-setup').hidden", JsWaitOptions::kNone);
     LOG(INFO) << "OobeInteractiveUITest: Waiting for fingerprint setup screen "
                  "to initializes.";
-    test::OobeJS().CreateWaiter("!$('fingerprint-setup-impl').hidden")->Wait();
+    WaitForJsCondition("!$('fingerprint-setup-impl').hidden",
+                       JsWaitOptions::kNone);
     LOG(INFO) << "OobeInteractiveUITest: Waiting for fingerprint setup screen "
                  "to show setupFingerprint.";
-    test::OobeJS()
-        .CreateWaiter("!$('fingerprint-setup-impl').$.setupFingerprint.hidden")
-        ->Wait();
+    WaitForJsCondition("!$('fingerprint-setup-impl').$.setupFingerprint.hidden",
+                       JsWaitOptions::kNone);
   }
 
   void RunFingerprintScreenChecks() {
@@ -285,9 +307,8 @@
         "$('fingerprint-setup-impl').$.setupFingerprint.hidden");
     LOG(INFO) << "OobeInteractiveUITest: Waiting for fingerprint setup "
                  "to switch to placeFinger.";
-    test::OobeJS()
-        .CreateWaiter("!$('fingerprint-setup-impl').$.placeFinger.hidden")
-        ->Wait();
+    WaitForJsCondition("!$('fingerprint-setup-impl').$.placeFinger.hidden",
+                       JsWaitOptions::kNone);
   }
 
   void ExitFingerprintPinSetupScreen() {
@@ -300,16 +321,16 @@
         "$('fingerprint-setup-impl').$.setupFingerprintLater.click()");
     LOG(INFO) << "OobeInteractiveUITest: Waiting for fingerprint setup screen "
                  "to close.";
-    test::CreatePredicateOrOobeDestroyedWaiter(
-        "Oobe.getInstance().currentScreen.id != 'fingerprint-setup'")
-        ->Wait();
+    WaitForJsCondition(
+        "Oobe.getInstance().currentScreen.id !="
+        "'fingerprint-setup'",
+        JsWaitOptions::kSatisfyIfOobeDestroyed);
     LOG(INFO) << "OobeInteractiveUITest: 'fingerprint-setup' screen done.";
   }
 
   void WaitForDiscoverScreen() {
-    test::OobeJS()
-        .CreateWaiter("Oobe.getInstance().currentScreen.id == 'discover'")
-        ->Wait();
+    WaitForJsCondition("Oobe.getInstance().currentScreen.id == 'discover'",
+                       JsWaitOptions::kNone);
     LOG(INFO) << "OobeInteractiveUITest: Switched to 'discover' screen.";
   }
 
@@ -324,7 +345,7 @@
         "setup.hidden");
     EXPECT_TRUE(quick_unlock_private_get_auth_token_password_.has_value());
     EXPECT_EQ(quick_unlock_private_get_auth_token_password_,
-              OobeBaseTest::kFakeUserPassword);
+              FakeGaiaMixin::kFakeUserPassword);
   }
 
   void ExitDiscoverPinSetupScreen() {
@@ -334,16 +355,14 @@
     test::OobeJS().ExecuteAsync(
         "$('discover-impl').root.querySelector('discover-pin-setup-module')."
         "$.setupSkipButton.click()");
-    test::CreatePredicateOrOobeDestroyedWaiter(
-        "Oobe.getInstance().currentScreen.id != 'discover'")
-        ->Wait();
+    WaitForJsCondition("Oobe.getInstance().currentScreen.id != 'discover'",
+                       JsWaitOptions::kSatisfyIfOobeDestroyed);
     LOG(INFO) << "OobeInteractiveUITest: 'discover' screen done.";
   }
 
   void WaitForUserImageScreen() {
-    test::OobeJS()
-        .CreateWaiter("Oobe.getInstance().currentScreen.id == 'user-image'")
-        ->Wait();
+    WaitForJsCondition("Oobe.getInstance().currentScreen.id == 'user-image'",
+                       JsWaitOptions::kNone);
 
     LOG(INFO) << "OobeInteractiveUITest: Switched to 'user-image' screen.";
   }
@@ -354,6 +373,8 @@
   base::Optional<Parameters> params_;
 
  private:
+  FakeGaiaMixin fake_gaia_{&mixin_host_, embedded_test_server()};
+
   DISALLOW_COPY_AND_ASSIGN(OobeInteractiveUITest);
 };
 
diff --git a/chrome/browser/chromeos/login/reset_browsertest.cc b/chrome/browser/chromeos/login/reset_browsertest.cc
index 8cbd332..54eb691 100644
--- a/chrome/browser/chromeos/login/reset_browsertest.cc
+++ b/chrome/browser/chromeos/login/reset_browsertest.cc
@@ -9,6 +9,7 @@
 #include "chrome/browser/chromeos/login/login_manager_test.h"
 #include "chrome/browser/chromeos/login/oobe_screen.h"
 #include "chrome/browser/chromeos/login/startup_utils.h"
+#include "chrome/browser/chromeos/login/test/js_checker.h"
 #include "chrome/browser/chromeos/login/test/oobe_screen_waiter.h"
 #include "chrome/browser/chromeos/login/ui/webui_login_view.h"
 #include "chrome/common/chrome_switches.h"
diff --git a/chrome/browser/chromeos/login/saml/saml_browsertest.cc b/chrome/browser/chromeos/login/saml/saml_browsertest.cc
index 0bd24cd2..ff0d7e6 100644
--- a/chrome/browser/chromeos/login/saml/saml_browsertest.cc
+++ b/chrome/browser/chromeos/login/saml/saml_browsertest.cc
@@ -32,7 +32,9 @@
 #include "chrome/browser/chromeos/login/existing_user_controller.h"
 #include "chrome/browser/chromeos/login/screens/gaia_view.h"
 #include "chrome/browser/chromeos/login/startup_utils.h"
+#include "chrome/browser/chromeos/login/test/fake_gaia_mixin.h"
 #include "chrome/browser/chromeos/login/test/https_forwarder.h"
+#include "chrome/browser/chromeos/login/test/js_checker.h"
 #include "chrome/browser/chromeos/login/test/oobe_base_test.h"
 #include "chrome/browser/chromeos/login/test/oobe_screen_waiter.h"
 #include "chrome/browser/chromeos/login/ui/login_display_host.h"
@@ -327,27 +329,33 @@
 class SamlTest : public OobeBaseTest {
  public:
   SamlTest() : cryptohome_client_(new SecretInterceptingFakeCryptohomeClient) {
-    set_initialize_fake_merge_session(false);
+    fake_gaia_.set_initialize_fake_merge_session(false);
   }
   ~SamlTest() override {}
 
   void SetUpCommandLine(base::CommandLine* command_line) override {
+    OobeBaseTest::SetUpCommandLine(command_line);
+
     command_line->AppendSwitch(switches::kOobeSkipPostLogin);
     command_line->AppendSwitch(
         chromeos::switches::kAllowFailedPolicyFetchForTest);
 
-    const GURL gaia_url = gaia_https_forwarder_.GetURLForSSLHost("");
+    ASSERT_TRUE(saml_https_forwarder_.Initialize(
+        kIdPHost, embedded_test_server()->base_url()));
+    const GURL gaia_url =
+        fake_gaia_.gaia_https_forwarder()->GetURLForSSLHost("");
     const GURL saml_idp_url = saml_https_forwarder_.GetURLForSSLHost("SAML");
     fake_saml_idp_.SetUp(saml_idp_url.path(), gaia_url);
-    fake_gaia_->RegisterSamlUser(kFirstSAMLUserEmail, saml_idp_url);
-    fake_gaia_->RegisterSamlUser(kSecondSAMLUserEmail, saml_idp_url);
-    fake_gaia_->RegisterSamlUser(
+    fake_gaia_.fake_gaia()->RegisterSamlUser(kFirstSAMLUserEmail, saml_idp_url);
+    fake_gaia_.fake_gaia()->RegisterSamlUser(kSecondSAMLUserEmail,
+                                             saml_idp_url);
+    fake_gaia_.fake_gaia()->RegisterSamlUser(
         kHTTPSAMLUserEmail,
         embedded_test_server()->base_url().Resolve("/SAML"));
-    fake_gaia_->RegisterSamlUser(kDifferentDomainSAMLUserEmail, saml_idp_url);
-    fake_gaia_->RegisterSamlDomainRedirectUrl("corp.example.com", saml_idp_url);
-
-    OobeBaseTest::SetUpCommandLine(command_line);
+    fake_gaia_.fake_gaia()->RegisterSamlUser(kDifferentDomainSAMLUserEmail,
+                                             saml_idp_url);
+    fake_gaia_.fake_gaia()->RegisterSamlDomainRedirectUrl("corp.example.com",
+                                                          saml_idp_url);
   }
 
   void SetUpInProcessBrowserTestFixture() override {
@@ -358,7 +366,7 @@
   }
 
   void SetUpOnMainThread() override {
-    fake_gaia_->SetFakeMergeSessionParams(
+    fake_gaia_.fake_gaia()->SetFakeMergeSessionParams(
         kFirstSAMLUserEmail, kTestAuthSIDCookie1, kTestAuthLSIDCookie1);
 
     embedded_test_server()->RegisterRequestHandler(base::Bind(
@@ -434,16 +442,12 @@
   FakeSamlIdp* fake_saml_idp() { return &fake_saml_idp_; }
 
  protected:
-  void InitHttpsForwarders() override {
-    ASSERT_TRUE(saml_https_forwarder_.Initialize(
-        kIdPHost, embedded_test_server()->base_url()));
-    OobeBaseTest::InitHttpsForwarders();
-  }
-
   HTTPSForwarder saml_https_forwarder_;
 
   SecretInterceptingFakeCryptohomeClient* cryptohome_client_;
 
+  FakeGaiaMixin fake_gaia_{&mixin_host_, embedded_test_server()};
+
  private:
   FakeSamlIdp fake_saml_idp_;
 
@@ -696,8 +700,8 @@
   fake_saml_idp()->SetLoginHTMLTemplate("saml_login.html");
   StartSamlAndWaitForIdpPageLoad(kFirstSAMLUserEmail);
 
-  fake_gaia_->SetFakeMergeSessionParams("", kTestAuthSIDCookie1,
-                                        kTestAuthLSIDCookie1);
+  fake_gaia_.fake_gaia()->SetFakeMergeSessionParams("", kTestAuthSIDCookie1,
+                                                    kTestAuthLSIDCookie1);
   SetSignFormField("Email", "fake_user");
   SetSignFormField("Password", "fake_password");
   ExecuteJsInSigninFrame("document.getElementById('Submit').click();");
@@ -910,7 +914,7 @@
   token_info.scopes.insert(GaiaConstants::kOAuthWrapBridgeUserInfoScope);
   token_info.audience = GaiaUrls::GetInstance()->oauth2_chrome_client_id();
   token_info.email = kFirstSAMLUserEmail;
-  fake_gaia_->IssueOAuthToken(kTestRefreshToken, token_info);
+  fake_gaia_.fake_gaia()->IssueOAuthToken(kTestRefreshToken, token_info);
 
   SamlTest::SetUpOnMainThread();
 }
@@ -937,7 +941,8 @@
     content::RenderFrameHost* render_frame_host,
     const GURL& validated_url) {
   const GURL origin = validated_url.GetOrigin();
-  if (origin != gaia_https_forwarder_.GetURLForSSLHost(std::string()) &&
+  if (origin !=
+          fake_gaia_.gaia_https_forwarder()->GetURLForSSLHost(std::string()) &&
       origin != saml_https_forwarder_.GetURLForSSLHost(std::string())) {
     return;
   }
@@ -1262,9 +1267,9 @@
   fake_saml_idp()->SetLoginHTMLTemplate("saml_login.html");
   StartSamlAndWaitForIdpPageLoad(user_id);
 
-  fake_gaia_->SetFakeMergeSessionParams(user_id, auth_sid_cookie,
-                                        auth_lsid_cookie);
-  SetupFakeGaiaForLogin(user_id, "", kTestRefreshToken);
+  fake_gaia_.fake_gaia()->SetFakeMergeSessionParams(user_id, auth_sid_cookie,
+                                                    auth_lsid_cookie);
+  fake_gaia_.SetupFakeGaiaForLogin(user_id, "", kTestRefreshToken);
 
   SetSignFormField("Email", "fake_user");
   SetSignFormField("Password", "fake_password");
@@ -1308,9 +1313,10 @@
 
   WaitForSigninScreen();
 
-  fake_gaia_->SetFakeMergeSessionParams(kNonSAMLUserEmail, kFakeSIDCookie,
-                                        kFakeLSIDCookie);
-  SetupFakeGaiaForLogin(kNonSAMLUserEmail, "", kTestRefreshToken);
+  fake_gaia_.fake_gaia()->SetFakeMergeSessionParams(
+      kNonSAMLUserEmail, FakeGaiaMixin::kFakeSIDCookie,
+      FakeGaiaMixin::kFakeLSIDCookie);
+  fake_gaia_.SetupFakeGaiaForLogin(kNonSAMLUserEmail, "", kTestRefreshToken);
 
   // Log in without SAML.
   LoginDisplayHost::default_host()
@@ -1483,7 +1489,7 @@
 // Disabled due to flakiness, see crbug.com/699228
 IN_PROC_BROWSER_TEST_F(SAMLPolicyTest, DISABLED_SAMLInterstitialNext) {
   fake_saml_idp()->SetLoginHTMLTemplate("saml_login.html");
-  fake_gaia_->SetFakeMergeSessionParams(
+  fake_gaia_.fake_gaia()->SetFakeMergeSessionParams(
       kFirstSAMLUserEmail, kTestAuthSIDCookie1, kTestAuthLSIDCookie1);
   SetLoginBehaviorPolicyToSAMLInterstitial();
   WaitForSigninScreen();
diff --git a/chrome/browser/chromeos/login/screens/mock_update_screen.cc b/chrome/browser/chromeos/login/screens/mock_update_screen.cc
index d2caed8..dfdbb6f5 100644
--- a/chrome/browser/chromeos/login/screens/mock_update_screen.cc
+++ b/chrome/browser/chromeos/login/screens/mock_update_screen.cc
@@ -9,12 +9,18 @@
 
 namespace chromeos {
 
-MockUpdateScreen::MockUpdateScreen(BaseScreenDelegate* base_screen_delegate,
-                                   UpdateView* view)
-    : UpdateScreen(base_screen_delegate, view) {}
+MockUpdateScreen::MockUpdateScreen(
+    BaseScreenDelegate* base_screen_delegate,
+    UpdateView* view,
+    const UpdateScreen::ScreenExitCallback& exit_callback)
+    : UpdateScreen(base_screen_delegate, view, exit_callback) {}
 
 MockUpdateScreen::~MockUpdateScreen() {}
 
+void MockUpdateScreen::RunExit(UpdateScreen::Result result) {
+  ExitUpdate(result);
+}
+
 MockUpdateView::MockUpdateView() {
   EXPECT_CALL(*this, MockBind(_)).Times(AtLeast(1));
 }
diff --git a/chrome/browser/chromeos/login/screens/mock_update_screen.h b/chrome/browser/chromeos/login/screens/mock_update_screen.h
index d4bd6e89..0d7362f4 100644
--- a/chrome/browser/chromeos/login/screens/mock_update_screen.h
+++ b/chrome/browser/chromeos/login/screens/mock_update_screen.h
@@ -14,12 +14,16 @@
 
 class MockUpdateScreen : public UpdateScreen {
  public:
-  MockUpdateScreen(BaseScreenDelegate* base_screen_delegate, UpdateView* view);
+  MockUpdateScreen(BaseScreenDelegate* base_screen_delegate,
+                   UpdateView* view,
+                   const ScreenExitCallback& exit_callback);
   virtual ~MockUpdateScreen();
 
   MOCK_METHOD0(Show, void());
   MOCK_METHOD0(Hide, void());
   MOCK_METHOD0(StartNetworkCheck, void());
+
+  void RunExit(UpdateScreen::Result result);
 };
 
 class MockUpdateView : public UpdateView {
diff --git a/chrome/browser/chromeos/login/screens/screen_exit_code.cc b/chrome/browser/chromeos/login/screens/screen_exit_code.cc
index 17c259c..2469f029 100644
--- a/chrome/browser/chromeos/login/screens/screen_exit_code.cc
+++ b/chrome/browser/chromeos/login/screens/screen_exit_code.cc
@@ -16,13 +16,13 @@
       return "HID_DETECTION_COMPLETED";
     case ScreenExitCode::CONNECTION_FAILED:
       return "CONNECTION_FAILED";
-    case ScreenExitCode::UPDATE_INSTALLED:
+    case ScreenExitCode::DEPRECATED_UPDATE_INSTALLED:
       return "UPDATE_INSTALLED";
-    case ScreenExitCode::UPDATE_NOUPDATE:
+    case ScreenExitCode::DEPRECATED_UPDATE_NOUPDATE:
       return "UPDATE_NOUPDATE";
-    case ScreenExitCode::UPDATE_ERROR_CHECKING_FOR_UPDATE:
+    case ScreenExitCode::DEPRECATED_UPDATE_ERROR_CHECKING_FOR_UPDATE:
       return "UPDATE_ERROR_CHECKING_FOR_UPDATE";
-    case ScreenExitCode::UPDATE_ERROR_UPDATING:
+    case ScreenExitCode::DEPRECATED_UPDATE_ERROR_UPDATING:
       return "UPDATE_ERROR_UPDATING";
     case ScreenExitCode::USER_IMAGE_SELECTED:
       return "USER_IMAGE_SELECTED";
@@ -58,7 +58,7 @@
       return "ARC_TERMS_OF_SERVICE_SKIPPED";
     case ScreenExitCode::ARC_TERMS_OF_SERVICE_ACCEPTED:
       return "ARC_TERMS_OF_SERVICE_ACCEPTED";
-    case ScreenExitCode::UPDATE_ERROR_UPDATING_CRITICAL_UPDATE:
+    case ScreenExitCode::DEPRECATED_UPDATE_ERROR_UPDATING_CRITICAL_UPDATE:
       return "UPDATE_ERROR_UPDATING_CRITICAL_UPDATE";
     case ScreenExitCode::SYNC_CONSENT_FINISHED:
       return "SYNC_CONSENT_FINISHED";
diff --git a/chrome/browser/chromeos/login/screens/screen_exit_code.h b/chrome/browser/chromeos/login/screens/screen_exit_code.h
index b19a2cf..f2c21d4 100644
--- a/chrome/browser/chromeos/login/screens/screen_exit_code.h
+++ b/chrome/browser/chromeos/login/screens/screen_exit_code.h
@@ -24,13 +24,13 @@
   HID_DETECTION_COMPLETED = 1,
   // Connection failed while trying to load a WebPageScreen.
   CONNECTION_FAILED = 2,
-  UPDATE_INSTALLED = 3,
+  DEPRECATED_UPDATE_INSTALLED = 3,
   // This exit code means EITHER that there was no update, OR that there
   // was an update, but that it was not a "critical" update. "Critical" updates
   // are those that have a deadline and require the device to reboot.
-  UPDATE_NOUPDATE = 4,
-  UPDATE_ERROR_CHECKING_FOR_UPDATE = 5,
-  UPDATE_ERROR_UPDATING = 6,
+  DEPRECATED_UPDATE_NOUPDATE = 4,
+  DEPRECATED_UPDATE_ERROR_CHECKING_FOR_UPDATE = 5,
+  DEPRECATED_UPDATE_ERROR_UPDATING = 6,
   USER_IMAGE_SELECTED = 7,
   EULA_ACCEPTED = 8,
   EULA_BACK = 9,
@@ -48,7 +48,7 @@
   ENABLE_DEBUGGING_CANCELED = 22,
   ARC_TERMS_OF_SERVICE_SKIPPED = 23,
   ARC_TERMS_OF_SERVICE_ACCEPTED = 24,
-  UPDATE_ERROR_UPDATING_CRITICAL_UPDATE = 25,
+  DEPRECATED_UPDATE_ERROR_UPDATING_CRITICAL_UPDATE = 25,
   ENCRYPTION_MIGRATION_FINISHED = 26,
   ENCRYPTION_MIGRATION_SKIPPED = 27,
   SYNC_CONSENT_FINISHED = 32,
@@ -68,7 +68,7 @@
   MARKETING_OPT_IN_FINISHED = 46,
   ASSISTANT_OPTIN_FLOW_FINISHED = 47,
   MULTIDEVICE_SETUP_FINISHED = 48,
-  UPDATE_REJECT_OVER_CELLULAR = 49,
+  DEPRECATED_UPDATE_REJECT_OVER_CELLULAR = 49,
   SUPERVISION_TRANSITION_FINISHED = 50,
   EXIT_CODES_COUNT  // not a real code, must be the last
 };
diff --git a/chrome/browser/chromeos/login/screens/update_screen.cc b/chrome/browser/chromeos/login/screens/update_screen.cc
index 17218fb..e86102e 100644
--- a/chrome/browser/chromeos/login/screens/update_screen.cc
+++ b/chrome/browser/chromeos/login/screens/update_screen.cc
@@ -104,10 +104,12 @@
 }
 
 UpdateScreen::UpdateScreen(BaseScreenDelegate* base_screen_delegate,
-                           UpdateView* view)
+                           UpdateView* view,
+                           const ScreenExitCallback& exit_callback)
     : BaseScreen(base_screen_delegate, OobeScreen::SCREEN_OOBE_UPDATE),
       reboot_check_delay_(kWaitForRebootTimeSec),
       view_(view),
+      exit_callback_(exit_callback),
       histogram_helper_(new ErrorScreensHistogramHelper("Update")),
       weak_factory_(this) {
   if (view_)
@@ -145,17 +147,20 @@
   ignore_idle_status_ = ignore_idle_status;
 }
 
-void UpdateScreen::ExitUpdate(ScreenExitCode exit_code) {
+void UpdateScreen::ExitUpdate(Result result) {
   DBusThreadManager::Get()->GetUpdateEngineClient()->RemoveObserver(this);
   network_portal_detector::GetInstance()->RemoveObserver(this);
 
-  Finish(exit_code);
+  exit_callback_.Run(result);
 }
 
 void UpdateScreen::UpdateStatusChanged(
     const UpdateEngineClient::Status& status) {
   if (is_checking_for_update_ &&
-      status.status > UpdateEngineClient::UPDATE_STATUS_CHECKING_FOR_UPDATE) {
+      status.status > UpdateEngineClient::UPDATE_STATUS_CHECKING_FOR_UPDATE &&
+      status.status != UpdateEngineClient::UPDATE_STATUS_ERROR &&
+      status.status !=
+          UpdateEngineClient::UPDATE_STATUS_REPORTING_ERROR_EVENT) {
     is_checking_for_update_ = false;
   }
   if (ignore_idle_status_ &&
@@ -175,7 +180,7 @@
           .SetBoolean(kContextKeyShowEstimatedTimeLeft, false);
       if (!HasCriticalUpdate()) {
         VLOG(1) << "Noncritical update available: " << status.new_version;
-        ExitUpdate(ScreenExitCode::UPDATE_NOUPDATE);
+        ExitUpdate(Result::UPDATE_NOT_REQUIRED);
       } else {
         VLOG(1) << "Critical update available: " << status.new_version;
         GetContextEditor()
@@ -198,7 +203,7 @@
         download_average_speed_ = 0.0;
         if (!HasCriticalUpdate()) {
           VLOG(1) << "Non-critical update available: " << status.new_version;
-          ExitUpdate(ScreenExitCode::UPDATE_NOUPDATE);
+          ExitUpdate(Result::UPDATE_NOT_REQUIRED);
         } else {
           VLOG(1) << "Critical update available: " << status.new_version;
           GetContextEditor()
@@ -239,7 +244,7 @@
                             base::TimeDelta::FromSeconds(reboot_check_delay_),
                             this, &UpdateScreen::OnWaitForRebootTimeElapsed);
       } else {
-        ExitUpdate(ScreenExitCode::UPDATE_NOUPDATE);
+        ExitUpdate(Result::UPDATE_NOT_REQUIRED);
       }
       break;
     case UpdateEngineClient::UPDATE_STATUS_NEED_PERMISSION_TO_UPDATE:
@@ -263,21 +268,19 @@
       // Otherwise, it's possible that the update request has not yet been
       // started.
       if (!ignore_idle_status_)
-        ExitUpdate(ScreenExitCode::UPDATE_NOUPDATE);
+        ExitUpdate(Result::UPDATE_NOT_REQUIRED);
       break;
     case UpdateEngineClient::UPDATE_STATUS_ERROR:
     case UpdateEngineClient::UPDATE_STATUS_REPORTING_ERROR_EVENT:
-      if (is_checking_for_update_) {
-        ExitUpdate(ScreenExitCode::UPDATE_ERROR_CHECKING_FOR_UPDATE);
-      } else if (HasCriticalUpdate()) {
-        ExitUpdate(ScreenExitCode::UPDATE_ERROR_UPDATING_CRITICAL_UPDATE);
+      // Ignore update errors for non-critical updates to prevent blocking the
+      // user from getting to login screen during OOBE if the pending update is
+      // not critical.
+      if (is_checking_for_update_ || !HasCriticalUpdate()) {
+        ExitUpdate(Result::UPDATE_NOT_REQUIRED);
       } else {
-        ExitUpdate(ScreenExitCode::UPDATE_ERROR_UPDATING);
+        ExitUpdate(Result::UPDATE_ERROR);
       }
       break;
-    default:
-      NOTREACHED();
-      break;
   }
 }
 
@@ -335,7 +338,7 @@
 
 void UpdateScreen::CancelUpdate() {
   VLOG(1) << "Forced update cancel";
-  ExitUpdate(ScreenExitCode::UPDATE_NOUPDATE);
+  ExitUpdate(Result::UPDATE_NOT_REQUIRED);
 }
 
 // TODO(jdufault): This should return a pointer. See crbug.com/672142.
@@ -384,7 +387,7 @@
     GetContextEditor()
         .SetBoolean(kContextKeyShowCurtain, true)
         .SetBoolean(kContextKeyRequiresPermissionForCelluar, false);
-    ExitUpdate(ScreenExitCode::UPDATE_REJECT_OVER_CELLULAR);
+    ExitUpdate(Result::UPDATE_ERROR);
   } else {
     BaseScreen::OnUserAction(action_id);
   }
@@ -402,7 +405,7 @@
     GetContextEditor()
         .SetBoolean(kContextKeyShowCurtain, true)
         .SetBoolean(kContextKeyRequiresPermissionForCelluar, false);
-    ExitUpdate(ScreenExitCode::UPDATE_REJECT_OVER_CELLULAR);
+    ExitUpdate(Result::UPDATE_ERROR);
   }
 }
 
@@ -574,7 +577,7 @@
     UpdateEngineClient::UpdateCheckResult result) {
   VLOG(1) << "Callback from RequestUpdateCheck, result " << result;
   if (result != UpdateEngineClient::UPDATE_RESULT_SUCCESS)
-    ExitUpdate(ScreenExitCode::UPDATE_ERROR_CHECKING_FOR_UPDATE);
+    ExitUpdate(Result::UPDATE_NOT_REQUIRED);
 }
 
 void UpdateScreen::OnConnectRequested() {
diff --git a/chrome/browser/chromeos/login/screens/update_screen.h b/chrome/browser/chromeos/login/screens/update_screen.h
index 77378c7..9a4ec98f 100644
--- a/chrome/browser/chromeos/login/screens/update_screen.h
+++ b/chrome/browser/chromeos/login/screens/update_screen.h
@@ -27,13 +27,46 @@
 class UpdateView;
 
 // Controller for the update screen.
+//
+// The screen will request an update availability check from the update engine,
+// and track the update engine progress. When the UpdateScreen finishes, it will
+// run the |exit_callback| with the screen result.
+//
+// If the update engine reports no updates are found, or the available
+// update is not critical, UpdateScreen will report UPDATE_NOT_REQUIRED result.
+//
+// If the update engine reports an error while performing a critical update,
+// UpdateScreen will report UPDATE_ERROR result.
+//
+// If the update engine reports that update is blocked because it would be
+// performed over a metered network, UpdateScreen will request user consent
+// before proceeding with the update. If the user rejects, UpdateScreen will
+// exit and report UPDATE_ERROR result.
+//
+// If update engine finds a critical update, UpdateScreen will wait for the
+// update engine to apply the update, and then request a reboot (if reboot
+// request times out, a message requesting manual reboot will be shown to the
+// user).
+//
+// Before update check request is made, the screen will ensure that the device
+// has network connectivity - if the current network is not online (e.g. behind
+// a protal), it will request an ErrorScreen to be shown. Update check will be
+// delayed until the Internet connectivity is established.
 class UpdateScreen : public BaseScreen,
                      public UpdateEngineClient::Observer,
                      public NetworkPortalDetector::Observer {
  public:
   static UpdateScreen* Get(ScreenManager* manager);
 
-  UpdateScreen(BaseScreenDelegate* base_screen_delegate, UpdateView* view);
+  enum class Result {
+    UPDATE_NOT_REQUIRED,
+    UPDATE_ERROR,
+  };
+
+  using ScreenExitCallback = base::RepeatingCallback<void(Result result)>;
+  UpdateScreen(BaseScreenDelegate* base_screen_delegate,
+               UpdateView* view,
+               const ScreenExitCallback& exit_callback);
   ~UpdateScreen() override;
 
   // Called when the being destroyed. This should call Unbind() on the
@@ -45,9 +78,6 @@
 
   void SetIgnoreIdleStatus(bool ignore_idle_status);
 
-  // Reports update results to the BaseScreenDelegate.
-  void ExitUpdate(ScreenExitCode exit_code);
-
   // UpdateEngineClient::Observer implementation:
   void UpdateStatusChanged(const UpdateEngineClient::Status& status) override;
 
@@ -61,6 +91,14 @@
 
   base::OneShotTimer& GetErrorMessageTimerForTesting();
 
+  void set_exit_callback_for_testing(const ScreenExitCallback& callback) {
+    exit_callback_ = callback;
+  }
+
+ protected:
+  // Reports update results.
+  void ExitUpdate(Result result);
+
  private:
   FRIEND_TEST_ALL_PREFIXES(UpdateScreenTest, TestBasic);
   FRIEND_TEST_ALL_PREFIXES(UpdateScreenTest, TestUpdateAvailable);
@@ -144,6 +182,7 @@
   bool ignore_idle_status_ = true;
 
   UpdateView* view_ = nullptr;
+  ScreenExitCallback exit_callback_;
 
   // Time of the first notification from the downloading stage.
   base::Time download_start_time_;
diff --git a/chrome/browser/chromeos/login/screens/update_screen_browsertest.cc b/chrome/browser/chromeos/login/screens/update_screen_browsertest.cc
index e24797e4..d8dab39 100644
--- a/chrome/browser/chromeos/login/screens/update_screen_browsertest.cc
+++ b/chrome/browser/chromeos/login/screens/update_screen_browsertest.cc
@@ -90,6 +90,8 @@
     ASSERT_EQ(WizardController::default_controller()->current_screen(),
               update_screen_);
     update_screen_->base_screen_delegate_ = mock_base_screen_delegate_.get();
+    update_screen_->set_exit_callback_for_testing(base::BindRepeating(
+        &UpdateScreenTest::HandleScreenExit, base::Unretained(this)));
   }
 
   void TearDownOnMainThread() override {
@@ -134,7 +136,14 @@
   NetworkPortalDetectorTestImpl* network_portal_detector_ =
       nullptr;  // Unowned.
 
+  base::Optional<UpdateScreen::Result> last_screen_result_;
+
  private:
+  void HandleScreenExit(UpdateScreen::Result result) {
+    EXPECT_FALSE(last_screen_result_.has_value());
+    last_screen_result_ = result;
+  }
+
   DISALLOW_COPY_AND_ASSIGN(UpdateScreenTest);
 };
 
@@ -154,10 +163,11 @@
   // UpdateStatusChanged().
   fake_update_engine_client_->set_default_status(status);
 
-  EXPECT_CALL(*mock_base_screen_delegate_,
-              OnExit(ScreenExitCode::UPDATE_NOUPDATE))
-      .Times(1);
   update_screen_->UpdateStatusChanged(status);
+
+  ASSERT_TRUE(last_screen_result_.has_value());
+  EXPECT_EQ(UpdateScreen::Result::UPDATE_NOT_REQUIRED,
+            last_screen_result_.value());
 }
 
 IN_PROC_BROWSER_TEST_F(UpdateScreenTest, TestUpdateAvailable) {
@@ -198,17 +208,16 @@
 
 IN_PROC_BROWSER_TEST_F(UpdateScreenTest, TestErrorIssuingUpdateCheck) {
   // First, cancel the update that is already in progress.
-  EXPECT_CALL(*mock_base_screen_delegate_,
-              OnExit(ScreenExitCode::UPDATE_NOUPDATE))
-      .Times(1);
   update_screen_->CancelUpdate();
+  last_screen_result_.reset();
 
   fake_update_engine_client_->set_update_check_result(
       chromeos::UpdateEngineClient::UPDATE_RESULT_FAILED);
-  EXPECT_CALL(*mock_base_screen_delegate_,
-              OnExit(ScreenExitCode::UPDATE_ERROR_CHECKING_FOR_UPDATE))
-      .Times(1);
   update_screen_->StartNetworkCheck();
+
+  ASSERT_TRUE(last_screen_result_.has_value());
+  EXPECT_EQ(UpdateScreen::Result::UPDATE_NOT_REQUIRED,
+            last_screen_result_.value());
 }
 
 IN_PROC_BROWSER_TEST_F(UpdateScreenTest, TestErrorCheckingForUpdate) {
@@ -218,38 +227,38 @@
   // UpdateStatusChanged().
   fake_update_engine_client_->set_default_status(status);
 
-  EXPECT_CALL(*mock_base_screen_delegate_,
-              OnExit(ScreenExitCode::UPDATE_ERROR_CHECKING_FOR_UPDATE))
-      .Times(1);
   update_screen_->UpdateStatusChanged(status);
+
+  ASSERT_TRUE(last_screen_result_.has_value());
+  EXPECT_EQ(UpdateScreen::Result::UPDATE_NOT_REQUIRED,
+            last_screen_result_.value());
 }
 
 IN_PROC_BROWSER_TEST_F(UpdateScreenTest, TestErrorUpdating) {
   UpdateEngineClient::Status status;
   status.status = UpdateEngineClient::UPDATE_STATUS_UPDATE_AVAILABLE;
   status.new_version = "latest and greatest";
-  // GetLastStatus() will be called via ExitUpdate() called from
-  // UpdateStatusChanged().
   fake_update_engine_client_->set_default_status(status);
 
   update_screen_->UpdateStatusChanged(status);
 
+  ASSERT_TRUE(last_screen_result_.has_value());
+  EXPECT_EQ(UpdateScreen::Result::UPDATE_NOT_REQUIRED,
+            last_screen_result_.value());
+  last_screen_result_.reset();
+
   status.status = UpdateEngineClient::UPDATE_STATUS_ERROR;
-  // GetLastStatus() will be called via ExitUpdate() called from
-  // UpdateStatusChanged().
   fake_update_engine_client_->set_default_status(status);
-
-  EXPECT_CALL(*mock_base_screen_delegate_,
-              OnExit(ScreenExitCode::UPDATE_ERROR_UPDATING))
-      .Times(1);
   update_screen_->UpdateStatusChanged(status);
+
+  ASSERT_TRUE(last_screen_result_.has_value());
+  EXPECT_EQ(UpdateScreen::Result::UPDATE_NOT_REQUIRED,
+            last_screen_result_.value());
 }
 
 IN_PROC_BROWSER_TEST_F(UpdateScreenTest, TestTemproraryOfflineNetwork) {
-  EXPECT_CALL(*mock_base_screen_delegate_,
-              OnExit(ScreenExitCode::UPDATE_NOUPDATE))
-      .Times(1);
   update_screen_->CancelUpdate();
+  last_screen_result_.reset();
 
   // Change ethernet state to portal.
   NetworkPortalDetector::CaptivePortalState portal_state;
@@ -286,18 +295,16 @@
   fake_update_engine_client_->set_update_check_result(
       chromeos::UpdateEngineClient::UPDATE_RESULT_FAILED);
 
-  EXPECT_CALL(*mock_base_screen_delegate_,
-              OnExit(ScreenExitCode::UPDATE_ERROR_CHECKING_FOR_UPDATE))
-      .Times(1);
-
   NotifyPortalDetectionCompleted();
+
+  ASSERT_TRUE(last_screen_result_.has_value());
+  EXPECT_EQ(UpdateScreen::Result::UPDATE_NOT_REQUIRED,
+            last_screen_result_.value());
 }
 
 IN_PROC_BROWSER_TEST_F(UpdateScreenTest, TestTwoOfflineNetworks) {
-  EXPECT_CALL(*mock_base_screen_delegate_,
-              OnExit(ScreenExitCode::UPDATE_NOUPDATE))
-      .Times(1);
   update_screen_->CancelUpdate();
+  last_screen_result_.reset();
 
   // Change ethernet state to portal.
   NetworkPortalDetector::CaptivePortalState portal_state;
@@ -337,16 +344,16 @@
       .Times(1);
 
   NotifyPortalDetectionCompleted();
+
+  EXPECT_FALSE(last_screen_result_.has_value());
 }
 
 IN_PROC_BROWSER_TEST_F(UpdateScreenTest, TestVoidNetwork) {
   SetDefaultNetwork(std::string());
 
   // Cancels pending update request.
-  EXPECT_CALL(*mock_base_screen_delegate_,
-              OnExit(ScreenExitCode::UPDATE_NOUPDATE))
-      .Times(1);
   update_screen_->CancelUpdate();
+  last_screen_result_.reset();
 
   // First portal detection attempt returns NULL network and undefined
   // results, so detection is restarted.
@@ -367,13 +374,12 @@
   EXPECT_CALL(*mock_base_screen_delegate_, ShowErrorScreen()).Times(1);
   base::RunLoop().RunUntilIdle();
   NotifyPortalDetectionCompleted();
+  EXPECT_FALSE(last_screen_result_.has_value());
 }
 
 IN_PROC_BROWSER_TEST_F(UpdateScreenTest, TestAPReselection) {
-  EXPECT_CALL(*mock_base_screen_delegate_,
-              OnExit(ScreenExitCode::UPDATE_NOUPDATE))
-      .Times(1);
   update_screen_->CancelUpdate();
+  last_screen_result_.reset();
 
   // Change ethernet state to portal.
   NetworkPortalDetector::CaptivePortalState portal_state;
@@ -405,12 +411,13 @@
       .Times(1);
   fake_update_engine_client_->set_update_check_result(
       chromeos::UpdateEngineClient::UPDATE_RESULT_FAILED);
-  EXPECT_CALL(*mock_base_screen_delegate_,
-              OnExit(ScreenExitCode::UPDATE_ERROR_CHECKING_FOR_UPDATE))
-      .Times(1);
 
   update_screen_->OnConnectRequested();
   base::RunLoop().RunUntilIdle();
+
+  ASSERT_TRUE(last_screen_result_.has_value());
+  EXPECT_EQ(UpdateScreen::Result::UPDATE_NOT_REQUIRED,
+            last_screen_result_.value());
 }
 
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/screens/update_screen_unittest.cc b/chrome/browser/chromeos/login/screens/update_screen_unittest.cc
index 0f1db6c..4efd922 100644
--- a/chrome/browser/chromeos/login/screens/update_screen_unittest.cc
+++ b/chrome/browser/chromeos/login/screens/update_screen_unittest.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/chromeos/login/screens/update_screen.h"
 
 #include "base/command_line.h"
+#include "base/optional.h"
 #include "base/test/scoped_mock_time_message_loop_task_runner.h"
 #include "chrome/browser/chromeos/login/screens/mock_base_screen_delegate.h"
 #include "chrome/browser/chromeos/login/screens/mock_error_screen.h"
@@ -42,20 +43,23 @@
       const std::unique_ptr<UpdateScreen>& update_screen,
       bool available,
       bool critical) {
-    update_engine_status_.status =
+    UpdateEngineClient::Status update_engine_status;
+    update_engine_status.status =
         UpdateEngineClient::UPDATE_STATUS_CHECKING_FOR_UPDATE;
     fake_update_engine_client_->NotifyObserversThatStatusChanged(
-        update_engine_status_);
+        update_engine_status);
+
     if (critical) {
       ASSERT_TRUE(available) << "Does not make sense for an update to be "
                                 "critical if one is not even available.";
       update_screen->is_ignore_update_deadlines_ = true;
     }
-    update_engine_status_.status =
+    update_engine_status.status =
         available ? UpdateEngineClient::UPDATE_STATUS_UPDATE_AVAILABLE
                   : UpdateEngineClient::UPDATE_STATUS_IDLE;
+
     fake_update_engine_client_->NotifyObserversThatStatusChanged(
-        update_engine_status_);
+        update_engine_status);
   }
 
   // testing::Test:
@@ -82,6 +86,11 @@
     EXPECT_CALL(mock_base_screen_delegate_, GetErrorScreen())
         .Times(AnyNumber())
         .WillRepeatedly(Return(mock_error_screen_.get()));
+
+    update_screen_ = std::make_unique<UpdateScreen>(
+        &mock_base_screen_delegate_, &mock_view_,
+        base::BindRepeating(&UpdateScreenUnitTest::HandleScreenExit,
+                            base::Unretained(this)));
   }
 
   void TearDown() override {
@@ -101,12 +110,18 @@
   MockBaseScreenDelegate mock_base_screen_delegate_;
   MockUpdateView mock_view_;
   MockNetworkErrorView mock_error_view_;
-  UpdateEngineClient::Status update_engine_status_;
   std::unique_ptr<MockErrorScreen> mock_error_screen_;
   MockNetworkPortalDetector* mock_network_portal_detector_;
   FakeUpdateEngineClient* fake_update_engine_client_;
 
+  base::Optional<UpdateScreen::Result> last_screen_result_;
+
  private:
+  void HandleScreenExit(UpdateScreen::Result result) {
+    EXPECT_FALSE(last_screen_result_.has_value());
+    last_screen_result_ = result;
+  }
+
   // Test versions of core browser infrastructure.
   content::TestBrowserThreadBundle threads_;
   ScopedTestingLocalState local_state_;
@@ -115,15 +130,7 @@
 };
 
 TEST_F(UpdateScreenUnitTest, HandlesNoUpdate) {
-  // Set expectation that UpdateScreen will exit successfully
-  // with code UPDATE_NOUPDATE.
-  EXPECT_CALL(mock_base_screen_delegate_,
-              OnExit(ScreenExitCode::UPDATE_NOUPDATE))
-      .Times(1);
-
   // DUT reaches UpdateScreen.
-  update_screen_.reset(
-      new UpdateScreen(&mock_base_screen_delegate_, &mock_view_));
   update_screen_->StartNetworkCheck();
 
   // Verify that the DUT checks for an update.
@@ -132,20 +139,14 @@
   // No updates are available.
   SimulateUpdateAvailable(update_screen_, false /* available */,
                           false /* critical */);
+
+  ASSERT_TRUE(last_screen_result_.has_value());
+  EXPECT_EQ(UpdateScreen::Result::UPDATE_NOT_REQUIRED,
+            last_screen_result_.value());
 }
 
 TEST_F(UpdateScreenUnitTest, HandlesNonCriticalUpdate) {
-  // Set expectation that UpdateScreen will exit successfully
-  // with code UPDATE_NOUPDATE. No, this is not a typo.
-  // UPDATE_NOUPDATE means that either there was no update
-  // or there was a non-critical update.
-  EXPECT_CALL(mock_base_screen_delegate_,
-              OnExit(ScreenExitCode::UPDATE_NOUPDATE))
-      .Times(1);
-
   // DUT reaches UpdateScreen.
-  update_screen_.reset(
-      new UpdateScreen(&mock_base_screen_delegate_, &mock_view_));
   update_screen_->StartNetworkCheck();
 
   // Verify that the DUT checks for an update.
@@ -154,16 +155,14 @@
   // A non-critical update is available.
   SimulateUpdateAvailable(update_screen_, true /* available */,
                           false /* critical */);
+
+  ASSERT_TRUE(last_screen_result_.has_value());
+  EXPECT_EQ(UpdateScreen::Result::UPDATE_NOT_REQUIRED,
+            last_screen_result_.value());
 }
 
 TEST_F(UpdateScreenUnitTest, HandlesCriticalUpdate) {
-  // Set expectation that UpdateScreen does not exit.
-  // This is the case because a critical update mandates reboot.
-  EXPECT_CALL(mock_base_screen_delegate_, OnExit(_)).Times(0);
-
   // DUT reaches UpdateScreen.
-  update_screen_.reset(
-      new UpdateScreen(&mock_base_screen_delegate_, &mock_view_));
   update_screen_->StartNetworkCheck();
 
   // Verify that the DUT checks for an update.
@@ -172,6 +171,31 @@
   // An update is available, and it's critical!
   SimulateUpdateAvailable(update_screen_, true /* available */,
                           true /* critical */);
+
+  EXPECT_FALSE(last_screen_result_.has_value());
+}
+
+TEST_F(UpdateScreenUnitTest, HandleCriticalUpdateError) {
+  // DUT reaches UpdateScreen.
+  update_screen_->StartNetworkCheck();
+
+  // Verify that the DUT checks for an update.
+  EXPECT_EQ(fake_update_engine_client_->request_update_check_call_count(), 1);
+
+  // An update is available, and it's critical!
+  SimulateUpdateAvailable(update_screen_, true /* available */,
+                          true /* critical */);
+
+  EXPECT_FALSE(last_screen_result_.has_value());
+
+  UpdateEngineClient::Status update_engine_status;
+  update_engine_status.status =
+      UpdateEngineClient::UPDATE_STATUS_REPORTING_ERROR_EVENT;
+  fake_update_engine_client_->NotifyObserversThatStatusChanged(
+      update_engine_status);
+
+  ASSERT_TRUE(last_screen_result_.has_value());
+  EXPECT_EQ(UpdateScreen::Result::UPDATE_ERROR, last_screen_result_.value());
 }
 
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/screens/user_selection_screen_browsertest.cc b/chrome/browser/chromeos/login/screens/user_selection_screen_browsertest.cc
index 0f2ec937..1e8375d 100644
--- a/chrome/browser/chromeos/login/screens/user_selection_screen_browsertest.cc
+++ b/chrome/browser/chromeos/login/screens/user_selection_screen_browsertest.cc
@@ -10,6 +10,7 @@
 #include "base/strings/stringprintf.h"
 #include "chrome/browser/chromeos/login/login_manager_test.h"
 #include "chrome/browser/chromeos/login/startup_utils.h"
+#include "chrome/browser/chromeos/login/test/js_checker.h"
 #include "chrome/browser/chromeos/login/test/oobe_screen_waiter.h"
 #include "chrome/browser/chromeos/login/ui/login_display_host.h"
 #include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h"
diff --git a/chrome/browser/chromeos/login/session/chrome_session_manager_browsertest.cc b/chrome/browser/chromeos/login/session/chrome_session_manager_browsertest.cc
index 700750f..3e017678 100644
--- a/chrome/browser/chromeos/login/session/chrome_session_manager_browsertest.cc
+++ b/chrome/browser/chromeos/login/session/chrome_session_manager_browsertest.cc
@@ -14,6 +14,8 @@
 #include "chrome/browser/chromeos/login/screens/gaia_view.h"
 #include "chrome/browser/chromeos/login/session/user_session_manager.h"
 #include "chrome/browser/chromeos/login/startup_utils.h"
+#include "chrome/browser/chromeos/login/test/fake_gaia_mixin.h"
+#include "chrome/browser/chromeos/login/test/oobe_base_test.h"
 #include "chrome/browser/chromeos/login/test/oobe_screen_waiter.h"
 #include "chrome/browser/chromeos/login/ui/login_display_host.h"
 #include "chrome/browser/chromeos/login/ui/user_adding_screen.h"
@@ -73,7 +75,9 @@
 
 class ChromeSessionManagerTest : public LoginManagerTest {
  public:
-  ChromeSessionManagerTest() : LoginManagerTest(true, true) {}
+  ChromeSessionManagerTest()
+      : LoginManagerTest(true, true),
+        fake_gaia_{&mixin_host_, embedded_test_server()} {}
   ~ChromeSessionManagerTest() override {}
 
   // LoginManagerTest:
@@ -91,6 +95,9 @@
     OobeScreenWaiter(OobeScreen::SCREEN_GAIA_SIGNIN).Wait();
   }
 
+ protected:
+  FakeGaiaMixin fake_gaia_;
+
  private:
   DISALLOW_COPY_AND_ASSIGN(ChromeSessionManagerTest);
 };
@@ -103,8 +110,9 @@
   EXPECT_EQ(0u, manager->sessions().size());
 
   // Login via fake gaia to add a new user.
-  fake_gaia_.SetFakeMergeSessionParams(kTestUsers[0].email, "fake_sid",
-                                       "fake_lsid");
+  fake_gaia_.SetupFakeGaiaForLoginManager();
+  fake_gaia_.fake_gaia()->SetFakeMergeSessionParams(kTestUsers[0].email,
+                                                    "fake_sid", "fake_lsid");
   StartSignInScreen();
 
   content::WindowedNotificationObserver session_start_waiter(
@@ -190,8 +198,9 @@
     EXPECT_EQ(0u, manager->sessions().size());
 
     // Login via fake gaia to add a new user.
-    fake_gaia_.SetFakeMergeSessionParams(kTestUsers[0].email, "fake_sid",
-                                         "fake_lsid");
+    fake_gaia_.SetupFakeGaiaForLoginManager();
+    fake_gaia_.fake_gaia()->SetFakeMergeSessionParams(kTestUsers[0].email,
+                                                      "fake_sid", "fake_lsid");
     StartSignInScreen();
 
     content::WindowedNotificationObserver session_start_waiter(
diff --git a/chrome/browser/chromeos/login/signin/device_id_browsertest.cc b/chrome/browser/chromeos/login/signin/device_id_browsertest.cc
index 2207f73..f999231 100644
--- a/chrome/browser/chromeos/login/signin/device_id_browsertest.cc
+++ b/chrome/browser/chromeos/login/signin/device_id_browsertest.cc
@@ -10,6 +10,8 @@
 #include "base/strings/stringprintf.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/chromeos/login/screens/gaia_view.h"
+#include "chrome/browser/chromeos/login/test/fake_gaia_mixin.h"
+#include "chrome/browser/chromeos/login/test/js_checker.h"
 #include "chrome/browser/chromeos/login/test/oobe_base_test.h"
 #include "chrome/browser/chromeos/login/test/oobe_screen_waiter.h"
 #include "chrome/browser/chromeos/login/ui/login_display_host.h"
@@ -24,6 +26,7 @@
 #include "components/user_manager/remove_user_delegate.h"
 #include "components/user_manager/user_manager.h"
 #include "content/public/browser/notification_service.h"
+#include "content/public/test/test_utils.h"
 
 namespace {
 
@@ -72,7 +75,7 @@
   }
 
   std::string GetDeviceIdFromGAIA(const std::string& refresh_token) {
-    return fake_gaia_->GetDeviceIdByRefreshToken(refresh_token);
+    return fake_gaia_.fake_gaia()->GetDeviceIdByRefreshToken(refresh_token);
   }
 
   // Checks that user's device ID retrieved from UserManager and Profile are the
@@ -109,8 +112,8 @@
     FakeGaia::MergeSessionParams params;
     params.email = user_id;
     params.refresh_token = refresh_token;
-    fake_gaia_->UpdateMergeSessionParams(params);
-    fake_gaia_->MapEmailToGaiaId(user_id, gaia_id);
+    fake_gaia_.fake_gaia()->UpdateMergeSessionParams(params);
+    fake_gaia_.fake_gaia()->MapEmailToGaiaId(user_id, gaia_id);
 
     LoginDisplayHost::default_host()
         ->GetOobeUI()
@@ -164,12 +167,13 @@
       EXPECT_TRUE(it.value().GetAsString(&device_id));
       map[it.key()] = device_id;
     }
-    fake_gaia_->SetRefreshTokenToDeviceIdMap(map);
+    fake_gaia_.fake_gaia()->SetRefreshTokenToDeviceIdMap(map);
   }
 
   void SaveRefreshTokenToDeviceIdMap() {
     base::DictionaryValue dictionary;
-    for (const auto& kv : fake_gaia_->refresh_token_to_device_id_map())
+    for (const auto& kv :
+         fake_gaia_.fake_gaia()->refresh_token_to_device_id_map())
       dictionary.SetKey(kv.first, base::Value(kv.second));
     std::string json;
     EXPECT_TRUE(base::JSONWriter::Write(dictionary, &json));
@@ -179,45 +183,51 @@
   }
 
   std::unique_ptr<base::RunLoop> user_removal_loop_;
+  FakeGaiaMixin fake_gaia_{&mixin_host_, embedded_test_server()};
 };
 
 // Add the first user and check that device ID is consistent.
 IN_PROC_BROWSER_TEST_F(DeviceIDTest, PRE_PRE_PRE_PRE_PRE_NewUsers) {
-  SignInOnline(kFakeUserEmail, kFakeUserPassword, kRefreshToken1,
-               kFakeUserGaiaId);
-  CheckDeviceIDIsConsistent(AccountId::FromUserEmail(kFakeUserEmail),
-                            kRefreshToken1);
+  SignInOnline(FakeGaiaMixin::kFakeUserEmail, FakeGaiaMixin::kFakeUserPassword,
+               kRefreshToken1, FakeGaiaMixin::kFakeUserGaiaId);
+  CheckDeviceIDIsConsistent(
+      AccountId::FromUserEmail(FakeGaiaMixin::kFakeUserEmail), kRefreshToken1);
 }
 
 // Authenticate the first user through GAIA and verify that device ID remains
 // the same.
 IN_PROC_BROWSER_TEST_F(DeviceIDTest, PRE_PRE_PRE_PRE_NewUsers) {
   const std::string device_id =
-      GetDeviceId(AccountId::FromUserEmail(kFakeUserEmail));
+      GetDeviceId(AccountId::FromUserEmail(FakeGaiaMixin::kFakeUserEmail));
   EXPECT_FALSE(device_id.empty());
   EXPECT_EQ(device_id, GetDeviceIdFromGAIA(kRefreshToken1));
 
-  SignInOnline(kFakeUserEmail, kFakeUserPassword, kRefreshToken2,
-               kFakeUserGaiaId);
-  CheckDeviceIDIsConsistent(AccountId::FromUserEmail(kFakeUserEmail),
-                            kRefreshToken2);
+  SignInOnline(FakeGaiaMixin::kFakeUserEmail, FakeGaiaMixin::kFakeUserPassword,
+               kRefreshToken2, FakeGaiaMixin::kFakeUserGaiaId);
+  CheckDeviceIDIsConsistent(
+      AccountId::FromUserEmail(FakeGaiaMixin::kFakeUserEmail), kRefreshToken2);
 
-  CHECK_EQ(device_id, GetDeviceId(AccountId::FromUserEmail(kFakeUserEmail)));
+  CHECK_EQ(
+      device_id,
+      GetDeviceId(AccountId::FromUserEmail(FakeGaiaMixin::kFakeUserEmail)));
 }
 
 // Authenticate the first user offline and verify that device ID remains
 // the same.
 IN_PROC_BROWSER_TEST_F(DeviceIDTest, PRE_PRE_PRE_NewUsers) {
   const std::string device_id =
-      GetDeviceId(AccountId::FromUserEmail(kFakeUserEmail));
+      GetDeviceId(AccountId::FromUserEmail(FakeGaiaMixin::kFakeUserEmail));
   EXPECT_FALSE(device_id.empty());
 
-  SignInOffline(kFakeUserEmail, kFakeUserPassword);
-  CheckDeviceIDIsConsistent(AccountId::FromUserEmail(kFakeUserEmail),
-                            kRefreshToken2);
+  SignInOffline(FakeGaiaMixin::kFakeUserEmail,
+                FakeGaiaMixin::kFakeUserPassword);
+  CheckDeviceIDIsConsistent(
+      AccountId::FromUserEmail(FakeGaiaMixin::kFakeUserEmail), kRefreshToken2);
 
   // Verify that device ID remained the same after offline auth.
-  CHECK_EQ(device_id, GetDeviceId(AccountId::FromUserEmail(kFakeUserEmail)));
+  CHECK_EQ(
+      device_id,
+      GetDeviceId(AccountId::FromUserEmail(FakeGaiaMixin::kFakeUserEmail)));
 }
 
 // Add the second user.
@@ -249,36 +259,41 @@
 
 // Set up a user that has a device ID stored in preference only.
 IN_PROC_BROWSER_TEST_F(DeviceIDTest, PRE_Migration) {
-  SignInOnline(kFakeUserEmail, kFakeUserPassword, kRefreshToken1,
-               kFakeUserGaiaId);
+  SignInOnline(FakeGaiaMixin::kFakeUserEmail, FakeGaiaMixin::kFakeUserPassword,
+               kRefreshToken1, FakeGaiaMixin::kFakeUserGaiaId);
 
   // Simulate user that has device ID saved only in preferences (pre-M44).
   PrefService* prefs =
       ProfileHelper::Get()
           ->GetProfileByUser(user_manager::UserManager::Get()->GetActiveUser())
           ->GetPrefs();
-  prefs->SetString(prefs::kGoogleServicesSigninScopedDeviceId,
-                   GetDeviceId(AccountId::FromUserEmail(kFakeUserEmail)));
+  prefs->SetString(
+      prefs::kGoogleServicesSigninScopedDeviceId,
+      GetDeviceId(AccountId::FromUserEmail(FakeGaiaMixin::kFakeUserEmail)));
 
   // Can't use SetKnownUserDeviceId here, because it forbids changing a device
   // ID.
   user_manager::known_user::SetStringPref(
-      AccountId::FromUserEmail(kFakeUserEmail), "device_id", std::string());
+      AccountId::FromUserEmail(FakeGaiaMixin::kFakeUserEmail), "device_id",
+      std::string());
 }
 
 // Tests that after the first sign in the device ID has been moved to the Local
 // state.
 IN_PROC_BROWSER_TEST_F(DeviceIDTest, Migration) {
-  EXPECT_TRUE(GetDeviceId(AccountId::FromUserEmail(kFakeUserEmail)).empty());
-  SignInOffline(kFakeUserEmail, kFakeUserPassword);
-  CheckDeviceIDIsConsistent(AccountId::FromUserEmail(kFakeUserEmail),
-                            kRefreshToken1);
+  EXPECT_TRUE(
+      GetDeviceId(AccountId::FromUserEmail(FakeGaiaMixin::kFakeUserEmail))
+          .empty());
+  SignInOffline(FakeGaiaMixin::kFakeUserEmail,
+                FakeGaiaMixin::kFakeUserPassword);
+  CheckDeviceIDIsConsistent(
+      AccountId::FromUserEmail(FakeGaiaMixin::kFakeUserEmail), kRefreshToken1);
 }
 
 // Set up a user that doesn't have a device ID.
 IN_PROC_BROWSER_TEST_F(DeviceIDTest, PRE_LegacyUsers) {
-  SignInOnline(kFakeUserEmail, kFakeUserPassword, kRefreshToken1,
-               kFakeUserGaiaId);
+  SignInOnline(FakeGaiaMixin::kFakeUserEmail, FakeGaiaMixin::kFakeUserPassword,
+               kRefreshToken1, FakeGaiaMixin::kFakeUserGaiaId);
 
   PrefService* prefs =
       ProfileHelper::Get()
@@ -290,17 +305,21 @@
   // Can't use SetKnownUserDeviceId here, because it forbids changing a device
   // ID.
   user_manager::known_user::SetStringPref(
-      AccountId::FromUserEmail(kFakeUserEmail), "device_id", std::string());
+      AccountId::FromUserEmail(FakeGaiaMixin::kFakeUserEmail), "device_id",
+      std::string());
 }
 
 // Tests that device ID has been generated after the first sign in.
 IN_PROC_BROWSER_TEST_F(DeviceIDTest, LegacyUsers) {
-  EXPECT_TRUE(GetDeviceId(AccountId::FromUserEmail(kFakeUserEmail)).empty());
-  SignInOffline(kFakeUserEmail, kFakeUserPassword);
+  EXPECT_TRUE(
+      GetDeviceId(AccountId::FromUserEmail(FakeGaiaMixin::kFakeUserEmail))
+          .empty());
+  SignInOffline(FakeGaiaMixin::kFakeUserEmail,
+                FakeGaiaMixin::kFakeUserPassword);
   // Last param |auth_code| is empty, because we don't pass a device ID to GAIA
   // in this case.
-  CheckDeviceIDIsConsistent(AccountId::FromUserEmail(kFakeUserEmail),
-                            std::string());
+  CheckDeviceIDIsConsistent(
+      AccountId::FromUserEmail(FakeGaiaMixin::kFakeUserEmail), std::string());
 }
 
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/signin/oauth2_browsertest.cc b/chrome/browser/chromeos/login/signin/oauth2_browsertest.cc
index f0d6f8563..d0c95e7 100644
--- a/chrome/browser/chromeos/login/signin/oauth2_browsertest.cc
+++ b/chrome/browser/chromeos/login/signin/oauth2_browsertest.cc
@@ -22,6 +22,8 @@
 #include "chrome/browser/chromeos/login/signin/oauth2_login_manager_factory.h"
 #include "chrome/browser/chromeos/login/signin_specifics.h"
 #include "chrome/browser/chromeos/login/startup_utils.h"
+#include "chrome/browser/chromeos/login/test/fake_gaia_mixin.h"
+#include "chrome/browser/chromeos/login/test/js_checker.h"
 #include "chrome/browser/chromeos/login/test/oobe_base_test.h"
 #include "chrome/browser/chromeos/login/ui/login_display_host.h"
 #include "chrome/browser/chromeos/login/wizard_controller.h"
@@ -228,7 +230,8 @@
 
 class OAuth2Test : public OobeBaseTest {
  protected:
-  OAuth2Test() {}
+  OAuth2Test() = default;
+  ~OAuth2Test() override = default;
 
   // OobeBaseTest overrides.
   void SetUpCommandLine(base::CommandLine* command_line) override {
@@ -257,15 +260,17 @@
     params.id_token = is_under_advanced_protection
                           ? kTestIdTokenAdvancedProtectionEnabled
                           : kTestIdTokenAdvancedProtectionDisabled;
-    fake_gaia_->SetMergeSessionParams(params);
-    SetupFakeGaiaForLogin(kTestEmail, kTestGaiaId, kTestRefreshToken);
+    fake_gaia_.fake_gaia()->SetMergeSessionParams(params);
+    fake_gaia_.SetupFakeGaiaForLogin(kTestEmail, kTestGaiaId,
+                                     kTestRefreshToken);
   }
 
   void SetupGaiaServerForUnexpiredAccount() {
     FakeGaia::MergeSessionParams params;
     params.email = kTestEmail;
-    fake_gaia_->SetMergeSessionParams(params);
-    SetupFakeGaiaForLogin(kTestEmail, kTestGaiaId, kTestRefreshToken);
+    fake_gaia_.fake_gaia()->SetMergeSessionParams(params);
+    fake_gaia_.SetupFakeGaiaForLogin(kTestEmail, kTestGaiaId,
+                                     kTestRefreshToken);
   }
 
   void SetupGaiaServerForExpiredAccount() {
@@ -273,8 +278,9 @@
     params.gaia_uber_token = kTestGaiaUberToken;
     params.session_sid_cookie = kTestSession2SIDCookie;
     params.session_lsid_cookie = kTestSession2LSIDCookie;
-    fake_gaia_->SetMergeSessionParams(params);
-    SetupFakeGaiaForLogin(kTestEmail, kTestGaiaId, kTestRefreshToken);
+    fake_gaia_.fake_gaia()->SetMergeSessionParams(params);
+    fake_gaia_.SetupFakeGaiaForLogin(kTestEmail, kTestGaiaId,
+                                     kTestRefreshToken);
   }
 
   void LoginAsExistingUser() {
@@ -445,6 +451,8 @@
     request_deferers_[path] = request_deferer;
   }
 
+  FakeGaiaMixin fake_gaia_{&mixin_host_, embedded_test_server()};
+
  private:
   std::map<std::string, RequestDeferrer*> request_deferers_;
 
@@ -653,7 +661,7 @@
   params.auth_code = kTestAuthCode;
   params.refresh_token = kTestRefreshToken;
   params.access_token = kTestAuthLoginAccessToken;
-  fake_gaia_->SetMergeSessionParams(params);
+  fake_gaia_.fake_gaia()->SetMergeSessionParams(params);
 
   // Simulate an online sign-in.
   LoginDisplayHost::default_host()
diff --git a/chrome/browser/chromeos/login/test/fake_gaia_mixin.cc b/chrome/browser/chromeos/login/test/fake_gaia_mixin.cc
new file mode 100644
index 0000000..ec68ef8
--- /dev/null
+++ b/chrome/browser/chromeos/login/test/fake_gaia_mixin.cc
@@ -0,0 +1,107 @@
+// 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/login/test/fake_gaia_mixin.h"
+
+#include "ash/public/cpp/ash_switches.h"
+#include "base/command_line.h"
+#include "google_apis/gaia/gaia_constants.h"
+#include "google_apis/gaia/gaia_switches.h"
+#include "google_apis/gaia/gaia_urls.h"
+#include "net/test/embedded_test_server/http_response.h"
+
+namespace chromeos {
+
+namespace {
+constexpr char kGAIAHost[] = "accounts.google.com";
+constexpr char kTestAllScopeAccessToken[] = "fake-all-scope-token";
+}  // namespace
+
+// static
+const char FakeGaiaMixin::kFakeUserEmail[] = "fake-email@gmail.com";
+const char FakeGaiaMixin::kFakeUserPassword[] = "fake-password";
+const char FakeGaiaMixin::kFakeUserGaiaId[] = "fake-gaiaId";
+const char FakeGaiaMixin::kEmptyUserServices[] = "[]";
+
+const char FakeGaiaMixin::kFakeSIDCookie[] = "fake-SID-cookie";
+const char FakeGaiaMixin::kFakeLSIDCookie[] = "fake-LSID-cookie";
+
+const char FakeGaiaMixin::kEnterpriseUser1[] = "user-1@example.com";
+const char FakeGaiaMixin::kEnterpriseUser1GaiaId[] = "0000111111";
+const char FakeGaiaMixin::kEnterpriseUser2[] = "user-2@example.com";
+const char FakeGaiaMixin::kEnterpriseUser2GaiaId[] = "0000222222";
+
+const char FakeGaiaMixin::kTestUserinfoToken1[] = "fake-userinfo-token-1";
+const char FakeGaiaMixin::kTestRefreshToken1[] = "fake-refresh-token-1";
+const char FakeGaiaMixin::kTestUserinfoToken2[] = "fake-userinfo-token-2";
+const char FakeGaiaMixin::kTestRefreshToken2[] = "fake-refresh-token-2";
+
+FakeGaiaMixin::FakeGaiaMixin(InProcessBrowserTestMixinHost* host,
+                             net::EmbeddedTestServer* embedded_test_server)
+    : InProcessBrowserTestMixin(host),
+      embedded_test_server_(embedded_test_server),
+      fake_gaia_(std::make_unique<FakeGaia>()) {}
+
+FakeGaiaMixin::~FakeGaiaMixin() = default;
+
+void FakeGaiaMixin::SetupFakeGaiaForLogin(const std::string& user_email,
+                                          const std::string& gaia_id,
+                                          const std::string& refresh_token) {
+  if (!gaia_id.empty())
+    fake_gaia_->MapEmailToGaiaId(user_email, gaia_id);
+
+  FakeGaia::AccessTokenInfo token_info;
+  token_info.token = kTestAllScopeAccessToken;
+  token_info.audience = GaiaUrls::GetInstance()->oauth2_chrome_client_id();
+  token_info.email = user_email;
+  token_info.any_scope = true;
+  fake_gaia_->IssueOAuthToken(refresh_token, token_info);
+}
+
+void FakeGaiaMixin::SetupFakeGaiaForLoginManager() {
+  FakeGaia::AccessTokenInfo token_info;
+  token_info.scopes.insert(GaiaConstants::kDeviceManagementServiceOAuth);
+  token_info.scopes.insert(GaiaConstants::kOAuthWrapBridgeUserInfoScope);
+  token_info.audience = GaiaUrls::GetInstance()->oauth2_chrome_client_id();
+
+  token_info.token = kTestUserinfoToken1;
+  token_info.email = kEnterpriseUser1;
+  fake_gaia_->IssueOAuthToken(kTestRefreshToken1, token_info);
+
+  token_info.token = kTestUserinfoToken2;
+  token_info.email = kEnterpriseUser2;
+  fake_gaia_->IssueOAuthToken(kTestRefreshToken2, token_info);
+}
+
+void FakeGaiaMixin::SetUp() {
+  embedded_test_server_->RegisterDefaultHandler(base::BindRepeating(
+      &FakeGaia::HandleRequest, base::Unretained(fake_gaia_.get())));
+}
+
+void FakeGaiaMixin::SetUpCommandLine(base::CommandLine* command_line) {
+  // This needs to happen after the embedded test server is initialized, which
+  // happens after FakeGaiaMixin::SetUp() but before
+  // FakeGaiaMixin::SetUpCommandLine().
+  ASSERT_TRUE(gaia_https_forwarder_.Initialize(
+      kGAIAHost, embedded_test_server_->base_url()));
+
+  GURL gaia_url = gaia_https_forwarder_.GetURLForSSLHost(std::string());
+  command_line->AppendSwitchASCII(::switches::kGaiaUrl, gaia_url.spec());
+  command_line->AppendSwitchASCII(::switches::kLsoUrl, gaia_url.spec());
+  command_line->AppendSwitchASCII(::switches::kGoogleApisUrl, gaia_url.spec());
+  command_line->AppendSwitchASCII(::switches::kOAuthAccountManagerUrl,
+                                  gaia_url.spec());
+}
+
+void FakeGaiaMixin::SetUpOnMainThread() {
+  fake_gaia_->Initialize();
+  fake_gaia_->set_issue_oauth_code_cookie(true);
+
+  if (initialize_fake_merge_session()) {
+    fake_gaia_->SetFakeMergeSessionParams(kFakeUserEmail, kFakeSIDCookie,
+                                          kFakeLSIDCookie);
+  }
+}
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/test/fake_gaia_mixin.h b/chrome/browser/chromeos/login/test/fake_gaia_mixin.h
new file mode 100644
index 0000000..867762f
--- /dev/null
+++ b/chrome/browser/chromeos/login/test/fake_gaia_mixin.h
@@ -0,0 +1,93 @@
+// 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_LOGIN_TEST_FAKE_GAIA_MIXIN_H_
+#define CHROME_BROWSER_CHROMEOS_LOGIN_TEST_FAKE_GAIA_MIXIN_H_
+
+#include <memory>
+#include <string>
+
+#include "base/macros.h"
+#include "chrome/browser/chromeos/login/mixin_based_in_process_browser_test.h"
+#include "chrome/browser/chromeos/login/test/https_forwarder.h"
+#include "google_apis/gaia/fake_gaia.h"
+
+namespace base {
+class CommandLine;
+}
+
+namespace chromeos {
+
+class FakeGaiaMixin : public InProcessBrowserTestMixin {
+ public:
+  // Default fake user email and password, may be used by tests.
+  static const char kFakeUserEmail[];
+  static const char kFakeUserPassword[];
+  static const char kFakeUserGaiaId[];
+  static const char kEmptyUserServices[];
+
+  // FakeGaia is configured to return these cookies for kFakeUserEmail.
+  static const char kFakeSIDCookie[];
+  static const char kFakeLSIDCookie[];
+
+  // For obviously consumer users (that have e.g. @gmail.com e-mail) policy
+  // fetching code is skipped. This code is executed only for users that may be
+  // enterprise users. Thus if you derive from this class and don't need
+  // policies, please use @gmail.com e-mail for login. But if you need policies
+  // for your test, you must use e-mail addresses that a) have a potentially
+  // enterprise domain and b) have been registered with |fake_gaia_|.
+  // For your convenience, the e-mail addresses for users that have been set up
+  // in this way are provided below.
+  static const char kEnterpriseUser1[];
+  static const char kEnterpriseUser1GaiaId[];
+  static const char kEnterpriseUser2[];
+  static const char kEnterpriseUser2GaiaId[];
+
+  static const char kTestUserinfoToken1[];
+  static const char kTestRefreshToken1[];
+  static const char kTestUserinfoToken2[];
+  static const char kTestRefreshToken2[];
+
+  FakeGaiaMixin(InProcessBrowserTestMixinHost* host,
+                net::EmbeddedTestServer* embedded_test_server);
+  ~FakeGaiaMixin() override;
+
+  // Sets up fake gaia for the login code:
+  // - Maps |user_email| to |gaia_id|. If |gaia_id| is empty, |user_email| will
+  //   be mapped to kDefaultGaiaId in FakeGaia;
+  // - Issues a special all-scope access token associated with the test refresh
+  //   token;
+  void SetupFakeGaiaForLogin(const std::string& user_email,
+                             const std::string& gaia_id,
+                             const std::string& refresh_token);
+  void SetupFakeGaiaForLoginManager();
+
+  bool initialize_fake_merge_session() {
+    return initialize_fake_merge_session_;
+  }
+  void set_initialize_fake_merge_session(bool value) {
+    initialize_fake_merge_session_ = value;
+  }
+
+  FakeGaia* fake_gaia() { return fake_gaia_.get(); }
+  HTTPSForwarder* gaia_https_forwarder() { return &gaia_https_forwarder_; }
+
+  // InProcessBrowserTestMixin:
+  void SetUp() override;
+  void SetUpCommandLine(base::CommandLine* command_line) override;
+  void SetUpOnMainThread() override;
+
+ private:
+  net::EmbeddedTestServer* embedded_test_server_;
+  HTTPSForwarder gaia_https_forwarder_;
+
+  std::unique_ptr<FakeGaia> fake_gaia_;
+  bool initialize_fake_merge_session_ = true;
+
+  DISALLOW_COPY_AND_ASSIGN(FakeGaiaMixin);
+};
+
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_LOGIN_TEST_FAKE_GAIA_MIXIN_H_
diff --git a/chrome/browser/chromeos/login/test/js_checker.cc b/chrome/browser/chromeos/login/test/js_checker.cc
index e09224a..d8adbdc 100644
--- a/chrome/browser/chromeos/login/test/js_checker.cc
+++ b/chrome/browser/chromeos/login/test/js_checker.cc
@@ -5,7 +5,6 @@
 #include "chrome/browser/chromeos/login/test/js_checker.h"
 
 #include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/chromeos/login/test/test_predicate_waiter.h"
 #include "chrome/browser/chromeos/login/ui/login_display_host.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/web_contents.h"
@@ -19,11 +18,6 @@
   return "window.domAutomationController.send(" + expression + ")";
 }
 
-bool CheckConditionIfOobeExists(const std::string& js_condition) {
-  return !chromeos::LoginDisplayHost::default_host() ||
-         chromeos::test::OobeJS().GetBool(js_condition);
-}
-
 }  // namespace
 
 namespace chromeos {
@@ -98,13 +92,6 @@
   EXPECT_NE(GetBool(expression), result) << expression;
 }
 
-std::unique_ptr<TestConditionWaiter> JSChecker::CreateWaiter(
-    const std::string& js_condition) {
-  TestPredicateWaiter::PredicateCheck predicate = base::BindRepeating(
-      &JSChecker::GetBool, base::Unretained(this), js_condition);
-  return std::make_unique<TestPredicateWaiter>(predicate);
-}
-
 void JSChecker::GetBoolImpl(const std::string& expression, bool* result) {
   CHECK(web_contents_);
   ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
@@ -138,12 +125,5 @@
       LoginDisplayHost::default_host()->GetOobeWebContents(), script);
 }
 
-std::unique_ptr<TestConditionWaiter> CreatePredicateOrOobeDestroyedWaiter(
-    const std::string& js_condition) {
-  TestPredicateWaiter::PredicateCheck predicate =
-      base::BindRepeating(&CheckConditionIfOobeExists, js_condition);
-  return std::make_unique<TestPredicateWaiter>(predicate);
-}
-
 }  // namespace test
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/test/js_checker.h b/chrome/browser/chromeos/login/test/js_checker.h
index e45c1ce..d18e1bf 100644
--- a/chrome/browser/chromeos/login/test/js_checker.h
+++ b/chrome/browser/chromeos/login/test/js_checker.h
@@ -5,7 +5,6 @@
 #ifndef CHROME_BROWSER_CHROMEOS_LOGIN_TEST_JS_CHECKER_H_
 #define CHROME_BROWSER_CHROMEOS_LOGIN_TEST_JS_CHECKER_H_
 
-#include <memory>
 #include <string>
 
 namespace content {
@@ -15,8 +14,6 @@
 namespace chromeos {
 namespace test {
 
-class TestConditionWaiter;
-
 // Utility class for tests that allows us to evalute and check JavaScript
 // expressions inside given web contents. All calls are made synchronously.
 class JSChecker {
@@ -49,11 +46,6 @@
   void ExpectEQ(const std::string& expression, bool result);
   void ExpectNE(const std::string& expression, bool result);
 
-  // Checks test waiter that would await until |js_condition| evaluates
-  // to true.
-  std::unique_ptr<TestConditionWaiter> CreateWaiter(
-      const std::string& js_condition);
-
   void set_web_contents(content::WebContents* web_contents) {
     web_contents_ = web_contents;
   }
@@ -74,11 +66,6 @@
 void ExecuteOobeJS(const std::string& script);
 void ExecuteOobeJSAsync(const std::string& script);
 
-// Helper method to create waiter over js condition that would also be satisfied
-// if oobe UI is destroyed.
-std::unique_ptr<TestConditionWaiter> CreatePredicateOrOobeDestroyedWaiter(
-    const std::string& js_expression);
-
 }  // namespace test
 }  // namespace chromeos
 
diff --git a/chrome/browser/chromeos/login/test/oobe_base_test.cc b/chrome/browser/chromeos/login/test/oobe_base_test.cc
index 608276b..ee23b45 100644
--- a/chrome/browser/chromeos/login/test/oobe_base_test.cc
+++ b/chrome/browser/chromeos/login/test/oobe_base_test.cc
@@ -16,6 +16,7 @@
 #include "chrome/browser/chromeos/login/session/user_session_manager.h"
 #include "chrome/browser/chromeos/login/session/user_session_manager_test_api.h"
 #include "chrome/browser/chromeos/login/test/https_forwarder.h"
+#include "chrome/browser/chromeos/login/test/js_checker.h"
 #include "chrome/browser/chromeos/login/ui/login_display_host_webui.h"
 #include "chrome/browser/chromeos/login/ui/webui_login_view.h"
 #include "chrome/browser/chromeos/net/network_portal_detector_test_impl.h"
@@ -33,30 +34,15 @@
 #include "content/public/browser/notification_registrar.h"
 #include "content/public/browser/notification_service.h"
 #include "content/public/test/browser_test_utils.h"
+#include "content/public/test/test_utils.h"
 #include "google_apis/gaia/gaia_switches.h"
-#include "google_apis/gaia/gaia_urls.h"
 #include "net/dns/mock_host_resolver.h"
 #include "net/test/embedded_test_server/http_request.h"
 #include "net/test/embedded_test_server/http_response.h"
 
 namespace chromeos {
 
-namespace {
-
-constexpr char kGAIAHost[] = "accounts.google.com";
-constexpr char kTestAllScopeAccessToken[] = "fake-all-scope-token";
-
-}  // namespace
-
-// static
-const char OobeBaseTest::kFakeUserEmail[] = "fake-email@gmail.com";
-const char OobeBaseTest::kFakeUserPassword[] = "fake-password";
-const char OobeBaseTest::kFakeUserGaiaId[] = "fake-gaiaId";
-const char OobeBaseTest::kEmptyUserServices[] = "[]";
-const char OobeBaseTest::kFakeSIDCookie[] = "fake-SID-cookie";
-const char OobeBaseTest::kFakeLSIDCookie[] = "fake-LSID-cookie";
-
-OobeBaseTest::OobeBaseTest() : fake_gaia_(new FakeGaia()) {
+OobeBaseTest::OobeBaseTest() {
   set_exit_when_last_browser_closes(false);
   set_chromeos_user_ = false;
 }
@@ -66,30 +52,24 @@
 void OobeBaseTest::RegisterAdditionalRequestHandlers() {}
 
 void OobeBaseTest::SetUp() {
+  mixin_host_.SetUp();
+
   base::FilePath test_data_dir;
   base::PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir);
   embedded_test_server()->ServeFilesFromDirectory(test_data_dir);
 
   RegisterAdditionalRequestHandlers();
 
-  embedded_test_server()->RegisterRequestHandler(
-      base::Bind(&FakeGaia::HandleRequest, base::Unretained(fake_gaia_.get())));
 
   // Don't spin up the IO thread yet since no threads are allowed while
   // spawning sandbox host process. See crbug.com/322732.
   ASSERT_TRUE(embedded_test_server()->InitializeAndListen());
 
-  // Start https wrapper here so that the URLs can be pointed at it in
-  // SetUpCommandLine().
-  InitHttpsForwarders();
-
-  mixin_host_.SetUp();
   extensions::ExtensionApiTest::SetUp();
 }
 
 void OobeBaseTest::SetUpCommandLine(base::CommandLine* command_line) {
   extensions::ExtensionApiTest::SetUpCommandLine(command_line);
-  mixin_host_.SetUpCommandLine(command_line);
 
   if (ShouldForceWebUiLogin())
     command_line->AppendSwitch(ash::switches::kShowWebUiLogin);
@@ -99,15 +79,7 @@
     command_line->AppendSwitch(::switches::kDisableBackgroundNetworking);
   command_line->AppendSwitchASCII(chromeos::switches::kLoginProfile, "user");
 
-  GURL gaia_url = gaia_https_forwarder_.GetURLForSSLHost(std::string());
-  command_line->AppendSwitchASCII(::switches::kGaiaUrl, gaia_url.spec());
-  command_line->AppendSwitchASCII(::switches::kLsoUrl, gaia_url.spec());
-  command_line->AppendSwitchASCII(::switches::kGoogleApisUrl, gaia_url.spec());
-  command_line->AppendSwitchASCII(::switches::kOAuthAccountManagerUrl,
-                                  gaia_url.spec());
-
-  fake_gaia_->Initialize();
-  fake_gaia_->set_issue_oauth_code_cookie(true);
+  mixin_host_.SetUpCommandLine(command_line);
 }
 
 void OobeBaseTest::SetUpDefaultCommandLine(base::CommandLine* command_line) {
@@ -126,11 +98,6 @@
 }
 
 void OobeBaseTest::SetUpOnMainThread() {
-  if (initialize_fake_merge_session()) {
-    fake_gaia_->SetFakeMergeSessionParams(kFakeUserEmail, kFakeSIDCookie,
-                                          kFakeLSIDCookie);
-  }
-
   // Start the accept thread as the sandbox host process has already been
   // spawned.
   host_resolver()->AddRule("*", "127.0.0.1");
@@ -174,11 +141,6 @@
   extensions::ExtensionApiTest::TearDown();
 }
 
-void OobeBaseTest::InitHttpsForwarders() {
-  ASSERT_TRUE(gaia_https_forwarder_.Initialize(
-      kGAIAHost, embedded_test_server()->base_url()));
-}
-
 bool OobeBaseTest::ShouldForceWebUiLogin() {
   return true;
 }
@@ -302,18 +264,4 @@
   ExecuteJsInSigninFrame(js);
 }
 
-void OobeBaseTest::SetupFakeGaiaForLogin(const std::string& user_email,
-                                         const std::string& gaia_id,
-                                         const std::string& refresh_token) {
-  if (!gaia_id.empty())
-    fake_gaia_->MapEmailToGaiaId(user_email, gaia_id);
-
-  FakeGaia::AccessTokenInfo token_info;
-  token_info.token = kTestAllScopeAccessToken;
-  token_info.audience = GaiaUrls::GetInstance()->oauth2_chrome_client_id();
-  token_info.email = user_email;
-  token_info.any_scope = true;
-  fake_gaia_->IssueOAuthToken(refresh_token, token_info);
-}
-
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/test/oobe_base_test.h b/chrome/browser/chromeos/login/test/oobe_base_test.h
index 0276090d..4f5ddb4 100644
--- a/chrome/browser/chromeos/login/test/oobe_base_test.h
+++ b/chrome/browser/chromeos/login/test/oobe_base_test.h
@@ -7,17 +7,9 @@
 
 #include <string>
 
-#include "base/callback.h"
-#include "base/command_line.h"
 #include "base/macros.h"
 #include "chrome/browser/chromeos/login/mixin_based_in_process_browser_test.h"
-#include "chrome/browser/chromeos/login/test/https_forwarder.h"
-#include "chrome/browser/chromeos/login/test/js_checker.h"
 #include "chrome/browser/extensions/extension_apitest.h"
-#include "chrome/test/base/in_process_browser_test.h"
-#include "content/public/test/test_utils.h"
-#include "google_apis/gaia/fake_gaia.h"
-#include "net/test/embedded_test_server/embedded_test_server.h"
 
 namespace content {
 class WebUI;
@@ -31,17 +23,6 @@
 // Base class for OOBE, login, SAML and Kiosk tests.
 class OobeBaseTest : public extensions::ExtensionApiTest {
  public:
-  // Default fake user email and password, may be used by tests.
-
-  static const char kFakeUserEmail[];
-  static const char kFakeUserPassword[];
-  static const char kFakeUserGaiaId[];
-  static const char kEmptyUserServices[];
-
-  // FakeGaia is configured to return these cookies for kFakeUserEmail.
-  static const char kFakeSIDCookie[];
-  static const char kFakeLSIDCookie[];
-
   OobeBaseTest();
   ~OobeBaseTest() override;
 
@@ -50,7 +31,7 @@
   virtual void RegisterAdditionalRequestHandlers();
 
  protected:
-  // InProcessBrowserTest:
+  // extensions::ExtensionApiTest:
   void SetUp() override;
   void SetUpCommandLine(base::CommandLine* command_line) override;
   void SetUpDefaultCommandLine(base::CommandLine* command_line) override;
@@ -60,8 +41,6 @@
   void TearDownInProcessBrowserTestFixture() override;
   void TearDown() override;
 
-  virtual void InitHttpsForwarders();
-
   // If this returns true (default), the |ash::switches::kShowWebUiLogin|
   // command-line switch is passed to force the Web Ui Login.
   // If this returns false, the switch is omitted so the views-based login may
@@ -77,13 +56,6 @@
   base::Closure SimulateNetworkOnlineClosure();
   base::Closure SimulateNetworkPortalClosure();
 
-  bool initialize_fake_merge_session() {
-    return initialize_fake_merge_session_;
-  }
-  void set_initialize_fake_merge_session(bool value) {
-    initialize_fake_merge_session_ = value;
-  }
-
   // Returns chrome://oobe WebUI.
   content::WebUI* GetLoginUI();
 
@@ -97,18 +69,8 @@
   void SetSignFormField(const std::string& field_id,
                         const std::string& field_value);
 
-  // Sets up fake gaia for the login code:
-  // - Maps |user_email| to |gaia_id|. If |gaia_id| is empty, |user_email| will
-  //   be mapped to kDefaultGaiaId in FakeGaia;
-  // - Issues a special all-scope access token associated with the test refresh
-  //   token;
-  void SetupFakeGaiaForLogin(const std::string& user_email,
-                             const std::string& gaia_id,
-                             const std::string& refresh_token);
-
   InProcessBrowserTestMixinHost mixin_host_;
 
-  std::unique_ptr<FakeGaia> fake_gaia_;
   NetworkPortalDetectorTestImpl* network_portal_detector_ = nullptr;
 
   // Whether to use background networking. Note this is only effective when it
@@ -117,9 +79,7 @@
 
   std::unique_ptr<content::WindowedNotificationObserver>
       login_screen_load_observer_;
-  HTTPSForwarder gaia_https_forwarder_;
   std::string gaia_frame_parent_ = "signin-frame";
-  bool initialize_fake_merge_session_ = true;
 
   DISALLOW_COPY_AND_ASSIGN(OobeBaseTest);
 };
diff --git a/chrome/browser/chromeos/login/test/oobe_screen_waiter.h b/chrome/browser/chromeos/login/test/oobe_screen_waiter.h
index 8dbaec2f..e9c8643d 100644
--- a/chrome/browser/chromeos/login/test/oobe_screen_waiter.h
+++ b/chrome/browser/chromeos/login/test/oobe_screen_waiter.h
@@ -7,7 +7,6 @@
 
 #include "base/macros.h"
 #include "chrome/browser/chromeos/login/oobe_screen.h"
-#include "chrome/browser/chromeos/login/test/test_condition_waiter.h"
 #include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h"
 
 namespace content {
@@ -17,12 +16,13 @@
 namespace chromeos {
 
 // A waiter that blocks until the expected oobe screen is reached.
-class OobeScreenWaiter : public OobeUI::Observer,
-                         public test::TestConditionWaiter {
+class OobeScreenWaiter : public OobeUI::Observer {
  public:
   explicit OobeScreenWaiter(OobeScreen expected_screen);
   ~OobeScreenWaiter() override;
 
+  // Run message loop to wait for the expected_screen to become current screen.
+  void Wait();
 
   // Run message loop to wait for the expected_screen to be fully initialized.
   void WaitForInitialization();
@@ -37,9 +37,6 @@
                               OobeScreen new_screen) override;
   void OnScreenInitialized(OobeScreen screen) override;
 
-  // TestConditionWaiter;
-  void Wait() override;
-
  private:
   OobeUI* GetOobeUI();
 
diff --git a/chrome/browser/chromeos/login/test/test_predicate_waiter.cc b/chrome/browser/chromeos/login/test/test_condition_waiter.cc
similarity index 60%
rename from chrome/browser/chromeos/login/test/test_predicate_waiter.cc
rename to chrome/browser/chromeos/login/test/test_condition_waiter.cc
index eaef5f66..834ceff 100644
--- a/chrome/browser/chromeos/login/test/test_predicate_waiter.cc
+++ b/chrome/browser/chromeos/login/test/test_condition_waiter.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/chromeos/login/test/test_predicate_waiter.h"
+#include "chrome/browser/chromeos/login/test/test_condition_waiter.h"
 
 #include "base/callback.h"
 
@@ -10,27 +10,27 @@
 namespace test {
 namespace {
 
-const base::TimeDelta kPredicateCheckFrequency =
+const base::TimeDelta kConditionCheckFrequency =
     base::TimeDelta::FromMilliseconds(200);
 
 }  // anonymous namespace
 
-TestPredicateWaiter::TestPredicateWaiter(
+TestConditionWaiter::TestConditionWaiter(
     const base::RepeatingCallback<bool(void)>& is_fulfilled)
     : is_fulfilled_(is_fulfilled) {}
 
-TestPredicateWaiter::~TestPredicateWaiter() = default;
+TestConditionWaiter::~TestConditionWaiter() = default;
 
-void TestPredicateWaiter::Wait() {
+void TestConditionWaiter::Wait() {
   if (is_fulfilled_.Run())
     return;
 
-  timer_.Start(FROM_HERE, kPredicateCheckFrequency, this,
-               &TestPredicateWaiter::CheckPredicate);
+  timer_.Start(FROM_HERE, kConditionCheckFrequency, this,
+               &TestConditionWaiter::CheckCondition);
   run_loop_.Run();
 }
 
-void TestPredicateWaiter::CheckPredicate() {
+void TestConditionWaiter::CheckCondition() {
   if (is_fulfilled_.Run()) {
     run_loop_.Quit();
     timer_.Stop();
diff --git a/chrome/browser/chromeos/login/test/test_condition_waiter.h b/chrome/browser/chromeos/login/test/test_condition_waiter.h
index 8f2b199d..03d6dfc 100644
--- a/chrome/browser/chromeos/login/test/test_condition_waiter.h
+++ b/chrome/browser/chromeos/login/test/test_condition_waiter.h
@@ -1,23 +1,34 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
+// 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_LOGIN_TEST_TEST_CONDITION_WAITER_H_
 #define CHROME_BROWSER_CHROMEOS_LOGIN_TEST_TEST_CONDITION_WAITER_H_
 
-#include "base/macros.h"
+#include "base/callback_forward.h"
+#include "base/run_loop.h"
+#include "base/timer/timer.h"
 
 namespace chromeos {
 namespace test {
 
-// Generic class for conditions that can be awaited it test.
+// Waits for condition to be fulfilled.
 class TestConditionWaiter {
  public:
-  virtual ~TestConditionWaiter() = default;
-  virtual void Wait() = 0;
+  using ConditionCheck = base::RepeatingCallback<bool(void)>;
 
- protected:
-  TestConditionWaiter() = default;
+  explicit TestConditionWaiter(const ConditionCheck& is_fulfilled);
+  ~TestConditionWaiter();
+
+  void Wait();
+
+ private:
+  void CheckCondition();
+
+  const ConditionCheck is_fulfilled_;
+
+  base::RepeatingTimer timer_;
+  base::RunLoop run_loop_;
 
   DISALLOW_COPY_AND_ASSIGN(TestConditionWaiter);
 };
diff --git a/chrome/browser/chromeos/login/test/test_predicate_waiter.h b/chrome/browser/chromeos/login/test/test_predicate_waiter.h
deleted file mode 100644
index 24663e8..0000000
--- a/chrome/browser/chromeos/login/test/test_predicate_waiter.h
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_TEST_TEST_PREDICATE_WAITER_H_
-#define CHROME_BROWSER_CHROMEOS_LOGIN_TEST_TEST_PREDICATE_WAITER_H_
-
-#include "base/callback_forward.h"
-#include "base/run_loop.h"
-#include "base/timer/timer.h"
-#include "chrome/browser/chromeos/login/test/test_condition_waiter.h"
-
-namespace chromeos {
-namespace test {
-
-// Waits for predicate to be fulfilled.
-class TestPredicateWaiter : public TestConditionWaiter {
- public:
-  using PredicateCheck = base::RepeatingCallback<bool(void)>;
-
-  explicit TestPredicateWaiter(const PredicateCheck& is_fulfilled);
-  ~TestPredicateWaiter() override;
-
-  // TestConditionWaiter
-  void Wait() override;
-
- private:
-  void CheckPredicate();
-
-  const PredicateCheck is_fulfilled_;
-
-  base::RepeatingTimer timer_;
-  base::RunLoop run_loop_;
-
-  DISALLOW_COPY_AND_ASSIGN(TestPredicateWaiter);
-};
-
-}  // namespace test
-}  // namespace chromeos
-
-#endif  // CHROME_BROWSER_CHROMEOS_LOGIN_TEST_TEST_PREDICATE_WAITER_H_
diff --git a/chrome/browser/chromeos/login/user_board_view_mojo.h b/chrome/browser/chromeos/login/user_board_view_mojo.h
index 7f945d6..0fb0873 100644
--- a/chrome/browser/chromeos/login/user_board_view_mojo.h
+++ b/chrome/browser/chromeos/login/user_board_view_mojo.h
@@ -36,8 +36,8 @@
   void SetAuthType(const AccountId& account_id,
                    proximity_auth::mojom::AuthType auth_type,
                    const base::string16& initial_value) override;
-  void Bind(UserSelectionScreen* screen) override{};
-  void Unbind() override{};
+  void Bind(UserSelectionScreen* screen) override {}
+  void Unbind() override {}
   base::WeakPtr<UserBoardView> GetWeakPtr() override;
 
  private:
diff --git a/chrome/browser/chromeos/login/users/avatar/user_image_manager_browsertest.cc b/chrome/browser/chromeos/login/users/avatar/user_image_manager_browsertest.cc
index 4515901..1368b07 100644
--- a/chrome/browser/chromeos/login/users/avatar/user_image_manager_browsertest.cc
+++ b/chrome/browser/chromeos/login/users/avatar/user_image_manager_browsertest.cc
@@ -27,6 +27,7 @@
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chromeos/login/login_manager_test.h"
 #include "chrome/browser/chromeos/login/startup_utils.h"
+#include "chrome/browser/chromeos/login/test/fake_gaia_mixin.h"
 #include "chrome/browser/chromeos/login/users/avatar/user_image_manager_impl.h"
 #include "chrome/browser/chromeos/login/users/avatar/user_image_manager_test_util.h"
 #include "chrome/browser/chromeos/login/users/chrome_user_manager.h"
@@ -209,8 +210,9 @@
     token_info.audience = GaiaUrls::GetInstance()->oauth2_chrome_client_id();
     token_info.token = kRandomTokenStrForTesting;
     token_info.email = test_account_id1_.GetUserEmail();
-    fake_gaia_.IssueOAuthToken(kRandomTokenStrForTesting, token_info);
-    fake_gaia_.MapEmailToGaiaId(
+    fake_gaia_.fake_gaia()->IssueOAuthToken(kRandomTokenStrForTesting,
+                                            token_info);
+    fake_gaia_.fake_gaia()->MapEmailToGaiaId(
         kTestUserEmail1, identity::GetTestGaiaIdForEmail(kTestUserEmail1));
   }
 
@@ -339,12 +341,14 @@
       kTestUserEmail2,
       identity::GetTestGaiaIdForEmail(kTestUserEmail2));
   const AccountId enterprise_account_id_ = AccountId::FromUserEmailGaiaId(
-      kEnterpriseUser1,
-      identity::GetTestGaiaIdForEmail(kEnterpriseUser1));
+      FakeGaiaMixin::kEnterpriseUser1,
+      identity::GetTestGaiaIdForEmail(FakeGaiaMixin::kEnterpriseUser1));
   const cryptohome::AccountIdentifier cryptohome_id_ =
       cryptohome::CreateAccountIdentifierFromAccountId(enterprise_account_id_);
 
  private:
+  FakeGaiaMixin fake_gaia_{&mixin_host_, embedded_test_server()};
+
   DISALLOW_COPY_AND_ASSIGN(UserImageManagerTest);
 };
 
diff --git a/chrome/browser/chromeos/login/users/wallpaper_policy_browsertest.cc b/chrome/browser/chromeos/login/users/wallpaper_policy_browsertest.cc
index 7667eff..8f785ecd 100644
--- a/chrome/browser/chromeos/login/users/wallpaper_policy_browsertest.cc
+++ b/chrome/browser/chromeos/login/users/wallpaper_policy_browsertest.cc
@@ -23,6 +23,7 @@
 #include "base/threading/thread_restrictions.h"
 #include "chrome/browser/chromeos/login/login_manager_test.h"
 #include "chrome/browser/chromeos/login/startup_utils.h"
+#include "chrome/browser/chromeos/login/test/fake_gaia_mixin.h"
 #include "chrome/browser/chromeos/login/ui/login_display_host.h"
 #include "chrome/browser/chromeos/ownership/owner_settings_service_chromeos_factory.h"
 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
@@ -135,17 +136,14 @@
  protected:
   WallpaperPolicyTest()
       : LoginManagerTest(true, true),
-        wallpaper_change_count_(0),
         owner_key_util_(new ownership::MockOwnerKeyUtil()),
-        fake_session_manager_client_(new FakeSessionManagerClient),
-        observer_binding_(this),
-        weak_ptr_factory_(this) {
-    testUsers_.push_back(AccountId::FromUserEmailGaiaId(
-        LoginManagerTest::kEnterpriseUser1,
-        LoginManagerTest::kEnterpriseUser1GaiaId));
-    testUsers_.push_back(AccountId::FromUserEmailGaiaId(
-        LoginManagerTest::kEnterpriseUser2,
-        LoginManagerTest::kEnterpriseUser2GaiaId));
+        fake_session_manager_client_(new FakeSessionManagerClient) {
+    testUsers_.push_back(
+        AccountId::FromUserEmailGaiaId(FakeGaiaMixin::kEnterpriseUser1,
+                                       FakeGaiaMixin::kEnterpriseUser1GaiaId));
+    testUsers_.push_back(
+        AccountId::FromUserEmailGaiaId(FakeGaiaMixin::kEnterpriseUser2,
+                                       FakeGaiaMixin::kEnterpriseUser2GaiaId));
   }
 
   std::unique_ptr<policy::UserPolicyBuilder> GetUserPolicyBuilder(
@@ -331,21 +329,23 @@
 
   base::FilePath test_data_dir_;
   std::unique_ptr<base::RunLoop> run_loop_;
-  int wallpaper_change_count_;
+  int wallpaper_change_count_ = 0;
   std::unique_ptr<policy::UserPolicyBuilder> user_policy_builders_[2];
   policy::DevicePolicyBuilder device_policy_;
   scoped_refptr<ownership::MockOwnerKeyUtil> owner_key_util_;
   FakeSessionManagerClient* fake_session_manager_client_;
   std::vector<AccountId> testUsers_;
+  FakeGaiaMixin fake_gaia_{&mixin_host_, embedded_test_server()};
 
  private:
   // The binding this instance uses to implement ash::mojom::WallpaperObserver.
-  mojo::AssociatedBinding<ash::mojom::WallpaperObserver> observer_binding_;
+  mojo::AssociatedBinding<ash::mojom::WallpaperObserver> observer_binding_{
+      this};
 
   // The average ARGB color of the current wallpaper.
   base::Optional<SkColor> average_color_;
 
-  base::WeakPtrFactory<WallpaperPolicyTest> weak_ptr_factory_;
+  base::WeakPtrFactory<WallpaperPolicyTest> weak_ptr_factory_{this};
 
   DISALLOW_COPY_AND_ASSIGN(WallpaperPolicyTest);
 };
diff --git a/chrome/browser/chromeos/login/webview_login_browsertest.cc b/chrome/browser/chromeos/login/webview_login_browsertest.cc
index e6c54a36..7b6e494 100644
--- a/chrome/browser/chromeos/login/webview_login_browsertest.cc
+++ b/chrome/browser/chromeos/login/webview_login_browsertest.cc
@@ -19,6 +19,8 @@
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/chromeos/login/helper.h"
 #include "chrome/browser/chromeos/login/signin_partition_manager.h"
+#include "chrome/browser/chromeos/login/test/fake_gaia_mixin.h"
+#include "chrome/browser/chromeos/login/test/js_checker.h"
 #include "chrome/browser/chromeos/login/test/oobe_base_test.h"
 #include "chrome/browser/chromeos/login/test/oobe_screen_waiter.h"
 #include "chrome/browser/chromeos/login/ui/login_display_host.h"
@@ -164,8 +166,8 @@
 
 class WebviewLoginTest : public OobeBaseTest {
  public:
-  WebviewLoginTest() {}
-  ~WebviewLoginTest() override {}
+  WebviewLoginTest() = default;
+  ~WebviewLoginTest() override = default;
 
   void SetUpCommandLine(base::CommandLine* command_line) override {
     command_line->AppendSwitch(switches::kOobeSkipPostLogin);
@@ -234,6 +236,7 @@
 
  protected:
   chromeos::ScopedTestingCrosSettings scoped_testing_cros_settings_;
+  FakeGaiaMixin fake_gaia_{&mixin_host_, embedded_test_server()};
 
  private:
   DISALLOW_COPY_AND_ASSIGN(WebviewLoginTest);
@@ -245,7 +248,7 @@
 
   ExpectIdentifierPage();
 
-  SetSignFormField("identifier", OobeBaseTest::kFakeUserEmail);
+  SetSignFormField("identifier", FakeGaiaMixin::kFakeUserEmail);
   ClickNext();
   WaitForGaiaPageBackButtonUpdate();
   ExpectPasswordPage();
@@ -255,7 +258,7 @@
       content::NotificationService::AllSources());
 
   SetSignFormField("services", "[]");
-  SetSignFormField("password", OobeBaseTest::kFakeUserPassword);
+  SetSignFormField("password", FakeGaiaMixin::kFakeUserPassword);
   ClickNext();
 
   session_start_waiter.Wait();
@@ -269,7 +272,7 @@
   ExpectIdentifierPage();
 
   // Move to password page.
-  SetSignFormField("identifier", OobeBaseTest::kFakeUserEmail);
+  SetSignFormField("identifier", FakeGaiaMixin::kFakeUserEmail);
   ClickNext();
   WaitForGaiaPageBackButtonUpdate();
   ExpectPasswordPage();
@@ -290,7 +293,7 @@
 
   // Finish sign-up.
   SetSignFormField("services", "[]");
-  SetSignFormField("password", OobeBaseTest::kFakeUserPassword);
+  SetSignFormField("password", FakeGaiaMixin::kFakeUserPassword);
   ClickNext();
 
   session_start_waiter.Wait();
@@ -319,7 +322,7 @@
   WaitForGaiaPageLoad();
   test::OobeJS().ExecuteAsync("Oobe.showSigninUI('user@example.com')");
   WaitForGaiaPageReload();
-  EXPECT_EQ(fake_gaia_->prefilled_email(), "user@example.com");
+  EXPECT_EQ(fake_gaia_.fake_gaia()->prefilled_email(), "user@example.com");
 }
 
 IN_PROC_BROWSER_TEST_F(WebviewLoginTest, StoragePartitionHandling) {
diff --git a/chrome/browser/chromeos/login/wizard_controller.cc b/chrome/browser/chromeos/login/wizard_controller.cc
index c335fdc..7032633e 100644
--- a/chrome/browser/chromeos/login/wizard_controller.cc
+++ b/chrome/browser/chromeos/login/wizard_controller.cc
@@ -373,7 +373,10 @@
     return std::make_unique<NetworkScreen>(this,
                                            oobe_ui->GetNetworkScreenView());
   } else if (screen == OobeScreen::SCREEN_OOBE_UPDATE) {
-    return std::make_unique<UpdateScreen>(this, oobe_ui->GetUpdateView());
+    return std::make_unique<UpdateScreen>(
+        this, oobe_ui->GetUpdateView(),
+        base::BindRepeating(&WizardController::OnUpdateScreenExit,
+                            weak_factory_.GetWeakPtr()));
   } else if (screen == OobeScreen::SCREEN_USER_IMAGE_PICKER) {
     return std::make_unique<UserImageScreen>(this, oobe_ui->GetUserImageView());
   } else if (screen == OobeScreen::SCREEN_OOBE_EULA) {
@@ -707,8 +710,41 @@
   skip_update_enroll_after_eula_ = true;
 }
 
+void WizardController::OnScreenExit(OobeScreen screen) {
+  DCHECK_EQ(screen, current_screen_->screen_id());
+
+  if (IsOOBEStepToTrack(screen)) {
+    RecordUMAHistogramForOOBEStepCompletionTime(
+        screen, base::Time::Now() - screen_show_times_[screen]);
+  }
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 // WizardController, ExitHandlers:
+void WizardController::OnUpdateScreenExit(UpdateScreen::Result result) {
+  VLOG(1) << "Update screen exit: " << static_cast<int>(result);
+  OnScreenExit(OobeScreen::SCREEN_OOBE_UPDATE);
+
+  switch (result) {
+    case UpdateScreen::Result::UPDATE_NOT_REQUIRED:
+      OnUpdateCompleted();
+      break;
+    case UpdateScreen::Result::UPDATE_ERROR:
+      // Ignore update errors if the OOBE flow has already completed - this
+      // prevents the user getting blocked from getting to the login screen.
+      if (is_out_of_box_) {
+        ShowNetworkScreen();
+      } else {
+        OnUpdateCompleted();
+      }
+      break;
+  }
+}
+
+void WizardController::OnUpdateCompleted() {
+  ShowAutoEnrollmentCheckScreen();
+}
+
 void WizardController::OnHIDDetectionCompleted() {
   // Check for tests configuration.
   if (!StartupUtils::IsOobeCompleted())
@@ -776,14 +812,6 @@
   ShowLoginScreen(LoginScreenContext());
 }
 
-void WizardController::OnUpdateCompleted() {
-  ShowAutoEnrollmentCheckScreen();
-}
-
-void WizardController::OnUpdateOverCellularRejected() {
-  ShowNetworkScreen();
-}
-
 void WizardController::OnEulaAccepted() {
   time_eula_accepted_ = base::Time::Now();
   StartupUtils::MarkEulaAccepted();
@@ -823,26 +851,6 @@
 #endif
 }
 
-void WizardController::OnUpdateErrorCheckingForUpdate() {
-  // TODO(nkostylev): Update should be required during OOBE.
-  // We do not want to block users from being able to proceed to the login
-  // screen if there is any error checking for an update.
-  // They could use "browse without sign-in" feature to set up the network to be
-  // able to perform the update later.
-  OnUpdateCompleted();
-}
-
-void WizardController::OnUpdateErrorUpdating(bool is_critical_update) {
-  // If there was an error while getting or applying the update, return to
-  // network selection screen if the OOBE isn't complete and the update is
-  // deemed critical. Otherwise, similar to OnUpdateErrorCheckingForUpdate(), we
-  // do not want to block users from being able to proceed to the login screen.
-  if (is_out_of_box_ && is_critical_update)
-    ShowNetworkScreen();
-  else
-    OnUpdateCompleted();
-}
-
 void WizardController::OnUserImageSelected() {
   OnOobeFlowFinished();
 }
@@ -1204,7 +1212,7 @@
 
   const OobeScreen screen = new_current->screen_id();
   if (IsOOBEStepToTrack(screen))
-    screen_show_times_[GetOobeScreenName(screen)] = base::Time::Now();
+    screen_show_times_[screen] = base::Time::Now();
 
   previous_screen_ = current_screen_;
   current_screen_ = new_current;
@@ -1371,13 +1379,8 @@
 // WizardController, BaseScreenDelegate overrides:
 void WizardController::OnExit(ScreenExitCode exit_code) {
   VLOG(1) << "Wizard screen exit code: " << ExitCodeToString(exit_code);
-  const OobeScreen previous_screen = current_screen_->screen_id();
-  if (IsOOBEStepToTrack(previous_screen)) {
-    RecordUMAHistogramForOOBEStepCompletionTime(
-        previous_screen,
-        base::Time::Now() -
-            screen_show_times_[GetOobeScreenName(previous_screen)]);
-  }
+  OnScreenExit(current_screen_->screen_id());
+
   switch (exit_code) {
     case ScreenExitCode::HID_DETECTION_COMPLETED:
       OnHIDDetectionCompleted();
@@ -1397,22 +1400,6 @@
     case ScreenExitCode::CONNECTION_FAILED:
       OnConnectionFailed();
       break;
-    case ScreenExitCode::UPDATE_INSTALLED:
-    case ScreenExitCode::UPDATE_NOUPDATE:
-      OnUpdateCompleted();
-      break;
-    case ScreenExitCode::UPDATE_REJECT_OVER_CELLULAR:
-      OnUpdateOverCellularRejected();
-      return;
-    case ScreenExitCode::UPDATE_ERROR_CHECKING_FOR_UPDATE:
-      OnUpdateErrorCheckingForUpdate();
-      break;
-    case ScreenExitCode::UPDATE_ERROR_UPDATING:
-      OnUpdateErrorUpdating(false /* is_critical_update */);
-      break;
-    case ScreenExitCode::UPDATE_ERROR_UPDATING_CRITICAL_UPDATE:
-      OnUpdateErrorUpdating(true /* is_critical_update */);
-      break;
     case ScreenExitCode::USER_IMAGE_SELECTED:
       OnUserImageSelected();
       break;
diff --git a/chrome/browser/chromeos/login/wizard_controller.h b/chrome/browser/chromeos/login/wizard_controller.h
index 88842f78..79d7211 100644
--- a/chrome/browser/chromeos/login/wizard_controller.h
+++ b/chrome/browser/chromeos/login/wizard_controller.h
@@ -25,6 +25,7 @@
 #include "chrome/browser/chromeos/login/screens/eula_screen.h"
 #include "chrome/browser/chromeos/login/screens/hid_detection_screen.h"
 #include "chrome/browser/chromeos/login/screens/reset_screen.h"
+#include "chrome/browser/chromeos/login/screens/update_screen.h"
 #include "chrome/browser/chromeos/login/screens/welcome_screen.h"
 #include "chrome/browser/chromeos/policy/enrollment_config.h"
 
@@ -190,19 +191,20 @@
   // Shows previous screen. Should only be called if previous screen exists.
   void ShowPreviousScreen();
 
+  // Shared actions to be performed on a screen exit.
+  void OnScreenExit(OobeScreen screen);
+
   // Exit handlers:
+  void OnUpdateScreenExit(UpdateScreen::Result result);
+  void OnUpdateCompleted();
   void OnHIDDetectionCompleted();
   void OnWelcomeContinued();
   void OnNetworkBack();
   void OnNetworkConnected();
   void OnOfflineDemoModeSetup();
   void OnConnectionFailed();
-  void OnUpdateCompleted();
-  void OnUpdateOverCellularRejected();
   void OnEulaAccepted();
   void OnEulaBack();
-  void OnUpdateErrorCheckingForUpdate();
-  void OnUpdateErrorUpdating(bool is_critical_update);
   void OnUserImageSelected();
   void OnEnrollmentDone();
   void OnDeviceModificationCanceled();
@@ -429,7 +431,7 @@
   std::unique_ptr<DemoSetupController> demo_setup_controller_;
 
   // Maps screen names to last time of their shows.
-  std::map<std::string, base::Time> screen_show_times_;
+  std::map<OobeScreen, base::Time> screen_show_times_;
 
   // Tests check result of timezone resolve.
   bool timezone_resolved_ = false;
diff --git a/chrome/browser/chromeos/login/wizard_controller_browsertest.cc b/chrome/browser/chromeos/login/wizard_controller_browsertest.cc
index 1ae2400..9f1bd14 100644
--- a/chrome/browser/chromeos/login/wizard_controller_browsertest.cc
+++ b/chrome/browser/chromeos/login/wizard_controller_browsertest.cc
@@ -608,7 +608,9 @@
     mock_update_view_ = std::make_unique<MockUpdateView>();
     mock_update_screen_ =
         MockScreenExpectLifecycle(std::make_unique<MockUpdateScreen>(
-            wizard_controller, mock_update_view_.get()));
+            wizard_controller, mock_update_view_.get(),
+            base::BindRepeating(&WizardController::OnUpdateScreenExit,
+                                base::Unretained(wizard_controller))));
 
     mock_eula_view_ = std::make_unique<MockEulaView>();
     mock_eula_screen_ =
@@ -766,7 +768,7 @@
     CheckCurrentScreen(OobeScreen::SCREEN_OOBE_UPDATE);
     EXPECT_CALL(*mock_update_screen_, Hide()).Times(1);
     EXPECT_CALL(*mock_auto_enrollment_check_screen_, Show()).Times(1);
-    OnExit(ScreenExitCode::UPDATE_INSTALLED);
+    mock_update_screen_->RunExit(UpdateScreen::Result::UPDATE_NOT_REQUIRED);
 
     CheckCurrentScreen(OobeScreen::SCREEN_AUTO_ENROLLMENT_CHECK);
     EXPECT_CALL(*mock_auto_enrollment_check_screen_, Hide()).Times(0);
@@ -867,7 +869,7 @@
   CheckCurrentScreen(OobeScreen::SCREEN_OOBE_UPDATE);
   EXPECT_CALL(*mock_update_screen_, Hide()).Times(1);
   EXPECT_CALL(*mock_auto_enrollment_check_screen_, Show()).Times(1);
-  OnExit(ScreenExitCode::UPDATE_ERROR_UPDATING);
+  mock_update_screen_->RunExit(UpdateScreen::Result::UPDATE_NOT_REQUIRED);
 
   CheckCurrentScreen(OobeScreen::SCREEN_AUTO_ENROLLMENT_CHECK);
   EXPECT_CALL(*mock_auto_enrollment_check_screen_, Hide()).Times(0);
@@ -910,43 +912,7 @@
   EXPECT_CALL(*mock_auto_enrollment_check_screen_, Show()).Times(0);
   EXPECT_CALL(*mock_network_screen_, Show()).Times(1);
   EXPECT_CALL(*mock_network_screen_, Hide()).Times(0);  // last transition
-  OnExit(ScreenExitCode::UPDATE_ERROR_UPDATING_CRITICAL_UPDATE);
-  CheckCurrentScreen(OobeScreen::SCREEN_OOBE_NETWORK);
-}
-
-// Tests that WizardController goes back to network selection if the user
-// declined to accept update over a cellular network.
-IN_PROC_BROWSER_TEST_F(WizardControllerFlowTest,
-                       ControlFlowErrorUpdateRejectedOverCellular) {
-  CheckCurrentScreen(OobeScreen::SCREEN_OOBE_WELCOME);
-  EXPECT_CALL(*mock_update_screen_, StartNetworkCheck()).Times(0);
-  EXPECT_CALL(*mock_update_screen_, Show()).Times(0);
-  EXPECT_CALL(*mock_network_screen_, Show()).Times(1);
-  EXPECT_CALL(*mock_welcome_screen_, Hide()).Times(1);
-  EXPECT_CALL(*mock_welcome_screen_, SetConfiguration(IsNull(), _)).Times(1);
-  OnExit(ScreenExitCode::WELCOME_CONTINUED);
-
-  CheckCurrentScreen(OobeScreen::SCREEN_OOBE_NETWORK);
-  EXPECT_CALL(*mock_eula_screen_, Show()).Times(1);
-  EXPECT_CALL(*mock_network_screen_, Hide()).Times(1);
-  OnExit(ScreenExitCode::NETWORK_CONNECTED);
-
-  CheckCurrentScreen(OobeScreen::SCREEN_OOBE_EULA);
-  EXPECT_CALL(*mock_eula_screen_, Hide()).Times(1);
-  EXPECT_CALL(*mock_update_screen_, StartNetworkCheck()).Times(1);
-  EXPECT_CALL(*mock_update_screen_, Show()).Times(1);
-  OnExit(ScreenExitCode::EULA_ACCEPTED);
-
-  // Let update screen smooth time process (time = 0ms).
-  content::RunAllPendingInMessageLoop();
-
-  CheckCurrentScreen(OobeScreen::SCREEN_OOBE_UPDATE);
-  EXPECT_CALL(*mock_update_screen_, Hide()).Times(1);
-  EXPECT_CALL(*mock_eula_screen_, Show()).Times(0);
-  EXPECT_CALL(*mock_auto_enrollment_check_screen_, Show()).Times(0);
-  EXPECT_CALL(*mock_network_screen_, Show()).Times(1);
-  EXPECT_CALL(*mock_network_screen_, Hide()).Times(0);  // last transition
-  OnExit(ScreenExitCode::UPDATE_REJECT_OVER_CELLULAR);
+  mock_update_screen_->RunExit(UpdateScreen::Result::UPDATE_ERROR);
   CheckCurrentScreen(OobeScreen::SCREEN_OOBE_NETWORK);
 }
 
@@ -1050,13 +1016,13 @@
 }
 
 // This parameterized test class extends WizardControllerFlowTest to verify how
-// WizardController behaves if it fails to apply an update after the OOBE is
-// marked complete.
-class WizardControllerErrorUpdateAfterCompletedOobeTest
+// WizardController behaves if it does not find or fails to apply an update
+// after the OOBE is marked complete.
+class WizardControllerUpdateAfterCompletedOobeTest
     : public WizardControllerFlowTest,
-      public testing::WithParamInterface<ScreenExitCode> {
+      public testing::WithParamInterface<UpdateScreen::Result> {
  protected:
-  WizardControllerErrorUpdateAfterCompletedOobeTest() = default;
+  WizardControllerUpdateAfterCompletedOobeTest() = default;
 
   void SetUpOnMainThread() override {
     StartupUtils::MarkOobeCompleted();  // Pretend OOBE was complete.
@@ -1064,15 +1030,13 @@
   }
 
  private:
-  DISALLOW_COPY_AND_ASSIGN(WizardControllerErrorUpdateAfterCompletedOobeTest);
+  DISALLOW_COPY_AND_ASSIGN(WizardControllerUpdateAfterCompletedOobeTest);
 };
 
-// This test verifies that if WizardController fails to apply an update, either
-// critical or non-critical, after the OOBE is marked complete, it allows the
-// user to proceed to log in.
-IN_PROC_BROWSER_TEST_P(WizardControllerErrorUpdateAfterCompletedOobeTest,
+// This test verifies that if WizardController reports any result after the
+// OOBE is marked complete, it allows the user to proceed to log in.
+IN_PROC_BROWSER_TEST_P(WizardControllerUpdateAfterCompletedOobeTest,
                        ControlFlowErrorUpdate) {
-  const ScreenExitCode update_screen_exit_code = GetParam();
   CheckCurrentScreen(OobeScreen::SCREEN_OOBE_WELCOME);
   EXPECT_CALL(*mock_update_screen_, StartNetworkCheck()).Times(0);
   EXPECT_CALL(*mock_update_screen_, Show()).Times(0);
@@ -1098,7 +1062,7 @@
   CheckCurrentScreen(OobeScreen::SCREEN_OOBE_UPDATE);
   EXPECT_CALL(*mock_update_screen_, Hide()).Times(1);
   EXPECT_CALL(*mock_auto_enrollment_check_screen_, Show()).Times(1);
-  OnExit(update_screen_exit_code);
+  mock_update_screen_->RunExit(GetParam());
 
   CheckCurrentScreen(OobeScreen::SCREEN_AUTO_ENROLLMENT_CHECK);
   EXPECT_CALL(*mock_auto_enrollment_check_screen_, Hide()).Times(0);
@@ -1109,10 +1073,10 @@
 }
 
 INSTANTIATE_TEST_SUITE_P(
-    WizardControllerErrorUpdateAfterCompletedOobe,
-    WizardControllerErrorUpdateAfterCompletedOobeTest,
-    testing::Values(ScreenExitCode::UPDATE_ERROR_UPDATING,
-                    ScreenExitCode::UPDATE_ERROR_UPDATING_CRITICAL_UPDATE));
+    WizardControllerUpdateAfterCompletedOobe,
+    WizardControllerUpdateAfterCompletedOobeTest,
+    testing::Values(UpdateScreen::Result::UPDATE_NOT_REQUIRED,
+                    UpdateScreen::Result::UPDATE_ERROR));
 
 class WizardControllerDeviceStateTest : public WizardControllerFlowTest {
  protected:
@@ -1227,7 +1191,7 @@
   CheckCurrentScreen(OobeScreen::SCREEN_OOBE_UPDATE);
   EXPECT_CALL(*mock_update_screen_, Hide()).Times(1);
   EXPECT_CALL(*mock_auto_enrollment_check_screen_, Show()).Times(1);
-  OnExit(ScreenExitCode::UPDATE_INSTALLED);
+  mock_update_screen_->RunExit(UpdateScreen::Result::UPDATE_NOT_REQUIRED);
 
   CheckCurrentScreen(OobeScreen::SCREEN_AUTO_ENROLLMENT_CHECK);
   mock_auto_enrollment_check_screen_->RealShow();
@@ -1272,7 +1236,7 @@
   CheckCurrentScreen(OobeScreen::SCREEN_OOBE_UPDATE);
   EXPECT_CALL(*mock_update_screen_, Hide()).Times(1);
   EXPECT_CALL(*mock_auto_enrollment_check_screen_, Show()).Times(1);
-  OnExit(ScreenExitCode::UPDATE_INSTALLED);
+  mock_update_screen_->RunExit(UpdateScreen::Result::UPDATE_NOT_REQUIRED);
 
   CheckCurrentScreen(OobeScreen::SCREEN_AUTO_ENROLLMENT_CHECK);
   EXPECT_CALL(*mock_auto_enrollment_check_screen_, Hide()).Times(1);
@@ -1370,7 +1334,7 @@
   CheckCurrentScreen(OobeScreen::SCREEN_OOBE_UPDATE);
   EXPECT_CALL(*mock_update_screen_, Hide()).Times(1);
   EXPECT_CALL(*mock_auto_enrollment_check_screen_, Show()).Times(1);
-  OnExit(ScreenExitCode::UPDATE_INSTALLED);
+  mock_update_screen_->RunExit(UpdateScreen::Result::UPDATE_NOT_REQUIRED);
 
   CheckCurrentScreen(OobeScreen::SCREEN_AUTO_ENROLLMENT_CHECK);
   EXPECT_CALL(*mock_auto_enrollment_check_screen_, Hide()).Times(1);
@@ -1468,7 +1432,7 @@
   CheckCurrentScreen(OobeScreen::SCREEN_OOBE_UPDATE);
   EXPECT_CALL(*mock_update_screen_, Hide()).Times(1);
   EXPECT_CALL(*mock_auto_enrollment_check_screen_, Show()).Times(1);
-  OnExit(ScreenExitCode::UPDATE_INSTALLED);
+  mock_update_screen_->RunExit(UpdateScreen::Result::UPDATE_NOT_REQUIRED);
 
   CheckCurrentScreen(OobeScreen::SCREEN_AUTO_ENROLLMENT_CHECK);
   mock_auto_enrollment_check_screen_->RealShow();
@@ -1620,7 +1584,7 @@
   CheckCurrentScreen(OobeScreen::SCREEN_OOBE_UPDATE);
   EXPECT_CALL(*mock_update_screen_, Hide()).Times(1);
   EXPECT_CALL(*mock_auto_enrollment_check_screen_, Show()).Times(1);
-  OnExit(ScreenExitCode::UPDATE_INSTALLED);
+  mock_update_screen_->RunExit(UpdateScreen::Result::UPDATE_NOT_REQUIRED);
 
   CheckCurrentScreen(OobeScreen::SCREEN_AUTO_ENROLLMENT_CHECK);
   EXPECT_CALL(*mock_auto_enrollment_check_screen_, Hide()).Times(1);
@@ -1694,7 +1658,7 @@
   CheckCurrentScreen(OobeScreen::SCREEN_OOBE_UPDATE);
   EXPECT_CALL(*mock_update_screen_, Hide()).Times(1);
   EXPECT_CALL(*mock_auto_enrollment_check_screen_, Show()).Times(1);
-  OnExit(ScreenExitCode::UPDATE_INSTALLED);
+  mock_update_screen_->RunExit(UpdateScreen::Result::UPDATE_NOT_REQUIRED);
 
   CheckCurrentScreen(OobeScreen::SCREEN_AUTO_ENROLLMENT_CHECK);
   mock_auto_enrollment_check_screen_->RealShow();
@@ -1789,7 +1753,7 @@
   CheckCurrentScreen(OobeScreen::SCREEN_OOBE_UPDATE);
   EXPECT_CALL(*mock_update_screen_, Hide()).Times(1);
   EXPECT_CALL(*mock_auto_enrollment_check_screen_, Show()).Times(1);
-  OnExit(ScreenExitCode::UPDATE_INSTALLED);
+  mock_update_screen_->RunExit(UpdateScreen::Result::UPDATE_NOT_REQUIRED);
 
   CheckCurrentScreen(OobeScreen::SCREEN_AUTO_ENROLLMENT_CHECK);
   mock_auto_enrollment_check_screen_->RealShow();
@@ -1833,7 +1797,7 @@
   CheckCurrentScreen(OobeScreen::SCREEN_OOBE_UPDATE);
   EXPECT_CALL(*mock_update_screen_, Hide()).Times(1);
   EXPECT_CALL(*mock_auto_enrollment_check_screen_, Show()).Times(1);
-  OnExit(ScreenExitCode::UPDATE_INSTALLED);
+  mock_update_screen_->RunExit(UpdateScreen::Result::UPDATE_NOT_REQUIRED);
 
   CheckCurrentScreen(OobeScreen::SCREEN_AUTO_ENROLLMENT_CHECK);
   mock_auto_enrollment_check_screen_->RealShow();
@@ -1889,7 +1853,7 @@
   CheckCurrentScreen(OobeScreen::SCREEN_OOBE_UPDATE);
   EXPECT_CALL(*mock_update_screen_, Hide()).Times(1);
   EXPECT_CALL(*mock_auto_enrollment_check_screen_, Show()).Times(1);
-  OnExit(ScreenExitCode::UPDATE_INSTALLED);
+  mock_update_screen_->RunExit(UpdateScreen::Result::UPDATE_NOT_REQUIRED);
 
   CheckCurrentScreen(OobeScreen::SCREEN_AUTO_ENROLLMENT_CHECK);
   mock_auto_enrollment_check_screen_->RealShow();
@@ -1945,7 +1909,7 @@
   CheckCurrentScreen(OobeScreen::SCREEN_OOBE_UPDATE);
   EXPECT_CALL(*mock_update_screen_, Hide()).Times(1);
   EXPECT_CALL(*mock_auto_enrollment_check_screen_, Show()).Times(1);
-  OnExit(ScreenExitCode::UPDATE_INSTALLED);
+  mock_update_screen_->RunExit(UpdateScreen::Result::UPDATE_NOT_REQUIRED);
 
   CheckCurrentScreen(OobeScreen::SCREEN_AUTO_ENROLLMENT_CHECK);
   mock_auto_enrollment_check_screen_->RealShow();
@@ -2027,7 +1991,7 @@
   CheckCurrentScreen(OobeScreen::SCREEN_OOBE_UPDATE);
   EXPECT_CALL(*mock_update_screen_, Hide()).Times(1);
   EXPECT_CALL(*mock_auto_enrollment_check_screen_, Show()).Times(1);
-  OnExit(ScreenExitCode::UPDATE_INSTALLED);
+  mock_update_screen_->RunExit(UpdateScreen::Result::UPDATE_NOT_REQUIRED);
 
   CheckCurrentScreen(OobeScreen::SCREEN_AUTO_ENROLLMENT_CHECK);
   mock_auto_enrollment_check_screen_->RealShow();
@@ -2192,7 +2156,7 @@
   CheckCurrentScreen(OobeScreen::SCREEN_OOBE_UPDATE);
   EXPECT_CALL(*mock_update_screen_, Hide()).Times(1);
   EXPECT_CALL(*mock_auto_enrollment_check_screen_, Show()).Times(1);
-  OnExit(ScreenExitCode::UPDATE_INSTALLED);
+  mock_update_screen_->RunExit(UpdateScreen::Result::UPDATE_NOT_REQUIRED);
 
   CheckCurrentScreen(OobeScreen::SCREEN_AUTO_ENROLLMENT_CHECK);
   EXPECT_CALL(*mock_auto_enrollment_check_screen_, Hide()).Times(1);
@@ -2240,7 +2204,7 @@
   CheckCurrentScreen(OobeScreen::SCREEN_OOBE_UPDATE);
   EXPECT_CALL(*mock_update_screen_, Hide()).Times(1);
   EXPECT_CALL(*mock_auto_enrollment_check_screen_, Show()).Times(1);
-  OnExit(ScreenExitCode::UPDATE_INSTALLED);
+  mock_update_screen_->RunExit(UpdateScreen::Result::UPDATE_NOT_REQUIRED);
 
   CheckCurrentScreen(OobeScreen::SCREEN_AUTO_ENROLLMENT_CHECK);
   EXPECT_CALL(*mock_auto_enrollment_check_screen_, Hide()).Times(1);
@@ -2377,7 +2341,7 @@
   EXPECT_CALL(*mock_update_screen_, Hide()).Times(1);
   EXPECT_CALL(*mock_auto_enrollment_check_screen_, Show()).Times(1);
 
-  OnExit(ScreenExitCode::UPDATE_INSTALLED);
+  mock_update_screen_->RunExit(UpdateScreen::Result::UPDATE_NOT_REQUIRED);
 
   CheckCurrentScreen(OobeScreen::SCREEN_AUTO_ENROLLMENT_CHECK);
   EXPECT_TRUE(DemoSetupController::IsOobeDemoSetupFlowInProgress());
@@ -2504,7 +2468,7 @@
   EXPECT_CALL(*mock_update_screen_, Hide()).Times(1);
   EXPECT_CALL(*mock_auto_enrollment_check_screen_, Show()).Times(1);
 
-  OnExit(ScreenExitCode::UPDATE_INSTALLED);
+  mock_update_screen_->RunExit(UpdateScreen::Result::UPDATE_NOT_REQUIRED);
 
   CheckCurrentScreen(OobeScreen::SCREEN_AUTO_ENROLLMENT_CHECK);
   EXPECT_TRUE(DemoSetupController::IsOobeDemoSetupFlowInProgress());
@@ -2674,7 +2638,7 @@
   EXPECT_CALL(*mock_update_screen_, Hide()).Times(1);
   EXPECT_CALL(*mock_auto_enrollment_check_screen_, Show()).Times(1);
 
-  OnExit(ScreenExitCode::UPDATE_INSTALLED);
+  mock_update_screen_->RunExit(UpdateScreen::Result::UPDATE_NOT_REQUIRED);
 
   CheckCurrentScreen(OobeScreen::SCREEN_AUTO_ENROLLMENT_CHECK);
   EXPECT_TRUE(DemoSetupController::IsOobeDemoSetupFlowInProgress());
diff --git a/chrome/browser/chromeos/policy/app_install_event_log_uploader_unittest.cc b/chrome/browser/chromeos/policy/app_install_event_log_uploader_unittest.cc
index c039b6c..f1d6981 100644
--- a/chrome/browser/chromeos/policy/app_install_event_log_uploader_unittest.cc
+++ b/chrome/browser/chromeos/policy/app_install_event_log_uploader_unittest.cc
@@ -44,7 +44,7 @@
                 HAS_1_TEMPLATE_PARAMS(int, k),
                 AND_1_VALUE_PARAMS(out)) {
   *out = std::move(*testing::get<k>(args));
-};
+}
 
 class MockAppInstallEventLogUploaderDelegate
     : public AppInstallEventLogUploader::Delegate {
diff --git a/chrome/browser/chromeos/policy/app_install_event_logger_unittest.cc b/chrome/browser/chromeos/policy/app_install_event_logger_unittest.cc
index 11cdc8f5..463281f 100644
--- a/chrome/browser/chromeos/policy/app_install_event_logger_unittest.cc
+++ b/chrome/browser/chromeos/policy/app_install_event_logger_unittest.cc
@@ -66,7 +66,7 @@
                 HAS_1_TEMPLATE_PARAMS(int, k),
                 AND_1_VALUE_PARAMS(out)) {
   *out = testing::get<k>(args).timestamp();
-};
+}
 
 int64_t GetCurrentTimestamp() {
   return (base::Time::Now() - base::Time::UnixEpoch()).InMicroseconds();
diff --git a/chrome/browser/chromeos/policy/device_cloud_policy_initializer.cc b/chrome/browser/chromeos/policy/device_cloud_policy_initializer.cc
index f0bcfde9..635e07d 100644
--- a/chrome/browser/chromeos/policy/device_cloud_policy_initializer.cc
+++ b/chrome/browser/chromeos/policy/device_cloud_policy_initializer.cc
@@ -118,7 +118,7 @@
       attestation_flow_.get(), CreateClient(device_management_service),
       background_task_runner_, ad_join_delegate, enrollment_config,
       std::move(dm_auth), install_attributes_->GetDeviceId(),
-      manager_->GetDeviceRequisition(),
+      manager_->GetDeviceRequisition(), manager_->GetSubOrganization(),
       base::Bind(&DeviceCloudPolicyInitializer::EnrollmentCompleted,
                  base::Unretained(this), enrollment_callback)));
 }
diff --git a/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.cc b/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.cc
index b57b81a3..ed5dfbe 100644
--- a/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.cc
+++ b/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.cc
@@ -191,6 +191,28 @@
   return GetDeviceRequisition() == kSharkRequisition;
 }
 
+std::string DeviceCloudPolicyManagerChromeOS::GetSubOrganization() const {
+  if (!local_state_)
+    return std::string();
+  std::string sub_organization;
+  const PrefService::Preference* pref =
+      local_state_->FindPreference(prefs::kDeviceEnrollmentSubOrganization);
+  if (!pref->IsDefaultValue())
+    pref->GetValue()->GetAsString(&sub_organization);
+  return sub_organization;
+}
+
+void DeviceCloudPolicyManagerChromeOS::SetSubOrganization(
+    const std::string& sub_organization) {
+  if (!local_state_)
+    return;
+  if (sub_organization.empty())
+    local_state_->ClearPref(prefs::kDeviceEnrollmentSubOrganization);
+  else
+    local_state_->SetString(prefs::kDeviceEnrollmentSubOrganization,
+                            sub_organization);
+}
+
 void DeviceCloudPolicyManagerChromeOS::SetDeviceEnrollmentAutoStart() {
   if (local_state_) {
     local_state_->SetBoolean(prefs::kDeviceEnrollmentAutoStart, true);
@@ -213,6 +235,8 @@
     PrefRegistrySimple* registry) {
   registry->RegisterStringPref(prefs::kDeviceEnrollmentRequisition,
                                std::string());
+  registry->RegisterStringPref(prefs::kDeviceEnrollmentSubOrganization,
+                               std::string());
   registry->RegisterBooleanPref(prefs::kDeviceEnrollmentAutoStart, false);
   registry->RegisterBooleanPref(prefs::kDeviceEnrollmentCanExit, true);
   registry->RegisterDictionaryPref(prefs::kServerBackedDeviceState);
diff --git a/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.h b/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.h
index 76b439f..3ba6ccb 100644
--- a/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.h
+++ b/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.h
@@ -82,6 +82,10 @@
   bool IsRemoraRequisition() const;
   bool IsSharkRequisition() const;
 
+  // Gets/Sets the sub organization.
+  std::string GetSubOrganization() const;
+  void SetSubOrganization(const std::string& sub_organization);
+
   // If set, the device will start the enterprise enrollment OOBE.
   void SetDeviceEnrollmentAutoStart();
 
diff --git a/chrome/browser/chromeos/policy/device_local_account_browsertest.cc b/chrome/browser/chromeos/policy/device_local_account_browsertest.cc
index 67a3f564..c404d60 100644
--- a/chrome/browser/chromeos/policy/device_local_account_browsertest.cc
+++ b/chrome/browser/chromeos/policy/device_local_account_browsertest.cc
@@ -1710,7 +1710,7 @@
   ASSERT_NO_FATAL_FAILURE(CloseLogoutConfirmationDialog());
 
   app_window_registry->RemoveObserver(this);
-};
+}
 
 IN_PROC_BROWSER_TEST_F(DeviceLocalAccountTest, NoRecommendedLocaleNoSwitch) {
   UploadAndInstallDeviceLocalAccountPolicy();
diff --git a/chrome/browser/chromeos/policy/device_status_collector_browsertest.cc b/chrome/browser/chromeos/policy/device_status_collector_browsertest.cc
index 41bf298..44bde3d 100644
--- a/chrome/browser/chromeos/policy/device_status_collector_browsertest.cc
+++ b/chrome/browser/chromeos/policy/device_status_collector_browsertest.cc
@@ -433,7 +433,7 @@
         chromeos::kReportDeviceNetworkInterfaces, false);
   }
 
-  void TearDown() override { status_collector_.reset(); };
+  void TearDown() override { status_collector_.reset(); }
 
  protected:
   // States tracked to calculate a child's active time.
diff --git a/chrome/browser/chromeos/policy/enrollment_handler_chromeos.cc b/chrome/browser/chromeos/policy/enrollment_handler_chromeos.cc
index 3815bca..4204fe66e 100644
--- a/chrome/browser/chromeos/policy/enrollment_handler_chromeos.cc
+++ b/chrome/browser/chromeos/policy/enrollment_handler_chromeos.cc
@@ -171,6 +171,7 @@
     std::unique_ptr<DMAuth> dm_auth,
     const std::string& client_id,
     const std::string& requisition,
+    const std::string& sub_organization,
     const EnrollmentCallback& completion_callback)
     : store_(store),
       install_attributes_(install_attributes),
@@ -182,6 +183,7 @@
       enrollment_config_(enrollment_config),
       client_id_(client_id),
       requisition_(requisition),
+      sub_organization_(sub_organization),
       completion_callback_(completion_callback),
       enrollment_step_(STEP_PENDING),
       weak_ptr_factory_(this) {
@@ -461,7 +463,7 @@
         EnrollmentModeToRegistrationFlavor(enrollment_config_.mode),
         em::DeviceRegisterRequest::LIFETIME_INDEFINITE, license_type_,
         dm_auth_->Clone(), pem_certificate_chain, client_id_, requisition_,
-        current_state_key_);
+        current_state_key_, sub_organization_);
   } else {
     ReportResult(EnrollmentStatus::ForStatus(
         EnrollmentStatus::REGISTRATION_CERT_FETCH_FAILED));
diff --git a/chrome/browser/chromeos/policy/enrollment_handler_chromeos.h b/chrome/browser/chromeos/policy/enrollment_handler_chromeos.h
index 593447a..b8031e0 100644
--- a/chrome/browser/chromeos/policy/enrollment_handler_chromeos.h
+++ b/chrome/browser/chromeos/policy/enrollment_handler_chromeos.h
@@ -79,6 +79,7 @@
       std::unique_ptr<DMAuth> dm_auth,
       const std::string& client_id,
       const std::string& requisition,
+      const std::string& sub_organization,
       const EnrollmentCallback& completion_callback);
   ~EnrollmentHandlerChromeOS() override;
 
@@ -236,6 +237,7 @@
   std::unique_ptr<policy::DMAuth> dm_auth_;
   std::string client_id_;
   std::string requisition_;
+  std::string sub_organization_;
   EnrollmentCallback completion_callback_;
   AvailableLicensesCallback available_licenses_callback_;
   enterprise_management::LicenseType::LicenseTypeEnum license_type_ =
diff --git a/chrome/browser/chromeos/policy/login_policy_test_base.cc b/chrome/browser/chromeos/policy/login_policy_test_base.cc
index b5fb3f6..424fda6 100644
--- a/chrome/browser/chromeos/policy/login_policy_test_base.cc
+++ b/chrome/browser/chromeos/policy/login_policy_test_base.cc
@@ -41,8 +41,7 @@
   set_open_about_blank_on_browser_launch(false);
 }
 
-LoginPolicyTestBase::~LoginPolicyTestBase() {
-}
+LoginPolicyTestBase::~LoginPolicyTestBase() = default;
 
 void LoginPolicyTestBase::SetUp() {
   base::DictionaryValue mandatory;
@@ -61,12 +60,12 @@
 
 void LoginPolicyTestBase::SetUpOnMainThread() {
   SetMergeSessionParams();
-  SetupFakeGaiaForLogin(GetAccount(), "", kTestRefreshToken);
+  fake_gaia_.SetupFakeGaiaForLogin(GetAccount(), "", kTestRefreshToken);
   OobeBaseTest::SetUpOnMainThread();
 
   FakeGaia::MergeSessionParams params;
   params.id_token = GetIdToken();
-  fake_gaia_->UpdateMergeSessionParams(params);
+  fake_gaia_.fake_gaia()->UpdateMergeSessionParams(params);
 }
 
 std::string LoginPolicyTestBase::GetAccount() const {
@@ -97,7 +96,7 @@
   params.session_sid_cookie = kTestSessionSIDCookie;
   params.session_lsid_cookie = kTestSessionLSIDCookie;
   params.email = GetAccount();
-  fake_gaia_->SetMergeSessionParams(params);
+  fake_gaia_.fake_gaia()->SetMergeSessionParams(params);
 }
 
 void LoginPolicyTestBase::SkipToLoginScreen() {
diff --git a/chrome/browser/chromeos/policy/login_policy_test_base.h b/chrome/browser/chromeos/policy/login_policy_test_base.h
index 6ea6bafa..a6ac354 100644
--- a/chrome/browser/chromeos/policy/login_policy_test_base.h
+++ b/chrome/browser/chromeos/policy/login_policy_test_base.h
@@ -9,6 +9,7 @@
 #include <string>
 
 #include "base/macros.h"
+#include "chrome/browser/chromeos/login/test/fake_gaia_mixin.h"
 #include "chrome/browser/chromeos/login/test/oobe_base_test.h"
 
 namespace base {
@@ -50,6 +51,8 @@
   static const char kAccountId[];
   static const char kEmptyServices[];
 
+  chromeos::FakeGaiaMixin fake_gaia_{&mixin_host_, embedded_test_server()};
+
  private:
   void SetUpGaiaServerWithAccessTokens();
   void SetMergeSessionParams();
diff --git a/chrome/browser/chromeos/policy/system_log_uploader.cc b/chrome/browser/chromeos/policy/system_log_uploader.cc
index 87b095c..f07a181 100644
--- a/chrome/browser/chromeos/policy/system_log_uploader.cc
+++ b/chrome/browser/chromeos/policy/system_log_uploader.cc
@@ -128,7 +128,7 @@
   }
   return policy::GetAllPolicyValuesAsJSON(
       ProfileManager::GetActiveUserProfile(), include_user_policies,
-      true /* with_device_data */);
+      true /* with_device_data */, true /* is_pretty_print */);
 }
 
 void SystemLogDelegate::LoadSystemLogs(LogUploadCallback upload_callback) {
diff --git a/chrome/browser/chromeos/policy/user_cloud_external_data_manager_browsertest.cc b/chrome/browser/chromeos/policy/user_cloud_external_data_manager_browsertest.cc
index 24393d2..bd1e69ff 100644
--- a/chrome/browser/chromeos/policy/user_cloud_external_data_manager_browsertest.cc
+++ b/chrome/browser/chromeos/policy/user_cloud_external_data_manager_browsertest.cc
@@ -48,7 +48,7 @@
 class UserCloudExternalDataManagerTest : public LoginPolicyTestBase {
  protected:
   void SetUp() override {
-    set_initialize_fake_merge_session(false);
+    fake_gaia_.set_initialize_fake_merge_session(false);
 
     LoginPolicyTestBase::SetUp();
   }
diff --git a/chrome/browser/chromeos/power/ml/real_boot_clock.cc b/chrome/browser/chromeos/power/ml/real_boot_clock.cc
index 8b244677..d15c0d3 100644
--- a/chrome/browser/chromeos/power/ml/real_boot_clock.cc
+++ b/chrome/browser/chromeos/power/ml/real_boot_clock.cc
@@ -19,8 +19,7 @@
   struct timespec ts = {0};
   const int ret = clock_gettime(CLOCK_BOOTTIME, &ts);
   DCHECK_EQ(ret, 0);
-  return base::TimeDelta::FromSeconds(ts.tv_sec) +
-         base::TimeDelta::FromNanoseconds(ts.tv_nsec);
+  return base::TimeDelta::FromTimeSpec(ts);
 }
 
 }  // namespace ml
diff --git a/chrome/browser/chromeos/power/ml/smart_dim/model_impl.cc b/chrome/browser/chromeos/power/ml/smart_dim/model_impl.cc
index 7615f75e..5f308f33 100644
--- a/chrome/browser/chromeos/power/ml/smart_dim/model_impl.cc
+++ b/chrome/browser/chromeos/power/ml/smart_dim/model_impl.cc
@@ -410,6 +410,12 @@
   cancelable_callback_.Cancel();
 }
 
+void SmartDimModelImpl::SetMlServiceClientForTesting(
+    std::unique_ptr<MlServiceClient> client) {
+  DCHECK(!ml_service_client_);
+  ml_service_client_ = std::move(client);
+}
+
 void SmartDimModelImpl::LazyInitialize() {
   // TODO(crbug.com/893425): Remove the flag check once we shift to ML service
   // completely.
diff --git a/chrome/browser/chromeos/power/ml/smart_dim/model_impl.h b/chrome/browser/chromeos/power/ml/smart_dim/model_impl.h
index f56b629e..13dc266 100644
--- a/chrome/browser/chromeos/power/ml/smart_dim/model_impl.h
+++ b/chrome/browser/chromeos/power/ml/smart_dim/model_impl.h
@@ -60,8 +60,14 @@
                           DimDecisionCallback dim_callback) override;
   void CancelPreviousRequest() override;
 
+  // Override MlServiceClient in a unit test environment where there is no real
+  // ML Service daemon to connect to.
+  void SetMlServiceClientForTesting(std::unique_ptr<MlServiceClient> client);
+
  private:
-  friend class SmartDimModelImplTest;
+  FRIEND_TEST_ALL_PREFIXES(SmartDimTfNativeModelTest, Basic);
+  FRIEND_TEST_ALL_PREFIXES(SmartDimTfNativeModelTest, OptionalFeaturesMissing);
+
   // Loads the preprocessor config if not already loaded. Also initializes the
   // MlServiceClient object if the ML Service is being used for inference.
   void LazyInitialize();
diff --git a/chrome/browser/chromeos/power/ml/smart_dim/model_unittest.cc b/chrome/browser/chromeos/power/ml/smart_dim/model_unittest.cc
index 6a87103..9208ba1d 100644
--- a/chrome/browser/chromeos/power/ml/smart_dim/model_unittest.cc
+++ b/chrome/browser/chromeos/power/ml/smart_dim/model_unittest.cc
@@ -12,6 +12,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/test/scoped_feature_list.h"
 #include "base/test/scoped_task_environment.h"
+#include "base/threading/sequenced_task_runner_handle.h"
 #include "base/time/time.h"
 #include "chrome/browser/chromeos/power/ml/user_activity_event.pb.h"
 #include "chromeos/constants/chromeos_features.h"
@@ -22,154 +23,240 @@
 namespace power {
 namespace ml {
 
-class SmartDimModelImplTest : public testing::Test {
+namespace {
+
+UserActivityEvent::Features DefaultFeatures() {
+  UserActivityEvent::Features features;
+  // Bucketize to 95.
+  features.set_battery_percent(96.0);
+  features.set_device_management(UserActivityEvent::Features::UNMANAGED);
+  features.set_device_mode(UserActivityEvent::Features::CLAMSHELL);
+  features.set_device_type(UserActivityEvent::Features::CHROMEBOOK);
+  // Bucketize to 200.
+  features.set_key_events_in_last_hour(290);
+  features.set_last_activity_day(UserActivityEvent::Features::THU);
+  // Bucketize to 7.
+  features.set_last_activity_time_sec(25920);
+  // Bucketize to 7.
+  features.set_last_user_activity_time_sec(25920);
+  // Bucketize to 2000.
+  features.set_mouse_events_in_last_hour(2600);
+  features.set_on_battery(false);
+  features.set_previous_negative_actions_count(3);
+  features.set_previous_positive_actions_count(0);
+  features.set_recent_time_active_sec(190);
+  features.set_video_playing_time_sec(0);
+  features.set_on_to_dim_sec(30);
+  features.set_dim_to_screen_off_sec(10);
+  features.set_time_since_last_key_sec(30);
+  features.set_time_since_last_mouse_sec(688);
+  // Bucketize to 900.
+  features.set_time_since_video_ended_sec(1100);
+  features.set_has_form_entry(false);
+  features.set_source_id(123);  // not used.
+  features.set_engagement_score(40);
+  features.set_tab_domain("//mail.google.com");
+  return features;
+}
+
+// Class to hold scoped local modifications to Smart-dim related feature flags.
+class SmartDimFeatureFlags {
+ public:
+  SmartDimFeatureFlags() = default;
+
+  void Initialize(const bool use_ml_service, const double dim_threshold) {
+    const std::map<std::string, std::string> params = {
+        {"dim_threshold", base::NumberToString(dim_threshold)}};
+    smart_dim_feature_override_.InitAndEnableFeatureWithParameters(
+        features::kUserActivityPrediction, params);
+
+    if (use_ml_service) {
+      ml_service_feature_override_.InitAndEnableFeature(
+          features::kUserActivityPredictionMlService);
+    } else {
+      ml_service_feature_override_.InitAndDisableFeature(
+          features::kUserActivityPredictionMlService);
+    }
+  }
+
+ private:
+  base::test::ScopedFeatureList smart_dim_feature_override_;
+  base::test::ScopedFeatureList ml_service_feature_override_;
+
+  DISALLOW_COPY_AND_ASSIGN(SmartDimFeatureFlags);
+};
+
+class FakeMlServiceClient : public MlServiceClient {
+ public:
+  FakeMlServiceClient() = default;
+  ~FakeMlServiceClient() override {}
+
+  // MlServiceClient:
+  void DoInference(
+      const std::vector<float>& features,
+      base::RepeatingCallback<UserActivityEvent::ModelPrediction(float)>
+          get_prediction_callback,
+      SmartDimModel::DimDecisionCallback decision_callback) override {
+    // Corresponds to DefaultFeatures() with TfNativeModel:
+    const float inactivity_score = -3.6615708;
+
+    UserActivityEvent::ModelPrediction model_prediction =
+        get_prediction_callback.Run(inactivity_score);
+    base::SequencedTaskRunnerHandle::Get()->PostTask(
+        FROM_HERE,
+        base::BindOnce(std::move(decision_callback), model_prediction));
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(FakeMlServiceClient);
+};
+
+}  // namespace
+
+// Parameterized test fixture. The bool parameter is whether to test the ML
+// Service codepath. If false, the old TFNative codepath is tested.
+class SmartDimModelImplTest : public testing::TestWithParam<bool> {
  public:
   SmartDimModelImplTest()
       : scoped_task_environment_(
             base::test::ScopedTaskEnvironment::MainThreadType::IO,
-            base::test::ScopedTaskEnvironment::ExecutionMode::QUEUED) {
-    // Bucketize to 95.
-    features_.set_battery_percent(96.0);
-    features_.set_device_management(UserActivityEvent::Features::UNMANAGED);
-    features_.set_device_mode(UserActivityEvent::Features::CLAMSHELL);
-    features_.set_device_type(UserActivityEvent::Features::CHROMEBOOK);
-    // Bucketize to 200.
-    features_.set_key_events_in_last_hour(290);
-    features_.set_last_activity_day(UserActivityEvent::Features::THU);
-    // Bucketize to 7.
-    features_.set_last_activity_time_sec(25920);
-    // Bucketize to 7.
-    features_.set_last_user_activity_time_sec(25920);
-    // Bucketize to 2000.
-    features_.set_mouse_events_in_last_hour(2600);
-    features_.set_on_battery(false);
-    features_.set_previous_negative_actions_count(3);
-    features_.set_previous_positive_actions_count(0);
-    features_.set_recent_time_active_sec(190);
-    features_.set_video_playing_time_sec(0);
-    features_.set_on_to_dim_sec(30);
-    features_.set_dim_to_screen_off_sec(10);
-    features_.set_time_since_last_key_sec(30);
-    features_.set_time_since_last_mouse_sec(688);
-    // Bucketize to 900.
-    features_.set_time_since_video_ended_sec(1100);
-    features_.set_has_form_entry(false);
-    features_.set_source_id(123);  // not used.
-    features_.set_engagement_score(40);
-    features_.set_tab_domain("//mail.google.com");
-  }
+            base::test::ScopedTaskEnvironment::ExecutionMode::QUEUED) {}
 
   ~SmartDimModelImplTest() override = default;
 
  protected:
-  float CalculateInactivityScore(const UserActivityEvent::Features& features) {
-    float inactivity_score;
-    SmartDimModelResult result =
-        smart_dim_model_.CalculateInactivityScoreTfNative(features,
-                                                          &inactivity_score);
-    EXPECT_EQ(SmartDimModelResult::kSuccess, result);
-    return inactivity_score;
+  // More readable name for the test parameter:
+  bool UsesMlService() const { return GetParam(); }
+
+  // Sets a fake MlServiceClient into |impl|.
+  void InjectFakeMlServiceClient(SmartDimModelImpl* const impl) {
+    impl->SetMlServiceClientForTesting(std::make_unique<FakeMlServiceClient>());
   }
 
   base::test::ScopedTaskEnvironment scoped_task_environment_;
-  UserActivityEvent::Features features_;
-  SmartDimModelImpl smart_dim_model_;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(SmartDimModelImplTest);
 };
 
-TEST_F(SmartDimModelImplTest, Basic) {
-  const float inactivity_score = CalculateInactivityScore(features_);
+// For the TFNative model, test a hard-coded known-good model result.
+TEST(SmartDimTfNativeModelTest, Basic) {
+  base::test::ScopedTaskEnvironment env;
+  SmartDimFeatureFlags flags;
+  flags.Initialize(false /* use_ml_service */, -0.1 /* dim_threshold */);
+
+  SmartDimModelImpl smart_dim_model;
+
+  float inactivity_score;
+  EXPECT_EQ(SmartDimModelResult::kSuccess,
+            smart_dim_model.CalculateInactivityScoreTfNative(
+                DefaultFeatures(), &inactivity_score));
   // Score has been calculated outside of chrome.
   EXPECT_FLOAT_EQ(-3.6615708, inactivity_score);
 }
 
-TEST_F(SmartDimModelImplTest, OptionalFeaturesMissing) {
-  features_.clear_battery_percent();
-  features_.clear_time_since_last_key_sec();
-  features_.clear_time_since_last_mouse_sec();
-  features_.clear_time_since_video_ended_sec();
-  features_.clear_source_id();
-  features_.clear_has_form_entry();
-  features_.clear_engagement_score();
-  features_.clear_tab_domain();
+// For the TFNative model, test a known-good result with empty features.
+TEST(SmartDimTfNativeModelTest, OptionalFeaturesMissing) {
+  base::test::ScopedTaskEnvironment env;
+  SmartDimFeatureFlags flags;
+  flags.Initialize(false /* use_ml_service */, -0.1 /* dim_threshold */);
 
-  const float inactivity_score = CalculateInactivityScore(features_);
+  SmartDimModelImpl smart_dim_model;
+
+  UserActivityEvent::Features features = DefaultFeatures();
+  features.clear_battery_percent();
+  features.clear_time_since_last_key_sec();
+  features.clear_time_since_last_mouse_sec();
+  features.clear_time_since_video_ended_sec();
+  features.clear_source_id();
+  features.clear_has_form_entry();
+  features.clear_engagement_score();
+  features.clear_tab_domain();
+
+  float inactivity_score;
+  EXPECT_EQ(SmartDimModelResult::kSuccess,
+            smart_dim_model.CalculateInactivityScoreTfNative(
+                features, &inactivity_score));
   // Score has been calculated outside of chrome.
   EXPECT_FLOAT_EQ(-1.9680425, inactivity_score);
 }
 
-TEST_F(SmartDimModelImplTest, ShouldNotDim) {
-  const std::map<std::string, std::string> params = {
-      {"dim_threshold", base::NumberToString(-0.1)}};
-  base::test::ScopedFeatureList scoped_feature_list;
-  scoped_feature_list.InitAndEnableFeatureWithParameters(
-      features::kUserActivityPrediction, params);
+TEST_P(SmartDimModelImplTest, ShouldNotDim) {
+  SmartDimFeatureFlags flags;
+  flags.Initialize(UsesMlService(), -0.1 /* dim_threshold */);
+
+  SmartDimModelImpl smart_dim_model;
+  if (UsesMlService())
+    InjectFakeMlServiceClient(&smart_dim_model);
 
   bool callback_done = false;
-  smart_dim_model_.RequestDimDecision(
-      features_, base::BindOnce(
-                     [](bool* callback_done,
-                        UserActivityEvent::ModelPrediction prediction) {
-                       EXPECT_EQ(UserActivityEvent::ModelPrediction::NO_DIM,
-                                 prediction.response());
-                       EXPECT_EQ(47, prediction.decision_threshold());
-                       EXPECT_EQ(2, prediction.inactivity_score());
-                       *callback_done = true;
-                     },
-                     &callback_done));
+  smart_dim_model.RequestDimDecision(
+      DefaultFeatures(), base::BindOnce(
+                             [](bool* callback_done,
+                                UserActivityEvent::ModelPrediction prediction) {
+                               EXPECT_EQ(
+                                   UserActivityEvent::ModelPrediction::NO_DIM,
+                                   prediction.response());
+                               EXPECT_EQ(47, prediction.decision_threshold());
+                               EXPECT_EQ(2, prediction.inactivity_score());
+                               *callback_done = true;
+                             },
+                             &callback_done));
   scoped_task_environment_.RunUntilIdle();
   EXPECT_TRUE(callback_done);
 }
 
-TEST_F(SmartDimModelImplTest, ShouldDim) {
-  const std::map<std::string, std::string> params = {
-      {"dim_threshold", base::NumberToString(-10)}};
-  base::test::ScopedFeatureList scoped_feature_list;
-  scoped_feature_list.InitAndEnableFeatureWithParameters(
-      features::kUserActivityPrediction, params);
+TEST_P(SmartDimModelImplTest, ShouldDim) {
+  SmartDimFeatureFlags flags;
+  flags.Initialize(UsesMlService(), -10.0 /* dim_threshold */);
+
+  SmartDimModelImpl smart_dim_model;
+  if (UsesMlService())
+    InjectFakeMlServiceClient(&smart_dim_model);
 
   bool callback_done = false;
-  smart_dim_model_.RequestDimDecision(
-      features_, base::BindOnce(
-                     [](bool* callback_done,
-                        UserActivityEvent::ModelPrediction prediction) {
-                       EXPECT_EQ(UserActivityEvent::ModelPrediction::DIM,
-                                 prediction.response());
-                       EXPECT_EQ(0, prediction.decision_threshold());
-                       EXPECT_EQ(2, prediction.inactivity_score());
-                       *callback_done = true;
-                     },
-                     &callback_done));
+  smart_dim_model.RequestDimDecision(
+      DefaultFeatures(), base::BindOnce(
+                             [](bool* callback_done,
+                                UserActivityEvent::ModelPrediction prediction) {
+                               EXPECT_EQ(
+                                   UserActivityEvent::ModelPrediction::DIM,
+                                   prediction.response());
+                               EXPECT_EQ(0, prediction.decision_threshold());
+                               EXPECT_EQ(2, prediction.inactivity_score());
+                               *callback_done = true;
+                             },
+                             &callback_done));
   scoped_task_environment_.RunUntilIdle();
   EXPECT_TRUE(callback_done);
 }
 
 // Check that CancelableCallback ensures a callback doesn't execute twice, in
 // case two RequestDimDecision() calls were made before any callback ran.
-TEST_F(SmartDimModelImplTest, CheckCancelableCallback) {
-  const std::map<std::string, std::string> params = {
-      {"dim_threshold", base::NumberToString(-10)}};
-  base::test::ScopedFeatureList scoped_feature_list;
-  scoped_feature_list.InitAndEnableFeatureWithParameters(
-      features::kUserActivityPrediction, params);
+TEST_P(SmartDimModelImplTest, CheckCancelableCallback) {
+  SmartDimFeatureFlags flags;
+  flags.Initialize(UsesMlService(), -10.0 /* dim_threshold */);
+
+  SmartDimModelImpl smart_dim_model;
+  if (UsesMlService())
+    InjectFakeMlServiceClient(&smart_dim_model);
 
   bool callback_done = false;
   int num_callbacks_run = 0;
   for (int i = 0; i < 2; i++) {
-    smart_dim_model_.RequestDimDecision(
-        features_, base::BindOnce(
-                       [](bool* callback_done, int* num_callbacks_run,
-                          UserActivityEvent::ModelPrediction prediction) {
-                         EXPECT_EQ(UserActivityEvent::ModelPrediction::DIM,
-                                   prediction.response());
-                         EXPECT_EQ(0, prediction.decision_threshold());
-                         EXPECT_EQ(2, prediction.inactivity_score());
-                         *callback_done = true;
-                         (*num_callbacks_run)++;
-                       },
-                       &callback_done, &num_callbacks_run));
+    smart_dim_model.RequestDimDecision(
+        DefaultFeatures(),
+        base::BindOnce(
+            [](bool* callback_done, int* num_callbacks_run,
+               UserActivityEvent::ModelPrediction prediction) {
+              EXPECT_EQ(UserActivityEvent::ModelPrediction::DIM,
+                        prediction.response());
+              EXPECT_EQ(0, prediction.decision_threshold());
+              EXPECT_EQ(2, prediction.inactivity_score());
+              *callback_done = true;
+              (*num_callbacks_run)++;
+            },
+            &callback_done, &num_callbacks_run));
   }
   scoped_task_environment_.RunUntilIdle();
   EXPECT_TRUE(callback_done);
@@ -178,26 +265,31 @@
 
 // Check that CancelPreviousRequest() can successfully prevent a previous
 // requested dim decision request from running.
-TEST_F(SmartDimModelImplTest, CheckCanceledRequest) {
-  const std::map<std::string, std::string> params = {
-      {"dim_threshold", base::NumberToString(-10)}};
-  base::test::ScopedFeatureList scoped_feature_list;
-  scoped_feature_list.InitAndEnableFeatureWithParameters(
-      features::kUserActivityPrediction, params);
+TEST_P(SmartDimModelImplTest, CheckCanceledRequest) {
+  SmartDimFeatureFlags flags;
+  flags.Initialize(UsesMlService(), -10.0 /* dim_threshold */);
+
+  SmartDimModelImpl smart_dim_model;
+  if (UsesMlService())
+    InjectFakeMlServiceClient(&smart_dim_model);
 
   bool callback_done = false;
-  smart_dim_model_.RequestDimDecision(
-      features_, base::BindOnce(
-                     [](bool* callback_done,
-                        UserActivityEvent::ModelPrediction prediction) {
-                       *callback_done = true;
-                     },
-                     &callback_done));
-  smart_dim_model_.CancelPreviousRequest();
+  smart_dim_model.RequestDimDecision(
+      DefaultFeatures(), base::BindOnce(
+                             [](bool* callback_done,
+                                UserActivityEvent::ModelPrediction prediction) {
+                               *callback_done = true;
+                             },
+                             &callback_done));
+  smart_dim_model.CancelPreviousRequest();
   scoped_task_environment_.RunUntilIdle();
   EXPECT_FALSE(callback_done);
 }
 
+INSTANTIATE_TEST_SUITE_P(SmartDimModelImplTests,
+                         SmartDimModelImplTest,
+                         testing::Bool());
+
 }  // namespace ml
 }  // namespace power
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/power/ml/user_activity_manager_unittest.cc b/chrome/browser/chromeos/power/ml/user_activity_manager_unittest.cc
index c4606f8..3790ac4 100644
--- a/chrome/browser/chromeos/power/ml/user_activity_manager_unittest.cc
+++ b/chrome/browser/chromeos/power/ml/user_activity_manager_unittest.cc
@@ -156,7 +156,7 @@
   }
 
   // TODO(crbug.com/893425): Add unit tests that test this API.
-  void CancelPreviousRequest() override { cancelable_callback_.Cancel(); };
+  void CancelPreviousRequest() override { cancelable_callback_.Cancel(); }
 
  private:
   int inactivity_score_ = -1;
diff --git a/chrome/browser/chromeos/smb_client/smb_service.cc b/chrome/browser/chromeos/smb_client/smb_service.cc
index 0655a59..a5c0b569 100644
--- a/chrome/browser/chromeos/smb_client/smb_service.cc
+++ b/chrome/browser/chromeos/smb_client/smb_service.cc
@@ -121,7 +121,9 @@
   }
 }
 
-SmbService::~SmbService() {}
+SmbService::~SmbService() {
+  net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
+}
 
 // static
 SmbService* SmbService::Get(content::BrowserContext* context) {
@@ -525,6 +527,7 @@
       base::BindRepeating(&SmbService::RequestUpdatedSharePath,
                           base::Unretained(this))));
   RestoreMounts();
+  net::NetworkChangeNotifier::AddNetworkChangeObserver(this);
 }
 
 void SmbService::FireMountCallback(MountResponse callback,
@@ -662,6 +665,22 @@
          previous_host_discovery_time_ + kHostDiscoveryInterval;
 }
 
+void SmbService::OnNetworkChanged(
+    net::NetworkChangeNotifier::ConnectionType type) {
+  user_manager::User* user =
+      chromeos::ProfileHelper::Get()->GetUserByProfile(profile_);
+
+  if (!user) {
+    // If a network change occurs on the lockscreen, do nothing.
+    return;
+  }
+
+  // Run host discovery to refresh list of cached hosts for subsequent name
+  // resolution attempts.
+  share_finder_->DiscoverHostsInNetwork(base::DoNothing()
+                                        /* HostDiscoveryResponse */);
+}
+
 void SmbService::RecordMountCount() const {
   const std::vector<ProvidedFileSystemInfo> file_systems =
       GetProviderService()->GetProvidedFileSystemInfoList(provider_id_);
diff --git a/chrome/browser/chromeos/smb_client/smb_service.h b/chrome/browser/chromeos/smb_client/smb_service.h
index 076faf0f..b74dd9d5 100644
--- a/chrome/browser/chromeos/smb_client/smb_service.h
+++ b/chrome/browser/chromeos/smb_client/smb_service.h
@@ -25,6 +25,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chromeos/dbus/smb_provider_client.h"
 #include "components/keyed_service/core/keyed_service.h"
+#include "net/base/network_change_notifier.h"
 
 namespace base {
 class FilePath;
@@ -46,6 +47,7 @@
 
 // Creates and manages an smb file system.
 class SmbService : public KeyedService,
+                   public net::NetworkChangeNotifier::NetworkChangeObserver,
                    public base::SupportsWeakPtr<SmbService> {
  public:
   using MountResponse = base::OnceCallback<void(SmbMountResult result)>;
@@ -245,6 +247,11 @@
   // false if HostDiscovery was recently run.
   bool ShouldRunHostDiscoveryAgain() const;
 
+  // NetworkChangeNotifier::NetworkChangeObserver override. Runs HostDiscovery
+  // when network detects a change.
+  void OnNetworkChanged(
+      net::NetworkChangeNotifier::ConnectionType type) override;
+
   // Records metrics on the number of SMB mounts a user has.
   void RecordMountCount() const;
 
diff --git a/chrome/browser/component_updater/optimization_hints_component_installer.cc b/chrome/browser/component_updater/optimization_hints_component_installer.cc
index c6a50aa2..6d796a8 100644
--- a/chrome/browser/component_updater/optimization_hints_component_installer.cc
+++ b/chrome/browser/component_updater/optimization_hints_component_installer.cc
@@ -26,6 +26,8 @@
 
 namespace {
 
+const char kDisableInstallerUpdate[] = "optimization-guide-disable-installer";
+
 // The extension id is: lmelglejhemejginpboagddgdfbepgmp
 const uint8_t kOptimizationHintsPublicKeySHA256[32] = {
     0xbc, 0x4b, 0x6b, 0x49, 0x74, 0xc4, 0x96, 0x8d, 0xf1, 0xe0, 0x63,
@@ -89,7 +91,9 @@
   }
   optimization_guide::OptimizationGuideService* optimization_guide_service =
       g_browser_process->optimization_guide_service();
-  if (optimization_guide_service) {
+  if (optimization_guide_service &&
+      !base::CommandLine::ForCurrentProcess()->HasSwitch(
+          kDisableInstallerUpdate)) {
     optimization_guide::HintsComponentInfo info(
         version,
         install_dir.Append(optimization_guide::kUnindexedHintsFileName));
diff --git a/chrome/browser/extensions/active_tab_permission_granter.cc b/chrome/browser/extensions/active_tab_permission_granter.cc
index 16c2bbd4..1615b29 100644
--- a/chrome/browser/extensions/active_tab_permission_granter.cc
+++ b/chrome/browser/extensions/active_tab_permission_granter.cc
@@ -154,7 +154,7 @@
   if (!new_apis.empty() || !new_hosts.is_empty()) {
     granted_extensions_.Insert(extension);
     PermissionSet new_permissions(std::move(new_apis), ManifestPermissionSet(),
-                                  new_hosts, new_hosts);
+                                  new_hosts.Clone(), new_hosts.Clone());
     permissions_data->UpdateTabSpecificPermissions(tab_id_, new_permissions);
     content::NavigationEntry* navigation_entry =
         web_contents()->GetController().GetVisibleEntry();
diff --git a/chrome/browser/extensions/api/chrome_extensions_api_client.cc b/chrome/browser/extensions/api/chrome_extensions_api_client.cc
index 25e9e3ee..bf53f91 100644
--- a/chrome/browser/extensions/api/chrome_extensions_api_client.cc
+++ b/chrome/browser/extensions/api/chrome_extensions_api_client.cc
@@ -36,6 +36,7 @@
 #include "chrome/browser/search/instant_io_context.h"
 #include "chrome/browser/ui/pdf/chrome_pdf_web_contents_helper_client.h"
 #include "chrome/browser/ui/webui/devtools_ui.h"
+#include "chrome/common/url_constants.h"
 #include "chrome/common/webui_url_constants.h"
 #include "components/pdf/browser/pdf_web_contents_helper.h"
 #include "components/signin/core/browser/signin_header_helper.h"
@@ -119,10 +120,9 @@
     const WebRequestInfo& request) const {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
 
-  // TODO(crbug.com/890006): Determine if the code here can be cleaned up
-  // since browser initiated non-navigation requests are now hidden from
-  // extensions.
-
+  // Note: browser initiated non-navigation requests are hidden from extensions.
+  // But we do still need to protect some sensitive sub-frame navigation
+  // requests.
   // Exclude main frame navigation requests.
   bool is_browser_request = request.render_process_id == -1 &&
                             request.type != content::RESOURCE_TYPE_MAIN_FRAME;
@@ -137,6 +137,12 @@
        request.initiator ==
            url::Origin::Create(GURL(chrome::kChromeUINewTabURL)));
 
+  // Hide requests made by the browser on behalf of the local NTP.
+  is_sensitive_request |=
+      (is_browser_request &&
+       request.initiator ==
+           url::Origin::Create(GURL(chrome::kChromeSearchLocalNtpUrl)));
+
   // Hide requests made by the NTP Instant renderer.
   is_sensitive_request |= InstantIOContext::IsInstantProcess(
       request.resource_context, request.render_process_id);
diff --git a/chrome/browser/extensions/api/developer_private/developer_private_api.cc b/chrome/browser/extensions/api/developer_private/developer_private_api.cc
index 9c14f31..93b9840 100644
--- a/chrome/browser/extensions/api/developer_private/developer_private_api.cc
+++ b/chrome/browser/extensions/api/developer_private/developer_private_api.cc
@@ -2014,7 +2014,8 @@
       .GrantRuntimePermissions(
           *extension,
           PermissionSet(APIPermissionSet(), ManifestPermissionSet(),
-                        new_host_permissions, new_host_permissions),
+                        new_host_permissions.Clone(),
+                        new_host_permissions.Clone()),
           base::BindOnce(&DeveloperPrivateAddHostPermissionFunction::
                              OnRuntimePermissionsGranted,
                          base::RetainedRef(this)));
@@ -2054,7 +2055,8 @@
   std::unique_ptr<const PermissionSet> permissions_to_remove =
       PermissionSet::CreateIntersection(
           PermissionSet(APIPermissionSet(), ManifestPermissionSet(),
-                        host_permissions_to_remove, host_permissions_to_remove),
+                        host_permissions_to_remove.Clone(),
+                        host_permissions_to_remove.Clone()),
           *scripting_modifier.GetRevokablePermissions(),
           URLPatternSet::IntersectionBehavior::kDetailed);
   if (permissions_to_remove->IsEmpty())
diff --git a/chrome/browser/extensions/api/developer_private/developer_private_api_unittest.cc b/chrome/browser/extensions/api/developer_private/developer_private_api_unittest.cc
index bd2f24d2..d04549c5 100644
--- a/chrome/browser/extensions/api/developer_private/developer_private_api_unittest.cc
+++ b/chrome/browser/extensions/api/developer_private/developer_private_api_unittest.cc
@@ -1644,8 +1644,8 @@
 
   URLPatternSet hosts({URLPattern(Extension::kValidHostPermissionSchemes,
                                   "https://example.com/*")});
-  PermissionSet permissions(APIPermissionSet(), ManifestPermissionSet(), hosts,
-                            hosts);
+  PermissionSet permissions(APIPermissionSet(), ManifestPermissionSet(),
+                            hosts.Clone(), hosts.Clone());
   permissions_test_util::GrantRuntimePermissionsAndWaitForCompletion(
       profile(), *extension, permissions);
 
diff --git a/chrome/browser/extensions/api/enterprise_reporting_private/chrome_desktop_report_request_helper.cc b/chrome/browser/extensions/api/enterprise_reporting_private/chrome_desktop_report_request_helper.cc
index 1fc47dd8..c754c5b 100644
--- a/chrome/browser/extensions/api/enterprise_reporting_private/chrome_desktop_report_request_helper.cc
+++ b/chrome/browser/extensions/api/enterprise_reporting_private/chrome_desktop_report_request_helper.cc
@@ -114,7 +114,7 @@
     request->mutable_browser_report()
         ->mutable_chrome_user_profile_reports(0)
         ->set_policy_data(
-            policy::GetAllPolicyValuesAsJSON(profile, true, false));
+            policy::GetAllPolicyValuesAsJSON(profile, true, false, false));
 
     int64_t timestamp = GetMachineLevelUserCloudPolicyFetchTimestamp();
     if (timestamp > 0) {
diff --git a/chrome/browser/extensions/api/file_system/file_system_apitest_chromeos.cc b/chrome/browser/extensions/api/file_system/file_system_apitest_chromeos.cc
index cbfc974..2b605066 100644
--- a/chrome/browser/extensions/api/file_system/file_system_apitest_chromeos.cc
+++ b/chrome/browser/extensions/api/file_system/file_system_apitest_chromeos.cc
@@ -159,7 +159,7 @@
   void TearDown() override {
     FileSystemChooseEntryFunction::StopSkippingPickerForTest();
     PlatformAppBrowserTest::TearDown();
-  };
+  }
 
   base::FilePath GetDriveMountPoint() {
     if (base::FeatureList::IsEnabled(chromeos::features::kDriveFs)) {
diff --git a/chrome/browser/extensions/api/messaging/native_message_host_chromeos.cc b/chrome/browser/extensions/api/messaging/native_message_host_chromeos.cc
index 9a5e8ef..b262d1f0 100644
--- a/chrome/browser/extensions/api/messaging/native_message_host_chromeos.cc
+++ b/chrome/browser/extensions/api/messaging/native_message_host_chromeos.cc
@@ -63,11 +63,11 @@
     } else {
       ProcessEcho(*request);
     }
-  };
+  }
 
   scoped_refptr<base::SingleThreadTaskRunner> task_runner() const override {
     return base::ThreadTaskRunnerHandle::Get();
-  };
+  }
 
  private:
   void ProcessEcho(const base::DictionaryValue& request) {
diff --git a/chrome/browser/extensions/api/permissions/permissions_api.cc b/chrome/browser/extensions/api/permissions/permissions_api.cc
index 524f1220..7065b38 100644
--- a/chrome/browser/extensions/api/permissions/permissions_api.cc
+++ b/chrome/browser/extensions/api/permissions/permissions_api.cc
@@ -163,7 +163,7 @@
 
   PermissionSet permissions(
       std::move(unpack_result->optional_apis), ManifestPermissionSet(),
-      unpack_result->optional_explicit_hosts, URLPatternSet());
+      std::move(unpack_result->optional_explicit_hosts), URLPatternSet());
 
   // Only try and remove those permissions that are active on the extension.
   // For backwards compatability with behavior before this check was added, just
@@ -255,15 +255,15 @@
   // are "new", i.e. aren't already active on the extension.
   requested_optional_ = std::make_unique<const PermissionSet>(
       std::move(unpack_result->optional_apis), ManifestPermissionSet(),
-      unpack_result->optional_explicit_hosts, URLPatternSet());
+      std::move(unpack_result->optional_explicit_hosts), URLPatternSet());
   requested_optional_ =
       PermissionSet::CreateDifference(*requested_optional_, active_permissions);
 
   // Do the same for withheld permissions.
   requested_withheld_ = std::make_unique<const PermissionSet>(
       APIPermissionSet(), ManifestPermissionSet(),
-      unpack_result->required_explicit_hosts,
-      unpack_result->required_scriptable_hosts);
+      std::move(unpack_result->required_explicit_hosts),
+      std::move(unpack_result->required_scriptable_hosts));
   requested_withheld_ =
       PermissionSet::CreateDifference(*requested_withheld_, active_permissions);
 
diff --git a/chrome/browser/extensions/api/permissions/permissions_api_helpers_unittest.cc b/chrome/browser/extensions/api/permissions/permissions_api_helpers_unittest.cc
index e2cffeb0..12c46b9 100644
--- a/chrome/browser/extensions/api/permissions/permissions_api_helpers_unittest.cc
+++ b/chrome/browser/extensions/api/permissions/permissions_api_helpers_unittest.cc
@@ -44,9 +44,9 @@
        URLPattern(UserScript::ValidUserScriptSchemes(), "http://d.com/*")});
 
   // Pack the permission set to value and verify its contents.
-  std::unique_ptr<Permissions> pack_result(
-      PackPermissionSet(PermissionSet(std::move(apis), ManifestPermissionSet(),
-                                      explicit_hosts, scriptable_hosts)));
+  std::unique_ptr<Permissions> pack_result(PackPermissionSet(
+      PermissionSet(std::move(apis), ManifestPermissionSet(),
+                    std::move(explicit_hosts), std::move(scriptable_hosts))));
   ASSERT_TRUE(pack_result);
   ASSERT_TRUE(pack_result->permissions);
   EXPECT_THAT(*pack_result->permissions,
@@ -75,9 +75,9 @@
   optional_apis.insert(APIPermission::kTab);
   URLPatternSet optional_explicit_hosts(
       {URLPattern(Extension::kValidHostPermissionSchemes, "http://a.com/*")});
-  PermissionSet optional_permissions(std::move(optional_apis),
-                                     ManifestPermissionSet(),
-                                     optional_explicit_hosts, URLPatternSet());
+  PermissionSet optional_permissions(
+      std::move(optional_apis), ManifestPermissionSet(),
+      std::move(optional_explicit_hosts), URLPatternSet());
 
   // Origins shouldn't have to be present.
   {
@@ -229,11 +229,11 @@
   });
 
   PermissionSet required_permissions(
-      APIPermissionSet(), ManifestPermissionSet(), required_explicit_hosts,
-      required_scriptable_hosts);
-  PermissionSet optional_permissions(APIPermissionSet(),
-                                     ManifestPermissionSet(),
-                                     optional_explicit_hosts, URLPatternSet());
+      APIPermissionSet(), ManifestPermissionSet(),
+      std::move(required_explicit_hosts), std::move(required_scriptable_hosts));
+  PermissionSet optional_permissions(
+      APIPermissionSet(), ManifestPermissionSet(),
+      std::move(optional_explicit_hosts), URLPatternSet());
 
   Permissions permissions_object;
   permissions_object.origins =
diff --git a/chrome/browser/extensions/api/permissions/permissions_api_unittest.cc b/chrome/browser/extensions/api/permissions/permissions_api_unittest.cc
index 5ff3bb1..dfb7fcf 100644
--- a/chrome/browser/extensions/api/permissions/permissions_api_unittest.cc
+++ b/chrome/browser/extensions/api/permissions/permissions_api_unittest.cc
@@ -294,7 +294,7 @@
     permissions_test_util::GrantRuntimePermissionsAndWaitForCompletion(
         profile(), *extension,
         PermissionSet(APIPermissionSet(), ManifestPermissionSet(),
-                      explicit_hosts, URLPatternSet()));
+                      std::move(explicit_hosts), URLPatternSet()));
     const GURL example_url("https://example.com");
     const PermissionSet& active_permissions =
         extension->permissions_data()->active_permissions();
diff --git a/chrome/browser/extensions/api/permissions/permissions_apitest.cc b/chrome/browser/extensions/api/permissions/permissions_apitest.cc
index fd210d82..15317c48 100644
--- a/chrome/browser/extensions/api/permissions/permissions_apitest.cc
+++ b/chrome/browser/extensions/api/permissions/permissions_apitest.cc
@@ -89,8 +89,8 @@
   ExtensionPrefs* prefs = ExtensionPrefs::Get(browser()->profile());
   prefs->AddRuntimeGrantedPermissions(
       "kjmkgkdkpedkejedfhmfcenooemhbpbo",
-      PermissionSet(std::move(apis), ManifestPermissionSet(), explicit_hosts,
-                    URLPatternSet()));
+      PermissionSet(std::move(apis), ManifestPermissionSet(),
+                    std::move(explicit_hosts), URLPatternSet()));
 
   PermissionsRequestFunction::SetIgnoreUserGestureForTests(true);
   ASSERT_TRUE(StartEmbeddedTestServer());
diff --git a/chrome/browser/extensions/api/runtime/chrome_runtime_api_delegate.cc b/chrome/browser/extensions/api/runtime/chrome_runtime_api_delegate.cc
index ddc4aa0..60918e08 100644
--- a/chrome/browser/extensions/api/runtime/chrome_runtime_api_delegate.cc
+++ b/chrome/browser/extensions/api/runtime/chrome_runtime_api_delegate.cc
@@ -278,7 +278,9 @@
   Profile* profile = Profile::FromBrowserContext(browser_context_);
   Browser* browser = chrome::FindLastActiveWithProfile(profile);
   if (!browser)
-    browser = new Browser(Browser::CreateParams(profile, false));
+    browser = Browser::Create(Browser::CreateParams(profile, false));
+  if (!browser)
+    return;
 
   NavigateParams params(browser, uninstall_url,
                         ui::PAGE_TRANSITION_CLIENT_REDIRECT);
diff --git a/chrome/browser/extensions/api/tabs/tabs_api.cc b/chrome/browser/extensions/api/tabs/tabs_api.cc
index edfe45a3..8a397739 100644
--- a/chrome/browser/extensions/api/tabs/tabs_api.cc
+++ b/chrome/browser/extensions/api/tabs/tabs_api.cc
@@ -632,7 +632,9 @@
         ConvertToWindowShowState(create_data->state);
   }
 
-  Browser* new_window = new Browser(create_params);
+  Browser* new_window = Browser::Create(create_params);
+  if (!new_window)
+    return RespondNow(Error(tabs_constants::kBrowserWindowNotAllowed));
 
   for (const GURL& url : urls) {
     NavigateParams navigate_params(new_window, url, ui::PAGE_TRANSITION_LINK);
diff --git a/chrome/browser/extensions/api/tabs/tabs_constants.cc b/chrome/browser/extensions/api/tabs/tabs_constants.cc
index abe7720..ed8ab5f 100644
--- a/chrome/browser/extensions/api/tabs/tabs_constants.cc
+++ b/chrome/browser/extensions/api/tabs/tabs_constants.cc
@@ -116,6 +116,7 @@
 const char kJavaScriptUrlsNotAllowedInTabsUpdate[] =
     "JavaScript URLs are not allowed in chrome.tabs.update. Use "
     "chrome.tabs.executeScript instead.";
+const char kBrowserWindowNotAllowed[] = "Browser windows not allowed.";
 
 }  // namespace tabs_constants
 }  // namespace extensions
diff --git a/chrome/browser/extensions/api/tabs/tabs_constants.h b/chrome/browser/extensions/api/tabs/tabs_constants.h
index 286da52..a58d601 100644
--- a/chrome/browser/extensions/api/tabs/tabs_constants.h
+++ b/chrome/browser/extensions/api/tabs/tabs_constants.h
@@ -106,6 +106,7 @@
 extern const char kCannotDetermineLanguageOfUnloadedTab[];
 extern const char kMissingLockWindowFullscreenPrivatePermission[];
 extern const char kJavaScriptUrlsNotAllowedInTabsUpdate[];
+extern const char kBrowserWindowNotAllowed[];
 
 }  // namespace tabs_constants
 }  // namespace extensions
diff --git a/chrome/browser/extensions/api/terminal/terminal_private_apitest.cc b/chrome/browser/extensions/api/terminal/terminal_private_apitest.cc
index f14022f..5a5e25b 100644
--- a/chrome/browser/extensions/api/terminal/terminal_private_apitest.cc
+++ b/chrome/browser/extensions/api/terminal/terminal_private_apitest.cc
@@ -18,4 +18,4 @@
 IN_PROC_BROWSER_TEST_F(ExtensionTerminalPrivateApiTest, TerminalTest) {
   EXPECT_TRUE(RunExtensionSubtest("terminal/component_extension", "test.html"))
       << message_;
-};
+}
diff --git a/chrome/browser/extensions/api/web_request/web_request_permissions_unittest.cc b/chrome/browser/extensions/api/web_request/web_request_permissions_unittest.cc
index bf9be3b..5e25be0 100644
--- a/chrome/browser/extensions/api/web_request/web_request_permissions_unittest.cc
+++ b/chrome/browser/extensions/api/web_request/web_request_permissions_unittest.cc
@@ -8,6 +8,7 @@
 
 #include "base/macros.h"
 #include "chrome/common/extensions/extension_test_util.h"
+#include "chrome/common/url_constants.h"
 #include "chromeos/login/login_state/scoped_test_public_session_login_state.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "extensions/browser/api/web_request/web_request_info.h"
@@ -123,6 +124,37 @@
       WebRequestPermissions::HideRequest(extension_info_map_.get(), request));
 }
 
+// Ensure requests made by the local NTP are hidden from extensions. Regression
+// test for crbug.com/931013.
+TEST_F(ExtensionWebRequestHelpersTestWithThreadsTest, LocalNTPRequests) {
+  const GURL example_com("http://example.com");
+
+  WebRequestInfo info;
+  info.url = example_com;
+  info.initiator = url::Origin::Create(GURL(chrome::kChromeSearchLocalNtpUrl));
+  info.render_process_id = -1;
+
+  // Sub-resource browser initiated requests are hidden from extensions.
+  info.type = content::RESOURCE_TYPE_SUB_RESOURCE;
+  info.web_request_type = extensions::WebRequestResourceType::OTHER;
+  info.is_browser_side_navigation = false;
+  EXPECT_TRUE(
+      WebRequestPermissions::HideRequest(extension_info_map_.get(), info));
+
+  // Sub-frame navigations initiated from the local ntp should be hidden.
+  info.type = content::RESOURCE_TYPE_SUB_FRAME;
+  info.web_request_type = extensions::WebRequestResourceType::SUB_FRAME;
+  info.is_browser_side_navigation = true;
+  EXPECT_TRUE(
+      WebRequestPermissions::HideRequest(extension_info_map_.get(), info));
+
+  // Sub-frame navigations initiated from a non-sensitive domain should not be
+  // hidden.
+  info.initiator = url::Origin::Create(example_com);
+  EXPECT_FALSE(
+      WebRequestPermissions::HideRequest(extension_info_map_.get(), info));
+}
+
 TEST_F(ExtensionWebRequestHelpersTestWithThreadsTest,
        TestCanExtensionAccessURL_HostPermissions) {
   // Request with empty initiator.
diff --git a/chrome/browser/extensions/extension_prefs_unittest.cc b/chrome/browser/extensions/extension_prefs_unittest.cc
index 4b7ef8df..02c665c 100644
--- a/chrome/browser/extensions/extension_prefs_unittest.cc
+++ b/chrome/browser/extensions/extension_prefs_unittest.cc
@@ -204,8 +204,6 @@
     AddPattern(&shost_permissions_, "http://somesite.com/*");
     AddPattern(&shost_permissions_, "http://example.com/*");
 
-    URLPatternSet empty_extent;
-
     // Make sure both granted api and host permissions start empty.
     EXPECT_TRUE(prefs()->GetGrantedPermissions(extension_id_)->IsEmpty());
 
@@ -214,7 +212,7 @@
       prefs()->AddGrantedPermissions(
           extension_id_,
           PermissionSet(api_perm_set1_.Clone(), ManifestPermissionSet(),
-                        empty_extent, empty_extent));
+                        URLPatternSet(), URLPatternSet()));
       std::unique_ptr<const PermissionSet> granted_permissions =
           prefs()->GetGrantedPermissions(extension_id_);
       EXPECT_TRUE(granted_permissions.get());
@@ -228,7 +226,7 @@
       prefs()->AddGrantedPermissions(
           extension_id_,
           PermissionSet(APIPermissionSet(), ManifestPermissionSet(),
-                        ehost_perm_set1_, empty_extent));
+                        ehost_perm_set1_.Clone(), URLPatternSet()));
       std::unique_ptr<const PermissionSet> granted_permissions =
           prefs()->GetGrantedPermissions(extension_id_);
       EXPECT_FALSE(granted_permissions->IsEmpty());
@@ -242,7 +240,7 @@
       prefs()->AddGrantedPermissions(
           extension_id_,
           PermissionSet(APIPermissionSet(), ManifestPermissionSet(),
-                        empty_extent, shost_perm_set1_));
+                        URLPatternSet(), shost_perm_set1_.Clone()));
       std::unique_ptr<const PermissionSet> granted_permissions =
           prefs()->GetGrantedPermissions(extension_id_);
       EXPECT_FALSE(granted_permissions->IsEmpty());
@@ -261,7 +259,7 @@
       prefs()->AddGrantedPermissions(
           extension_id_,
           PermissionSet(api_perm_set2_.Clone(), ManifestPermissionSet(),
-                        ehost_perm_set2_, shost_perm_set2_));
+                        ehost_perm_set2_.Clone(), shost_perm_set2_.Clone()));
 
       std::unique_ptr<const PermissionSet> granted_permissions =
           prefs()->GetGrantedPermissions(extension_id_);
@@ -309,22 +307,25 @@
   void Initialize() override {
     extension_id_ = prefs_.AddExtensionAndReturnId("test");
 
-    APIPermissionSet api_perms;
-    api_perms.insert(APIPermission::kTab);
-    api_perms.insert(APIPermission::kBookmark);
-    api_perms.insert(APIPermission::kHistory);
+    {
+      APIPermissionSet api_perms;
+      api_perms.insert(APIPermission::kTab);
+      api_perms.insert(APIPermission::kBookmark);
+      api_perms.insert(APIPermission::kHistory);
 
-    URLPatternSet ehosts;
-    AddPattern(&ehosts, "http://*.google.com/*");
-    AddPattern(&ehosts, "http://example.com/*");
-    AddPattern(&ehosts, "chrome://favicon/*");
+      URLPatternSet ehosts;
+      AddPattern(&ehosts, "http://*.google.com/*");
+      AddPattern(&ehosts, "http://example.com/*");
+      AddPattern(&ehosts, "chrome://favicon/*");
 
-    URLPatternSet shosts;
-    AddPattern(&shosts, "https://*.google.com/*");
-    AddPattern(&shosts, "http://reddit.com/r/test/*");
+      URLPatternSet shosts;
+      AddPattern(&shosts, "https://*.google.com/*");
+      AddPattern(&shosts, "http://reddit.com/r/test/*");
 
-    active_perms_.reset(new PermissionSet(
-        api_perms.Clone(), ManifestPermissionSet(), ehosts, shosts));
+      active_perms_.reset(
+          new PermissionSet(std::move(api_perms), ManifestPermissionSet(),
+                            std::move(ehosts), std::move(shosts)));
+    }
 
     // Make sure the active permissions start empty.
     std::unique_ptr<const PermissionSet> active =
@@ -955,11 +956,12 @@
     api_perms.insert(APIPermission::kBookmark);
     api_perms.insert(APIPermission::kHistory);
 
-    URLPatternSet ehosts, shosts;
+    URLPatternSet shosts;
     AddPattern(&shosts, "chrome://print/*");
 
-    active_perms_.reset(new PermissionSet(
-        std::move(api_perms), ManifestPermissionSet(), ehosts, shosts));
+    active_perms_.reset(new PermissionSet(std::move(api_perms),
+                                          ManifestPermissionSet(),
+                                          URLPatternSet(), std::move(shosts)));
     // Set the active permissions.
     prefs()->SetActivePermissions(component_extension_->id(), *active_perms_);
     prefs()->SetActivePermissions(no_component_extension_->id(),
@@ -1031,8 +1033,8 @@
       // correctly added.
       URLPatternSet added_urls({example_com, chromium_org});
       PermissionSet added_permissions(APIPermissionSet(),
-                                      ManifestPermissionSet(), added_urls,
-                                      URLPatternSet());
+                                      ManifestPermissionSet(),
+                                      std::move(added_urls), URLPatternSet());
       prefs()->AddRuntimeGrantedPermissions(extension_a_->id(),
                                             added_permissions);
 
@@ -1046,16 +1048,16 @@
       // Remove one of the hosts. The only remaining host should be
       // example.com
       URLPatternSet removed_urls({chromium_org});
-      PermissionSet removed_permissions(APIPermissionSet(),
-                                        ManifestPermissionSet(), removed_urls,
-                                        URLPatternSet());
+      PermissionSet removed_permissions(
+          APIPermissionSet(), ManifestPermissionSet(), std::move(removed_urls),
+          URLPatternSet());
       prefs()->RemoveRuntimeGrantedPermissions(extension_a_->id(),
                                                removed_permissions);
 
       URLPatternSet remaining_urls({example_com});
-      PermissionSet remaining_permissions(APIPermissionSet(),
-                                          ManifestPermissionSet(),
-                                          remaining_urls, URLPatternSet());
+      PermissionSet remaining_permissions(
+          APIPermissionSet(), ManifestPermissionSet(),
+          std::move(remaining_urls), URLPatternSet());
       std::unique_ptr<const PermissionSet> retrieved_permissions =
           prefs()->GetRuntimeGrantedPermissions(extension_a_->id());
       ASSERT_TRUE(retrieved_permissions);
@@ -1073,9 +1075,9 @@
       // permission.
       URLPattern example_com(URLPattern::SCHEME_ALL, "https://example.com/*");
       URLPatternSet remaining_urls({example_com});
-      PermissionSet remaining_permissions(APIPermissionSet(),
-                                          ManifestPermissionSet(),
-                                          remaining_urls, URLPatternSet());
+      PermissionSet remaining_permissions(
+          APIPermissionSet(), ManifestPermissionSet(),
+          std::move(remaining_urls), URLPatternSet());
       std::unique_ptr<const PermissionSet> retrieved_permissions =
           prefs()->GetRuntimeGrantedPermissions(extension_a_->id());
       ASSERT_TRUE(retrieved_permissions);
diff --git a/chrome/browser/extensions/extension_tab_util.cc b/chrome/browser/extensions/extension_tab_util.cc
index b6fdacf3..5d5e34f 100644
--- a/chrome/browser/extensions/extension_tab_util.cc
+++ b/chrome/browser/extensions/extension_tab_util.cc
@@ -91,7 +91,11 @@
                        bool user_gesture,
                        std::string* error) {
   Browser::CreateParams params(Browser::TYPE_TABBED, profile, user_gesture);
-  Browser* browser = new Browser(params);
+  Browser* browser = Browser::Create(params);
+  if (!browser) {
+    *error = tabs_constants::kBrowserWindowNotAllowed;
+    return nullptr;
+  }
   browser->window()->Show();
   return browser;
 }
@@ -226,7 +230,11 @@
     if (!browser) {
       Browser::CreateParams params =
           Browser::CreateParams(Browser::TYPE_TABBED, profile, user_gesture);
-      browser = new Browser(params);
+      browser = Browser::Create(params);
+      if (!browser) {
+        *error = tabs_constants::kBrowserWindowNotAllowed;
+        return nullptr;
+      }
       browser->window()->Show();
     }
   }
@@ -653,8 +661,12 @@
   const bool browser_created = !browser;
   if (!browser) {
     Browser::CreateParams params = Browser::CreateParams(profile, user_gesture);
-    browser = new Browser(params);
+    browser = Browser::Create(params);
   }
+
+  if (!browser)
+    return;
+
   NavigateParams params(browser, std::move(web_contents));
 
   // The extension_app_id parameter ends up as app_name in the Browser
@@ -706,7 +718,9 @@
   DCHECK(!profile->IsOffTheRecord() || IncognitoInfo::IsSplitMode(extension));
   Browser* browser = chrome::FindBrowserWithProfile(profile);
   if (!browser)
-    browser = new Browser(Browser::CreateParams(profile, true));
+    browser = Browser::Create(Browser::CreateParams(profile, true));
+  if (!browser)
+    return false;
   return extensions::ExtensionTabUtil::OpenOptionsPage(extension, browser);
 }
 
diff --git a/chrome/browser/extensions/permissions_updater.cc b/chrome/browser/extensions/permissions_updater.cc
index 7043b03..02c9dcb 100644
--- a/chrome/browser/extensions/permissions_updater.cc
+++ b/chrome/browser/extensions/permissions_updater.cc
@@ -360,7 +360,7 @@
         active_permissions_to_remove->apis().Clone(),
         active_permissions_to_remove->manifest_permissions().Clone(),
         URLPatternSet(removable_explicit_hosts),
-        active_permissions_to_remove->scriptable_hosts());
+        active_permissions_to_remove->scriptable_hosts().Clone());
   }
 
   CHECK(extension.permissions_data()->active_permissions().Contains(
@@ -537,7 +537,8 @@
   std::unique_ptr<const PermissionSet> new_withheld =
       PermissionSet::CreateDifference(
           PermissionSet(APIPermissionSet(), ManifestPermissionSet(),
-                        required.explicit_hosts(), required.scriptable_hosts()),
+                        required.explicit_hosts().Clone(),
+                        required.scriptable_hosts().Clone()),
           *new_active);
 
   extension->permissions_data()->SetPermissions(std::move(new_active),
diff --git a/chrome/browser/extensions/permissions_updater_unittest.cc b/chrome/browser/extensions/permissions_updater_unittest.cc
index 59c7fd9..69d49bea 100644
--- a/chrome/browser/extensions/permissions_updater_unittest.cc
+++ b/chrome/browser/extensions/permissions_updater_unittest.cc
@@ -173,8 +173,8 @@
   URLPatternSet default_hosts;
   AddPattern(&default_hosts, "http://a.com/*");
   PermissionSet default_permissions(default_apis.Clone(),
-                                    ManifestPermissionSet(), default_hosts,
-                                    URLPatternSet());
+                                    ManifestPermissionSet(),
+                                    std::move(default_hosts), URLPatternSet());
 
   // Make sure it loaded properly.
   ASSERT_EQ(default_permissions,
@@ -191,7 +191,7 @@
   AddPattern(&hosts, "http://*.c.com/*");
 
   {
-    PermissionSet delta(apis.Clone(), ManifestPermissionSet(), hosts,
+    PermissionSet delta(apis.Clone(), ManifestPermissionSet(), hosts.Clone(),
                         URLPatternSet());
 
     PermissionsUpdaterListener listener;
@@ -225,7 +225,7 @@
     // In the second part of the test, we'll remove the permissions that we
     // just added except for 'notifications'.
     apis.erase(APIPermission::kNotifications);
-    PermissionSet delta(apis.Clone(), ManifestPermissionSet(), hosts,
+    PermissionSet delta(apis.Clone(), ManifestPermissionSet(), hosts.Clone(),
                         URLPatternSet());
 
     PermissionsUpdaterListener listener;
@@ -552,9 +552,9 @@
 
   URLPatternSet explicit_hosts({URLPattern(
       Extension::kValidHostPermissionSchemes, "https://example.com/*")});
-  PermissionSet runtime_granted_permissions(APIPermissionSet(),
-                                            ManifestPermissionSet(),
-                                            explicit_hosts, URLPatternSet());
+  PermissionSet runtime_granted_permissions(
+      APIPermissionSet(), ManifestPermissionSet(), std::move(explicit_hosts),
+      URLPatternSet());
 
   // Granting runtime-granted permissions should update the runtime granted
   // permissions store in preferences, but *not* granted permissions in
@@ -620,9 +620,9 @@
 
     URLPatternSet url_pattern_set;
     url_pattern_set.AddOrigin(URLPattern::SCHEME_ALL, kOrigin);
-    const PermissionSet permission_set(APIPermissionSet(),
-                                       ManifestPermissionSet(), url_pattern_set,
-                                       URLPatternSet());
+    const PermissionSet permission_set(
+        APIPermissionSet(), ManifestPermissionSet(), std::move(url_pattern_set),
+        URLPatternSet());
     // Give the extension access to the test site. Now, the test site permission
     // should be revokable.
     permissions_test_util::GrantRuntimePermissionsAndWaitForCompletion(
diff --git a/chrome/browser/extensions/scripting_permissions_modifier.cc b/chrome/browser/extensions/scripting_permissions_modifier.cc
index a6c1bd7..9463806 100644
--- a/chrome/browser/extensions/scripting_permissions_modifier.cc
+++ b/chrome/browser/extensions/scripting_permissions_modifier.cc
@@ -90,7 +90,7 @@
   *granted_permissions_out = std::make_unique<PermissionSet>(
       requested_permissions.apis().Clone(),
       requested_permissions.manifest_permissions().Clone(),
-      granted_explicit_hosts, granted_scriptable_hosts);
+      std::move(granted_explicit_hosts), std::move(granted_scriptable_hosts));
 }
 
 // Returns true if the extension should even be considered for being affected
@@ -202,7 +202,7 @@
 
   return std::make_unique<PermissionSet>(
       permissions->apis().Clone(), permissions->manifest_permissions().Clone(),
-      std::move(new_explicit_hosts), permissions->scriptable_hosts());
+      std::move(new_explicit_hosts), permissions->scriptable_hosts().Clone());
 }
 
 }  // namespace
@@ -348,7 +348,7 @@
       .GrantRuntimePermissions(
           *extension_,
           PermissionSet(APIPermissionSet(), ManifestPermissionSet(),
-                        explicit_hosts, scriptable_hosts),
+                        std::move(explicit_hosts), std::move(scriptable_hosts)),
           base::DoNothing::Once());
 }
 
@@ -385,7 +385,7 @@
       .RevokeRuntimePermissions(
           *extension_,
           PermissionSet(APIPermissionSet(), ManifestPermissionSet(),
-                        explicit_hosts, scriptable_hosts),
+                        std::move(explicit_hosts), std::move(scriptable_hosts)),
           base::DoNothing::Once());
 }
 
@@ -466,8 +466,8 @@
       extension_->permissions_data()->withheld_permissions();
 
   PermissionSet permissions(APIPermissionSet(), ManifestPermissionSet(),
-                            withheld.explicit_hosts(),
-                            withheld.scriptable_hosts());
+                            withheld.explicit_hosts().Clone(),
+                            withheld.scriptable_hosts().Clone());
   PermissionsUpdater(browser_context_)
       .GrantRuntimePermissions(*extension_, permissions,
                                base::DoNothing::Once());
diff --git a/chrome/browser/extensions/scripting_permissions_modifier_unittest.cc b/chrome/browser/extensions/scripting_permissions_modifier_unittest.cc
index 7a95b465..61b5a40 100644
--- a/chrome/browser/extensions/scripting_permissions_modifier_unittest.cc
+++ b/chrome/browser/extensions/scripting_permissions_modifier_unittest.cc
@@ -468,8 +468,8 @@
                                    "https://example.com/*"));
     permissions_test_util::GrantOptionalPermissionsAndWaitForCompletion(
         profile(), *extension,
-        PermissionSet(APIPermissionSet(), ManifestPermissionSet(), patterns,
-                      URLPatternSet()));
+        PermissionSet(APIPermissionSet(), ManifestPermissionSet(),
+                      std::move(patterns), URLPatternSet()));
   }
 
   EXPECT_THAT(GetEffectivePatternsAsStrings(*extension),
@@ -719,7 +719,7 @@
   ExtensionPrefs::Get(profile())->AddRuntimeGrantedPermissions(
       extension->id(),
       PermissionSet(APIPermissionSet(), ManifestPermissionSet(),
-                    google_com_pattern, google_com_pattern));
+                    google_com_pattern.Clone(), google_com_pattern.Clone()));
 
   const GURL google_com("https://google.com");
   {
diff --git a/chrome/browser/extensions/service_worker_apitest.cc b/chrome/browser/extensions/service_worker_apitest.cc
index 9dee818..91925b7 100644
--- a/chrome/browser/extensions/service_worker_apitest.cc
+++ b/chrome/browser/extensions/service_worker_apitest.cc
@@ -309,6 +309,13 @@
       << message_;
 }
 
+// Tests chrome.tabs events.
+IN_PROC_BROWSER_TEST_P(ServiceWorkerBasedBackgroundTest, TabsEvents) {
+  ASSERT_TRUE(
+      RunExtensionTest("service_worker/worker_based_background/tabs_events"))
+      << message_;
+}
+
 // Listens for |message| from extension Service Worker early so that tests can
 // wait for the message on startup (and not miss it).
 class ServiceWorkerWithEarlyMessageListenerTest
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index c47fc60..f4151aa6 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -43,11 +43,6 @@
     "expiry_milestone": 76
   },
   {
-    "name": "ProtectSyncCredentialOnReauth",
-    // "owners": [ "your-team" ],
-    "expiry_milestone": 76
-  },
-  {
     "name": "SupervisedUserCommittedInterstitials",
     // "owners": [ "your-team" ],
     "expiry_milestone": 76
@@ -736,8 +731,8 @@
   },
   {
     "name": "enable-app-list-search-autocomplete",
-    // "owners": [ "your-team" ],
-    "expiry_milestone": 76
+    "owners": [ "newcomer" ],
+    "expiry_milestone": 75
   },
   {
     "name": "enable-app-notification-status-messaging",
@@ -2070,7 +2065,7 @@
   },
   {
     "name": "fcm-invalidations",
-    // "owners": [ "your-team" ],
+    "owners": [ "melandory", "chrome-sync-dev@google.com" ],
     "expiry_milestone": 76
   },
   {
@@ -2724,11 +2719,6 @@
     "expiry_milestone": 74
   },
   {
-    "name": "protect-sync-credential",
-    // "owners": [ "your-team" ],
-    "expiry_milestone": 76
-  },
-  {
     "name": "pull-to-refresh",
     // "owners": [ "your-team" ],
     "expiry_milestone": 76
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index a6f02c71..4afecb2f 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -1581,16 +1581,6 @@
 const char kPrintPreviewRegisterPromosDescription[] =
     "Enable registering unregistered cloud printers from print preview.";
 
-const char kProtectSyncCredentialName[] = "Autofill sync credential";
-const char kProtectSyncCredentialDescription[] =
-    "How the password manager handles autofill for the sync credential.";
-
-const char kProtectSyncCredentialOnReauthName[] =
-    "Autofill sync credential only for transactional reauth pages";
-const char kProtectSyncCredentialOnReauthDescription[] =
-    "How the password manager handles autofill for the sync credential only "
-    "for transactional reauth pages.";
-
 const char kPullToRefreshName[] = "Pull-to-refresh gesture";
 const char kPullToRefreshDescription[] =
     "Pull-to-refresh gesture in response to vertical overscroll.";
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index 84e6aa2d..c1ca8b3 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -946,12 +946,6 @@
 extern const char kPrintPreviewRegisterPromosName[];
 extern const char kPrintPreviewRegisterPromosDescription[];
 
-extern const char kProtectSyncCredentialName[];
-extern const char kProtectSyncCredentialDescription[];
-
-extern const char kProtectSyncCredentialOnReauthName[];
-extern const char kProtectSyncCredentialOnReauthDescription[];
-
 extern const char kPullToRefreshName[];
 extern const char kPullToRefreshDescription[];
 extern const char kPullToRefreshEnabledTouchscreen[];
diff --git a/chrome/browser/lookalikes/lookalike_url_interstitial_page.cc b/chrome/browser/lookalikes/lookalike_url_interstitial_page.cc
index 232101f..58d773e 100644
--- a/chrome/browser/lookalikes/lookalike_url_interstitial_page.cc
+++ b/chrome/browser/lookalikes/lookalike_url_interstitial_page.cc
@@ -73,6 +73,10 @@
 
 void LookalikeUrlInterstitialPage::OnInterstitialClosing() {}
 
+bool LookalikeUrlInterstitialPage::ShouldDisplayURL() const {
+  return false;
+}
+
 // This handles the commands sent from the interstitial JavaScript.
 void LookalikeUrlInterstitialPage::CommandReceived(const std::string& command) {
   if (command == "\"pageLoadComplete\"") {
diff --git a/chrome/browser/lookalikes/lookalike_url_interstitial_page.h b/chrome/browser/lookalikes/lookalike_url_interstitial_page.h
index aeeb0b5..ccb7817 100644
--- a/chrome/browser/lookalikes/lookalike_url_interstitial_page.h
+++ b/chrome/browser/lookalikes/lookalike_url_interstitial_page.h
@@ -45,6 +45,7 @@
   void PopulateInterstitialStrings(
       base::DictionaryValue* load_time_data) override;
   void OnInterstitialClosing() override;
+  bool ShouldDisplayURL() const override;
   int GetHTMLTemplateId() override;
 
  private:
diff --git a/chrome/browser/lookalikes/lookalike_url_navigation_throttle_browsertest.cc b/chrome/browser/lookalikes/lookalike_url_navigation_throttle_browsertest.cc
index 8173894..6f5d9784 100644
--- a/chrome/browser/lookalikes/lookalike_url_navigation_throttle_browsertest.cc
+++ b/chrome/browser/lookalikes/lookalike_url_navigation_throttle_browsertest.cc
@@ -187,6 +187,7 @@
       NavigateToURL(browser, navigated_url);
       navigation_observer.Wait();
       EXPECT_EQ(nullptr, GetCurrentInterstitial(web_contents));
+      EXPECT_TRUE(IsUrlShowing(browser));
     }
     {
       // Navigate to an empty page. This will happen after any
@@ -196,6 +197,7 @@
       NavigateToURL(browser, GURL("about:blank"));
       navigation_observer.Wait();
       EXPECT_EQ(nullptr, GetCurrentInterstitial(web_contents));
+      EXPECT_TRUE(IsUrlShowing(browser));
     }
   }
 
@@ -215,6 +217,7 @@
 
     EXPECT_EQ(LookalikeUrlInterstitialPage::kTypeForTesting,
               GetInterstitialType(web_contents));
+    EXPECT_FALSE(IsUrlShowing(browser));
   }
 
   // Tests that the histogram event |expected_event| is recorded. If the UI is
@@ -297,8 +300,12 @@
 
   base::SimpleTestClock* test_clock() { return &test_clock_; }
 
- private:
-  bool ui_enabled() const { return GetParam() == UIEnabled::kEnabled; }
+ protected:
+  virtual bool ui_enabled() const { return GetParam() == UIEnabled::kEnabled; }
+
+  static bool IsUrlShowing(Browser* browser) {
+    return !browser->location_bar_model()->GetFormattedFullURL().empty();
+  }
 
   // Simulates a link click navigation. We don't use
   // ui_test_utils::NavigateToURL(const GURL&) because it simulates the user
@@ -327,6 +334,7 @@
         browser->tab_strip_model()->GetActiveWebContents();
 
     EXPECT_EQ(nullptr, GetCurrentInterstitial(web_contents));
+    EXPECT_TRUE(IsUrlShowing(browser));
     {
       content::TestNavigationObserver navigation_observer(web_contents, 1);
       NavigateToURL(browser, navigated_url);
@@ -335,6 +343,7 @@
 
     EXPECT_EQ(LookalikeUrlInterstitialPage::kTypeForTesting,
               GetInterstitialType(web_contents));
+    EXPECT_FALSE(IsUrlShowing(browser));
 
     // Clicking the link in the interstitial should remove the interstitial and
     // navigate to the suggested URL.
@@ -347,6 +356,7 @@
 
     EXPECT_EQ(nullptr, GetCurrentInterstitial(web_contents));
     EXPECT_EQ(expected_suggested_url, web_contents->GetURL());
+    EXPECT_TRUE(IsUrlShowing(browser));
 
     // Clicking the link in the interstitial should also remove the original URL
     // from history.
@@ -376,6 +386,7 @@
 
     EXPECT_EQ(LookalikeUrlInterstitialPage::kTypeForTesting,
               GetInterstitialType(web_contents));
+    EXPECT_FALSE(IsUrlShowing(browser));
 
     // Clicking the ignore button in the interstitial should remove the
     // interstitial and navigate to the original URL.
@@ -388,6 +399,7 @@
 
     EXPECT_EQ(nullptr, GetCurrentInterstitial(web_contents));
     EXPECT_EQ(navigated_url, web_contents->GetURL());
+    EXPECT_TRUE(IsUrlShowing(browser));
 
     // Clicking the link should result in the original URL appearing in history.
     ui_test_utils::HistoryEnumerator enumerator(browser->profile());
@@ -399,6 +411,54 @@
   base::SimpleTestClock test_clock_;
 };
 
+class LookalikeUrlInterstitialPageBrowserTest
+    : public LookalikeUrlNavigationThrottleBrowserTest {
+ public:
+  // Checks that navigating to |navigated_url| displays an interstitial with a
+  // hidden URL, and then navigating to other pages shows/hides the URLs
+  // appropriately both when a URL is expected to be hidden (by navigating to
+  // "chrome://newtab") and when expected to be shown (by navigating to
+  // |subsequent_url|).
+  static void TestInterstitialHidesUrlThenRestores(Browser* browser,
+                                                   const GURL& navigated_url,
+                                                   const GURL& subsequent_url) {
+    content::WebContents* web_contents =
+        browser->tab_strip_model()->GetActiveWebContents();
+
+    EXPECT_EQ(nullptr, GetCurrentInterstitial(web_contents));
+    EXPECT_TRUE(IsUrlShowing(browser));
+    {
+      content::TestNavigationObserver navigation_observer(web_contents, 1);
+      NavigateToURL(browser, navigated_url);
+      navigation_observer.Wait();
+    }
+
+    EXPECT_EQ(LookalikeUrlInterstitialPage::kTypeForTesting,
+              GetInterstitialType(web_contents));
+    EXPECT_FALSE(IsUrlShowing(browser));
+
+    {
+      content::TestNavigationObserver navigation_observer(web_contents, 1);
+      ui_test_utils::NavigateToURL(browser, subsequent_url);
+      navigation_observer.Wait();
+    }
+
+    EXPECT_EQ(nullptr, GetCurrentInterstitial(web_contents));
+    EXPECT_TRUE(IsUrlShowing(browser));
+
+    {
+      content::TestNavigationObserver navigation_observer(web_contents, 1);
+      ui_test_utils::NavigateToURL(browser, GURL("chrome://newtab"));
+      navigation_observer.Wait();
+    }
+
+    EXPECT_FALSE(IsUrlShowing(browser));
+  }
+
+ protected:
+  bool ui_enabled() const override { return true; }
+};
+
 INSTANTIATE_TEST_SUITE_P(,
                          LookalikeUrlNavigationThrottleBrowserTest,
                          ::testing::Values(UIEnabled::kDisabled,
@@ -731,3 +791,12 @@
     TestOnlyInterstitialShown(browser(), kNavigatedUrl);
   }
 }
+
+// Verify that the URL shows normally on pages after a lookalike interstitial.
+IN_PROC_BROWSER_TEST_F(LookalikeUrlInterstitialPageBrowserTest,
+                       UrlShownAfterInterstitial) {
+  const GURL kNavigatedUrl = GetURL("goooglé.com");
+  const GURL kSubsequentUrl = GetURL("example.com");
+  TestInterstitialHidesUrlThenRestores(browser(), kNavigatedUrl,
+                                       kSubsequentUrl);
+}
diff --git a/chrome/browser/performance_manager/graph/frame_node_impl.cc b/chrome/browser/performance_manager/graph/frame_node_impl.cc
index da16a55c..1134a08 100644
--- a/chrome/browser/performance_manager/graph/frame_node_impl.cc
+++ b/chrome/browser/performance_manager/graph/frame_node_impl.cc
@@ -35,6 +35,7 @@
 
 void FrameNodeImpl::SetProcess(
     const resource_coordinator::CoordinationUnitID& cu_id) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   ProcessNodeImpl* process_cu = ProcessNodeImpl::GetNodeByID(graph_, cu_id);
   if (!process_cu)
     return;
@@ -45,6 +46,7 @@
 
 void FrameNodeImpl::AddChildFrame(
     const resource_coordinator::CoordinationUnitID& cu_id) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(cu_id != id());
   FrameNodeImpl* frame_cu = FrameNodeImpl::GetNodeByID(graph_, cu_id);
   if (!frame_cu)
@@ -61,6 +63,7 @@
 
 void FrameNodeImpl::RemoveChildFrame(
     const resource_coordinator::CoordinationUnitID& cu_id) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(cu_id != id());
   FrameNodeImpl* frame_cu = FrameNodeImpl::GetNodeByID(graph_, cu_id);
   if (!frame_cu)
@@ -77,6 +80,7 @@
 
 void FrameNodeImpl::SetLifecycleState(
     resource_coordinator::mojom::LifecycleState state) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (state == lifecycle_state_)
     return;
 
@@ -91,12 +95,14 @@
 }
 
 void FrameNodeImpl::SetHasNonEmptyBeforeUnload(bool has_nonempty_beforeunload) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   has_nonempty_beforeunload_ = has_nonempty_beforeunload;
 }
 
 void FrameNodeImpl::SetInterventionPolicy(
     resource_coordinator::mojom::PolicyControlledIntervention intervention,
     resource_coordinator::mojom::InterventionPolicy policy) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   size_t i = static_cast<size_t>(intervention);
   DCHECK_LT(i, base::size(intervention_policy_));
 
@@ -128,22 +134,27 @@
 }
 
 FrameNodeImpl* FrameNodeImpl::GetParentFrameNode() const {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return parent_frame_coordination_unit_;
 }
 
 PageNodeImpl* FrameNodeImpl::GetPageNode() const {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return page_coordination_unit_;
 }
 
 ProcessNodeImpl* FrameNodeImpl::GetProcessNode() const {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return process_coordination_unit_;
 }
 
 bool FrameNodeImpl::IsMainFrame() const {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return !parent_frame_coordination_unit_;
 }
 
 bool FrameNodeImpl::AreAllInterventionPoliciesSet() const {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   // The convention is that policies are first set en masse, in order. So if
   // the last policy is set then they are all considered to be set. Check this
   // in DEBUG builds.
@@ -169,6 +180,7 @@
 
 void FrameNodeImpl::SetAllInterventionPoliciesForTesting(
     resource_coordinator::mojom::InterventionPolicy policy) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   for (size_t i = 0; i < base::size(intervention_policy_); ++i) {
     SetInterventionPolicy(
         static_cast<resource_coordinator::mojom::PolicyControlledIntervention>(
@@ -178,6 +190,7 @@
 }
 
 void FrameNodeImpl::OnEventReceived(resource_coordinator::mojom::Event event) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   for (auto& observer : observers())
     observer.OnFrameEventReceived(this, event);
 }
@@ -185,11 +198,13 @@
 void FrameNodeImpl::OnPropertyChanged(
     resource_coordinator::mojom::PropertyType property_type,
     int64_t value) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   for (auto& observer : observers())
     observer.OnFramePropertyChanged(this, property_type, value);
 }
 
 bool FrameNodeImpl::HasFrameNodeInAncestors(FrameNodeImpl* frame_cu) const {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (parent_frame_coordination_unit_ == frame_cu ||
       (parent_frame_coordination_unit_ &&
        parent_frame_coordination_unit_->HasFrameNodeInAncestors(frame_cu))) {
@@ -199,6 +214,7 @@
 }
 
 bool FrameNodeImpl::HasFrameNodeInDescendants(FrameNodeImpl* frame_cu) const {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   for (FrameNodeImpl* child : child_frame_coordination_units_) {
     if (child == frame_cu || child->HasFrameNodeInDescendants(frame_cu)) {
       return true;
@@ -208,36 +224,43 @@
 }
 
 void FrameNodeImpl::AddParentFrame(FrameNodeImpl* parent_frame_cu) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   parent_frame_coordination_unit_ = parent_frame_cu;
 }
 
 bool FrameNodeImpl::AddChildFrame(FrameNodeImpl* child_frame_cu) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return child_frame_coordination_units_.count(child_frame_cu)
              ? false
              : child_frame_coordination_units_.insert(child_frame_cu).second;
 }
 
 void FrameNodeImpl::RemoveParentFrame(FrameNodeImpl* parent_frame_cu) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(parent_frame_coordination_unit_ == parent_frame_cu);
   parent_frame_coordination_unit_ = nullptr;
 }
 
 bool FrameNodeImpl::RemoveChildFrame(FrameNodeImpl* child_frame_cu) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return child_frame_coordination_units_.erase(child_frame_cu) > 0;
 }
 
 void FrameNodeImpl::AddPageNode(PageNodeImpl* page_coordination_unit) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(!page_coordination_unit_);
   page_coordination_unit_ = page_coordination_unit;
 }
 
 void FrameNodeImpl::RemovePageNode(PageNodeImpl* page_coordination_unit) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(page_coordination_unit == page_coordination_unit_);
   page_coordination_unit_ = nullptr;
 }
 
 void FrameNodeImpl::RemoveProcessNode(
     ProcessNodeImpl* process_coordination_unit) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(process_coordination_unit == process_coordination_unit_);
   process_coordination_unit_ = nullptr;
 }
diff --git a/chrome/browser/performance_manager/graph/node_base.cc b/chrome/browser/performance_manager/graph/node_base.cc
index f062d8e..a6ad917 100644
--- a/chrome/browser/performance_manager/graph/node_base.cc
+++ b/chrome/browser/performance_manager/graph/node_base.cc
@@ -14,30 +14,41 @@
 
 NodeBase::NodeBase(const resource_coordinator::CoordinationUnitID& id,
                    Graph* graph)
-    : graph_(graph), id_(id.type, id.id) {}
+    : graph_(graph), id_(id.type, id.id) {
+  // TODO(siggi): The constructor needs to detach from the sequence once the
+  //     lifetime changes are done.
+  // DETACH_FROM_SEQUENCE(sequence_checker_);
+}
 
-NodeBase::~NodeBase() = default;
+NodeBase::~NodeBase() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+}
 
 void NodeBase::Destruct() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   graph_->DestroyNode(this);
 }
 
 void NodeBase::BeforeDestroyed() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   for (auto& observer : observers_)
     observer.OnBeforeNodeDestroyed(this);
 }
 
 void NodeBase::AddObserver(GraphObserver* observer) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   observers_.AddObserver(observer);
 }
 
 void NodeBase::RemoveObserver(GraphObserver* observer) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   observers_.RemoveObserver(observer);
 }
 
 bool NodeBase::GetProperty(
     const resource_coordinator::mojom::PropertyType property_type,
     int64_t* result) const {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   auto value_it = properties_.find(property_type);
   if (value_it != properties_.end()) {
     *result = value_it->second;
@@ -49,6 +60,7 @@
 int64_t NodeBase::GetPropertyOrDefault(
     const resource_coordinator::mojom::PropertyType property_type,
     int64_t default_value) const {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   int64_t value = 0;
   if (GetProperty(property_type, &value))
     return value;
@@ -56,6 +68,7 @@
 }
 
 void NodeBase::OnEventReceived(resource_coordinator::mojom::Event event) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   for (auto& observer : observers())
     observer.OnEventReceived(this, event);
 }
@@ -63,17 +76,20 @@
 void NodeBase::OnPropertyChanged(
     resource_coordinator::mojom::PropertyType property_type,
     int64_t value) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   for (auto& observer : observers())
     observer.OnPropertyChanged(this, property_type, value);
 }
 
 void NodeBase::SendEvent(resource_coordinator::mojom::Event event) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   OnEventReceived(event);
 }
 
 void NodeBase::SetProperty(
     resource_coordinator::mojom::PropertyType property_type,
     int64_t value) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   // The |GraphObserver| API specification dictates that
   // the property is guaranteed to be set on the |NodeBase|
   // and propagated to the appropriate associated |CoordianationUnitBase|
diff --git a/chrome/browser/performance_manager/graph/node_base.h b/chrome/browser/performance_manager/graph/node_base.h
index 5f93ab0..65ba5ccd 100644
--- a/chrome/browser/performance_manager/graph/node_base.h
+++ b/chrome/browser/performance_manager/graph/node_base.h
@@ -11,6 +11,7 @@
 #include "base/callback.h"
 #include "base/macros.h"
 #include "base/observer_list.h"
+#include "base/sequence_checker.h"
 #include "chrome/browser/performance_manager/graph/graph.h"
 #include "chrome/browser/performance_manager/observers/coordination_unit_graph_observer.h"
 #include "mojo/public/cpp/bindings/binding_set.h"
@@ -75,6 +76,8 @@
   Graph* const graph_;
   const resource_coordinator::CoordinationUnitID id_;
 
+  SEQUENCE_CHECKER(sequence_checker_);
+
  private:
   base::ObserverList<GraphObserver>::Unchecked observers_;
   std::map<resource_coordinator::mojom::PropertyType, int64_t> properties_;
diff --git a/chrome/browser/performance_manager/graph/page_node_impl.cc b/chrome/browser/performance_manager/graph/page_node_impl.cc
index 301964d..c8cddf7 100644
--- a/chrome/browser/performance_manager/graph/page_node_impl.cc
+++ b/chrome/browser/performance_manager/graph/page_node_impl.cc
@@ -40,6 +40,7 @@
 
 void PageNodeImpl::AddFrame(
     const resource_coordinator::CoordinationUnitID& cu_id) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(cu_id.type == resource_coordinator::CoordinationUnitType::kFrame);
   FrameNodeImpl* frame_cu = FrameNodeImpl::GetNodeByID(graph_, cu_id);
   if (!frame_cu)
@@ -50,6 +51,7 @@
 
 void PageNodeImpl::RemoveFrame(
     const resource_coordinator::CoordinationUnitID& cu_id) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(cu_id != id());
   FrameNodeImpl* frame_cu = FrameNodeImpl::GetNodeByID(graph_, cu_id);
   if (!frame_cu)
@@ -84,6 +86,7 @@
     base::TimeTicks navigation_committed_time,
     int64_t navigation_id,
     const std::string& url) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   navigation_committed_time_ = navigation_committed_time;
   main_frame_url_ = url;
   navigation_id_ = navigation_id;
@@ -92,6 +95,7 @@
 
 std::set<ProcessNodeImpl*> PageNodeImpl::GetAssociatedProcessCoordinationUnits()
     const {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   std::set<ProcessNodeImpl*> process_cus;
 
   for (auto* frame_cu : frame_coordination_units_) {
@@ -103,6 +107,7 @@
 }
 
 bool PageNodeImpl::IsVisible() const {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   int64_t is_visible = 0;
   bool has_property = GetProperty(
       resource_coordinator::mojom::PropertyType::kVisible, &is_visible);
@@ -111,6 +116,7 @@
 }
 
 double PageNodeImpl::GetCPUUsage() const {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   double cpu_usage = 0.0;
 
   for (auto* process_cu : GetAssociatedProcessCoordinationUnits()) {
@@ -130,6 +136,7 @@
 }
 
 bool PageNodeImpl::GetExpectedTaskQueueingDuration(int64_t* output) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   // Calculate the EQT for the process of the main frame only because
   // the smoothness of the main frame may affect the users the most.
   FrameNodeImpl* main_frame_cu = GetMainFrameNode();
@@ -144,16 +151,19 @@
 }
 
 base::TimeDelta PageNodeImpl::TimeSinceLastNavigation() const {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (navigation_committed_time_.is_null())
     return base::TimeDelta();
   return ResourceCoordinatorClock::NowTicks() - navigation_committed_time_;
 }
 
 base::TimeDelta PageNodeImpl::TimeSinceLastVisibilityChange() const {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return ResourceCoordinatorClock::NowTicks() - visibility_change_time_;
 }
 
 FrameNodeImpl* PageNodeImpl::GetMainFrameNode() const {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   for (auto* frame_cu : frame_coordination_units_) {
     if (frame_cu->IsMainFrame())
       return frame_cu;
@@ -164,6 +174,7 @@
 void PageNodeImpl::OnFrameLifecycleStateChanged(
     FrameNodeImpl* frame_cu,
     resource_coordinator::mojom::LifecycleState old_state) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(base::ContainsKey(frame_coordination_units_, frame_cu));
   DCHECK_NE(old_state, frame_cu->lifecycle_state());
 
@@ -182,6 +193,7 @@
     resource_coordinator::mojom::PolicyControlledIntervention intervention,
     resource_coordinator::mojom::InterventionPolicy old_policy,
     resource_coordinator::mojom::InterventionPolicy new_policy) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   const size_t kIndex = ToIndex(intervention);
 
   // Invalidate the local policy aggregation for this intervention. It will be
@@ -205,6 +217,7 @@
 resource_coordinator::mojom::InterventionPolicy
 PageNodeImpl::GetInterventionPolicy(
     resource_coordinator::mojom::PolicyControlledIntervention intervention) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   // If there are no frames, or they've not all reported, then return kUnknown.
   if (frame_coordination_units_.empty() ||
       intervention_policy_frames_reported_ !=
@@ -226,6 +239,7 @@
 }
 
 void PageNodeImpl::OnEventReceived(resource_coordinator::mojom::Event event) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   for (auto& observer : observers())
     observer.OnPageEventReceived(this, event);
 }
@@ -233,6 +247,7 @@
 void PageNodeImpl::OnPropertyChanged(
     const resource_coordinator::mojom::PropertyType property_type,
     int64_t value) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (property_type == resource_coordinator::mojom::PropertyType::kVisible)
     visibility_change_time_ = ResourceCoordinatorClock::NowTicks();
   for (auto& observer : observers())
@@ -240,6 +255,7 @@
 }
 
 bool PageNodeImpl::AddFrame(FrameNodeImpl* frame_cu) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   const bool inserted = frame_coordination_units_.insert(frame_cu).second;
   if (inserted) {
     OnNumFrozenFramesStateChange(
@@ -253,6 +269,7 @@
 }
 
 bool PageNodeImpl::RemoveFrame(FrameNodeImpl* frame_cu) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   bool removed = frame_coordination_units_.erase(frame_cu) > 0;
   if (removed) {
     OnNumFrozenFramesStateChange(
@@ -267,6 +284,7 @@
 }
 
 void PageNodeImpl::OnNumFrozenFramesStateChange(int num_frozen_frames_delta) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   num_frozen_frames_ += num_frozen_frames_delta;
   DCHECK_LE(num_frozen_frames_, frame_coordination_units_.size());
 
@@ -307,6 +325,7 @@
 }
 
 void PageNodeImpl::InvalidateAllInterventionPolicies() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   for (size_t i = 0; i <= kMaxInterventionIndex; ++i)
     intervention_policy_[i] =
         resource_coordinator::mojom::InterventionPolicy::kUnknown;
@@ -314,6 +333,7 @@
 
 void PageNodeImpl::MaybeInvalidateInterventionPolicies(FrameNodeImpl* frame_cu,
                                                        bool adding_frame) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   // Ensure that the frame was already added or removed as expected.
   DCHECK(adding_frame == frame_coordination_units_.count(frame_cu));
 
@@ -343,6 +363,7 @@
 
 void PageNodeImpl::RecomputeInterventionPolicy(
     resource_coordinator::mojom::PolicyControlledIntervention intervention) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   const size_t kIndex = ToIndex(intervention);
 
   // This should never be called with an empty frame tree.
diff --git a/chrome/browser/performance_manager/graph/process_node_impl.cc b/chrome/browser/performance_manager/graph/process_node_impl.cc
index 8a5ebee6..30626ca66 100644
--- a/chrome/browser/performance_manager/graph/process_node_impl.cc
+++ b/chrome/browser/performance_manager/graph/process_node_impl.cc
@@ -27,6 +27,7 @@
 
 void ProcessNodeImpl::AddFrame(FrameNodeImpl* frame_cu) {
   const bool inserted = frame_coordination_units_.insert(frame_cu).second;
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(inserted);
   if (frame_cu->lifecycle_state() ==
       resource_coordinator::mojom::LifecycleState::kFrozen)
@@ -46,6 +47,7 @@
 }
 
 void ProcessNodeImpl::SetLaunchTime(base::Time launch_time) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(launch_time_.is_null());
   launch_time_ = launch_time;
 }
@@ -58,6 +60,7 @@
 }
 
 void ProcessNodeImpl::SetPID(base::ProcessId pid) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   // Either this is the initial process associated with this process CU,
   // or it's a subsequent process. In the latter case, there must have been
   // an exit status associated with the previous process.
@@ -80,6 +83,7 @@
 }
 
 void ProcessNodeImpl::SetProcessExitStatus(int32_t exit_status) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   exit_status_ = exit_status;
 }
 
@@ -88,6 +92,7 @@
 }
 
 const std::set<FrameNodeImpl*>& ProcessNodeImpl::GetFrameNodes() const {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   return frame_coordination_units_;
 }
 
@@ -97,6 +102,7 @@
 // frames.
 std::set<PageNodeImpl*> ProcessNodeImpl::GetAssociatedPageCoordinationUnits()
     const {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   std::set<PageNodeImpl*> page_cus;
   for (auto* frame_cu : frame_coordination_units_) {
     if (auto* page_cu = frame_cu->GetPageNode())
@@ -108,6 +114,7 @@
 void ProcessNodeImpl::OnFrameLifecycleStateChanged(
     FrameNodeImpl* frame_cu,
     resource_coordinator::mojom::LifecycleState old_state) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(base::ContainsKey(frame_coordination_units_, frame_cu));
   DCHECK_NE(old_state, frame_cu->lifecycle_state());
 
@@ -120,6 +127,7 @@
 
 void ProcessNodeImpl::OnEventReceived(
     resource_coordinator::mojom::Event event) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   for (auto& observer : observers())
     observer.OnProcessEventReceived(this, event);
 }
@@ -127,11 +135,13 @@
 void ProcessNodeImpl::OnPropertyChanged(
     const resource_coordinator::mojom::PropertyType property_type,
     int64_t value) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   for (auto& observer : observers())
     observer.OnProcessPropertyChanged(this, property_type, value);
 }
 
 void ProcessNodeImpl::RemoveFrame(FrameNodeImpl* frame_cu) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(base::ContainsKey(frame_coordination_units_, frame_cu));
   frame_coordination_units_.erase(frame_cu);
 
@@ -141,11 +151,13 @@
 }
 
 void ProcessNodeImpl::DecrementNumFrozenFrames() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   --num_frozen_frames_;
   DCHECK_GE(num_frozen_frames_, 0);
 }
 
 void ProcessNodeImpl::IncrementNumFrozenFrames() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   ++num_frozen_frames_;
   DCHECK_LE(num_frozen_frames_,
             static_cast<int>(frame_coordination_units_.size()));
diff --git a/chrome/browser/performance_manager/graph/system_node_impl.cc b/chrome/browser/performance_manager/graph/system_node_impl.cc
index b0af5d3..cf23570 100644
--- a/chrome/browser/performance_manager/graph/system_node_impl.cc
+++ b/chrome/browser/performance_manager/graph/system_node_impl.cc
@@ -30,6 +30,7 @@
 void SystemNodeImpl::DistributeMeasurementBatch(
     resource_coordinator::mojom::ProcessResourceMeasurementBatchPtr
         measurement_batch) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   base::TimeDelta time_since_last_measurement;
   if (!last_measurement_end_time_.is_null()) {
     // Use the end of the measurement batch as a proxy for when every
@@ -156,6 +157,7 @@
 }
 
 void SystemNodeImpl::OnEventReceived(resource_coordinator::mojom::Event event) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   for (auto& observer : observers())
     observer.OnSystemEventReceived(this, event);
 }
@@ -163,6 +165,7 @@
 void SystemNodeImpl::OnPropertyChanged(
     resource_coordinator::mojom::PropertyType property_type,
     int64_t value) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   for (auto& observer : observers())
     observer.OnSystemPropertyChanged(this, property_type, value);
 }
diff --git a/chrome/browser/policy/policy_conversions.cc b/chrome/browser/policy/policy_conversions.cc
index f59d56c5..7f5d18e4 100644
--- a/chrome/browser/policy/policy_conversions.cc
+++ b/chrome/browser/policy/policy_conversions.cc
@@ -75,10 +75,11 @@
 using PolicyToSchemaMap = base::flat_map<std::string, policy::Schema>;
 
 // Utility function that returns a JSON serialization of the given |dict|.
-std::string DictionaryToJSONString(const Value& dict) {
+std::string DictionaryToJSONString(const Value& dict, bool is_pretty_print) {
   std::string json_string;
   base::JSONWriter::WriteWithOptions(
-      dict, base::JSONWriter::OPTIONS_PRETTY_PRINT, &json_string);
+      dict, (is_pretty_print ? base::JSONWriter::OPTIONS_PRETTY_PRINT : 0),
+      &json_string);
   return json_string;
 }
 
@@ -87,14 +88,15 @@
 // i18n_template.js will display.
 Value CopyAndMaybeConvert(const Value& value,
                           bool convert_values,
-                          const base::Optional<policy::Schema>& schema) {
+                          const base::Optional<policy::Schema>& schema,
+                          bool is_pretty_print) {
   Value value_copy = value.Clone();
   if (schema.has_value())
     schema->MaskSensitiveValues(&value_copy);
   if (!convert_values)
     return value_copy;
   if (value_copy.is_dict())
-    return Value(DictionaryToJSONString(value_copy));
+    return Value(DictionaryToJSONString(value_copy, is_pretty_print));
 
   if (!value_copy.is_list()) {
     return value_copy;
@@ -103,7 +105,8 @@
   Value result(Value::Type::LIST);
   for (const auto& element : value_copy.GetList()) {
     if (element.is_dict()) {
-      result.GetList().emplace_back(Value(DictionaryToJSONString(element)));
+      result.GetList().emplace_back(
+          Value(DictionaryToJSONString(element, is_pretty_print)));
     } else {
       result.GetList().push_back(element.Clone());
     }
@@ -140,12 +143,14 @@
     const policy::PolicyMap::Entry& policy,
     policy::PolicyErrorMap* errors,
     bool convert_values,
-    const base::Optional<PolicyToSchemaMap>& known_policy_schemas) {
+    const base::Optional<PolicyToSchemaMap>& known_policy_schemas,
+    bool is_pretty_print) {
   base::Optional<policy::Schema> known_policy_schema =
       GetKnownPolicySchema(known_policy_schemas, policy_name);
   Value value(Value::Type::DICTIONARY);
-  value.SetKey("value", CopyAndMaybeConvert(*policy.value, convert_values,
-                                            known_policy_schema));
+  value.SetKey("value",
+               CopyAndMaybeConvert(*policy.value, convert_values,
+                                   known_policy_schema, is_pretty_print));
   value.SetKey(
       "scope",
       Value((policy.scope == policy::POLICY_SCOPE_USER) ? "user" : "machine"));
@@ -172,8 +177,9 @@
   if (!policy.conflicts.empty()) {
     Value conflict_values(Value::Type::LIST);
     for (const auto& conflict : policy.conflicts) {
-      base::Value conflicted_policy_value = GetPolicyValue(
-          policy_name, conflict, errors, convert_values, known_policy_schemas);
+      base::Value conflicted_policy_value =
+          GetPolicyValue(policy_name, conflict, errors, convert_values,
+                         known_policy_schemas, is_pretty_print);
       conflict_values.GetList().push_back(std::move(conflicted_policy_value));
     }
 
@@ -195,22 +201,25 @@
     bool with_user_policies,
     bool convert_values,
     const base::Optional<PolicyToSchemaMap>& known_policy_schemas,
-    Value* values) {
+    Value* values,
+    bool is_pretty_print) {
   DCHECK(values);
   for (const auto& entry : map) {
     const std::string& policy_name = entry.first;
     const PolicyMap::Entry& policy = entry.second;
     if (policy.scope == policy::POLICY_SCOPE_USER && !with_user_policies)
       continue;
-    base::Value value = GetPolicyValue(policy_name, policy, errors,
-                                       convert_values, known_policy_schemas);
+    base::Value value =
+        GetPolicyValue(policy_name, policy, errors, convert_values,
+                       known_policy_schemas, is_pretty_print);
     values->SetKey(policy_name, std::move(value));
   }
 }
 
 base::Optional<PolicyToSchemaMap> GetKnownPolicies(
     const scoped_refptr<policy::SchemaMap> schema_map,
-    const PolicyNamespace& policy_namespace) {
+    const PolicyNamespace& policy_namespace,
+    bool is_pretty_print) {
   const Schema* schema = schema_map->GetSchema(policy_namespace);
   // There is no policy name verification without valid schema.
   if (!schema || !schema->valid())
@@ -231,7 +240,8 @@
 void GetChromePolicyValues(content::BrowserContext* context,
                            bool keep_user_policies,
                            bool convert_values,
-                           Value* values) {
+                           Value* values,
+                           bool is_pretty_print) {
   policy::PolicyService* policy_service = GetPolicyService(context);
   policy::PolicyMap map;
 
@@ -262,14 +272,17 @@
   // Convert dictionary values to strings for display.
   handler_list->PrepareForDisplaying(&map);
 
-  GetPolicyValues(map, &errors, keep_user_policies, convert_values,
-                  GetKnownPolicies(schema_map, policy_namespace), values);
+  GetPolicyValues(
+      map, &errors, keep_user_policies, convert_values,
+      GetKnownPolicies(schema_map, policy_namespace, is_pretty_print), values,
+      is_pretty_print);
 }
 
 #if defined(OS_CHROMEOS)
 void GetDeviceLocalAccountPolicies(bool convert_values,
                                    Value* values,
-                                   bool with_device_data) {
+                                   bool with_device_data,
+                                   bool is_pretty_print) {
   // DeviceLocalAccount policies are only available for affiliated users and for
   // system logs.
   if (!with_device_data &&
@@ -327,9 +340,10 @@
     // Convert dictionary values to strings for display.
     handler_list->PrepareForDisplaying(&map);
 
-    GetPolicyValues(map, &errors, true, convert_values,
-                    GetKnownPolicies(schema_map, policy_namespace),
-                    &current_account_policies);
+    GetPolicyValues(
+        map, &errors, true, convert_values,
+        GetKnownPolicies(schema_map, policy_namespace, is_pretty_print),
+        &current_account_policies, is_pretty_print);
     values->SetKey(user_id, std::move(current_account_policies));
   }
 }
@@ -340,7 +354,8 @@
 Value GetAllPolicyValuesAsDictionary(content::BrowserContext* context,
                                      bool with_user_policies,
                                      bool convert_values,
-                                     bool with_device_data) {
+                                     bool with_device_data,
+                                     bool is_pretty_print) {
   Value all_policies(Value::Type::DICTIONARY);
   if (!context) {
     LOG(ERROR) << "Can not dump policies, null context";
@@ -352,7 +367,7 @@
   // Add Chrome policy values.
   Value chrome_policies(Value::Type::DICTIONARY);
   GetChromePolicyValues(context, with_user_policies, convert_values,
-                        &chrome_policies);
+                        &chrome_policies, is_pretty_print);
   all_policies.SetKey("chromePolicies", std::move(chrome_policies));
 
 #if BUILDFLAG(ENABLE_EXTENSIONS)
@@ -383,10 +398,11 @@
     policy::PolicyNamespace policy_namespace = policy::PolicyNamespace(
         policy::POLICY_DOMAIN_EXTENSIONS, extension->id());
     policy::PolicyErrorMap empty_error_map;
-    GetPolicyValues(GetPolicyService(context)->GetPolicies(policy_namespace),
-                    &empty_error_map, with_user_policies, convert_values,
-                    GetKnownPolicies(schema_map, policy_namespace),
-                    &extension_policies);
+    GetPolicyValues(
+        GetPolicyService(context)->GetPolicies(policy_namespace),
+        &empty_error_map, with_user_policies, convert_values,
+        GetKnownPolicies(schema_map, policy_namespace, is_pretty_print),
+        &extension_policies, is_pretty_print);
     extension_values.SetKey(extension->id(), std::move(extension_policies));
   }
   all_policies.SetKey("extensionPolicies", std::move(extension_values));
@@ -395,7 +411,7 @@
 #if defined(OS_CHROMEOS)
   Value device_local_account_policies(Value::Type::DICTIONARY);
   GetDeviceLocalAccountPolicies(convert_values, &device_local_account_policies,
-                                with_device_data);
+                                with_device_data, is_pretty_print);
   all_policies.SetKey("deviceLocalAccountPolicies",
                       std::move(device_local_account_policies));
 #endif  // defined(OS_CHROMEOS)
@@ -458,14 +474,15 @@
 
 std::string GetAllPolicyValuesAsJSON(content::BrowserContext* context,
                                      bool with_user_policies,
-                                     bool with_device_data) {
+                                     bool with_device_data,
+                                     bool is_pretty_print) {
   Value all_policies = policy::GetAllPolicyValuesAsDictionary(
-      context, with_user_policies, false /* convert_values */,
-      with_device_data);
+      context, with_user_policies, false /* convert_values */, with_device_data,
+      is_pretty_print);
   if (with_device_data) {
     FillIdentityFields(&all_policies);
   }
-  return DictionaryToJSONString(all_policies);
+  return DictionaryToJSONString(all_policies, is_pretty_print);
 }
 
 }  // namespace policy
diff --git a/chrome/browser/policy/policy_conversions.h b/chrome/browser/policy/policy_conversions.h
index efc2ffc5..9dc9a93 100644
--- a/chrome/browser/policy/policy_conversions.h
+++ b/chrome/browser/policy/policy_conversions.h
@@ -20,19 +20,23 @@
 // |with_device_data| governs if device identity data (e.g.
 // enrollment client ID) and device local accounts policies are included,
 // it is used in logs uploads to the server.
+// |is_pretty_print| govers if JSON policy value is pretty printed.
 base::Value GetAllPolicyValuesAsDictionary(content::BrowserContext* context,
                                            bool with_user_policies,
                                            bool convert_values,
-                                           bool with_device_data);
+                                           bool with_device_data,
+                                           bool is_pretty_print);
 
 // Returns a JSON with the values of all set policies.
 // |with_user_policies| governs if values with POLICY_SCOPE_USER are included.
 // |with_device_data| governs if device identity data (e.g.
 // enrollment client ID) and device local accounts policies are included,
 // it is used in logs uploads to the server.
+// |is_pretty_print| governs if the output is formatted.
 std::string GetAllPolicyValuesAsJSON(content::BrowserContext* context,
                                      bool with_user_policies,
-                                     bool with_device_data);
+                                     bool with_device_data,
+                                     bool is_pretty_print);
 
 }  // namespace policy
 
diff --git a/chrome/browser/previews/previews_lite_page_browsertest.cc b/chrome/browser/previews/previews_lite_page_browsertest.cc
index 64a14978..aff8c86 100644
--- a/chrome/browser/previews/previews_lite_page_browsertest.cc
+++ b/chrome/browser/previews/previews_lite_page_browsertest.cc
@@ -1704,8 +1704,8 @@
         ->previews_opt_guide()
         ->ListenForNextUpdateForTesting(run_loop.QuitClosure());
 
-    g_browser_process->optimization_guide_service()->MaybeUpdateHintsComponent(
-        component_info);
+    g_browser_process->optimization_guide_service()
+        ->MaybeUpdateHintsComponentOnUIThread(component_info);
 
     run_loop.Run();
   }
@@ -1722,6 +1722,11 @@
             resource_patterns));
   }
 
+  void SetUpCommandLine(base::CommandLine* cmd) override {
+    PreviewsLitePageServerBrowserTest::SetUpCommandLine(cmd);
+    cmd->AppendSwitch("optimization-guide-disable-installer");
+  }
+
  private:
 
   optimization_guide::testing::TestHintsComponentCreator
diff --git a/chrome/browser/profiles/off_the_record_profile_impl.cc b/chrome/browser/profiles/off_the_record_profile_impl.cc
index cf0c0e09..198a919 100644
--- a/chrome/browser/profiles/off_the_record_profile_impl.cc
+++ b/chrome/browser/profiles/off_the_record_profile_impl.cc
@@ -343,6 +343,10 @@
   return profile_->IsLegacySupervised();
 }
 
+bool OffTheRecordProfileImpl::AllowsBrowserWindows() const {
+  return profile_->AllowsBrowserWindows();
+}
+
 PrefService* OffTheRecordProfileImpl::GetPrefs() {
   return prefs_.get();
 }
diff --git a/chrome/browser/profiles/off_the_record_profile_impl.h b/chrome/browser/profiles/off_the_record_profile_impl.h
index 8763bafc..170b258 100644
--- a/chrome/browser/profiles/off_the_record_profile_impl.h
+++ b/chrome/browser/profiles/off_the_record_profile_impl.h
@@ -51,6 +51,7 @@
   bool IsSupervised() const override;
   bool IsChild() const override;
   bool IsLegacySupervised() const override;
+  bool AllowsBrowserWindows() const override;
   ExtensionSpecialStoragePolicy* GetExtensionSpecialStoragePolicy() override;
   PrefService* GetPrefs() override;
   const PrefService* GetPrefs() const override;
diff --git a/chrome/browser/profiles/profile.h b/chrome/browser/profiles/profile.h
index 32bab41..7b7f95b 100644
--- a/chrome/browser/profiles/profile.h
+++ b/chrome/browser/profiles/profile.h
@@ -171,6 +171,10 @@
   // Returns whether the profile is a legacy supervised user profile.
   virtual bool IsLegacySupervised() const = 0;
 
+  // Returns whether opening browser windows is allowed in this profile. For
+  // example, browser windows are not allowed in Sign-in profile on Chrome OS.
+  virtual bool AllowsBrowserWindows() const = 0;
+
   // Accessor. The instance is created upon first access.
   virtual ExtensionSpecialStoragePolicy*
       GetExtensionSpecialStoragePolicy() = 0;
diff --git a/chrome/browser/profiles/profile_impl.cc b/chrome/browser/profiles/profile_impl.cc
index 1fc22c6..f52ac17 100644
--- a/chrome/browser/profiles/profile_impl.cc
+++ b/chrome/browser/profiles/profile_impl.cc
@@ -895,6 +895,16 @@
   return IsSupervised() && !IsChild();
 }
 
+bool ProfileImpl::AllowsBrowserWindows() const {
+#if defined(OS_CHROMEOS)
+  if (chromeos::ProfileHelper::IsSigninProfile(this) ||
+      chromeos::ProfileHelper::IsLockScreenAppProfile(this)) {
+    return false;
+  }
+#endif
+  return !IsSystemProfile();
+}
+
 ExtensionSpecialStoragePolicy* ProfileImpl::GetExtensionSpecialStoragePolicy() {
 #if BUILDFLAG(ENABLE_EXTENSIONS)
   if (!extension_special_storage_policy_.get()) {
diff --git a/chrome/browser/profiles/profile_impl.h b/chrome/browser/profiles/profile_impl.h
index 7d8fb7b..bffa1086 100644
--- a/chrome/browser/profiles/profile_impl.h
+++ b/chrome/browser/profiles/profile_impl.h
@@ -131,6 +131,7 @@
   bool IsSupervised() const override;
   bool IsChild() const override;
   bool IsLegacySupervised() const override;
+  bool AllowsBrowserWindows() const override;
   ExtensionSpecialStoragePolicy* GetExtensionSpecialStoragePolicy() override;
   PrefService* GetPrefs() override;
   const PrefService* GetPrefs() const override;
diff --git a/chrome/browser/profiles/profile_window_browsertest.cc b/chrome/browser/profiles/profile_window_browsertest.cc
index 7b3598c..e25f5e0fe 100644
--- a/chrome/browser/profiles/profile_window_browsertest.cc
+++ b/chrome/browser/profiles/profile_window_browsertest.cc
@@ -239,8 +239,16 @@
   EXPECT_FALSE(UserManager::IsShowing());
 }
 
+// TODO(crbug.com/935746): Test is flaky on Win and Linux.
+#if defined(OS_LINUX) || defined(OS_WIN)
+#define MAYBE_OpenBrowserWindowForProfileWithSigninRequired \
+  DISABLED_OpenBrowserWindowForProfileWithSigninRequired
+#else
+#define MAYBE_OpenBrowserWindowForProfileWithSigninRequired \
+  OpenBrowserWindowForProfileWithSigninRequired
+#endif
 IN_PROC_BROWSER_TEST_F(ProfileWindowBrowserTest,
-                       OpenBrowserWindowForProfileWithSigninRequired) {
+                       MAYBE_OpenBrowserWindowForProfileWithSigninRequired) {
   Profile* profile = browser()->profile();
   ProfileAttributesEntry* entry;
   ASSERT_TRUE(g_browser_process->profile_manager()
diff --git a/chrome/browser/resources/chromeos/assistant_optin/assistant_get_more.html b/chrome/browser/resources/chromeos/assistant_optin/assistant_get_more.html
index 0022de9..b1c65f8f 100644
--- a/chrome/browser/resources/chromeos/assistant_optin/assistant_get_more.html
+++ b/chrome/browser/resources/chromeos/assistant_optin/assistant_get_more.html
@@ -8,10 +8,12 @@
     <link rel="stylesheet" href="assistant_get_more.css">
     <link rel="stylesheet" href="assistant_shared_styles.css">
     <oobe-dialog id="get-more-dialog" role="dialog" has-buttons hide-shadow
-        no-footer-padding no-header>
+        no-footer-padding no-header
+        i18n-values="aria-label:assistantReadyTitle">
       <div slot="footer">
         <div class="container">
-          <img id="logo" src="assistant_logo.png">
+          <img id="logo" src="assistant_logo.png"
+              i18n-values="aria-label:assistantLogo">
           <div class="title" i18n-content="assistantReadyTitle"></div>
           <div class="content" id="intro-text"
               i18n-content="assistantReadyMessage"></div>
diff --git a/chrome/browser/resources/chromeos/assistant_optin/assistant_loading.html b/chrome/browser/resources/chromeos/assistant_optin/assistant_loading.html
index aa8db30..ee362e42 100644
--- a/chrome/browser/resources/chromeos/assistant_optin/assistant_loading.html
+++ b/chrome/browser/resources/chromeos/assistant_optin/assistant_loading.html
@@ -14,7 +14,8 @@
         no-footer-padding no-header>
       <div slot="footer">
         <div class="container" id="error-container">
-          <img id="logo" src="assistant_logo.png">
+          <img id="logo" src="assistant_logo.png"
+              i18n-values="aria-label:assistantLogo">
           <div class="title" i18n-content="assistantOptinLoadErrorTitle"></div>
           <div class="sub-title" i18n-content="assistantOptinLoadErrorMessage">
           </div>
diff --git a/chrome/browser/resources/chromeos/assistant_optin/assistant_third_party.html b/chrome/browser/resources/chromeos/assistant_optin/assistant_third_party.html
index d0f650b5..e27c2bcc 100644
--- a/chrome/browser/resources/chromeos/assistant_optin/assistant_third_party.html
+++ b/chrome/browser/resources/chromeos/assistant_optin/assistant_third_party.html
@@ -12,7 +12,8 @@
         no-footer-padding no-header>
       <div slot="footer">
         <div class="container">
-          <img id="logo" src="assistant_logo.png">
+          <img id="logo" src="assistant_logo.png"
+              i18n-values="aria-label:assistantLogo">
           <div class="title" id="title-text"></div>
           <div class="line"></div>
           <div id="insertion-point"></div>
diff --git a/chrome/browser/resources/chromeos/assistant_optin/assistant_third_party.js b/chrome/browser/resources/chromeos/assistant_optin/assistant_third_party.js
index 2c75ab9..c98b609 100644
--- a/chrome/browser/resources/chromeos/assistant_optin/assistant_third_party.js
+++ b/chrome/browser/resources/chromeos/assistant_optin/assistant_third_party.js
@@ -111,6 +111,8 @@
    * Reload the page with the given consent string text data.
    */
   reloadContent: function(data) {
+    this.$['third-party-dialog'].setAttribute(
+        'aria-label', data['thirdPartyTitle']);
     this.$['title-text'].textContent = data['thirdPartyTitle'];
     this.$['next-button-text'].textContent = data['thirdPartyContinueButton'];
     this.$['footer-text'].innerHTML =
diff --git a/chrome/browser/resources/chromeos/assistant_optin/assistant_value_prop.html b/chrome/browser/resources/chromeos/assistant_optin/assistant_value_prop.html
index 198385f..bcd36c9 100644
--- a/chrome/browser/resources/chromeos/assistant_optin/assistant_value_prop.html
+++ b/chrome/browser/resources/chromeos/assistant_optin/assistant_value_prop.html
@@ -14,7 +14,8 @@
         role="dialog" has-buttons no-footer-padding no-header>
       <div slot="footer">
         <div class="container">
-          <img id="logo" src="assistant_logo.png">
+          <img id="logo" src="assistant_logo.png"
+              i18n-values="aria-label:assistantLogo">
           <div class="title" id="title-text"></div>
           <div class="content" id="intro-text"></div>
           <div class="flex layout horizontal center">
diff --git a/chrome/browser/resources/chromeos/assistant_optin/assistant_value_prop.js b/chrome/browser/resources/chromeos/assistant_optin/assistant_value_prop.js
index 626dda1..af5cc79 100644
--- a/chrome/browser/resources/chromeos/assistant_optin/assistant_value_prop.js
+++ b/chrome/browser/resources/chromeos/assistant_optin/assistant_value_prop.js
@@ -241,6 +241,8 @@
    * Reload the page with the given consent string text data.
    */
   reloadContent: function(data) {
+    this.$['value-prop-dialog'].setAttribute(
+        'aria-label', data['valuePropTitle']);
     this.$['user-image'].src = data['valuePropUserImage'];
     this.$['title-text'].textContent = data['valuePropTitle'];
     this.$['intro-text'].textContent = data['valuePropIntro'];
diff --git a/chrome/browser/resources/chromeos/assistant_optin/assistant_voice_match.html b/chrome/browser/resources/chromeos/assistant_optin/assistant_voice_match.html
index 2d9e93c5..84903c9c 100644
--- a/chrome/browser/resources/chromeos/assistant_optin/assistant_voice_match.html
+++ b/chrome/browser/resources/chromeos/assistant_optin/assistant_voice_match.html
@@ -10,10 +10,12 @@
     <link rel="stylesheet" href="assistant_shared_styles.css">
     <link rel="stylesheet" href="assistant_voice_match.css">
     <oobe-dialog id="voice-match-dialog" role="dialog" has-buttons hide-shadow
-        no-footer-padding no-header class="intro">
+        no-footer-padding no-header class="intro"
+        i18n-values="aria-label:assistantVoiceMatchTitle">
       <div slot="footer">
         <div class="container">
-          <img id="logo" src="assistant_logo.png">
+          <img id="logo" src="assistant_logo.png"
+              i18n-values="aria-label:assistantLogo">
           <div id="intro-container">
             <div class="title" i18n-content="assistantVoiceMatchTitle"></div>
             <div class="content"
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/background_test.extjs b/chrome/browser/resources/chromeos/chromevox/cvox2/background/background_test.extjs
index f3746f1..0534cd7 100644
--- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/background_test.extjs
+++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/background_test.extjs
@@ -1369,7 +1369,14 @@
   });
 });
 
-TEST_F('ChromeVoxBackgroundTest', 'TextSelectionAndLiveRegion', function() {
+// TODO(crbug.com/935678): Test times out flakily in MSAN builds.
+TEST_F_WITH_PREAMBLE(`
+#if defined(MEMORY_SANITIZER)
+#define MAYBE_TextSelectionAndLiveRegion DISABLED_TextSelectionAndLiveRegion
+#else
+#define MAYBE_TextSelectionAndLiveRegion TextSelectionAndLiveRegion
+#endif
+`, 'ChromeVoxBackgroundTest', 'MAYBE_TextSelectionAndLiveRegion', function() {
   DesktopAutomationHandler.announceActions = true;
   var mockFeedback = this.createMockFeedback();
   this.runWithLoadedTree(function(root) {/*!
diff --git a/chrome/browser/resources/chromeos/zip_archiver/cpp/volume_archive_minizip.cc b/chrome/browser/resources/chromeos/zip_archiver/cpp/volume_archive_minizip.cc
index b155f35..309ade6 100644
--- a/chrome/browser/resources/chromeos/zip_archiver/cpp/volume_archive_minizip.cc
+++ b/chrome/browser/resources/chromeos/zip_archiver/cpp/volume_archive_minizip.cc
@@ -56,7 +56,7 @@
   return MZ_OK;
 }
 
-};  // namespace
+}  // namespace
 
 // vtable for the archive read stream provided to minizip. Only functions which
 // are necessary to read the archive are provided.
diff --git a/chrome/browser/resources/settings/crostini_page/crostini_subpage.html b/chrome/browser/resources/settings/crostini_page/crostini_subpage.html
index a83dd31e..0f5db20 100644
--- a/chrome/browser/resources/settings/crostini_page/crostini_subpage.html
+++ b/chrome/browser/resources/settings/crostini_page/crostini_subpage.html
@@ -44,13 +44,15 @@
         </div>
       </div>
     </template>
-    <div id="remove" class="settings-box"
-        actionable on-click="onRemoveTap_">
-      <div class="start">$i18n{crostiniRemove}</div>
-      <paper-icon-button-light class="subpage-arrow">
-        <button aria-label="$i18n{crostiniRemove}"></button>
-      </paper-icon-button-light>
-    </div>
+    <template is="dom-if" if="[[!hideCrostiniUninstall_]]">
+      <div id="remove" class="settings-box"
+           actionable on-click="onRemoveTap_">
+        <div class="start">$i18n{crostiniRemove}</div>
+        <paper-icon-button-light class="subpage-arrow">
+          <button aria-label="$i18n{crostiniRemove}"></button>
+        </paper-icon-button-light>
+      </div>
+    </template>
   </template>
   <script src="crostini_subpage.js"></script>
 </dom-module>
diff --git a/chrome/browser/resources/settings/crostini_page/crostini_subpage.js b/chrome/browser/resources/settings/crostini_page/crostini_subpage.js
index d671051..c3690f73 100644
--- a/chrome/browser/resources/settings/crostini_page/crostini_subpage.js
+++ b/chrome/browser/resources/settings/crostini_page/crostini_subpage.js
@@ -40,10 +40,26 @@
         return loadTimeData.getBoolean('showCrostiniExportImport');
       },
     },
+
+    /**
+     * Whether the uninstall options should be displayed.
+     * @private {boolean}
+     */
+    hideCrostiniUninstall_: {
+      type: Boolean,
+    },
   },
 
   observers: ['onCrostiniEnabledChanged_(prefs.crostini.enabled.value)'],
 
+  created: function() {
+    const callback = (status) => {
+      this.hideCrostiniUninstall_ = status;
+    };
+    cr.addWebUIListener('crostini-installer-status-changed', callback);
+    cr.sendWithPromise('requestCrostiniInstallerStatus').then(callback);
+  },
+
   /** @private */
   onCrostiniEnabledChanged_: function(enabled) {
     if (!enabled &&
diff --git a/chrome/browser/task_manager/sampling/arc_shared_sampler.cc b/chrome/browser/task_manager/sampling/arc_shared_sampler.cc
index b327661..dd38ced 100644
--- a/chrome/browser/task_manager/sampling/arc_shared_sampler.cc
+++ b/chrome/browser/task_manager/sampling/arc_shared_sampler.cc
@@ -23,7 +23,7 @@
 constexpr base::TimeDelta kAppThrottleLimit = base::TimeDelta::FromSeconds(2);
 constexpr base::TimeDelta kSystemThrottleLimit =
     base::TimeDelta::FromSeconds(3);
-};  // namespace
+}  // namespace
 
 ArcSharedSampler::ArcSharedSampler() : weak_ptr_factory_(this) {}
 
diff --git a/chrome/browser/translate/translate_fake_page.cc b/chrome/browser/translate/translate_fake_page.cc
index de2c7a6..e009e6a3 100644
--- a/chrome/browser/translate/translate_fake_page.cc
+++ b/chrome/browser/translate/translate_fake_page.cc
@@ -54,6 +54,8 @@
 
 // translate::mojom::Page implementation.
 void FakePageImpl::Translate(const std::string& translate_script,
+                             network::mojom::URLLoaderFactoryPtr
+                                 unused_loader_factory_for_translate_script,
                              const std::string& source_lang,
                              const std::string& target_lang,
                              TranslateCallback callback) {
diff --git a/chrome/browser/translate/translate_fake_page.h b/chrome/browser/translate/translate_fake_page.h
index bd368d22..c456071 100644
--- a/chrome/browser/translate/translate_fake_page.h
+++ b/chrome/browser/translate/translate_fake_page.h
@@ -9,10 +9,12 @@
 
 #include <memory>
 #include <set>
+#include <string>
 #include <tuple>
 #include <utility>
 #include <vector>
 
+#include "base/optional.h"
 #include "build/build_config.h"
 #include "chrome/browser/infobars/infobar_service.h"
 #include "chrome/browser/renderer_context_menu/render_view_context_menu_test_util.h"
@@ -47,10 +49,12 @@
   translate::mojom::PagePtr BindToNewPagePtr();
 
   // translate::mojom::Page implementation.
-  void Translate(const std::string& translate_script,
-                 const std::string& source_lang,
-                 const std::string& target_lang,
-                 TranslateCallback callback) override;
+  void Translate(
+      const std::string& translate_script,
+      network::mojom::URLLoaderFactoryPtr loader_factory_for_translate_script,
+      const std::string& source_lang,
+      const std::string& target_lang,
+      TranslateCallback callback) override;
 
   void RevertTranslation() override;
 
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index 91a02a3..acc5a52 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -2655,6 +2655,8 @@
       "views/page_action/page_action_icon_container_view.h",
       "views/page_action/page_action_icon_view.cc",
       "views/page_action/page_action_icon_view.h",
+      "views/page_action/pwa_install_view.cc",
+      "views/page_action/pwa_install_view.h",
       "views/page_action/zoom_view.cc",
       "views/page_action/zoom_view.h",
       "views/page_info/chosen_object_view.cc",
diff --git a/chrome/browser/ui/app_list/app_list_client_impl.cc b/chrome/browser/ui/app_list/app_list_client_impl.cc
index 38713223..25dffa6 100644
--- a/chrome/browser/ui/app_list/app_list_client_impl.cc
+++ b/chrome/browser/ui/app_list/app_list_client_impl.cc
@@ -260,6 +260,18 @@
   }
 }
 
+void AppListClientImpl::OnSearchResultVisibilityChanged(const std::string& id,
+                                                        bool visibility) {
+  if (!search_controller_)
+    return;
+
+  ChromeSearchResult* result = search_controller_->FindSearchResult(id);
+  if (result == nullptr) {
+    return;
+  }
+  result->OnVisibilityChanged(visibility);
+}
+
 void AppListClientImpl::ActiveUserChanged(
     const user_manager::User* active_user) {
   if (!active_user->is_profile_created())
diff --git a/chrome/browser/ui/app_list/app_list_client_impl.h b/chrome/browser/ui/app_list/app_list_client_impl.h
index 8721360..60078c1 100644
--- a/chrome/browser/ui/app_list/app_list_client_impl.h
+++ b/chrome/browser/ui/app_list/app_list_client_impl.h
@@ -78,6 +78,8 @@
   void OnPageBreakItemDeleted(const std::string& id) override;
   void GetNavigableContentsFactory(
       content::mojom::NavigableContentsFactoryRequest request) override;
+  void OnSearchResultVisibilityChanged(const std::string& id,
+                                       bool visible) override;
 
   // user_manager::UserManager::UserSessionStateObserver:
   void ActiveUserChanged(const user_manager::User* active_user) override;
diff --git a/chrome/browser/ui/app_list/crostini/crostini_app_context_menu.cc b/chrome/browser/ui/app_list/crostini/crostini_app_context_menu.cc
index 0155ddf..48e3240 100644
--- a/chrome/browser/ui/app_list/crostini/crostini_app_context_menu.cc
+++ b/chrome/browser/ui/app_list/crostini/crostini_app_context_menu.cc
@@ -26,8 +26,11 @@
   if (!crostini::IsCrostiniEnabled(profile())) {
     return false;
   }
-  if (app_id() == crostini::kCrostiniTerminalId) {
-    return true;  // Crostini can always be uninstalled if enabled.
+  if (app_id() == crostini::kCrostiniTerminalId &&
+      !crostini::CrostiniManager::GetForProfile(profile())
+           ->GetInstallerViewStatus()) {
+    // Crostini should not be uninstalled if the installer is still running.
+    return true;
   }
 
   if (!base::FeatureList::IsEnabled(features::kCrostiniAppUninstallGui)) {
diff --git a/chrome/browser/ui/app_list/search/arc/arc_app_reinstall_app_result.cc b/chrome/browser/ui/app_list/search/arc/arc_app_reinstall_app_result.cc
index f2cd178..82b830f 100644
--- a/chrome/browser/ui/app_list/search/arc/arc_app_reinstall_app_result.cc
+++ b/chrome/browser/ui/app_list/search/arc/arc_app_reinstall_app_result.cc
@@ -27,16 +27,15 @@
     const arc::mojom::AppReinstallCandidatePtr& mojom_data,
 
     const gfx::ImageSkia& skia_icon) {
-  ash::mojom::SearchResultMetadataPtr metadata = {base::in_place};
   set_id(kPlayStoreAppUrlPrefix + mojom_data->package_name);
   SetResultType(ash::SearchResultType::kPlayStoreReinstallApp);
   SetTitle(base::UTF8ToUTF16(mojom_data->title));
-  SetDetails(base::UTF8ToUTF16(metadata->id));
   SetDisplayType(ash::SearchResultDisplayType::kRecommendation);
   set_relevance(kAppReinstallRelevance);
 
   SetIcon(skia_icon);
   SetChipIcon(skia_icon);
+  SetNotifyVisibilityChange(true);
 
   if (mojom_data->star_rating != 0.0f)
     SetRating(mojom_data->star_rating);
diff --git a/chrome/browser/ui/app_list/search/arc/arc_app_shortcuts_search_provider.cc b/chrome/browser/ui/app_list/search/arc/arc_app_shortcuts_search_provider.cc
index c3a91c24..b16b080 100644
--- a/chrome/browser/ui/app_list/search/arc/arc_app_shortcuts_search_provider.cc
+++ b/chrome/browser/ui/app_list/search/arc/arc_app_shortcuts_search_provider.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/ui/app_list/search/arc/arc_app_shortcuts_search_provider.h"
 
 #include <memory>
+#include <string>
 #include <utility>
 
 #include "ash/public/cpp/app_list/app_list_features.h"
@@ -14,6 +15,7 @@
 #include "chrome/browser/ui/app_list/arc/arc_app_utils.h"
 #include "chrome/browser/ui/app_list/search/arc/arc_app_shortcut_search_result.h"
 #include "chrome/browser/ui/app_list/search/search_result_ranker/app_search_result_ranker.h"
+#include "chrome/browser/ui/app_list/search/search_result_ranker/ranking_item_util.h"
 #include "components/arc/arc_bridge_service.h"
 #include "components/arc/arc_service_manager.h"
 
@@ -54,10 +56,19 @@
           weak_ptr_factory_.GetWeakPtr()));
 }
 
+void ArcAppShortcutsSearchProvider::Train(const std::string& id,
+                                          RankingItemType type) {
+  if (type == RankingItemType::kArcAppShortcut && ranker_ != nullptr)
+    ranker_->Train(id);
+}
+
 void ArcAppShortcutsSearchProvider::OnGetAppShortcutGlobalQueryItems(
     std::vector<arc::mojom::AppShortcutItemPtr> shortcut_items) {
   const ArcAppListPrefs* arc_prefs = ArcAppListPrefs::Get(profile_);
   DCHECK(arc_prefs);
+  base::flat_map<std::string, float> ranker_scores;
+  if (app_list_features::IsAppSearchResultRankerEnabled() && ranker_ != nullptr)
+    ranker_scores = ranker_->Rank();
 
   SearchProvider::Results search_results;
   for (auto& item : shortcut_items) {
@@ -68,16 +79,16 @@
     // Ignore shortcuts for apps that are not present in the launcher.
     if (!app_info || !app_info->show_in_launcher)
       continue;
-    search_results.emplace_back(std::make_unique<ArcAppShortcutSearchResult>(
-        std::move(item), profile_, list_controller_));
-
-    if (app_list_features::IsAppSearchResultRankerEnabled() &&
-        ranker_ != nullptr) {
-      // TODO(crbug.com/931149): tweak the scores of each search result item
-      // using the ranker.
-    }
+    auto result = std::make_unique<ArcAppShortcutSearchResult>(
+        std::move(item), profile_, list_controller_);
+    // TODO(crbug.com/931149): update the formula for relevance scores.
+    // This formula should be updated in the same way as query-based
+    // app search results
+    const auto find_in_ranker = ranker_scores.find(result->id());
+    if (find_in_ranker != ranker_scores.end())
+      result->set_relevance(result->relevance() + find_in_ranker->second / 10);
+    search_results.emplace_back(std::move(result));
   }
-
   SwapResults(&search_results);
 }
 
diff --git a/chrome/browser/ui/app_list/search/arc/arc_app_shortcuts_search_provider.h b/chrome/browser/ui/app_list/search/arc/arc_app_shortcuts_search_provider.h
index af537a62..8b3b3914 100644
--- a/chrome/browser/ui/app_list/search/arc/arc_app_shortcuts_search_provider.h
+++ b/chrome/browser/ui/app_list/search/arc/arc_app_shortcuts_search_provider.h
@@ -5,6 +5,7 @@
 #ifndef CHROME_BROWSER_UI_APP_LIST_SEARCH_ARC_ARC_APP_SHORTCUTS_SEARCH_PROVIDER_H_
 #define CHROME_BROWSER_UI_APP_LIST_SEARCH_ARC_ARC_APP_SHORTCUTS_SEARCH_PROVIDER_H_
 
+#include <string>
 #include <vector>
 
 #include "base/macros.h"
@@ -30,6 +31,7 @@
 
   // SearchProvider:
   void Start(const base::string16& query) override;
+  void Train(const std::string& id, RankingItemType type) override;
 
  private:
   void OnGetAppShortcutGlobalQueryItems(
@@ -38,8 +40,6 @@
   const int max_results_;
   Profile* const profile_;                            // Owned by ProfileInfo.
   AppListControllerDelegate* const list_controller_;  // Owned by AppListClient.
-  // TODO(crbug.com/931149): train this ranker on app shortcut clicks, and use
-  // it to tweak their relevance scores.
   AppSearchResultRanker* ranker_;
 
   base::WeakPtrFactory<ArcAppShortcutsSearchProvider> weak_ptr_factory_;
diff --git a/chrome/browser/ui/app_list/search/arc/arc_app_shortcuts_search_provider_unittest.cc b/chrome/browser/ui/app_list/search/arc/arc_app_shortcuts_search_provider_unittest.cc
index da831c6..e92c850 100644
--- a/chrome/browser/ui/app_list/search/arc/arc_app_shortcuts_search_provider_unittest.cc
+++ b/chrome/browser/ui/app_list/search/arc/arc_app_shortcuts_search_provider_unittest.cc
@@ -17,6 +17,7 @@
 #include "chrome/browser/ui/app_list/arc/arc_app_test.h"
 #include "chrome/browser/ui/app_list/search/chrome_search_result.h"
 #include "chrome/browser/ui/app_list/search/search_result_ranker/app_search_result_ranker.h"
+#include "chrome/browser/ui/app_list/search/search_result_ranker/ranking_item_util.h"
 #include "chrome/browser/ui/app_list/test/test_app_list_controller_delegate.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -88,7 +89,7 @@
 TEST_P(ArcAppShortcutsSearchProviderTest, Basic) {
   const bool launchable = GetParam();
 
-  AddArcAppAndShortcut(
+  const std::string app_id = AddArcAppAndShortcut(
       CreateAppInfo("FakeName", "FakeActivity", kFakeAppPackageName),
       launchable);
 
@@ -109,6 +110,27 @@
               base::UTF16ToUTF8(results[i]->title()));
     EXPECT_EQ(ash::SearchResultDisplayType::kTile, results[i]->display_type());
   }
+
+  // If ranker_ is nullptr, the program won't break
+  // TODO(crbug.com/931149): Add more tests to check ranker_ does have some
+  // effects
+  auto provider_null_ranker = std::make_unique<ArcAppShortcutsSearchProvider>(
+      kMaxResults, profile(), controller_.get(), nullptr);
+
+  EXPECT_TRUE(provider_null_ranker->results().empty());
+  arc::IconDecodeRequest::DisableSafeDecodingForTesting();
+
+  provider_null_ranker->Start(base::UTF8ToUTF16(kQuery));
+  provider_null_ranker->Train(app_id, RankingItemType::kArcAppShortcut);
+  const auto& results_null_ranker = provider_null_ranker->results();
+  EXPECT_EQ(kMaxResults, results_null_ranker.size());
+  // Verify search results.
+  for (size_t i = 0; i < results_null_ranker.size(); ++i) {
+    EXPECT_EQ(base::StringPrintf("ShortLabel %zu", i),
+              base::UTF16ToUTF8(results_null_ranker[i]->title()));
+    EXPECT_EQ(ash::SearchResultDisplayType::kTile,
+              results_null_ranker[i]->display_type());
+  }
 }
 
 INSTANTIATE_TEST_SUITE_P(, ArcAppShortcutsSearchProviderTest, testing::Bool());
diff --git a/chrome/browser/ui/app_list/search/chrome_search_result.cc b/chrome/browser/ui/app_list/search/chrome_search_result.cc
index 03409c3..2856c465 100644
--- a/chrome/browser/ui/app_list/search/chrome_search_result.cc
+++ b/chrome/browser/ui/app_list/search/chrome_search_result.cc
@@ -153,6 +153,11 @@
     updater->SetSearchResultMetadata(id(), CloneMetadata());
 }
 
+void ChromeSearchResult::SetNotifyVisibilityChange(
+    bool notify_visibility_change) {
+  metadata_->notify_visibility_change = notify_visibility_change;
+}
+
 void ChromeSearchResult::NotifyItemInstalled() {
   AppListModelUpdater* updater = model_updater();
   if (updater)
@@ -161,6 +166,10 @@
 
 void ChromeSearchResult::InvokeAction(int action_index, int event_flags) {}
 
+void ChromeSearchResult::OnVisibilityChanged(bool visibility) {
+  VLOG(1) << " Visibility change to " << visibility << " and ID is " << id();
+}
+
 void ChromeSearchResult::UpdateFromMatch(
     const app_list::TokenizedString& title,
     const app_list::TokenizedStringMatch& match) {
diff --git a/chrome/browser/ui/app_list/search/chrome_search_result.h b/chrome/browser/ui/app_list/search/chrome_search_result.h
index 0de4454..b218830 100644
--- a/chrome/browser/ui/app_list/search/chrome_search_result.h
+++ b/chrome/browser/ui/app_list/search/chrome_search_result.h
@@ -57,6 +57,10 @@
   const gfx::ImageSkia& chip_icon() const { return metadata_->chip_icon; }
   const gfx::ImageSkia& badge_icon() const { return metadata_->badge_icon; }
 
+  bool notify_visibility_change() const {
+    return metadata_->notify_visibility_change;
+  }
+
   // The following methods set Chrome side data here, and call model updater
   // interface to update Ash.
   void SetTitle(const base::string16& title);
@@ -77,6 +81,7 @@
   void SetIcon(const gfx::ImageSkia& icon);
   void SetChipIcon(const gfx::ImageSkia& icon);
   void SetBadgeIcon(const gfx::ImageSkia& badge_icon);
+  void SetNotifyVisibilityChange(bool notify_visibility_change);
 
   // The following methods call model updater to update Ash.
   void SetPercentDownloaded(int percent_downloaded);
@@ -103,6 +108,9 @@
   // Opens the result. Clients should use AppListViewDelegate::OpenSearchResult.
   virtual void Open(int event_flags) = 0;
 
+  // Called if set visible/hidden.
+  virtual void OnVisibilityChanged(bool visibility);
+
   // Updates the result's relevance score, and sets its title and title tags,
   // based on a string match result.
   void UpdateFromMatch(const app_list::TokenizedString& title,
diff --git a/chrome/browser/ui/app_list/search/search_result_ranker/ranking_item_util.cc b/chrome/browser/ui/app_list/search/search_result_ranker/ranking_item_util.cc
index 42ced60..01825e2 100644
--- a/chrome/browser/ui/app_list/search/search_result_ranker/ranking_item_util.cc
+++ b/chrome/browser/ui/app_list/search/search_result_ranker/ranking_item_util.cc
@@ -93,4 +93,4 @@
   return RankingItemType::kApp;
 }
 
-};  // namespace app_list
+}  // namespace app_list
diff --git a/chrome/browser/ui/app_list/search/search_result_ranker/ranking_item_util.h b/chrome/browser/ui/app_list/search/search_result_ranker/ranking_item_util.h
index 17adb15..f8d274a2 100644
--- a/chrome/browser/ui/app_list/search/search_result_ranker/ranking_item_util.h
+++ b/chrome/browser/ui/app_list/search/search_result_ranker/ranking_item_util.h
@@ -37,6 +37,6 @@
 RankingItemType RankingItemTypeFromChromeAppListItem(
     const ChromeAppListItem& item);
 
-};  // namespace app_list
+}  // namespace app_list
 
 #endif  // CHROME_BROWSER_UI_APP_LIST_SEARCH_SEARCH_RESULT_RANKER_RANKING_ITEM_UTIL_H_
diff --git a/chrome/browser/ui/ash/multi_user/multi_user_util_chromeos_unittest.cc b/chrome/browser/ui/ash/multi_user/multi_user_util_chromeos_unittest.cc
index f5aa2c7..7346997 100644
--- a/chrome/browser/ui/ash/multi_user/multi_user_util_chromeos_unittest.cc
+++ b/chrome/browser/ui/ash/multi_user/multi_user_util_chromeos_unittest.cc
@@ -75,7 +75,7 @@
 
   identity::IdentityTestEnvironment* identity_test_env() {
     return identity_test_env_adaptor_->identity_test_env();
-  };
+  }
 
  private:
   std::unique_ptr<TestingProfile> profile_;
diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc
index d2092842..cea05aa 100644
--- a/chrome/browser/ui/browser.cc
+++ b/chrome/browser/ui/browser.cc
@@ -306,6 +306,13 @@
   }
 }
 
+// Returns whether a browser window can be created for the specified profile.
+bool CanCreateBrowserForProfile(Profile* profile) {
+  return IncognitoModePrefs::CanOpenBrowser(profile) &&
+         (!profile->IsGuestSession() || profile->IsOffTheRecord()) &&
+         profile->AllowsBrowserWindows();
+}
+
 }  // namespace
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -383,6 +390,13 @@
 ///////////////////////////////////////////////////////////////////////////////
 // Browser, Constructors, Creation, Showing:
 
+// static
+Browser* Browser::Create(const CreateParams& params) {
+  if (!CanCreateBrowserForProfile(params.profile))
+    return nullptr;
+  return new Browser(params);
+}
+
 Browser::Browser(const CreateParams& params)
     : extension_registry_observer_(this),
       type_(params.type),
diff --git a/chrome/browser/ui/browser.h b/chrome/browser/ui/browser.h
index f78f734c..41e0a9b 100644
--- a/chrome/browser/ui/browser.h
+++ b/chrome/browser/ui/browser.h
@@ -237,6 +237,22 @@
 
   // Constructors, Creation, Showing //////////////////////////////////////////
 
+  // Creates a browser instance with the provided params.
+  // Returns nullptr if the requested browser creation is not allowed.
+  // For example, browser creation will not be allowed for profiles that
+  // disallow browsing (like sign-in profile on Chrome OS).
+  //
+  // Unless |params->window| is specified, a new BrowserWindow will be created
+  // for the browser - the created BrowserWindow will take the ownership of the
+  // created Browser instance.
+  //
+  // If |params.window| or |params.skip_window_init_for_testing| are set, the
+  // caller is expected to take the ownership of the created Browser instance.
+  static Browser* Create(const CreateParams& params);
+
+  // DEPRECATED in favor of Create().
+  // TODO(tbarzic): Make the constructor non-public once browser construction
+  // instances are replaced with Create(). https://crbug.com/916859.
   explicit Browser(const CreateParams& params);
   ~Browser() override;
 
diff --git a/chrome/browser/ui/browser_unittest.cc b/chrome/browser/ui/browser_unittest.cc
index 44009caf..9cc1375 100644
--- a/chrome/browser/ui/browser_unittest.cc
+++ b/chrome/browser/ui/browser_unittest.cc
@@ -6,10 +6,12 @@
 
 #include "base/macros.h"
 #include "chrome/app/chrome_command_ids.h"
+#include "chrome/browser/prefs/incognito_mode_prefs.h"
 #include "chrome/browser/ui/browser_command_controller.h"
 #include "chrome/browser/ui/browser_commands.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/test/base/browser_with_test_window_test.h"
+#include "chrome/test/base/testing_profile.h"
 #include "components/zoom/zoom_controller.h"
 #include "content/public/browser/render_widget_host_view.h"
 #include "content/public/browser/site_instance.h"
@@ -154,6 +156,118 @@
   EXPECT_FALSE(chrome::CanZoomOut(raw_contents));
 }
 
+// Tests that Browser::Create creates a guest session browser for OTR profile
+// only.
+TEST_F(BrowserUnitTest, CreateGuestSessionBrowser) {
+  TestingProfile::Builder profile_builder;
+  profile_builder.SetGuestSession();
+  std::unique_ptr<TestingProfile> test_profile = profile_builder.Build();
+  TestingProfile::Builder otr_profile_builder;
+  otr_profile_builder.SetGuestSession();
+  otr_profile_builder.BuildIncognito(test_profile.get());
+
+  // Try creating a browser in original guest profile - it should fail.
+  std::unique_ptr<Browser> browser(
+      Browser::Create(Browser::CreateParams(test_profile.get(), false)));
+  EXPECT_FALSE(browser);
+
+  // Creating a browser in OTR guest profile should succeed.
+  Browser::CreateParams off_the_record_create_params(
+      test_profile->GetOffTheRecordProfile(), false);
+  std::unique_ptr<BrowserWindow> test_window(CreateBrowserWindow());
+  off_the_record_create_params.window = test_window.get();
+  std::unique_ptr<Browser> otr_browser(
+      Browser::Create(off_the_record_create_params));
+  EXPECT_TRUE(otr_browser);
+}
+
+TEST_F(BrowserUnitTest, CreateBrowserFailsIfProfileDisallowsBrowserWindows) {
+  TestingProfile::Builder profile_builder;
+  profile_builder.DisallowBrowserWindows();
+  std::unique_ptr<TestingProfile> test_profile = profile_builder.Build();
+  TestingProfile::Builder otr_profile_builder;
+  otr_profile_builder.DisallowBrowserWindows();
+  otr_profile_builder.BuildIncognito(test_profile.get());
+
+  // Verify creating browser fails in both original and OTR version of the
+  // profile.
+  std::unique_ptr<Browser> browser(
+      Browser::Create(Browser::CreateParams(test_profile.get(), false)));
+  EXPECT_FALSE(browser);
+  std::unique_ptr<Browser> otr_browser(Browser::Create(
+      Browser::CreateParams(test_profile->GetOffTheRecordProfile(), false)));
+  EXPECT_FALSE(otr_browser);
+}
+
+// Tests BrowserCreate() when Incognito mode is disabled.
+TEST_F(BrowserUnitTest, CreateBrowserWithIncognitoModeDisabled) {
+  TestingProfile::Builder profile_builder;
+  std::unique_ptr<TestingProfile> test_profile = profile_builder.Build();
+  IncognitoModePrefs::SetAvailability(test_profile->GetPrefs(),
+                                      IncognitoModePrefs::DISABLED);
+
+  // Creating a browser window in OTR profile should fail if incognito is
+  // disabled.
+  std::unique_ptr<Browser> otr_browser(Browser::Create(
+      Browser::CreateParams(test_profile->GetOffTheRecordProfile(), false)));
+  EXPECT_FALSE(otr_browser);
+
+  // Verify creating a browser in the original profile succeeds.
+  Browser::CreateParams create_params(test_profile.get(), false);
+  std::unique_ptr<BrowserWindow> test_window(CreateBrowserWindow());
+  create_params.window = test_window.get();
+  std::unique_ptr<Browser> test_browser(Browser::Create(create_params));
+  EXPECT_TRUE(test_browser);
+}
+
+// Tests BrowserCreate() when Incognito mode is forced.
+TEST_F(BrowserUnitTest, CreateBrowserWithIncognitoModeForced) {
+  TestingProfile::Builder profile_builder;
+  std::unique_ptr<TestingProfile> test_profile = profile_builder.Build();
+  IncognitoModePrefs::SetAvailability(test_profile->GetPrefs(),
+                                      IncognitoModePrefs::FORCED);
+
+  // Creating a browser window in the original profile should fail if incognito
+  // is forced.
+  std::unique_ptr<Browser> browser(
+      Browser::Create(Browser::CreateParams(test_profile.get(), false)));
+  EXPECT_FALSE(browser);
+
+  // Creating a browser in OTR test profile should succeed.
+  Browser::CreateParams off_the_record_create_params(
+      test_profile->GetOffTheRecordProfile(), false);
+  std::unique_ptr<BrowserWindow> test_window(CreateBrowserWindow());
+  off_the_record_create_params.window = test_window.get();
+  std::unique_ptr<Browser> otr_browser(
+      Browser::Create(off_the_record_create_params));
+  EXPECT_TRUE(otr_browser);
+}
+
+// Tests BrowserCreate() with not restrictions on incognito mode.
+TEST_F(BrowserUnitTest, CreateBrowserWithIncognitoModeEnabled) {
+  TestingProfile::Builder profile_builder;
+  std::unique_ptr<TestingProfile> test_profile = profile_builder.Build();
+
+  ASSERT_EQ(IncognitoModePrefs::ENABLED,
+            IncognitoModePrefs::GetAvailability(test_profile->GetPrefs()));
+
+  // Creating a browser in the original test profile should succeed.
+  Browser::CreateParams create_params(test_profile.get(), false);
+  std::unique_ptr<BrowserWindow> test_window(CreateBrowserWindow());
+  create_params.window = test_window.get();
+  std::unique_ptr<Browser> test_browser(Browser::Create(create_params));
+  EXPECT_TRUE(test_browser);
+
+  // Creating a browser in OTR test profile should succeed.
+  Browser::CreateParams off_the_record_create_params(
+      test_profile->GetOffTheRecordProfile(), false);
+  std::unique_ptr<BrowserWindow> otr_test_window(CreateBrowserWindow());
+  off_the_record_create_params.window = otr_test_window.get();
+  std::unique_ptr<Browser> otr_browser(
+      Browser::Create(off_the_record_create_params));
+  EXPECT_TRUE(otr_browser);
+}
+
 class BrowserBookmarkBarTest : public BrowserWithTestWindowTest {
  public:
   BrowserBookmarkBarTest() {}
diff --git a/chrome/browser/ui/extensions/hosted_app_browsertest.cc b/chrome/browser/ui/extensions/hosted_app_browsertest.cc
index 3dfc4475..b33d5ade 100644
--- a/chrome/browser/ui/extensions/hosted_app_browsertest.cc
+++ b/chrome/browser/ui/extensions/hosted_app_browsertest.cc
@@ -24,7 +24,7 @@
 #include "chrome/browser/badging/badge_manager.h"
 #include "chrome/browser/badging/badge_manager_delegate.h"
 #include "chrome/browser/badging/badge_manager_factory.h"
-#include "chrome/browser/banners/app_banner_manager_desktop.h"
+#include "chrome/browser/banners/test_app_banner_manager_desktop.h"
 #include "chrome/browser/engagement/site_engagement_service.h"
 #include "chrome/browser/extensions/extension_browsertest.h"
 #include "chrome/browser/extensions/extension_service.h"
@@ -259,62 +259,6 @@
   return model->IsEnabledAt(index) ? kEnabled : kDisabled;
 }
 
-class TestAppBannerManagerDesktop : public banners::AppBannerManagerDesktop {
- public:
-  explicit TestAppBannerManagerDesktop(WebContents* web_contents)
-      : AppBannerManagerDesktop(web_contents) {}
-
-  static TestAppBannerManagerDesktop* CreateForWebContents(
-      WebContents* web_contents) {
-    web_contents->SetUserData(
-        UserDataKey(),
-        std::make_unique<TestAppBannerManagerDesktop>(web_contents));
-    return static_cast<TestAppBannerManagerDesktop*>(
-        web_contents->GetUserData(UserDataKey()));
-  }
-
-  // Returns whether the installable check passed.
-  bool WaitForInstallableCheck() {
-    DCHECK(IsExperimentalAppBannersEnabled());
-
-    if (!installable_.has_value()) {
-      base::RunLoop run_loop;
-      quit_closure_ = run_loop.QuitClosure();
-      run_loop.Run();
-    }
-    DCHECK(installable_.has_value());
-    return *installable_;
-  }
-
-  // AppBannerManager:
-  void OnDidGetManifest(const InstallableData& result) override {
-    AppBannerManagerDesktop::OnDidGetManifest(result);
-
-    // AppBannerManagerDesktop does not call |OnDidPerformInstallableCheck| to
-    // complete the installability check in this case, instead it early exits
-    // with failure.
-    if (result.error_code != NO_ERROR_DETECTED)
-      SetInstallable(false);
-  }
-  void OnDidPerformInstallableCheck(const InstallableData& result) override {
-    AppBannerManagerDesktop::OnDidPerformInstallableCheck(result);
-    SetInstallable(result.error_code == NO_ERROR_DETECTED);
-  }
-
- private:
-  void SetInstallable(bool installable) {
-    DCHECK(!installable_.has_value());
-    installable_ = installable;
-    if (quit_closure_)
-      std::move(quit_closure_).Run();
-  }
-
-  base::Optional<bool> installable_;
-  base::OnceClosure quit_closure_;
-
-  DISALLOW_COPY_AND_ASSIGN(TestAppBannerManagerDesktop);
-};
-
 }  // namespace
 
 // Parameters are {app_type, desktop_pwa_flag}. |app_type| controls whether it
@@ -1258,7 +1202,7 @@
 // incognito windows.
 IN_PROC_BROWSER_TEST_P(HostedAppPWAOnlyTest, ShortcutMenuOptionsInIncognito) {
   Browser* incognito_browser = CreateIncognitoBrowser(profile());
-  auto* manager = TestAppBannerManagerDesktop::CreateForWebContents(
+  auto* manager = banners::TestAppBannerManagerDesktop::CreateForWebContents(
       incognito_browser->tab_strip_model()->GetActiveWebContents());
 
   ASSERT_TRUE(https_server()->Start());
@@ -1275,7 +1219,7 @@
 // for an installable PWA.
 IN_PROC_BROWSER_TEST_P(HostedAppPWAOnlyTest,
                        ShortcutMenuOptionsForInstallablePWA) {
-  auto* manager = TestAppBannerManagerDesktop::CreateForWebContents(
+  auto* manager = banners::TestAppBannerManagerDesktop::CreateForWebContents(
       browser()->tab_strip_model()->GetActiveWebContents());
 
   ASSERT_TRUE(https_server()->Start());
@@ -1290,7 +1234,7 @@
 // a non-installable site.
 IN_PROC_BROWSER_TEST_P(HostedAppPWAOnlyTest,
                        ShortcutMenuOptionsForNonInstallableSite) {
-  auto* manager = TestAppBannerManagerDesktop::CreateForWebContents(
+  auto* manager = banners::TestAppBannerManagerDesktop::CreateForWebContents(
       browser()->tab_strip_model()->GetActiveWebContents());
 
   ASSERT_TRUE(https_server()->Start());
@@ -1381,7 +1325,7 @@
 // Tests that the manifest name of the current installable site is used in the
 // installation menu text.
 IN_PROC_BROWSER_TEST_P(HostedAppPWAOnlyTest, InstallToShelfContainsAppName) {
-  auto* manager = TestAppBannerManagerDesktop::CreateForWebContents(
+  auto* manager = banners::TestAppBannerManagerDesktop::CreateForWebContents(
       browser()->tab_strip_model()->GetActiveWebContents());
 
   ASSERT_TRUE(https_server()->Start());
diff --git a/chrome/browser/ui/page_action/page_action_icon_container.h b/chrome/browser/ui/page_action/page_action_icon_container.h
index 39d72d4..773bb18 100644
--- a/chrome/browser/ui/page_action/page_action_icon_container.h
+++ b/chrome/browser/ui/page_action/page_action_icon_container.h
@@ -10,6 +10,7 @@
   // of LocationBar to this interface.
   kFind,
   kManagePasswords,
+  kPwaInstall,
   kTranslate,
   kZoom,
 };
diff --git a/chrome/browser/ui/toolbar/chrome_location_bar_model_delegate.cc b/chrome/browser/ui/toolbar/chrome_location_bar_model_delegate.cc
index 75c4de6..e6b0ed0 100644
--- a/chrome/browser/ui/toolbar/chrome_location_bar_model_delegate.cc
+++ b/chrome/browser/ui/toolbar/chrome_location_bar_model_delegate.cc
@@ -18,6 +18,7 @@
 #include "components/offline_pages/buildflags/buildflags.h"
 #include "components/omnibox/browser/autocomplete_input.h"
 #include "components/prefs/pref_service.h"
+#include "components/security_interstitials/content/security_interstitial_tab_helper.h"
 #include "components/security_state/core/security_state.h"
 #include "content/public/browser/navigation_controller.h"
 #include "content/public/browser/navigation_entry.h"
@@ -93,6 +94,12 @@
   if (!entry)
     return true;
 
+  security_interstitials::SecurityInterstitialTabHelper* tab_helper =
+      security_interstitials::SecurityInterstitialTabHelper::FromWebContents(
+          GetActiveWebContents());
+  if (tab_helper && tab_helper->IsDisplayingInterstitial())
+    return tab_helper->ShouldDisplayURL();
+
   if (entry->IsViewSourceMode() ||
       entry->GetPageType() == content::PAGE_TYPE_INTERSTITIAL) {
     return true;
diff --git a/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.cc b/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.cc
index 3b86a61..4a2f79fb 100644
--- a/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.cc
+++ b/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.cc
@@ -42,6 +42,7 @@
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/gfx/color_palette.h"
 #include "ui/gfx/paint_vector_icon.h"
+#include "ui/native_theme/native_theme.h"
 #include "ui/resources/grit/ui_resources.h"
 
 namespace {
@@ -122,7 +123,19 @@
 }
 
 gfx::Image CreateFavicon(const gfx::VectorIcon& icon) {
-  return gfx::Image(gfx::CreateVectorIcon(icon, 16, gfx::kChromeIconGrey));
+  ui::NativeTheme* native_theme = ui::NativeTheme::GetInstanceForNativeUi();
+  return gfx::Image(
+      gfx::CreateVectorIcon(icon, 16,
+                            native_theme->GetSystemColor(
+                                ui::NativeTheme::kColorId_DefaultIconColor)));
+}
+
+// TODO(https://crbug.com/935593): Use a centralized method when it's available.
+gfx::Image GetDefaultFavicon() {
+  ui::NativeTheme* native_theme = ui::NativeTheme::GetInstanceForNativeUi();
+  return ui::ResourceBundle::GetSharedInstance().GetNativeImageNamed(
+      native_theme->SystemDarkModeEnabled() ? IDR_DEFAULT_FAVICON_DARK
+                                            : IDR_DEFAULT_FAVICON);
 }
 
 }  // namespace
@@ -167,10 +180,7 @@
       browser_(browser),
       session_sync_service_(
           SessionSyncServiceFactory::GetInstance()->GetForProfile(
-              browser->profile())),
-      default_favicon_(
-          ui::ResourceBundle::GetSharedInstance().GetNativeImageNamed(
-              IDR_DEFAULT_FAVICON)) {
+              browser->profile())) {
   // Invoke asynchronous call to load tabs from local last session, which does
   // nothing if the tabs have already been loaded or they shouldn't be loaded.
   // TabRestoreServiceChanged() will be called after the tabs are loaded.
@@ -580,7 +590,7 @@
 
   // Otherwise, start to fetch the favicon from local history asynchronously.
   // Set default icon first.
-  SetIcon(index_in_menu, default_favicon_);
+  SetIcon(index_in_menu, GetDefaultFavicon());
   // Start request to fetch actual icon if possible.
   favicon::FaviconService* favicon_service =
       FaviconServiceFactory::GetForProfile(browser_->profile(),
diff --git a/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.h b/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.h
index e36446cf..515952c 100644
--- a/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.h
+++ b/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model.h
@@ -30,10 +30,6 @@
 struct FaviconImageResult;
 }
 
-namespace gfx {
-class Image;
-}
-
 namespace sessions {
 struct SessionTab;
 }
@@ -179,8 +175,6 @@
   // menumodel.
   int last_local_model_index_ = kHistorySeparatorIndex;
 
-  gfx::Image default_favicon_;
-
   base::CancelableTaskTracker local_tab_cancelable_task_tracker_;
   base::CancelableTaskTracker other_devices_tab_cancelable_task_tracker_;
 
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc b/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc
index 17e569e..9ac209c 100644
--- a/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc
+++ b/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc
@@ -1752,6 +1752,9 @@
       browser_, page_navigator_, GetWidget(), node, start_index, true);
   bookmark_drop_menu_->set_observer(this);
   bookmark_drop_menu_->RunMenuAt(this);
+
+  for (BookmarkBarViewObserver& observer : observers_)
+    observer.OnDropMenuShown();
 }
 
 void BookmarkBarView::StopShowFolderDropMenuTimer() {
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_bar_view_observer.h b/chrome/browser/ui/views/bookmarks/bookmark_bar_view_observer.h
index fa3526c..9e8618b 100644
--- a/chrome/browser/ui/views/bookmarks/bookmark_bar_view_observer.h
+++ b/chrome/browser/ui/views/bookmarks/bookmark_bar_view_observer.h
@@ -7,7 +7,13 @@
 
 class BookmarkBarViewObserver {
  public:
-  virtual void OnBookmarkBarVisibilityChanged() = 0;
+  // Called when the BookmarkBarView's visibility is directly toggled.  Not
+  // called when the visibility changes due to e.g. a parent being made visible.
+  virtual void OnBookmarkBarVisibilityChanged() {}
+
+  // Called when the user drags over a folder, causing a menu to appear (into
+  // which bookmarks can be dropped).
+  virtual void OnDropMenuShown() {}
 
  protected:
   ~BookmarkBarViewObserver() {}
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_bar_view_test.cc b/chrome/browser/ui/views/bookmarks/bookmark_bar_view_test.cc
index 45d2721..530fb8c 100644
--- a/chrome/browser/ui/views/bookmarks/bookmark_bar_view_test.cc
+++ b/chrome/browser/ui/views/bookmarks/bookmark_bar_view_test.cc
@@ -527,14 +527,7 @@
   }
 };
 
-#if defined(OS_WIN)
-// Disable this test on Win10: http://crbug.com/828063
-#define MAYBE_HideOnDesktopClick DISABLED_HideOnDesktopClick
-#else
-#define MAYBE_HideOnDesktopClick HideOnDesktopClick
-#endif
-
-VIEW_TEST(BookmarkBarViewTest2, MAYBE_HideOnDesktopClick)
+VIEW_TEST(BookmarkBarViewTest2, HideOnDesktopClick)
 
 // Brings up menu. Moves over child to make sure submenu appears, moves over
 // another child and make sure next menu appears.
@@ -1088,14 +1081,7 @@
   views::MenuItemView* first_menu_;
 };
 
-// Fails on official cros bot. crbug.com/431427.
-#if defined(OS_CHROMEOS) && defined(OFFICIAL_BUILD)
-#define MAYBE_ScrollButtonScrolls DISABLED_ScrollButtonScrolls
-#else
-#define MAYBE_ScrollButtonScrolls ScrollButtonScrolls
-#endif
-
-VIEW_TEST(BookmarkBarViewTest9, MAYBE_ScrollButtonScrolls)
+VIEW_TEST(BookmarkBarViewTest9, ScrollButtonScrolls)
 
 // Tests up/down/left/enter key messages.
 class BookmarkBarViewTest10 : public BookmarkBarViewEventTestBase {
@@ -1296,8 +1282,6 @@
 class BookmarkBarViewTest12 : public BookmarkBarViewEventTestBase {
  protected:
   void DoTestOnMessageLoop() override {
-    base::RunLoop().RunUntilIdle();
-
     // Open up the other folder.
     views::LabelButton* button = bb_view_->other_bookmarks_button();
     ui_test_utils::MoveMouseToCenterAndPress(button, ui_controls::LEFT,
@@ -1699,8 +1683,7 @@
   std::unique_ptr<BookmarkContextMenuNotificationObserver> observer_;
 };
 
-// Flaky. See http://crbug.com/820435.
-VIEW_TEST(BookmarkBarViewTest17, DISABLED_ContextMenus3)
+VIEW_TEST(BookmarkBarViewTest17, ContextMenus3)
 
 // Verifies sibling menus works. Clicks on the 'other bookmarks' folder, then
 // moves the mouse over the first item on the bookmark bar and makes sure the
@@ -2230,7 +2213,6 @@
     ui_test_utils::MoveMouseToCenterAndPress(
         button, ui_controls::LEFT, ui_controls::DOWN | ui_controls::UP,
         CreateEventTask(this, &BookmarkBarViewTest25::Step2));
-    base::RunLoop().RunUntilIdle();
   }
 
  private:
@@ -2273,7 +2255,6 @@
     ui_test_utils::MoveMouseToCenterAndPress(
         button, ui_controls::LEFT, ui_controls::DOWN | ui_controls::UP,
         CreateEventTask(this, &BookmarkBarViewTest26::Step2));
-    base::RunLoop().RunUntilIdle();
   }
 
  private:
diff --git a/chrome/browser/ui/views/crostini/crostini_installer_view.cc b/chrome/browser/ui/views/crostini/crostini_installer_view.cc
index 3385414..15e7fc5 100644
--- a/chrome/browser/ui/views/crostini/crostini_installer_view.cc
+++ b/chrome/browser/ui/views/crostini/crostini_installer_view.cc
@@ -110,6 +110,9 @@
   // set it to the desired value.
   g_crostini_installer_view->SetBigMessageLabel();
   g_crostini_installer_view->GetWidget()->Show();
+
+  crostini::CrostiniManager::GetForProfile(profile)->SetInstallerViewStatus(
+      true);
 }
 
 int CrostiniInstallerView::GetDialogButtons() const {
@@ -470,6 +473,8 @@
 }
 
 CrostiniInstallerView::~CrostiniInstallerView() {
+  crostini::CrostiniManager::GetForProfile(profile_)->SetInstallerViewStatus(
+      false);
   g_crostini_installer_view = nullptr;
   if (quit_closure_for_testing_) {
     std::move(quit_closure_for_testing_).Run();
diff --git a/chrome/browser/ui/views/crostini/crostini_installer_view_browsertest.cc b/chrome/browser/ui/views/crostini/crostini_installer_view_browsertest.cc
index 5ded51a94..ff43690 100644
--- a/chrome/browser/ui/views/crostini/crostini_installer_view_browsertest.cc
+++ b/chrome/browser/ui/views/crostini/crostini_installer_view_browsertest.cc
@@ -162,6 +162,9 @@
   EXPECT_TRUE(HasAcceptButton());
   EXPECT_TRUE(HasCancelButton());
 
+  EXPECT_TRUE(crostini::CrostiniManager::GetForProfile(browser()->profile())
+                  ->GetInstallerViewStatus());
+
   ActiveView()->GetDialogClientView()->AcceptWindow();
   EXPECT_FALSE(ActiveView()->GetWidget()->IsClosed());
   EXPECT_FALSE(HasAcceptButton());
@@ -174,6 +177,9 @@
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(nullptr, ActiveView());
 
+  EXPECT_FALSE(crostini::CrostiniManager::GetForProfile(browser()->profile())
+                   ->GetInstallerViewStatus());
+
   histogram_tester.ExpectUniqueSample(
       "Crostini.SetupResult",
       static_cast<base::HistogramBase::Sample>(
@@ -211,6 +217,9 @@
   EXPECT_TRUE(HasAcceptButton());
   EXPECT_TRUE(HasCancelButton());
 
+  EXPECT_TRUE(crostini::CrostiniManager::GetForProfile(browser()->profile())
+                  ->GetInstallerViewStatus());
+
   ActiveView()->GetDialogClientView()->AcceptWindow();
   EXPECT_FALSE(ActiveView()->GetWidget()->IsClosed());
   EXPECT_TRUE(HasAcceptButton());
@@ -223,6 +232,9 @@
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(nullptr, ActiveView());
 
+  EXPECT_FALSE(crostini::CrostiniManager::GetForProfile(browser()->profile())
+                   ->GetInstallerViewStatus());
+
   histogram_tester.ExpectUniqueSample(
       "Crostini.SetupResult",
       static_cast<base::HistogramBase::Sample>(
@@ -235,10 +247,14 @@
 
   ShowUi("default");
   EXPECT_NE(nullptr, ActiveView());
+  EXPECT_TRUE(crostini::CrostiniManager::GetForProfile(browser()->profile())
+                  ->GetInstallerViewStatus());
   ActiveView()->GetDialogClientView()->CancelWindow();
   EXPECT_TRUE(ActiveView()->GetWidget()->IsClosed());
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(nullptr, ActiveView());
+  EXPECT_FALSE(crostini::CrostiniManager::GetForProfile(browser()->profile())
+                   ->GetInstallerViewStatus());
 
   histogram_tester.ExpectUniqueSample(
       "Crostini.SetupResult",
@@ -251,6 +267,8 @@
   base::HistogramTester histogram_tester;
   ShowUi("default");
   EXPECT_NE(nullptr, ActiveView());
+  EXPECT_TRUE(crostini::CrostiniManager::GetForProfile(browser()->profile())
+                  ->GetInstallerViewStatus());
   vm_tools::concierge::StartVmResponse response;
   response.set_status(vm_tools::concierge::VM_STATUS_FAILURE);
   waiting_fake_concierge_client_->set_start_vm_response(std::move(response));
@@ -261,6 +279,8 @@
   ActiveView()->GetDialogClientView()->CancelWindow();
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(nullptr, ActiveView());
+  EXPECT_FALSE(crostini::CrostiniManager::GetForProfile(browser()->profile())
+                   ->GetInstallerViewStatus());
 
   histogram_tester.ExpectUniqueSample(
       "Crostini.SetupResult",
diff --git a/chrome/browser/ui/views/intent_picker_bubble_view_unittest.cc b/chrome/browser/ui/views/intent_picker_bubble_view_unittest.cc
index 1053756..ee5beb2 100644
--- a/chrome/browser/ui/views/intent_picker_bubble_view_unittest.cc
+++ b/chrome/browser/ui/views/intent_picker_bubble_view_unittest.cc
@@ -11,7 +11,7 @@
 #include "base/callback.h"
 #include "base/macros.h"
 #include "chrome/browser/chromeos/apps/intent_helper/apps_navigation_types.h"
-#include "chrome/browser/chromeos/arc/intent_helper/arc_navigation_throttle.h"
+#include "chrome/browser/chromeos/arc/intent_helper/arc_intent_picker_app_fetcher.h"
 #include "chrome/test/base/browser_with_test_window_test.h"
 #include "components/arc/intent_helper/arc_intent_helper_bridge.h"
 #include "content/public/browser/web_contents.h"
diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.cc b/chrome/browser/ui/views/location_bar/location_bar_view.cc
index 4b593dc4..f71d7462 100644
--- a/chrome/browser/ui/views/location_bar/location_bar_view.cc
+++ b/chrome/browser/ui/views/location_bar/location_bar_view.cc
@@ -56,6 +56,7 @@
 #include "chrome/browser/ui/views/page_action/page_action_icon_container_view.h"
 #include "chrome/browser/ui/views/page_info/page_info_bubble_view.h"
 #include "chrome/browser/ui/views/passwords/manage_passwords_icon_views.h"
+#include "chrome/common/chrome_features.h"
 #include "chrome/grit/chromium_strings.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/bookmarks/common/bookmark_pref_names.h"
@@ -224,6 +225,8 @@
     params.types_enabled.push_back(PageActionIconType::kFind);
     params.types_enabled.push_back(PageActionIconType::kTranslate);
     params.types_enabled.push_back(PageActionIconType::kZoom);
+    if (base::FeatureList::IsEnabled(features::kDesktopPWAsOmniboxInstall))
+      params.types_enabled.push_back(PageActionIconType::kPwaInstall);
   }
   params.icon_size = GetLayoutConstant(LOCATION_BAR_ICON_SIZE);
   params.icon_color = icon_color;
@@ -239,19 +242,16 @@
     save_credit_card_icon_view_ = new autofill::SaveCardIconView(
         command_updater(), browser_, this, font_list);
     page_action_icons_.push_back(save_credit_card_icon_view_);
-  }
-  if (browser_) {
+
     local_card_migration_icon_view_ = new autofill::LocalCardMigrationIconView(
         command_updater(), browser_, this, font_list);
     page_action_icons_.push_back(local_card_migration_icon_view_);
-  }
 
 #if defined(OS_CHROMEOS)
-  if (browser_)
     page_action_icons_.push_back(intent_picker_view_ =
                                      new IntentPickerView(browser_, this));
 #endif
-  if (browser_) {
+
     page_action_icons_.push_back(
         star_view_ = new StarView(command_updater(), browser_, this));
   }
diff --git a/chrome/browser/ui/views/menu_view_drag_and_drop_test.cc b/chrome/browser/ui/views/menu_view_drag_and_drop_test.cc
index 6e0d3c5..1f0152a 100644
--- a/chrome/browser/ui/views/menu_view_drag_and_drop_test.cc
+++ b/chrome/browser/ui/views/menu_view_drag_and_drop_test.cc
@@ -487,10 +487,4 @@
 
 // Test that if a menu is opened for a drop handled entirely by menu code, the
 // menu will try to close if it does not receive any drag updates.
-// Disabled for being flaky. Tracked in http://crbug.com/863296.
-#if defined(OS_MACOSX)
-#define MAYBE_MenuViewCancelsForOwnDrag DISABLED_MenuViewCancelsForOwnDrag
-#else
-#define MAYBE_MenuViewCancelsForOwnDrag MenuViewCancelsForOwnDrag
-#endif
-VIEW_TEST(MenuViewDragAndDropForDropCancel, MAYBE_MenuViewCancelsForOwnDrag)
+VIEW_TEST(MenuViewDragAndDropForDropCancel, MenuViewCancelsForOwnDrag)
diff --git a/chrome/browser/ui/views/page_action/page_action_icon_container_view.cc b/chrome/browser/ui/views/page_action/page_action_icon_container_view.cc
index 41513dc2..fdc0b9c6 100644
--- a/chrome/browser/ui/views/page_action/page_action_icon_container_view.cc
+++ b/chrome/browser/ui/views/page_action/page_action_icon_container_view.cc
@@ -7,6 +7,7 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/views/location_bar/find_bar_icon.h"
 #include "chrome/browser/ui/views/location_bar/zoom_bubble_view.h"
+#include "chrome/browser/ui/views/page_action/pwa_install_view.h"
 #include "chrome/browser/ui/views/page_action/zoom_view.h"
 #include "chrome/browser/ui/views/passwords/manage_passwords_icon_views.h"
 #include "chrome/browser/ui/views/translate/translate_icon_view.h"
@@ -41,6 +42,12 @@
             params.command_updater, params.page_action_icon_delegate);
         page_action_icons_.push_back(manage_passwords_icon_);
         break;
+      case PageActionIconType::kPwaInstall:
+        DCHECK(params.command_updater);
+        pwa_install_view_ = new PwaInstallView(
+            params.command_updater, params.page_action_icon_delegate);
+        page_action_icons_.push_back(pwa_install_view_);
+        break;
       case PageActionIconType::kTranslate:
         DCHECK(params.command_updater);
         translate_icon_ = new TranslateIconView(
@@ -81,6 +88,8 @@
       return find_bar_icon_;
     case PageActionIconType::kManagePasswords:
       return manage_passwords_icon_;
+    case PageActionIconType::kPwaInstall:
+      return pwa_install_view_;
     case PageActionIconType::kTranslate:
       return translate_icon_;
     case PageActionIconType::kZoom:
diff --git a/chrome/browser/ui/views/page_action/page_action_icon_container_view.h b/chrome/browser/ui/views/page_action/page_action_icon_container_view.h
index 05cafc1..afcd0fd 100644
--- a/chrome/browser/ui/views/page_action/page_action_icon_container_view.h
+++ b/chrome/browser/ui/views/page_action/page_action_icon_container_view.h
@@ -19,6 +19,7 @@
 class CommandUpdater;
 class FindBarIcon;
 class ManagePasswordsIconViews;
+class PwaInstallView;
 class TranslateIconView;
 class ZoomView;
 
@@ -76,6 +77,7 @@
   ZoomView* zoom_view_ = nullptr;
   FindBarIcon* find_bar_icon_ = nullptr;
   ManagePasswordsIconViews* manage_passwords_icon_ = nullptr;
+  PwaInstallView* pwa_install_view_ = nullptr;
   TranslateIconView* translate_icon_ = nullptr;
   std::vector<PageActionIconView*> page_action_icons_;
 
diff --git a/chrome/browser/ui/views/page_action/pwa_install_view.cc b/chrome/browser/ui/views/page_action/pwa_install_view.cc
new file mode 100644
index 0000000..5b3a5306
--- /dev/null
+++ b/chrome/browser/ui/views/page_action/pwa_install_view.cc
@@ -0,0 +1,51 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/views/page_action/pwa_install_view.h"
+
+#include "chrome/app/chrome_command_ids.h"
+#include "chrome/browser/banners/app_banner_manager.h"
+#include "chrome/browser/web_applications/components/web_app_tab_helper_base.h"
+#include "components/omnibox/browser/vector_icons.h"
+
+PwaInstallView::PwaInstallView(CommandUpdater* command_updater,
+                               PageActionIconView::Delegate* delegate)
+    : PageActionIconView(command_updater, IDC_INSTALL_PWA, delegate) {
+  SetVisible(false);
+}
+
+PwaInstallView::~PwaInstallView() {}
+
+bool PwaInstallView::Update() {
+  content::WebContents* web_contents = GetWebContents();
+  if (!web_contents)
+    return false;
+
+  bool is_installable =
+      banners::AppBannerManager::IsWebContentsInstallable(web_contents);
+  bool is_installed =
+      web_app::WebAppTabHelperBase::FromWebContents(web_contents)
+          ->HasAssociatedApp();
+  bool show_install_button = is_installable && !is_installed;
+
+  bool was_visible = visible();
+  SetVisible(show_install_button);
+  return visible() != was_visible;
+}
+
+void PwaInstallView::OnExecuting(PageActionIconView::ExecuteSource source) {}
+
+views::BubbleDialogDelegateView* PwaInstallView::GetBubble() const {
+  // TODO(https://907351): Implement.
+  return nullptr;
+}
+
+const gfx::VectorIcon& PwaInstallView::GetVectorIcon() const {
+  return omnibox::kPlusIcon;
+}
+
+base::string16 PwaInstallView::GetTextForTooltipAndAccessibleName() const {
+  // TODO(https://907351): Implement.
+  return base::string16();
+}
diff --git a/chrome/browser/ui/views/page_action/pwa_install_view.h b/chrome/browser/ui/views/page_action/pwa_install_view.h
new file mode 100644
index 0000000..48272f7
--- /dev/null
+++ b/chrome/browser/ui/views/page_action/pwa_install_view.h
@@ -0,0 +1,31 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_VIEWS_PAGE_ACTION_PWA_INSTALL_VIEW_H_
+#define CHROME_BROWSER_UI_VIEWS_PAGE_ACTION_PWA_INSTALL_VIEW_H_
+
+#include "base/macros.h"
+#include "chrome/browser/ui/views/page_action/page_action_icon_view.h"
+
+// A plus icon to surface whether a site has passed PWA (progressive web app)
+// installability checks and can be installed.
+class PwaInstallView : public PageActionIconView {
+ public:
+  explicit PwaInstallView(CommandUpdater* command_updater,
+                          PageActionIconView::Delegate* delegate);
+  ~PwaInstallView() override;
+
+ protected:
+  // PageActionIconView:
+  bool Update() override;
+  void OnExecuting(PageActionIconView::ExecuteSource source) override;
+  views::BubbleDialogDelegateView* GetBubble() const override;
+  const gfx::VectorIcon& GetVectorIcon() const override;
+  base::string16 GetTextForTooltipAndAccessibleName() const override;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(PwaInstallView);
+};
+
+#endif  // CHROME_BROWSER_UI_VIEWS_PAGE_ACTION_PWA_INSTALL_VIEW_H_
diff --git a/chrome/browser/ui/views/page_action/pwa_install_view_browsertest.cc b/chrome/browser/ui/views/page_action/pwa_install_view_browsertest.cc
new file mode 100644
index 0000000..c947e48
--- /dev/null
+++ b/chrome/browser/ui/views/page_action/pwa_install_view_browsertest.cc
@@ -0,0 +1,114 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/views/page_action/pwa_install_view.h"
+
+#include "base/files/file_path.h"
+#include "base/test/scoped_feature_list.h"
+#include "chrome/browser/banners/test_app_banner_manager_desktop.h"
+#include "chrome/browser/ui/browser_commands.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
+#include "chrome/browser/ui/views/frame/toolbar_button_provider.h"
+#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
+#include "chrome/browser/ui/views/location_bar/star_view.h"
+#include "chrome/browser/ui/views/page_action/page_action_icon_container_view.h"
+#include "chrome/common/chrome_features.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "chrome/test/base/ui_test_utils.h"
+
+namespace {
+
+const base::FilePath::CharType kDocRoot[] =
+    FILE_PATH_LITERAL("chrome/test/data");
+
+}  // namespace
+
+class PwaInstallViewBrowserTest : public InProcessBrowserTest {
+ public:
+  PwaInstallViewBrowserTest()
+      : https_server_(net::EmbeddedTestServer::TYPE_HTTPS) {}
+  ~PwaInstallViewBrowserTest() override {}
+
+  void SetUp() override {
+    DCHECK(base::FeatureList::IsEnabled(features::kDesktopPWAWindowing));
+    scoped_feature_list_.InitAndEnableFeature(
+        features::kDesktopPWAsOmniboxInstall);
+
+    https_server_.AddDefaultHandlers(base::FilePath(kDocRoot));
+    ASSERT_TRUE(https_server_.Start());
+
+    InProcessBrowserTest::SetUp();
+  }
+
+  void SetUpCommandLine(base::CommandLine* command_line) override {
+    InProcessBrowserTest::SetUpCommandLine(command_line);
+
+    command_line->AppendSwitchASCII(
+        switches::kUnsafelyTreatInsecureOriginAsSecure,
+        GetInstallableAppURL().GetOrigin().spec());
+  }
+
+  content::WebContents* GetCurrentTab() {
+    return browser()->tab_strip_model()->GetActiveWebContents();
+  }
+
+  content::WebContents* OpenNewTab(const GURL& url,
+                                   bool expected_installability) {
+    chrome::NewTab(browser());
+    content::WebContents* web_contents = GetCurrentTab();
+    auto* app_banner_manager =
+        banners::TestAppBannerManagerDesktop::CreateForWebContents(
+            web_contents);
+    DCHECK(!app_banner_manager->WaitForInstallableCheck());
+
+    ui_test_utils::NavigateToURL(browser(), url);
+    DCHECK_EQ(app_banner_manager->WaitForInstallableCheck(),
+              expected_installability);
+
+    return web_contents;
+  }
+
+  GURL GetInstallableAppURL() {
+    return https_server_.GetURL("/banners/manifest_test_page.html");
+  }
+
+  GURL GetNonInstallableAppURL() {
+    return https_server_.GetURL("app.com", "/simple.html");
+  }
+
+  PageActionIconView* GetPwaInstallView() {
+    return BrowserView::GetBrowserViewForBrowser(browser())
+        ->toolbar_button_provider()
+        ->GetPageActionIconContainerView()
+        ->GetPageActionIconView(PageActionIconType::kPwaInstall);
+  }
+
+ private:
+  base::test::ScopedFeatureList scoped_feature_list_;
+  net::EmbeddedTestServer https_server_;
+
+  DISALLOW_COPY_AND_ASSIGN(PwaInstallViewBrowserTest);
+};
+
+// Tests that the plus icon updates its visibiliy when switching between
+// installable/non-installable tabs.
+IN_PROC_BROWSER_TEST_F(PwaInstallViewBrowserTest,
+                       IconVisibilityAfterTabSwitching) {
+  PageActionIconView* pwa_install_view = GetPwaInstallView();
+  EXPECT_FALSE(pwa_install_view->visible());
+
+  content::WebContents* installable_web_contents =
+      OpenNewTab(GetInstallableAppURL(), true);
+  content::WebContents* non_installable_web_contents =
+      OpenNewTab(GetNonInstallableAppURL(), false);
+
+  chrome::SelectPreviousTab(browser());
+  ASSERT_EQ(installable_web_contents, GetCurrentTab());
+  EXPECT_TRUE(pwa_install_view->visible());
+
+  chrome::SelectNextTab(browser());
+  ASSERT_EQ(non_installable_web_contents, GetCurrentTab());
+  EXPECT_FALSE(pwa_install_view->visible());
+}
diff --git a/chrome/browser/ui/views/toolbar/toolbar_view.h b/chrome/browser/ui/views/toolbar/toolbar_view.h
index 41801d1..70cf85e 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_view.h
+++ b/chrome/browser/ui/views/toolbar/toolbar_view.h
@@ -30,7 +30,7 @@
 #include "ui/views/view.h"
 
 #if defined(OS_CHROMEOS)
-#include "chrome/browser/chromeos/arc/intent_helper/arc_navigation_throttle.h"
+#include "chrome/browser/chromeos/arc/intent_helper/arc_intent_picker_app_fetcher.h"
 #include "chrome/browser/ui/views/intent_picker_bubble_view.h"
 #include "components/arc/common/intent_helper.mojom.h"  // nogncheck https://crbug.com/784179
 #include "components/arc/intent_helper/arc_intent_helper_bridge.h"
diff --git a/chrome/browser/ui/views/webshare/webshare_target_picker_view_unittest.cc b/chrome/browser/ui/views/webshare/webshare_target_picker_view_unittest.cc
index 438d7622..34f1a43 100644
--- a/chrome/browser/ui/views/webshare/webshare_target_picker_view_unittest.cc
+++ b/chrome/browser/ui/views/webshare/webshare_target_picker_view_unittest.cc
@@ -28,6 +28,8 @@
 constexpr char kAppName1[] = "App One";
 constexpr char kAppName2[] = "App Two";
 constexpr char kAction[] = "share";
+constexpr char kMethod[] = "GET";
+constexpr char kEnctype[] = "application/x-www-form-urlencoded";
 constexpr char kParamText[] = "text";
 constexpr char kParamTitle[] = "title";
 constexpr char kParamUrl[] = "url";
@@ -125,13 +127,19 @@
 
 // Table with 2 targets. Choose second target and share.
 TEST_F(WebShareTargetPickerViewTest, ChooseItem) {
-  std::vector<WebShareTarget> targets;
-  targets.emplace_back(GURL(kUrl1), kAppName1, GURL(kAction), kParamText,
-                       kParamTitle, kParamUrl);
-  targets.emplace_back(GURL(kUrl2), kAppName2, GURL(kAction), kParamText,
-                       kParamTitle, kParamUrl);
+  {
+    std::vector<WebShareTarget> targets;
+    std::vector<WebShareTargetFiles> files1;
+    std::vector<WebShareTargetFiles> files2;
+    targets.emplace_back(GURL(kUrl1), kAppName1, GURL(kAction), kMethod,
+                         kEnctype, kParamText, kParamTitle, kParamUrl,
+                         std::move(files1));
+    targets.emplace_back(GURL(kUrl2), kAppName2, GURL(kAction), kMethod,
+                         kEnctype, kParamText, kParamTitle, kParamUrl,
+                         std::move(files2));
 
-  CreateView(std::move(targets));
+    CreateView(std::move(targets));
+  }
   EXPECT_EQ(2, table()->RowCount());
   EXPECT_EQ(base::ASCIIToUTF16("App One (https://appone.com/)"),
             table()->model()->GetText(0, 0));
@@ -155,18 +163,22 @@
 
   run_loop.Run();
 
-  EXPECT_EQ(WebShareTarget(GURL(kUrl2), kAppName2, GURL(kAction), kParamText,
-                           kParamTitle, kParamUrl),
+  EXPECT_EQ(WebShareTarget(GURL(kUrl2), kAppName2, GURL(kAction), kMethod,
+                           kEnctype, kParamText, kParamTitle, kParamUrl, {}),
             *result());
 }
 
 // Table with 1 target. Select using double-click.
 TEST_F(WebShareTargetPickerViewTest, ChooseItemWithDoubleClick) {
-  std::vector<WebShareTarget> targets;
-  targets.emplace_back(GURL(kUrl1), kAppName1, GURL(kAction), kParamText,
-                       kParamTitle, kParamUrl);
+  {
+    std::vector<WebShareTarget> targets;
+    std::vector<WebShareTargetFiles> files;
+    targets.emplace_back(GURL(kUrl1), kAppName1, GURL(kAction), kMethod,
+                         kEnctype, kParamText, kParamTitle, kParamUrl,
+                         std::move(files));
 
-  CreateView(std::move(targets));
+    CreateView(std::move(targets));
+  }
   EXPECT_EQ(1, table()->RowCount());
   EXPECT_EQ(base::ASCIIToUTF16("App One (https://appone.com/)"),
             table()->model()->GetText(0, 0));
@@ -180,18 +192,22 @@
 
   run_loop.Run();
 
-  EXPECT_EQ(WebShareTarget(GURL(kUrl1), kAppName1, GURL(kAction), kParamText,
-                           kParamTitle, kParamUrl),
+  EXPECT_EQ(WebShareTarget(GURL(kUrl1), kAppName1, GURL(kAction), kMethod,
+                           kEnctype, kParamText, kParamTitle, kParamUrl, {}),
             *result());
 }
 
 // Table with 1 target. Select, share and GetText.
 TEST_F(WebShareTargetPickerViewTest, GetTextAfterAccept) {
-  std::vector<WebShareTarget> targets;
-  targets.emplace_back(GURL(kUrl1), kAppName1, GURL(kAction), kParamText,
-                       kParamTitle, kParamUrl);
+  {
+    std::vector<WebShareTarget> targets;
+    std::vector<WebShareTargetFiles> files;
+    targets.emplace_back(GURL(kUrl1), kAppName1, GURL(kAction), kMethod,
+                         kEnctype, kParamText, kParamTitle, kParamUrl,
+                         std::move(files));
 
-  CreateView(std::move(targets));
+    CreateView(std::move(targets));
+  }
   EXPECT_EQ(1, table()->RowCount());
   EXPECT_EQ(base::ASCIIToUTF16("App One (https://appone.com/)"),
             table()->model()->GetText(0, 0));
@@ -208,7 +224,7 @@
   EXPECT_EQ(base::ASCIIToUTF16("App One (https://appone.com/)"),
             table()->model()->GetText(0, 0));
 
-  EXPECT_EQ(WebShareTarget(GURL(kUrl1), kAppName1, GURL(kAction), kParamText,
-                           kParamTitle, kParamUrl),
+  EXPECT_EQ(WebShareTarget(GURL(kUrl1), kAppName1, GURL(kAction), kMethod,
+                           kEnctype, kParamText, kParamTitle, kParamUrl, {}),
             *result());
 }
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 988ecf79..4a9b237 100644
--- a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
+++ b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
@@ -125,11 +125,12 @@
 #include "chrome/browser/ui/webui/webapks_ui.h"
 #include "components/feed/feed_feature_list.h"
 #else
-#include "chrome/browser/ui/webui/devtools_ui.h"
-#include "chrome/browser/ui/webui/inspect_ui.h"
 #include "chrome/browser/ui/webui/bookmarks/bookmarks_ui.h"
+#include "chrome/browser/ui/webui/devtools_ui.h"
 #include "chrome/browser/ui/webui/downloads/downloads_ui.h"
 #include "chrome/browser/ui/webui/history_ui.h"
+#include "chrome/browser/ui/webui/inspect_ui.h"
+#include "chrome/browser/ui/webui/management_ui.h"
 #include "chrome/browser/ui/webui/ntp/new_tab_ui.h"
 #include "chrome/browser/ui/webui/page_not_available_for_guest/page_not_available_for_guest_ui.h"
 #include "chrome/browser/ui/webui/sync_file_system_internals/sync_file_system_internals_ui.h"
@@ -883,6 +884,9 @@
   if (page_url.host_piece() == chrome::kChromeUISettingsHost)
     return settings_utils::GetFaviconResourceBytes(scale_factor);
 
+  if (page_url.host_piece() == chrome::kChromeUIManagementHost)
+    return ManagementUI::GetFaviconResourceBytes(scale_factor);
+
 #if BUILDFLAG(ENABLE_EXTENSIONS)
   if (page_url.host_piece() == chrome::kChromeUIExtensionsHost ||
       page_url.host_piece() == chrome::kChromeUIExtensionsFrameHost) {
diff --git a/chrome/browser/ui/webui/chromeos/login/arc_terms_of_service_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/arc_terms_of_service_screen_handler.h
index 6d501e8..b6435e5 100644
--- a/chrome/browser/ui/webui/chromeos/login/arc_terms_of_service_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/arc_terms_of_service_screen_handler.h
@@ -54,7 +54,7 @@
   // OobeUI::Observer:
   void OnCurrentScreenChanged(OobeScreen current_screen,
                               OobeScreen new_screen) override;
-  void OnScreenInitialized(OobeScreen screen) override{};
+  void OnScreenInitialized(OobeScreen screen) override {}
 
   // system::TimezoneSettings::Observer:
   void TimezoneChanged(const icu::TimeZone& timezone) override;
diff --git a/chrome/browser/ui/webui/chromeos/login/assistant_optin_flow_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/assistant_optin_flow_screen_handler.cc
index 784140eb..930827b 100644
--- a/chrome/browser/ui/webui/chromeos/login/assistant_optin_flow_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/assistant_optin_flow_screen_handler.cc
@@ -59,6 +59,7 @@
 void AssistantOptInFlowScreenHandler::DeclareLocalizedValues(
     ::login::LocalizedValuesBuilder* builder) {
   builder->Add("locale", g_browser_process->GetApplicationLocale());
+  builder->Add("assistantLogo", IDS_VOICE_INTERACTION_LOGO);
   builder->Add("assistantOptinLoading",
                IDS_VOICE_INTERACTION_VALUE_PROP_LOADING);
   builder->Add("assistantOptinLoadErrorTitle",
diff --git a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h
index 186ac57..ef9db6ff 100644
--- a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h
@@ -225,7 +225,7 @@
   // OobeUI::Observer implementation:
   void OnCurrentScreenChanged(OobeScreen current_screen,
                               OobeScreen new_screen) override;
-  void OnScreenInitialized(OobeScreen screen) override{};
+  void OnScreenInitialized(OobeScreen screen) override {}
 
   // ash::mojom::WallpaperObserver implementation:
   void OnWallpaperChanged(uint32_t image_id) override;
diff --git a/chrome/browser/ui/webui/chromeos/network_ui.h b/chrome/browser/ui/webui/chromeos/network_ui.h
index b75aac8..49f9d7f 100644
--- a/chrome/browser/ui/webui/chromeos/network_ui.h
+++ b/chrome/browser/ui/webui/chromeos/network_ui.h
@@ -10,7 +10,7 @@
 
 namespace base {
 class DictionaryValue;
-};
+}
 
 namespace chromeos {
 
diff --git a/chrome/browser/ui/webui/management_ui.cc b/chrome/browser/ui/webui/management_ui.cc
index e5a381b..aac14c3 100644
--- a/chrome/browser/ui/webui/management_ui.cc
+++ b/chrome/browser/ui/webui/management_ui.cc
@@ -11,9 +11,11 @@
 #include "chrome/browser/ui/webui/management_ui_handler.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/grit/browser_resources.h"
+#include "chrome/grit/theme_resources.h"
 #include "components/strings/grit/components_strings.h"
 #include "content/public/browser/web_ui.h"
 #include "extensions/buildflags/buildflags.h"
+#include "ui/base/resource/resource_bundle.h"
 
 namespace {
 
@@ -99,6 +101,13 @@
 
 }  // namespace
 
+// static
+base::RefCountedMemory* ManagementUI::GetFaviconResourceBytes(
+    ui::ScaleFactor scale_factor) {
+  return ui::ResourceBundle::GetSharedInstance().LoadDataResourceBytesForScale(
+      IDR_MANAGEMENT_FAVICON, scale_factor);
+}
+
 ManagementUI::ManagementUI(content::WebUI* web_ui) : WebUIController(web_ui) {
   web_ui->AddMessageHandler(std::make_unique<ManagementUIHandler>());
   content::WebUIDataSource* source = CreateManagementUIHtmlSource();
diff --git a/chrome/browser/ui/webui/management_ui.h b/chrome/browser/ui/webui/management_ui.h
index 4d30b78e..f3be72a2 100644
--- a/chrome/browser/ui/webui/management_ui.h
+++ b/chrome/browser/ui/webui/management_ui.h
@@ -7,6 +7,11 @@
 
 #include "base/macros.h"
 #include "content/public/browser/web_ui_controller.h"
+#include "ui/base/resource/scale_factor.h"
+
+namespace base {
+class RefCountedMemory;
+}
 
 namespace content {
 class WebUI;
@@ -18,6 +23,9 @@
   explicit ManagementUI(content::WebUI* web_ui);
   ~ManagementUI() override;
 
+  static base::RefCountedMemory* GetFaviconResourceBytes(
+      ui::ScaleFactor scale_factor);
+
  private:
   DISALLOW_COPY_AND_ASSIGN(ManagementUI);
 };
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 1748ee0..3621f103 100644
--- a/chrome/browser/ui/webui/net_internals/net_internals_ui.cc
+++ b/chrome/browser/ui/webui/net_internals/net_internals_ui.cc
@@ -434,7 +434,8 @@
   base::FilePath policies_path = path.Append("policies.json");
   std::string json_policies = policy::GetAllPolicyValuesAsJSON(
       web_ui()->GetWebContents()->GetBrowserContext(),
-      true /* with_user_policies */, false /* with_device_data */);
+      true /* with_user_policies */, false /* with_device_data */,
+      true /* is_pretty_print */);
   base::PostTaskWithTraitsAndReply(
       FROM_HERE,
       {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
diff --git a/chrome/browser/ui/webui/policy_ui_handler.cc b/chrome/browser/ui/webui/policy_ui_handler.cc
index 8a6eb89..1a008bb9 100644
--- a/chrome/browser/ui/webui/policy_ui_handler.cc
+++ b/chrome/browser/ui/webui/policy_ui_handler.cc
@@ -845,7 +845,7 @@
   base::Value all_policies = policy::GetAllPolicyValuesAsDictionary(
       web_ui()->GetWebContents()->GetBrowserContext(),
       true /* with_user_policies */, true /* convert_values */,
-      false /* with_device_data */);
+      false /* with_device_data */, true /* is_pretty_print */);
   web_ui()->CallJavascriptFunctionUnsafe("policy.Page.setPolicyValues",
                                          all_policies);
 }
@@ -922,7 +922,8 @@
     const base::FilePath& path) const {
   std::string json_policies = policy::GetAllPolicyValuesAsJSON(
       web_ui()->GetWebContents()->GetBrowserContext(),
-      true /* with_user_policies */, false /* with_device_data */);
+      true /* with_user_policies */, false /* with_device_data */,
+      true /* is_pretty_print */);
 
   base::PostTaskWithTraits(
       FROM_HERE,
diff --git a/chrome/browser/ui/webui/settings/chromeos/crostini_handler.cc b/chrome/browser/ui/webui/settings/chromeos/crostini_handler.cc
index df251be..f0cf9ce 100644
--- a/chrome/browser/ui/webui/settings/chromeos/crostini_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/crostini_handler.cc
@@ -4,6 +4,8 @@
 
 #include "chrome/browser/ui/webui/settings/chromeos/crostini_handler.h"
 
+#include <string>
+
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "chrome/browser/chromeos/crostini/crostini_export_import.h"
@@ -20,7 +22,13 @@
 CrostiniHandler::CrostiniHandler(Profile* profile)
     : profile_(profile), weak_ptr_factory_(this) {}
 
-CrostiniHandler::~CrostiniHandler() = default;
+CrostiniHandler::~CrostiniHandler() {
+  if (crostini::CrostiniManager::GetForProfile(profile_)
+          ->HasInstallerViewStatusObserver(this)) {
+    crostini::CrostiniManager::GetForProfile(profile_)
+        ->RemoveInstallerViewStatusObserver(this);
+  }
+}
 
 void CrostiniHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
@@ -48,6 +56,13 @@
       "importCrostiniContainer",
       base::BindRepeating(&CrostiniHandler::HandleImportCrostiniContainer,
                           weak_ptr_factory_.GetWeakPtr()));
+  web_ui()->RegisterMessageCallback(
+      "requestCrostiniInstallerStatus",
+      base::BindRepeating(
+          &CrostiniHandler::HandleCrostiniInstallerStatusRequest,
+          weak_ptr_factory_.GetWeakPtr()));
+  crostini::CrostiniManager::GetForProfile(profile_)
+      ->AddInstallerViewStatusObserver(this);
 }
 
 void CrostiniHandler::HandleRequestCrostiniInstallerView(
@@ -112,5 +127,25 @@
       web_ui()->GetWebContents());
 }
 
+void CrostiniHandler::HandleCrostiniInstallerStatusRequest(
+    const base::ListValue* args) {
+  AllowJavascript();
+  CHECK_EQ(1U, args->GetSize());
+  std::string callback_id;
+  CHECK(args->GetString(0, &callback_id));
+  bool status = crostini::CrostiniManager::GetForProfile(profile_)
+                    ->GetInstallerViewStatus();
+  ResolveJavascriptCallback(base::Value(callback_id), base::Value(status));
+}
+
+void CrostiniHandler::OnCrostiniInstallerViewStatusChanged(bool status) {
+  // It's technically possible for this to be called before Javascript is
+  // enabled, in which case we must not call FireWebUIListener
+  if (IsJavascriptAllowed()) {
+    // Other side listens with cr.addWebUIListener
+    FireWebUIListener("crostini-installer-status-changed", base::Value(status));
+  }
+}
+
 }  // namespace settings
 }  // namespace chromeos
diff --git a/chrome/browser/ui/webui/settings/chromeos/crostini_handler.h b/chrome/browser/ui/webui/settings/chromeos/crostini_handler.h
index f0e6c0d1..6358b30e 100644
--- a/chrome/browser/ui/webui/settings/chromeos/crostini_handler.h
+++ b/chrome/browser/ui/webui/settings/chromeos/crostini_handler.h
@@ -6,6 +6,7 @@
 #define CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_CROSTINI_HANDLER_H_
 
 #include "base/memory/weak_ptr.h"
+#include "chrome/browser/chromeos/crostini/crostini_manager.h"
 #include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h"
 
 class Profile;
@@ -17,7 +18,8 @@
 namespace chromeos {
 namespace settings {
 
-class CrostiniHandler : public ::settings::SettingsPageUIHandler {
+class CrostiniHandler : public ::settings::SettingsPageUIHandler,
+                        public crostini::InstallerViewStatusObserver {
  public:
   explicit CrostiniHandler(Profile* profile);
   ~CrostiniHandler() override;
@@ -40,6 +42,10 @@
   void HandleExportCrostiniContainer(const base::ListValue* args);
   // Import the crostini container.
   void HandleImportCrostiniContainer(const base::ListValue* args);
+  // Handle a request for the CrostiniInstallerView status.
+  void HandleCrostiniInstallerStatusRequest(const base::ListValue* args);
+  // Handle the CrostiniInstallerView opening/closing.
+  void OnCrostiniInstallerViewStatusChanged(bool open) override;
 
   Profile* profile_;
   // weak_ptr_factory_ should always be last member.
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 90f2b6e7..282ce5d 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
@@ -446,7 +446,6 @@
       {"crostiniPageTitle", IDS_SETTINGS_CROSTINI_TITLE},
       {"crostiniPageLabel", IDS_SETTINGS_CROSTINI_LABEL},
       {"crostiniEnable", IDS_SETTINGS_TURN_ON},
-      {"crostiniRemove", IDS_SETTINGS_CROSTINI_REMOVE},
       {"crostiniSharedPaths", IDS_SETTINGS_CROSTINI_SHARED_PATHS},
       {"crostiniSharedPathsListHeading",
        IDS_SETTINGS_CROSTINI_SHARED_PATHS_LIST_HEADING},
@@ -471,8 +470,11 @@
   html_source->AddString(
       "crostiniSubtext",
       l10n_util::GetStringFUTF16(
-          IDS_SETTINGS_CROSTINI_SUBTEXT,
+          IDS_SETTINGS_CROSTINI_SUBTEXT, ui::GetChromeOSDeviceName(),
           GetHelpUrlWithBoard(chrome::kLinuxAppsLearnMoreURL)));
+  html_source->AddString("crostiniRemove", l10n_util::GetStringFUTF16(
+                                               IDS_SETTINGS_CROSTINI_REMOVE,
+                                               ui::GetChromeOSDeviceName()));
   html_source->AddString(
       "crostiniSharedPathsInstructionsLocate",
       l10n_util::GetStringFUTF16(
diff --git a/chrome/browser/web_applications/components/web_app_tab_helper_base.cc b/chrome/browser/web_applications/components/web_app_tab_helper_base.cc
index 32f7cec..23a6f57 100644
--- a/chrome/browser/web_applications/components/web_app_tab_helper_base.cc
+++ b/chrome/browser/web_applications/components/web_app_tab_helper_base.cc
@@ -28,6 +28,10 @@
   SetAppId(FindAppIdInScopeOfUrl(init_url));
 }
 
+bool WebAppTabHelperBase::HasAssociatedApp() const {
+  return !app_id_.empty();
+}
+
 void WebAppTabHelperBase::SetAppId(const AppId& app_id) {
   if (app_id_ == app_id)
     return;
diff --git a/chrome/browser/web_applications/components/web_app_tab_helper_base.h b/chrome/browser/web_applications/components/web_app_tab_helper_base.h
index f94e636..088ae80 100644
--- a/chrome/browser/web_applications/components/web_app_tab_helper_base.h
+++ b/chrome/browser/web_applications/components/web_app_tab_helper_base.h
@@ -35,6 +35,8 @@
 
   const AppId& app_id() const { return app_id_; }
 
+  bool HasAssociatedApp() const;
+
   // Set associated app_id.
   void SetAppId(const AppId& app_id);
 
diff --git a/chrome/browser/webshare/share_service_impl.cc b/chrome/browser/webshare/share_service_impl.cc
index 120c8b9..36858a5 100644
--- a/chrome/browser/webshare/share_service_impl.cc
+++ b/chrome/browser/webshare/share_service_impl.cc
@@ -74,6 +74,7 @@
       pref_service->GetDictionary(prefs::kWebShareVisitedTargets);
 
   std::vector<WebShareTarget> sufficiently_engaged_targets;
+  sufficiently_engaged_targets.reserve(share_targets_dict->size());
   for (const auto& it : *share_targets_dict) {
     GURL manifest_url(it.first);
     // This should not happen, but if the prefs file is corrupted, it might, so
@@ -92,6 +93,10 @@
     share_target_dict->GetString("name", &name);
     std::string action;
     share_target_dict->GetString("action", &action);
+    std::string method;
+    share_target_dict->GetString("method", &method);
+    std::string enctype;
+    share_target_dict->GetString("enctype", &enctype);
     std::string text;
     share_target_dict->GetString("text", &text);
     std::string title;
@@ -99,9 +104,41 @@
     std::string url;
     share_target_dict->GetString("url", &url);
 
+    std::vector<WebShareTargetFiles> files;
+    const base::ListValue* files_list = nullptr;
+    share_target_dict->GetList("files", &files_list);
+    if (files_list) {
+      files.reserve(files_list->GetSize());
+      for (const base::Value& entry : files_list->GetList()) {
+        const base::DictionaryValue* file_dict;
+        entry.GetAsDictionary(&file_dict);
+        // This should not happen, but if the prefs file is corrupted, it might,
+        // so don't (D)CHECK, just continue gracefully.
+        if (!file_dict)
+          continue;
+
+        std::string entry_name;
+        file_dict->GetString("name", &entry_name);
+        if (entry_name.empty())
+          continue;
+
+        std::vector<std::string> accept;
+        const base::ListValue* accept_list = nullptr;
+        file_dict->GetList("accept", &accept_list);
+        if (accept_list) {
+          accept.reserve(accept_list->GetSize());
+          for (const base::Value& accept_string : accept_list->GetList()) {
+            accept.push_back(accept_string.GetString());
+          }
+        }
+        files.emplace_back(std::move(entry_name), std::move(accept));
+      }
+    }
+
     sufficiently_engaged_targets.emplace_back(
         std::move(manifest_url), std::move(name), GURL(std::move(action)),
-        std::move(text), std::move(title), std::move(url));
+        std::move(method), std::move(enctype), std::move(text),
+        std::move(title), std::move(url), std::move(files));
   }
 
   return sufficiently_engaged_targets;
diff --git a/chrome/browser/webshare/share_service_impl_unittest.cc b/chrome/browser/webshare/share_service_impl_unittest.cc
index a575884..bd1415d 100644
--- a/chrome/browser/webshare/share_service_impl_unittest.cc
+++ b/chrome/browser/webshare/share_service_impl_unittest.cc
@@ -37,6 +37,12 @@
 constexpr char kActionLowWithQuery[] =
     "https://www.example-low.com/target/share?a=b&c=d";
 constexpr char kActionMin[] = "https://www.example-min.com/target/share";
+constexpr char kMethodHigh[] = "GET";
+constexpr char kMethodLow[] = "POST";
+constexpr char kMethodMin[] = "POST";
+constexpr char kEnctypeHigh[] = "application/x-www-form-urlencoded";
+constexpr char kEnctypeLow[] = "multipart/form-data";
+constexpr char kEnctypeMin[] = "application/x-www-form-urlencoded";
 constexpr char kManifestUrlHigh[] =
     "https://www.example-high.com/target/manifest.json";
 constexpr char kManifestUrlLow[] =
@@ -63,10 +69,14 @@
   void AddShareTargetToPrefs(const std::string& manifest_url,
                              const std::string& name,
                              const std::string& action,
+                             const std::string& method,
+                             const std::string& enctype,
                              const std::string& text,
                              const std::string& title,
                              const std::string& url) {
     constexpr char kActionKey[] = "action";
+    constexpr char kEnctypeKey[] = "enctype";
+    constexpr char kMethodKey[] = "method";
     constexpr char kNameKey[] = "name";
     constexpr char kTextKey[] = "text";
     constexpr char kTitleKey[] = "title";
@@ -80,6 +90,8 @@
         new base::DictionaryValue);
 
     origin_dict->SetKey(kActionKey, base::Value(action));
+    origin_dict->SetKey(kEnctypeKey, base::Value(enctype));
+    origin_dict->SetKey(kMethodKey, base::Value(method));
     origin_dict->SetKey(kNameKey, base::Value(name));
     origin_dict->SetKey(kTextKey, base::Value(text));
     origin_dict->SetKey(kTitleKey, base::Value(title));
@@ -196,16 +208,17 @@
 // Basic test to check the Share method calls the callback with the expected
 // parameters.
 TEST_F(ShareServiceImplUnittest, ShareCallbackParams) {
-  share_service_helper()->AddShareTargetToPrefs(kManifestUrlLow, kTargetName,
-                                                kActionLow, kParamText,
-                                                kParamTitle, kParamUrl);
-  share_service_helper()->AddShareTargetToPrefs(kManifestUrlHigh, kTargetName,
-                                                kActionHigh, kParamText,
-                                                kParamTitle, kParamUrl);
+  share_service_helper()->AddShareTargetToPrefs(
+      kManifestUrlLow, kTargetName, kActionLow, kMethodLow, kEnctypeLow,
+      kParamText, kParamTitle, kParamUrl);
+  share_service_helper()->AddShareTargetToPrefs(
+      kManifestUrlHigh, kTargetName, kActionHigh, kMethodHigh, kEnctypeHigh,
+      kParamText, kParamTitle, kParamUrl);
   // Expect this invalid URL to be ignored (not crash);
   // https://crbug.com/762388.
   share_service_helper()->AddShareTargetToPrefs(
-      "", kTargetName, kActionHigh, kParamText, kParamTitle, kParamUrl);
+      "", kTargetName, kActionHigh, kMethodHigh, kEnctypeHigh, kParamText,
+      kParamTitle, kParamUrl);
 
   base::OnceCallback<void(blink::mojom::ShareError)> callback =
       base::BindOnce(&DidShare, blink::mojom::ShareError::OK);
@@ -219,12 +232,14 @@
   run_loop.Run();
 
   std::vector<WebShareTarget> expected_targets;
-  expected_targets.emplace_back(GURL(kManifestUrlHigh), kTargetName,
-                                GURL(kActionHigh), kParamText, kParamTitle,
-                                kParamUrl);
-  expected_targets.emplace_back(GURL(kManifestUrlLow), kTargetName,
-                                GURL(kActionLow), kParamText, kParamTitle,
-                                kParamUrl);
+  std::vector<WebShareTargetFiles> files_high;
+  std::vector<WebShareTargetFiles> files_low;
+  expected_targets.emplace_back(
+      GURL(kManifestUrlHigh), kTargetName, GURL(kActionHigh), kMethodHigh,
+      kEnctypeHigh, kParamText, kParamTitle, kParamUrl, std::move(files_high));
+  expected_targets.emplace_back(
+      GURL(kManifestUrlLow), kTargetName, GURL(kActionLow), kMethodLow,
+      kEnctypeLow, kParamText, kParamTitle, kParamUrl, std::move(files_low));
   EXPECT_EQ(expected_targets, share_service_helper()->GetTargetsInPicker());
 
   // Pick example-low.com.
@@ -239,9 +254,9 @@
 
 // Adds URL already containing query parameters.
 TEST_F(ShareServiceImplUnittest, ShareCallbackWithQueryString) {
-  share_service_helper()->AddShareTargetToPrefs(kManifestUrlLow, kTargetName,
-                                                kActionLowWithQuery, kParamText,
-                                                kParamTitle, kParamUrl);
+  share_service_helper()->AddShareTargetToPrefs(
+      kManifestUrlLow, kTargetName, kActionLowWithQuery, kMethodLow,
+      kEnctypeLow, kParamText, kParamTitle, kParamUrl);
   base::OnceCallback<void(blink::mojom::ShareError)> callback =
       base::BindOnce(&DidShare, blink::mojom::ShareError::OK);
 
@@ -254,9 +269,10 @@
   run_loop.Run();
 
   std::vector<WebShareTarget> expected_targets;
-  expected_targets.emplace_back(GURL(kManifestUrlLow), kTargetName,
-                                GURL(kActionLowWithQuery), kParamText,
-                                kParamTitle, kParamUrl);
+  std::vector<WebShareTargetFiles> files;
+  expected_targets.emplace_back(
+      GURL(kManifestUrlLow), kTargetName, GURL(kActionLowWithQuery), kMethodLow,
+      kEnctypeLow, kParamText, kParamTitle, kParamUrl, std::move(files));
   EXPECT_EQ(expected_targets, share_service_helper()->GetTargetsInPicker());
 
   // Pick example-low.com.
@@ -294,12 +310,12 @@
 
 // Tests the result of cancelling the share in the picker UI, that has targets.
 TEST_F(ShareServiceImplUnittest, ShareCancelWithTargets) {
-  share_service_helper()->AddShareTargetToPrefs(kManifestUrlHigh, kTargetName,
-                                                kActionHigh, kParamText,
-                                                kParamTitle, kParamUrl);
-  share_service_helper()->AddShareTargetToPrefs(kManifestUrlLow, kTargetName,
-                                                kActionLow, kParamText,
-                                                kParamTitle, kParamUrl);
+  share_service_helper()->AddShareTargetToPrefs(
+      kManifestUrlHigh, kTargetName, kActionHigh, kMethodHigh, kEnctypeHigh,
+      kParamText, kParamTitle, kParamUrl);
+  share_service_helper()->AddShareTargetToPrefs(
+      kManifestUrlLow, kTargetName, kActionLow, kMethodLow, kEnctypeLow,
+      kParamText, kParamTitle, kParamUrl);
 
   // Expect an error message in response.
   base::OnceCallback<void(blink::mojom::ShareError)> callback =
@@ -314,12 +330,14 @@
   run_loop.Run();
 
   std::vector<WebShareTarget> expected_targets;
-  expected_targets.emplace_back(GURL(kManifestUrlHigh), kTargetName,
-                                GURL(kActionHigh), kParamText, kParamTitle,
-                                kParamUrl);
-  expected_targets.emplace_back(GURL(kManifestUrlLow), kTargetName,
-                                GURL(kActionLow), kParamText, kParamTitle,
-                                kParamUrl);
+  std::vector<WebShareTargetFiles> files_high;
+  std::vector<WebShareTargetFiles> files_low;
+  expected_targets.emplace_back(
+      GURL(kManifestUrlHigh), kTargetName, GURL(kActionHigh), kMethodHigh,
+      kEnctypeHigh, kParamText, kParamTitle, kParamUrl, std::move(files_high));
+  expected_targets.emplace_back(
+      GURL(kManifestUrlLow), kTargetName, GURL(kActionLow), kMethodLow,
+      kEnctypeLow, kParamText, kParamTitle, kParamUrl, std::move(files_low));
   EXPECT_EQ(expected_targets, share_service_helper()->GetTargetsInPicker());
 
   // Cancel the dialog.
@@ -330,12 +348,12 @@
 
 // Test to check that only targets with enough engagement were in picker.
 TEST_F(ShareServiceImplUnittest, ShareWithSomeInsufficientlyEngagedTargets) {
-  share_service_helper()->AddShareTargetToPrefs(kManifestUrlMin, kTargetName,
-                                                kActionMin, kParamText,
-                                                kParamTitle, kParamUrl);
-  share_service_helper()->AddShareTargetToPrefs(kManifestUrlLow, kTargetName,
-                                                kActionLow, kParamText,
-                                                kParamTitle, kParamUrl);
+  share_service_helper()->AddShareTargetToPrefs(
+      kManifestUrlMin, kTargetName, kActionMin, kMethodMin, kEnctypeMin,
+      kParamText, kParamTitle, kParamUrl);
+  share_service_helper()->AddShareTargetToPrefs(
+      kManifestUrlLow, kTargetName, kActionLow, kMethodLow, kEnctypeLow,
+      kParamText, kParamTitle, kParamUrl);
 
   base::OnceCallback<void(blink::mojom::ShareError)> callback =
       base::BindOnce(&DidShare, blink::mojom::ShareError::OK);
@@ -349,9 +367,10 @@
   run_loop.Run();
 
   std::vector<WebShareTarget> expected_targets;
-  expected_targets.emplace_back(GURL(kManifestUrlLow), kTargetName,
-                                GURL(kActionLow), kParamText, kParamTitle,
-                                kParamUrl);
+  std::vector<WebShareTargetFiles> files;
+  expected_targets.emplace_back(
+      GURL(kManifestUrlLow), kTargetName, GURL(kActionLow), kMethodLow,
+      kEnctypeLow, kParamText, kParamTitle, kParamUrl, std::move(files));
   EXPECT_EQ(expected_targets, share_service_helper()->GetTargetsInPicker());
 
   // Pick example-low.com.
@@ -367,9 +386,9 @@
 // Test that deleting the share service while the picker is open does not crash
 // (https://crbug.com/690775).
 TEST_F(ShareServiceImplUnittest, ShareServiceDeletion) {
-  share_service_helper()->AddShareTargetToPrefs(kManifestUrlLow, kTargetName,
-                                                kActionLow, kParamText,
-                                                kParamTitle, kParamUrl);
+  share_service_helper()->AddShareTargetToPrefs(
+      kManifestUrlLow, kTargetName, kActionLow, kMethodLow, kEnctypeLow,
+      kParamText, kParamTitle, kParamUrl);
 
   base::RunLoop run_loop;
   share_service_helper()->set_run_loop(&run_loop);
@@ -386,9 +405,10 @@
   run_loop.Run();
 
   std::vector<WebShareTarget> expected_targets;
-  expected_targets.emplace_back(GURL(kManifestUrlLow), kTargetName,
-                                GURL(kActionLow), kParamText, kParamTitle,
-                                kParamUrl);
+  std::vector<WebShareTargetFiles> files;
+  expected_targets.emplace_back(
+      GURL(kManifestUrlLow), kTargetName, GURL(kActionLow), kMethodLow,
+      kEnctypeLow, kParamText, kParamTitle, kParamUrl, std::move(files));
   EXPECT_EQ(expected_targets, share_service_helper()->GetTargetsInPicker());
 
   chrome::WebShareTargetPickerCallback picker_callback =
diff --git a/chrome/browser/webshare/share_target_pref_helper.cc b/chrome/browser/webshare/share_target_pref_helper.cc
index df7d9b0..9841e167 100644
--- a/chrome/browser/webshare/share_target_pref_helper.cc
+++ b/chrome/browser/webshare/share_target_pref_helper.cc
@@ -32,9 +32,13 @@
 
   constexpr char kNameKey[] = "name";
   constexpr char kActionKey[] = "action";
+  constexpr char kMethodKey[] = "method";
+  constexpr char kEnctypeKey[] = "enctype";
   constexpr char kTitleKey[] = "title";
   constexpr char kTextKey[] = "text";
   constexpr char kUrlKey[] = "url";
+  constexpr char kFilesKey[] = "files";
+  constexpr char kAcceptKey[] = "accept";
 
   std::unique_ptr<base::DictionaryValue> origin_dict(new base::DictionaryValue);
 
@@ -47,6 +51,18 @@
       kActionKey,
       base::Value(manifest.share_target->action.ReplaceComponents(replacements)
                       .spec()));
+  origin_dict->SetKey(
+      kMethodKey,
+      base::Value(manifest.share_target->method ==
+                          blink::Manifest::ShareTarget::Method::kPost
+                      ? "POST"
+                      : "GET"));
+  origin_dict->SetKey(
+      kEnctypeKey,
+      base::Value(manifest.share_target->enctype ==
+                          blink::Manifest::ShareTarget::Enctype::kMultipart
+                      ? "multipart/form-data"
+                      : "application/x-www-form-urlencoded"));
   if (!manifest.share_target->params.text.is_null()) {
     origin_dict->SetKey(
         kTextKey, base::Value(manifest.share_target->params.text.string()));
@@ -60,6 +76,26 @@
         kUrlKey, base::Value(manifest.share_target->params.url.string()));
   }
 
+  if (!manifest.share_target->params.files.empty()) {
+    std::vector<base::Value> files;
+    files.reserve(manifest.share_target->params.files.size());
+    for (const blink::Manifest::ShareTargetFile& share_target_file :
+         manifest.share_target->params.files) {
+      std::vector<base::Value> accept;
+      accept.reserve(share_target_file.accept.size());
+      for (const base::string16& entry : share_target_file.accept) {
+        accept.push_back(base::Value(entry));
+      }
+
+      files.push_back(base::DictionaryValue());
+      base::DictionaryValue& file_dict =
+          static_cast<base::DictionaryValue&>(files.back());
+      file_dict.SetKey(kNameKey, base::Value(share_target_file.name));
+      file_dict.SetKey(kAcceptKey, base::ListValue(std::move(accept)));
+    }
+    origin_dict->SetKey(kFilesKey, base::Value(files));
+  }
+
   share_target_dict->SetWithoutPathExpansion(manifest_url.spec(),
                                              std::move(origin_dict));
 }
diff --git a/chrome/browser/webshare/share_target_pref_helper_unittest.cc b/chrome/browser/webshare/share_target_pref_helper_unittest.cc
index cd8647e..04d7fce 100644
--- a/chrome/browser/webshare/share_target_pref_helper_unittest.cc
+++ b/chrome/browser/webshare/share_target_pref_helper_unittest.cc
@@ -36,15 +36,21 @@
 
 constexpr char kNameKey[] = "name";
 constexpr char kActionKey[] = "action";
+constexpr char kMethodKey[] = "method";
+constexpr char kEnctypeKey[] = "enctype";
 constexpr char kTextKey[] = "text";
 constexpr char kTitleKey[] = "title";
 constexpr char kUrlKey[] = "url";
+constexpr char kFilesKey[] = "files";
+constexpr char kAcceptKey[] = "accept";
 
 TEST_F(ShareTargetPrefHelperUnittest, AddMultipleShareTargets) {
   // Add a share target to prefs that wasn't previously stored.
   GURL manifest_url("https://www.sharetarget.com/manifest.json");
   blink::Manifest::ShareTarget share_target;
   share_target.action = GURL("https://www.sharetarget.com/share");
+  share_target.method = blink::Manifest::ShareTarget::Method::kGet;
+  share_target.enctype = blink::Manifest::ShareTarget::Enctype::kApplication;
   share_target.params.title =
       base::NullableString16(base::ASCIIToUTF16("mytitle"));
   share_target.params.text =
@@ -62,11 +68,17 @@
   const base::DictionaryValue* share_target_info_dict = nullptr;
   ASSERT_TRUE(share_target_dict->GetDictionaryWithoutPathExpansion(
       manifest_url.spec(), &share_target_info_dict));
-  EXPECT_EQ(4UL, share_target_info_dict->size());
+  EXPECT_EQ(6UL, share_target_info_dict->size());
   std::string action_url_in_dict;
   EXPECT_TRUE(
       share_target_info_dict->GetString(kActionKey, &action_url_in_dict));
   EXPECT_EQ("https://www.sharetarget.com/share", action_url_in_dict);
+  std::string method_in_dict;
+  EXPECT_TRUE(share_target_info_dict->GetString(kMethodKey, &method_in_dict));
+  EXPECT_EQ("GET", method_in_dict);
+  std::string enctype_in_dict;
+  EXPECT_TRUE(share_target_info_dict->GetString(kEnctypeKey, &enctype_in_dict));
+  EXPECT_EQ("application/x-www-form-urlencoded", enctype_in_dict);
   std::string title_in_dict;
   EXPECT_TRUE(share_target_info_dict->GetString(kTitleKey, &title_in_dict));
   EXPECT_EQ("mytitle", title_in_dict);
@@ -89,10 +101,14 @@
   EXPECT_EQ(2UL, share_target_dict->size());
   ASSERT_TRUE(share_target_dict->GetDictionaryWithoutPathExpansion(
       manifest_url.spec(), &share_target_info_dict));
-  EXPECT_EQ(5UL, share_target_info_dict->size());
+  EXPECT_EQ(7UL, share_target_info_dict->size());
   EXPECT_TRUE(
       share_target_info_dict->GetString(kActionKey, &action_url_in_dict));
   EXPECT_EQ("https://www.sharetarget.com/share", action_url_in_dict);
+  EXPECT_TRUE(share_target_info_dict->GetString(kMethodKey, &method_in_dict));
+  EXPECT_EQ("GET", method_in_dict);
+  EXPECT_TRUE(share_target_info_dict->GetString(kEnctypeKey, &enctype_in_dict));
+  EXPECT_EQ("application/x-www-form-urlencoded", enctype_in_dict);
   std::string name_in_dict;
   EXPECT_TRUE(share_target_info_dict->GetString(kNameKey, &name_in_dict));
   EXPECT_TRUE(share_target_info_dict->GetString(kTitleKey, &title_in_dict));
@@ -113,6 +129,8 @@
   GURL manifest_url(kManifestUrl);
   blink::Manifest::ShareTarget share_target;
   share_target.action = GURL(kAction);
+  share_target.method = blink::Manifest::ShareTarget::Method::kGet;
+  share_target.enctype = blink::Manifest::ShareTarget::Enctype::kApplication;
   share_target.params.title =
       base::NullableString16(base::ASCIIToUTF16(kTitle));
   blink::Manifest manifest;
@@ -127,11 +145,17 @@
   const base::DictionaryValue* share_target_info_dict = nullptr;
   ASSERT_TRUE(share_target_dict->GetDictionaryWithoutPathExpansion(
       kManifestUrl, &share_target_info_dict));
-  EXPECT_EQ(2UL, share_target_info_dict->size());
+  EXPECT_EQ(4UL, share_target_info_dict->size());
   std::string action_url_in_dict;
   EXPECT_TRUE(
       share_target_info_dict->GetString(kActionKey, &action_url_in_dict));
   EXPECT_EQ("https://www.sharetarget.com/share", action_url_in_dict);
+  std::string method_in_dict;
+  EXPECT_TRUE(share_target_info_dict->GetString(kMethodKey, &method_in_dict));
+  EXPECT_EQ("GET", method_in_dict);
+  std::string enctype_in_dict;
+  EXPECT_TRUE(share_target_info_dict->GetString(kEnctypeKey, &enctype_in_dict));
+  EXPECT_EQ("application/x-www-form-urlencoded", enctype_in_dict);
 
   // Add same share target to prefs that was previously stored; shouldn't
   // duplicate it.
@@ -142,7 +166,7 @@
   EXPECT_EQ(1UL, share_target_dict->size());
   ASSERT_TRUE(share_target_dict->GetDictionaryWithoutPathExpansion(
       kManifestUrl, &share_target_info_dict));
-  EXPECT_EQ(2UL, share_target_info_dict->size());
+  EXPECT_EQ(4UL, share_target_info_dict->size());
   EXPECT_TRUE(
       share_target_info_dict->GetString(kActionKey, &action_url_in_dict));
   EXPECT_EQ("https://www.sharetarget.com/share", action_url_in_dict);
@@ -153,6 +177,8 @@
   GURL manifest_url("https://www.sharetarget.com/manifest.json");
   blink::Manifest::ShareTarget share_target;
   share_target.action = GURL("https://www.sharetarget.com/share");
+  share_target.method = blink::Manifest::ShareTarget::Method::kPost;
+  share_target.enctype = blink::Manifest::ShareTarget::Enctype::kMultipart;
   share_target.params.title =
       base::NullableString16(base::ASCIIToUTF16("title"));
   blink::Manifest manifest;
@@ -167,11 +193,17 @@
   const base::DictionaryValue* share_target_info_dict = nullptr;
   ASSERT_TRUE(share_target_dict->GetDictionaryWithoutPathExpansion(
       manifest_url.spec(), &share_target_info_dict));
-  EXPECT_EQ(2UL, share_target_info_dict->size());
+  EXPECT_EQ(4UL, share_target_info_dict->size());
   std::string action_url_in_dict;
   EXPECT_TRUE(
       share_target_info_dict->GetString(kActionKey, &action_url_in_dict));
   EXPECT_EQ("https://www.sharetarget.com/share", action_url_in_dict);
+  std::string method_in_dict;
+  EXPECT_TRUE(share_target_info_dict->GetString(kMethodKey, &method_in_dict));
+  EXPECT_EQ("POST", method_in_dict);
+  std::string enctype_in_dict;
+  EXPECT_TRUE(share_target_info_dict->GetString(kEnctypeKey, &enctype_in_dict));
+  EXPECT_EQ("multipart/form-data", enctype_in_dict);
   std::string title_in_dict;
   EXPECT_TRUE(share_target_info_dict->GetString(kTitleKey, &title_in_dict));
   EXPECT_EQ("title", title_in_dict);
@@ -188,10 +220,14 @@
   EXPECT_EQ(1UL, share_target_dict->size());
   ASSERT_TRUE(share_target_dict->GetDictionaryWithoutPathExpansion(
       manifest_url.spec(), &share_target_info_dict));
-  EXPECT_EQ(3UL, share_target_info_dict->size());
+  EXPECT_EQ(5UL, share_target_info_dict->size());
   EXPECT_TRUE(
       share_target_info_dict->GetString(kActionKey, &action_url_in_dict));
   EXPECT_EQ("https://www.sharetarget.com/share", action_url_in_dict);
+  EXPECT_TRUE(share_target_info_dict->GetString(kMethodKey, &method_in_dict));
+  EXPECT_EQ("POST", method_in_dict);
+  EXPECT_TRUE(share_target_info_dict->GetString(kEnctypeKey, &enctype_in_dict));
+  EXPECT_EQ("multipart/form-data", enctype_in_dict);
   EXPECT_TRUE(share_target_info_dict->GetString(kTitleKey, &title_in_dict));
   EXPECT_EQ("title", title_in_dict);
   std::string text_in_dict;
@@ -220,6 +256,8 @@
   GURL manifest_url("https://www.sharetarget.com/manifest.json");
   blink::Manifest::ShareTarget share_target;
   share_target.action = GURL("https://www.sharetarget.com/share");
+  share_target.method = blink::Manifest::ShareTarget::Method::kPost;
+  share_target.enctype = blink::Manifest::ShareTarget::Enctype::kMultipart;
   share_target.params.title =
       base::NullableString16(base::ASCIIToUTF16("title"));
   blink::Manifest manifest;
@@ -234,11 +272,17 @@
   const base::DictionaryValue* share_target_info_dict = nullptr;
   ASSERT_TRUE(share_target_dict->GetDictionaryWithoutPathExpansion(
       manifest_url.spec(), &share_target_info_dict));
-  EXPECT_EQ(2UL, share_target_info_dict->size());
+  EXPECT_EQ(4UL, share_target_info_dict->size());
   std::string action_url_in_dict;
   EXPECT_TRUE(
       share_target_info_dict->GetString(kActionKey, &action_url_in_dict));
   EXPECT_EQ("https://www.sharetarget.com/share", action_url_in_dict);
+  std::string method_in_dict;
+  EXPECT_TRUE(share_target_info_dict->GetString(kMethodKey, &method_in_dict));
+  EXPECT_EQ("POST", method_in_dict);
+  std::string enctype_in_dict;
+  EXPECT_TRUE(share_target_info_dict->GetString(kEnctypeKey, &enctype_in_dict));
+  EXPECT_EQ("multipart/form-data", enctype_in_dict);
   std::string title_in_dict;
   EXPECT_TRUE(share_target_info_dict->GetString(kTitleKey, &title_in_dict));
   EXPECT_EQ("title", title_in_dict);
@@ -258,6 +302,8 @@
   GURL manifest_url("https://www.sharetarget.com/manifest.json");
   blink::Manifest::ShareTarget share_target;
   share_target.action = GURL("https://www.sharetarget.com/share?a=b&c=d");
+  share_target.method = blink::Manifest::ShareTarget::Method::kPost;
+  share_target.enctype = blink::Manifest::ShareTarget::Enctype::kApplication;
   share_target.params.title =
       base::NullableString16(base::ASCIIToUTF16("my title"));
   share_target.params.text =
@@ -276,11 +322,17 @@
   const base::DictionaryValue* share_target_info_dict = nullptr;
   ASSERT_TRUE(share_target_dict->GetDictionaryWithoutPathExpansion(
       manifest_url.spec(), &share_target_info_dict));
-  EXPECT_EQ(4UL, share_target_info_dict->size());
+  EXPECT_EQ(6UL, share_target_info_dict->size());
   std::string action_url_in_dict;
   EXPECT_TRUE(
       share_target_info_dict->GetString(kActionKey, &action_url_in_dict));
   EXPECT_EQ("https://www.sharetarget.com/share", action_url_in_dict);
+  std::string method_in_dict;
+  EXPECT_TRUE(share_target_info_dict->GetString(kMethodKey, &method_in_dict));
+  EXPECT_EQ("POST", method_in_dict);
+  std::string enctype_in_dict;
+  EXPECT_TRUE(share_target_info_dict->GetString(kEnctypeKey, &enctype_in_dict));
+  EXPECT_EQ("application/x-www-form-urlencoded", enctype_in_dict);
   std::string title_in_dict;
   EXPECT_TRUE(share_target_info_dict->GetString(kTitleKey, &title_in_dict));
   EXPECT_EQ("my title", title_in_dict);
@@ -292,4 +344,71 @@
   EXPECT_EQ("my url://", url_in_dict);
 }
 
+TEST_F(ShareTargetPrefHelperUnittest, Files) {
+  // Add a share target that accepts files.
+  GURL manifest_url("https://www.sharetarget.com/manifest.json");
+  blink::Manifest::ShareTarget share_target;
+  share_target.action = GURL("https://www.sharetarget.com/");
+  share_target.method = blink::Manifest::ShareTarget::Method::kPost;
+  share_target.enctype = blink::Manifest::ShareTarget::Enctype::kMultipart;
+  share_target.params.files.emplace_back(blink::Manifest::ShareTargetFile(
+      {base::ASCIIToUTF16("records"),
+       {base::ASCIIToUTF16("text/csv"), base::ASCIIToUTF16(".csv")}}));
+  share_target.params.files.emplace_back(blink::Manifest::ShareTargetFile(
+      {base::ASCIIToUTF16("graphs"), {base::ASCIIToUTF16("image/svg+xml")}}));
+  blink::Manifest manifest;
+  manifest.share_target =
+      base::Optional<blink::Manifest::ShareTarget>(share_target);
+
+  UpdateShareTargetInPrefs(manifest_url, manifest, pref_service());
+
+  const base::DictionaryValue* share_target_dict =
+      pref_service()->GetDictionary(prefs::kWebShareVisitedTargets);
+  EXPECT_EQ(1UL, share_target_dict->size());
+  const base::DictionaryValue* share_target_info_dict = nullptr;
+  ASSERT_TRUE(share_target_dict->GetDictionaryWithoutPathExpansion(
+      manifest_url.spec(), &share_target_info_dict));
+  EXPECT_EQ(4UL, share_target_info_dict->size());
+  std::string action_url_in_dict;
+  EXPECT_TRUE(
+      share_target_info_dict->GetString(kActionKey, &action_url_in_dict));
+  EXPECT_EQ("https://www.sharetarget.com/", action_url_in_dict);
+  std::string method_in_dict;
+  EXPECT_TRUE(share_target_info_dict->GetString(kMethodKey, &method_in_dict));
+  EXPECT_EQ("POST", method_in_dict);
+  std::string enctype_in_dict;
+  EXPECT_TRUE(share_target_info_dict->GetString(kEnctypeKey, &enctype_in_dict));
+  EXPECT_EQ("multipart/form-data", enctype_in_dict);
+  const base::ListValue* files_list = nullptr;
+  ASSERT_TRUE(share_target_info_dict->GetList(kFilesKey, &files_list));
+  ASSERT_EQ(2UL, files_list->GetSize());
+
+  {
+    const base::DictionaryValue* records_dict = nullptr;
+    ASSERT_TRUE(files_list->GetDictionary(0, &records_dict));
+    EXPECT_EQ(2UL, records_dict->size());
+    std::string name_in_records_dict;
+    EXPECT_TRUE(records_dict->GetString(kNameKey, &name_in_records_dict));
+    EXPECT_EQ("records", name_in_records_dict);
+    const base::ListValue* accept_in_records_dict = nullptr;
+    ASSERT_TRUE(records_dict->GetList(kAcceptKey, &accept_in_records_dict));
+    ASSERT_EQ(2UL, accept_in_records_dict->GetSize());
+    EXPECT_EQ("text/csv", accept_in_records_dict->GetList()[0].GetString());
+    EXPECT_EQ(".csv", accept_in_records_dict->GetList()[1].GetString());
+  }
+
+  {
+    const base::DictionaryValue* graphs_dict = nullptr;
+    ASSERT_TRUE(files_list->GetDictionary(1, &graphs_dict));
+    EXPECT_EQ(2UL, graphs_dict->size());
+    std::string name_in_graphs_dict;
+    EXPECT_TRUE(graphs_dict->GetString(kNameKey, &name_in_graphs_dict));
+    EXPECT_EQ("graphs", name_in_graphs_dict);
+    const base::ListValue* accept_in_graphs_dict = nullptr;
+    ASSERT_TRUE(graphs_dict->GetList(kAcceptKey, &accept_in_graphs_dict));
+    ASSERT_EQ(1UL, accept_in_graphs_dict->GetSize());
+    EXPECT_EQ("image/svg+xml", accept_in_graphs_dict->GetList()[0].GetString());
+  }
+}
+
 }  // namespace
diff --git a/chrome/browser/webshare/webshare_target.cc b/chrome/browser/webshare/webshare_target.cc
index 2eaa2262..215bdccd 100644
--- a/chrome/browser/webshare/webshare_target.cc
+++ b/chrome/browser/webshare/webshare_target.cc
@@ -9,32 +9,66 @@
 
 #include "base/strings/utf_string_conversions.h"
 
+WebShareTargetFiles::WebShareTargetFiles() {}
+
+WebShareTargetFiles::WebShareTargetFiles(const std::string& name,
+                                         const std::vector<std::string>& accept)
+    : name_(name), accept_(accept) {}
+
+WebShareTargetFiles::~WebShareTargetFiles() {}
+
+WebShareTargetFiles::WebShareTargetFiles(WebShareTargetFiles&& other) = default;
+
+bool WebShareTargetFiles::operator==(const WebShareTargetFiles& other) const {
+  return std::tie(name_, accept_) == std::tie(other.name_, other.accept_);
+}
+
 WebShareTarget::WebShareTarget(const GURL& manifest_url,
                                const std::string& name,
                                const GURL& action,
+                               const std::string& method,
+                               const std::string& enctype,
                                const std::string& text,
                                const std::string& title,
-                               const std::string& url)
+                               const std::string& url,
+                               std::vector<WebShareTargetFiles> files)
     : manifest_url_(manifest_url),
       name_(name),
       action_(action),
+      method_(method),
+      enctype_(enctype),
       text_(text),
       title_(title),
-      url_(url) {}
+      url_(url),
+      files_(std::move(files)) {}
 
 WebShareTarget::~WebShareTarget() {}
 
 WebShareTarget::WebShareTarget(WebShareTarget&& other) = default;
 
 bool WebShareTarget::operator==(const WebShareTarget& other) const {
-  return std::tie(manifest_url_, name_, action_, text_, title_, url_) ==
-         std::tie(other.manifest_url_, other.name_, other.action_, text_,
-                  title_, url_);
+  return std::tie(manifest_url_, name_, action_, method_, enctype_, text_,
+                  title_, url_, files_) ==
+         std::tie(other.manifest_url_, other.name_, other.action_,
+                  other.method_, other.enctype_, other.text_, other.title_,
+                  other.url_, other.files_);
+}
+
+std::ostream& operator<<(std::ostream& out, const WebShareTargetFiles& files) {
+  out << "WebShareTargetFiles(" << files.name() << ", [";
+  for (const std::string& accept : files.accept()) {
+    out << accept << ", ";
+  }
+  return out << "])";
 }
 
 std::ostream& operator<<(std::ostream& out, const WebShareTarget& target) {
-  return out << "WebShareTarget(GURL(" << target.manifest_url().spec() << "), "
-             << target.name() << ", " << target.action() << ", "
-             << target.text() << ", " << target.title() << ", " << target.url()
-             << ")";
+  out << "WebShareTarget(GURL(" << target.manifest_url().spec() << "), "
+      << target.name() << ", " << target.action() << ", " << target.method()
+      << ", " << target.enctype() << ", " << target.text() << ", "
+      << target.title() << ", " << target.url() << ", [";
+  for (const WebShareTargetFiles& files : target.files()) {
+    out << files << ", ";
+  }
+  return out << "])";
 }
diff --git a/chrome/browser/webshare/webshare_target.h b/chrome/browser/webshare/webshare_target.h
index 9ad7546..1390d7e 100644
--- a/chrome/browser/webshare/webshare_target.h
+++ b/chrome/browser/webshare/webshare_target.h
@@ -6,36 +6,78 @@
 #define CHROME_BROWSER_WEBSHARE_WEBSHARE_TARGET_H_
 
 #include <string>
+#include <vector>
 
 #include "url/gurl.h"
 
+// Represents a ShareTargetFiles entry of a Web Share Target. The attributes are
+// usually retrieved from share_target.params.files in the site's manifest.
+// https://wicg.github.io/web-share-target/level-2/#sharetargetfiles-and-its-members
+class WebShareTargetFiles {
+ public:
+  WebShareTargetFiles();
+
+  WebShareTargetFiles(const std::string& name,
+                      const std::vector<std::string>& accept);
+
+  ~WebShareTargetFiles();
+
+  // Move constructor
+  WebShareTargetFiles(WebShareTargetFiles&& other);
+
+  // Move assignment
+  WebShareTargetFiles& operator=(WebShareTargetFiles&& other) = default;
+
+  const std::string& name() const { return name_; }
+  const std::vector<std::string>& accept() const { return accept_; }
+
+  bool operator==(const WebShareTargetFiles& other) const;
+
+ private:
+  std::string name_;
+  std::vector<std::string> accept_;
+
+  DISALLOW_COPY_AND_ASSIGN(WebShareTargetFiles);
+};
+
+// Used by gtest to print a readable output on test failures.
+std::ostream& operator<<(std::ostream& out, const WebShareTargetFiles& target);
+
 // Represents a Web Share Target and its attributes. The attributes are usually
 // retrieved from the share_target field in the site's manifest.
+// https://wicg.github.io/web-share-target/level-2/#sharetarget-and-its-members
+// https://wicg.github.io/web-share-target/level-2/#sharetargetparams-and-its-members
 class WebShareTarget {
  public:
   WebShareTarget(const GURL& manifest_url,
                  const std::string& name,
                  const GURL& action,
+                 const std::string& method,
+                 const std::string& enctype,
                  const std::string& text,
                  const std::string& title,
-                 const std::string& url);
+                 const std::string& url,
+                 std::vector<WebShareTargetFiles> files);
   ~WebShareTarget();
 
   // Move constructor
   WebShareTarget(WebShareTarget&& other);
 
-  // Move assigment
+  // Move assignment
   WebShareTarget& operator=(WebShareTarget&& other) = default;
 
   const std::string& name() const { return name_; }
   const GURL& manifest_url() const { return manifest_url_; }
   // The action URL to append query parameters to.
   const GURL& action() const { return action_; }
+  const std::string& method() const { return method_; }
+  const std::string& enctype() const { return enctype_; }
 
   // Parameters
   const std::string& text() const { return text_; }
   const std::string& title() const { return title_; }
   const std::string& url() const { return url_; }
+  const std::vector<WebShareTargetFiles>& files() const { return files_; }
 
   bool operator==(const WebShareTarget& other) const;
 
@@ -43,9 +85,12 @@
   GURL manifest_url_;
   std::string name_;
   GURL action_;
+  std::string method_;
+  std::string enctype_;
   std::string text_;
   std::string title_;
   std::string url_;
+  std::vector<WebShareTargetFiles> files_;
 
   DISALLOW_COPY_AND_ASSIGN(WebShareTarget);
 };
diff --git a/chrome/common/extensions/permissions/chrome_permission_message_provider_unittest.cc b/chrome/common/extensions/permissions/chrome_permission_message_provider_unittest.cc
index a3d8e0c..8c251ec 100644
--- a/chrome/common/extensions/permissions/chrome_permission_message_provider_unittest.cc
+++ b/chrome/common/extensions/permissions/chrome_permission_message_provider_unittest.cc
@@ -154,9 +154,9 @@
       URLPattern(URLPattern::SCHEME_ALL, "https://ɡoogle.com/"));
   explicit_hosts.AddPattern(
       URLPattern(URLPattern::SCHEME_ALL, "https://*.ɡoogle.com/"));
-  extensions::PermissionSet permissions(APIPermissionSet(),
-                                        ManifestPermissionSet(), explicit_hosts,
-                                        URLPatternSet());
+  extensions::PermissionSet permissions(
+      APIPermissionSet(), ManifestPermissionSet(), std::move(explicit_hosts),
+      URLPatternSet());
 
   PermissionMessages messages = message_provider()->GetPermissionMessages(
       message_provider()->GetAllPermissionIDs(permissions,
diff --git a/chrome/common/extensions/permissions/permission_set_unittest.cc b/chrome/common/extensions/permissions/permission_set_unittest.cc
index 64e828c7..7beb355c 100644
--- a/chrome/common/extensions/permissions/permission_set_unittest.cc
+++ b/chrome/common/extensions/permissions/permission_set_unittest.cc
@@ -311,7 +311,8 @@
   AddPattern(&explicit_hosts, "http://www.example.com/a/particular/path/*");
 
   PermissionSet perm_set(std::move(apis), std::move(manifest_permissions),
-                         explicit_hosts, scriptable_hosts);
+                         std::move(explicit_hosts),
+                         std::move(scriptable_hosts));
   ASSERT_TRUE(
       perm_set.HasExplicitAccessToOrigin(GURL("http://www.google.com/")));
   ASSERT_TRUE(
@@ -368,9 +369,11 @@
   AddPattern(&effective_hosts, "http://*.google.com/*");
 
   set1.reset(new PermissionSet(apis1.Clone(), manifest_permissions.Clone(),
-                               explicit_hosts1, scriptable_hosts1));
+                               explicit_hosts1.Clone(),
+                               scriptable_hosts1.Clone()));
   set2.reset(new PermissionSet(apis2.Clone(), manifest_permissions.Clone(),
-                               explicit_hosts2, scriptable_hosts2));
+                               explicit_hosts2.Clone(),
+                               scriptable_hosts2.Clone()));
   union_set = PermissionSet::CreateUnion(*set1, *set2);
   EXPECT_TRUE(set1->Contains(*set2));
   EXPECT_TRUE(set1->Contains(*union_set));
@@ -423,7 +426,8 @@
       URLPatternSet::CreateUnion(explicit_hosts2, scriptable_hosts2);
 
   set2.reset(new PermissionSet(apis2.Clone(), manifest_permissions.Clone(),
-                               explicit_hosts2, scriptable_hosts2));
+                               explicit_hosts2.Clone(),
+                               scriptable_hosts2.Clone()));
   union_set = PermissionSet::CreateUnion(*set1, *set2);
 
   EXPECT_FALSE(set1->Contains(*set2));
@@ -481,9 +485,11 @@
   AddPattern(&scriptable_hosts1, "http://www.reddit.com/*");
 
   set1.reset(new PermissionSet(apis1.Clone(), manifest_permissions.Clone(),
-                               explicit_hosts1, scriptable_hosts1));
+                               explicit_hosts1.Clone(),
+                               scriptable_hosts1.Clone()));
   set2.reset(new PermissionSet(apis2.Clone(), manifest_permissions.Clone(),
-                               explicit_hosts2, scriptable_hosts2));
+                               explicit_hosts2.Clone(),
+                               scriptable_hosts2.Clone()));
   new_set = PermissionSet::CreateIntersection(*set1, *set2);
   EXPECT_TRUE(set1->Contains(*new_set));
   EXPECT_TRUE(set2->Contains(*new_set));
@@ -531,7 +537,8 @@
   AddPattern(&effective_hosts, "http://*.google.com/*");
 
   set2.reset(new PermissionSet(apis2.Clone(), manifest_permissions.Clone(),
-                               explicit_hosts2, scriptable_hosts2));
+                               explicit_hosts2.Clone(),
+                               scriptable_hosts2.Clone()));
   new_set = PermissionSet::CreateIntersection(*set1, *set2);
 
   EXPECT_TRUE(set1->Contains(*new_set));
@@ -589,9 +596,11 @@
   AddPattern(&scriptable_hosts1, "http://www.reddit.com/*");
 
   set1.reset(new PermissionSet(apis1.Clone(), manifest_permissions.Clone(),
-                               explicit_hosts1, scriptable_hosts1));
+                               explicit_hosts1.Clone(),
+                               scriptable_hosts1.Clone()));
   set2.reset(new PermissionSet(apis2.Clone(), manifest_permissions.Clone(),
-                               explicit_hosts2, scriptable_hosts2));
+                               explicit_hosts2.Clone(),
+                               scriptable_hosts2.Clone()));
   new_set = PermissionSet::CreateDifference(*set1, *set2);
   EXPECT_EQ(*set1, *new_set);
 
@@ -627,7 +636,8 @@
   AddPattern(&effective_hosts, "http://www.reddit.com/*");
 
   set2.reset(new PermissionSet(apis2.Clone(), manifest_permissions.Clone(),
-                               explicit_hosts2, scriptable_hosts2));
+                               explicit_hosts2.Clone(),
+                               scriptable_hosts2.Clone()));
   new_set = PermissionSet::CreateDifference(*set1, *set2);
 
   EXPECT_TRUE(set1->Contains(*new_set));
@@ -933,7 +943,8 @@
     hosts.AddPattern(URLPattern(URLPattern::SCHEME_CHROMEUI,
                                 "chrome://favicon/"));
     PermissionSet permissions(std::move(api_permissions),
-                              ManifestPermissionSet(), hosts, URLPatternSet());
+                              ManifestPermissionSet(), std::move(hosts),
+                              URLPatternSet());
     EXPECT_TRUE(PermissionSetProducesMessage(
         permissions, Manifest::TYPE_EXTENSION,
         MakePermissionIDSet(APIPermission::kTab, APIPermission::kFavicon)));
@@ -946,7 +957,7 @@
     hosts.AddPattern(URLPattern(URLPattern::SCHEME_CHROMEUI,
                                 "chrome://favicon/"));
     PermissionSet permissions(api_permissions.Clone(), ManifestPermissionSet(),
-                              hosts, URLPatternSet());
+                              std::move(hosts), URLPatternSet());
     EXPECT_TRUE(PermissionSetProducesMessage(
         permissions, Manifest::TYPE_EXTENSION,
         MakePermissionIDSet(APIPermission::kHistory, APIPermission::kFavicon)));
@@ -958,7 +969,8 @@
     URLPatternSet hosts;
     hosts.AddPattern(URLPattern(URLPattern::SCHEME_CHROMEUI, "*://*/*"));
     PermissionSet permissions(std::move(api_permissions),
-                              ManifestPermissionSet(), hosts, URLPatternSet());
+                              ManifestPermissionSet(), std::move(hosts),
+                              URLPatternSet());
     EXPECT_TRUE(PermissionSetProducesMessage(
         permissions, Manifest::TYPE_EXTENSION,
         MakePermissionIDSet(APIPermission::kHostsAll, APIPermission::kTab)));
@@ -970,7 +982,8 @@
     URLPatternSet hosts;
     hosts.AddPattern(URLPattern(URLPattern::SCHEME_CHROMEUI, "*://*/*"));
     PermissionSet permissions(std::move(api_permissions),
-                              ManifestPermissionSet(), hosts, URLPatternSet());
+                              ManifestPermissionSet(), std::move(hosts),
+                              URLPatternSet());
     EXPECT_TRUE(PermissionSetProducesMessage(
         permissions, Manifest::TYPE_EXTENSION,
         MakePermissionIDSet(APIPermission::kHostsAll,
@@ -983,7 +996,8 @@
     URLPatternSet hosts;
     hosts.AddPattern(URLPattern(URLPattern::SCHEME_CHROMEUI, "*://*/*"));
     PermissionSet permissions(std::move(api_permissions),
-                              ManifestPermissionSet(), hosts, URLPatternSet());
+                              ManifestPermissionSet(), std::move(hosts),
+                              URLPatternSet());
     EXPECT_TRUE(PermissionSetProducesMessage(
         permissions, Manifest::TYPE_EXTENSION,
         MakePermissionIDSet(APIPermission::kHostsAll)));
@@ -1472,7 +1486,8 @@
     expected.insert("*.example.com");
 
     PermissionSet perm_set(APIPermissionSet(), ManifestPermissionSet(),
-                           explicit_hosts, scriptable_hosts);
+                           std::move(explicit_hosts),
+                           std::move(scriptable_hosts));
     EXPECT_EQ(expected, permission_message_util::GetDistinctHosts(
                             perm_set.effective_hosts(), true, true));
   }
@@ -1674,7 +1689,6 @@
        true,
        false},
   };
-  const URLPatternSet empty_scriptable_hosts;
   const PermissionMessageProvider* provider = PermissionMessageProvider::Get();
   for (size_t i = 0; i < base::size(test_cases); ++i) {
     URLPatternSet explicit_hosts1;
@@ -1689,9 +1703,9 @@
           URLPattern(final_host.schemes, final_host.pattern));
     }
     const PermissionSet set1(APIPermissionSet(), ManifestPermissionSet(),
-                             explicit_hosts1, empty_scriptable_hosts);
+                             std::move(explicit_hosts1), URLPatternSet());
     const PermissionSet set2(APIPermissionSet(), ManifestPermissionSet(),
-                             explicit_hosts2, empty_scriptable_hosts);
+                             std::move(explicit_hosts2), URLPatternSet());
     EXPECT_EQ(test_case.is_increase,
               provider->IsPrivilegeIncrease(set1, set2, test_case.type))
         << "Failure at index " << i;
@@ -1703,15 +1717,14 @@
 
 TEST(PermissionsTest, GetAPIsAsStrings) {
   APIPermissionSet apis;
-  URLPatternSet empty_set;
 
   apis.insert(APIPermission::kProxy);
   apis.insert(APIPermission::kBackground);
   apis.insert(APIPermission::kNotifications);
   apis.insert(APIPermission::kTab);
 
-  PermissionSet perm_set(apis.Clone(), ManifestPermissionSet(), empty_set,
-                         empty_set);
+  PermissionSet perm_set(apis.Clone(), ManifestPermissionSet(), URLPatternSet(),
+                         URLPatternSet());
   std::set<std::string> api_names = perm_set.GetAPIsAsStrings();
 
   // The result is correct if it has the same number of elements
@@ -1722,21 +1735,19 @@
 }
 
 TEST(PermissionsTest, IsEmpty) {
-  URLPatternSet empty_extent;
-
   std::unique_ptr<const PermissionSet> empty(new PermissionSet());
   EXPECT_TRUE(empty->IsEmpty());
   std::unique_ptr<const PermissionSet> perm_set;
 
   perm_set.reset(new PermissionSet(APIPermissionSet(), ManifestPermissionSet(),
-                                   empty_extent, empty_extent));
+                                   URLPatternSet(), URLPatternSet()));
   EXPECT_TRUE(perm_set->IsEmpty());
 
   APIPermissionSet non_empty_apis;
   non_empty_apis.insert(APIPermission::kBackground);
   perm_set.reset(new PermissionSet(std::move(non_empty_apis),
-                                   ManifestPermissionSet(), empty_extent,
-                                   empty_extent));
+                                   ManifestPermissionSet(), URLPatternSet(),
+                                   URLPatternSet()));
   EXPECT_FALSE(perm_set->IsEmpty());
 
   // Try non standard host
@@ -1744,22 +1755,21 @@
   AddPattern(&non_empty_extent, "http://www.google.com/*");
 
   perm_set.reset(new PermissionSet(APIPermissionSet(), ManifestPermissionSet(),
-                                   non_empty_extent, empty_extent));
+                                   non_empty_extent.Clone(), URLPatternSet()));
   EXPECT_FALSE(perm_set->IsEmpty());
 
   perm_set.reset(new PermissionSet(APIPermissionSet(), ManifestPermissionSet(),
-                                   empty_extent, non_empty_extent));
+                                   URLPatternSet(), non_empty_extent.Clone()));
   EXPECT_FALSE(perm_set->IsEmpty());
 }
 
 TEST(PermissionsTest, ImpliedPermissions) {
-  URLPatternSet empty_extent;
   APIPermissionSet apis;
   apis.insert(APIPermission::kFileBrowserHandler);
   EXPECT_EQ(1U, apis.size());
 
-  PermissionSet perm_set(std::move(apis), ManifestPermissionSet(), empty_extent,
-                         empty_extent);
+  PermissionSet perm_set(std::move(apis), ManifestPermissionSet(),
+                         URLPatternSet(), URLPatternSet());
   EXPECT_EQ(2U, perm_set.apis().size());
 }
 
@@ -1789,7 +1799,7 @@
   allowed_hosts.AddPattern(
       URLPattern(URLPattern::SCHEME_ALL, "chrome://thumb/"));
   PermissionSet permissions(APIPermissionSet(), ManifestPermissionSet(),
-                            allowed_hosts, URLPatternSet());
+                            std::move(allowed_hosts), URLPatternSet());
   PermissionMessageProvider::Get()->GetPermissionMessages(
       PermissionMessageProvider::Get()->GetAllPermissionIDs(
           permissions, Manifest::TYPE_EXTENSION));
diff --git a/chrome/common/extensions/permissions/permissions_data_unittest.cc b/chrome/common/extensions/permissions/permissions_data_unittest.cc
index 6a1c3b3..4a95239 100644
--- a/chrome/common/extensions/permissions/permissions_data_unittest.cc
+++ b/chrome/common/extensions/permissions/permissions_data_unittest.cc
@@ -216,11 +216,13 @@
 
   // Tab-specific permissions should be included in the effective hosts.
   GURL tab_url("http://www.example.com/");
-  URLPatternSet new_hosts;
-  new_hosts.AddOrigin(URLPattern::SCHEME_ALL, tab_url);
-  extension->permissions_data()->UpdateTabSpecificPermissions(
-      1, PermissionSet(APIPermissionSet(), ManifestPermissionSet(), new_hosts,
-                       URLPatternSet()));
+  {
+    URLPatternSet new_hosts;
+    new_hosts.AddOrigin(URLPattern::SCHEME_ALL, tab_url);
+    extension->permissions_data()->UpdateTabSpecificPermissions(
+        1, PermissionSet(APIPermissionSet(), ManifestPermissionSet(),
+                         std::move(new_hosts), URLPatternSet()));
+  }
   EXPECT_TRUE(
       extension->permissions_data()->GetEffectiveHostPermissions().MatchesURL(
           tab_url));
@@ -694,7 +696,7 @@
 
   {
     PermissionSet permissions(APIPermissionSet(), ManifestPermissionSet(),
-                              allowed_hosts, URLPatternSet());
+                              allowed_hosts.Clone(), URLPatternSet());
     permissions_data->UpdateTabSpecificPermissions(0, permissions);
     EXPECT_EQ(permissions.explicit_hosts(),
               permissions_data->GetTabSpecificPermissionsForTesting(0)
@@ -723,14 +725,14 @@
 
   {
     PermissionSet permissions1(APIPermissionSet(), ManifestPermissionSet(),
-                               allowed_hosts, URLPatternSet());
+                               allowed_hosts.Clone(), URLPatternSet());
     permissions_data->UpdateTabSpecificPermissions(0, permissions1);
     EXPECT_EQ(permissions1.explicit_hosts(),
               permissions_data->GetTabSpecificPermissionsForTesting(0)
                   ->explicit_hosts());
 
     PermissionSet permissions2(APIPermissionSet(), ManifestPermissionSet(),
-                               more_allowed_hosts, URLPatternSet());
+                               more_allowed_hosts.Clone(), URLPatternSet());
     permissions_data->UpdateTabSpecificPermissions(1, permissions2);
     EXPECT_EQ(permissions2.explicit_hosts(),
               permissions_data->GetTabSpecificPermissionsForTesting(1)
@@ -778,8 +780,8 @@
     tab_hosts.AddOrigin(UserScript::ValidUserScriptSchemes(),
                         settings_url.GetOrigin());
     PermissionSet tab_permissions(std::move(tab_api_permissions),
-                                  ManifestPermissionSet(), tab_hosts,
-                                  tab_hosts);
+                                  ManifestPermissionSet(), tab_hosts.Clone(),
+                                  tab_hosts.Clone());
     active_tab->permissions_data()->UpdateTabSpecificPermissions(
         kTabId, tab_permissions);
   }
@@ -805,8 +807,8 @@
     tab_hosts.AddOrigin(UserScript::ValidUserScriptSchemes(),
                         file_url.GetOrigin());
     PermissionSet tab_permissions(std::move(tab_api_permissions),
-                                  ManifestPermissionSet(), tab_hosts,
-                                  tab_hosts);
+                                  ManifestPermissionSet(), tab_hosts.Clone(),
+                                  tab_hosts.Clone());
     active_tab->permissions_data()->UpdateTabSpecificPermissions(
         kTabId, tab_permissions);
   }
@@ -850,7 +852,7 @@
   tab_hosts.AddOrigin(UserScript::ValidUserScriptSchemes(),
                       GURL("https://chrome.google.com./webstore").GetOrigin());
   PermissionSet tab_permissions(APIPermissionSet(), ManifestPermissionSet(),
-                                tab_hosts, tab_hosts);
+                                tab_hosts.Clone(), tab_hosts.Clone());
   for (const Extension* extension : extensions) {
     // Give the extension activeTab permissions to run on the webstore - it
     // shouldn't make a difference.
@@ -1079,8 +1081,8 @@
     tab_hosts.AddOrigin(UserScript::ValidUserScriptSchemes(),
                         url::Origin::Create(url).GetURL());
     PermissionSet tab_permissions(std::move(tab_api_permissions),
-                                  ManifestPermissionSet(), tab_hosts,
-                                  tab_hosts);
+                                  ManifestPermissionSet(), tab_hosts.Clone(),
+                                  tab_hosts.Clone());
     extension.permissions_data()->UpdateTabSpecificPermissions(kTabId,
                                                                tab_permissions);
   }
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc
index 8d502c3..e2c8bfb 100644
--- a/chrome/common/pref_names.cc
+++ b/chrome/common/pref_names.cc
@@ -1846,6 +1846,9 @@
 // Device requisition for enterprise enrollment.
 const char kDeviceEnrollmentRequisition[] = "enrollment.device_requisition";
 
+// Sub organization for enterprise enrollment.
+const char kDeviceEnrollmentSubOrganization[] = "enrollment.sub_organization";
+
 // Whether to automatically start the enterprise enrollment step during OOBE.
 const char kDeviceEnrollmentAutoStart[] = "enrollment.auto_start";
 
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h
index 653706f..7d085ff 100644
--- a/chrome/common/pref_names.h
+++ b/chrome/common/pref_names.h
@@ -618,6 +618,7 @@
 extern const char kRebootAfterUpdate[];
 extern const char kDeviceRobotAnyApiRefreshToken[];
 extern const char kDeviceEnrollmentRequisition[];
+extern const char kDeviceEnrollmentSubOrganization[];
 extern const char kDeviceEnrollmentAutoStart[];
 extern const char kDeviceEnrollmentCanExit[];
 extern const char kDeviceDMToken[];
diff --git a/chrome/renderer/translate/translate_helper_browsertest.cc b/chrome/renderer/translate/translate_helper_browsertest.cc
index 93e6f1b..d8888c7 100644
--- a/chrome/renderer/translate/translate_helper_browsertest.cc
+++ b/chrome/renderer/translate/translate_helper_browsertest.cc
@@ -89,7 +89,8 @@
     trans_result_error_type_ = translate::TranslateErrors::NONE;
 
     // Will get new result values via OnPageTranslated.
-    Translate(translate_script, source_lang, target_lang,
+    Translate(translate_script, network::mojom::URLLoaderFactoryPtr(),
+              source_lang, target_lang,
               base::Bind(&TestTranslateHelper::OnPageTranslated,
                          base::Unretained(this)));
   }
diff --git a/chrome/services/cups_ipp_parser/public/cpp/BUILD.gn b/chrome/services/cups_ipp_parser/public/cpp/BUILD.gn
index 530ccb2d..6d3e36c 100644
--- a/chrome/services/cups_ipp_parser/public/cpp/BUILD.gn
+++ b/chrome/services/cups_ipp_parser/public/cpp/BUILD.gn
@@ -22,15 +22,18 @@
     configs += [ "//printing:cups" ]
   }
 
-  fuzzer_test("ipp_message_parser_fuzzer") {
-    sources = [
-      "ipp_message_parser_fuzzer.cc",
-    ]
-    deps = [
-      ":cpp",
-    ]
+  # Fuzzer target only available on fuzzing builds.
+  if (use_fuzzing_engine) {
+    fuzzer_test("ipp_message_parser_fuzzer") {
+      sources = [
+        "ipp_message_parser_fuzzer.cc",
+      ]
+      deps = [
+        ":cpp",
+      ]
 
-    dict = "ipp_message_parser_fuzzer.dict"
+      dict = "ipp_message_parser_fuzzer.dict"
+    }
   }
 }
 
@@ -46,3 +49,7 @@
     "//services/service_manager/public/cpp",
   ]
 }
+
+# A dummy group to make fuzz targets discoverable.
+group("fuzzers") {
+}
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 2f9cafb5..7577fdb 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -605,6 +605,8 @@
       "../browser/banners/app_banner_manager_browsertest_base.cc",
       "../browser/banners/app_banner_manager_browsertest_base.h",
       "../browser/banners/app_banner_manager_desktop_browsertest.cc",
+      "../browser/banners/test_app_banner_manager_desktop.cc",
+      "../browser/banners/test_app_banner_manager_desktop.h",
       "../browser/bitmap_fetcher/bitmap_fetcher_browsertest.cc",
       "../browser/browser_encoding_browsertest.cc",
       "../browser/browsing_data/browsing_data_cache_storage_helper_browsertest.cc",
@@ -1628,6 +1630,7 @@
         "../browser/ui/views/media_router/media_router_ui_browsertest.cc",
         "../browser/ui/views/media_router/presentation_receiver_window_view_browsertest.cc",
         "../browser/ui/views/omnibox/omnibox_popup_contents_view_browsertest.cc",
+        "../browser/ui/views/page_action/pwa_install_view_browsertest.cc",
         "../browser/ui/views/page_action/zoom_view_browsertest.cc",
         "../browser/ui/views/page_info/page_info_bubble_view_browsertest.cc",
         "../browser/ui/views/passwords/password_bubble_browsertest.cc",
@@ -1867,6 +1870,8 @@
         "../browser/chromeos/login/signin/oauth2_browsertest.cc",
         "../browser/chromeos/login/test/enrollment_helper_mixin.cc",
         "../browser/chromeos/login/test/enrollment_helper_mixin.h",
+        "../browser/chromeos/login/test/fake_gaia_mixin.cc",
+        "../browser/chromeos/login/test/fake_gaia_mixin.h",
         "../browser/chromeos/login/test/hid_controller_mixin.cc",
         "../browser/chromeos/login/test/hid_controller_mixin.h",
         "../browser/chromeos/login/test/https_forwarder.cc",
@@ -3215,6 +3220,7 @@
       "//chrome/android:app_hooks_java",
       "//chrome/android:chrome_java",
       "//chrome/services/media_gallery_util:unit_tests",
+      "//components/download/internal/common:internal_java",
       "//components/favicon/core/test:test_support",
       "//components/gcm_driver/instance_id/android:instance_id_driver_java",
       "//components/gcm_driver/instance_id/android:instance_id_driver_test_support_java",
@@ -5804,6 +5810,10 @@
       "//skia",
       "//testing/gmock",
       "//testing/gtest",
+
+      # TODO(uwyiming@chromium.org) create a gn target for Web Page Replay Go (WPR Go) and only WPR Go.
+      # So that test targets requiring WPR Go does not pull down the whole telemetry tool chain.
+      "//third_party/catapult:telemetry_chrome_test_support",
       "//third_party/hunspell",
       "//third_party/icu",
       "//third_party/libpng",
diff --git a/chrome/test/base/testing_profile.cc b/chrome/test/base/testing_profile.cc
index 5cc0e9b..aab392c 100644
--- a/chrome/test/base/testing_profile.cc
+++ b/chrome/test/base/testing_profile.cc
@@ -249,6 +249,7 @@
       testing_prefs_(nullptr),
       original_profile_(nullptr),
       guest_session_(false),
+      allows_browser_windows_(true),
       last_session_exited_cleanly_(true),
       profile_path_(path),
       browser_context_dependency_manager_(
@@ -279,6 +280,7 @@
     std::unique_ptr<sync_preferences::PrefServiceSyncable> prefs,
     TestingProfile* parent,
     bool guest_session,
+    bool allows_browser_windows,
     base::Optional<bool> is_new_profile,
     const std::string& supervised_user_id,
     std::unique_ptr<policy::PolicyService> policy_service,
@@ -289,6 +291,7 @@
       testing_prefs_(nullptr),
       original_profile_(parent),
       guest_session_(guest_session),
+      allows_browser_windows_(allows_browser_windows),
       is_new_profile_(std::move(is_new_profile)),
       supervised_user_id_(supervised_user_id),
       last_session_exited_cleanly_(true),
@@ -730,6 +733,10 @@
   return IsSupervised() && !IsChild();
 }
 
+bool TestingProfile::AllowsBrowserWindows() const {
+  return allows_browser_windows_;
+}
+
 #if BUILDFLAG(ENABLE_EXTENSIONS)
 void TestingProfile::SetExtensionSpecialStoragePolicy(
     ExtensionSpecialStoragePolicy* extension_special_storage_policy) {
@@ -1049,6 +1056,7 @@
     : build_called_(false),
       delegate_(nullptr),
       guest_session_(false),
+      allows_browser_windows_(true),
       profile_name_(kTestingProfile) {}
 
 TestingProfile::Builder::~Builder() {
@@ -1078,6 +1086,10 @@
   guest_session_ = true;
 }
 
+void TestingProfile::Builder::DisallowBrowserWindows() {
+  allows_browser_windows_ = false;
+}
+
 void TestingProfile::Builder::OverrideIsNewProfile(bool is_new_profile) {
   is_new_profile_ = is_new_profile;
 }
@@ -1112,8 +1124,8 @@
                          extension_policy_,
 #endif
                          std::move(pref_service_), nullptr, guest_session_,
-                         std::move(is_new_profile_), supervised_user_id_,
-                         std::move(policy_service_),
+                         allows_browser_windows_, std::move(is_new_profile_),
+                         supervised_user_id_, std::move(policy_service_),
                          std::move(testing_factories_), profile_name_));
 }
 
@@ -1124,12 +1136,12 @@
   build_called_ = true;
 
   // Note: Owned by |original_profile|.
-  return new TestingProfile(path_, delegate_,
+  return new TestingProfile(
+      path_, delegate_,
 #if BUILDFLAG(ENABLE_EXTENSIONS)
-                            extension_policy_,
+      extension_policy_,
 #endif
-                            std::move(pref_service_), original_profile,
-                            guest_session_, std::move(is_new_profile_),
-                            supervised_user_id_, std::move(policy_service_),
-                            std::move(testing_factories_), profile_name_);
+      std::move(pref_service_), original_profile, guest_session_,
+      allows_browser_windows_, std::move(is_new_profile_), supervised_user_id_,
+      std::move(policy_service_), std::move(testing_factories_), profile_name_);
 }
diff --git a/chrome/test/base/testing_profile.h b/chrome/test/base/testing_profile.h
index 8c1f0b0..f31cd0f9 100644
--- a/chrome/test/base/testing_profile.h
+++ b/chrome/test/base/testing_profile.h
@@ -115,6 +115,9 @@
     // Makes the Profile being built a guest profile.
     void SetGuestSession();
 
+    // Makes Profile::AllowsBrowserWindows() return false.
+    void DisallowBrowserWindows();
+
     // Override the default behavior of is_new_profile to return the provided
     // value.
     void OverrideIsNewProfile(bool is_new_profile);
@@ -150,6 +153,7 @@
     base::FilePath path_;
     Delegate* delegate_;
     bool guest_session_;
+    bool allows_browser_windows_;
     base::Optional<bool> is_new_profile_;
     std::string supervised_user_id_;
     std::unique_ptr<policy::PolicyService> policy_service_;
@@ -182,6 +186,7 @@
                  std::unique_ptr<sync_preferences::PrefServiceSyncable> prefs,
                  TestingProfile* parent,
                  bool guest_session,
+                 bool allows_browser_windows,
                  base::Optional<bool> is_new_profile,
                  const std::string& supervised_user_id,
                  std::unique_ptr<policy::PolicyService> policy_service,
@@ -296,6 +301,7 @@
   bool IsSupervised() const override;
   bool IsChild() const override;
   bool IsLegacySupervised() const override;
+  bool AllowsBrowserWindows() const override;
 #if BUILDFLAG(ENABLE_EXTENSIONS)
   void SetExtensionSpecialStoragePolicy(
       ExtensionSpecialStoragePolicy* extension_special_storage_policy);
@@ -403,6 +409,8 @@
 
   bool guest_session_;
 
+  bool allows_browser_windows_;
+
   base::Optional<bool> is_new_profile_;
 
   std::string supervised_user_id_;
diff --git a/chrome/test/data/appcache/french_page_with_appcache.html b/chrome/test/data/appcache/french_page_with_appcache.html
new file mode 100644
index 0000000..16df202b
--- /dev/null
+++ b/chrome/test/data/appcache/french_page_with_appcache.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html manifest="simple_page.manifest">
+<head>
+  <head><title>Cette page est en Français</title></head>
+  <script type="text/javascript">
+    function onCachedEvent() {
+      window.document.title = "AppCache mis à jour";
+    }
+
+    function onLoad() {
+      window.applicationCache.addEventListener('cached', onCachedEvent, false);
+    }
+  </script>
+</head>
+<body onload="onLoad()">
+Cette page a été rédigée en français. Saviez-vous que le Français est la langue officielle des jeux olympiques? Ça vous en bouche un coin, pas vrai?
+</body>
+</html>
diff --git a/chrome/test/data/appcache/simple_page.manifest b/chrome/test/data/appcache/simple_page.manifest
new file mode 100644
index 0000000..a6f40c55
--- /dev/null
+++ b/chrome/test/data/appcache/simple_page.manifest
@@ -0,0 +1,4 @@
+CACHE MANIFEST
+
+NETWORK:
+*
diff --git a/chrome/test/data/extensions/api_test/service_worker/worker_based_background/tabs_events/manifest.json b/chrome/test/data/extensions/api_test/service_worker/worker_based_background/tabs_events/manifest.json
new file mode 100644
index 0000000..2f6852a
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/service_worker/worker_based_background/tabs_events/manifest.json
@@ -0,0 +1,8 @@
+{
+  "name": "Service Worker-based background script",
+  "version": "0.1",
+  "manifest_version": 2,
+  "description": "Test tabs events APIs for service worker-based background scripts.",
+  "permissions": ["tabs"],
+  "background": {"service_worker_script": "service_worker_background.js"}
+}
diff --git a/chrome/test/data/extensions/api_test/service_worker/worker_based_background/tabs_events/service_worker_background.js b/chrome/test/data/extensions/api_test/service_worker/worker_based_background/tabs_events/service_worker_background.js
new file mode 100644
index 0000000..bc578a0
--- /dev/null
+++ b/chrome/test/data/extensions/api_test/service_worker/worker_based_background/tabs_events/service_worker_background.js
@@ -0,0 +1,108 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var tabProps = [];
+const NEW_TAB_URL = 'chrome://newtab/';
+
+chrome.test.runTests([
+  // Get the info for any tabs already exist.
+  function testTabQueryInitial() {
+    try {
+      chrome.tabs.query({currentWindow: true}, function(tabs) {
+        chrome.test.assertEq(1, tabs.length);
+        tabProps.push({id: tabs[0].id, url: tabs[0].url});
+        chrome.test.succeed();
+      });
+    } catch(e) {
+      chrome.test.fail(e);
+    }
+  },
+  // Create a new tab. Use an onCreated listener to update the array of open
+  // tabs. Use an onUpdatedListener to make sure the next test doesn't start
+  // before the onUpdated events for the create call are finished.
+  function testTabCreate() {
+    chrome.tabs.onCreated.addListener(function localListener(tab) {
+      chrome.test.assertEq(NEW_TAB_URL, tab.url);
+      tabProps.push({id: tab.id, url: tab.url});
+      chrome.tabs.onCreated.removeListener(localListener);
+    });
+    chrome.tabs.onUpdated.addListener(function localListener (
+        tabId, changeInfo, tab) {
+      if (changeInfo.status === 'complete') {
+        chrome.tabs.onUpdated.removeListener(localListener);
+        chrome.test.succeed();
+      }
+    });
+    try {
+      // Create the tab inactive, so we can activate it later.
+      chrome.tabs.create({url: NEW_TAB_URL, active: false});
+    } catch (e) {
+      chrome.test.fail(e);
+    }
+  },
+  // Test the chrome.tabs.onUpdated listener.
+  function testTabOnUpdatedListener() {
+    var newUrl = 'chrome://version/';
+    chrome.tabs.onUpdated.addListener(function localListener(
+        tabId, changeInfo, tab) {
+      if (changeInfo.status === 'loading') {
+        chrome.tabs.onUpdated.removeListener(localListener);
+        chrome.test.assertEq(tabProps[1].id, tabId);
+        chrome.test.assertEq(newUrl, changeInfo.url);
+        chrome.test.succeed();
+      }
+    });
+    try {
+      chrome.tabs.update(tabProps[1].id, {url: newUrl});
+      tabProps[1].url = newUrl;
+    } catch(e) {
+      chrome.test.fail(e);
+    }
+  },
+  // Check the chrome.tabs.onMoved listener.
+  function testTabMove() {
+    var expectedId = tabProps[0].id
+    chrome.test.listenOnce(chrome.tabs.onMoved,
+                           function localListener(tabId, moveInfo) {
+      chrome.test.assertEq(expectedId, tabId);
+    });
+    try {
+      chrome.tabs.move(expectedId, {index: -1});
+    } catch(e) {
+      chrome.test.fail(e);
+    }
+  },
+  // Check the chrome.tabs.onActivated listener.
+  function testTabActivated() {
+    var tabId = tabProps[1].id;
+    chrome.tabs.onActivated.addListener(function localListener(activeInfo) {
+      chrome.tabs.onActivated.removeListener(localListener);
+      chrome.test.assertEq(tabId, activeInfo.tabId);
+      chrome.test.succeed();
+    });
+    try {
+      // Make an existing tab active.
+      chrome.tabs.update(tabId, {active: true});
+    } catch(e) {
+      chrome.test.fail(e);
+    }
+  },
+  // Check the chrome.tabs.onRemoved listener.
+  function testTabRemoved() {
+    var tabIdToClose = tabProps[1].id;
+    chrome.tabs.onRemoved.addListener(function localListener(
+        tabId, removeInfo) {
+      chrome.tabs.onRemoved.removeListener(localListener);
+      chrome.test.assertEq(tabIdToClose, tabId);
+      chrome.test.assertFalse(removeInfo.isWindowClosing);
+      chrome.test.succeed();
+    });
+    try {
+      // Remove the tab.
+      chrome.tabs.remove(tabIdToClose);
+    } catch(e) {
+      chrome.test.fail(e);
+    }
+  },
+]);
diff --git a/chrome/test/data/webui/settings/crostini_page_test.js b/chrome/test/data/webui/settings/crostini_page_test.js
index 98cb4733..566ed684 100644
--- a/chrome/test/data/webui/settings/crostini_page_test.js
+++ b/chrome/test/data/webui/settings/crostini_page_test.js
@@ -88,6 +88,7 @@
       crostiniPage.$$('#crostini').click();
       return flushAsync().then(() => {
         subpage = crostiniPage.$$('settings-crostini-subpage');
+        subpage.hideCrostiniUninstall_ = false;
         assertTrue(!!subpage);
       });
     });
diff --git a/chromecast/media/cma/backend/android/audio_sink_android_audiotrack_impl.cc b/chromecast/media/cma/backend/android/audio_sink_android_audiotrack_impl.cc
index 3d2e992..7cb788a 100644
--- a/chromecast/media/cma/backend/android/audio_sink_android_audiotrack_impl.cc
+++ b/chromecast/media/cma/backend/android/audio_sink_android_audiotrack_impl.cc
@@ -13,6 +13,7 @@
 #include "base/logging.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
+#include "base/time/time.h"
 #include "chromecast/media/cma/base/decoder_buffer_base.h"
 #include "jni/AudioSinkAudioTrackImpl_jni.h"
 #include "media/base/audio_bus.h"
@@ -284,12 +285,10 @@
 void AudioSinkAndroidAudioTrackImpl::TrackRawMonotonicClockDeviation() {
   timespec now = {0, 0};
   clock_gettime(CLOCK_MONOTONIC, &now);
-  int64_t now_usec =
-      static_cast<int64_t>(now.tv_sec) * 1000000 + now.tv_nsec / 1000;
+  int64_t now_usec = base::TimeDelta::FromTimeSpec(now).InMicroseconds();
 
   clock_gettime(CLOCK_MONOTONIC_RAW, &now);
-  int64_t now_raw_usec =
-      static_cast<int64_t>(now.tv_sec) * 1000000 + now.tv_nsec / 1000;
+  int64_t now_raw_usec = base::TimeDelta::FromTimeSpec(now).InMicroseconds();
 
   // TODO(ckuiper): Eventually we want to use this to convert from non-RAW to
   // RAW timestamps to improve accuracy.
diff --git a/chromecast/media/cma/backend/media_pipeline_backend_for_mixer.cc b/chromecast/media/cma/backend/media_pipeline_backend_for_mixer.cc
index 985b41d..cb77767 100644
--- a/chromecast/media/cma/backend/media_pipeline_backend_for_mixer.cc
+++ b/chromecast/media/cma/backend/media_pipeline_backend_for_mixer.cc
@@ -9,6 +9,7 @@
 
 #include "base/bind.h"
 #include "base/single_thread_task_runner.h"
+#include "base/time/time.h"
 #include "build/build_config.h"
 #include "chromecast/base/task_runner_impl.h"
 #include "chromecast/media/cma/backend/audio_decoder_for_mixer.h"
@@ -235,7 +236,7 @@
 #else
   clock_gettime(CLOCK_MONOTONIC, &now);
 #endif // MEDIA_CLOCK_MONOTONIC_RAW
-  return static_cast<int64_t>(now.tv_sec) * 1000000 + now.tv_nsec / 1000;
+  return base::TimeDelta::FromTimeSpec(now).InMicroseconds();
 }
 #elif defined(OS_FUCHSIA)
 int64_t MediaPipelineBackendForMixer::MonotonicClockNow() const {
diff --git a/chromeos/components/drivefs/drivefs_search_unittest.cc b/chromeos/components/drivefs/drivefs_search_unittest.cc
index 427e43a..a9924a9 100644
--- a/chromeos/components/drivefs/drivefs_search_unittest.cc
+++ b/chromeos/components/drivefs/drivefs_search_unittest.cc
@@ -101,7 +101,7 @@
       return false;
   }
   return arg.shared_with_me == shared && arg.available_offline == offline;
-};
+}
 
 TEST_F(DriveFsSearchTest, Search) {
   DriveFsSearch search(&mock_drivefs_, network_connection_tracker_.get(),
diff --git a/chromeos/constants/chromeos_switches.cc b/chromeos/constants/chromeos_switches.cc
index bb639cbe9..26551e8 100644
--- a/chromeos/constants/chromeos_switches.cc
+++ b/chromeos/constants/chromeos_switches.cc
@@ -52,6 +52,9 @@
 const base::Feature kShowSplashScreenInDemoMode{
     "ShowSplashScreenInDemoMode", base::FEATURE_DISABLED_BY_DEFAULT};
 
+const base::Feature kSupportCountryCustomizationInDemoMode{
+    "SupportCountryCustomizationInDemoMode", base::FEATURE_DISABLED_BY_DEFAULT};
+
 // Please keep the order of these switches synchronized with the header file
 // (i.e. in alphabetical order).
 
diff --git a/chromeos/constants/chromeos_switches.h b/chromeos/constants/chromeos_switches.h
index 23ca5c4..bf25ff08 100644
--- a/chromeos/constants/chromeos_switches.h
+++ b/chromeos/constants/chromeos_switches.h
@@ -166,6 +166,10 @@
 // before demo sessions log in.
 CHROMEOS_EXPORT extern const base::Feature kShowSplashScreenInDemoMode;
 
+// Controls whether to support country-level customization in Demo Mode.
+CHROMEOS_EXPORT extern const base::Feature
+    kSupportCountryCustomizationInDemoMode;
+
 // Returns true if the system should wake in response to wifi traffic.
 CHROMEOS_EXPORT bool WakeOnWifiEnabled();
 
diff --git a/chromeos/dbus/debug_daemon_client.cc b/chromeos/dbus/debug_daemon_client.cc
index d3f34d4..5cb6984 100644
--- a/chromeos/dbus/debug_daemon_client.cc
+++ b/chromeos/dbus/debug_daemon_client.cc
@@ -4,6 +4,7 @@
 
 #include "chromeos/dbus/debug_daemon_client.h"
 
+#include <dbus/dbus-protocol.h>
 #include <fcntl.h>
 #include <stddef.h>
 #include <stdint.h>
@@ -15,8 +16,6 @@
 #include <utility>
 #include <vector>
 
-#include <dbus/dbus-protocol.h>
-
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/files/file_path.h"
diff --git a/chromeos/dbus/modem_messaging_client.cc b/chromeos/dbus/modem_messaging_client.cc
index 9967cff..18ab45198 100644
--- a/chromeos/dbus/modem_messaging_client.cc
+++ b/chromeos/dbus/modem_messaging_client.cc
@@ -163,7 +163,7 @@
   }
 
  protected:
-  void Init(dbus::Bus* bus) override { bus_ = bus; };
+  void Init(dbus::Bus* bus) override { bus_ = bus; }
 
  private:
   using ProxyMap = std::map<std::pair<std::string, std::string>,
diff --git a/chromeos/network/managed_network_configuration_handler_unittest.cc b/chromeos/network/managed_network_configuration_handler_unittest.cc
index 1138fb7..a367164 100644
--- a/chromeos/network/managed_network_configuration_handler_unittest.cc
+++ b/chromeos/network/managed_network_configuration_handler_unittest.cc
@@ -69,7 +69,7 @@
 
   void PoliciesApplied(const std::string& userhash) override {
     policies_applied_count_++;
-  };
+  }
 
   int GetPoliciesAppliedCountAndReset() {
     int count = policies_applied_count_;
diff --git a/chromeos/services/assistant/assistant_manager_service_impl.cc b/chromeos/services/assistant/assistant_manager_service_impl.cc
index f1adf66..2c1dc4e 100644
--- a/chromeos/services/assistant/assistant_manager_service_impl.cc
+++ b/chromeos/services/assistant/assistant_manager_service_impl.cc
@@ -125,7 +125,9 @@
                            &ash_message_center_controller_);
 }
 
-AssistantManagerServiceImpl::~AssistantManagerServiceImpl() {}
+AssistantManagerServiceImpl::~AssistantManagerServiceImpl() {
+  background_thread_.Stop();
+}
 
 void AssistantManagerServiceImpl::Start(const std::string& access_token,
                                         bool enable_hotword,
@@ -140,28 +142,15 @@
 
   EnableHotword(enable_hotword);
 
-  using AssistantManagerPtr =
-      std::unique_ptr<assistant_client::AssistantManager>;
-  // This is a tempory holder of the |assistant_client::AssistantManager| that
-  // is going to be created on the background thread. It is owned by the
-  // background task callback closure.
-  auto* new_assistant_manager = new AssistantManagerPtr();
-
   // LibAssistant creation will make file IO and sync wait. Post the creation to
   // background thread to avoid DCHECK.
   background_thread_.task_runner()->PostTaskAndReply(
       FROM_HERE,
-      base::BindOnce(
-          [](AssistantManagerPtr* result,
-             base::OnceCallback<AssistantManagerPtr()> task) {
-            *result = std::move(task).Run();
-          },
-          new_assistant_manager,
-          base::BindOnce(&AssistantManagerServiceImpl::StartAssistantInternal,
-                         base::Unretained(this), access_token)),
+      base::BindOnce(&AssistantManagerServiceImpl::StartAssistantInternal,
+                     base::Unretained(this), access_token),
       base::BindOnce(&AssistantManagerServiceImpl::PostInitAssistant,
-                     base::Unretained(this), std::move(post_init_callback),
-                     base::Owned(new_assistant_manager)));
+                     weak_factory_.GetWeakPtr(),
+                     std::move(post_init_callback)));
 }
 
 void AssistantManagerServiceImpl::Stop() {
@@ -750,16 +739,15 @@
           weak_factory_.GetWeakPtr(), error_code));
 }
 
-std::unique_ptr<assistant_client::AssistantManager>
-AssistantManagerServiceImpl::StartAssistantInternal(
+void AssistantManagerServiceImpl::StartAssistantInternal(
     const std::string& access_token) {
   DCHECK(background_thread_.task_runner()->BelongsToCurrentThread());
 
-  std::unique_ptr<assistant_client::AssistantManager> assistant_manager;
-  assistant_manager.reset(assistant_client::AssistantManager::Create(
+  base::AutoLock lock(new_assistant_manager_lock_);
+  new_assistant_manager_.reset(assistant_client::AssistantManager::Create(
       platform_api_.get(), CreateLibAssistantConfig()));
   auto* assistant_manager_internal =
-      UnwrapAssistantManagerInternal(assistant_manager.get());
+      UnwrapAssistantManagerInternal(new_assistant_manager_.get());
 
   UpdateInternalOptions(assistant_manager_internal);
 
@@ -768,8 +756,8 @@
   assistant_manager_internal->SetAssistantManagerDelegate(this);
   assistant_manager_internal->GetFuchsiaApiHelperOrDie()->SetFuchsiaApiDelegate(
       &chromium_api_delegate_);
-  assistant_manager->AddConversationStateListener(this);
-  assistant_manager->AddDeviceStateListener(this);
+  new_assistant_manager_->AddConversationStateListener(this);
+  new_assistant_manager_->AddDeviceStateListener(this);
 
   std::vector<std::string> server_experiment_ids;
   FillServerExperimentIds(&server_experiment_ids);
@@ -777,20 +765,32 @@
   if (server_experiment_ids.size() > 0)
     assistant_manager_internal->AddExtraExperimentIds(server_experiment_ids);
 
-  assistant_manager->SetAuthTokens(
+  new_assistant_manager_->SetAuthTokens(
       {std::pair<std::string, std::string>(kUserID, access_token)});
-  assistant_manager->Start();
-
-  return assistant_manager;
+  new_assistant_manager_->Start();
 }
 
 void AssistantManagerServiceImpl::PostInitAssistant(
-    base::OnceClosure post_init_callback,
-    std::unique_ptr<assistant_client::AssistantManager>* assistant_manager) {
+    base::OnceClosure post_init_callback) {
   DCHECK(service_->main_task_runner()->RunsTasksInCurrentSequence());
   DCHECK_EQ(state_, State::STARTED);
 
-  assistant_manager_ = std::move(*assistant_manager);
+  {
+    base::AutoLock lock(new_assistant_manager_lock_);
+
+    // It is possible that multiple |StartAssistantInternal| finished on
+    // background thread, before any of the matching |PostInitAssistant| had
+    // run. Because we only hold the last created instance in
+    // |new_assistant_manager_|, it is possible that |new_assistant_manager_| be
+    // null if we moved it in previous |PostInitAssistant| runs.
+    if (!new_assistant_manager_) {
+      std::move(post_init_callback).Run();
+      return;
+    }
+
+    assistant_manager_ = std::move(new_assistant_manager_);
+  }
+
   assistant_manager_internal_ =
       UnwrapAssistantManagerInternal(assistant_manager_.get());
   state_ = State::RUNNING;
diff --git a/chromeos/services/assistant/assistant_manager_service_impl.h b/chromeos/services/assistant/assistant_manager_service_impl.h
index 0730001..8a09daf 100644
--- a/chromeos/services/assistant/assistant_manager_service_impl.h
+++ b/chromeos/services/assistant/assistant_manager_service_impl.h
@@ -13,6 +13,7 @@
 #include "ash/public/interfaces/ash_message_center_controller.mojom.h"
 #include "ash/public/interfaces/assistant_controller.mojom.h"
 #include "ash/public/interfaces/voice_interaction_controller.mojom.h"
+#include "base/synchronization/lock.h"
 #include "base/threading/thread.h"
 #include "chromeos/assistant/internal/action/cros_action_module.h"
 #include "chromeos/assistant/internal/cros_display_connection.h"
@@ -180,11 +181,8 @@
   }
 
  private:
-  std::unique_ptr<assistant_client::AssistantManager> StartAssistantInternal(
-      const std::string& access_token);
-  void PostInitAssistant(
-      base::OnceClosure post_init_callback,
-      std::unique_ptr<assistant_client::AssistantManager>* assistant_manager);
+  void StartAssistantInternal(const std::string& access_token);
+  void PostInitAssistant(base::OnceClosure post_init_callback);
 
   // Update device id, type and locale
   void UpdateDeviceSettings();
@@ -256,6 +254,10 @@
   std::unique_ptr<CrosDisplayConnection> display_connection_;
   std::unique_ptr<assistant_client::AssistantManager> assistant_manager_;
   std::unique_ptr<AssistantSettingsManagerImpl> assistant_settings_manager_;
+  // |new_asssistant_manager_| is created on |background_thread_| then posted to
+  // main thread to finish initialization then move to |assistant_manager_|.
+  std::unique_ptr<assistant_client::AssistantManager> new_assistant_manager_;
+  base::Lock new_assistant_manager_lock_;
   // same ownership as assistant_manager_.
   assistant_client::AssistantManagerInternal* assistant_manager_internal_ =
       nullptr;
diff --git a/chromeos/services/device_sync/cryptauth_enrollment_result.h b/chromeos/services/device_sync/cryptauth_enrollment_result.h
index 4929a4bc..c1698bf 100644
--- a/chromeos/services/device_sync/cryptauth_enrollment_result.h
+++ b/chromeos/services/device_sync/cryptauth_enrollment_result.h
@@ -59,7 +59,7 @@
 
   const base::Optional<cryptauthv2::ClientDirective>& client_directive() const {
     return client_directive_;
-  };
+  }
 
   bool IsSuccess() const;
 
diff --git a/chromeos/services/device_sync/cryptauth_gcm_manager_impl.h b/chromeos/services/device_sync/cryptauth_gcm_manager_impl.h
index e539ec0..16345ee 100644
--- a/chromeos/services/device_sync/cryptauth_gcm_manager_impl.h
+++ b/chromeos/services/device_sync/cryptauth_gcm_manager_impl.h
@@ -17,7 +17,7 @@
 
 namespace gcm {
 class GCMDriver;
-};
+}
 
 namespace chromeos {
 
diff --git a/chromeos/services/device_sync/persistent_enrollment_scheduler_unittest.cc b/chromeos/services/device_sync/persistent_enrollment_scheduler_unittest.cc
index a5b840f..aa9cc1f4 100644
--- a/chromeos/services/device_sync/persistent_enrollment_scheduler_unittest.cc
+++ b/chromeos/services/device_sync/persistent_enrollment_scheduler_unittest.cc
@@ -66,7 +66,7 @@
     fake_client_directive_.set_retry_period_millis(
         kFakeRetryPeriod.InMilliseconds());
     fake_client_directive_.set_retry_attempts(kFakeMaxImmediateRetries);
-  };
+  }
 
   ~DeviceSyncPersistentEnrollmentSchedulerTest() override = default;
 
diff --git a/chromeos/services/secure_channel/device_to_device_authenticator.h b/chromeos/services/secure_channel/device_to_device_authenticator.h
index 5d95002..533521b 100644
--- a/chromeos/services/secure_channel/device_to_device_authenticator.h
+++ b/chromeos/services/secure_channel/device_to_device_authenticator.h
@@ -18,7 +18,7 @@
 
 namespace base {
 class OneShotTimer;
-};
+}
 
 namespace chromeos {
 
diff --git a/chromeos/settings/cros_settings_provider.cc b/chromeos/settings/cros_settings_provider.cc
index 070292b..7b6761d 100644
--- a/chromeos/settings/cros_settings_provider.cc
+++ b/chromeos/settings/cros_settings_provider.cc
@@ -43,4 +43,4 @@
   notify_cb_ = notify_cb;
 }
 
-};  // namespace chromeos
+}  // namespace chromeos
diff --git a/components/crash/content/app/BUILD.gn b/components/crash/content/app/BUILD.gn
index 915c034..f71dd88 100644
--- a/components/crash/content/app/BUILD.gn
+++ b/components/crash/content/app/BUILD.gn
@@ -66,7 +66,10 @@
   }
 
   if (is_android) {
-    deps += [ "//components/crash/android:jni_headers" ]
+    deps += [
+      "//components/crash/android:jni_headers",
+      "//third_party/crashpad/crashpad/handler",
+    ]
   }
 
   if (is_android || is_linux) {
diff --git a/components/crash/content/app/crashpad_linux.cc b/components/crash/content/app/crashpad_linux.cc
index 6244bfe..365b1fd 100644
--- a/components/crash/content/app/crashpad_linux.cc
+++ b/components/crash/content/app/crashpad_linux.cc
@@ -4,6 +4,7 @@
 
 #include "components/crash/content/app/crashpad.h"
 
+#include <dlfcn.h>
 #include <string.h>
 #include <sys/socket.h>
 #include <sys/types.h>
@@ -246,6 +247,33 @@
   }
 }
 
+// Constructs paths to a handler trampoline executable and a library exporting
+// the symbol `CrashpadHandlerMain()`. This requires this function to be built
+// into the same object exporting this symbol and the handler trampoline is
+// adjacent to it.
+bool GetHandlerTrampoline(std::string* handler_trampoline,
+                          std::string* handler_library) {
+  Dl_info info;
+  if (dladdr(reinterpret_cast<void*>(&GetHandlerTrampoline), &info) == 0) {
+    return false;
+  }
+
+  std::string local_handler_library(info.dli_fname);
+
+  size_t libdir_end = local_handler_library.rfind('/');
+  if (libdir_end == std::string::npos) {
+    return false;
+  }
+
+  std::string local_handler_trampoline(local_handler_library, 0,
+                                       libdir_end + 1);
+  local_handler_trampoline += "libcrashpad_handler_trampoline.so";
+
+  handler_trampoline->swap(local_handler_trampoline);
+  handler_library->swap(local_handler_library);
+  return true;
+}
+
 #if defined(__arm__) && defined(__ARM_ARCH_7A__)
 #define CURRENT_ABI "armeabi-v7a"
 #elif defined(__arm__)
@@ -281,7 +309,8 @@
 
 // Copies and extends the current environment with CLASSPATH and LD_LIBRARY_PATH
 // set to library paths in the APK.
-bool BuildEnvironmentWithApk(std::vector<std::string>* result) {
+bool BuildEnvironmentWithApk(bool use_64_bit,
+                             std::vector<std::string>* result) {
   DCHECK(result->empty());
 
   std::string classpath;
@@ -299,6 +328,12 @@
   env->GetVar(kLdLibraryPathVar, &current_library_path);
   library_path += ":" + current_library_path;
 
+  static constexpr char kRuntimeRootVar[] = "ANDROID_RUNTIME_ROOT";
+  std::string runtime_root;
+  if (env->GetVar(kRuntimeRootVar, &runtime_root)) {
+    library_path += ":" + runtime_root + (use_64_bit ? "/lib64" : "/lib");
+  }
+
   result->push_back("CLASSPATH=" + classpath);
   result->push_back("LD_LIBRARY_PATH=" + library_path);
   for (char** envp = environ; *envp != nullptr; ++envp) {
@@ -414,6 +449,19 @@
 }
 
 class HandlerStarter {
+#if defined(OS_ANDROID)
+  // TODO(jperaza): Currently only launching a same-bitness handler is
+  // supported. The logic to build package paths, locate a handler executable,
+  // and the crashpad client interface for launching a Java handler need to be
+  // updated to use a specified bitness before a cross-bitness handler can be
+  // used.
+#if defined(ARCH_CPU_64_BITS)
+  static constexpr bool kUse64Bit = true;
+#else
+  static constexpr bool kUse64Bit = false;
+#endif
+#endif  // OS_ANDROID
+
  public:
   static HandlerStarter* Get() {
     static HandlerStarter* instance = new HandlerStarter();
@@ -443,25 +491,35 @@
 
 #if defined(OS_ANDROID)
     if (!base::PathExists(handler_path)) {
-      use_java_handler_ = true;
+      // The linker doesn't support loading executables passed on its command
+      // line until Q.
+      if (base::android::BuildInfo::GetInstance()->is_at_least_q()) {
+        bool found_library =
+            GetHandlerTrampoline(&handler_trampoline_, &handler_library_);
+        DCHECK(found_library);
+      } else {
+        use_java_handler_ = true;
+      }
     }
 
     if (!dump_at_crash) {
       return database_path;
     }
 
-    if (use_java_handler_) {
+    if (use_java_handler_ || !handler_trampoline_.empty()) {
       std::vector<std::string> env;
-      if (!BuildEnvironmentWithApk(&env)) {
+      if (!BuildEnvironmentWithApk(kUse64Bit, &env)) {
         return database_path;
       }
 
-      // TODO(jperaza): The logic for constructing an appropriate
-      // CLASSPATH/LD_LIBRARY_PATH won't work for Android Q+. The handler will
-      // need to be launched by executing the dynamic linker instead.
-      bool result = GetCrashpadClient().StartJavaHandlerAtCrash(
-          kCrashpadJavaMain, &env, database_path, metrics_path, url,
-          process_annotations, arguments);
+      bool result = use_java_handler_
+                        ? GetCrashpadClient().StartJavaHandlerAtCrash(
+                              kCrashpadJavaMain, &env, database_path,
+                              metrics_path, url, process_annotations, arguments)
+                        : GetCrashpadClient().StartHandlerWithLinkerAtCrash(
+                              handler_trampoline_, handler_library_, kUse64Bit,
+                              &env, database_path, metrics_path, url,
+                              process_annotations, arguments);
       DCHECK(result);
       return database_path;
     }
@@ -501,18 +559,21 @@
     }
 
 #if defined(OS_ANDROID)
-    if (use_java_handler_) {
+    if (use_java_handler_ || !handler_trampoline_.empty()) {
       std::vector<std::string> env;
-      if (!BuildEnvironmentWithApk(&env)) {
+      if (!BuildEnvironmentWithApk(kUse64Bit, &env)) {
         return false;
       }
 
-      // TODO(jperaza): The logic for constructing an appropriate
-      // CLASSPATH/LD_LIBRARY_PATH won't work for Android Q+. The handler will
-      // need to be launched by executing the dynamic linker instead.
-      bool result = GetCrashpadClient().StartJavaHandlerForClient(
-          kCrashpadJavaMain, &env, database_path, metrics_path, url,
-          process_annotations, arguments, fd);
+      bool result =
+          use_java_handler_
+              ? GetCrashpadClient().StartJavaHandlerForClient(
+                    kCrashpadJavaMain, &env, database_path, metrics_path, url,
+                    process_annotations, arguments, fd)
+              : GetCrashpadClient().StartHandlerWithLinkerForClient(
+                    handler_trampoline_, handler_library_, kUse64Bit, &env,
+                    database_path, metrics_path, url, process_annotations,
+                    arguments, fd);
       return result;
     }
 #endif
@@ -532,6 +593,8 @@
 
   crashpad::SanitizationInformation browser_sanitization_info_;
 #if defined(OS_ANDROID)
+  std::string handler_trampoline_;
+  std::string handler_library_;
   bool use_java_handler_ = false;
 #endif
 
diff --git a/components/download/internal/common/android/download_collection_bridge.cc b/components/download/internal/common/android/download_collection_bridge.cc
index d2d17b76..113dc49 100644
--- a/components/download/internal/common/android/download_collection_bridge.cc
+++ b/components/download/internal/common/android/download_collection_bridge.cc
@@ -108,4 +108,11 @@
   return base::File(fd);
 }
 
+// static
+bool DownloadCollectionBridge::FileNameExists(const base::FilePath& file_name) {
+  JNIEnv* env = base::android::AttachCurrentThread();
+  ScopedJavaLocalRef<jstring> jfile_name =
+      ConvertUTF8ToJavaString(env, file_name.value());
+  return Java_DownloadCollectionBridge_fileNameExists(env, jfile_name);
+}
 }  // namespace download
diff --git a/components/download/internal/common/android/download_collection_bridge.h b/components/download/internal/common/android/download_collection_bridge.h
index 38f3fcf..2cfdfdef 100644
--- a/components/download/internal/common/android/download_collection_bridge.h
+++ b/components/download/internal/common/android/download_collection_bridge.h
@@ -43,6 +43,9 @@
   // Opens the intermediate Uri for writing.
   static base::File OpenIntermediateUri(const base::FilePath& intermediate_uri);
 
+  // Checks whether a file name exists.
+  static bool FileNameExists(const base::FilePath& file_name);
+
  private:
   DISALLOW_COPY_AND_ASSIGN(DownloadCollectionBridge);
 };
diff --git a/components/download/internal/common/android/java/src/org/chromium/components/download/DownloadCollectionBridge.java b/components/download/internal/common/android/java/src/org/chromium/components/download/DownloadCollectionBridge.java
index ccb4ba9..0df8624 100644
--- a/components/download/internal/common/android/java/src/org/chromium/components/download/DownloadCollectionBridge.java
+++ b/components/download/internal/common/android/java/src/org/chromium/components/download/DownloadCollectionBridge.java
@@ -10,7 +10,6 @@
 
 import org.chromium.base.ContextUtils;
 import org.chromium.base.Log;
-import org.chromium.base.ThreadUtils;
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.annotations.JNINamespace;
 
@@ -22,14 +21,17 @@
     // Singleton instance that allows embedders to replace their implementation.
     private static DownloadCollectionBridge sDownloadCollectionBridge;
     private static final String TAG = "DownloadCollection";
+    // Guards access to sDownloadCollectionBridge.
+    private static final Object sLock = new Object();
 
     /**
      * Return getDownloadCollectionBridge singleton.
      */
     public static DownloadCollectionBridge getDownloadCollectionBridge() {
-        ThreadUtils.assertOnUiThread();
-        if (sDownloadCollectionBridge == null) {
-            sDownloadCollectionBridge = new DownloadCollectionBridge();
+        synchronized (sLock) {
+            if (sDownloadCollectionBridge == null) {
+                sDownloadCollectionBridge = new DownloadCollectionBridge();
+            }
         }
         return sDownloadCollectionBridge;
     }
@@ -38,8 +40,9 @@
      * Sets the singlton object to use later.
      */
     public static void setDownloadCollectionBridge(DownloadCollectionBridge bridge) {
-        ThreadUtils.assertOnUiThread();
-        sDownloadCollectionBridge = bridge;
+        synchronized (sLock) {
+            sDownloadCollectionBridge = bridge;
+        }
     }
 
     /**
@@ -90,6 +93,13 @@
     }
 
     /**
+     * @return whether a download with the file name exists.
+     */
+    protected boolean checkFileNameExists(final String fileName) {
+        return false;
+    }
+
+    /**
      * Creates an intermediate URI for download to be written into. On completion, call
      * nativeOnCreateIntermediateUriResult() with |callbackId|.
      * @param fileName Name of the file.
@@ -164,4 +174,12 @@
         }
         return -1;
     }
+
+    /**
+     * @return whether a download with the file name exists.
+     */
+    @CalledByNative
+    private static boolean fileNameExists(final String fileName) {
+        return getDownloadCollectionBridge().checkFileNameExists(fileName);
+    }
 }
diff --git a/components/download/internal/common/download_path_reservation_tracker.cc b/components/download/internal/common/download_path_reservation_tracker.cc
index 93bf59b..b5eccbd 100644
--- a/components/download/internal/common/download_path_reservation_tracker.cc
+++ b/components/download/internal/common/download_path_reservation_tracker.cc
@@ -31,6 +31,10 @@
 #include "net/base/filename_util.h"
 #include "url/gurl.h"
 
+#if defined(OS_ANDROID)
+#include "components/download/internal/common/android/download_collection_bridge.h"
+#endif
+
 namespace download {
 
 namespace {
@@ -103,6 +107,21 @@
   return false;
 }
 
+// Returns true if the given file name is in use by any path reservation or the
+// file system. Called on the task runner returned by
+// DownloadPathReservationTracker::GetTaskRunner().
+bool IsFileNameInUse(const base::FilePath& path) {
+#if defined(OS_ANDROID)
+  // If there is a reservation, then the path is in use.
+  if (IsPathReserved(path.BaseName()))
+    return true;
+
+  if (DownloadCollectionBridge::FileNameExists(path.BaseName()))
+    return true;
+#endif
+  return false;
+}
+
 // Returns true if the given path is in use by any path reservation or the
 // file system. Called on the task runner returned by
 // DownloadPathReservationTracker::GetTaskRunner().
@@ -120,10 +139,12 @@
 
 // Create a unique filename by appending a uniquifier. Modifies |path| in place
 // if successful and returns true. Otherwise |path| is left unmodified and
-// returns false.
+// returns false. If |check_file_name_only| is true, this method will only check
+// the name of the file to guarantee that it is unique.
 bool CreateUniqueFilename(int max_path_component_length,
                           const base::Time& download_start_time,
-                          base::FilePath* path) {
+                          base::FilePath* path,
+                          bool check_file_name_only) {
   // Try every numeric uniquifier. Then make one attempt with the timestamp.
   for (int uniquifier = 1;
        uniquifier <= DownloadPathReservationTracker::kMaxUniqueFiles + 1;
@@ -164,11 +185,13 @@
     }
     path_to_check = path_to_check.InsertBeforeExtensionASCII(suffix);
 
-    if (!IsPathInUse(path_to_check)) {
+    if ((check_file_name_only && !IsFileNameInUse(path_to_check)) ||
+        (!check_file_name_only && !IsPathInUse(path_to_check))) {
       *path = path_to_check;
       return true;
     }
   }
+
   return false;
 }
 
@@ -198,6 +221,32 @@
          info.temporary_path.DirName() == target_path.DirName();
 }
 
+// Called when reservation conflicts happen. Returns the result on whether the
+// conflict can be resolved, and uniquifying the file name if necessary. If
+// |check_file_name_only| is true, this method will only check the name of the
+// file to guarantee that it is unique.
+PathValidationResult ResolveReservationConflicts(
+    const CreateReservationInfo& info,
+    int max_path_component_length,
+    base::FilePath* target_path,
+    bool check_file_name_only) {
+  switch (info.conflict_action) {
+    case DownloadPathReservationTracker::UNIQUIFY:
+      return CreateUniqueFilename(max_path_component_length, info.start_time,
+                                  target_path, check_file_name_only)
+                 ? PathValidationResult::SUCCESS
+                 : PathValidationResult::CONFLICT;
+
+    case DownloadPathReservationTracker::OVERWRITE:
+      return PathValidationResult::SUCCESS;
+
+    case DownloadPathReservationTracker::PROMPT:
+      return PathValidationResult::CONFLICT;
+  }
+  NOTREACHED();
+  return PathValidationResult::SUCCESS;
+}
+
 // Verify that |target_path| can be written to and also resolve any conflicts if
 // necessary by uniquifying the filename.
 PathValidationResult ValidatePathAndResolveConflicts(
@@ -239,21 +288,8 @@
   if (!IsPathInUse(*target_path))
     return PathValidationResult::SUCCESS;
 
-  switch (info.conflict_action) {
-    case DownloadPathReservationTracker::UNIQUIFY:
-      return CreateUniqueFilename(max_path_component_length, info.start_time,
-                                  target_path)
-                 ? PathValidationResult::SUCCESS
-                 : PathValidationResult::CONFLICT;
-
-    case DownloadPathReservationTracker::OVERWRITE:
-      return PathValidationResult::SUCCESS;
-
-    case DownloadPathReservationTracker::PROMPT:
-      return PathValidationResult::CONFLICT;
-  }
-  NOTREACHED();
-  return PathValidationResult::SUCCESS;
+  return ResolveReservationConflicts(info, max_path_component_length,
+                                     target_path, false);
 }
 
 // Called on the task runner returned by
@@ -288,6 +324,22 @@
   base::FilePath target_dir = target_path.DirName();
   base::FilePath filename = target_path.BaseName();
 
+#if defined(OS_ANDROID)
+  if (DownloadCollectionBridge::ShouldPublishDownload(target_path)) {
+    // If the download is written to a content URI, put file name in the
+    // reservation map as content URIs will always be different.
+    PathValidationResult result = PathValidationResult::SUCCESS;
+    if (IsFileNameInUse(filename)) {
+      int max_path_component_length =
+          base::GetMaximumPathComponentLength(target_path.DirName());
+      result = ResolveReservationConflicts(info, max_path_component_length,
+                                           &target_path, true);
+    }
+    (*g_reservation_map)[info.key] = target_path.BaseName();
+    *reserved_path = target_path;
+    return result;
+  }
+#endif
   // Create target_dir if necessary and appropriate. target_dir may be the last
   // directory that the user selected in a FilePicker; if that directory has
   // since been removed, do NOT automatically re-create it. Only automatically
@@ -342,9 +394,19 @@
   callback.Run(result, *reserved_path);
 }
 
+// Gets the path reserved in the global |g_reservation_map|. For content Uri,
+// file name instead of file path is used.
+base::FilePath GetReservationPath(DownloadItem* download_item) {
+#if defined(OS_ANDROID)
+  if (download_item->GetTargetFilePath().IsContentUri())
+    return download_item->GetFileNameToReportUser();
+#endif
+  return download_item->GetTargetFilePath();
+}
+
 DownloadItemObserver::DownloadItemObserver(DownloadItem* download_item)
     : download_item_(download_item),
-      last_target_path_(download_item->GetTargetFilePath()) {
+      last_target_path_(GetReservationPath(download_item)) {
   download_item_->AddObserver(this);
   download_item_->SetUserData(&kUserDataKey, base::WrapUnique(this));
 }
@@ -360,7 +422,7 @@
   switch (download->GetState()) {
     case DownloadItem::IN_PROGRESS: {
       // Update the reservation.
-      base::FilePath new_target_path = download->GetTargetFilePath();
+      base::FilePath new_target_path = GetReservationPath(download);
       if (new_target_path != last_target_path_) {
         DownloadPathReservationTracker::GetTaskRunner()->PostTask(
             FROM_HERE,
diff --git a/components/exo/gaming_seat_unittest.cc b/components/exo/gaming_seat_unittest.cc
index 922adcb3..2ebac9a 100644
--- a/components/exo/gaming_seat_unittest.cc
+++ b/components/exo/gaming_seat_unittest.cc
@@ -27,8 +27,8 @@
   MOCK_CONST_METHOD1(CanAcceptGamepadEventsForSurface, bool(Surface*));
   MOCK_METHOD0(GamepadAdded, GamepadDelegate*());
   MOCK_METHOD0(Die, void());
-  void OnGamingSeatDestroying(GamingSeat*) override { delete this; };
-  ~MockGamingSeatDelegate() { Die(); };
+  void OnGamingSeatDestroying(GamingSeat*) override { delete this; }
+  ~MockGamingSeatDelegate() { Die(); }
 };
 
 class MockGamepadDelegate : public GamepadDelegate {
diff --git a/components/exo/test/test_client_controlled_state_delegate.cc b/components/exo/test/test_client_controlled_state_delegate.cc
index 2a8f35b0..58990a4 100644
--- a/components/exo/test/test_client_controlled_state_delegate.cc
+++ b/components/exo/test/test_client_controlled_state_delegate.cc
@@ -84,7 +84,7 @@
         return base::WrapUnique<ash::wm::ClientControlledState::Delegate>(
             new TestClientControlledStateDelegate());
       }));
-};
+}
 
 // static
 void TestClientControlledStateDelegate::UninstallFactory() {
diff --git a/components/exo/wayland/clients/client_helper.cc b/components/exo/wayland/clients/client_helper.cc
index 29531c72..2b8e00e 100644
--- a/components/exo/wayland/clients/client_helper.cc
+++ b/components/exo/wayland/clients/client_helper.cc
@@ -54,7 +54,7 @@
                 zwp_linux_buffer_release_v1_destroy)
 DEFAULT_DELETER(zwp_fullscreen_shell_v1, zwp_fullscreen_shell_v1_destroy)
 DEFAULT_DELETER(zwp_input_timestamps_manager_v1,
-                zwp_input_timestamps_manager_v1_destroy);
+                zwp_input_timestamps_manager_v1_destroy)
 DEFAULT_DELETER(zwp_input_timestamps_v1, zwp_input_timestamps_v1_destroy)
 DEFAULT_DELETER(zwp_linux_buffer_params_v1, zwp_linux_buffer_params_v1_destroy)
 DEFAULT_DELETER(zwp_linux_dmabuf_v1, zwp_linux_dmabuf_v1_destroy)
diff --git a/components/image_fetcher/OWNERS b/components/image_fetcher/OWNERS
index e2501f1..860cdf7 100644
--- a/components/image_fetcher/OWNERS
+++ b/components/image_fetcher/OWNERS
@@ -1,5 +1,6 @@
 fgorski@chromium.org
 markusheintz@chromium.org
 treib@chromium.org
+wylieb@chromium.org
 
 # COMPONENT: Internals>Images
diff --git a/components/metrics/call_stack_profile_builder.cc b/components/metrics/call_stack_profile_builder.cc
index f176a2e..9a0c48e 100644
--- a/components/metrics/call_stack_profile_builder.cc
+++ b/components/metrics/call_stack_profile_builder.cc
@@ -91,7 +91,7 @@
     // keep the frame information even if its module is invalid so we have
     // visibility into how often this issue is happening on the server.
     CallStackProfile::Location* location = stack.add_frame();
-    if (!frame.module->is_valid)
+    if (!frame.module)
       continue;
 
     // Dedup modules.
diff --git a/components/metrics/call_stack_profile_builder_unittest.cc b/components/metrics/call_stack_profile_builder_unittest.cc
index 7481a5c..59f159b 100644
--- a/components/metrics/call_stack_profile_builder_unittest.cc
+++ b/components/metrics/call_stack_profile_builder_unittest.cc
@@ -251,8 +251,8 @@
       std::make_unique<TestingCallStackProfileBuilder>(kProfileParams);
 
   const uintptr_t module_base_address1 = 0x1000;
-  Module module1;  // module1 has no information hence invalid.
-  Frame frame1 = {module_base_address1 + 0x10, &module1};
+  // A frame with no module.
+  Frame frame1 = {module_base_address1 + 0x10, nullptr};
 
   const uintptr_t module_base_address2 = 0x1100;
 #if defined(OS_WIN)
diff --git a/components/offline_items_collection/core/BUILD.gn b/components/offline_items_collection/core/BUILD.gn
index 430c73c..e3a5122 100644
--- a/components/offline_items_collection/core/BUILD.gn
+++ b/components/offline_items_collection/core/BUILD.gn
@@ -21,6 +21,7 @@
     "offline_item_filter.h",
     "offline_item_state.h",
     "pending_state.h",
+    "rename_result.h",
     "throttled_offline_content_provider.cc",
     "throttled_offline_content_provider.h",
   ]
@@ -118,6 +119,7 @@
       "offline_item_filter.h",
       "offline_item_state.h",
       "pending_state.h",
+      "rename_result.h",
     ]
   }
 }
diff --git a/components/offline_items_collection/core/rename_result.h b/components/offline_items_collection/core/rename_result.h
new file mode 100644
index 0000000..3b47c8e
--- /dev/null
+++ b/components/offline_items_collection/core/rename_result.h
@@ -0,0 +1,19 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_OFFLINE_ITEMS_COLLECTION_CORE_RENAME_RESULT_H_
+#define COMPONENTS_OFFLINE_ITEMS_COLLECTION_CORE_RENAME_RESULT_H_
+
+// The type of download rename dialog that should by shown by Android.
+// A Java counterpart will be generated for this enum.
+// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.components.offline_items_collection
+enum class RenameResult {
+  SUCCESS = 0,                // Rename filename successfully
+  FAILURE_NAME_CONFLICT = 1,  // Filename already exists
+  FAILURE_NAME_TOO_LONG = 2,  // Illegal file name: too long
+  FAILURE_UNKNOWN = 3,        // Unknown
+  kMaxValue = FAILURE_UNKNOWN
+};
+
+#endif  // COMPONENTS_OFFLINE_ITEMS_COLLECTION_CORE_RENAME_RESULT_H_
diff --git a/components/omnibox/browser/BUILD.gn b/components/omnibox/browser/BUILD.gn
index 594d5b84..1d20ae5 100644
--- a/components/omnibox/browser/BUILD.gn
+++ b/components/omnibox/browser/BUILD.gn
@@ -51,6 +51,7 @@
     "open_in_new.icon",
     "page.icon",
     "pedal.icon",
+    "plus.icon",
     "product.icon",
     "star_active.icon",
     "star.icon",
diff --git a/components/omnibox/browser/vector_icons/plus.icon b/components/omnibox/browser/vector_icons/plus.icon
new file mode 100644
index 0000000..5fbcd9f
--- /dev/null
+++ b/components/omnibox/browser/vector_icons/plus.icon
@@ -0,0 +1,21 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+CANVAS_DIMENSIONS, 16,
+CIRCLE, 8, 8, 6.5,
+CIRCLE, 8, 8, 5,
+MOVE_TO, 4.7f, 7.2f,
+R_H_LINE_TO, 2.5,
+R_V_LINE_TO, -2.5,
+R_H_LINE_TO, 1.4,
+R_V_LINE_TO, 2.5,
+R_H_LINE_TO, 2.5,
+R_V_LINE_TO, 1.4,
+R_H_LINE_TO, -2.5,
+R_V_LINE_TO, 2.5,
+R_H_LINE_TO, -1.4,
+R_V_LINE_TO, -2.5,
+R_H_LINE_TO, -2.5,
+R_V_LINE_TO, -1.4,
+CLOSE
diff --git a/components/optimization_guide/optimization_guide_service.h b/components/optimization_guide/optimization_guide_service.h
index 92b8fbb0..a971643 100644
--- a/components/optimization_guide/optimization_guide_service.h
+++ b/components/optimization_guide/optimization_guide_service.h
@@ -40,13 +40,13 @@
   // Virtual so it can be mocked out in tests.
   virtual void MaybeUpdateHintsComponent(const HintsComponentInfo& info);
 
- private:
   // If the hints component version in |info| is greater than that in
   // |hints_component_info_|, updates |hints_component_info_| and dispatches it
   // to all observers. In the case where the version is not greater, it does
   // nothing.
   void MaybeUpdateHintsComponentOnUIThread(const HintsComponentInfo& info);
 
+ private:
   // Runner for indexing tasks.
   SEQUENCE_CHECKER(sequence_checker_);
 
diff --git a/components/password_manager/core/browser/credentials_filter.h b/components/password_manager/core/browser/credentials_filter.h
index f65c1fb..13b83d6 100644
--- a/components/password_manager/core/browser/credentials_filter.h
+++ b/components/password_manager/core/browser/credentials_filter.h
@@ -19,11 +19,6 @@
   CredentialsFilter() {}
   virtual ~CredentialsFilter() {}
 
-  // Removes from |results| all forms which should be ignored for any password
-  // manager-related purposes, and returns the rest.
-  virtual std::vector<std::unique_ptr<autofill::PasswordForm>> FilterResults(
-      std::vector<std::unique_ptr<autofill::PasswordForm>> results) const = 0;
-
   // Should |form| be offered to be saved?
   virtual bool ShouldSave(const autofill::PasswordForm& form) const = 0;
 
diff --git a/components/password_manager/core/browser/form_fetcher_impl.cc b/components/password_manager/core/browser/form_fetcher_impl.cc
index b1a6672a..cbc8c0a 100644
--- a/components/password_manager/core/browser/form_fetcher_impl.cc
+++ b/components/password_manager/core/browser/form_fetcher_impl.cc
@@ -320,9 +320,6 @@
 
   const size_t original_count = non_federated_.size();
 
-  non_federated_ =
-      client_->GetStoreResultFilter()->FilterResults(std::move(non_federated_));
-
   filtered_count_ = original_count - non_federated_.size();
 
   weak_non_federated_ = MakeWeakCopies(non_federated_);
diff --git a/components/password_manager/core/browser/form_fetcher_impl_unittest.cc b/components/password_manager/core/browser/form_fetcher_impl_unittest.cc
index d0975d27..d588682 100644
--- a/components/password_manager/core/browser/form_fetcher_impl_unittest.cc
+++ b/components/password_manager/core/browser/form_fetcher_impl_unittest.cc
@@ -75,14 +75,6 @@
 
   ~NameFilter() override = default;
 
-  std::vector<std::unique_ptr<PasswordForm>> FilterResults(
-      std::vector<std::unique_ptr<PasswordForm>> results) const override {
-    base::EraseIf(results, [this](const std::unique_ptr<PasswordForm>& form) {
-      return !ShouldSave(*form);
-    });
-    return results;
-  }
-
   bool ShouldSave(const PasswordForm& form) const override {
     return form.username_value != name_;
   }
@@ -381,11 +373,12 @@
   results.push_back(std::make_unique<PasswordForm>(federated));
   results.push_back(std::make_unique<PasswordForm>(non_federated1));
   results.push_back(std::make_unique<PasswordForm>(non_federated2));
-  // Non-federated results should have been filtered: no "user" here.
-  constexpr size_t kNumFiltered = 1u;
+  // Expect that nothing got filtered out, since CredentialsFilter no longer
+  // filters things out:
   EXPECT_CALL(consumer_,
-              ProcessMatches(UnorderedElementsAre(Pointee(non_federated2)),
-                             kNumFiltered));
+              ProcessMatches(UnorderedElementsAre(Pointee(non_federated1),
+                                                  Pointee(non_federated2)),
+                             0U));
   form_fetcher_->OnGetPasswordStoreResults(std::move(results));
   EXPECT_EQ(FormFetcher::State::NOT_WAITING, form_fetcher_->GetState());
   // However, federated results should not be filtered.
diff --git a/components/password_manager/core/browser/stub_credentials_filter.cc b/components/password_manager/core/browser/stub_credentials_filter.cc
index 7d47155..e00176f 100644
--- a/components/password_manager/core/browser/stub_credentials_filter.cc
+++ b/components/password_manager/core/browser/stub_credentials_filter.cc
@@ -10,13 +10,6 @@
 
 StubCredentialsFilter::~StubCredentialsFilter() = default;
 
-std::vector<std::unique_ptr<autofill::PasswordForm>>
-StubCredentialsFilter::FilterResults(
-    std::vector<std::unique_ptr<autofill::PasswordForm>> results) const {
-  FilterResultsPtr(&results);
-  return results;
-}
-
 bool StubCredentialsFilter::ShouldSave(
     const autofill::PasswordForm& form) const {
   return true;
@@ -40,7 +33,4 @@
   return false;
 }
 
-void StubCredentialsFilter::FilterResultsPtr(
-    std::vector<std::unique_ptr<autofill::PasswordForm>>* results) const {}
-
 }  // namespace password_manager
diff --git a/components/password_manager/core/browser/stub_credentials_filter.h b/components/password_manager/core/browser/stub_credentials_filter.h
index f56d01f4..4a6d98e 100644
--- a/components/password_manager/core/browser/stub_credentials_filter.h
+++ b/components/password_manager/core/browser/stub_credentials_filter.h
@@ -19,9 +19,6 @@
   ~StubCredentialsFilter() override;
 
   // CredentialsFilter
-  std::vector<std::unique_ptr<autofill::PasswordForm>> FilterResults(
-      std::vector<std::unique_ptr<autofill::PasswordForm>> results)
-      const override;
   bool ShouldSave(const autofill::PasswordForm& form) const override;
   bool ShouldSaveGaiaPasswordHash(
       const autofill::PasswordForm& form) const override;
@@ -31,12 +28,6 @@
       const PasswordFormManagerInterface& form_manager) const override;
   bool IsSyncAccountEmail(const std::string& username) const override;
 
-  // A version of FilterResult without moveable arguments, which cannot be
-  // mocked in GMock. StubCredentialsFilter::FilterResults(arg) calls
-  // FilterResultsPtr(&arg).
-  virtual void FilterResultsPtr(
-      std::vector<std::unique_ptr<autofill::PasswordForm>>* results) const;
-
  private:
   DISALLOW_COPY_AND_ASSIGN(StubCredentialsFilter);
 };
diff --git a/components/password_manager/core/browser/sync_credentials_filter.cc b/components/password_manager/core/browser/sync_credentials_filter.cc
index f839024..963ec6d3 100644
--- a/components/password_manager/core/browser/sync_credentials_filter.cc
+++ b/components/password_manager/core/browser/sync_credentials_filter.cc
@@ -21,24 +21,6 @@
 
 namespace password_manager {
 
-namespace {
-
-// Returns true if the last loaded page was for transactional re-auth on a
-// Google property.
-bool LastLoadWasTransactionalReauthPage(const GURL& last_load_url) {
-  if (last_load_url.GetOrigin() !=
-      GaiaUrls::GetInstance()->gaia_url().GetOrigin())
-    return false;
-
-  // TODO(crbug.com/543085): GAIA stops using the "rart" URL param, and instead
-  // includes a hidden form field with name "rart". "rart" is the transactional
-  // reauth paramter.
-  std::string ignored_value;
-  return net::GetValueForKeyInQuery(last_load_url, "rart", &ignored_value);
-}
-
-}  // namespace
-
 SyncCredentialsFilter::SyncCredentialsFilter(
     const PasswordManagerClient* client,
     SyncServiceFactoryFunction sync_service_factory_function,
@@ -49,32 +31,6 @@
 
 SyncCredentialsFilter::~SyncCredentialsFilter() {}
 
-std::vector<std::unique_ptr<PasswordForm>> SyncCredentialsFilter::FilterResults(
-    std::vector<std::unique_ptr<PasswordForm>> results) const {
-  const AutofillForSyncCredentialsState autofill_sync_state =
-      GetAutofillForSyncCredentialsState();
-
-  if (autofill_sync_state != DISALLOW_SYNC_CREDENTIALS &&
-      (autofill_sync_state != DISALLOW_SYNC_CREDENTIALS_FOR_REAUTH ||
-       !LastLoadWasTransactionalReauthPage(
-           client_->GetLastCommittedEntryURL()))) {
-    return results;
-  }
-
-  auto begin_of_removed =
-      std::partition(results.begin(), results.end(),
-                     [this](const std::unique_ptr<PasswordForm>& form) {
-                       return ShouldSave(*form);
-                     });
-
-  UMA_HISTOGRAM_BOOLEAN("PasswordManager.SyncCredentialFiltered",
-                        begin_of_removed != results.end());
-
-  results.erase(begin_of_removed, results.end());
-
-  return results;
-}
-
 bool SyncCredentialsFilter::ShouldSave(
     const autofill::PasswordForm& form) const {
   return !client_->IsIncognito() &&
@@ -118,37 +74,4 @@
   }
 }
 
-// static
-SyncCredentialsFilter::AutofillForSyncCredentialsState
-SyncCredentialsFilter::GetAutofillForSyncCredentialsState() {
-  bool protect_sync_credential_enabled =
-      base::FeatureList::IsEnabled(features::kProtectSyncCredential);
-  bool protect_sync_credential_on_reauth_enabled =
-      base::FeatureList::IsEnabled(features::kProtectSyncCredentialOnReauth);
-
-  if (protect_sync_credential_enabled) {
-    if (protect_sync_credential_on_reauth_enabled) {
-      // Both the features are enabled, do not ever fill the sync credential.
-      return DISALLOW_SYNC_CREDENTIALS;
-    }
-
-    // Only 'ProtectSyncCredentialOnReauth' feature is kept disabled. This
-    // is "illegal", emit a warning and do not ever fill the sync credential.
-    LOG(WARNING) << "This is illegal! Feature "
-                    "'ProtectSyncCredentialOnReauth' cannot be kept "
-                    "disabled if 'protect-sync-credential' feature is enabled. "
-                    "We shall not ever fill the sync credential is such cases.";
-    return DISALLOW_SYNC_CREDENTIALS;
-  }
-
-  if (protect_sync_credential_on_reauth_enabled) {
-    // Only 'ProtectSyncCredentialOnReauth' feature is kept enabled, fill
-    // the sync credential everywhere but on reauth.
-    return DISALLOW_SYNC_CREDENTIALS_FOR_REAUTH;
-  }
-
-  // Both the features are disabled, fill the sync credential everywhere.
-  return ALLOW_SYNC_CREDENTIALS;
-}
-
 }  // namespace password_manager
diff --git a/components/password_manager/core/browser/sync_credentials_filter.h b/components/password_manager/core/browser/sync_credentials_filter.h
index c1f08a7..09bfe3b 100644
--- a/components/password_manager/core/browser/sync_credentials_filter.h
+++ b/components/password_manager/core/browser/sync_credentials_filter.h
@@ -41,9 +41,6 @@
   ~SyncCredentialsFilter() override;
 
   // CredentialsFilter
-  std::vector<std::unique_ptr<autofill::PasswordForm>> FilterResults(
-      std::vector<std::unique_ptr<autofill::PasswordForm>> results)
-      const override;
   bool ShouldSave(const autofill::PasswordForm& form) const override;
   bool ShouldSaveGaiaPasswordHash(
       const autofill::PasswordForm& form) const override;
@@ -54,15 +51,6 @@
   bool IsSyncAccountEmail(const std::string& username) const override;
 
  private:
-  enum AutofillForSyncCredentialsState {
-    ALLOW_SYNC_CREDENTIALS,
-    DISALLOW_SYNC_CREDENTIALS_FOR_REAUTH,
-    DISALLOW_SYNC_CREDENTIALS,
-  };
-
-  // Determines autofill state based on experiment and flag values.
-  static AutofillForSyncCredentialsState GetAutofillForSyncCredentialsState();
-
   const PasswordManagerClient* const client_;
 
   const SyncServiceFactoryFunction sync_service_factory_function_;
diff --git a/components/password_manager/core/browser/sync_credentials_filter_unittest.cc b/components/password_manager/core/browser/sync_credentials_filter_unittest.cc
index 925aad8a..a6ea831 100644
--- a/components/password_manager/core/browser/sync_credentials_filter_unittest.cc
+++ b/components/password_manager/core/browser/sync_credentials_filter_unittest.cc
@@ -15,9 +15,7 @@
 #include "base/macros.h"
 #include "base/stl_util.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/test/metrics/histogram_tester.h"
 #include "base/test/metrics/user_action_tester.h"
-#include "base/test/scoped_feature_list.h"
 #include "components/autofill/core/common/password_form.h"
 #include "components/password_manager/core/browser/fake_form_fetcher.h"
 #include "components/password_manager/core/browser/mock_password_store.h"
@@ -30,7 +28,6 @@
 #include "components/password_manager/core/common/password_manager_features.h"
 #include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/testing_pref_service.h"
-#include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 #if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
@@ -50,19 +47,6 @@
 const char kEnterpriseURL[] = "https://enterprise.test/";
 #endif  // SYNC_PASSWORD_REUSE_DETECTION_ENABLED
 
-void DisallowSyncOnReauth(base::test::ScopedFeatureList* feature_list) {
-  feature_list->InitFromCommandLine(
-      features::kProtectSyncCredentialOnReauth.name,
-      features::kProtectSyncCredential.name);
-}
-
-void DisallowSync(base::test::ScopedFeatureList* feature_list) {
-  feature_list->InitFromCommandLine(
-      features::kProtectSyncCredential.name + std::string(",") +
-          features::kProtectSyncCredentialOnReauth.name,
-      std::string());
-}
-
 class FakePasswordManagerClient : public StubPasswordManagerClient {
  public:
   FakePasswordManagerClient()
@@ -114,25 +98,10 @@
   DISALLOW_COPY_AND_ASSIGN(FakePasswordManagerClient);
 };
 
-bool IsFormFiltered(const CredentialsFilter* filter, const PasswordForm& form) {
-  std::vector<std::unique_ptr<PasswordForm>> vector;
-  vector.push_back(std::make_unique<PasswordForm>(form));
-  vector = filter->FilterResults(std::move(vector));
-  return vector.empty();
-}
-
 }  // namespace
 
 class CredentialsFilterTest : public SyncUsernameTestBase {
  public:
-  struct TestCase {
-    enum { SYNCING_PASSWORDS, NOT_SYNCING_PASSWORDS } password_sync;
-    PasswordForm form;
-    const char* const last_committed_entry_url;
-    enum { FORM_FILTERED, FORM_NOT_FILTERED } is_form_filtered;
-    enum { NO_HISTOGRAM, HISTOGRAM_REPORTED } histogram_reported;
-  };
-
   // Flag for creating a PasswordFormManager, deciding its IsNewLogin() value.
   enum class LoginState { NEW, EXISTING };
 
@@ -154,24 +123,6 @@
     fetcher_.Fetch();
   }
 
-  void CheckFilterResultsTestCase(const TestCase& test_case) {
-    DCHECK(identity_manager()->HasPrimaryAccount());
-
-    SetSyncingPasswords(test_case.password_sync == TestCase::SYNCING_PASSWORDS);
-    client_.set_last_committed_entry_url(test_case.last_committed_entry_url);
-    base::HistogramTester tester;
-    const bool expected_is_form_filtered =
-        test_case.is_form_filtered == TestCase::FORM_FILTERED;
-    EXPECT_EQ(expected_is_form_filtered,
-              IsFormFiltered(&filter_, test_case.form));
-    if (test_case.histogram_reported == TestCase::HISTOGRAM_REPORTED) {
-      tester.ExpectUniqueSample("PasswordManager.SyncCredentialFiltered",
-                                expected_is_form_filtered, 1);
-    } else {
-      tester.ExpectTotalCount("PasswordManager.SyncCredentialFiltered", 0);
-    }
-  }
-
   // Makes |form_manager_| provisionally save |pending_|. Depending on
   // |login_state| being NEW or EXISTING, prepares |form_manager_| in a state in
   // which |pending_| looks like a new or existing credential, respectively.
@@ -196,149 +147,6 @@
   SyncCredentialsFilter filter_;
 };
 
-TEST_F(CredentialsFilterTest, FilterResults_AllowAll_NonSyncingAccount) {
-  FakeSigninAs("another_user@example.org");
-
-  CheckFilterResultsTestCase(
-      {TestCase::SYNCING_PASSWORDS, SimpleGaiaForm("user@example.org"),
-       "https://accounts.google.com/login?rart=123&continue=blah",
-       TestCase::FORM_NOT_FILTERED, TestCase::NO_HISTOGRAM});
-}
-
-TEST_F(CredentialsFilterTest, FilterResults_AllowAll_SyncingAccount) {
-  FakeSigninAs("user@example.org");
-
-  // By default, sync username is not filtered at all.
-  const TestCase kTestCases[] = {
-      // Reauth URL.
-      {TestCase::SYNCING_PASSWORDS, SimpleGaiaForm("user@example.org"),
-       "https://accounts.google.com/login?rart=123&continue=blah",
-       TestCase::FORM_NOT_FILTERED, TestCase::NO_HISTOGRAM},
-
-      // Slightly invalid reauth URL.
-      {TestCase::SYNCING_PASSWORDS, SimpleGaiaForm("user@example.org"),
-       "https://accounts.google.com/addlogin?rart",  // Missing rart value.
-       TestCase::FORM_NOT_FILTERED, TestCase::NO_HISTOGRAM},
-
-      // Non-reauth URL.
-      {TestCase::SYNCING_PASSWORDS, SimpleGaiaForm("user@example.org"),
-       "https://accounts.google.com/login?param=123",
-       TestCase::FORM_NOT_FILTERED, TestCase::NO_HISTOGRAM},
-
-      // Non-GAIA "reauth" URL.
-      {TestCase::SYNCING_PASSWORDS, SimpleNonGaiaForm("user@example.org"),
-       "https://site.com/login?rart=678", TestCase::FORM_NOT_FILTERED,
-       TestCase::NO_HISTOGRAM},
-  };
-
-  for (size_t i = 0; i < base::size(kTestCases); ++i) {
-    SCOPED_TRACE(testing::Message() << "i=" << i);
-    CheckFilterResultsTestCase(kTestCases[i]);
-  }
-}
-
-TEST_F(CredentialsFilterTest,
-       FilterResults_DisallowSyncOnReauth_NonSyncingAccount) {
-  FakeSigninAs("another_user@example.org");
-
-  // Only 'ProtectSyncCredentialOnReauth' feature is kept enabled, fill the
-  // sync credential everywhere but on reauth.
-  base::test::ScopedFeatureList scoped_feature_list;
-  DisallowSyncOnReauth(&scoped_feature_list);
-
-  CheckFilterResultsTestCase(
-      {TestCase::SYNCING_PASSWORDS, SimpleGaiaForm("user@example.org"),
-       "https://accounts.google.com/login?rart=123&continue=blah",
-       TestCase::FORM_NOT_FILTERED, TestCase::HISTOGRAM_REPORTED});
-}
-
-TEST_F(CredentialsFilterTest,
-       FilterResults_DisallowSyncOnReauth_SyncingAccount) {
-  FakeSigninAs("user@example.org");
-
-  // Only 'ProtectSyncCredentialOnReauth' feature is kept enabled, fill the
-  // sync credential everywhere but on reauth.
-  base::test::ScopedFeatureList scoped_feature_list;
-  DisallowSyncOnReauth(&scoped_feature_list);
-
-  const TestCase kTestCases[] = {
-      // Reauth URL.
-      {TestCase::SYNCING_PASSWORDS, SimpleGaiaForm("user@example.org"),
-       "https://accounts.google.com/login?rart=123&continue=blah",
-       TestCase::FORM_FILTERED, TestCase::HISTOGRAM_REPORTED},
-
-      // Slightly invalid reauth URL.
-      {TestCase::SYNCING_PASSWORDS, SimpleGaiaForm("user@example.org"),
-       "https://accounts.google.com/addlogin?rart",  // Missing rart value.
-       TestCase::FORM_FILTERED, TestCase::HISTOGRAM_REPORTED},
-
-      // Non-reauth URL.
-      {TestCase::SYNCING_PASSWORDS, SimpleGaiaForm("user@example.org"),
-       "https://accounts.google.com/login?param=123",
-       TestCase::FORM_NOT_FILTERED, TestCase::NO_HISTOGRAM},
-
-      // Non-GAIA "reauth" URL.
-      {TestCase::SYNCING_PASSWORDS, SimpleNonGaiaForm("user@example.org"),
-       "https://site.com/login?rart=678", TestCase::FORM_NOT_FILTERED,
-       TestCase::NO_HISTOGRAM},
-  };
-
-  for (size_t i = 0; i < base::size(kTestCases); ++i) {
-    SCOPED_TRACE(testing::Message() << "i=" << i);
-    CheckFilterResultsTestCase(kTestCases[i]);
-  }
-}
-
-TEST_F(CredentialsFilterTest, FilterResults_DisallowSync_NonSyncingAccount) {
-  FakeSigninAs("another_user@example.org");
-
-  // Both features are kept enabled, should cause sync credential to be
-  // filtered.
-  base::test::ScopedFeatureList scoped_feature_list;
-  DisallowSync(&scoped_feature_list);
-
-  CheckFilterResultsTestCase(
-      {TestCase::SYNCING_PASSWORDS, SimpleGaiaForm("user@example.org"),
-       "https://accounts.google.com/login?rart=123&continue=blah",
-       TestCase::FORM_NOT_FILTERED, TestCase::HISTOGRAM_REPORTED});
-}
-
-TEST_F(CredentialsFilterTest, FilterResults_DisallowSync_SyncingAccount) {
-  FakeSigninAs("user@example.org");
-
-  // Both features are kept enabled, should cause sync credential to be
-  // filtered.
-  base::test::ScopedFeatureList scoped_feature_list;
-  DisallowSync(&scoped_feature_list);
-
-  const TestCase kTestCases[] = {
-      // Reauth URL.
-      {TestCase::SYNCING_PASSWORDS, SimpleGaiaForm("user@example.org"),
-       "https://accounts.google.com/login?rart=123&continue=blah",
-       TestCase::FORM_FILTERED, TestCase::HISTOGRAM_REPORTED},
-
-      // Slightly invalid reauth URL.
-      {TestCase::SYNCING_PASSWORDS, SimpleGaiaForm("user@example.org"),
-       "https://accounts.google.com/addlogin?rart",  // Missing rart value.
-       TestCase::FORM_FILTERED, TestCase::HISTOGRAM_REPORTED},
-
-      // Non-reauth URL.
-      {TestCase::SYNCING_PASSWORDS, SimpleGaiaForm("user@example.org"),
-       "https://accounts.google.com/login?param=123", TestCase::FORM_FILTERED,
-       TestCase::HISTOGRAM_REPORTED},
-
-      // Non-GAIA "reauth" URL.
-      {TestCase::SYNCING_PASSWORDS, SimpleNonGaiaForm("user@example.org"),
-       "https://site.com/login?rart=678", TestCase::FORM_NOT_FILTERED,
-       TestCase::HISTOGRAM_REPORTED},
-  };
-
-  for (size_t i = 0; i < base::size(kTestCases); ++i) {
-    SCOPED_TRACE(testing::Message() << "i=" << i);
-    CheckFilterResultsTestCase(kTestCases[i]);
-  }
-}
-
 TEST_F(CredentialsFilterTest, ReportFormLoginSuccess_ExistingSyncCredentials) {
   FakeSigninAs("user@gmail.com");
   SetSyncingPasswords(true);
@@ -425,26 +233,6 @@
   EXPECT_TRUE(filter_.ShouldSave(form));
 }
 
-TEST_F(CredentialsFilterTest, ShouldFilterOneForm) {
-  // Both features are kept enabled, should cause sync credential to be
-  // filtered.
-  base::test::ScopedFeatureList scoped_feature_list;
-  DisallowSync(&scoped_feature_list);
-
-  std::vector<std::unique_ptr<PasswordForm>> results;
-  results.push_back(
-      std::make_unique<PasswordForm>(SimpleGaiaForm("test1@gmail.com")));
-  results.push_back(
-      std::make_unique<PasswordForm>(SimpleGaiaForm("test2@gmail.com")));
-
-  FakeSigninAs("test1@gmail.com");
-
-  results = filter_.FilterResults(std::move(results));
-
-  ASSERT_EQ(1u, results.size());
-  EXPECT_EQ(SimpleGaiaForm("test2@gmail.com"), *results[0]);
-}
-
 #if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
 TEST_F(CredentialsFilterTest, ShouldSaveGaiaPasswordHash) {
   PasswordForm gaia_form = SimpleGaiaForm("user@gmail.org");
diff --git a/components/password_manager/core/common/password_manager_features.cc b/components/password_manager/core/common/password_manager_features.cc
index 1284283..8c0e968 100644
--- a/components/password_manager/core/common/password_manager_features.cc
+++ b/components/password_manager/core/common/password_manager_features.cc
@@ -36,15 +36,6 @@
     "PasswordGenerationRequirementsDomainOverrides",
     base::FEATURE_ENABLED_BY_DEFAULT};
 
-// Disallow autofilling of the sync credential.
-const base::Feature kProtectSyncCredential = {
-    "protect-sync-credential", base::FEATURE_DISABLED_BY_DEFAULT};
-
-// Disallow autofilling of the sync credential only for transactional reauth
-// pages.
-const base::Feature kProtectSyncCredentialOnReauth = {
-    "ProtectSyncCredentialOnReauth", base::FEATURE_DISABLED_BY_DEFAULT};
-
 // Controls the ability to import passwords from Chrome's settings page.
 const base::Feature kPasswordImport = {"PasswordImport",
                                        base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/components/password_manager/core/common/password_manager_features.h b/components/password_manager/core/common/password_manager_features.h
index 2196b89d..c0e0db5 100644
--- a/components/password_manager/core/common/password_manager_features.h
+++ b/components/password_manager/core/common/password_manager_features.h
@@ -32,8 +32,6 @@
 extern const base::Feature kOnlyNewParser;
 extern const base::Feature kPasswordImport;
 extern const base::Feature kPasswordsKeyboardAccessory;
-extern const base::Feature kProtectSyncCredential;
-extern const base::Feature kProtectSyncCredentialOnReauth;
 extern const base::Feature kRecoverPasswordsForSyncUsers;
 
 // Field trial and corresponding parameters.
diff --git a/components/policy/core/common/cloud/cloud_policy_client.cc b/components/policy/core/common/cloud/cloud_policy_client.cc
index 0f42902..63cb402a 100644
--- a/components/policy/core/common/cloud/cloud_policy_client.cc
+++ b/components/policy/core/common/cloud/cloud_policy_client.cc
@@ -258,7 +258,8 @@
     const std::string& pem_certificate_chain,
     const std::string& client_id,
     const std::string& requisition,
-    const std::string& current_state_key) {
+    const std::string& current_state_key,
+    const std::string& sub_organization) {
   DCHECK(signing_service_);
   DCHECK(service_);
   DCHECK(!is_registered());
@@ -289,6 +290,12 @@
     request->mutable_license_type()->set_license_type(license_type);
   request->set_lifetime(lifetime);
 
+  if (!sub_organization.empty()) {
+    em::DeviceRegisterConfiguration* configuration =
+        data.mutable_device_register_configuration();
+    configuration->set_device_owner(sub_organization);
+  }
+
   signing_service_->SignData(
       data.SerializeAsString(),
       base::Bind(&CloudPolicyClient::OnRegisterWithCertificateRequestSigned,
diff --git a/components/policy/core/common/cloud/cloud_policy_client.h b/components/policy/core/common/cloud/cloud_policy_client.h
index cedbe388..f8487a72 100644
--- a/components/policy/core/common/cloud/cloud_policy_client.h
+++ b/components/policy/core/common/cloud/cloud_policy_client.h
@@ -150,7 +150,8 @@
       const std::string& pem_certificate_chain,
       const std::string& client_id,
       const std::string& requisition,
-      const std::string& current_state_key);
+      const std::string& current_state_key,
+      const std::string& sub_organization);
 
   // Attempts to enroll with the device management service using an enrollment
   // token. Results in a registration change or error notification.
diff --git a/components/policy/core/common/cloud/cloud_policy_client_unittest.cc b/components/policy/core/common/cloud/cloud_policy_client_unittest.cc
index 9402d28..e00ff4b 100644
--- a/components/policy/core/common/cloud/cloud_policy_client_unittest.cc
+++ b/components/policy/core/common/cloud/cloud_policy_client_unittest.cc
@@ -727,7 +727,7 @@
       em::DeviceRegisterRequest::FLAVOR_ENROLLMENT_ATTESTATION,
       em::DeviceRegisterRequest::LIFETIME_INDEFINITE,
       em::LicenseType::UNDEFINED, DMAuth::NoAuth(), kEnrollmentCertificate,
-      std::string(), std::string(), std::string());
+      std::string(), std::string(), std::string(), std::string());
   EXPECT_TRUE(client_->is_registered());
   EXPECT_FALSE(client_->GetPolicyFor(policy_type_, std::string()));
   EXPECT_EQ(DM_STATUS_SUCCESS, client_->status());
@@ -747,7 +747,7 @@
       em::DeviceRegisterRequest::FLAVOR_ENROLLMENT_ATTESTATION,
       em::DeviceRegisterRequest::LIFETIME_INDEFINITE,
       em::LicenseType::UNDEFINED, DMAuth::NoAuth(), kEnrollmentCertificate,
-      std::string(), std::string(), std::string());
+      std::string(), std::string(), std::string(), std::string());
   EXPECT_FALSE(client_->is_registered());
   EXPECT_EQ(DM_STATUS_CANNOT_SIGN_REQUEST, client_->status());
 }
diff --git a/components/policy/proto/device_management_backend.proto b/components/policy/proto/device_management_backend.proto
index a8b9f46..9a803d98 100644
--- a/components/policy/proto/device_management_backend.proto
+++ b/components/policy/proto/device_management_backend.proto
@@ -1642,6 +1642,12 @@
   optional SignedData signed_request = 1;
 }
 
+// Requested configuration to be passed along a registration request.
+message DeviceRegisterConfiguration {
+  // The device owner's email address.
+  optional string device_owner = 1;
+}
+
 message CertificateBasedDeviceRegistrationData {
   enum CertificateType {
     UNKNOWN = 0;
@@ -1659,8 +1665,8 @@
   optional bytes device_certificate = 2;
   // regular device registration request
   optional DeviceRegisterRequest device_register_request = 3;
-  // The device owner's email address.
-  optional string device_owner = 4;
+  // Additional configuration to register the device.
+  optional DeviceRegisterConfiguration device_register_configuration = 4;
 }
 
 // Request to enroll a Chrome browser. Fields match identically named fields
diff --git a/components/security_interstitials/content/security_interstitial_page.cc b/components/security_interstitials/content/security_interstitial_page.cc
index f81a05e..bebef31 100644
--- a/components/security_interstitials/content/security_interstitial_page.cc
+++ b/components/security_interstitials/content/security_interstitial_page.cc
@@ -66,6 +66,10 @@
   create_view_ = false;
 }
 
+bool SecurityInterstitialPage::ShouldDisplayURL() const {
+  return true;
+}
+
 std::string SecurityInterstitialPage::GetHTMLContents() {
   base::DictionaryValue load_time_data;
   PopulateInterstitialStrings(&load_time_data);
diff --git a/components/security_interstitials/content/security_interstitial_page.h b/components/security_interstitials/content/security_interstitial_page.h
index 0855d45..7450fb0 100644
--- a/components/security_interstitials/content/security_interstitial_page.h
+++ b/components/security_interstitials/content/security_interstitial_page.h
@@ -50,6 +50,10 @@
   // to e.g. update metrics.
   virtual void OnInterstitialClosing() = 0;
 
+  // Whether a URL should be displayed on this interstitial page. This is
+  // respected by committed interstitials only.
+  virtual bool ShouldDisplayURL() const;
+
  protected:
   // Returns true if the interstitial should create a new navigation entry.
   virtual bool ShouldCreateNewNavigation() const = 0;
diff --git a/components/security_interstitials/content/security_interstitial_tab_helper.cc b/components/security_interstitials/content/security_interstitial_tab_helper.cc
index 0971008..4458f5db 100644
--- a/components/security_interstitials/content/security_interstitial_tab_helper.cc
+++ b/components/security_interstitials/content/security_interstitial_tab_helper.cc
@@ -60,6 +60,15 @@
   helper->SetBlockingPage(navigation_id, std::move(blocking_page));
 }
 
+bool SecurityInterstitialTabHelper::ShouldDisplayURL() const {
+  CHECK(IsDisplayingInterstitial());
+  return blocking_page_for_currently_committed_navigation_->ShouldDisplayURL();
+}
+
+bool SecurityInterstitialTabHelper::IsDisplayingInterstitial() const {
+  return blocking_page_for_currently_committed_navigation_ != nullptr;
+}
+
 security_interstitials::SecurityInterstitialPage*
 SecurityInterstitialTabHelper::
     GetBlockingPageForCurrentlyCommittedNavigationForTesting() {
diff --git a/components/security_interstitials/content/security_interstitial_tab_helper.h b/components/security_interstitials/content/security_interstitial_tab_helper.h
index bafc5e6..62dbb0d3 100644
--- a/components/security_interstitials/content/security_interstitial_tab_helper.h
+++ b/components/security_interstitials/content/security_interstitial_tab_helper.h
@@ -43,6 +43,12 @@
       std::unique_ptr<security_interstitials::SecurityInterstitialPage>
           blocking_page);
 
+  // Determines whether a URL should be shown on the current navigation page.
+  bool ShouldDisplayURL() const;
+
+  // Whether this tab helper is tracking a currently-displaying interstitial.
+  bool IsDisplayingInterstitial() const;
+
   security_interstitials::SecurityInterstitialPage*
   GetBlockingPageForCurrentlyCommittedNavigationForTesting();
 
diff --git a/components/services/font/public/cpp/font_loader.cc b/components/services/font/public/cpp/font_loader.cc
index 7fca697..3c90c90 100644
--- a/components/services/font/public/cpp/font_loader.cc
+++ b/components/services/font/public/cpp/font_loader.cc
@@ -40,7 +40,7 @@
 
 SkStreamAsset* FontLoader::openStream(const FontIdentity& identity) {
   TRACE_EVENT2("font_loader", "FontLoader::openStream", "identity",
-               identity.fID, "name", identity.fString.c_str());
+               identity.fID, "name", TRACE_STR_COPY(identity.fString.c_str()));
   {
     base::AutoLock lock(lock_);
     auto mapped_font_files_it = mapped_font_files_.find(identity.fID);
diff --git a/components/subresource_filter/core/common/indexed_ruleset.cc b/components/subresource_filter/core/common/indexed_ruleset.cc
index af89f6e..964176a 100644
--- a/components/subresource_filter/core/common/indexed_ruleset.cc
+++ b/components/subresource_filter/core/common/indexed_ruleset.cc
@@ -52,12 +52,12 @@
 
 // RulesetIndexer --------------------------------------------------------------
 
-const int RulesetIndexer::kIndexedFormatVersion = 25;
+const int RulesetIndexer::kIndexedFormatVersion = 26;
 
 // This static assert is meant to catch cases where
 // url_pattern_index::kUrlPatternIndexFormatVersion is incremented without
 // updating RulesetIndexer::kIndexedFormatVersion.
-static_assert(url_pattern_index::kUrlPatternIndexFormatVersion == 4,
+static_assert(url_pattern_index::kUrlPatternIndexFormatVersion == 5,
               "kUrlPatternIndexFormatVersion has changed, make sure you've "
               "also updated RulesetIndexer::kIndexedFormatVersion above.");
 
diff --git a/components/tracing/common/native_stack_sampler_android.cc b/components/tracing/common/native_stack_sampler_android.cc
index 4cb51b0..e28ae1f 100644
--- a/components/tracing/common/native_stack_sampler_android.cc
+++ b/components/tracing/common/native_stack_sampler_android.cc
@@ -4,7 +4,6 @@
 
 #include "components/tracing/common/native_stack_sampler_android.h"
 
-#include "base/no_destructor.h"
 #include "base/sampling_heap_profiler/module_cache.h"
 #include "base/trace_event/trace_event.h"
 
@@ -18,13 +17,10 @@
 
 NativeStackSamplerAndroid::~NativeStackSamplerAndroid() = default;
 
-void NativeStackSamplerAndroid::ProfileRecordingStarting() {}
-
 std::vector<base::StackSamplingProfiler::Frame>
 NativeStackSamplerAndroid::RecordStackFrames(
     StackBuffer* stack_buffer,
     base::StackSamplingProfiler::ProfileBuilder* profile_builder) {
-  static base::NoDestructor<base::ModuleCache::Module> invalid_module;
   if (!unwinder_.is_initialized()) {
     // May block on disk access. This function is executed on the profiler
     // thread, so this will only block profiling execution.
@@ -38,8 +34,7 @@
   frames.reserve(depth);
   for (size_t i = 0; i < depth; ++i) {
     // TODO(ssid): Add support for obtaining modules here.
-    frames.emplace_back(reinterpret_cast<uintptr_t>(pcs[i]),
-                        invalid_module.get());
+    frames.emplace_back(reinterpret_cast<uintptr_t>(pcs[i]), nullptr);
   }
   return frames;
 }
diff --git a/components/tracing/common/native_stack_sampler_android.h b/components/tracing/common/native_stack_sampler_android.h
index e5c49aa..e80ae2e5 100644
--- a/components/tracing/common/native_stack_sampler_android.h
+++ b/components/tracing/common/native_stack_sampler_android.h
@@ -22,7 +22,6 @@
   ~NativeStackSamplerAndroid() override;
 
   // StackSamplingProfiler::NativeStackSampler:
-  void ProfileRecordingStarting() override;
   std::vector<base::StackSamplingProfiler::Frame> RecordStackFrames(
       StackBuffer* stack_buffer,
       base::StackSamplingProfiler::ProfileBuilder* profile_builder) override;
diff --git a/components/translate/content/DEPS b/components/translate/content/DEPS
index c57486b..83c2ce4 100644
--- a/components/translate/content/DEPS
+++ b/components/translate/content/DEPS
@@ -1,4 +1,6 @@
 include_rules = [
   "+content/public/common",
   "+mojo/public",
+  "+services/network/public",
+  "+third_party/blink/public",
 ]
diff --git a/components/translate/content/browser/content_translate_driver.cc b/components/translate/content/browser/content_translate_driver.cc
index 7c91e182..cee7663b 100644
--- a/components/translate/content/browser/content_translate_driver.cc
+++ b/components/translate/content/browser/content_translate_driver.cc
@@ -4,6 +4,9 @@
 
 #include "components/translate/content/browser/content_translate_driver.h"
 
+#include <string>
+#include <utility>
+
 #include "base/bind.h"
 #include "base/location.h"
 #include "base/logging.h"
@@ -13,6 +16,7 @@
 #include "components/search_engines/template_url_service.h"
 #include "components/translate/core/browser/translate_download_manager.h"
 #include "components/translate/core/browser/translate_manager.h"
+#include "components/translate/core/common/translate_util.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/navigation_controller.h"
 #include "content/public/browser/navigation_details.h"
@@ -20,11 +24,15 @@
 #include "content/public/browser/navigation_handle.h"
 #include "content/public/browser/page_navigator.h"
 #include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/render_process_host.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/referrer.h"
 #include "net/http/http_status_code.h"
+#include "services/network/public/mojom/network_context.mojom.h"
 #include "url/gurl.h"
 
+namespace translate {
+
 namespace {
 
 // The maximum number of attempts we'll do to see if the page has finshed
@@ -33,8 +41,6 @@
 
 }  // namespace
 
-namespace translate {
-
 ContentTranslateDriver::ContentTranslateDriver(
     content::NavigationController* nav_controller,
     const TemplateURLService* template_url_service,
@@ -107,6 +113,23 @@
     observer.OnIsPageTranslatedChanged(web_contents);
 }
 
+network::mojom::URLLoaderFactoryPtr
+ContentTranslateDriver::CreateURLLoaderFactory() {
+  // Find the renderer process that will need to use the URLLoaderFactory.
+  // Currently translate requests are only sent to the main frame process.
+  content::RenderProcessHost* process =
+      web_contents()->GetMainFrame()->GetProcess();
+
+  // Create a new URLLoaderFactory, locking the initiator origin to the one
+  // returned by GetTranslateSecurityOrigin.
+  network::mojom::URLLoaderFactoryPtr factory;
+  url::Origin origin = url::Origin::Create(GetTranslateSecurityOrigin());
+  network::mojom::TrustedURLLoaderHeaderClientPtrInfo null_header_client;
+  process->CreateURLLoaderFactory(origin, std::move(null_header_client),
+                                  mojo::MakeRequest(&factory));
+  return factory;
+}
+
 void ContentTranslateDriver::TranslatePage(int page_seq_no,
                                            const std::string& translate_script,
                                            const std::string& source_lang,
@@ -116,7 +139,7 @@
     return;  // This page has navigated away.
 
   it->second->Translate(
-      translate_script, source_lang, target_lang,
+      translate_script, CreateURLLoaderFactory(), source_lang, target_lang,
       base::BindOnce(&ContentTranslateDriver::OnPageTranslated,
                      base::Unretained(this)));
 }
diff --git a/components/translate/content/browser/content_translate_driver.h b/components/translate/content/browser/content_translate_driver.h
index 9b05c7e..f937d826 100644
--- a/components/translate/content/browser/content_translate_driver.h
+++ b/components/translate/content/browser/content_translate_driver.h
@@ -6,6 +6,7 @@
 #define COMPONENTS_TRANSLATE_CONTENT_BROWSER_CONTENT_TRANSLATE_DRIVER_H_
 
 #include <map>
+#include <string>
 
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
@@ -15,6 +16,7 @@
 #include "components/translate/core/common/translate_errors.h"
 #include "content/public/browser/web_contents_observer.h"
 #include "mojo/public/cpp/bindings/binding_set.h"
+#include "services/network/public/mojom/url_loader_factory.mojom.h"
 
 namespace content {
 class NavigationController;
@@ -123,6 +125,13 @@
   bool IsDefaultSearchEngineOriginator(
       const url::Origin& originating_origin) const;
 
+  // Creates a URLLoaderFactory that may be used by the translate scripts that
+  // get injected into isolated worlds within the page to be translated.  Such
+  // scripts (or rather, their isolated worlds) are associated with a
+  // translate-specific origin like https://translate.googleapis.com and use
+  // this origin as |request_initiator| of http requests.
+  network::mojom::URLLoaderFactoryPtr CreateURLLoaderFactory();
+
   // The navigation controller of the tab we are associated with.
   content::NavigationController* navigation_controller_;
 
diff --git a/components/translate/content/common/BUILD.gn b/components/translate/content/common/BUILD.gn
index a5b6a678..ae52137 100644
--- a/components/translate/content/common/BUILD.gn
+++ b/components/translate/content/common/BUILD.gn
@@ -11,6 +11,7 @@
 
   public_deps = [
     "//mojo/public/mojom/base",
+    "//services/network/public/mojom:mojom",
     "//url/mojom:url_mojom_gurl",
   ]
 }
diff --git a/components/translate/content/common/translate.mojom b/components/translate/content/common/translate.mojom
index 7d09c8f..0893def 100644
--- a/components/translate/content/common/translate.mojom
+++ b/components/translate/content/common/translate.mojom
@@ -6,6 +6,7 @@
 
 import "mojo/public/mojom/base/time.mojom";
 import "mojo/public/mojom/base/string16.mojom";
+import "services/network/public/mojom/url_loader_factory.mojom";
 import "url/mojom/url.mojom";
 
 enum TranslateError {
@@ -39,6 +40,12 @@
   // Requests that the page be translated from |source_lang| to
   // |target_lang|.
   //
+  // |loader_factory_for_translate_script| should provide a factory that the
+  // translation scripts can use for making fetch requests associated with the
+  // "translate" origin (the default factory's |request_initiator_site_lock| is
+  // not compatible with |request_initiator| of fetch requests initiated by the
+  // "translate" origin).
+  //
   // If a Translate request is already in progress with a matching
   // |target_lang|, this request will respond with |cancelled| set
   // to |true|.
@@ -49,7 +56,10 @@
   //
   // If |cancelled| is |true| all other response values should be
   // ignored.
-  Translate(string translate_script, string source_lang, string target_lang)
+  Translate(string translate_script,
+            network.mojom.URLLoaderFactory loader_factory_for_translate_script,
+            string source_lang,
+            string target_lang)
       => (bool cancelled, string original_lang, string translated_lang,
           TranslateError error);
 
diff --git a/components/translate/content/renderer/BUILD.gn b/components/translate/content/renderer/BUILD.gn
index d04d8d6..72a8873 100644
--- a/components/translate/content/renderer/BUILD.gn
+++ b/components/translate/content/renderer/BUILD.gn
@@ -15,8 +15,6 @@
     "//components/translate/content/common",
     "//components/translate/core/common",
     "//components/translate/core/language_detection",
-    "//content/public/common",
-    "//content/public/renderer",
     "//services/service_manager/public/cpp",
     "//third_party/blink/public:blink",
     "//url",
@@ -24,6 +22,8 @@
   ]
 
   public_deps = [
+    "//content/public/common",
+    "//content/public/renderer",
     "//third_party/blink/public:blink_headers",
   ]
 }
diff --git a/components/translate/content/renderer/translate_helper.cc b/components/translate/content/renderer/translate_helper.cc
index 2cc44a6..8b8a8a6 100644
--- a/components/translate/content/renderer/translate_helper.cc
+++ b/components/translate/content/renderer/translate_helper.cc
@@ -8,6 +8,7 @@
 
 #include "base/bind.h"
 #include "base/compiler_specific.h"
+#include "base/feature_list.h"
 #include "base/json/string_escape.h"
 #include "base/location.h"
 #include "base/logging.h"
@@ -25,7 +26,9 @@
 #include "content/public/common/url_constants.h"
 #include "content/public/renderer/render_frame.h"
 #include "content/public/renderer/render_thread.h"
+#include "services/network/public/cpp/features.h"
 #include "services/service_manager/public/cpp/interface_provider.h"
+#include "third_party/blink/public/common/loader/url_loader_factory_bundle.h"
 #include "third_party/blink/public/platform/web_isolated_world_info.h"
 #include "third_party/blink/public/web/web_document.h"
 #include "third_party/blink/public/web/web_language_detection_details.h"
@@ -282,10 +285,20 @@
 }
 
 // mojom::Page implementations.
-void TranslateHelper::Translate(const std::string& translate_script,
-                                const std::string& source_lang,
-                                const std::string& target_lang,
-                                TranslateCallback callback) {
+void TranslateHelper::Translate(
+    const std::string& translate_script,
+    network::mojom::URLLoaderFactoryPtr loader_factory_for_translate_script,
+    const std::string& source_lang,
+    const std::string& target_lang,
+    TranslateCallback callback) {
+  url::Origin translate_origin =
+      url::Origin::Create(GetTranslateSecurityOrigin());
+
+  if (base::FeatureList::IsEnabled(network::features::kNetworkService)) {
+    render_frame()->MarkInitiatorAsRequiringSeparateURLLoaderFactory(
+        translate_origin, std::move(loader_factory_for_translate_script));
+  }
+
   WebLocalFrame* main_frame = render_frame()->GetWebFrame();
   if (!main_frame) {
     // Cancelled.
@@ -322,8 +335,7 @@
   // Set up v8 isolated world with proper content-security-policy and
   // security-origin.
   blink::WebIsolatedWorldInfo info;
-  info.security_origin =
-      WebSecurityOrigin::Create(GetTranslateSecurityOrigin());
+  info.security_origin = WebSecurityOrigin::Create(translate_origin.GetURL());
   info.content_security_policy = WebString::FromUTF8(kContentSecurityPolicy);
   main_frame->SetIsolatedWorldInfo(world_id_, info);
 
diff --git a/components/translate/content/renderer/translate_helper.h b/components/translate/content/renderer/translate_helper.h
index 494985d0..5dba2be 100644
--- a/components/translate/content/renderer/translate_helper.h
+++ b/components/translate/content/renderer/translate_helper.h
@@ -17,6 +17,7 @@
 #include "components/translate/core/common/translate_errors.h"
 #include "content/public/renderer/render_frame_observer.h"
 #include "mojo/public/cpp/bindings/binding.h"
+#include "services/network/public/mojom/url_loader_factory.mojom.h"
 #include "url/gurl.h"
 
 namespace blink {
@@ -44,10 +45,12 @@
   void PrepareForUrl(const GURL& url);
 
   // mojom::Page implementation.
-  void Translate(const std::string& translate_script,
-                 const std::string& source_lang,
-                 const std::string& target_lang,
-                 TranslateCallback callback) override;
+  void Translate(
+      const std::string& translate_script,
+      network::mojom::URLLoaderFactoryPtr loader_factory_for_translate_script,
+      const std::string& source_lang,
+      const std::string& target_lang,
+      TranslateCallback callback) override;
   void RevertTranslation() override;
 
  protected:
diff --git a/components/url_pattern_index/url_pattern.cc b/components/url_pattern_index/url_pattern.cc
index 81b80bfb..1d914efa 100644
--- a/components/url_pattern_index/url_pattern.cc
+++ b/components/url_pattern_index/url_pattern.cc
@@ -33,9 +33,11 @@
 
 namespace {
 
+constexpr char kWildcard = '*';
+
 class IsWildcard {
  public:
-  bool operator()(char c) const { return c == '*'; }
+  bool operator()(char c) const { return c == kWildcard; }
 };
 
 proto::UrlPatternType ConvertUrlPatternType(flat::UrlPatternType type) {
@@ -343,15 +345,30 @@
   DCHECK(base::IsStringASCII(url.spec()));
   DCHECK(base::IsStringASCII(url.GetLowerCaseSpec()));
 
+  // Pre-process patterns to ensure left anchored and right anchored patterns
+  // don't begin and end with a wildcard respectively i.e. change "|*xyz" to
+  // "*xyz" and "xyz*|" to "xyz*".
+  proto::AnchorType anchor_left = anchor_left_;
+  proto::AnchorType anchor_right = anchor_right_;
+  if (!url_pattern_.empty()) {
+    if (url_pattern_.front() == kWildcard) {
+      // Note: We don't handle "||*" and expect clients to disallow it.
+      DCHECK_NE(proto::ANCHOR_TYPE_SUBDOMAIN, anchor_left_);
+      anchor_left = proto::ANCHOR_TYPE_NONE;
+    }
+    if (url_pattern_.back() == kWildcard)
+      anchor_right = proto::ANCHOR_TYPE_NONE;
+  }
+
   if (match_case()) {
-    return IsCaseSensitiveMatch(url_pattern_, anchor_left_, anchor_right_,
+    return IsCaseSensitiveMatch(url_pattern_, anchor_left, anchor_right,
                                 url.spec(), url.host());
   }
 
   // Use the lower-cased url for case-insensitive comparison. Case-insensitive
   // patterns should already be lower-cased.
   DCHECK(!HasAnyUpperAscii(url_pattern_));
-  return IsCaseSensitiveMatch(url_pattern_, anchor_left_, anchor_right_,
+  return IsCaseSensitiveMatch(url_pattern_, anchor_left, anchor_right,
                               url.GetLowerCaseSpec(), url.host());
 }
 
diff --git a/components/url_pattern_index/url_pattern_index.cc b/components/url_pattern_index/url_pattern_index.cc
index a2d96a8..ad885a3 100644
--- a/components/url_pattern_index/url_pattern_index.cc
+++ b/components/url_pattern_index/url_pattern_index.cc
@@ -343,6 +343,13 @@
     if (anchor_right_ == flat::AnchorType_SUBDOMAIN)
       return false;  // Unsupported right anchor.
 
+    // We disallow patterns like "||*xyz" because it isn't clear how to match
+    // them.
+    if (anchor_left_ == flat::AnchorType_SUBDOMAIN &&
+        (!rule_.url_pattern().empty() && rule_.url_pattern().front() == '*')) {
+      return false;
+    }
+
     return true;
   }
 
diff --git a/components/url_pattern_index/url_pattern_index.h b/components/url_pattern_index/url_pattern_index.h
index ec1dc95..0262664e 100644
--- a/components/url_pattern_index/url_pattern_index.h
+++ b/components/url_pattern_index/url_pattern_index.h
@@ -83,7 +83,7 @@
 // Increase this value when introducing an incompatible change to the
 // UrlPatternIndex schema (flat/url_pattern_index.fbs). url_pattern_index
 // clients can use this as a signal to rebuild rulesets.
-constexpr int kUrlPatternIndexFormatVersion = 4;
+constexpr int kUrlPatternIndexFormatVersion = 5;
 
 // The class used to construct an index over the URL patterns of a set of URL
 // rules. The rules themselves need to be converted to FlatBuffers format by the
diff --git a/components/url_pattern_index/url_pattern_unittest.cc b/components/url_pattern_index/url_pattern_unittest.cc
index 950c907..a2c642a 100644
--- a/components/url_pattern_index/url_pattern_unittest.cc
+++ b/components/url_pattern_index/url_pattern_unittest.cc
@@ -186,6 +186,10 @@
       {{"abc*^", kAnchorNone, kAnchorNone}, "https://abc.com?q=123", true},
       {{"abc*^", kAnchorNone, kBoundary}, "https://abc.com", true},
       {{"abc*^", kAnchorNone, kBoundary}, "https://abc.com?q=123", true},
+      {{"abc*", kAnchorNone, kBoundary}, "https://a.com/abcxyz", true},
+      {{"*google.com", kBoundary, kAnchorNone}, "https://www.google.com", true},
+      {{"*", kBoundary, kBoundary}, "https://example.com", true},
+      {{"", kBoundary, kBoundary}, "https://example.com", false},
   };
 
   for (const auto& test_case : kTestCases) {
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index 765c9d898b..d45a2eb 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -2433,6 +2433,7 @@
       "//media",
       "//third_party/mozilla",
       "//ui/accelerated_widget_mac",
+      "//ui/base/now_playing",
     ]
     libs += [
       "Carbon.framework",
diff --git a/content/browser/accessibility/accessibility_tree_formatter_auralinux.cc b/content/browser/accessibility/accessibility_tree_formatter_auralinux.cc
index ea88671..9875b08 100644
--- a/content/browser/accessibility/accessibility_tree_formatter_auralinux.cc
+++ b/content/browser/accessibility/accessibility_tree_formatter_auralinux.cc
@@ -331,6 +331,14 @@
     }
   }
 
+  const base::ListValue* table_info;
+  node.GetList("table", &table_info);
+  for (auto it = table_info->begin(); it != table_info->end(); ++it) {
+    std::string table_property;
+    if (it->GetAsString(&table_property))
+      WriteAttribute(true, table_property, &line);
+  }
+
   return line;
 }
 
diff --git a/content/browser/accessibility/accessibility_win_browsertest.cc b/content/browser/accessibility/accessibility_win_browsertest.cc
index 2dcfdab40..3764569 100644
--- a/content/browser/accessibility/accessibility_win_browsertest.cc
+++ b/content/browser/accessibility/accessibility_win_browsertest.cc
@@ -3183,14 +3183,11 @@
           <div aria-label='not'>
             not scrollable
           </div>
-          <div style='width:10px; overflow:scroll' aria-label='x'>
-              scrollable in x
-            </div>
-          <div style='height:10px; overflow:scroll' aria-label='y'>
-            scrollable in y
+          <div style='width:100px; overflow:auto' aria-label='x'>
+              <div style='width:200px; height:100px'></div>
           </div>
-          <div style='width:10px; height:10px; overflow:scroll' aria-label='xy'>
-            scrollable in x and y
+          <div style='height:100px; overflow:auto' aria-label='y'>
+              <div style='width:100px; height:200px'></div>
           </div>
         </body>
       </html>
@@ -3204,10 +3201,9 @@
     double size_vertical;
   };
   double error = 0.01f;
-  std::vector<ScrollTestData> all_expected = {{"not", false, false, 0, 0},
-                                              {"x", true, false, 12.65, 0},
-                                              {"y", false, true, 0, 28.57},
-                                              {"xy", true, true, 12.65, 9.34}};
+  std::vector<ScrollTestData> all_expected = {{"not", false, false, 0.0, 0.0},
+                                              {"x", true, false, 50.0, 0.0},
+                                              {"y", false, true, 0.0, 50.0}};
   for (auto& expected : all_expected) {
     BrowserAccessibility* browser_accessibility =
         FindNode(ax::mojom::Role::kGenericContainer, expected.node_name);
@@ -3308,4 +3304,41 @@
   }
 }
 
+IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest,
+                       TestIsContentElementPropertyId) {
+  LoadInitialAccessibilityTreeFromHtml(
+      R"HTML(<!DOCTYPE html>
+      <html>
+        <table>
+          <tr>
+              <th aria-label="header">
+                  header
+              </th>
+              <td> data </td>
+          </tr>
+        </table>
+      </html>)HTML");
+
+  BrowserAccessibility* target =
+      FindNode(ax::mojom::Role::kRowHeader, "header");
+  EXPECT_NE(nullptr, target);
+  BrowserAccessibilityComWin* accessibility_com_win =
+      ToBrowserAccessibilityWin(target)->GetCOM();
+  EXPECT_NE(nullptr, accessibility_com_win);
+
+  base::win::ScopedVariant result;
+  accessibility_com_win->GetPropertyValue(UIA_IsContentElementPropertyId,
+                                          result.Receive());
+
+  BrowserAccessibility* child = target->PlatformDeepestFirstChild();
+  EXPECT_NE(nullptr, child);
+  accessibility_com_win = ToBrowserAccessibilityWin(child)->GetCOM();
+  EXPECT_NE(nullptr, accessibility_com_win);
+
+  result.Release();
+  accessibility_com_win->GetPropertyValue(UIA_IsContentElementPropertyId,
+                                          result.Receive());
+  EXPECT_EQ(VT_BOOL, result.type());
+  EXPECT_EQ(VARIANT_FALSE, result.ptr()->boolVal);
+}
 }  // namespace content
diff --git a/content/browser/accessibility/ax_platform_node_win_browsertest.cc b/content/browser/accessibility/ax_platform_node_win_browsertest.cc
new file mode 100644
index 0000000..f1d91d5
--- /dev/null
+++ b/content/browser/accessibility/ax_platform_node_win_browsertest.cc
@@ -0,0 +1,271 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/accessibility/platform/ax_platform_node_win.h"
+
+#include "content/browser/accessibility/browser_accessibility.h"
+#include "content/browser/accessibility/browser_accessibility_com_win.h"
+#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
+#include "content/shell/browser/shell.h"
+#include "content/test/accessibility_browser_test_utils.h"
+#include "net/base/escape.h"
+
+using Microsoft::WRL::ComPtr;
+
+namespace content {
+class AXPlatformNodeWinBrowserTest : public ContentBrowserTest {
+ protected:
+  void LoadInitialAccessibilityTreeFromHtml(
+      const std::string& html,
+      ui::AXMode accessibility_mode = ui::kAXModeComplete) {
+    AccessibilityNotificationWaiter waiter(shell()->web_contents(),
+                                           accessibility_mode,
+                                           ax::mojom::Event::kLoadComplete);
+    GURL html_data_url =
+        GURL("data:text/html," + net::EscapeQueryParamValue(html, false));
+    NavigateToURL(shell(), html_data_url);
+    waiter.WaitForNotification();
+  }
+
+  void UIAIWindowProviderGetIsModalBrowserTestTemplate(
+      ax::mojom::Role expected_role,
+      content::BrowserAccessibility* (content::BrowserAccessibility::*f)(
+          uint32_t) const,
+      uint32_t index_arg,
+      bool expected_is_modal,
+      bool expected_is_window_provider_available) {
+    WebContentsImpl* web_contents_impl =
+        static_cast<WebContentsImpl*>(shell()->web_contents());
+    ASSERT_NE(nullptr, web_contents_impl);
+
+    BrowserAccessibilityManager* browser_accessibility_manager =
+        web_contents_impl->GetRootBrowserAccessibilityManager();
+    ASSERT_NE(nullptr, browser_accessibility_manager);
+
+    BrowserAccessibility* root_browser_accessibility =
+        browser_accessibility_manager->GetRoot();
+    ASSERT_NE(nullptr, root_browser_accessibility);
+    BrowserAccessibilityComWin* root_browser_accessibility_com_win =
+        ToBrowserAccessibilityWin(root_browser_accessibility)->GetCOM();
+    ASSERT_NE(nullptr, root_browser_accessibility_com_win);
+
+    BrowserAccessibility* browser_accessibility =
+        (root_browser_accessibility->*f)(index_arg);
+    ASSERT_NE(nullptr, browser_accessibility);
+    ASSERT_EQ(expected_role, browser_accessibility->GetRole());
+    BrowserAccessibilityComWin* browser_accessibility_com_win =
+        ToBrowserAccessibilityWin(browser_accessibility)->GetCOM();
+    ASSERT_NE(nullptr, browser_accessibility_com_win);
+
+    ComPtr<IWindowProvider> window_provider = nullptr;
+    ASSERT_HRESULT_SUCCEEDED(browser_accessibility_com_win->GetPatternProvider(
+        UIA_WindowPatternId, &window_provider));
+    if (expected_is_window_provider_available) {
+      ASSERT_NE(nullptr, window_provider.Get());
+
+      BOOL is_modal = FALSE;
+      ASSERT_HRESULT_SUCCEEDED(window_provider->get_IsModal(&is_modal));
+      ASSERT_EQ(expected_is_modal, is_modal);
+    } else {
+      ASSERT_EQ(nullptr, window_provider.Get());
+    }
+  }
+};
+
+IN_PROC_BROWSER_TEST_F(AXPlatformNodeWinBrowserTest,
+                       UIAIWindowProviderGetIsModalOnDialog) {
+  LoadInitialAccessibilityTreeFromHtml(std::string(R"HTML(
+      <!DOCTYPE html>
+      <html>
+        <body>
+          <dialog open>Example Text</dialog>
+        </body>
+      </html>
+  )HTML"));
+
+  UIAIWindowProviderGetIsModalBrowserTestTemplate(
+      ax::mojom::Role::kDialog, &BrowserAccessibility::PlatformGetChild, 0,
+      false, true);
+}
+
+IN_PROC_BROWSER_TEST_F(AXPlatformNodeWinBrowserTest,
+                       UIAIWindowProviderGetIsModalOnDialogAriaModalFalse) {
+  LoadInitialAccessibilityTreeFromHtml(std::string(R"HTML(
+      <!DOCTYPE html>
+      <html>
+        <body>
+          <dialog open aria-modal="false">Example Text</dialog>
+        </body>
+      </html>
+  )HTML"));
+
+  UIAIWindowProviderGetIsModalBrowserTestTemplate(
+      ax::mojom::Role::kDialog, &BrowserAccessibility::PlatformGetChild, 0,
+      false, true);
+}
+
+IN_PROC_BROWSER_TEST_F(AXPlatformNodeWinBrowserTest,
+                       UIAIWindowProviderGetIsModalOnDialogAriaModalTrue) {
+  LoadInitialAccessibilityTreeFromHtml(std::string(R"HTML(
+      <!DOCTYPE html>
+      <html>
+        <body>
+          <dialog open aria-modal="true">Example Text</dialog>
+        </body>
+      </html>
+  )HTML"));
+
+  UIAIWindowProviderGetIsModalBrowserTestTemplate(
+      ax::mojom::Role::kDialog, &BrowserAccessibility::PlatformGetChild, 0,
+      true, true);
+}
+
+IN_PROC_BROWSER_TEST_F(AXPlatformNodeWinBrowserTest,
+                       UIAIWindowProviderGetIsModalOnDiv) {
+  LoadInitialAccessibilityTreeFromHtml(std::string(R"HTML(
+      <!DOCTYPE html>
+      <html>
+        <body>
+          <div>Example Text</div>
+        </body>
+      </html>
+  )HTML"));
+
+  UIAIWindowProviderGetIsModalBrowserTestTemplate(
+      ax::mojom::Role::kGenericContainer,
+      &BrowserAccessibility::PlatformGetChild, 0, false, false);
+}
+
+IN_PROC_BROWSER_TEST_F(AXPlatformNodeWinBrowserTest,
+                       UIAIWindowProviderGetIsModalOnDivAriaModalFalse) {
+  LoadInitialAccessibilityTreeFromHtml(std::string(R"HTML(
+      <!DOCTYPE html>
+      <html>
+        <body>
+          <div aria-modal="false">Example Text</div>
+        </body>
+      </html>
+  )HTML"));
+
+  UIAIWindowProviderGetIsModalBrowserTestTemplate(
+      ax::mojom::Role::kGenericContainer,
+      &BrowserAccessibility::PlatformGetChild, 0, false, false);
+}
+
+IN_PROC_BROWSER_TEST_F(AXPlatformNodeWinBrowserTest,
+                       UIAIWindowProviderGetIsModalOnDivAriaModalTrue) {
+  LoadInitialAccessibilityTreeFromHtml(std::string(R"HTML(
+      <!DOCTYPE html>
+      <html>
+        <body>
+          <div aria-modal="true">Example Text</div>
+        </body>
+      </html>
+  )HTML"));
+
+  UIAIWindowProviderGetIsModalBrowserTestTemplate(
+      ax::mojom::Role::kGenericContainer,
+      &BrowserAccessibility::PlatformGetChild, 0, false, false);
+}
+
+IN_PROC_BROWSER_TEST_F(AXPlatformNodeWinBrowserTest,
+                       UIAIWindowProviderGetIsModalOnDivDialog) {
+  LoadInitialAccessibilityTreeFromHtml(std::string(R"HTML(
+      <!DOCTYPE html>
+      <html>
+        <body>
+          <div role="dialog">Example Text</div>
+        </body>
+      </html>
+  )HTML"));
+
+  UIAIWindowProviderGetIsModalBrowserTestTemplate(
+      ax::mojom::Role::kDialog, &BrowserAccessibility::PlatformGetChild, 0,
+      false, true);
+}
+
+IN_PROC_BROWSER_TEST_F(AXPlatformNodeWinBrowserTest,
+                       UIAIWindowProviderGetIsModalOnDivDialogAriaModalFalse) {
+  LoadInitialAccessibilityTreeFromHtml(std::string(R"HTML(
+      <!DOCTYPE html>
+      <html>
+        <body>
+          <div role="dialog" aria-modal="false">Example Text</div>
+        </body>
+      </html>
+  )HTML"));
+
+  UIAIWindowProviderGetIsModalBrowserTestTemplate(
+      ax::mojom::Role::kDialog, &BrowserAccessibility::PlatformGetChild, 0,
+      false, true);
+}
+
+IN_PROC_BROWSER_TEST_F(AXPlatformNodeWinBrowserTest,
+                       UIAIWindowProviderGetIsModalOnDivDialogAriaModalTrue) {
+  LoadInitialAccessibilityTreeFromHtml(std::string(R"HTML(
+      <!DOCTYPE html>
+      <html>
+        <body>
+          <div role="dialog" aria-modal="true">Example Text</div>
+        </body>
+      </html>
+  )HTML"));
+
+  UIAIWindowProviderGetIsModalBrowserTestTemplate(
+      ax::mojom::Role::kDialog, &BrowserAccessibility::PlatformGetChild, 0,
+      true, true);
+}
+
+IN_PROC_BROWSER_TEST_F(AXPlatformNodeWinBrowserTest,
+                       UIAIWindowProviderGetIsModalOnDivAlertDialog) {
+  LoadInitialAccessibilityTreeFromHtml(std::string(R"HTML(
+      <!DOCTYPE html>
+      <html>
+        <body>
+          <div role="alertdialog">Example Text</div>
+        </body>
+      </html>
+  )HTML"));
+
+  UIAIWindowProviderGetIsModalBrowserTestTemplate(
+      ax::mojom::Role::kAlertDialog, &BrowserAccessibility::PlatformGetChild, 0,
+      false, true);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    AXPlatformNodeWinBrowserTest,
+    UIAIWindowProviderGetIsModalOnDivAlertDialogAriaModalFalse) {
+  LoadInitialAccessibilityTreeFromHtml(std::string(R"HTML(
+      <!DOCTYPE html>
+      <html>
+        <body>
+          <div role="alertdialog" aria-modal="false">Example Text</div>
+        </body>
+      </html>
+  )HTML"));
+
+  UIAIWindowProviderGetIsModalBrowserTestTemplate(
+      ax::mojom::Role::kAlertDialog, &BrowserAccessibility::PlatformGetChild, 0,
+      false, true);
+}
+
+IN_PROC_BROWSER_TEST_F(
+    AXPlatformNodeWinBrowserTest,
+    UIAIWindowProviderGetIsModalOnDivAlertDialogAriaModalTrue) {
+  LoadInitialAccessibilityTreeFromHtml(std::string(R"HTML(
+      <!DOCTYPE html>
+      <html>
+        <body>
+          <div role="alertdialog" aria-modal="true">Example Text</div>
+        </body>
+      </html>
+  )HTML"));
+
+  UIAIWindowProviderGetIsModalBrowserTestTemplate(
+      ax::mojom::Role::kAlertDialog, &BrowserAccessibility::PlatformGetChild, 0,
+      true, true);
+}
+}  // namespace content
diff --git a/content/browser/accessibility/browser_accessibility.cc b/content/browser/accessibility/browser_accessibility.cc
index 1ef1b51..41ef1ca 100644
--- a/content/browser/accessibility/browser_accessibility.cc
+++ b/content/browser/accessibility/browser_accessibility.cc
@@ -928,6 +928,10 @@
   return offscreen;
 }
 
+bool BrowserAccessibility::IsWebContent() const {
+  return true;
+}
+
 std::set<ui::AXPlatformNode*> BrowserAccessibility::GetNodesForNodeIdSet(
     const std::set<int32_t>& ids) {
   std::set<ui::AXPlatformNode*> nodes;
@@ -1119,11 +1123,11 @@
   return node()->GetTableColCount();
 }
 
-int32_t BrowserAccessibility::GetTableAriaColCount() const {
+base::Optional<int32_t> BrowserAccessibility::GetTableAriaColCount() const {
   return node()->GetTableAriaColCount();
 }
 
-int32_t BrowserAccessibility::GetTableAriaRowCount() const {
+base::Optional<int32_t> BrowserAccessibility::GetTableAriaRowCount() const {
   return node()->GetTableAriaRowCount();
 }
 
@@ -1157,6 +1161,13 @@
   return result;
 }
 
+ui::AXPlatformNode* BrowserAccessibility::GetTableCaption() {
+  if (ui::AXNode* caption = node()->GetTableCaption())
+    return GetFromNodeID(caption->id());
+
+  return nullptr;
+}
+
 bool BrowserAccessibility::IsTableRow() const {
   return node()->IsTableRow();
 }
diff --git a/content/browser/accessibility/browser_accessibility.h b/content/browser/accessibility/browser_accessibility.h
index db2ca08e0..820830b 100644
--- a/content/browser/accessibility/browser_accessibility.h
+++ b/content/browser/accessibility/browser_accessibility.h
@@ -361,8 +361,8 @@
   bool IsTable() const override;
   int32_t GetTableColCount() const override;
   int32_t GetTableRowCount() const override;
-  int32_t GetTableAriaColCount() const override;
-  int32_t GetTableAriaRowCount() const override;
+  base::Optional<int32_t> GetTableAriaColCount() const override;
+  base::Optional<int32_t> GetTableAriaRowCount() const override;
   int32_t GetTableCellCount() const override;
   const std::vector<int32_t> GetColHeaderNodeIds() const override;
   const std::vector<int32_t> GetColHeaderNodeIds(
@@ -370,6 +370,7 @@
   const std::vector<int32_t> GetRowHeaderNodeIds() const override;
   const std::vector<int32_t> GetRowHeaderNodeIds(
       int32_t row_index) const override;
+  ui::AXPlatformNode* GetTableCaption() override;
 
   bool IsTableRow() const override;
   int32_t GetTableRowRowIndex() const override;
@@ -391,6 +392,7 @@
   base::string16 GetLocalizedRoleDescriptionForUnlabeledImage() const override;
   bool ShouldIgnoreHoveredStateForTesting() override;
   bool IsOffscreen() const override;
+  bool IsWebContent() const override;
   ui::AXPlatformNode* GetTargetNodeForRelation(
       ax::mojom::IntAttribute attr) override;
   std::set<ui::AXPlatformNode*> GetTargetNodesForRelation(
diff --git a/content/browser/accessibility/browser_accessibility_cocoa.mm b/content/browser/accessibility/browser_accessibility_cocoa.mm
index ae2e164..aa15efe9 100644
--- a/content/browser/accessibility/browser_accessibility_cocoa.mm
+++ b/content/browser/accessibility/browser_accessibility_cocoa.mm
@@ -16,6 +16,7 @@
 #include "base/mac/availability.h"
 #include "base/mac/foundation_util.h"
 #include "base/mac/scoped_cftyperef.h"
+#include "base/optional.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
 #include "base/strings/sys_string_conversions.h"
@@ -731,7 +732,11 @@
   if (!ui::IsTableLike(owner_->GetRole()))
     return nil;
   DCHECK(owner_->node());
-  return [NSNumber numberWithInt:owner_->node()->GetTableAriaColCount()];
+  base::Optional<int32_t> aria_col_count =
+      owner_->node()->GetTableAriaColCount();
+  if (!aria_col_count)
+    return nil;
+  return [NSNumber numberWithInt:aria_col_count.value()];
 }
 
 - (NSNumber*)ariaColumnIndex {
@@ -765,7 +770,11 @@
   if (!ui::IsTableLike(owner_->GetRole()))
     return nil;
   DCHECK(owner_->node());
-  return [NSNumber numberWithInt:owner_->node()->GetTableAriaRowCount()];
+  base::Optional<int32_t> aria_row_count =
+      owner_->node()->GetTableAriaRowCount();
+  if (!aria_row_count)
+    return nil;
+  return [NSNumber numberWithInt:aria_row_count.value()];
 }
 
 - (NSNumber*)ariaRowIndex {
diff --git a/content/browser/accessibility/browser_accessibility_manager_mac.mm b/content/browser/accessibility/browser_accessibility_manager_mac.mm
index ab88c41..7fe7130 100644
--- a/content/browser/accessibility/browser_accessibility_manager_mac.mm
+++ b/content/browser/accessibility/browser_accessibility_manager_mac.mm
@@ -342,7 +342,7 @@
           [native_node retain]);
       base::PostDelayedTaskWithTraits(
           FROM_HERE, {BrowserThread::UI},
-          base::Bind(
+          base::BindOnce(
               [](base::scoped_nsobject<BrowserAccessibilityCocoa> node) {
                 if (node && [node instanceActive]) {
                   NSAccessibilityPostNotification(
diff --git a/content/browser/accessibility/browser_accessibility_state_impl.cc b/content/browser/accessibility/browser_accessibility_state_impl.cc
index 95febe9..81f2aa2f 100644
--- a/content/browser/accessibility/browser_accessibility_state_impl.cc
+++ b/content/browser/accessibility/browser_accessibility_state_impl.cc
@@ -78,7 +78,7 @@
   // gives us better numbers.
   base::PostDelayedTaskWithTraits(
       FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
-      base::Bind(&BrowserAccessibilityStateImpl::UpdateHistograms, this),
+      base::BindOnce(&BrowserAccessibilityStateImpl::UpdateHistograms, this),
       base::TimeDelta::FromSeconds(ACCESSIBILITY_HISTOGRAM_DELAY_SECS));
 #else
   // On MacOS, UpdateHistograms should be called on the UI thread because it
diff --git a/content/browser/android/background_sync_network_observer_android.cc b/content/browser/android/background_sync_network_observer_android.cc
index 305b14a..efbad67 100644
--- a/content/browser/android/background_sync_network_observer_android.cc
+++ b/content/browser/android/background_sync_network_observer_android.cc
@@ -22,8 +22,8 @@
       new BackgroundSyncNetworkObserverAndroid::Observer(callback));
   base::PostTaskWithTraits(
       FROM_HERE, {BrowserThread::UI},
-      base::Bind(&BackgroundSyncNetworkObserverAndroid::Observer::Init,
-                 observer));
+      base::BindOnce(&BackgroundSyncNetworkObserverAndroid::Observer::Init,
+                     observer));
   return observer;
 }
 
@@ -53,8 +53,8 @@
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   base::PostTaskWithTraits(
       FROM_HERE, {BrowserThread::IO},
-      base::Bind(callback_, static_cast<network::mojom::ConnectionType>(
-                                new_connection_type)));
+      base::BindOnce(callback_, static_cast<network::mojom::ConnectionType>(
+                                    new_connection_type)));
 }
 
 BackgroundSyncNetworkObserverAndroid::Observer::Observer(
diff --git a/content/browser/android/scoped_surface_request_manager.cc b/content/browser/android/scoped_surface_request_manager.cc
index d7bcea2..55d170b 100644
--- a/content/browser/android/scoped_surface_request_manager.cc
+++ b/content/browser/android/scoped_surface_request_manager.cc
@@ -69,9 +69,9 @@
   // the lifetime of the browser process.
   base::PostTaskWithTraits(
       FROM_HERE, {BrowserThread::UI},
-      base::Bind(&ScopedSurfaceRequestManager::CompleteRequestOnUiThread,
-                 base::Unretained(this), request_token,
-                 base::Passed(&surface)));
+      base::BindOnce(&ScopedSurfaceRequestManager::CompleteRequestOnUiThread,
+                     base::Unretained(this), request_token,
+                     std::move(surface)));
 }
 
 void ScopedSurfaceRequestManager::CompleteRequestOnUiThread(
diff --git a/content/browser/browser_ipc_logging.cc b/content/browser/browser_ipc_logging.cc
index 07958a9..8d2e086 100644
--- a/content/browser/browser_ipc_logging.cc
+++ b/content/browser/browser_ipc_logging.cc
@@ -42,7 +42,7 @@
   // processes must be done on the IO thread.
   base::PostTaskWithTraits(
       FROM_HERE, {BrowserThread::IO},
-      base::Bind(EnableIPCLoggingForChildProcesses, enable));
+      base::BindOnce(EnableIPCLoggingForChildProcesses, enable));
 
   // Finally, tell the renderers which don't derive from ChildProcess.
   // Messages to the renderers must be done on the UI (main) thread.
diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc
index ba17a64..f16849b 100644
--- a/content/browser/browser_main_loop.cc
+++ b/content/browser/browser_main_loop.cc
@@ -180,6 +180,7 @@
 #include "content/browser/renderer_host/browser_compositor_view_mac.h"
 #include "content/browser/theme_helper_mac.h"
 #include "ui/accelerated_widget_mac/window_resize_helper_mac.h"
+#include "ui/base/now_playing/remote_command_center_delegate.h"
 #endif
 
 #if defined(OS_WIN)
@@ -1444,6 +1445,10 @@
 #endif
 
   if (MediaKeysListenerManager::IsMediaKeysListenerManagerEnabled()) {
+#if defined(OS_MACOSX)
+    remote_command_center_delegate_ =
+        now_playing::RemoteCommandCenterDelegate::Create();
+#endif
     media_keys_listener_manager_ =
         std::make_unique<MediaKeysListenerManagerImpl>(
             content::ServiceManagerConnection::GetForProcess()->GetConnector());
diff --git a/content/browser/browser_main_loop.h b/content/browser/browser_main_loop.h
index 2d642405..febdcd0 100644
--- a/content/browser/browser_main_loop.h
+++ b/content/browser/browser_main_loop.h
@@ -77,6 +77,12 @@
 class NetworkChangeNotifier;
 }  // namespace net
 
+#if defined(OS_MACOSX)
+namespace now_playing {
+class RemoteCommandCenterDelegate;
+}  // namespace now_playing
+#endif
+
 namespace viz {
 class CompositingModeReporterImpl;
 class FrameSinkManagerImpl;
@@ -356,6 +362,10 @@
   // Members initialized in |BrowserThreadsStarted()| --------------------------
   std::unique_ptr<mojo::core::ScopedIPCSupport> mojo_ipc_support_;
   std::unique_ptr<MediaKeysListenerManagerImpl> media_keys_listener_manager_;
+#if defined(OS_MACOSX)
+  std::unique_ptr<now_playing::RemoteCommandCenterDelegate>
+      remote_command_center_delegate_;
+#endif
 
   // |user_input_monitor_| has to outlive |audio_manager_|, so declared first.
   std::unique_ptr<media::UserInputMonitor> user_input_monitor_;
diff --git a/content/browser/cache_storage/cache_storage_quota_client.cc b/content/browser/cache_storage/cache_storage_quota_client.cc
index 50086c0..f9ca94d 100644
--- a/content/browser/cache_storage/cache_storage_quota_client.cc
+++ b/content/browser/cache_storage/cache_storage_quota_client.cc
@@ -11,6 +11,16 @@
 
 namespace content {
 
+namespace {
+
+bool IsValidOrigin(const url::Origin& origin) {
+  // Disallow opaque origins at the quota boundary because we DCHECK that we
+  // don't get an opaque origin in lower code layers.
+  return !origin.opaque();
+}
+
+}  // namespace
+
 CacheStorageQuotaClient::CacheStorageQuotaClient(
     base::WeakPtr<CacheStorageManager> cache_manager,
     CacheStorageOwner owner)
@@ -32,7 +42,7 @@
                                              GetUsageCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
-  if (!cache_manager_ || !DoesSupport(type)) {
+  if (!cache_manager_ || !DoesSupport(type) || !IsValidOrigin(origin)) {
     std::move(callback).Run(0);
     return;
   }
@@ -75,7 +85,7 @@
     return;
   }
 
-  if (!DoesSupport(type)) {
+  if (!DoesSupport(type) || !IsValidOrigin(origin)) {
     std::move(callback).Run(blink::mojom::QuotaStatusCode::kOk);
     return;
   }
diff --git a/content/browser/child_process_launcher_helper_android.cc b/content/browser/child_process_launcher_helper_android.cc
index 9073e88..de95aba 100644
--- a/content/browser/child_process_launcher_helper_android.cc
+++ b/content/browser/child_process_launcher_helper_android.cc
@@ -140,7 +140,7 @@
   AddRef();  // Balanced by OnChildProcessStarted.
   base::PostTaskWithTraits(
       FROM_HERE, {client_thread_id_},
-      base::Bind(
+      base::BindOnce(
           &ChildProcessLauncherHelper::set_java_peer_available_on_client_thread,
           this));
 
diff --git a/content/browser/devtools/protocol/tracing_handler.cc b/content/browser/devtools/protocol/tracing_handler.cc
index fbca49f6..6b4d0e6 100644
--- a/content/browser/devtools/protocol/tracing_handler.cc
+++ b/content/browser/devtools/protocol/tracing_handler.cc
@@ -220,6 +220,7 @@
       did_initiate_recording_(false),
       return_as_stream_(false),
       gzip_compression_(false),
+      buffer_usage_reporting_interval_(0),
       weak_factory_(this) {
   bool use_video_capture_api = true;
 #ifdef OS_ANDROID
@@ -397,8 +398,8 @@
   did_initiate_recording_ = true;
   return_as_stream_ = return_as_stream;
   gzip_compression_ = gzip_compression;
-  if (buffer_usage_reporting_interval.isJust())
-    SetupTimer(buffer_usage_reporting_interval.fromJust());
+  buffer_usage_reporting_interval_ =
+      buffer_usage_reporting_interval.fromMaybe(0);
 
   trace_config_ = base::trace_event::TraceConfig();
   if (config.isJust()) {
@@ -541,6 +542,8 @@
   EmitFrameTree();
   callback->sendSuccess();
 
+  SetupTimer(buffer_usage_reporting_interval_);
+
   bool screenshot_enabled;
   TRACE_EVENT_CATEGORY_GROUP_ENABLED(
       TRACE_DISABLED_BY_DEFAULT("devtools.screenshot"), &screenshot_enabled);
diff --git a/content/browser/devtools/protocol/tracing_handler.h b/content/browser/devtools/protocol/tracing_handler.h
index b07104f8..5c05b31 100644
--- a/content/browser/devtools/protocol/tracing_handler.h
+++ b/content/browser/devtools/protocol/tracing_handler.h
@@ -133,6 +133,7 @@
   bool did_initiate_recording_;
   bool return_as_stream_;
   bool gzip_compression_;
+  double buffer_usage_reporting_interval_;
   TraceDataBufferState trace_data_buffer_state_;
   std::unique_ptr<DevToolsVideoConsumer> video_consumer_;
   int number_of_screenshots_from_video_consumer_ = 0;
diff --git a/content/browser/download/download_browsertest.cc b/content/browser/download/download_browsertest.cc
index 878a7bb..a77abfb 100644
--- a/content/browser/download/download_browsertest.cc
+++ b/content/browser/download/download_browsertest.cc
@@ -3824,7 +3824,16 @@
   ContentBrowserClient* old_client_;
 };
 
-IN_PROC_BROWSER_TEST_F(MhtmlDownloadTest, ForceDownloadMultipartRelatedPage) {
+#if defined(THREAD_SANITIZER)
+// Flaky on TSAN https://crbug.com/932092
+#define MAYBE_ForceDownloadMultipartRelatedPage \
+  DISABLED_ForceDownloadMultipartRelatedPage
+#else
+#define MAYBE_ForceDownloadMultipartRelatedPage \
+  ForceDownloadMultipartRelatedPage
+#endif
+IN_PROC_BROWSER_TEST_F(MhtmlDownloadTest,
+                       MAYBE_ForceDownloadMultipartRelatedPage) {
   NavigateToURLAndWaitForDownload(
       shell(),
       // .mhtml file is mapped to "multipart/related" by the test server.
diff --git a/content/browser/mach_broker_mac.mm b/content/browser/mach_broker_mac.mm
index 01990f7..a9a906d 100644
--- a/content/browser/mach_broker_mac.mm
+++ b/content/browser/mach_broker_mac.mm
@@ -36,9 +36,9 @@
   // Do not attempt to reinitialize in the event of failure.
   initialized_ = true;
 
-  base::PostTaskWithTraits(
-      FROM_HERE, {BrowserThread::UI},
-      base::Bind(&MachBroker::RegisterNotifications, base::Unretained(this)));
+  base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+                           base::BindOnce(&MachBroker::RegisterNotifications,
+                                          base::Unretained(this)));
 
   if (!broker_.Init()) {
     LOG(ERROR) << "Failed to initialize the MachListenerThreadDelegate";
diff --git a/content/browser/media/android/media_player_renderer.cc b/content/browser/media/android/media_player_renderer.cc
index e876275..250cfc1c 100644
--- a/content/browser/media/android/media_player_renderer.cc
+++ b/content/browser/media/android/media_player_renderer.cc
@@ -91,9 +91,9 @@
 
   base::PostDelayedTaskWithTraits(
       FROM_HERE, {BrowserThread::UI},
-      base::Bind(&MediaPlayerRenderer::CreateMediaPlayer,
-                 weak_factory_.GetWeakPtr(),
-                 media_resource->GetMediaUrlParams(), init_cb),
+      base::BindOnce(&MediaPlayerRenderer::CreateMediaPlayer,
+                     weak_factory_.GetWeakPtr(),
+                     media_resource->GetMediaUrlParams(), init_cb),
       creation_delay);
 }
 
diff --git a/content/browser/renderer_host/media/media_devices_manager.cc b/content/browser/renderer_host/media/media_devices_manager.cc
index 995a1af8..2190283 100644
--- a/content/browser/renderer_host/media/media_devices_manager.cc
+++ b/content/browser/renderer_host/media/media_devices_manager.cc
@@ -524,8 +524,8 @@
 #if defined(OS_MACOSX)
   base::PostTaskWithTraits(
       FROM_HERE, {BrowserThread::UI},
-      base::Bind(&MediaDevicesManager::StartMonitoringOnUIThread,
-                 base::Unretained(this)));
+      base::BindOnce(&MediaDevicesManager::StartMonitoringOnUIThread,
+                     base::Unretained(this)));
 #endif
 }
 
diff --git a/content/browser/site_per_process_mac_browsertest.mm b/content/browser/site_per_process_mac_browsertest.mm
index ade271b3..919275be 100644
--- a/content/browser/site_per_process_mac_browsertest.mm
+++ b/content/browser/site_per_process_mac_browsertest.mm
@@ -54,8 +54,8 @@
     if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
       base::PostTaskWithTraits(
           FROM_HERE, {BrowserThread::UI},
-          base::Bind(&TextInputClientMacHelper::OnResult,
-                     base::Unretained(this), string, point));
+          base::BindOnce(&TextInputClientMacHelper::OnResult,
+                         base::Unretained(this), string, point));
       return;
     }
     word_ = string;
diff --git a/content/browser/speech/mock_tts_controller.cc b/content/browser/speech/mock_tts_controller.cc
index 0b98dfe..ac6fdd6 100644
--- a/content/browser/speech/mock_tts_controller.cc
+++ b/content/browser/speech/mock_tts_controller.cc
@@ -56,7 +56,7 @@
 
   TtsEngineDelegate* GetTtsEngineDelegate() override { return nullptr; }
 
-  void SetTtsPlatform(TtsPlatform* tts_platform) override{};
+  void SetTtsPlatform(TtsPlatform* tts_platform) override {}
 
   int QueueSize() override { return 0; }
 
diff --git a/content/browser/speech/tts_linux.cc b/content/browser/speech/tts_linux.cc
index e8ec9a37..e4cfe1e 100644
--- a/content/browser/speech/tts_linux.cc
+++ b/content/browser/speech/tts_linux.cc
@@ -101,9 +101,10 @@
   if (!command_line.HasSwitch(switches::kEnableSpeechDispatcher))
     return;
 
-  base::PostTaskWithTraits(
-      FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
-      base::Bind(&TtsPlatformImplLinux::Initialize, base::Unretained(this)));
+  base::PostTaskWithTraits(FROM_HERE,
+                           {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
+                           base::BindOnce(&TtsPlatformImplLinux::Initialize,
+                                          base::Unretained(this)));
 }
 
 void TtsPlatformImplLinux::Initialize() {
@@ -316,9 +317,9 @@
     current_notification_ = type;
     base::PostTaskWithTraits(
         FROM_HERE, {BrowserThread::UI},
-        base::Bind(&TtsPlatformImplLinux::OnSpeechEvent,
-                   base::Unretained(TtsPlatformImplLinux::GetInstance()),
-                   type));
+        base::BindOnce(&TtsPlatformImplLinux::OnSpeechEvent,
+                       base::Unretained(TtsPlatformImplLinux::GetInstance()),
+                       type));
   }
 }
 
@@ -336,9 +337,9 @@
     current_notification_ = state;
     base::PostTaskWithTraits(
         FROM_HERE, {BrowserThread::UI},
-        base::Bind(&TtsPlatformImplLinux::OnSpeechEvent,
-                   base::Unretained(TtsPlatformImplLinux::GetInstance()),
-                   state));
+        base::BindOnce(&TtsPlatformImplLinux::OnSpeechEvent,
+                       base::Unretained(TtsPlatformImplLinux::GetInstance()),
+                       state));
   }
 }
 
diff --git a/content/browser/web_contents/web_drag_source_mac.mm b/content/browser/web_contents/web_drag_source_mac.mm
index d858836..8b8bc62 100644
--- a/content/browser/web_contents/web_drag_source_mac.mm
+++ b/content/browser/web_contents/web_drag_source_mac.mm
@@ -323,7 +323,7 @@
     // The writer will take care of closing and deletion.
     base::PostTaskWithTraits(
         FROM_HERE, {base::TaskPriority::USER_VISIBLE, base::MayBlock()},
-        base::Bind(&PromiseWriterHelper, *dropData_, base::Passed(&file)));
+        base::BindOnce(&PromiseWriterHelper, *dropData_, std::move(file)));
   }
 
   // The DragDownloadFile constructor may have altered the value of |filePath|
diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.cc
index 140d2812..8608272 100644
--- a/content/child/runtime_features.cc
+++ b/content/child/runtime_features.cc
@@ -225,8 +225,9 @@
   if (base::FeatureList::IsEnabled(features::kScrollAnchorSerialization))
     WebRuntimeFeatures::EnableScrollAnchorSerialization(true);
 
-  if (base::FeatureList::IsEnabled(blink::features::kBlinkGenPropertyTrees))
-    WebRuntimeFeatures::EnableFeatureFromString("BlinkGenPropertyTrees", true);
+  WebRuntimeFeatures::EnableFeatureFromString(
+      "BlinkGenPropertyTrees",
+      base::FeatureList::IsEnabled(blink::features::kBlinkGenPropertyTrees));
 
   WebRuntimeFeatures::EnablePassiveDocumentEventListeners(
       base::FeatureList::IsEnabled(features::kPassiveDocumentEventListeners));
diff --git a/content/public/renderer/render_frame.h b/content/public/renderer/render_frame.h
index 95179687..59f14073 100644
--- a/content/public/renderer/render_frame.h
+++ b/content/public/renderer/render_frame.h
@@ -8,6 +8,7 @@
 #include <stddef.h>
 
 #include <memory>
+#include <string>
 
 #include "base/callback_forward.h"
 #include "base/single_thread_task_runner.h"
@@ -20,6 +21,7 @@
 #include "ppapi/buildflags/buildflags.h"
 #include "services/network/public/mojom/url_loader_factory.mojom.h"
 #include "services/service_manager/public/cpp/binder_registry.h"
+#include "third_party/blink/public/common/loader/url_loader_factory_bundle.h"
 #include "third_party/blink/public/mojom/frame/document_interface_broker.mojom.h"
 #include "third_party/blink/public/platform/task_type.h"
 #include "third_party/blink/public/web/web_navigation_policy.h"
@@ -294,6 +296,16 @@
   virtual void SetRenderFrameMediaPlaybackOptions(
       const RenderFrameMediaPlaybackOptions& opts) = 0;
 
+  // Requests that fetches initiated by |initiator_origin| should go through the
+  // provided |url_loader_factory|.  This method should be called before
+  // executing scripts in a isolated world - such scripts are typically
+  // associated with a security origin different from the main world (and
+  // therefore fetches from such scripts set |request_initiator| that is
+  // incompatible with |request_initiator_site_lock|.
+  virtual void MarkInitiatorAsRequiringSeparateURLLoaderFactory(
+      const url::Origin& initiator_origin,
+      network::mojom::URLLoaderFactoryPtr url_loader_factory) = 0;
+
  protected:
   ~RenderFrame() override {}
 
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index 0c3bb08..ad7210706 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -3830,6 +3830,17 @@
       ->UpdateThisAndAllClones(std::move(subresource_loader_factories));
 }
 
+void RenderFrameImpl::MarkInitiatorAsRequiringSeparateURLLoaderFactory(
+    const url::Origin& initiator_origin,
+    network::mojom::URLLoaderFactoryPtr url_loader_factory) {
+  DCHECK(base::FeatureList::IsEnabled(network::features::kNetworkService));
+
+  auto factory_bundle = std::make_unique<blink::URLLoaderFactoryBundleInfo>();
+  factory_bundle->initiator_specific_factory_infos()[initiator_origin] =
+      url_loader_factory.PassInterface();
+  UpdateSubresourceLoaderFactories(std::move(factory_bundle));
+}
+
 void RenderFrameImpl::BindDevToolsAgent(
     blink::mojom::DevToolsAgentHostAssociatedPtrInfo host,
     blink::mojom::DevToolsAgentAssociatedRequest request) {
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h
index 1239e8b..b14e43bfe 100644
--- a/content/renderer/render_frame_impl.h
+++ b/content/renderer/render_frame_impl.h
@@ -613,6 +613,9 @@
   void UpdateSubresourceLoaderFactories(
       std::unique_ptr<blink::URLLoaderFactoryBundleInfo>
           subresource_loader_factories) override;
+  void MarkInitiatorAsRequiringSeparateURLLoaderFactory(
+      const url::Origin& initiator_origin,
+      network::mojom::URLLoaderFactoryPtr url_loader_factory) override;
   void BindDevToolsAgent(
       blink::mojom::DevToolsAgentHostAssociatedPtrInfo host,
       blink::mojom::DevToolsAgentAssociatedRequest request) override;
diff --git a/content/shell/browser/web_test/scoped_android_configuration.cc b/content/shell/browser/web_test/scoped_android_configuration.cc
index f675604..499d9b7 100644
--- a/content/shell/browser/web_test/scoped_android_configuration.cc
+++ b/content/shell/browser/web_test/scoped_android_configuration.cc
@@ -117,8 +117,8 @@
       base::WaitableEvent::InitialState::NOT_SIGNALED);
   base::PostTaskWithTraits(
       FROM_HERE, {BrowserThread::IO},
-      base::Bind(&CreateAndConnectSocket, port,
-                 base::Bind(finish_redirection, &redirected)));
+      base::BindOnce(&CreateAndConnectSocket, port,
+                     base::Bind(finish_redirection, &redirected)));
   base::ScopedAllowBaseSyncPrimitivesForTesting allow_wait;
   while (!redirected.IsSignaled())
     redirected.Wait();
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index f273e9420..36a1064 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -1131,6 +1131,7 @@
   if (is_win) {
     sources += [
       "../browser/accessibility/accessibility_win_browsertest.cc",
+      "../browser/accessibility/ax_platform_node_win_browsertest.cc",
       "../browser/renderer_host/direct_manipulation_browsertest.cc",
     ]
 
diff --git a/content/test/content_browser_test_utils_internal.cc b/content/test/content_browser_test_utils_internal.cc
index 9a1f101..20309b8 100644
--- a/content/test/content_browser_test_utils_internal.cc
+++ b/content/test/content_browser_test_utils_internal.cc
@@ -421,8 +421,8 @@
     const FrameHostMsg_ShowPopup_Params& params) {
   base::PostTaskWithTraits(
       FROM_HERE, {content::BrowserThread::UI},
-      base::Bind(&ShowWidgetMessageFilter::OnShowWidgetOnUI, this,
-                 MSG_ROUTING_NONE, params.bounds));
+      base::BindOnce(&ShowWidgetMessageFilter::OnShowWidgetOnUI, this,
+                     MSG_ROUTING_NONE, params.bounds));
 }
 #endif
 
diff --git a/content/test/data/accessibility/html/caption-expected-auralinux.txt b/content/test/data/accessibility/html/caption-expected-auralinux.txt
index c238565..970e6c0 100644
--- a/content/test/data/accessibility/html/caption-expected-auralinux.txt
+++ b/content/test/data/accessibility/html/caption-expected-auralinux.txt
@@ -1,5 +1,5 @@
 [document web]
-++[table] name='Browser and Engine'
+++[table] name='Browser and Engine' cols=2 headers=('Browser', 'Engine'); rows=3 headers=(NONE); caption=true; spans=(all: 1x1)
 ++++[caption]
 ++++++[text] name='Browser and Engine'
 ++++[table row]
diff --git a/content/test/data/accessibility/html/col-expected-auralinux.txt b/content/test/data/accessibility/html/col-expected-auralinux.txt
index 6481413..293ae464 100644
--- a/content/test/data/accessibility/html/col-expected-auralinux.txt
+++ b/content/test/data/accessibility/html/col-expected-auralinux.txt
@@ -1,5 +1,5 @@
 [document web]
-++[table]
+++[table] cols=2 headers=('Browser', 'Rendering Engine'); rows=2 headers=(NONE); caption=false; spans=(all: 1x1)
 ++++[table row]
 ++++++[column header] name='Browser'
 ++++++++[text] name='Browser'
diff --git a/content/test/data/accessibility/html/colgroup-expected-auralinux.txt b/content/test/data/accessibility/html/colgroup-expected-auralinux.txt
index 8861fab..a3b6397 100644
--- a/content/test/data/accessibility/html/colgroup-expected-auralinux.txt
+++ b/content/test/data/accessibility/html/colgroup-expected-auralinux.txt
@@ -1,5 +1,5 @@
 [document web]
-++[table]
+++[table] cols=2 headers=('Single', 'Pair'); rows=2 headers=(NONE); caption=false; spans=(all: 1x1)
 ++++[table row]
 ++++++[column header] name='Single'
 ++++++++[text] name='Single'
diff --git a/content/test/data/accessibility/html/contenteditable-descendants-expected-auralinux.txt b/content/test/data/accessibility/html/contenteditable-descendants-expected-auralinux.txt
index 99ad9ce..a5a5d7b 100644
--- a/content/test/data/accessibility/html/contenteditable-descendants-expected-auralinux.txt
+++ b/content/test/data/accessibility/html/contenteditable-descendants-expected-auralinux.txt
@@ -9,7 +9,7 @@
 ++++++[text] name=' and a ' editable
 ++++++[push button] name='Button' editable
 ++++++[text] name='.' editable
-++++[table] editable
+++++[table] editable cols=1 headers=(NONE); rows=1 headers=(NONE); caption=false; spans=(all: 1x1)
 ++++++[table row] editable
 ++++++++[table cell] name='Always expose editable tables as tables.' editable
 ++++++++++[text] name='Always expose editable tables as tables.' editable
diff --git a/content/test/data/accessibility/html/contenteditable-descendants-with-selection-expected-auralinux.txt b/content/test/data/accessibility/html/contenteditable-descendants-with-selection-expected-auralinux.txt
index 6592354..125348a 100644
--- a/content/test/data/accessibility/html/contenteditable-descendants-with-selection-expected-auralinux.txt
+++ b/content/test/data/accessibility/html/contenteditable-descendants-with-selection-expected-auralinux.txt
@@ -9,7 +9,7 @@
 ++++++[text] name=' and a ' editable
 ++++++[push button] name='Button' editable
 ++++++[text] name='.' editable
-++++[table] editable
+++++[table] editable cols=1 headers=(NONE); rows=1 headers=(NONE); caption=false; spans=(all: 1x1)
 ++++++[table row] editable
 ++++++++[table cell] name='Always expose editable tables as tables.' editable
 ++++++++++[text] name='Always expose editable tables as tables.' editable
diff --git a/content/test/data/accessibility/html/table-focusable-sections-expected-auralinux.txt b/content/test/data/accessibility/html/table-focusable-sections-expected-auralinux.txt
index 514a10a..97848ca 100644
--- a/content/test/data/accessibility/html/table-focusable-sections-expected-auralinux.txt
+++ b/content/test/data/accessibility/html/table-focusable-sections-expected-auralinux.txt
@@ -1,5 +1,5 @@
 [document web] name='Table example - focusable thead, tbody, tfoot'
-++[table]
+++[table] cols=2 headers=('Sum', 'Subtraction'); rows=4 headers=(NONE); caption=false; spans=(all: 1x1)
 ++++[panel]
 ++++++[table row]
 ++++++++[column header] name='Sum'
diff --git a/content/test/data/accessibility/html/table-simple-expected-auralinux.txt b/content/test/data/accessibility/html/table-simple-expected-auralinux.txt
index 1e1cb95..0687a97 100644
--- a/content/test/data/accessibility/html/table-simple-expected-auralinux.txt
+++ b/content/test/data/accessibility/html/table-simple-expected-auralinux.txt
@@ -1,5 +1,5 @@
 [document web] name='Table example'
-++[table]
+++[table] cols=2 headers=('Pair', 'Single'); rows=3 headers=(NONE); caption=false; spans=(all: 1x1)
 ++++[table row]
 ++++++[column header] name='Pair'
 ++++++++[text] name='Pair'
diff --git a/content/test/data/accessibility/html/table-spans-expected-auralinux.txt b/content/test/data/accessibility/html/table-spans-expected-auralinux.txt
index 06d542a4..f0fa7c7 100644
--- a/content/test/data/accessibility/html/table-spans-expected-auralinux.txt
+++ b/content/test/data/accessibility/html/table-spans-expected-auralinux.txt
@@ -1,5 +1,5 @@
 [document web] name='Table example with rowspan and colspan'
-++[table]
+++[table] cols=2 headers=(NONE); rows=2 headers=(NONE); caption=false; spans=(cell at 0,0: 2x1, cell at 1,0: 2x1)
 ++++[table row]
 ++++++[table cell] name='AD'
 ++++++++[text] name='AD'
@@ -8,7 +8,7 @@
 ++++[table row]
 ++++++[table cell] name='EF'
 ++++++++[text] name='EF'
-++[table]
+++[table] cols=3 headers=(NONE); rows=2 headers=(NONE); caption=false; spans=(cell at 0,0: 2x1, cell at 0,1: 1x2, cell at 0,2: 1x2, cell at 1,0: 2x1)
 ++++[table row]
 ++++++[table cell] name='AD'
 ++++++++[text] name='AD'
diff --git a/content/test/data/accessibility/html/table-th-colheader-expected-auralinux.txt b/content/test/data/accessibility/html/table-th-colheader-expected-auralinux.txt
index e4bdf1104..10721b8 100644
--- a/content/test/data/accessibility/html/table-th-colheader-expected-auralinux.txt
+++ b/content/test/data/accessibility/html/table-th-colheader-expected-auralinux.txt
@@ -1,5 +1,5 @@
 [document web]
-++[table]
+++[table] cols=2 headers=('Firstname', 'Lastname'); rows=2 headers=(NONE); caption=false; spans=(all: 1x1)
 ++++[table row]
 ++++++[column header] name='Firstname' table-cell-index:0
 ++++++++[text] name='Firstname'
diff --git a/content/test/data/accessibility/html/table-th-rowheader-expected-auralinux.txt b/content/test/data/accessibility/html/table-th-rowheader-expected-auralinux.txt
index 39622ccd..db40158 100644
--- a/content/test/data/accessibility/html/table-th-rowheader-expected-auralinux.txt
+++ b/content/test/data/accessibility/html/table-th-rowheader-expected-auralinux.txt
@@ -1,5 +1,5 @@
 [document web] name='Table example - th rowheader'
-++[table]
+++[table] cols=2 headers=(NONE); rows=2 headers=('Firstname', 'Lastname'); caption=false; spans=(all: 1x1)
 ++++[table row]
 ++++++[row header] name='Firstname'
 ++++++++[text] name='Firstname'
diff --git a/content/test/data/accessibility/html/table-thead-tbody-tfoot-expected-auralinux.txt b/content/test/data/accessibility/html/table-thead-tbody-tfoot-expected-auralinux.txt
index 36aeba2..285701d 100644
--- a/content/test/data/accessibility/html/table-thead-tbody-tfoot-expected-auralinux.txt
+++ b/content/test/data/accessibility/html/table-thead-tbody-tfoot-expected-auralinux.txt
@@ -1,5 +1,5 @@
 [document web] name='Table example - thead, tbody, tfoot'
-++[table]
+++[table] cols=2 headers=('Sum', 'Subtraction'); rows=4 headers=(NONE); caption=false; spans=(all: 1x1)
 ++++[table row]
 ++++++[column header] name='Sum'
 ++++++++[text] name='Sum'
diff --git a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
index 0b715ea..412ad009 100644
--- a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
+++ b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
@@ -98,8 +98,6 @@
         ['nvidia'], bug=792210)
 
     # Windows only.
-    self.Fail('conformance2/glsl3/array-initialize-with-same-name-array.html',
-        ['win'], bug=757098)
     self.Flaky('conformance2/textures/svg_image/' +
         'tex-2d-rgb565-rgb-unsigned_short_5_6_5.html',
         ['win'], bug=736926)
diff --git a/device/usb/usb_ids.h b/device/usb/usb_ids.h
index 7f8dbdd..c69aca4 100644
--- a/device/usb/usb_ids.h
+++ b/device/usb/usb_ids.h
@@ -13,14 +13,14 @@
 namespace device {
 
 struct UsbProduct {
-  uint16_t id;
+  const uint16_t id;
   const char* name;
 };
 
 struct UsbVendor {
-  uint16_t id;
+  const uint16_t id;
   const char* name;
-  size_t product_size;
+  const size_t product_size;
   const UsbProduct* products;
 };
 
diff --git a/docs/README.md b/docs/README.md
index 841aa7f..2d73da3a 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -354,6 +354,8 @@
     integrating new and existing subsystems into Chromium as services
 *   [Converting Legacy IPC to Mojo](mojo_ipc_conversion.md) - Tips and common
     patterns for practical IPC conversion work
+*   [Mojo “Style” Guide](security/mojo.md) - Recommendations for best practices
+    from Mojo and IPC reviewers
 
 ### Probably Obsolete
 *   [TPM Quick Reference](tpm_quick_ref.md) - Trusted Platform Module notes.
diff --git a/docs/android_native_libraries.md b/docs/android_native_libraries.md
index 2252250..a2dfa972e7 100644
--- a/docs/android_native_libraries.md
+++ b/docs/android_native_libraries.md
@@ -12,6 +12,35 @@
  * Android N+ (MonochromePublic.apk):
    * `libmonochrome.so` is stored uncompressed (AndroidManifest.xml attribute disables extraction) and loaded directly from the apk (functionality now supported by the system linker).
 
+## Crashpad Packaging
+ * Crashpad is a native library providing out-of-process crash dumping. When a
+   dump is requested (e.g. after a crash), a Crashpad handler process is started
+   to produce a dump.
+ * Chrome and ChromeModern (Android J through M):
+   * libcrashpad_handler.so is a standalone executable containing all of the
+     crash dumping code. It is stored compressed and extracted automatically by
+     the system, allowing it to be directly executed to produce a crash dump.
+ * Monochrome (N through P), Trichrome (P), and SystemWebView (P-):
+    * All of the Crashpad code is linked into the package's main native library
+      (e.g. libmonochrome.so). When a dump is requested, /system/bin/app_process
+      is executed, loading CrashpadMain.java which in turn uses JNI to call into
+      the native crash dumping code. This approach requires building CLASSPATH
+      and LD_LIBRARY_PATH variables to ensure app_process can locate
+      CrashpadMain.java and any native libraries (e.g. system libraries, shared
+      libraries, split apks, etc.) the package's main native library depends on.
+ * Monochrome, Trichrome, and SystemWebView (Q+):
+    * All of the Crashpad handler code is linked into the package's native
+      library. libcrashpad_handler_trampoline.so is a minimal executable
+      packaged with the main native library, stored uncompressed and left
+      unextracted. When a dump is requested, /system/bin/linker is executed to
+      load the trampoline from the APK, which in turn `dlopen()`s the main
+      native library to load the remaining Crashpad handler code. A trampoline
+      is used to de-duplicate shared code between Crashpad and the main native
+      library packaged with it. This approach isn't used for P- because the
+      linker doesn't support loading executables on its command line until Q.
+      This approach also requires building a suitable LD_LIBRARY_PATH to locate
+      any shared libraries Chrome/WebView depends on.
+
 ## Debug Information
 **What is it?**
  * Sections of an ELF that provide debugging and symbolization information (e.g. ability convert addresses to function & line numbers).
diff --git a/extensions/browser/api/async_api_function.cc b/extensions/browser/api/async_api_function.cc
index e5ea2a0..efc60cbff17 100644
--- a/extensions/browser/api/async_api_function.cc
+++ b/extensions/browser/api/async_api_function.cc
@@ -60,7 +60,7 @@
   if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
     bool rv = base::PostTaskWithTraits(
         FROM_HERE, {BrowserThread::UI},
-        base::Bind(&AsyncApiFunction::RespondOnUIThread, this));
+        base::BindOnce(&AsyncApiFunction::RespondOnUIThread, this));
     DCHECK(rv);
   } else {
     SendResponse(Respond());
diff --git a/extensions/browser/api/bluetooth_socket/bluetooth_socket_event_dispatcher.cc b/extensions/browser/api/bluetooth_socket/bluetooth_socket_event_dispatcher.cc
index 31a533f..b6dd6de 100644
--- a/extensions/browser/api/bluetooth_socket/bluetooth_socket_event_dispatcher.cc
+++ b/extensions/browser/api/bluetooth_socket/bluetooth_socket_event_dispatcher.cc
@@ -211,7 +211,7 @@
   // calling StartReceive at this point would error with ERR_IO_PENDING.
   base::PostTaskWithTraits(
       FROM_HERE, {params.thread_id},
-      base::Bind(&BluetoothSocketEventDispatcher::StartReceive, params));
+      base::BindOnce(&BluetoothSocketEventDispatcher::StartReceive, params));
 }
 
 // static
@@ -307,7 +307,7 @@
   // calling StartAccept at this point would error with ERR_IO_PENDING.
   base::PostTaskWithTraits(
       FROM_HERE, {params.thread_id},
-      base::Bind(&BluetoothSocketEventDispatcher::StartAccept, params));
+      base::BindOnce(&BluetoothSocketEventDispatcher::StartAccept, params));
 }
 
 // static
@@ -353,8 +353,8 @@
 
   base::PostTaskWithTraits(
       FROM_HERE, {BrowserThread::UI},
-      base::Bind(&DispatchEvent, params.browser_context_id, params.extension_id,
-                 base::Passed(std::move(event))));
+      base::BindOnce(&DispatchEvent, params.browser_context_id,
+                     params.extension_id, std::move(event)));
 }
 
 // static
diff --git a/extensions/browser/api/cast_channel/cast_channel_api.cc b/extensions/browser/api/cast_channel/cast_channel_api.cc
index 554274d6..f696f11 100644
--- a/extensions/browser/api/cast_channel/cast_channel_api.cc
+++ b/extensions/browser/api/cast_channel/cast_channel_api.cc
@@ -515,9 +515,8 @@
       OnError::Create(channel_info, error_info);
   std::unique_ptr<Event> event(new Event(
       events::CAST_CHANNEL_ON_ERROR, OnError::kEventName, std::move(results)));
-  base::PostTaskWithTraits(
-      FROM_HERE, {BrowserThread::UI},
-      base::Bind(ui_dispatch_cb_, base::Passed(std::move(event))));
+  base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+                           base::BindOnce(ui_dispatch_cb_, std::move(event)));
 }
 
 void CastChannelAPI::CastMessageHandler::OnMessage(
@@ -537,9 +536,8 @@
   std::unique_ptr<Event> event(new Event(events::CAST_CHANNEL_ON_MESSAGE,
                                          OnMessage::kEventName,
                                          std::move(results)));
-  base::PostTaskWithTraits(
-      FROM_HERE, {BrowserThread::UI},
-      base::Bind(ui_dispatch_cb_, base::Passed(std::move(event))));
+  base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+                           base::BindOnce(ui_dispatch_cb_, std::move(event)));
 }
 
 }  // namespace extensions
diff --git a/extensions/browser/api/cast_channel/cast_channel_apitest.cc b/extensions/browser/api/cast_channel/cast_channel_apitest.cc
index 4bfd4c5..4f2da57 100644
--- a/extensions/browser/api/cast_channel/cast_channel_apitest.cc
+++ b/extensions/browser/api/cast_channel/cast_channel_apitest.cc
@@ -205,8 +205,9 @@
   void CallOnMessage(const std::string& message) {
     base::PostTaskWithTraits(
         FROM_HERE, {content::BrowserThread::IO},
-        base::Bind(&CastChannelAPITest::DoCallOnMessage, base::Unretained(this),
-                   GetApi(), mock_cast_socket_, message));
+        base::BindOnce(&CastChannelAPITest::DoCallOnMessage,
+                       base::Unretained(this), GetApi(), mock_cast_socket_,
+                       message));
   }
 
   void DoCallOnMessage(extensions::CastChannelAPI* api,
@@ -221,8 +222,8 @@
   void FireTimeout() {
     base::PostTaskWithTraits(
         FROM_HERE, {content::BrowserThread::IO},
-        base::Bind(&CastChannelAPITest::DoFireTimeout, base::Unretained(this),
-                   mock_cast_socket_));
+        base::BindOnce(&CastChannelAPITest::DoFireTimeout,
+                       base::Unretained(this), mock_cast_socket_));
   }
 
   void DoFireTimeout(MockCastSocket* cast_socket) {
@@ -257,8 +258,9 @@
 ACTION_P2(InvokeObserverOnError, api_test, cast_socket_service) {
   base::PostTaskWithTraits(
       FROM_HERE, {content::BrowserThread::IO},
-      base::Bind(&CastChannelAPITest::DoCallOnError, base::Unretained(api_test),
-                 base::Unretained(cast_socket_service)));
+      base::BindOnce(&CastChannelAPITest::DoCallOnError,
+                     base::Unretained(api_test),
+                     base::Unretained(cast_socket_service)));
 }
 
 // TODO(kmarshall): Win Dbg has a workaround that makes RunExtensionSubtest
diff --git a/extensions/browser/api/declarative/rules_cache_delegate.cc b/extensions/browser/api/declarative/rules_cache_delegate.cc
index 360b400..0235911 100644
--- a/extensions/browser/api/declarative/rules_cache_delegate.cc
+++ b/extensions/browser/api/declarative/rules_cache_delegate.cc
@@ -146,7 +146,7 @@
 
   base::PostTaskWithTraits(
       FROM_HERE, {rules_registry_thread_},
-      base::Bind(&RulesRegistry::MarkReady, registry_, storage_init_time_));
+      base::BindOnce(&RulesRegistry::MarkReady, registry_, storage_init_time_));
   notified_registry_ = true;
 }
 
@@ -213,8 +213,8 @@
   DCHECK_EQ(Type::kPersistent, type_);
   base::PostTaskWithTraits(
       FROM_HERE, {rules_registry_thread_},
-      base::Bind(&RulesRegistry::DeserializeAndAddRules, registry_,
-                 extension_id, base::Passed(&value)));
+      base::BindOnce(&RulesRegistry::DeserializeAndAddRules, registry_,
+                     extension_id, std::move(value)));
 
   waiting_for_extensions_.erase(extension_id);
 
diff --git a/extensions/browser/api/declarative/rules_registry_service.cc b/extensions/browser/api/declarative/rules_registry_service.cc
index 058569db..92d1478b 100644
--- a/extensions/browser/api/declarative/rules_registry_service.cc
+++ b/extensions/browser/api/declarative/rules_registry_service.cc
@@ -76,10 +76,10 @@
   rule_registries_.clear();
   base::PostTaskWithTraits(
       FROM_HERE, {content::BrowserThread::IO},
-      base::Bind(&RegisterToExtensionWebRequestEventRouterOnIO,
-                 browser_context_,
-                 RulesRegistryService::kDefaultRulesRegistryID,
-                 scoped_refptr<WebRequestRulesRegistry>(NULL)));
+      base::BindOnce(&RegisterToExtensionWebRequestEventRouterOnIO,
+                     browser_context_,
+                     RulesRegistryService::kDefaultRulesRegistryID,
+                     scoped_refptr<WebRequestRulesRegistry>(NULL)));
 }
 
 static base::LazyInstance<BrowserContextKeyedAPIFactory<RulesRegistryService>>::
@@ -200,9 +200,9 @@
   RegisterRulesRegistry(web_request_rules_registry);
   base::PostTaskWithTraits(
       FROM_HERE, {content::BrowserThread::IO},
-      base::Bind(&RegisterToExtensionWebRequestEventRouterOnIO,
-                 browser_context_, rules_registry_id,
-                 web_request_rules_registry));
+      base::BindOnce(&RegisterToExtensionWebRequestEventRouterOnIO,
+                     browser_context_, rules_registry_id,
+                     web_request_rules_registry));
   return web_request_rules_registry;
 }
 
@@ -250,10 +250,10 @@
     if (content::BrowserThread::CurrentlyOn(registry->owner_thread())) {
       (registry.get()->*notification_callback)(extension);
     } else {
-      base::PostTaskWithTraits(
-          FROM_HERE, {registry->owner_thread()},
-          base::Bind(&NotifyWithExtensionSafe, base::WrapRefCounted(extension),
-                     notification_callback, registry));
+      base::PostTaskWithTraits(FROM_HERE, {registry->owner_thread()},
+                               base::BindOnce(&NotifyWithExtensionSafe,
+                                              base::WrapRefCounted(extension),
+                                              notification_callback, registry));
     }
   }
 }
diff --git a/extensions/browser/api/declarative_net_request/constants.cc b/extensions/browser/api/declarative_net_request/constants.cc
index 084b92f..06f0f9e 100644
--- a/extensions/browser/api/declarative_net_request/constants.cc
+++ b/extensions/browser/api/declarative_net_request/constants.cc
@@ -31,6 +31,8 @@
 const char kErrorListNotPassed[] = "*: Rules file must contain a list.";
 const char kErrorNonAscii[] =
     "*: Rule with id * cannot have non-ascii characters as part of \"*\" key.";
+const char kErrorInvalidUrlFilter[] =
+    "*: Rule with id * has an invalid value for \"*\" key.";
 
 const char kRuleCountExceeded[] =
     "Declarative Net Request: Rule count exceeded. Some rules were ignored.";
diff --git a/extensions/browser/api/declarative_net_request/constants.h b/extensions/browser/api/declarative_net_request/constants.h
index 930e802..e4ef8d71 100644
--- a/extensions/browser/api/declarative_net_request/constants.h
+++ b/extensions/browser/api/declarative_net_request/constants.h
@@ -31,6 +31,7 @@
   ERROR_NON_ASCII_URL_FILTER,
   ERROR_NON_ASCII_DOMAIN,
   ERROR_NON_ASCII_EXCLUDED_DOMAIN,
+  ERROR_INVALID_URL_FILTER,
 };
 
 // Rule parsing errors.
@@ -46,6 +47,7 @@
 extern const char kErrorPersisting[];
 extern const char kErrorListNotPassed[];
 extern const char kErrorNonAscii[];
+extern const char kErrorInvalidUrlFilter[];
 
 // Rule indexing install warnings.
 extern const char kRuleCountExceeded[];
diff --git a/extensions/browser/api/declarative_net_request/indexed_rule.cc b/extensions/browser/api/declarative_net_request/indexed_rule.cc
index cfdc48a..cac21e0 100644
--- a/extensions/browser/api/declarative_net_request/indexed_rule.cc
+++ b/extensions/browser/api/declarative_net_request/indexed_rule.cc
@@ -23,6 +23,10 @@
 namespace flat_rule = url_pattern_index::flat;
 namespace dnr_api = extensions::api::declarative_net_request;
 
+constexpr char kAnchorCharacter = '|';
+constexpr char kSeparatorCharacter = '^';
+constexpr char kWildcardCharacter = '*';
+
 // Returns true if bitmask |sub| is a subset of |super|.
 constexpr bool IsSubset(unsigned sub, unsigned super) {
   return (super | sub) == super;
@@ -108,10 +112,6 @@
     return IsAtValidIndex() && url_filter_[index_] == kAnchorCharacter;
   }
 
-  static constexpr char kAnchorCharacter = '|';
-  static constexpr char kSeparatorCharacter = '^';
-  static constexpr char kWildcardCharacter = '*';
-
   const std::string url_filter_;
   const size_t url_filter_len_;
   size_t index_;
@@ -332,6 +332,14 @@
   UrlFilterParser::Parse(std::move(parsed_rule.condition.url_filter),
                          indexed_rule);
 
+  // url_pattern_index doesn't support patterns starting with a domain anchor
+  // followed by a wildcard, e.g. ||*xyz.
+  if (indexed_rule->anchor_left == flat_rule::AnchorType_SUBDOMAIN &&
+      !indexed_rule->url_pattern.empty() &&
+      indexed_rule->url_pattern.front() == kWildcardCharacter) {
+    return ParseResult::ERROR_INVALID_URL_FILTER;
+  }
+
   // Lower-case case-insensitive patterns as required by url pattern index.
   if (indexed_rule->options & flat_rule::OptionFlag_IS_CASE_INSENSITIVE)
     indexed_rule->url_pattern = base::ToLowerASCII(indexed_rule->url_pattern);
diff --git a/extensions/browser/api/declarative_net_request/indexed_rule_unittest.cc b/extensions/browser/api/declarative_net_request/indexed_rule_unittest.cc
index fbf780f..129e1b4 100644
--- a/extensions/browser/api/declarative_net_request/indexed_rule_unittest.cc
+++ b/extensions/browser/api/declarative_net_request/indexed_rule_unittest.cc
@@ -269,7 +269,10 @@
                                                       L"ase.com")),
        flat_rule::UrlPatternType_SUBSTRING, flat_rule::AnchorType_NONE,
        flat_rule::AnchorType_NONE, "", ParseResult::ERROR_NON_ASCII_URL_FILTER},
-  };
+      // Url pattern starting with the domain anchor followed by a wildcard.
+      {std::make_unique<std::string>("||*xyz"),
+       flat_rule::UrlPatternType_WILDCARDED, flat_rule::AnchorType_SUBDOMAIN,
+       flat_rule::AnchorType_NONE, "", ParseResult::ERROR_INVALID_URL_FILTER}};
 
   for (size_t i = 0; i < base::size(cases); ++i) {
     SCOPED_TRACE(base::StringPrintf("Testing case[%" PRIuS "]", i));
diff --git a/extensions/browser/api/declarative_net_request/indexed_ruleset_format_version_unittest.cc b/extensions/browser/api/declarative_net_request/indexed_ruleset_format_version_unittest.cc
index 686cb3f..5b60de45 100644
--- a/extensions/browser/api/declarative_net_request/indexed_ruleset_format_version_unittest.cc
+++ b/extensions/browser/api/declarative_net_request/indexed_ruleset_format_version_unittest.cc
@@ -96,7 +96,7 @@
   EXPECT_EQ(StripCommentsAndWhitespace(kFlatbufferSchemaExpected),
             StripCommentsAndWhitespace(flatbuffer_schema))
       << "Schema change detected; update this test and the schema version.";
-  EXPECT_EQ(4, GetIndexedRulesetFormatVersionForTesting())
+  EXPECT_EQ(5, GetIndexedRulesetFormatVersionForTesting())
       << "Update this test if you update the schema version.";
 }
 
diff --git a/extensions/browser/api/declarative_net_request/parse_info.cc b/extensions/browser/api/declarative_net_request/parse_info.cc
index 356b5d8..2b70e05 100644
--- a/extensions/browser/api/declarative_net_request/parse_info.cc
+++ b/extensions/browser/api/declarative_net_request/parse_info.cc
@@ -107,6 +107,11 @@
           kErrorNonAscii, json_rules_filename, std::to_string(*rule_id_),
           kExcludedDomainsKey);
       break;
+    case ParseResult::ERROR_INVALID_URL_FILTER:
+      error = ErrorUtils::FormatErrorMessage(
+          kErrorInvalidUrlFilter, json_rules_filename,
+          std::to_string(*rule_id_), kUrlFilterKey);
+      break;
   }
   return error;
 }
diff --git a/extensions/browser/api/declarative_net_request/utils.cc b/extensions/browser/api/declarative_net_request/utils.cc
index 0799e59b..9564d0bc 100644
--- a/extensions/browser/api/declarative_net_request/utils.cc
+++ b/extensions/browser/api/declarative_net_request/utils.cc
@@ -50,12 +50,12 @@
 // url_pattern_index.fbs. Whenever an extension with an indexed ruleset format
 // version different from the one currently used by Chrome is loaded, the
 // extension ruleset will be reindexed.
-constexpr int kIndexedRulesetFormatVersion = 4;
+constexpr int kIndexedRulesetFormatVersion = 5;
 
 // This static assert is meant to catch cases where
 // url_pattern_index::kUrlPatternIndexFormatVersion is incremented without
 // updating kIndexedRulesetFormatVersion.
-static_assert(url_pattern_index::kUrlPatternIndexFormatVersion == 4,
+static_assert(url_pattern_index::kUrlPatternIndexFormatVersion == 5,
               "kUrlPatternIndexFormatVersion has changed, make sure you've "
               "also updated kIndexedRulesetFormatVersion above.");
 
diff --git a/extensions/browser/api/display_source/display_source_apitestbase.cc b/extensions/browser/api/display_source/display_source_apitestbase.cc
index cfda562..21541a9ba6 100644
--- a/extensions/browser/api/display_source/display_source_apitestbase.cc
+++ b/extensions/browser/api/display_source/display_source_apitestbase.cc
@@ -340,8 +340,8 @@
   // on UI thread and call OnSinkConnected() to proceed with the test
   base::PostTaskWithTraits(
       FROM_HERE, {BrowserThread::IO},
-      base::Bind(&MockDisplaySourceConnectionDelegate::BindToUdpSocket,
-                 base::Unretained(this)));
+      base::BindOnce(&MockDisplaySourceConnectionDelegate::BindToUdpSocket,
+                     base::Unretained(this)));
 }
 
 void MockDisplaySourceConnectionDelegate::Disconnect(
@@ -432,7 +432,7 @@
                         udp_port_, message);
 
   base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
-                           base::Bind(message_received_cb_, message));
+                           base::BindOnce(message_received_cb_, message));
 }
 
 void MockDisplaySourceConnectionDelegate::
@@ -489,8 +489,8 @@
       // Change sink's status to connected and proceed with the test.
       base::PostTaskWithTraits(
           FROM_HERE, {BrowserThread::UI},
-          base::Bind(&MockDisplaySourceConnectionDelegate::OnSinkConnected,
-                     base::Unretained(this)));
+          base::BindOnce(&MockDisplaySourceConnectionDelegate::OnSinkConnected,
+                         base::Unretained(this)));
       break;
     }
   }
@@ -526,8 +526,8 @@
     socket_->Close();
     base::PostTaskWithTraits(
         FROM_HERE, {BrowserThread::UI},
-        base::Bind(&MockDisplaySourceConnectionDelegate::Disconnect,
-                   base::Unretained(this), StringCallback()));
+        base::BindOnce(&MockDisplaySourceConnectionDelegate::Disconnect,
+                       base::Unretained(this), StringCallback()));
     return;
    }
 
diff --git a/extensions/browser/api/display_source/wifi_display/wifi_display_media_service_impl.cc b/extensions/browser/api/display_source/wifi_display/wifi_display_media_service_impl.cc
index 7c58af6..c5dde5e 100644
--- a/extensions/browser/api/display_source/wifi_display/wifi_display_media_service_impl.cc
+++ b/extensions/browser/api/display_source/wifi_display/wifi_display_media_service_impl.cc
@@ -56,9 +56,9 @@
 void WiFiDisplayMediaServiceImpl::BindToRequest(
     mojom::WiFiDisplayMediaServiceRequest request,
     content::RenderFrameHost* render_frame_host) {
-  base::PostTaskWithTraits(FROM_HERE, {BrowserThread::IO},
-                           base::Bind(WiFiDisplayMediaServiceImpl::Create,
-                                      base::Passed(std::move(request))));
+  base::PostTaskWithTraits(
+      FROM_HERE, {BrowserThread::IO},
+      base::BindOnce(WiFiDisplayMediaServiceImpl::Create, std::move(request)));
 }
 
 WiFiDisplayMediaServiceImpl::WiFiDisplayMediaServiceImpl()
diff --git a/extensions/browser/api/networking_private/networking_private_linux.cc b/extensions/browser/api/networking_private/networking_private_linux.cc
index 5cb2b8c..8f134d5 100644
--- a/extensions/browser/api/networking_private/networking_private_linux.cc
+++ b/extensions/browser/api/networking_private/networking_private_linux.cc
@@ -1219,8 +1219,8 @@
 
   base::PostTaskWithTraits(
       FROM_HERE, {content::BrowserThread::UI},
-      base::Bind(&NetworkingPrivateLinux::OnNetworksChangedEventTask,
-                 base::Unretained(this), base::Passed(&guid_list)));
+      base::BindOnce(&NetworkingPrivateLinux::OnNetworksChangedEventTask,
+                     base::Unretained(this), std::move(guid_list)));
 }
 
 void NetworkingPrivateLinux::OnNetworksChangedEventTask(
diff --git a/extensions/browser/api/socket/socket_api.cc b/extensions/browser/api/socket/socket_api.cc
index 4b85f45..df937d06 100644
--- a/extensions/browser/api/socket/socket_api.cc
+++ b/extensions/browser/api/socket/socket_api.cc
@@ -127,8 +127,8 @@
 
     base::PostTaskWithTraits(
         FROM_HERE, {BrowserThread::UI},
-        base::Bind(&SocketAsyncApiFunction::OpenFirewallHoleOnUIThread, this,
-                   type, local_address.port(), socket_id));
+        base::BindOnce(&SocketAsyncApiFunction::OpenFirewallHoleOnUIThread,
+                       this, type, local_address.port(), socket_id));
     return;
   }
 #endif
@@ -148,8 +148,8 @@
       manager->Open(type, port, extension_id()).release());
   base::PostTaskWithTraits(
       FROM_HERE, {BrowserThread::IO},
-      base::Bind(&SocketAsyncApiFunction::OnFirewallHoleOpened, this, socket_id,
-                 base::Passed(&hole)));
+      base::BindOnce(&SocketAsyncApiFunction::OnFirewallHoleOpened, this,
+                     socket_id, std::move(hole)));
 }
 
 void SocketAsyncApiFunction::OnFirewallHoleOpened(
diff --git a/extensions/browser/api/sockets_tcp/tcp_socket_event_dispatcher.cc b/extensions/browser/api/sockets_tcp/tcp_socket_event_dispatcher.cc
index a4fa44e..ca3191f 100644
--- a/extensions/browser/api/sockets_tcp/tcp_socket_event_dispatcher.cc
+++ b/extensions/browser/api/sockets_tcp/tcp_socket_event_dispatcher.cc
@@ -149,7 +149,7 @@
     // calling StartReceive at this point would error with ERR_IO_PENDING.
     base::PostTaskWithTraits(
         FROM_HERE, {params.thread_id},
-        base::Bind(&TCPSocketEventDispatcher::StartRead, params));
+        base::BindOnce(&TCPSocketEventDispatcher::StartRead, params));
   } else if (bytes_read == net::ERR_IO_PENDING) {
     // This happens when resuming a socket which already had an
     // active "read" callback.
@@ -185,8 +185,8 @@
 
   base::PostTaskWithTraits(
       FROM_HERE, {BrowserThread::UI},
-      base::Bind(&DispatchEvent, params.browser_context_id, params.extension_id,
-                 base::Passed(std::move(event))));
+      base::BindOnce(&DispatchEvent, params.browser_context_id,
+                     params.extension_id, std::move(event)));
 }
 
 // static
diff --git a/extensions/browser/api/sockets_tcp_server/tcp_server_socket_event_dispatcher.cc b/extensions/browser/api/sockets_tcp_server/tcp_server_socket_event_dispatcher.cc
index 523171e6..e28831d9 100644
--- a/extensions/browser/api/sockets_tcp_server/tcp_server_socket_event_dispatcher.cc
+++ b/extensions/browser/api/sockets_tcp_server/tcp_server_socket_event_dispatcher.cc
@@ -156,7 +156,7 @@
     // calling StartAccept at this point would error with ERR_IO_PENDING.
     base::PostTaskWithTraits(
         FROM_HERE, {params.thread_id},
-        base::Bind(&TCPServerSocketEventDispatcher::StartAccept, params));
+        base::BindOnce(&TCPServerSocketEventDispatcher::StartAccept, params));
   } else {
     // Dispatch "onAcceptError" event but don't start another accept to avoid
     // potential infinite "accepts" if we have a persistent network error.
@@ -187,8 +187,8 @@
 
   base::PostTaskWithTraits(
       FROM_HERE, {BrowserThread::UI},
-      base::Bind(&DispatchEvent, params.browser_context_id, params.extension_id,
-                 base::Passed(std::move(event))));
+      base::BindOnce(&DispatchEvent, params.browser_context_id,
+                     params.extension_id, std::move(event)));
 }
 
 // static
diff --git a/extensions/browser/api/sockets_udp/udp_socket_event_dispatcher.cc b/extensions/browser/api/sockets_udp/udp_socket_event_dispatcher.cc
index b910536f..daba597 100644
--- a/extensions/browser/api/sockets_udp/udp_socket_event_dispatcher.cc
+++ b/extensions/browser/api/sockets_udp/udp_socket_event_dispatcher.cc
@@ -134,7 +134,7 @@
     // calling StartReceive at this point would error with ERR_IO_PENDING.
     base::PostTaskWithTraits(
         FROM_HERE, {params.thread_id},
-        base::Bind(&UDPSocketEventDispatcher::StartReceive, params));
+        base::BindOnce(&UDPSocketEventDispatcher::StartReceive, params));
   } else if (bytes_read == net::ERR_IO_PENDING) {
     // This happens when resuming a socket which already had an
     // active "recv" callback.
@@ -173,8 +173,8 @@
 
   base::PostTaskWithTraits(
       FROM_HERE, {BrowserThread::UI},
-      base::Bind(&DispatchEvent, params.browser_context_id, params.extension_id,
-                 base::Passed(std::move(event))));
+      base::BindOnce(&DispatchEvent, params.browser_context_id,
+                     params.extension_id, std::move(event)));
 }
 
 /*static*/
diff --git a/extensions/browser/api/storage/storage_api.cc b/extensions/browser/api/storage/storage_api.cc
index c023dc6..ecc8a46 100644
--- a/extensions/browser/api/storage/storage_api.cc
+++ b/extensions/browser/api/storage/storage_api.cc
@@ -70,7 +70,7 @@
   ResponseValue response = RunWithStorage(storage);
   base::PostTaskWithTraits(
       FROM_HERE, {BrowserThread::UI},
-      base::Bind(&SettingsFunction::Respond, this, base::Passed(&response)));
+      base::BindOnce(&SettingsFunction::Respond, this, std::move(response)));
 }
 
 ExtensionFunction::ResponseValue SettingsFunction::UseReadResult(
diff --git a/extensions/browser/api/virtual_keyboard_private/virtual_keyboard_private_api_unittest.cc b/extensions/browser/api/virtual_keyboard_private/virtual_keyboard_private_api_unittest.cc
index 4f56bee..3a46f1c 100644
--- a/extensions/browser/api/virtual_keyboard_private/virtual_keyboard_private_api_unittest.cc
+++ b/extensions/browser/api/virtual_keyboard_private/virtual_keyboard_private_api_unittest.cc
@@ -121,7 +121,7 @@
                           .GetDelegateForBrowserContext(browser_context())
                           ->GetOccludedBounds();
   EXPECT_EQ(0U, bounds.size());
-};
+}
 
 TEST_F(VirtualKeyboardPrivateApiUnittest, SetOccludedBoundsWithOneBound) {
   RunFunction(new VirtualKeyboardPrivateSetOccludedBoundsFunction(),
@@ -132,7 +132,7 @@
                           ->GetOccludedBounds();
   ASSERT_EQ(1U, bounds.size());
   EXPECT_EQ(gfx::Rect(0, 10, 20, 30), bounds[0]);
-};
+}
 
 TEST_F(VirtualKeyboardPrivateApiUnittest, SetOccludedBoundsWithTwoBounds) {
   RunFunction(new VirtualKeyboardPrivateSetOccludedBoundsFunction(),
@@ -145,7 +145,7 @@
   ASSERT_EQ(2U, bounds.size());
   EXPECT_EQ(gfx::Rect(0, 10, 20, 30), bounds[0]);
   EXPECT_EQ(gfx::Rect(10, 20, 30, 40), bounds[1]);
-};
+}
 
 TEST_F(VirtualKeyboardPrivateApiUnittest, SetHitTestBoundsWithNoBounds) {
   RunFunction(new VirtualKeyboardPrivateSetHitTestBoundsFunction(), "[[]]");
@@ -154,7 +154,7 @@
                           .GetDelegateForBrowserContext(browser_context())
                           ->GetHitTestBounds();
   EXPECT_EQ(0U, bounds.size());
-};
+}
 
 TEST_F(VirtualKeyboardPrivateApiUnittest, SetHitTestBoundsWithMultipleBounds) {
   RunFunction(new VirtualKeyboardPrivateSetHitTestBoundsFunction(),
@@ -167,6 +167,6 @@
   ASSERT_EQ(2U, bounds.size());
   EXPECT_EQ(gfx::Rect(0, 10, 20, 30), bounds[0]);
   EXPECT_EQ(gfx::Rect(10, 20, 30, 40), bounds[1]);
-};
+}
 
 }  // namespace extensions
diff --git a/extensions/browser/api/web_request/web_request_api.cc b/extensions/browser/api/web_request/web_request_api.cc
index 339bc00..639ae63 100644
--- a/extensions/browser/api/web_request/web_request_api.cc
+++ b/extensions/browser/api/web_request/web_request_api.cc
@@ -632,7 +632,7 @@
   // singleton is leaked.
   base::PostTaskWithTraits(
       FROM_HERE, {BrowserThread::IO},
-      base::Bind(
+      base::BindOnce(
           &ExtensionWebRequestEventRouter::RemoveEventListener,
           base::Unretained(ExtensionWebRequestEventRouter::GetInstance()), id,
           false /* not strict */));
@@ -2170,10 +2170,11 @@
                                GetRequestStageAsString(blocked_request.event));
       base::PostTaskWithTraits(
           FROM_HERE, {BrowserThread::UI},
-          base::Bind(&SendOnMessageEventOnUI, browser_context,
-                     delta.extension_id, blocked_request.request->is_web_view,
-                     blocked_request.request->web_view_instance_id,
-                     base::Passed(&event_details)));
+          base::BindOnce(&SendOnMessageEventOnUI, browser_context,
+                         delta.extension_id,
+                         blocked_request.request->is_web_view,
+                         blocked_request.request->web_view_instance_id,
+                         std::move(event_details)));
     }
   }
 }
@@ -2746,9 +2747,9 @@
   WarningSet warnings;
   warnings.insert(
       Warning::CreateRepeatedCacheFlushesWarning(extension_id_safe()));
-  base::PostTaskWithTraits(
-      FROM_HERE, {BrowserThread::UI},
-      base::Bind(&WarningService::NotifyWarningsOnUI, profile_id(), warnings));
+  base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+                           base::BindOnce(&WarningService::NotifyWarningsOnUI,
+                                          profile_id(), warnings));
 
   // Continue gracefully.
   RunWithValidation()->Execute();
diff --git a/extensions/browser/api/web_request/web_request_api_helpers.cc b/extensions/browser/api/web_request/web_request_api_helpers.cc
index 880c80fa..362b80fe 100644
--- a/extensions/browser/api/web_request/web_request_api_helpers.cc
+++ b/extensions/browser/api/web_request/web_request_api_helpers.cc
@@ -1236,7 +1236,7 @@
     ClearCacheOnNavigationOnUI();
   } else {
     base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI},
-                             base::Bind(&ClearCacheOnNavigationOnUI));
+                             base::BindOnce(&ClearCacheOnNavigationOnUI));
   }
 }
 
diff --git a/extensions/browser/api/web_request/web_request_permissions_unittest.cc b/extensions/browser/api/web_request/web_request_permissions_unittest.cc
index 6acb19d..f375041 100644
--- a/extensions/browser/api/web_request/web_request_permissions_unittest.cc
+++ b/extensions/browser/api/web_request/web_request_permissions_unittest.cc
@@ -202,7 +202,7 @@
   extension->permissions_data()->SetPermissions(
       std::make_unique<PermissionSet>(),  // active permissions.
       std::make_unique<PermissionSet>(
-          APIPermissionSet(), ManifestPermissionSet(), all_urls,
+          APIPermissionSet(), ManifestPermissionSet(), all_urls.Clone(),
           URLPatternSet()) /* withheld permissions */);
 
   scoped_refptr<InfoMap> info_map = base::MakeRefCounted<InfoMap>();
@@ -249,11 +249,11 @@
   URLPatternSet chromium_org_patterns({URLPattern(
       Extension::kValidHostPermissionSchemes, "https://chromium.org/*")});
   extension->permissions_data()->SetPermissions(
+      std::make_unique<PermissionSet>(
+          APIPermissionSet(), ManifestPermissionSet(),
+          std::move(chromium_org_patterns), URLPatternSet()),
       std::make_unique<PermissionSet>(APIPermissionSet(),
-                                      ManifestPermissionSet(),
-                                      chromium_org_patterns, URLPatternSet()),
-      std::make_unique<PermissionSet>(APIPermissionSet(),
-                                      ManifestPermissionSet(), all_urls,
+                                      ManifestPermissionSet(), all_urls.Clone(),
                                       URLPatternSet()));
 
   // example.com isn't granted, so without an initiator or with an initiator
@@ -312,11 +312,13 @@
 
   extension->permissions_data()->SetPermissions(
       std::make_unique<PermissionSet>(
-          APIPermissionSet(), ManifestPermissionSet(), kActivePatternSet,
-          kActivePatternSet),  // active permissions.
+          APIPermissionSet(), ManifestPermissionSet(),
+          kActivePatternSet.Clone(),
+          kActivePatternSet.Clone()),  // active permissions.
       std::make_unique<PermissionSet>(
-          APIPermissionSet(), ManifestPermissionSet(), kWithheldPatternSet,
-          kWithheldPatternSet) /* withheld permissions */);
+          APIPermissionSet(), ManifestPermissionSet(),
+          kWithheldPatternSet.Clone(),
+          kWithheldPatternSet.Clone()) /* withheld permissions */);
 
   scoped_refptr<InfoMap> info_map = base::MakeRefCounted<InfoMap>();
   info_map->AddExtension(extension.get(), base::Time(), false, false);
diff --git a/extensions/browser/api/webcam_private/visca_webcam.cc b/extensions/browser/api/webcam_private/visca_webcam.cc
index 3c768c0..99ce663 100644
--- a/extensions/browser/api/webcam_private/visca_webcam.cc
+++ b/extensions/browser/api/webcam_private/visca_webcam.cc
@@ -170,8 +170,9 @@
                        const OpenCompleteCallback& open_callback) {
   base::PostTaskWithTraits(
       FROM_HERE, {BrowserThread::IO},
-      base::Bind(&ViscaWebcam::OpenOnIOThread, weak_ptr_factory_.GetWeakPtr(),
-                 extension_id, base::Passed(&port_ptr_info), open_callback));
+      base::BindOnce(&ViscaWebcam::OpenOnIOThread,
+                     weak_ptr_factory_.GetWeakPtr(), extension_id,
+                     std::move(port_ptr_info), open_callback));
 }
 
 void ViscaWebcam::OpenOnIOThread(const std::string& extension_id,
@@ -237,7 +238,7 @@
   }
 
   base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
-                           base::Bind(open_callback, true));
+                           base::BindOnce(open_callback, true));
 }
 
 void ViscaWebcam::Send(const std::vector<char>& command,
@@ -247,8 +248,8 @@
   if (commands_.size() == 1) {
     base::PostTaskWithTraits(
         FROM_HERE, {BrowserThread::IO},
-        base::Bind(&ViscaWebcam::SendOnIOThread, weak_ptr_factory_.GetWeakPtr(),
-                   command, callback));
+        base::BindOnce(&ViscaWebcam::SendOnIOThread,
+                       weak_ptr_factory_.GetWeakPtr(), command, callback));
   }
 }
 
@@ -271,8 +272,9 @@
         base::BindRepeating(&ViscaWebcam::OnReceiveEvent,
                             weak_ptr_factory_.GetWeakPtr(), callback));
   } else {
-    base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
-                             base::Bind(callback, false, std::vector<char>()));
+    base::PostTaskWithTraits(
+        FROM_HERE, {BrowserThread::UI},
+        base::BindOnce(callback, false, std::vector<char>()));
   }
 }
 
@@ -287,7 +289,7 @@
     std::vector<char> response;
     response.swap(data_buffer_);
     base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
-                             base::Bind(callback, false, response));
+                             base::BindOnce(callback, false, response));
     serial_connection_->set_paused(true);
     return;
   }
@@ -305,13 +307,13 @@
   if (response.size() < 2 ||
       (static_cast<int>(response[1]) & 0xF0) == kViscaResponseError) {
     base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
-                             base::Bind(callback, false, response));
+                             base::BindOnce(callback, false, response));
     serial_connection_->set_paused(true);
   } else if ((static_cast<int>(response[1]) & 0xF0) != kViscaResponseAck &&
              (static_cast<int>(response[1]) & 0xFF) !=
                  kViscaResponseNetworkChange) {
     base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
-                             base::Bind(callback, true, response));
+                             base::BindOnce(callback, true, response));
     serial_connection_->set_paused(true);
   }
 }
@@ -392,16 +394,16 @@
   // If there are pending commands, process the next one.
   const std::vector<char> next_command = commands_.front().first;
   const CommandCompleteCallback next_callback = commands_.front().second;
-  base::PostTaskWithTraits(
-      FROM_HERE, {BrowserThread::IO},
-      base::Bind(&ViscaWebcam::SendOnIOThread, weak_ptr_factory_.GetWeakPtr(),
-                 next_command, next_callback));
+  base::PostTaskWithTraits(FROM_HERE, {BrowserThread::IO},
+                           base::BindOnce(&ViscaWebcam::SendOnIOThread,
+                                          weak_ptr_factory_.GetWeakPtr(),
+                                          next_command, next_callback));
 }
 
 void ViscaWebcam::PostOpenFailureTask(
     const OpenCompleteCallback& open_callback) {
   base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
-                           base::Bind(open_callback, false /* success? */));
+                           base::BindOnce(open_callback, false /* success? */));
 }
 
 void ViscaWebcam::GetPan(const GetPTZCompleteCallback& callback) {
diff --git a/extensions/browser/extension_prefs.cc b/extensions/browser/extension_prefs.cc
index a39b181..bbbbd74 100644
--- a/extensions/browser/extension_prefs.cc
+++ b/extensions/browser/extension_prefs.cc
@@ -580,9 +580,9 @@
       extension_id, JoinPrefs(pref_key, kPrefScriptableHosts),
       &scriptable_hosts, UserScript::ValidUserScriptSchemes());
 
-  return std::make_unique<PermissionSet>(std::move(apis),
-                                         std::move(manifest_permissions),
-                                         explicit_hosts, scriptable_hosts);
+  return std::make_unique<PermissionSet>(
+      std::move(apis), std::move(manifest_permissions),
+      std::move(explicit_hosts), std::move(scriptable_hosts));
 }
 
 // Set the API or Manifest permissions.
diff --git a/extensions/browser/guest_view/web_view/web_view_guest.cc b/extensions/browser/guest_view/web_view/web_view_guest.cc
index a554840..976f975 100644
--- a/extensions/browser/guest_view/web_view/web_view_guest.cc
+++ b/extensions/browser/guest_view/web_view/web_view_guest.cc
@@ -244,8 +244,8 @@
   // Clean up web request event listeners for the WebView.
   base::PostTaskWithTraits(
       FROM_HERE, {content::BrowserThread::IO},
-      base::Bind(&RemoveWebViewEventListenersOnIOThread, browser_context,
-                 embedder_process_id, view_instance_id));
+      base::BindOnce(&RemoveWebViewEventListenersOnIOThread, browser_context,
+                     embedder_process_id, view_instance_id));
 
   // Clean up content scripts for the WebView.
   auto* csm = WebViewContentScriptManager::Get(browser_context);
diff --git a/extensions/browser/requirements_checker.cc b/extensions/browser/requirements_checker.cc
index 8f2654df..163dcaf 100644
--- a/extensions/browser/requirements_checker.cc
+++ b/extensions/browser/requirements_checker.cc
@@ -78,8 +78,8 @@
   // ExtensionService::LoadExtensionsFromCommandLineFlag(). Remove these helper
   // functions after crbug.com/708354 is addressed.
   base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI},
-                           base::Bind(&RequirementsChecker::RunCallback,
-                                      weak_ptr_factory_.GetWeakPtr()));
+                           base::BindOnce(&RequirementsChecker::RunCallback,
+                                          weak_ptr_factory_.GetWeakPtr()));
 }
 
 void RequirementsChecker::RunCallback() {
diff --git a/extensions/browser/url_loader_factory_manager.cc b/extensions/browser/url_loader_factory_manager.cc
index edf8eb4..c907271d 100644
--- a/extensions/browser/url_loader_factory_manager.cc
+++ b/extensions/browser/url_loader_factory_manager.cc
@@ -57,18 +57,21 @@
 // point they can be removed from the allowlist.
 //
 // Migration plan for extension developers is described at
-// https://docs.google.com/document/d/1wOFTUmwM4NsDfjY4K6aXAbIyH7WJwLFPPIb5KAa1YZ8
+// https://chromium.org/Home/chromium-security/extension-content-script-fetches
 const char* kHardcodedPartOfCorbAllowlist[] = {
     "0149C10F1124F1ED6ACAD85C45E87A76A9DDC667",
     "072D729E856B1F2C9894AEEC3A5DF65E519D6BEE",
+    "0EAEA2FDEE025D95B3ABB37014EFF5A98AC4BEAE",
     "16A81AEA09A67B03F7AEA5B957D24A4095E764BE",
     "177508B365CBF1610CC2B53707749D79272F2F0B",
     "1AB9CC404876117F49135E67BAD813F935AAE9BA",
+    "1DB115A4344B58C0B7CC1595662E86C9E92C0848",
     "260871EABEDE6F2D07D0D9450096093EDAFCBF34",
     "2AA94E2D3F4DA33F0D3BCF5DD48F69B8BDB26F52",
     "3334952C8387B357A41DD8349D39AD9E7C423943",
     "360D8A88545D0C21CBDE2B55EA9E4E4285282B4C",
     "3FDD3DB17F3B686F5A05204700ABA13DF20AE957",
+    "4913450195D177430217CAB64B356DC6F6B0F483",
     "505F2C1E723731B2C8C9182FEAA73D00525B2048",
     "61E581B10D83C0AEF8366BB64C18C6615884B3D2",
     "6AE81EF3B13B15080A2DDB23A205A24C65CCC10B",
@@ -78,6 +81,7 @@
     "808FA9BB3CD501D7801D1CD6D5A3DBA088FDD46F",
     "82FDBBF79F3517C3946BD89EAAF90C46DFDA4681",
     "88C372CE52E21560C17BFD52556E60D694E12CAC",
+    "88F5F459139892C0F5DF3022676726BB3F01FB5C",
     "934B8F5753A3E5A276FC7D0EE5E575B335A0CC76",
     "973E35633030AD27DABEC99609424A61386C7309",
     "99E06C364BBB2D1F82A9D20BC1645BF21E478259",
@@ -93,6 +97,7 @@
     "D0537B1BADCE856227CE76E31B3772F6B68F653C",
     "E7036E906DBFB77C46EDDEB003A72C0B5CC9BE7F",
     "EC24668224116D19FF1A5FFAA61238B88773982C",
+    "EE4BE5F23D2E59E4713958465941EFB4A18166B7",
     "F59AB261280AB3AE9826D9359507838B90B07431",
 };
 
diff --git a/extensions/browser/value_store/value_store_frontend.cc b/extensions/browser/value_store/value_store_frontend.cc
index 606e2b91..f167cc5 100644
--- a/extensions/browser/value_store/value_store_frontend.cc
+++ b/extensions/browser/value_store/value_store_frontend.cc
@@ -47,8 +47,8 @@
 
     base::PostTaskWithTraits(
         FROM_HERE, {BrowserThread::UI},
-        base::Bind(&ValueStoreFrontend::Backend::RunCallback, this, callback,
-                   base::Passed(&value)));
+        base::BindOnce(&ValueStoreFrontend::Backend::RunCallback, this,
+                       callback, std::move(value)));
   }
 
   void Set(const std::string& key, std::unique_ptr<base::Value> value) {
diff --git a/extensions/common/extension_messages.cc b/extensions/common/extension_messages.cc
index 07003d4..b067beed 100644
--- a/extensions/common/extension_messages.cc
+++ b/extensions/common/extension_messages.cc
@@ -48,9 +48,9 @@
 std::unique_ptr<const PermissionSet>
 ExtensionMsg_PermissionSetStruct::ToPermissionSet() const {
   // TODO(devlin): Make this destructive so we can std::move() the members.
-  return std::make_unique<PermissionSet>(apis.Clone(),
-                                         manifest_permissions.Clone(),
-                                         explicit_hosts, scriptable_hosts);
+  return std::make_unique<PermissionSet>(
+      apis.Clone(), manifest_permissions.Clone(), explicit_hosts.Clone(),
+      scriptable_hosts.Clone());
 }
 
 ExtensionMsg_Loaded_Params::ExtensionMsg_Loaded_Params()
diff --git a/extensions/common/manifest_handlers/permissions_parser.cc b/extensions/common/manifest_handlers/permissions_parser.cc
index 0c1d632..2e07b78 100644
--- a/extensions/common/manifest_handlers/permissions_parser.cc
+++ b/extensions/common/manifest_handlers/permissions_parser.cc
@@ -355,11 +355,13 @@
   ManifestHandler::AddExtensionInitialRequiredPermissions(
       extension, &initial_required_permissions_->manifest_permissions);
 
+  // TODO(devlin): Make this destructive and std::move() from initial
+  // permissions so we can std::move() the sets.
   std::unique_ptr<const PermissionSet> required_permissions(new PermissionSet(
       initial_required_permissions_->api_permissions.Clone(),
       initial_required_permissions_->manifest_permissions.Clone(),
-      initial_required_permissions_->host_permissions,
-      initial_required_permissions_->scriptable_hosts));
+      initial_required_permissions_->host_permissions.Clone(),
+      initial_required_permissions_->scriptable_hosts.Clone()));
   extension->SetManifestData(
       keys::kPermissions,
       std::make_unique<ManifestPermissions>(std::move(required_permissions)));
@@ -367,7 +369,8 @@
   std::unique_ptr<const PermissionSet> optional_permissions(new PermissionSet(
       initial_optional_permissions_->api_permissions.Clone(),
       initial_optional_permissions_->manifest_permissions.Clone(),
-      initial_optional_permissions_->host_permissions, URLPatternSet()));
+      initial_optional_permissions_->host_permissions.Clone(),
+      URLPatternSet()));
   extension->SetManifestData(
       keys::kOptionalPermissions,
       std::make_unique<ManifestPermissions>(std::move(optional_permissions)));
diff --git a/extensions/common/permissions/permission_set.cc b/extensions/common/permissions/permission_set.cc
index 4428e59d..72e1e24 100644
--- a/extensions/common/permissions/permission_set.cc
+++ b/extensions/common/permissions/permission_set.cc
@@ -5,6 +5,8 @@
 #include "extensions/common/permissions/permission_set.h"
 
 #include <memory>
+#include <utility>
+#include <vector>
 
 #include "base/memory/ptr_util.h"
 #include "extensions/common/permissions/permissions_info.h"
@@ -16,17 +18,36 @@
 PermissionSet::PermissionSet() {}
 PermissionSet::PermissionSet(APIPermissionSet apis,
                              ManifestPermissionSet manifest_permissions,
-                             const URLPatternSet& explicit_hosts,
-                             const URLPatternSet& scriptable_hosts)
+                             URLPatternSet explicit_hosts,
+                             URLPatternSet scriptable_hosts)
     : apis_(std::move(apis)),
       manifest_permissions_(std::move(manifest_permissions)),
-      scriptable_hosts_(scriptable_hosts.Clone()) {
-  for (URLPattern pattern : explicit_hosts) {
-    // Strip the paths from the incoming explicit hosts; we don't use them.
-    pattern.SetPath("/*");
-    explicit_hosts_.AddPattern(std::move(pattern));
+      explicit_hosts_(std::move(explicit_hosts)),
+      scriptable_hosts_(std::move(scriptable_hosts)) {
+  // For explicit hosts, we require the path to be "/*". This is a little
+  // tricky, since URLPatternSets are backed by a std::set<>, where the
+  // elements are immutable (because they themselves are the keys). In order to
+  // work around this, we find the patterns we need to update, collect updated
+  // versions, remove them, and then insert the updated ones. This isn't very
+  // clean, but does mean that all the other URLPatterns in the set (which is
+  // likely the majority) get to be std::move'd efficiently.
+  // NOTE(devlin): This would be non-issue if URLPatternSet() was backed by e.g.
+  // a vector.
+  std::vector<URLPattern> modified_patterns;
+  for (auto iter = explicit_hosts_.begin(); iter != explicit_hosts_.end();) {
+    if (iter->path() == "/*") {
+      ++iter;
+      continue;
+    }
+    URLPattern modified_pattern(*iter);
+    modified_pattern.SetPath("/*");
+    modified_patterns.push_back(std::move(modified_pattern));
+    iter = explicit_hosts_.erase(iter);
   }
 
+  for (URLPattern& pattern : modified_patterns)
+    explicit_hosts_.AddPattern(std::move(pattern));
+
   InitImplicitPermissions();
   InitEffectiveHosts();
 }
@@ -51,9 +72,9 @@
   URLPatternSet scriptable_hosts = URLPatternSet::CreateDifference(
       set1.scriptable_hosts(), set2.scriptable_hosts());
 
-  return base::WrapUnique(new PermissionSet(std::move(apis),
-                                            std::move(manifest_permissions),
-                                            explicit_hosts, scriptable_hosts));
+  return base::WrapUnique(new PermissionSet(
+      std::move(apis), std::move(manifest_permissions),
+      std::move(explicit_hosts), std::move(scriptable_hosts)));
 }
 
 // static
@@ -74,9 +95,9 @@
   URLPatternSet scriptable_hosts = URLPatternSet::CreateIntersection(
       set1.scriptable_hosts(), set2.scriptable_hosts(), intersection_behavior);
 
-  return base::WrapUnique(new PermissionSet(std::move(apis),
-                                            std::move(manifest_permissions),
-                                            explicit_hosts, scriptable_hosts));
+  return base::WrapUnique(new PermissionSet(
+      std::move(apis), std::move(manifest_permissions),
+      std::move(explicit_hosts), std::move(scriptable_hosts)));
 }
 
 // static
@@ -97,9 +118,9 @@
   URLPatternSet scriptable_hosts = URLPatternSet::CreateUnion(
       set1.scriptable_hosts(), set2.scriptable_hosts());
 
-  return base::WrapUnique(new PermissionSet(std::move(apis),
-                                            std::move(manifest_permissions),
-                                            explicit_hosts, scriptable_hosts));
+  return base::WrapUnique(new PermissionSet(
+      std::move(apis), std::move(manifest_permissions),
+      std::move(explicit_hosts), std::move(scriptable_hosts)));
 }
 
 bool PermissionSet::operator==(
diff --git a/extensions/common/permissions/permission_set.h b/extensions/common/permissions/permission_set.h
index 18d5afe..af611b7 100644
--- a/extensions/common/permissions/permission_set.h
+++ b/extensions/common/permissions/permission_set.h
@@ -37,9 +37,8 @@
   // inferred from the given host permissions.
   PermissionSet(APIPermissionSet apis,
                 ManifestPermissionSet manifest_permissions,
-                // TODO(devlin): Pass these by value.
-                const URLPatternSet& explicit_hosts,
-                const URLPatternSet& scriptable_hosts);
+                URLPatternSet explicit_hosts,
+                URLPatternSet scriptable_hosts);
   ~PermissionSet();
 
   // Creates a new permission set equal to |set1| - |set2|.
diff --git a/extensions/common/url_pattern_set.h b/extensions/common/url_pattern_set.h
index c1c5e8f3..aa7c1a28 100644
--- a/extensions/common/url_pattern_set.h
+++ b/extensions/common/url_pattern_set.h
@@ -96,6 +96,7 @@
   const std::set<URLPattern>& patterns() const { return patterns_; }
   const_iterator begin() const { return patterns_.begin(); }
   const_iterator end() const { return patterns_.end(); }
+  iterator erase(iterator iter) { return patterns_.erase(iter); }
 
   // Returns a copy of this URLPatternSet; not instrumented as a copy
   // constructor to avoid accidental/unnecessary copies.
diff --git a/extensions/renderer/dispatcher.cc b/extensions/renderer/dispatcher.cc
index be331a4d..a6878cf 100644
--- a/extensions/renderer/dispatcher.cc
+++ b/extensions/renderer/dispatcher.cc
@@ -1191,7 +1191,7 @@
   extension->permissions_data()->UpdateTabSpecificPermissions(
       tab_id, extensions::PermissionSet(extensions::APIPermissionSet(),
                                         extensions::ManifestPermissionSet(),
-                                        new_hosts, new_hosts));
+                                        new_hosts.Clone(), new_hosts.Clone()));
 
   if (update_origin_whitelist)
     UpdateOriginPermissions(*extension);
diff --git a/extensions/shell/browser/shell_browser_context.cc b/extensions/shell/browser/shell_browser_context.cc
index f170020..eb7dad28 100644
--- a/extensions/shell/browser/shell_browser_context.cc
+++ b/extensions/shell/browser/shell_browser_context.cc
@@ -73,8 +73,8 @@
       extension_info_map));
   base::PostTaskWithTraits(
       FROM_HERE, {content::BrowserThread::IO},
-      base::Bind(&ShellBrowserContext::InitURLRequestContextOnIOThread,
-                 base::Unretained(this)));
+      base::BindOnce(&ShellBrowserContext::InitURLRequestContextOnIOThread,
+                     base::Unretained(this)));
   return url_request_context_getter();
 }
 
diff --git a/extensions/shell/browser/shell_content_browser_client.cc b/extensions/shell/browser/shell_content_browser_client.cc
index 7fed38d..c6bfb651 100644
--- a/extensions/shell/browser/shell_content_browser_client.cc
+++ b/extensions/shell/browser/shell_content_browser_client.cc
@@ -177,10 +177,10 @@
 
   base::PostTaskWithTraits(
       FROM_HERE, {BrowserThread::IO},
-      base::Bind(&InfoMap::RegisterExtensionProcess,
-                 browser_main_parts_->extension_system()->info_map(),
-                 extension->id(), site_instance->GetProcess()->GetID(),
-                 site_instance->GetId()));
+      base::BindOnce(&InfoMap::RegisterExtensionProcess,
+                     browser_main_parts_->extension_system()->info_map(),
+                     extension->id(), site_instance->GetProcess()->GetID(),
+                     site_instance->GetId()));
 }
 
 void ShellContentBrowserClient::SiteInstanceDeleting(
@@ -201,10 +201,10 @@
 
   base::PostTaskWithTraits(
       FROM_HERE, {BrowserThread::IO},
-      base::Bind(&InfoMap::UnregisterExtensionProcess,
-                 browser_main_parts_->extension_system()->info_map(),
-                 extension->id(), site_instance->GetProcess()->GetID(),
-                 site_instance->GetId()));
+      base::BindOnce(&InfoMap::UnregisterExtensionProcess,
+                     browser_main_parts_->extension_system()->info_map(),
+                     extension->id(), site_instance->GetProcess()->GetID(),
+                     site_instance->GetId()));
 }
 
 void ShellContentBrowserClient::AppendExtraCommandLineSwitches(
diff --git a/extensions/shell/browser/shell_extensions_browser_client.cc b/extensions/shell/browser/shell_extensions_browser_client.cc
index 4038586..e5b4d79 100644
--- a/extensions/shell/browser/shell_extensions_browser_client.cc
+++ b/extensions/shell/browser/shell_extensions_browser_client.cc
@@ -252,9 +252,9 @@
   if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
     base::PostTaskWithTraits(
         FROM_HERE, {BrowserThread::UI},
-        base::Bind(&ShellExtensionsBrowserClient::BroadcastEventToRenderers,
-                   base::Unretained(this), histogram_value, event_name,
-                   base::Passed(&args)));
+        base::BindOnce(&ShellExtensionsBrowserClient::BroadcastEventToRenderers,
+                       base::Unretained(this), histogram_value, event_name,
+                       std::move(args)));
     return;
   }
 
diff --git a/fuchsia/runners/BUILD.gn b/fuchsia/runners/BUILD.gn
index 0da5786..6f78591 100644
--- a/fuchsia/runners/BUILD.gn
+++ b/fuchsia/runners/BUILD.gn
@@ -18,7 +18,6 @@
   deps = [
     "//base",
     "//third_party/fuchsia-sdk/sdk:ui_app",
-    "//third_party/fuchsia-sdk/sdk:ui_viewsv1",
     "//url",
   ]
   public_deps = [
diff --git a/fuchsia/runners/common/web_component.cc b/fuchsia/runners/common/web_component.cc
index 05635e8..d0fbc5e 100644
--- a/fuchsia/runners/common/web_component.cc
+++ b/fuchsia/runners/common/web_component.cc
@@ -66,10 +66,6 @@
     view_provider_binding_ = std::make_unique<
         base::fuchsia::ScopedServiceBinding<fuchsia::ui::app::ViewProvider>>(
         startup_context()->public_services(), this);
-    legacy_view_provider_binding_ =
-        std::make_unique<base::fuchsia::ScopedServiceBinding<
-            fuchsia::ui::viewsv1::ViewProvider>>(
-            startup_context()->public_services(), this);
   }
 }
 
@@ -96,16 +92,6 @@
   view_is_bound_ = true;
 }
 
-void WebComponent::CreateView(
-    fidl::InterfaceRequest<fuchsia::ui::viewsv1token::ViewOwner> view_owner,
-    fidl::InterfaceRequest<fuchsia::sys::ServiceProvider> services) {
-  // Cast the ViewOwner request to view_token. This is temporary hack for
-  // ViewsV2 transition. This version of CreateView() will be removed in the
-  // future.
-  CreateView(zx::eventpair(view_owner.TakeChannel().release()),
-             std::move(services), nullptr);
-}
-
 void WebComponent::DestroyComponent(int termination_exit_code,
                                     fuchsia::sys::TerminationReason reason) {
   termination_reason_ = reason;
diff --git a/fuchsia/runners/common/web_component.h b/fuchsia/runners/common/web_component.h
index e81d6fb..91d4ca3 100644
--- a/fuchsia/runners/common/web_component.h
+++ b/fuchsia/runners/common/web_component.h
@@ -7,7 +7,6 @@
 
 #include <fuchsia/sys/cpp/fidl.h>
 #include <fuchsia/ui/app/cpp/fidl.h>
-#include <fuchsia/ui/viewsv1/cpp/fidl.h>
 #include <lib/fidl/cpp/binding.h>
 #include <lib/fidl/cpp/binding_set.h>
 #include <memory>
@@ -29,11 +28,8 @@
 // resources and service bindings.  Runners for specialized web-based content
 // (e.g. Cast applications) can extend this class to configure the Frame to
 // their needs, publish additional APIs, etc.
-// TODO(crbug.com/899348): Remove fuchsia::ui::viewsv1::ViewProvider after
-// SCN-1033 is closed.
 class WebComponent : public fuchsia::sys::ComponentController,
-                     public fuchsia::ui::app::ViewProvider,
-                     public fuchsia::ui::viewsv1::ViewProvider {
+                     public fuchsia::ui::app::ViewProvider {
  public:
   // Creates a WebComponent encapsulating a web.Frame. A ViewProvider service
   // will be published to the service-directory specified by |startup_context|,
@@ -64,11 +60,6 @@
       fidl::InterfaceHandle<fuchsia::sys::ServiceProvider> outgoing_services)
       override;
 
-  // fuchsia::ui::viewsv1::ViewProvider implementation.
-  void CreateView(
-      fidl::InterfaceRequest<fuchsia::ui::viewsv1token::ViewOwner> view_owner,
-      fidl::InterfaceRequest<fuchsia::sys::ServiceProvider> services) override;
-
   // Reports the supplied exit-code and reason to the |controller_binding_| and
   // requests that the |runner_| delete this component.
   virtual void DestroyComponent(int termination_exit_code,
@@ -98,9 +89,6 @@
   std::unique_ptr<
       base::fuchsia::ScopedServiceBinding<fuchsia::ui::app::ViewProvider>>
       view_provider_binding_;
-  std::unique_ptr<
-      base::fuchsia::ScopedServiceBinding<fuchsia::ui::viewsv1::ViewProvider>>
-      legacy_view_provider_binding_;
 
   // Termination reason and exit-code to be reported via the
   // sys::ComponentController::OnTerminated event.
diff --git a/gpu/command_buffer/service/raster_decoder.cc b/gpu/command_buffer/service/raster_decoder.cc
index ab79b722..6e194bf 100644
--- a/gpu/command_buffer/service/raster_decoder.cc
+++ b/gpu/command_buffer/service/raster_decoder.cc
@@ -60,7 +60,6 @@
 #include "gpu/command_buffer/service/skia_utils.h"
 #include "gpu/command_buffer/service/wrapped_sk_image.h"
 #include "third_party/skia/include/core/SkCanvas.h"
-#include "third_party/skia/include/core/SkColorSpaceXformCanvas.h"
 #include "third_party/skia/include/core/SkDeferredDisplayListRecorder.h"
 #include "third_party/skia/include/core/SkSurface.h"
 #include "third_party/skia/include/core/SkSurfaceProps.h"
@@ -577,7 +576,7 @@
   std::unique_ptr<cc::ServicePaintCache> paint_cache_;
 
   std::unique_ptr<SkDeferredDisplayListRecorder> recorder_;
-  std::unique_ptr<SkCanvas> raster_canvas_;
+  SkCanvas* raster_canvas_ = nullptr;  // ptr into recorder_ or sk_surface_
   uint32_t raster_color_space_id_;
   std::vector<SkDiscardableHandleId> locked_handles_;
 
@@ -1379,9 +1378,10 @@
 void RasterDecoderImpl::SetUpForRasterCHROMIUMForTest() {
   // Some tests use mock GL which doesn't work with skia. Just use a bitmap
   // backed surface for OOP raster commands.
-  sk_surface_ = SkSurface::MakeRaster(SkImageInfo::MakeN32Premul(10, 10));
-  raster_canvas_ = SkCreateColorSpaceXformCanvas(sk_surface_->getCanvas(),
-                                                 SkColorSpace::MakeSRGB());
+  auto info = SkImageInfo::MakeN32(10, 10, kPremul_SkAlphaType,
+                                   SkColorSpace::MakeSRGB());
+  sk_surface_ = SkSurface::MakeRaster(info);
+  raster_canvas_ = sk_surface_->getCanvas();
 }
 
 void RasterDecoderImpl::SetOOMErrorForTest() {
@@ -2078,25 +2078,21 @@
   if (!color_space_entry || !color_space_entry->color_space().IsValid()) {
     LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glBeginRasterCHROMIUM",
                        "failed to find valid color space");
-    shared_image_->EndWriteAccess(std::move(sk_surface_));
     shared_image_.reset();
     return;
   }
 
-  SkCanvas* canvas = nullptr;
   if (use_ddl_) {
     SkSurfaceCharacterization characterization;
     bool result = sk_surface_->characterize(&characterization);
     DCHECK(result) << "Failed to characterize raster SkSurface.";
     recorder_ =
         std::make_unique<SkDeferredDisplayListRecorder>(characterization);
-    canvas = recorder_->getCanvas();
+    raster_canvas_ = recorder_->getCanvas();
   } else {
-    canvas = sk_surface_->getCanvas();
+    raster_canvas_ = sk_surface_->getCanvas();
   }
 
-  raster_canvas_ = SkCreateColorSpaceXformCanvas(
-      canvas, color_space_entry->color_space().ToSkColorSpace());
   raster_color_space_id_ = color_space_transfer_cache_id;
 
   // All or nothing clearing, as no way to validate the client's input on what
@@ -2164,7 +2160,6 @@
   alignas(
       cc::PaintOpBuffer::PaintOpAlign) char data[sizeof(cc::LargestPaintOp)];
 
-  SkCanvas* canvas = raster_canvas_.get();
   cc::PlaybackParams playback_params(nullptr, SkMatrix::I());
   TransferCacheDeserializeHelperImpl impl(raster_decoder_id_, transfer_cache());
   cc::PaintOp::DeserializeOptions options(
@@ -2186,7 +2181,7 @@
       return;
     }
 
-    deserialized_op->Raster(canvas, playback_params);
+    deserialized_op->Raster(raster_canvas_, playback_params);
     deserialized_op->DestroyThis();
 
     paint_buffer_size -= skip;
@@ -2204,7 +2199,7 @@
 
   shared_context_state_->set_need_context_state_reset(true);
 
-  raster_canvas_.reset();
+  raster_canvas_ = nullptr;
 
   if (use_ddl_) {
     auto ddl = recorder_->detach();
diff --git a/gpu/command_buffer/service/shared_image_backing_factory_ahardwarebuffer.cc b/gpu/command_buffer/service/shared_image_backing_factory_ahardwarebuffer.cc
index e15c8fd..f77b658 100644
--- a/gpu/command_buffer/service/shared_image_backing_factory_ahardwarebuffer.cc
+++ b/gpu/command_buffer/service/shared_image_backing_factory_ahardwarebuffer.cc
@@ -219,8 +219,8 @@
         /*gpu_compositing=*/true, format());
     auto surface = SkSurface::MakeFromBackendTextureAsRenderTarget(
         gr_context, promise_texture_->backendTexture(),
-        kTopLeft_GrSurfaceOrigin, final_msaa_count, sk_color_type, nullptr,
-        &surface_props);
+        kTopLeft_GrSurfaceOrigin, final_msaa_count, sk_color_type,
+        backing()->color_space().ToSkColorSpace(), &surface_props);
     write_surface_ = surface.get();
     return surface;
   }
diff --git a/gpu/command_buffer/service/shared_image_backing_factory_gl_texture.cc b/gpu/command_buffer/service/shared_image_backing_factory_gl_texture.cc
index 98f6df2..0d07c45 100644
--- a/gpu/command_buffer/service/shared_image_backing_factory_gl_texture.cc
+++ b/gpu/command_buffer/service/shared_image_backing_factory_gl_texture.cc
@@ -270,8 +270,8 @@
         /*gpu_compositing=*/true, format());
     auto surface = SkSurface::MakeFromBackendTextureAsRenderTarget(
         gr_context, promise_texture_->backendTexture(),
-        kTopLeft_GrSurfaceOrigin, final_msaa_count, sk_color_type, nullptr,
-        &surface_props);
+        kTopLeft_GrSurfaceOrigin, final_msaa_count, sk_color_type,
+        backing()->color_space().ToSkColorSpace(), &surface_props);
     write_surface_ = surface.get();
     return surface;
   }
diff --git a/gpu/command_buffer/service/wrapped_sk_image.cc b/gpu/command_buffer/service/wrapped_sk_image.cc
index b551da6..f4b05d41 100644
--- a/gpu/command_buffer/service/wrapped_sk_image.cc
+++ b/gpu/command_buffer/service/wrapped_sk_image.cc
@@ -70,6 +70,7 @@
 
   sk_sp<SkSurface> GetSkSurface(int final_msaa_count,
                                 SkColorType color_type,
+                                sk_sp<SkColorSpace> color_space,
                                 const SkSurfaceProps& surface_props) {
     if (context_state_->context_lost())
       return nullptr;
@@ -79,7 +80,7 @@
     DCHECK(gr_texture.isValid());
     return SkSurface::MakeFromBackendTextureAsRenderTarget(
         context_state_->gr_context(), gr_texture, kTopLeft_GrSurfaceOrigin,
-        final_msaa_count, color_type, /*colorSpace=*/nullptr, &surface_props);
+        final_msaa_count, color_type, color_space, &surface_props);
   }
 
   sk_sp<SkPromiseImageTexture> promise_texture() { return promise_texture_; }
@@ -194,7 +195,8 @@
         /*gpu_compositing=*/true, format());
 
     auto surface = wrapped_sk_image()->GetSkSurface(
-        final_msaa_count, sk_color_type, surface_props);
+        final_msaa_count, sk_color_type,
+        backing()->color_space().ToSkColorSpace(), surface_props);
     write_surface_ = surface.get();
     return surface;
   }
diff --git a/infra/config/luci-milo.cfg b/infra/config/luci-milo.cfg
index a203161b..017d17d 100644
--- a/infra/config/luci-milo.cfg
+++ b/infra/config/luci-milo.cfg
@@ -489,7 +489,8 @@
   }
   builders {
     name: "buildbucket/luci.chromium.ci/WebKit Mac10.13 (retina)"
-    category: "chromium.mac|wbk"
+    category: "chromium.mac"
+    short_name: "wbk"
   }
   builders {
     name: "buildbucket/luci.chromium.ci/Linux Builder"
@@ -900,7 +901,7 @@
   }
   builders {
     name: "buildbucket/luci.chromium.ci/WebKit Mac10.13 (retina)"
-    category: "wbk"
+    short_name: "wbk"
   }
 }
 
diff --git a/ios/build/bots/scripts/test_runner.py b/ios/build/bots/scripts/test_runner.py
index 5ea5823..b34c5fb0 100644
--- a/ios/build/bots/scripts/test_runner.py
+++ b/ios/build/bots/scripts/test_runner.py
@@ -1453,9 +1453,6 @@
       xcode_info = get_current_xcode_info()
       xcode_version = float(xcode_info['version'])
       inject_path = 'usr/lib/libXCTestBundleInject.dylib'
-      # This can be removed once xcode versions < 10 are deprecated.
-      if 10 > xcode_version:
-        inject_path = 'Library/PrivateFrameworks/IDEBundleInjection.framework/'
       self.xctestrun_file = tempfile.mkstemp()[1]
       self.xctestrun_data = {
         'TestTargetName': {
diff --git a/ios/chrome/app/application_delegate/url_opener.mm b/ios/chrome/app/application_delegate/url_opener.mm
index 8d1fd5c6..84b5b3c9 100644
--- a/ios/chrome/app/application_delegate/url_opener.mm
+++ b/ios/chrome/app/application_delegate/url_opener.mm
@@ -12,6 +12,7 @@
 #import "ios/chrome/app/application_delegate/tab_opening.h"
 #include "ios/chrome/app/startup/chrome_app_startup_parameters.h"
 #import "ios/chrome/browser/chrome_url_util.h"
+#include "ios/chrome/browser/system_flags.h"
 #include "url/gurl.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
@@ -63,12 +64,29 @@
         [startupInformation setStartupParameters:nil];
       };
 
+      // TODO(crbug.com/935019): Exacly the same copy of this code is present in
+      // +[UserAcrtivityHandler
+      // handleStartupParametersWithTabOpener:startupInformation:interfaceProvider:]
+
+      GURL URL;
+      GURL virtualURL;
+      if ([params completeURL].SchemeIsFile() &&
+          base::FeatureList::IsEnabled(
+              experimental_flags::kExternalFilesLoadedInWebState)) {
+        // External URL will be loaded by WebState, which expects |completeURL|.
+        // Omnibox however suppose to display |externalURL|, which is used as
+        // virtual URL.
+        URL = [params completeURL];
+        virtualURL = [params externalURL];
+      } else {
+        URL = [params externalURL];
+      }
       [tabOpener
           dismissModalsAndOpenSelectedTabInMode:[params launchInIncognito]
                                                     ? ApplicationMode::INCOGNITO
                                                     : ApplicationMode::NORMAL
-                                        withURL:[params externalURL]
-                                     virtualURL:GURL::EmptyGURL()
+                                        withURL:URL
+                                     virtualURL:virtualURL
                                  dismissOmnibox:[params postOpeningAction] !=
                                                 FOCUS_OMNIBOX
                                      transition:ui::PAGE_TRANSITION_LINK
diff --git a/ios/chrome/app/application_delegate/url_opener_unittest.mm b/ios/chrome/app/application_delegate/url_opener_unittest.mm
index d7645282..2303e0b 100644
--- a/ios/chrome/app/application_delegate/url_opener_unittest.mm
+++ b/ios/chrome/app/application_delegate/url_opener_unittest.mm
@@ -6,11 +6,13 @@
 
 #import <Foundation/Foundation.h>
 
+#include "base/test/scoped_feature_list.h"
 #include "ios/chrome/app/application_delegate/app_state.h"
 #include "ios/chrome/app/application_delegate/mock_tab_opener.h"
 #include "ios/chrome/app/application_delegate/startup_information.h"
 #include "ios/chrome/app/startup/chrome_app_startup_parameters.h"
 #include "ios/chrome/browser/browser_state/test_chrome_browser_state.h"
+#include "ios/chrome/browser/system_flags.h"
 #import "ios/chrome/browser/tabs/tab_model.h"
 #import "ios/chrome/browser/ui/main/test/stub_browser_interface.h"
 #import "ios/chrome/browser/ui/main/test/stub_browser_interface_provider.h"
@@ -26,6 +28,13 @@
 #error "This file requires ARC support."
 #endif
 
+// URLOpenerTest is parameterized on this enum to test with
+// enabled and disabled kExternalFilesLoadedInWebState feature flag.
+enum class ExternalFilesLoadedInWebStateFeature {
+  Disabled = 0,
+  Enabled,
+};
+
 @interface StubStartupInformation : NSObject <StartupInformation>
 @end
 @implementation StubStartupInformation
@@ -55,17 +64,26 @@
 
 @end
 
-class URLOpenerTest : public PlatformTest {
+class URLOpenerTest
+    : public PlatformTest,
+      public testing::WithParamInterface<ExternalFilesLoadedInWebStateFeature> {
  protected:
-  void TearDown() override {
-    PlatformTest::TearDown();
+  URLOpenerTest() {
+    if (GetParam() == ExternalFilesLoadedInWebStateFeature::Enabled) {
+      scoped_feature_list_.InitAndEnableFeature(
+          experimental_flags::kExternalFilesLoadedInWebState);
+    } else {
+      scoped_feature_list_.InitAndDisableFeature(
+          experimental_flags::kExternalFilesLoadedInWebState);
+    }
   }
 
  private:
   web::TestWebThreadBundle thread_bundle_;
+  base::test::ScopedFeatureList scoped_feature_list_;
 };
 
-TEST_F(URLOpenerTest, HandleOpenURL) {
+TEST_P(URLOpenerTest, HandleOpenURL) {
   // A set of tests for robustness of
   // application:openURL:options:tabOpener:startupInformation:
   // It verifies that the function handles correctly different URLs parsed by
@@ -168,7 +186,21 @@
             else
               EXPECT_EQ(nil, startupInformation.startupParameters);
           } else if (result) {
-            EXPECT_EQ([params externalURL], [tabOpener url]);
+            if (GetParam() == ExternalFilesLoadedInWebStateFeature::Enabled) {
+              if ([params completeURL].SchemeIsFile()) {
+                // External file:// URL will be loaded by WebState, which
+                // expects complete // file:// URL. chrome:// URL is expected to
+                // be displayed in the omnibox, and omnibox shows virtual URL.
+                EXPECT_EQ([params completeURL], [tabOpener url]);
+                EXPECT_EQ([params externalURL], [tabOpener virtualURL]);
+              } else {
+                // External chromium-x-callback:// URL will be loaded by
+                // WebState, which expects externalURL URL.
+                EXPECT_EQ([params externalURL], [tabOpener url]);
+              }
+            } else {
+              EXPECT_EQ([params externalURL], [tabOpener url]);
+            }
             tabOpener.completionBlock();
             EXPECT_EQ(nil, startupInformation.startupParameters);
           }
@@ -179,7 +211,7 @@
 }
 
 // Tests that -handleApplication set startup parameters as expected.
-TEST_F(URLOpenerTest, VerifyLaunchOptions) {
+TEST_P(URLOpenerTest, VerifyLaunchOptions) {
   // Setup.
   NSURL* url = [NSURL URLWithString:@"chromium://www.google.com"];
   NSDictionary* launchOptions = @{
@@ -230,7 +262,7 @@
 
 // Tests that -handleApplication set startup parameters as expected with options
 // as nil.
-TEST_F(URLOpenerTest, VerifyLaunchOptionsNil) {
+TEST_P(URLOpenerTest, VerifyLaunchOptionsNil) {
   // Creates a mock with no stub. This test will pass only if we don't use these
   // objects.
   id startupInformationMock =
@@ -247,7 +279,7 @@
 
 // Tests that -handleApplication set startup parameters as expected with no
 // source application.
-TEST_F(URLOpenerTest, VerifyLaunchOptionsWithNoSourceApplication) {
+TEST_P(URLOpenerTest, VerifyLaunchOptionsWithNoSourceApplication) {
   // Setup.
   NSURL* url = [NSURL URLWithString:@"chromium://www.google.com"];
   NSDictionary* launchOptions = @{
@@ -269,7 +301,7 @@
 }
 
 // Tests that -handleApplication set startup parameters as expected with no url.
-TEST_F(URLOpenerTest, VerifyLaunchOptionsWithNoURL) {
+TEST_P(URLOpenerTest, VerifyLaunchOptionsWithNoURL) {
   // Setup.
   NSDictionary* launchOptions = @{
     UIApplicationLaunchOptionsSourceApplicationKey : @"com.apple.mobilesafari"
@@ -291,7 +323,7 @@
 
 // Tests that -handleApplication set startup parameters as expected with a bad
 // url.
-TEST_F(URLOpenerTest, VerifyLaunchOptionsWithBadURL) {
+TEST_P(URLOpenerTest, VerifyLaunchOptionsWithBadURL) {
   // Setup.
   NSURL* url = [NSURL URLWithString:@"chromium.www.google.com"];
   NSDictionary* launchOptions = @{
@@ -339,3 +371,9 @@
   EXPECT_TRUE(hasBeenCalled);
   EXPECT_OCMOCK_VERIFY(startupInformationMock);
 }
+
+INSTANTIATE_TEST_SUITE_P(
+    ProgrammaticURLOpenerTest,
+    URLOpenerTest,
+    ::testing::Values(ExternalFilesLoadedInWebStateFeature::Enabled,
+                      ExternalFilesLoadedInWebStateFeature::Disabled));
diff --git a/ios/chrome/app/application_delegate/user_activity_handler.mm b/ios/chrome/app/application_delegate/user_activity_handler.mm
index 2b10c86..018f840 100644
--- a/ios/chrome/app/application_delegate/user_activity_handler.mm
+++ b/ios/chrome/app/application_delegate/user_activity_handler.mm
@@ -255,6 +255,10 @@
     if ([tabOpener shouldCompletePaymentRequestOnCurrentTab:startupInformation])
       return;
 
+    // TODO(crbug.com/935019): Exacly the same copy of this code is present in
+    // +[URLOpener
+    // openURL:applicationActive:options:tabOpener:startupInformation:]
+
     // The app is already active so the applicationDidBecomeActive: method
     // will never be called. Open the requested URL after all modal UIs have
     // been dismissed. |_startupParameters| must be retained until all deferred
diff --git a/ios/chrome/browser/ui/settings/google_services/BUILD.gn b/ios/chrome/browser/ui/settings/google_services/BUILD.gn
index c66f9550..a199afa 100644
--- a/ios/chrome/browser/ui/settings/google_services/BUILD.gn
+++ b/ios/chrome/browser/ui/settings/google_services/BUILD.gn
@@ -34,6 +34,7 @@
     "resources:google_services_sync_error",
     "//base",
     "//components/browser_sync",
+    "//components/google/core/common",
     "//components/metrics",
     "//components/prefs",
     "//components/strings",
diff --git a/ios/chrome/browser/ui/settings/google_services/manage_sync_settings_coordinator.mm b/ios/chrome/browser/ui/settings/google_services/manage_sync_settings_coordinator.mm
index 0e57520..f47369b7 100644
--- a/ios/chrome/browser/ui/settings/google_services/manage_sync_settings_coordinator.mm
+++ b/ios/chrome/browser/ui/settings/google_services/manage_sync_settings_coordinator.mm
@@ -6,8 +6,13 @@
 
 #include "base/logging.h"
 #include "components/browser_sync/profile_sync_service.h"
+#include "components/google/core/common/google_util.h"
+#include "ios/chrome/browser/application_context.h"
+#include "ios/chrome/browser/chrome_url_constants.h"
 #include "ios/chrome/browser/sync/profile_sync_service_factory.h"
 #include "ios/chrome/browser/sync/sync_setup_service_factory.h"
+#import "ios/chrome/browser/ui/commands/application_commands.h"
+#import "ios/chrome/browser/ui/commands/open_new_tab_command.h"
 #import "ios/chrome/browser/ui/settings/google_services/manage_sync_settings_command_handler.h"
 #import "ios/chrome/browser/ui/settings/google_services/manage_sync_settings_mediator.h"
 #import "ios/chrome/browser/ui/settings/google_services/manage_sync_settings_table_view_controller.h"
@@ -84,6 +89,11 @@
 }
 
 - (void)openDataFromChromeSyncWebPage {
+  GURL url = google_util::AppendGoogleLocaleParam(
+      GURL(kSyncGoogleDashboardURL),
+      GetApplicationContext()->GetApplicationLocale());
+  OpenNewTabCommand* command = [OpenNewTabCommand commandWithURLFromChrome:url];
+  [self.dispatcher closeSettingsUIAndOpenURL:command];
 }
 
 @end
diff --git a/ios/web/shell/test/BUILD.gn b/ios/web/shell/test/BUILD.gn
index 5f8fac25..cd4712bd 100644
--- a/ios/web/shell/test/BUILD.gn
+++ b/ios/web/shell/test/BUILD.gn
@@ -20,7 +20,6 @@
   sources = [
     "context_menu_egtest.mm",
     "meta_tags_egtest.mm",
-    "navigation_egtest.mm",
     "page_state_egtest.mm",
     "plugin_placeholder_egtest.mm",
     "redirect_egtest.mm",
@@ -98,7 +97,6 @@
 bundle_data("bundle") {
   visibility = [ ":*" ]
   sources = [
-    "http_server_files/basic_navigation_test.html",
     "http_server_files/tall_page.html",
   ]
   outputs = [
diff --git a/ios/web/shell/test/http_server_files/basic_navigation_test.html b/ios/web/shell/test/http_server_files/basic_navigation_test.html
deleted file mode 100644
index 783c91ce..0000000
--- a/ios/web/shell/test/http_server_files/basic_navigation_test.html
+++ /dev/null
@@ -1,25 +0,0 @@
-<!DOCTYPE html>
-<html>
-  <head>
-    <meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
-    <title>Browsing tests</title>
-  </head>
-  <body>
-    <table>
-      <tr>
-        <th>Code</th>
-        <th>Expected result</th>
-      </tr>
-      <tr id="link-to-about-blank">
-        <td>
-          <a href="about:blank"
-            id="basic-link-navigation-to-about-blank"
-            name="basic-link-navigation-to-about-blank">
-                BasicLinkNavigationToAboutBlank
-          </a>
-        </td>
-        <td>about:blank opened in this tab</td>
-      </tr>
-    </table>
-  </body>
-</html>
diff --git a/ios/web/shell/test/navigation_egtest.mm b/ios/web/shell/test/navigation_egtest.mm
deleted file mode 100644
index 543da78..0000000
--- a/ios/web/shell/test/navigation_egtest.mm
+++ /dev/null
@@ -1,174 +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.
-
-#import <UIKit/UIKit.h>
-#import <WebKit/WebKit.h>
-#import <XCTest/XCTest.h>
-
-#import <EarlGrey/EarlGrey.h>
-
-#import "ios/web/public/test/http_server/http_server.h"
-#include "ios/web/public/test/http_server/http_server_util.h"
-#include "ios/web/shell/test/app/web_view_interaction_test_util.h"
-#import "ios/web/shell/test/earl_grey/shell_earl_grey.h"
-#import "ios/web/shell/test/earl_grey/shell_matchers.h"
-#import "ios/web/shell/test/earl_grey/web_shell_test_case.h"
-
-#if !defined(__has_feature) || !__has_feature(objc_arc)
-#error "This file requires ARC support."
-#endif
-
-// Navigation test cases for the web shell. These are Earl Grey integration
-// tests, which are based on XCTest.
-@interface NavigationTestCase : WebShellTestCase
-@end
-
-@implementation NavigationTestCase
-
-// Tests clicking a link to about:blank.
-- (void)testNavigationLinkToAboutBlank {
-  const GURL URL = web::test::HttpServer::MakeUrl(
-      "http://ios/web/shell/test/http_server_files/basic_navigation_test.html");
-  web::test::SetUpFileBasedHttpServer();
-
-  [ShellEarlGrey loadURL:URL];
-  [[EarlGrey selectElementWithMatcher:web::AddressFieldText(URL.spec())]
-      assertWithMatcher:grey_notNil()];
-
-  web::shell_test_util::TapWebViewElementWithId(
-      "basic-link-navigation-to-about-blank");
-
-  [[EarlGrey selectElementWithMatcher:web::AddressFieldText("about:blank")]
-      assertWithMatcher:grey_notNil()];
-}
-
-// Tests the back and forward button after entering two URLs.
-- (void)testNavigationBackAndForward {
-  // Create map of canned responses and set up the test HTML server.
-  std::map<GURL, std::string> responses;
-  const GURL URL1 = web::test::HttpServer::MakeUrl("http://firstURL");
-  const char response1[] = "Test Page 1";
-  responses[URL1] = response1;
-
-  const GURL URL2 = web::test::HttpServer::MakeUrl("http://secondURL");
-  const char response2[] = "Test Page 2";
-  responses[URL2] = response2;
-
-  web::test::SetUpSimpleHttpServer(responses);
-
-  [ShellEarlGrey loadURL:URL1];
-  [[EarlGrey selectElementWithMatcher:web::AddressFieldText(URL1.spec())]
-      assertWithMatcher:grey_notNil()];
-  [ShellEarlGrey waitForWebViewContainingText:response1];
-
-  [ShellEarlGrey loadURL:URL2];
-  [[EarlGrey selectElementWithMatcher:web::AddressFieldText(URL2.spec())]
-      assertWithMatcher:grey_notNil()];
-  [ShellEarlGrey waitForWebViewContainingText:response2];
-
-  [[EarlGrey selectElementWithMatcher:web::BackButton()]
-      performAction:grey_tap()];
-  [[EarlGrey selectElementWithMatcher:web::AddressFieldText(URL1.spec())]
-      assertWithMatcher:grey_notNil()];
-  [ShellEarlGrey waitForWebViewContainingText:response1];
-
-  [[EarlGrey selectElementWithMatcher:web::ForwardButton()]
-      performAction:grey_tap()];
-  [[EarlGrey selectElementWithMatcher:web::AddressFieldText(URL2.spec())]
-      assertWithMatcher:grey_notNil()];
-  [ShellEarlGrey waitForWebViewContainingText:response2];
-}
-
-// Tests back and forward navigation where a fragment link is tapped.
-- (void)testNavigationBackAndForwardAfterFragmentLink {
-  // Create map of canned responses and set up the test HTML server.
-  std::map<GURL, std::string> responses;
-  const GURL URL1 = web::test::HttpServer::MakeUrl("http://fragmentLink");
-  const std::string response = "<a href='#hash' id='link'>link</a>";
-  responses[URL1] = response;
-
-  const GURL URL2 = web::test::HttpServer::MakeUrl("http://fragmentLink/#hash");
-
-  web::test::SetUpSimpleHttpServer(responses);
-
-  [ShellEarlGrey loadURL:URL1];
-  [[EarlGrey selectElementWithMatcher:web::AddressFieldText(URL1.spec())]
-      assertWithMatcher:grey_notNil()];
-
-  web::shell_test_util::TapWebViewElementWithId("link");
-  [[EarlGrey selectElementWithMatcher:web::AddressFieldText(URL2.spec())]
-      assertWithMatcher:grey_notNil()];
-
-  [[EarlGrey selectElementWithMatcher:web::BackButton()]
-      performAction:grey_tap()];
-  [[EarlGrey selectElementWithMatcher:web::AddressFieldText(URL1.spec())]
-      assertWithMatcher:grey_notNil()];
-
-  [[EarlGrey selectElementWithMatcher:web::ForwardButton()]
-      performAction:grey_tap()];
-  [[EarlGrey selectElementWithMatcher:web::AddressFieldText(URL2.spec())]
-      assertWithMatcher:grey_notNil()];
-}
-
-// Tests tapping a link with onclick="event.preventDefault()" and verifies that
-// the URL didn't change..
-- (void)testNavigationLinkPreventDefaultOverridesHref {
-  // Create map of canned responses and set up the test HTML server.
-  std::map<GURL, std::string> responses;
-  const GURL URL = web::test::HttpServer::MakeUrl("http://overridesHrefLink");
-  const char pageHTML[] =
-      "<script>"
-      "  function printMsg() {"
-      "    document.body.appendChild(document.createTextNode('Default "
-      "prevented!'));"
-      "  }"
-      "</script>"
-      "<a href='#hash' id='overrides-href' onclick='event.preventDefault(); "
-      "printMsg();'>redirectLink</a>";
-  responses[URL] = pageHTML;
-
-  web::test::SetUpSimpleHttpServer(responses);
-
-  [ShellEarlGrey loadURL:URL];
-  [[EarlGrey selectElementWithMatcher:web::AddressFieldText(URL.spec())]
-      assertWithMatcher:grey_notNil()];
-
-  web::shell_test_util::TapWebViewElementWithId("overrides-href");
-
-  [[EarlGrey selectElementWithMatcher:web::AddressFieldText(URL.spec())]
-      assertWithMatcher:grey_notNil()];
-  [ShellEarlGrey waitForWebViewContainingText:"Default prevented!"];
-}
-
-// Tests tapping on a link with unsupported URL scheme.
-- (void)testNavigationUnsupportedSchema {
-  // Create map of canned responses and set up the test HTML server.
-  std::map<GURL, std::string> responses;
-  const GURL URL =
-      web::test::HttpServer::MakeUrl("http://urlWithUnsupportedSchemeLink");
-  const char pageHTML[] =
-      "<script>"
-      "  function printMsg() {"
-      "    document.body.appendChild(document.createTextNode("
-      "    'No navigation!'));"
-      "  }"
-      "</script>"
-      "<a href='aaa://unsupported' id='link' "
-      "onclick='printMsg();'>unsupportedScheme</a>";
-  responses[URL] = pageHTML;
-
-  web::test::SetUpSimpleHttpServer(responses);
-
-  [ShellEarlGrey loadURL:URL];
-  [[EarlGrey selectElementWithMatcher:web::AddressFieldText(URL.spec())]
-      assertWithMatcher:grey_notNil()];
-
-  web::shell_test_util::TapWebViewElementWithId("link");
-
-  [[EarlGrey selectElementWithMatcher:web::AddressFieldText(URL.spec())]
-      assertWithMatcher:grey_notNil()];
-  [ShellEarlGrey waitForWebViewContainingText:"No navigation!"];
-}
-
-@end
diff --git a/ios/web/web_state/ui/crw_web_controller.mm b/ios/web/web_state/ui/crw_web_controller.mm
index 953ac872..30f72d7f 100644
--- a/ios/web/web_state/ui/crw_web_controller.mm
+++ b/ios/web/web_state/ui/crw_web_controller.mm
@@ -3176,8 +3176,7 @@
   // item associated with navigationContext.
 
   if ([error.domain isEqual:base::SysUTF8ToNSString(web::kWebKitErrorDomain)]) {
-    if (error.code == web::kWebKitErrorPlugInLoadFailed ||
-        error.code == web::kWebKitErrorCannotShowUrl) {
+    if (error.code == web::kWebKitErrorPlugInLoadFailed) {
       // In cases where a Plug-in handles the load do not take any further
       // action.
       return;
diff --git a/ios/web/web_state/web_state_observer_inttest.mm b/ios/web/web_state/web_state_observer_inttest.mm
index 2f25fb1..26e9656e 100644
--- a/ios/web/web_state/web_state_observer_inttest.mm
+++ b/ios/web/web_state/web_state_observer_inttest.mm
@@ -35,6 +35,7 @@
 #include "ios/web/test/test_url_constants.h"
 #import "ios/web/test/web_int_test.h"
 #import "ios/web/web_state/ui/crw_web_controller.h"
+#include "ios/web/web_state/ui/web_kit_constants.h"
 #import "ios/web/web_state/web_state_impl.h"
 #import "net/base/mac/url_conversions.h"
 #include "net/http/http_response_headers.h"
@@ -990,6 +991,35 @@
   ASSERT_TRUE(test::WaitForPageToFinishLoading(web_state()));
 }
 
+// Tests failed navigation because URL with a space is not supported by
+// WKWebView (crbug.com/934379).
+TEST_P(WebStateObserverTest, WebViewUnsupportedUrlNavigation) {
+  GURL url("http:// .test");
+
+  // Perform a navigation to url with unsupported url, which will fail.
+  NavigationContext* context = nullptr;
+  int32_t nav_id = 0;
+  EXPECT_CALL(observer_, DidStartLoading(web_state()));
+  WebStatePolicyDecider::RequestInfo expected_request_info(
+      ui::PageTransition::PAGE_TRANSITION_TYPED,
+      /*target_main_frame=*/true, /*has_user_gesture=*/false);
+  EXPECT_CALL(*decider_,
+              ShouldAllowRequest(_, RequestInfoMatch(expected_request_info)))
+      .WillOnce(Return(true));
+  EXPECT_CALL(observer_, DidStartNavigation(web_state(), _))
+      .WillOnce(VerifyPageStartedContext(
+          web_state(), url, ui::PageTransition::PAGE_TRANSITION_TYPED, &context,
+          &nav_id));
+  EXPECT_CALL(observer_, DidFinishNavigation(web_state(), _))
+      .WillOnce(VerifyErrorFinishedContext(web_state(), url, &context, &nav_id,
+                                           web::kWebKitErrorCannotShowUrl));
+  EXPECT_CALL(observer_, DidStopLoading(web_state()));
+  EXPECT_CALL(observer_,
+              PageLoaded(web_state(), PageLoadCompletionStatus::FAILURE));
+  test::LoadUrl(web_state(), url);
+  ASSERT_TRUE(test::WaitForPageToFinishLoading(web_state()));
+}
+
 // Tests failed navigation because URL scheme is not supported by WebState.
 // TODO(crbug.com/917176): Actual callbacks for this navigation should not be
 // different from callbacks observed in WebViewUnsupportedSchemeNavigation.
diff --git a/ios/web_view/internal/passwords/mock_credentials_filter.h b/ios/web_view/internal/passwords/mock_credentials_filter.h
index c79ee08eb..324ead0f 100644
--- a/ios/web_view/internal/passwords/mock_credentials_filter.h
+++ b/ios/web_view/internal/passwords/mock_credentials_filter.h
@@ -19,9 +19,6 @@
   ~MockCredentialsFilter() override;
 
   // CredentialsFilter
-  std::vector<std::unique_ptr<autofill::PasswordForm>> FilterResults(
-      std::vector<std::unique_ptr<autofill::PasswordForm>> results)
-      const override;
   bool ShouldSave(const autofill::PasswordForm& form) const override;
   bool ShouldSaveGaiaPasswordHash(
       const autofill::PasswordForm& form) const override;
@@ -32,12 +29,6 @@
       const override;
   bool IsSyncAccountEmail(const std::string& username) const override;
 
-  // A version of FilterResult without moveable arguments, which cannot be
-  // mocked in GMock. MockCredentialsFilter::FilterResults(arg) calls
-  // FilterResultsPtr(&arg).
-  virtual void FilterResultsPtr(
-      std::vector<std::unique_ptr<autofill::PasswordForm>>* results) const;
-
  private:
   DISALLOW_COPY_AND_ASSIGN(MockCredentialsFilter);
 };
diff --git a/ios/web_view/internal/passwords/mock_credentials_filter.mm b/ios/web_view/internal/passwords/mock_credentials_filter.mm
index ae6c0b4..20f7775 100644
--- a/ios/web_view/internal/passwords/mock_credentials_filter.mm
+++ b/ios/web_view/internal/passwords/mock_credentials_filter.mm
@@ -14,13 +14,6 @@
 
 MockCredentialsFilter::~MockCredentialsFilter() = default;
 
-std::vector<std::unique_ptr<autofill::PasswordForm>>
-MockCredentialsFilter::FilterResults(
-    std::vector<std::unique_ptr<autofill::PasswordForm>> results) const {
-  FilterResultsPtr(&results);
-  return results;
-}
-
 bool MockCredentialsFilter::ShouldSave(
     const autofill::PasswordForm& form) const {
   return true;
@@ -44,7 +37,4 @@
   return false;
 }
 
-void MockCredentialsFilter::FilterResultsPtr(
-    std::vector<std::unique_ptr<autofill::PasswordForm>>* results) const {}
-
 }  // namespace ios_web_view
diff --git a/media/base/media_switches.cc b/media/base/media_switches.cc
index 1a142e0..4ba8ac8 100644
--- a/media/base/media_switches.cc
+++ b/media/base/media_switches.cc
@@ -259,6 +259,11 @@
 const base::Feature kD3D11VideoDecoder{"D3D11VideoDecoder",
                                        base::FEATURE_DISABLED_BY_DEFAULT};
 
+// Tell D3D11VideoDecoder to ignore workarounds for zero copy.  Requires that
+// kD3D11VideoDecoder is enabled.
+const base::Feature kD3D11VideoDecoderIgnoreWorkarounds{
+    "D3D11VideoDecoderIgnoreWorkarounds", base::FEATURE_DISABLED_BY_DEFAULT};
+
 // Enable usage of dav1d for AV1 video decoding.
 const base::Feature kDav1dVideoDecoder{"Dav1dVideoDecoder",
                                        base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/media/base/media_switches.h b/media/base/media_switches.h
index c6d4e0d4..b2ee1479 100644
--- a/media/base/media_switches.h
+++ b/media/base/media_switches.h
@@ -104,6 +104,7 @@
 MEDIA_EXPORT extern const base::Feature kBackgroundSrcVideoTrackOptimization;
 MEDIA_EXPORT extern const base::Feature kBackgroundVideoPauseOptimization;
 MEDIA_EXPORT extern const base::Feature kD3D11VideoDecoder;
+MEDIA_EXPORT extern const base::Feature kD3D11VideoDecoderIgnoreWorkarounds;
 MEDIA_EXPORT extern const base::Feature kDav1dVideoDecoder;
 MEDIA_EXPORT extern const base::Feature kExternalClearKeyForTesting;
 MEDIA_EXPORT extern const base::Feature kFallbackAfterDecodeError;
diff --git a/media/capture/video/chromeos/camera_hal_dispatcher_impl_unittest.cc b/media/capture/video/chromeos/camera_hal_dispatcher_impl_unittest.cc
index f6feeec8..e558eb4 100644
--- a/media/capture/video/chromeos/camera_hal_dispatcher_impl_unittest.cc
+++ b/media/capture/video/chromeos/camera_hal_dispatcher_impl_unittest.cc
@@ -174,7 +174,7 @@
 
   // Wait until the clients gets the newly established Mojo channel.
   DoLoop();
-};
+}
 
 // Test that the CameraHalDisptcherImpl correctly re-establishes a Mojo channel
 // for the client when the client reconnects after crash.
@@ -223,6 +223,6 @@
 
   // Wait until the clients gets the newly established Mojo channel.
   DoLoop();
-};
+}
 
 }  // namespace media
diff --git a/media/capture/video/chromeos/local_gpu_memory_buffer_manager.cc b/media/capture/video/chromeos/local_gpu_memory_buffer_manager.cc
index 6502cab..acc18fd 100644
--- a/media/capture/video/chromeos/local_gpu_memory_buffer_manager.cc
+++ b/media/capture/video/chromeos/local_gpu_memory_buffer_manager.cc
@@ -117,7 +117,7 @@
     }
     mapped_ = true;
     return true;
-  };
+  }
 
   void* memory(size_t plane) override {
     if (!mapped_) {
diff --git a/media/capture/video/chromeos/reprocess_manager.cc b/media/capture/video/chromeos/reprocess_manager.cc
index 8872c7c3..62dedde 100644
--- a/media/capture/video/chromeos/reprocess_manager.cc
+++ b/media/capture/video/chromeos/reprocess_manager.cc
@@ -49,7 +49,7 @@
 
 ReprocessManager::~ReprocessManager() {
   sequenced_task_runner_->DeleteSoon(FROM_HERE, std::move(impl));
-};
+}
 
 void ReprocessManager::SetReprocessOption(
     cros::mojom::Effect effect,
diff --git a/media/gpu/vp8_decoder.cc b/media/gpu/vp8_decoder.cc
index 4e18e87..94570a6f 100644
--- a/media/gpu/vp8_decoder.cc
+++ b/media/gpu/vp8_decoder.cc
@@ -9,7 +9,7 @@
 
 namespace {
 constexpr size_t kVP8NumFramesActive = 4;
-};
+}
 
 VP8Decoder::VP8Accelerator::VP8Accelerator() {}
 
diff --git a/media/gpu/windows/d3d11_video_decoder.cc b/media/gpu/windows/d3d11_video_decoder.cc
index 082136c..09a4654e 100644
--- a/media/gpu/windows/d3d11_video_decoder.cc
+++ b/media/gpu/windows/d3d11_video_decoder.cc
@@ -766,10 +766,14 @@
     return {};
   }
 
-  if (gpu_workarounds.disable_dxgi_zero_copy_video) {
-    UMA_HISTOGRAM_ENUMERATION(uma_name,
-                              NotSupportedReason::kZeroCopyVideoRequired);
-    return {};
+  // This workaround accounts for almost half of all startup results, and it's
+  // unclear that it's relevant here.
+  if (!base::FeatureList::IsEnabled(kD3D11VideoDecoderIgnoreWorkarounds)) {
+    if (gpu_workarounds.disable_dxgi_zero_copy_video) {
+      UMA_HISTOGRAM_ENUMERATION(uma_name,
+                                NotSupportedReason::kZeroCopyVideoRequired);
+      return {};
+    }
   }
 
   // Remember that this might query the angle device, so this won't work if
diff --git a/net/base/registry_controlled_domains/effective_tld_names.dat b/net/base/registry_controlled_domains/effective_tld_names.dat
index 69c7888..59db7d0c 100644
--- a/net/base/registry_controlled_domains/effective_tld_names.dat
+++ b/net/base/registry_controlled_domains/effective_tld_names.dat
@@ -4663,9 +4663,6 @@
 //      ccTLD for the Netherlands
 nl
 
-// BV.nl will be a registry for dutch BV's (besloten vennootschap)
-bv.nl
-
 // no : http://www.norid.no/regelverk/index.en.html
 // The Norwegian registry has declined to notify us of updates. The web pages
 // referenced below are the official source of the data. There is also an
@@ -7111,9 +7108,6 @@
 // aco : 2015-01-08 ACO Severin Ahlmann GmbH & Co. KG
 aco
 
-// active : 2014-05-01 Active Network, LLC
-active
-
 // actor : 2013-12-12 United TLD Holdco Ltd.
 actor
 
@@ -7414,9 +7408,6 @@
 // blackfriday : 2014-01-16 Uniregistry, Corp.
 blackfriday
 
-// blanco : 2015-07-16 BLANCO GmbH + Co KG
-blanco
-
 // blockbuster : 2015-07-30 Dish DBS Corporation
 blockbuster
 
@@ -8026,9 +8017,6 @@
 // enterprises : 2013-09-20 Binky Moon, LLC
 enterprises
 
-// epost : 2015-07-23 Deutsche Post AG
-epost
-
 // epson : 2014-12-04 Seiko Epson Corporation
 epson
 
@@ -9850,9 +9838,6 @@
 // space : 2014-04-03 DotSpace Inc.
 space
 
-// spiegel : 2014-02-05 SPIEGEL-Verlag Rudolf Augstein GmbH & Co. KG
-spiegel
-
 // sport : 2017-11-16 Global Association of International Sports Federations (GAISF)
 sport
 
@@ -10687,9 +10672,6 @@
 // zip : 2014-05-08 Charleston Road Registry Inc.
 zip
 
-// zippo : 2015-07-02 Zadco Company
-zippo
-
 // zone : 2013-11-14 Binky Moon, LLC
 zone
 
@@ -11092,6 +11074,11 @@
 reg.dk
 store.dk
 
+// dapps.earth : https://dapps.earth/
+// Submitted by Daniil Burdakov <icqkill@gmail.com>
+*.dapps.earth
+*.bzz.dapps.earth
+
 // Debian : https://www.debian.org/
 // Submitted by Peter Palfrader / Debian Sysadmin Team <dsa-publicsuffixlist@debian.org>
 debian.net
@@ -11638,6 +11625,7 @@
 
 // Fastly Inc. : http://www.fastly.com/
 // Submitted by Fastly Security <security@fastly.com>
+fastly-terrarium.com
 fastlylb.net
 map.fastlylb.net
 freetls.fastly.net
@@ -11672,6 +11660,12 @@
 // Filegear Inc. : https://www.filegear.com
 // Submitted by Jason Zhu <jason@owtware.com>
 filegear.me
+filegear-au.me
+filegear-de.me
+filegear-gb.me
+filegear-ie.me
+filegear-jp.me
+filegear-sg.me
 
 // Firebase, Inc.
 // Submitted by Chris Raynor <chris@firebase.com>
@@ -11734,6 +11728,8 @@
 
 // Google, Inc.
 // Submitted by Eduardo Vela <evn@google.com>
+run.app
+a.run.app
 *.0emm.com
 appspot.com
 blogspot.ae
@@ -11853,6 +11849,19 @@
 // Submitted by Hannu Aronsson <haa@iki.fi>
 iki.fi
 
+// Individual Network Berlin e.V. : https://www.in-berlin.de/
+// Submitted by Christian Seitz <chris@in-berlin.de>
+dyn-berlin.de
+in-berlin.de
+in-brb.de
+in-butter.de
+in-dsl.de
+in-dsl.net
+in-dsl.org
+in-vpn.de
+in-vpn.net
+in-vpn.org
+
 // info.at : http://www.info.at/
 biz.at
 info.at
@@ -11939,6 +11948,22 @@
 lcube-server.de
 svn-repos.de
 
+// Leadpages : https://www.leadpages.net
+// Submitted by Greg Dallavalle <domains@leadpages.net>
+leadpages.co
+lpages.co
+lpusercontent.com
+
+// Lifetime Hosting : https://Lifetime.Hosting/
+// Submitted by Mike Fillator <support@lifetime.hosting>
+co.business
+co.education
+co.events
+co.financial
+co.network
+co.place
+co.technology
+
 // Lightmaker Property Manager, Inc. : https://app.lmpm.com/
 // Submitted by Greg Holland <greg.holland@lmpm.com>
 app.lmpm.com
@@ -12494,6 +12519,10 @@
 // Submitted by Stefan Neufeind <info@speedpartner.de>
 customer.speedpartner.de
 
+// Standard Library : https://stdlib.com
+// Submitted by Jacob Lee <jacob@stdlib.com>
+api.stdlib.com
+
 // Storj Labs Inc. : https://storj.io/
 // Submitted by Philip Hutchins <hostmaster@storj.io>
 storj.farm
@@ -12506,6 +12535,11 @@
 // Submitted by Dan Miller <dm@sub6.com>
 temp-dns.com
 
+// Swisscom Application Cloud: https://developer.swisscom.com
+// Submitted by Matthias.Winzeler <matthias.winzeler@swisscom.com>
+applicationcloud.io
+scapp.io
+
 // Synology, Inc. : https://www.synology.com/
 // Submitted by Rony Weng <ronyweng@synology.com>
 diskstation.me
@@ -12534,6 +12568,12 @@
 med.pl
 sopot.pl
 
+// Telebit : https://telebit.cloud
+// Submitted by AJ ONeal <aj@telebit.cloud>
+telebit.app
+telebit.io
+*.telebit.xyz
+
 // The Gwiddle Foundation : https://gwiddlefoundation.org.uk
 // Submitted by Joshua Bayfield <joshua.bayfield@gwiddlefoundation.org.uk>
 gwiddle.co.uk
@@ -12693,6 +12733,10 @@
 // Submitted by Olli Vanhoja <olli@zeit.co>
 now.sh
 
+// Zine EOOD : https://zine.bg/
+// Submitted by Martin Angelov <martin@zine.bg>
+bss.design
+
 // Zone.id : https://zone.id/
 // Submitted by Su Hendro <admin@zone.id>
 zone.id
diff --git a/net/base/registry_controlled_domains/effective_tld_names.gperf b/net/base/registry_controlled_domains/effective_tld_names.gperf
index 9443898..56f3713 100644
--- a/net/base/registry_controlled_domains/effective_tld_names.gperf
+++ b/net/base/registry_controlled_domains/effective_tld_names.gperf
@@ -44,6 +44,7 @@
 9guacu.br, 0
 a.bg, 0
 a.prod.fastly.net, 4
+a.run.app, 4
 a.se, 0
 a.ssl.fastly.net, 4
 aa.no, 0
@@ -129,7 +130,6 @@
 aco, 0
 act.au, 0
 act.edu.au, 0
-active, 0
 actor, 0
 ad, 0
 ad.jp, 0
@@ -337,6 +337,7 @@
 ap.leg.br, 4
 aparecida.br, 0
 apartments, 0
+api.stdlib.com, 4
 apigee.io, 4
 app, 0
 app.lmpm.com, 4
@@ -344,6 +345,7 @@
 app.os.stg.fedoraproject.org, 4
 appchizi.com, 4
 apple, 0
+applicationcloud.io, 4
 applinzi.com, 4
 apps.fbsbx.com, 4
 apps.lair.io, 4
@@ -732,7 +734,6 @@
 black, 0
 blackbaudcdn.net, 4
 blackfriday, 0
-blanco, 0
 blockbuster, 0
 blog, 0
 blog.bo, 0
@@ -910,6 +911,7 @@
 bs, 0
 bs.it, 0
 bsb.br, 0
+bss.design, 4
 bt, 0
 bt.it, 0
 bu.no, 0
@@ -936,7 +938,6 @@
 buzen.fukuoka.jp, 0
 buzz, 0
 bv, 0
-bv.nl, 0
 bw, 0
 by, 0
 bydgoszcz.pl, 0
@@ -947,6 +948,7 @@
 bz, 0
 bz.it, 0
 bzh, 0
+bzz.dapps.earth, 6
 c.bg, 0
 c.cdn77.org, 4
 c.la, 4
@@ -1275,6 +1277,7 @@
 co.at, 0
 co.bb, 0
 co.bi, 0
+co.business, 4
 co.bw, 0
 co.ca, 4
 co.ci, 0
@@ -1284,6 +1287,9 @@
 co.cr, 0
 co.cz, 4
 co.dk, 4
+co.education, 4
+co.events, 4
+co.financial, 4
 co.gg, 0
 co.gl, 0
 co.gy, 0
@@ -1308,18 +1314,21 @@
 co.mw, 0
 co.mz, 0
 co.na, 0
+co.network, 4
 co.ni, 0
 co.nl, 4
 co.no, 4
 co.nz, 0
 co.om, 0
 co.pl, 4
+co.place, 4
 co.pn, 0
 co.pw, 0
 co.rs, 0
 co.rw, 0
 co.st, 0
 co.sz, 0
+co.technology, 4
 co.th, 0
 co.tj, 0
 co.tm, 0
@@ -1625,6 +1634,7 @@
 damnserver.com, 4
 dance, 0
 daplie.me, 4
+dapps.earth, 6
 data, 0
 database.museum, 0
 date, 0
@@ -1801,6 +1811,7 @@
 dvrcam.info, 4
 dvrdns.org, 4
 dy.fi, 4
+dyn-berlin.de, 4
 dyn-ip24.de, 4
 dyn-o-saur.com, 4
 dyn-vpn.de, 4
@@ -2061,7 +2072,6 @@
 environment.museum, 0
 environmentalconservation.museum, 0
 epilepsy.museum, 0
-epost, 0
 epson, 0
 equipment, 0
 equipment.aero, 0
@@ -2156,6 +2166,7 @@
 farsund.no, 0
 fashion, 0
 fast, 0
+fastly-terrarium.com, 4
 fastlylb.net, 4
 fastpanel.direct, 4
 fastvps-server.com, 4
@@ -2196,6 +2207,12 @@
 field.museum, 0
 figueres.museum, 0
 filatelia.museum, 0
+filegear-au.me, 4
+filegear-de.me, 4
+filegear-gb.me, 4
+filegear-ie.me, 4
+filegear-jp.me, 4
+filegear-sg.me, 4
 filegear.me, 4
 film, 0
 film.hu, 0
@@ -3268,7 +3285,16 @@
 imperia.it, 0
 in, 0
 in-addr.arpa, 0
+in-berlin.de, 4
+in-brb.de, 4
+in-butter.de, 4
+in-dsl.de, 4
+in-dsl.net, 4
+in-dsl.org, 4
 in-the-band.net, 4
+in-vpn.de, 4
+in-vpn.net, 4
+in-vpn.org, 4
 in.eu.org, 4
 in.futurecms.at, 6
 in.na, 0
@@ -4153,6 +4179,7 @@
 lcube-server.de, 4
 lds, 0
 le.it, 0
+leadpages.co, 4
 leangaviika.no, 0
 lease, 0
 leasing.aero, 0
@@ -4322,8 +4349,10 @@
 love, 0
 lowicz.pl, 0
 loyalist.museum, 0
+lpages.co, 4
 lpl, 0
 lplfinancial, 0
+lpusercontent.com, 4
 lr, 0
 ls, 0
 lt, 0
@@ -6378,6 +6407,7 @@
 rugby, 0
 ruhr, 0
 run, 0
+run.app, 4
 ruovat.no, 0
 russia.museum, 0
 rv.ua, 0
@@ -6587,6 +6617,7 @@
 sc.ug, 0
 sc.us, 0
 sca, 0
+scapp.io, 4
 scb, 0
 sch.ae, 0
 sch.id, 0
@@ -6979,7 +7010,6 @@
 spdns.eu, 4
 spdns.org, 4
 spectrum.myjino.ru, 6
-spiegel, 0
 spjelkavik.no, 0
 sport, 0
 sport.hu, 0
@@ -7267,6 +7297,9 @@
 tel, 0
 tel.tr, 0
 tele.amune.org, 4
+telebit.app, 4
+telebit.io, 4
+telebit.xyz, 6
 telefonica, 0
 telekommunikation.museum, 0
 television.museum, 0
@@ -8636,7 +8669,6 @@
 zhitomir.ua, 0
 zhytomyr.ua, 0
 zip, 0
-zippo, 0
 zj.cn, 0
 zlg.br, 0
 zm, 0
diff --git a/net/dns/fuzzed_host_resolver.cc b/net/dns/fuzzed_host_resolver.cc
index 7b4c0cf..9360fb1 100644
--- a/net/dns/fuzzed_host_resolver.cc
+++ b/net/dns/fuzzed_host_resolver.cc
@@ -30,6 +30,7 @@
 #include "net/dns/dns_config.h"
 #include "net/dns/dns_hosts.h"
 #include "net/dns/mdns_client.h"
+#include "net/dns/public/util.h"
 #include "net/log/net_log_with_source.h"
 #include "net/socket/datagram_server_socket.h"
 #include "net/socket/fuzzed_datagram_client_socket.h"
@@ -291,6 +292,10 @@
     for (int i = 0; i < num_socket_pairs; ++i) {
       auto send_socket =
           std::make_unique<FuzzedDatagramClientSocket>(data_provider_);
+      AddressFamily address_family = data_provider_->ConsumeBool()
+                                         ? ADDRESS_FAMILY_IPV4
+                                         : ADDRESS_FAMILY_IPV6;
+      send_socket->Connect(dns_util::GetMdnsGroupEndPoint(address_family));
       auto recv_socket = std::make_unique<FuzzedMdnsSocket>(data_provider_);
       socket_pairs->push_back(
           std::make_pair(std::move(send_socket), std::move(recv_socket)));
diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc
index 50a99c15..e20860ca 100644
--- a/net/http/http_network_transaction.cc
+++ b/net/http/http_network_transaction.cc
@@ -128,9 +128,14 @@
 
 HttpNetworkTransaction::~HttpNetworkTransaction() {
 #if BUILDFLAG(ENABLE_REPORTING)
-  // If no error or success report has been generated yet at this point, then
-  // this network transaction was prematurely cancelled.
-  GenerateNetworkErrorLoggingReport(ERR_ABORTED);
+  // Report a success if we have not already done so. Errors would have been
+  // reported from DoCallback(), DoReadBodyComplete(), HandleIOError(), or
+  // DoReadHeadersComplete().
+  // Note: This may incorrectly report an error as a success, e.g. if the
+  // request is cancelled after successfully receiving headers but would
+  // otherwise have encountered an error on reading the body.
+  if (headers_valid_ && next_state_ == STATE_NONE)
+    GenerateNetworkErrorLoggingReport(OK);
 #endif  // BUILDFLAG(ENABLE_REPORTING)
   if (stream_.get()) {
     // TODO(mbelshe): The stream_ should be able to compute whether or not the
@@ -1250,15 +1255,12 @@
   ProcessNetworkErrorLoggingHeader();
 
   // Generate NEL report here if we have to report an HTTP error (4xx or 5xx
-  // code), or if the response body will not be read, or on a redirect.
-  // Note: This will report a success for a redirect even if an error is
-  // encountered later while draining the body.
+  // code), or if the response body will not be read.
   int response_code = response_.headers->response_code();
   if ((response_code >= 400 && response_code < 600) ||
       response_code == HTTP_NO_CONTENT || response_code == HTTP_RESET_CONTENT ||
       response_code == HTTP_NOT_MODIFIED || request_->method == "HEAD" ||
-      response_.headers->GetContentLength() == 0 ||
-      response_.headers->IsRedirect(nullptr /* location */)) {
+      response_.headers->GetContentLength() == 0) {
     GenerateNetworkErrorLoggingReport(OK);
   }
 #endif  // BUILDFLAG(ENABLE_REPORTING)
diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc
index c5dc3d1..4c5681e4 100644
--- a/net/http/http_network_transaction_unittest.cc
+++ b/net/http/http_network_transaction_unittest.cc
@@ -646,14 +646,16 @@
 
   bool socket_requested() const { return socket_requested_; }
 
-  int RequestSocket(const std::string& group_name,
-                    const void* socket_params,
-                    RequestPriority priority,
-                    const SocketTag& socket_tag,
-                    ClientSocketPool::RespectLimits respect_limits,
-                    ClientSocketHandle* handle,
-                    CompletionOnceCallback callback,
-                    const NetLogWithSource& net_log) override {
+  int RequestSocket(
+      const std::string& group_name,
+      const void* socket_params,
+      RequestPriority priority,
+      const SocketTag& socket_tag,
+      ClientSocketPool::RespectLimits respect_limits,
+      ClientSocketHandle* handle,
+      CompletionOnceCallback callback,
+      const ClientSocketPool::ProxyAuthCallback& proxy_auth_callback,
+      const NetLogWithSource& net_log) override {
     last_group_name_ = group_name;
     socket_requested_ = true;
     return ERR_IO_PENDING;
@@ -18248,11 +18250,6 @@
     request.traffic_annotation =
         net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
 
-    MockWrite data_writes[] = {
-        MockWrite("GET / HTTP/1.1\r\n"
-                  "Host: www.example.org\r\n"
-                  "Connection: keep-alive\r\n\r\n"),
-    };
     MockRead data_reads[] = {
         MockRead("HTTP/1.0 200 OK\r\n"),
         MockRead("Report-To: {\"group\": \"nel\", \"max_age\": 86400, "
@@ -18262,6 +18259,11 @@
         MockRead("hello world"),
         MockRead(SYNCHRONOUS, OK),
     };
+    MockWrite data_writes[] = {
+        MockWrite("GET / HTTP/1.1\r\n"
+                  "Host: www.example.org\r\n"
+                  "Connection: keep-alive\r\n\r\n"),
+    };
 
     StaticSocketDataProvider reads(data_reads, data_writes);
     session_deps_.socket_factory->AddSocketDataProvider(&reads);
@@ -18376,13 +18378,6 @@
   // Makes an HTTPS request that should install a valid NEL policy.
   void RequestPolicy(CertStatus cert_status = 0) {
     std::string extra_header_string = extra_headers_.ToString();
-    MockWrite data_writes[] = {
-        MockWrite("GET / HTTP/1.1\r\n"
-                  "Host: www.example.org\r\n"
-                  "Connection: keep-alive\r\n"),
-        MockWrite(ASYNC, extra_header_string.data(),
-                  extra_header_string.size()),
-    };
     MockRead data_reads[] = {
         MockRead("HTTP/1.0 200 OK\r\n"),
         MockRead("NEL: {\"report_to\": \"nel\", \"max_age\": 86400}\r\n"),
@@ -18390,6 +18385,13 @@
         MockRead("hello world"),
         MockRead(SYNCHRONOUS, OK),
     };
+    MockWrite data_writes[] = {
+        MockWrite("GET / HTTP/1.1\r\n"
+                  "Host: www.example.org\r\n"
+                  "Connection: keep-alive\r\n"),
+        MockWrite(ASYNC, extra_header_string.data(),
+                  extra_header_string.size()),
+    };
 
     StaticSocketDataProvider reads(data_reads, data_writes);
     session_deps_.socket_factory->AddSocketDataProvider(&reads);
@@ -18608,18 +18610,18 @@
 TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
        CreateReportReadBodyError) {
   std::string extra_header_string = extra_headers_.ToString();
-  MockWrite data_writes[] = {
-      MockWrite("GET / HTTP/1.1\r\n"
-                "Host: www.example.org\r\n"
-                "Connection: keep-alive\r\n"),
-      MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
-  };
   MockRead data_reads[] = {
       MockRead("HTTP/1.0 200 OK\r\n"),
       MockRead("Content-Length: 100\r\n\r\n"),  // wrong content length
       MockRead("hello world"),
       MockRead(SYNCHRONOUS, OK),
   };
+  MockWrite data_writes[] = {
+      MockWrite("GET / HTTP/1.1\r\n"
+                "Host: www.example.org\r\n"
+                "Connection: keep-alive\r\n"),
+      MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
+  };
 
   StaticSocketDataProvider reads(data_reads, data_writes);
   session_deps_.socket_factory->AddSocketDataProvider(&reads);
@@ -18662,18 +18664,18 @@
 TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
        CreateReportReadBodyErrorAsync) {
   std::string extra_header_string = extra_headers_.ToString();
-  MockWrite data_writes[] = {
-      MockWrite("GET / HTTP/1.1\r\n"
-                "Host: www.example.org\r\n"
-                "Connection: keep-alive\r\n"),
-      MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
-  };
   MockRead data_reads[] = {
       MockRead("HTTP/1.0 200 OK\r\n"),
       MockRead("Content-Length: 100\r\n\r\n"),  // wrong content length
       MockRead("hello world"),
       MockRead(ASYNC, OK),
   };
+  MockWrite data_writes[] = {
+      MockWrite("GET / HTTP/1.1\r\n"
+                "Host: www.example.org\r\n"
+                "Connection: keep-alive\r\n"),
+      MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
+  };
 
   StaticSocketDataProvider reads(data_reads, data_writes);
   session_deps_.socket_factory->AddSocketDataProvider(&reads);
@@ -19239,67 +19241,6 @@
   EXPECT_EQ(0, error3.reporting_upload_depth);
 }
 
-TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
-       CreateReportCancelAfterStart) {
-  StaticSocketDataProvider data;
-  data.set_connect_data(MockConnect(SYNCHRONOUS, ERR_IO_PENDING));
-  session_deps_.socket_factory->AddSocketDataProvider(&data);
-
-  TestCompletionCallback callback;
-  auto session = CreateSession(&session_deps_);
-  auto trans =
-      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
-  int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
-  EXPECT_EQ(rv, ERR_IO_PENDING);
-
-  // Cancel after start.
-  trans.reset();
-
-  ASSERT_EQ(1u, network_error_logging_service()->errors().size());
-  CheckReport(0 /* index */, 0 /* status_code */, ERR_ABORTED,
-              IPAddress() /* server_ip */);
-}
-
-TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest,
-       CreateReportCancelBeforeReadingBody) {
-  std::string extra_header_string = extra_headers_.ToString();
-  MockWrite data_writes[] = {
-      MockWrite("GET / HTTP/1.1\r\n"
-                "Host: www.example.org\r\n"
-                "Connection: keep-alive\r\n"),
-      MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
-  };
-  MockRead data_reads[] = {
-      MockRead("HTTP/1.0 200 OK\r\n"),
-      MockRead("Content-Length: 100\r\n\r\n"),  // Body is never read.
-  };
-
-  StaticSocketDataProvider data(data_reads, data_writes);
-  session_deps_.socket_factory->AddSocketDataProvider(&data);
-
-  SSLSocketDataProvider ssl(ASYNC, OK);
-  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl);
-
-  TestCompletionCallback callback;
-  auto session = CreateSession(&session_deps_);
-  auto trans =
-      std::make_unique<HttpNetworkTransaction>(DEFAULT_PRIORITY, session.get());
-  int rv = trans->Start(&request_, callback.callback(), NetLogWithSource());
-  EXPECT_THAT(callback.GetResult(rv), IsOk());
-
-  const HttpResponseInfo* response = trans->GetResponseInfo();
-  ASSERT_TRUE(response);
-
-  EXPECT_TRUE(response->headers);
-  EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
-
-  // Cancel before reading the body.
-  trans.reset();
-
-  ASSERT_EQ(1u, network_error_logging_service()->errors().size());
-  CheckReport(0 /* index */, 200 /* status_code */, ERR_ABORTED);
-}
-
 TEST_F(HttpNetworkTransactionNetworkErrorLoggingTest, DontCreateReportHttp) {
   base::HistogramTester histograms;
   RequestPolicy();
@@ -19320,8 +19261,8 @@
       MockWrite(ASYNC, extra_header_string.data(), extra_header_string.size()),
   };
 
-  StaticSocketDataProvider data(data_reads, data_writes);
-  session_deps_.socket_factory->AddSocketDataProvider(&data);
+  StaticSocketDataProvider reads(data_reads, data_writes);
+  session_deps_.socket_factory->AddSocketDataProvider(&reads);
 
   // Insecure url
   url_ = "http://www.example.org/";
diff --git a/net/http/http_proxy_client_socket_pool_unittest.cc b/net/http/http_proxy_client_socket_pool_unittest.cc
index 9f4509b..56f3760 100644
--- a/net/http/http_proxy_client_socket_pool_unittest.cc
+++ b/net/http/http_proxy_client_socket_pool_unittest.cc
@@ -258,9 +258,10 @@
 
   Initialize(reads, writes, spdy_reads, spdy_writes);
 
-  int rv = handle_.Init("a", CreateTunnelParams(), LOW, SocketTag(),
-                        ClientSocketPool::RespectLimits::ENABLED,
-                        callback_.callback(), pool_.get(), NetLogWithSource());
+  int rv = handle_.Init(
+      "a", CreateTunnelParams(), LOW, SocketTag(),
+      ClientSocketPool::RespectLimits::ENABLED, callback_.callback(),
+      ClientSocketPool::ProxyAuthCallback(), pool_.get(), NetLogWithSource());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
   EXPECT_FALSE(handle_.is_initialized());
   EXPECT_FALSE(handle_.socket());
@@ -299,9 +300,10 @@
   Initialize(reads, writes, base::span<MockRead>(), base::span<MockWrite>());
   AddAuthToCache();
 
-  int rv = handle_.Init("a", CreateTunnelParams(), LOW, SocketTag(),
-                        ClientSocketPool::RespectLimits::ENABLED,
-                        callback_.callback(), pool_.get(), NetLogWithSource());
+  int rv = handle_.Init(
+      "a", CreateTunnelParams(), LOW, SocketTag(),
+      ClientSocketPool::RespectLimits::ENABLED, callback_.callback(),
+      ClientSocketPool::ProxyAuthCallback(), pool_.get(), NetLogWithSource());
   EXPECT_THAT(rv, IsOk());
   EXPECT_TRUE(handle_.is_initialized());
   ASSERT_TRUE(handle_.socket());
@@ -334,9 +336,10 @@
   Initialize(reads, writes, spdy_reads, spdy_writes);
   AddAuthToCache();
 
-  int rv = handle_.Init("a", CreateTunnelParams(), LOW, SocketTag(),
-                        ClientSocketPool::RespectLimits::ENABLED,
-                        callback_.callback(), pool_.get(), NetLogWithSource());
+  int rv = handle_.Init(
+      "a", CreateTunnelParams(), LOW, SocketTag(),
+      ClientSocketPool::RespectLimits::ENABLED, callback_.callback(),
+      ClientSocketPool::ProxyAuthCallback(), pool_.get(), NetLogWithSource());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
   EXPECT_FALSE(handle_.is_initialized());
   EXPECT_FALSE(handle_.socket());
@@ -361,9 +364,10 @@
   }
   socket_factory()->AddSSLSocketDataProvider(ssl_data_.get());
 
-  int rv = handle_.Init("a", CreateTunnelParams(), LOW, SocketTag(),
-                        ClientSocketPool::RespectLimits::ENABLED,
-                        callback_.callback(), pool_.get(), NetLogWithSource());
+  int rv = handle_.Init(
+      "a", CreateTunnelParams(), LOW, SocketTag(),
+      ClientSocketPool::RespectLimits::ENABLED, callback_.callback(),
+      ClientSocketPool::ProxyAuthCallback(), pool_.get(), NetLogWithSource());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
   EXPECT_FALSE(handle_.is_initialized());
   EXPECT_FALSE(handle_.socket());
@@ -420,9 +424,10 @@
   Initialize(reads, writes, spdy_reads, spdy_writes);
   AddAuthToCache();
 
-  int rv = handle_.Init("a", CreateTunnelParams(), LOW, SocketTag(),
-                        ClientSocketPool::RespectLimits::ENABLED,
-                        callback_.callback(), pool_.get(), NetLogWithSource());
+  int rv = handle_.Init(
+      "a", CreateTunnelParams(), LOW, SocketTag(),
+      ClientSocketPool::RespectLimits::ENABLED, callback_.callback(),
+      ClientSocketPool::ProxyAuthCallback(), pool_.get(), NetLogWithSource());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
   EXPECT_FALSE(handle_.is_initialized());
   EXPECT_FALSE(handle_.socket());
@@ -472,10 +477,10 @@
   SocketTag tag2(getuid(), 0x87654321);
 
   // Verify requested socket is tagged properly.
-  int rv =
-      handle_.Init("a", CreateNoTunnelParams(), LOW, tag1,
-                   ClientSocketPool::RespectLimits::ENABLED,
-                   CompletionOnceCallback(), pool_.get(), NetLogWithSource());
+  int rv = handle_.Init(
+      "a", CreateNoTunnelParams(), LOW, tag1,
+      ClientSocketPool::RespectLimits::ENABLED, CompletionOnceCallback(),
+      ClientSocketPool::ProxyAuthCallback(), pool_.get(), NetLogWithSource());
   EXPECT_THAT(rv, IsOk());
   EXPECT_TRUE(handle_.is_initialized());
   ASSERT_TRUE(handle_.socket());
@@ -487,9 +492,10 @@
   // Verify reused socket is retagged properly.
   StreamSocket* socket = handle_.socket();
   handle_.Reset();
-  rv = handle_.Init("a", CreateNoTunnelParams(), LOW, tag2,
-                    ClientSocketPool::RespectLimits::ENABLED,
-                    CompletionOnceCallback(), pool_.get(), NetLogWithSource());
+  rv = handle_.Init(
+      "a", CreateNoTunnelParams(), LOW, tag2,
+      ClientSocketPool::RespectLimits::ENABLED, CompletionOnceCallback(),
+      ClientSocketPool::ProxyAuthCallback(), pool_.get(), NetLogWithSource());
   EXPECT_THAT(rv, IsOk());
   EXPECT_TRUE(handle_.socket());
   EXPECT_TRUE(handle_.socket()->IsConnected());
@@ -523,10 +529,10 @@
   SocketTag tag2(getuid(), 0x87654321);
 
   // Verify requested socket is tagged properly.
-  int rv =
-      handle_.Init("a", CreateTunnelParams(), LOW, tag1,
-                   ClientSocketPool::RespectLimits::ENABLED,
-                   CompletionOnceCallback(), pool_.get(), NetLogWithSource());
+  int rv = handle_.Init(
+      "a", CreateTunnelParams(), LOW, tag1,
+      ClientSocketPool::RespectLimits::ENABLED, CompletionOnceCallback(),
+      ClientSocketPool::ProxyAuthCallback(), pool_.get(), NetLogWithSource());
   EXPECT_THAT(rv, IsOk());
   EXPECT_TRUE(handle_.is_initialized());
   ASSERT_TRUE(handle_.socket());
@@ -538,9 +544,10 @@
   // Verify reused socket is retagged properly.
   StreamSocket* socket = handle_.socket();
   handle_.Reset();
-  rv = handle_.Init("a", CreateNoTunnelParams(), LOW, tag2,
-                    ClientSocketPool::RespectLimits::ENABLED,
-                    CompletionOnceCallback(), pool_.get(), NetLogWithSource());
+  rv = handle_.Init(
+      "a", CreateNoTunnelParams(), LOW, tag2,
+      ClientSocketPool::RespectLimits::ENABLED, CompletionOnceCallback(),
+      ClientSocketPool::ProxyAuthCallback(), pool_.get(), NetLogWithSource());
   EXPECT_THAT(rv, IsOk());
   EXPECT_TRUE(handle_.socket());
   EXPECT_TRUE(handle_.socket()->IsConnected());
diff --git a/net/http/http_stream_factory_job.cc b/net/http/http_stream_factory_job.cc
index 4f72e404..2531856 100644
--- a/net/http/http_stream_factory_job.cc
+++ b/net/http/http_stream_factory_job.cc
@@ -1001,7 +1001,8 @@
         request_info_.load_flags, priority_, session_, proxy_info_,
         websocket_server_ssl_config, proxy_ssl_config_,
         request_info_.privacy_mode, net_log_, connection_.get(),
-        resolution_callback, io_callback_);
+        resolution_callback, io_callback_,
+        ClientSocketPool::ProxyAuthCallback());
   }
 
   return InitSocketHandleForHttpRequest(
@@ -1009,7 +1010,7 @@
       request_info_.load_flags, priority_, session_, proxy_info_, quic_version_,
       server_ssl_config_, proxy_ssl_config_, request_info_.privacy_mode,
       request_info_.socket_tag, net_log_, connection_.get(),
-      resolution_callback, io_callback_);
+      resolution_callback, io_callback_, ClientSocketPool::ProxyAuthCallback());
 }
 
 void HttpStreamFactory::Job::OnQuicHostResolution(int result) {
diff --git a/net/http/http_stream_factory_unittest.cc b/net/http/http_stream_factory_unittest.cc
index db1c5665..8721bbb 100644
--- a/net/http/http_stream_factory_unittest.cc
+++ b/net/http/http_stream_factory_unittest.cc
@@ -409,14 +409,16 @@
     last_group_name_.clear();
   }
 
-  int RequestSocket(const std::string& group_name,
-                    const void* socket_params,
-                    RequestPriority priority,
-                    const SocketTag& socket_tag,
-                    ClientSocketPool::RespectLimits respect_limits,
-                    ClientSocketHandle* handle,
-                    CompletionOnceCallback callback,
-                    const NetLogWithSource& net_log) override {
+  int RequestSocket(
+      const std::string& group_name,
+      const void* socket_params,
+      RequestPriority priority,
+      const SocketTag& socket_tag,
+      ClientSocketPool::RespectLimits respect_limits,
+      ClientSocketHandle* handle,
+      CompletionOnceCallback callback,
+      const ClientSocketPool::ProxyAuthCallback& proxy_auth_callback,
+      const NetLogWithSource& net_log) override {
     ADD_FAILURE();
     return ERR_UNEXPECTED;
   }
@@ -2132,7 +2134,7 @@
         TransportClientSocketPool::SocketParams::CreateFromSSLSocketParams(
             ssl_params),
         MEDIUM, SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
-        callback.callback(),
+        callback.callback(), ClientSocketPool::ProxyAuthCallback(),
         session->GetTransportSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL),
         NetLogWithSource());
     rv = callback.GetResult(rv);
diff --git a/net/http/transport_security_state_static.json b/net/http/transport_security_state_static.json
index 85d562b..db61c18 100644
--- a/net/http/transport_security_state_static.json
+++ b/net/http/transport_security_state_static.json
@@ -8293,7 +8293,6 @@
     { "name": "peoplesbankal.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "pepperworldhotshop.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "pethub.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "pharmgkb.org", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "philadelphia.com.mx", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "picoauto.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "picotech.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -11662,7 +11661,6 @@
     { "name": "ivi.es", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "jan-cermak.cz", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "jimgao.tk", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "itcko.sk", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "joedavison.me", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "joshuarogers.net", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "jetsetpay.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -53329,7 +53327,6 @@
     { "name": "nakitbonus2.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "nansa.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "narardetval.se", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "narduin.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "nature-shots.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "natureword.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ncdc.pt", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -61384,7 +61381,6 @@
     { "name": "irish.radio", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "irishradioplayer.radio", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "irkfap.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "isaac.world", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "isbaseballstillon.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "isg-tech.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "isolta.fi", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -62165,7 +62161,6 @@
     { "name": "toutelathailande.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "tower.land", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "toycu.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "toysale.by", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "trackfeed.tokyo", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "tradlost-natverk.se", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "trafficmgr.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -65781,7 +65776,6 @@
     { "name": "077768.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "081115.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "0x41.us", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "138000.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "161263.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "162361.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "177603.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -67405,6 +67399,485 @@
     { "name": "zeadaniel.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "zerocz.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "zhimingwang.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "03012.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "03018.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "035711630.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "04dco.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "0736ks.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "08845.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "095598.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "13214.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "132301.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "17kpw.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "288game.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "303312.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "338sa.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "377625.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "377632.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "377817.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "378553.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "4553.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "518.com.tw", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "69games.xxx", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "6dec.gc.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "756337.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "787637.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "901543.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "984.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "998sa.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "999salon.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "999salon.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "99spokes.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ab288.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ab2888.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ab28s.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "adviserplus.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "alighierirescaldina.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "all878.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "allbetgame.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "allbetgaming.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "allcinema.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "altered.si", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "alxlegal.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "amal2019.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "anarchistos.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "aprendiendoforexhoy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "arshell.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "arthuryidi.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "artistedeparis.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "artiwear.com.tw", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ashtonc.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "autorepairseattle.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ayumix3.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "aznews.site", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "azurlane.cool", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "b-dd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bancomap.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "beaker.coffee", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "beeswarmrehoming.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bernar.do", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bernyweb.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "besuccessful.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bi1gif.space", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bierwebshop.be", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bionima.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bitcoincasinos.pro", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "blblblblbl.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "blogcast.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bnck.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bonus.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bookofdenim.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "borysenko.se", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "brainyapp.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bravor.pe", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "breizh.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bugu.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "buycoins.top", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "byte.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bytenoc.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cadmanlaw.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cafejulian.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "calculates.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "calypsohost.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cameroonlounge.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "camisetasmalwee.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "campusfit.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cartelloni.roma.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "castlepointanime.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "catbox.moe", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cb1388.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cb1588.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "centermk.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cfc-swc.gc.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "charset.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "checktechnology.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "chefz.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "chengarda.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "chrono-ski-aravis.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cichol.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "classical-guitar-school.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "clevvi.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "clich.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "coinsmat.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "coinsz.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "coldlasers.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "collegesecretary.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "colors3d.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "comidina.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "comiteexpertes.gc.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "communalconsulting.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "consulting-cloud.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "coriolis.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cramersoft.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dansedesalonsaintave.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dat4u.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "daveedave.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dayofthegirl.gc.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "daywalkers-photography.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dec6.gc.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "defendersz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "degoticapunk.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "deviajesturismo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "devtoys.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dimagrimentoincorso.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "doggo.dance", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "download.dk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "drgiyaseddin.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dronesz.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dutchsailors.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ealadel.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "earfolds.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ecomia.dk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "eges.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "eightysoft.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "elaboratefiction.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "elburgozagalicos.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "elevationcreative.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "elevationfilms.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "endviolence.gc.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "entravex.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "epaslaugos.lt", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "epitome.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "epitome.games", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "esdvfootloose.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "esim.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "esport-agency.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "euroroad17.dk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "expertpanel.gc.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "exvs.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "eythorsson.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "facesdr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "faggut.gg", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fanzhencha.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fastconv.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fboerman.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fcbarcelona.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fdpbrig.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "feat.agency", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "feeg-wage.gc.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "feg-wge.gc.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fegc-wgec.gc.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "felixklein.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "femmes-women.gc.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "femmes.gc.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fflone.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "financialfreedomaus.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "finilaviolence.gc.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fitnessunder50.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fleetyards.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fmbilder.se", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "foliumbiosciences.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fosgreece.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fromthemonks.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fundavi.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fztopsec.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gamenauta.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gameres.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gaycamvids.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "getintopc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "giemall.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "globalinvestigations.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gmuh.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gr8engineer2b.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "handyklinik.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "haorenka.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "headforcloud.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hell.sh", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hicts.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hinaryazan.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hitechgr.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hoberg.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "homelab.farm", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "horoca.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hotcamvids.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hothiphopmusic.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hugh-dancy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "humio.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hvenetworks.cf", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hysolate.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ibericarmotorsmalaga.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ibericarmovilcentro.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ibericarmovilsur.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ibericarreicomsa.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ibericartechnik.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "icci.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "icelandicasian.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "icnc.ga", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "idbs.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "impactingsports.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "infraredradiant.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "iningrui.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "insegne.roma.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "instagib.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "iondrey.cf", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "iondrey.ga", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "iondrey.gq", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "iondrey.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "iwd.gc.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "izolpoznan.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jayharkess.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jif.gc.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jingyunbank.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jomibe.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jonasberger.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "journeedesfilles.gc.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jsk26.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "json.download", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jsproxy.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "juergmeier.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "justmade.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kaihub.tech", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kaisab.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kaktuskola.se", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "karrot.world", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kastgroup.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kb5151.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "keevault.pm", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kevincramer.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kevindavid.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "keywalker.co.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kfz-service-wachtmann.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kindconcentrates.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kitpartners.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kjmedia.dk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kk.sb", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kolibrisolutions.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kometia.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "laan247.dk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lachlanallison.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "landoncreekapartments.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "laresistencia.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lartduportrait.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "laurencball.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "letsflyinto.space", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "leuchtmann.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lffweb.ga", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "libravatar.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "libre-innovation.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lifeslonglist.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lincolnboolefoundation.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "liturgical.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "live8811.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "live8899.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "live8899.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "live8899.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "live9922.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lm1628.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lm228.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lm338.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "longma168.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "m12uno.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "madpsy.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "madridagency.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "maikoloc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "malacat.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "martinbaileyphotography.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "matiaskorhonen.fi", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mcblain.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "medeurope.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "media101.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "medicine.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "medicsz.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mele.ro", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mhf.gc.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mining.diamonds", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mns.co.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mns.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "momove.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "monopoly-one.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "monwarez.ovh", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "moseracctg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "multimed-solutions.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "muszic.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mycaelis.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "myconf.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "myhostvm.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mytime.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "namu.la", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ndx.ee", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nekorektni.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "netzklad.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "newburghhistoryblog.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "newflora.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "noradevot.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "noseastumismo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nt-catala.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nuipogoda.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "objetperso.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ochrebridge.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "offtopica.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "oleron.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "onlinesystem.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "opinionitech.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "oppress.life", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ortizmario.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "osez-l-odyssee.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "osmani-gebaeudereinigung.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pbz.pw", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pcsremodel.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pen-sec.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pfssales.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pictoriastudios.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pk8k.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "poetry.ge", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pogotowiekomputeroweolsztyn.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "polarfisk.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pommetelecom.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "porcore.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "profilib.top", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "prosperity-textile.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pteceng.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "purplscientific.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "qacademy.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "qualpay.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "quantifiedcommerce.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ragu.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ralvke.rocks", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rap4ever.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "raspberrypi.tv", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ratelimited.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ravencoin.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ravencoin.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "raysei.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rdcdesign.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rdfencingandgates.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "realcolors.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "retefrati.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "retropack.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "richlj.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "richlj.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "richtoinfinity.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "riight.online", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "romaindepeigne.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rootsh3ll.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rssnews.world", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "s1128.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sac.moe", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "saytu.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "schoenstatt-fathers.link", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "schoolarchive.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "scity88.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "scottspainting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "searchmore.dk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "searx.run", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "securemind.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sellcoins.top", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "semakincantik.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "serban.ro", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sewatec.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sexedquickies.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sexedrescue.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "shadowsocks.live", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sheaspire.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "siwyd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sketch.jpn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "skorovsud.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "skylarker.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sliptrickrecords.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "smrtrpck.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "softlan.com.py", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "solomonsklash.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "soulcasa.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "splorge.cloud", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "spotty.tech", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "spumanti.dk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "starryvoid.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "steamosaic.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "stefanfriedli.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "stopmodacruel.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "stucki-bagger.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sun1218.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sun1245.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sun1345.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sun1378.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sun668.asia", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sun668.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sunbingchen.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "suncity288.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "suncity8118.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "suncity8118.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "suncity818.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "suncity818.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "suncity8338.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "suncity8338.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "suncity858.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "suncity858.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "suncity8668.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "suncity8998.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "surfpacific.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "suzaku.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "swc-cfc.gc.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "swingtimeinthegardens.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "swissmadesecurity.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tagderinspiration.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "takeomi.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tcksolutions.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tdr.today", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "teetoptens.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "textpattern.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "the-archimedeans.org.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "thechargertimes.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "theclinician.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "theobora.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "theologyz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "thomas717.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "thomascauquil.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "totalclean.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "toxoproject.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "trekking-friends.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tsueri.cloud", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tvdates.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tycyc88.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "uastrategy.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "uberi.fi", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "uberifix.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "unblocked.pet", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "universe.horse", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "unpaismejor.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "uranius.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "utahhydrographics.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "uten.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "varmepumpe-guide.dk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vbsoft.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "verasani.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vextraz.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vim.ge", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vinosalmundo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vivemedialab.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "voceempaz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vrcinvestigations.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "wage-feeg.gc.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "wallis-inside.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "wallpapers-free.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "waterproofingahmedabad.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "webhotelsoversigt.dk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "websitesolutionsmedia.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "wellspringsga.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "westlahair.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "westlife.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "wge-feg.gc.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "wgec-fegc.gc.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "whitepack.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "whizdomcenter.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "whm.gc.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "whtcsj.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "women-femmes.gc.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "women.gc.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xm.digital", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xn--6oqx6c301allufxcm23a7sm.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xn--erban-e9b.ro", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xn--u8jvc1drbz972aywbk0by95ffo1aqm1c.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xn--underux-0za.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xoh.at", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "yezishurb.site", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "yicivideo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "young-brahmousin.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "yuvaindia.co.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zeiw.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zhl123.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zinglix.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zocial.life", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zoptiks.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     // END OF 1-YEAR BULK HSTS ENTRIES
 
     // Only eTLD+1 domains can be submitted automatically to hstspreload.org,
diff --git a/net/nqe/throughput_analyzer.cc b/net/nqe/throughput_analyzer.cc
index 2e9e2352..c539075 100644
--- a/net/nqe/throughput_analyzer.cc
+++ b/net/nqe/throughput_analyzer.cc
@@ -197,9 +197,16 @@
   // Try to remove the request from either |accuracy_degrading_requests_| or
   // |requests_|, since it is no longer active.
   if (accuracy_degrading_requests_.erase(&request) == 1u) {
-    // |request| cannot be in both |accuracy_degrading_requests_| and
-    // |requests_| at the same time.
-    DCHECK(requests_.end() == requests_.find(&request));
+    // Generally, |request| cannot be in both |accuracy_degrading_requests_|
+    // and |requests_| at the same time. However, in some cases, the same
+    // request may appear in both vectors. See https://crbug.com/849604 for
+    // more details.
+    // It's safe to delete |request| from |requests_| since (i)
+    // The observation window is currently not recording throughput, and (ii)
+    // |requests_| is a best effort guess of requests that are currently
+    // in-flight.
+    DCHECK(!IsCurrentlyTrackingThroughput());
+    requests_.erase(&request);
 
     // If a request that degraded the accuracy of throughput computation has
     // completed, then it may be possible to start the tracking window.
diff --git a/net/quic/quic_proxy_client_socket_unittest.cc b/net/quic/quic_proxy_client_socket_unittest.cc
index 35868a5f..0cb728b 100644
--- a/net/quic/quic_proxy_client_socket_unittest.cc
+++ b/net/quic/quic_proxy_client_socket_unittest.cc
@@ -34,6 +34,7 @@
 #include "net/quic/test_task_runner.h"
 #include "net/socket/socket_test_util.h"
 #include "net/test/cert_test_util.h"
+#include "net/test/gtest_util.h"
 #include "net/test/test_data_directory.h"
 #include "net/test/test_with_scoped_task_environment.h"
 #include "net/third_party/quic/core/crypto/null_encrypter.h"
diff --git a/net/socket/client_socket_handle.h b/net/socket/client_socket_handle.h
index 361075d..67c845f 100644
--- a/net/socket/client_socket_handle.h
+++ b/net/socket/client_socket_handle.h
@@ -86,6 +86,7 @@
            const SocketTag& socket_tag,
            ClientSocketPool::RespectLimits respect_limits,
            CompletionOnceCallback callback,
+           const ClientSocketPool::ProxyAuthCallback& proxy_auth_callback,
            PoolType* pool,
            const NetLogWithSource& net_log);
 
@@ -99,12 +100,13 @@
            const SocketTag& socket_tag,
            bool respect_limits,
            CompletionOnceCallback callback,
+           const ClientSocketPool::ProxyAuthCallback& proxy_auth_callback,
            PoolType* pool,
            const NetLogWithSource& net_log) {
     return Init(group_name, socket_params, priority, socket_tag,
                 respect_limits ? ClientSocketPool::RespectLimits::ENABLED
                                : ClientSocketPool::RespectLimits::DISABLED,
-                std::move(callback), pool, net_log);
+                std::move(callback), proxy_auth_callback, pool, net_log);
   }
 
   // Changes the priority of the ClientSocketHandle to the passed value.
@@ -265,6 +267,7 @@
     const SocketTag& socket_tag,
     ClientSocketPool::RespectLimits respect_limits,
     CompletionOnceCallback callback,
+    const ClientSocketPool::ProxyAuthCallback& proxy_auth_callback,
     PoolType* pool,
     const NetLogWithSource& net_log) {
   requesting_source_ = net_log.source();
@@ -276,9 +279,9 @@
   group_name_ = group_name;
   CompletionOnceCallback io_complete_callback =
       base::BindOnce(&ClientSocketHandle::OnIOComplete, base::Unretained(this));
-  int rv = pool_->RequestSocket(group_name, &socket_params, priority,
-                                socket_tag, respect_limits, this,
-                                std::move(io_complete_callback), net_log);
+  int rv = pool_->RequestSocket(
+      group_name, &socket_params, priority, socket_tag, respect_limits, this,
+      std::move(io_complete_callback), proxy_auth_callback, net_log);
   if (rv == ERR_IO_PENDING) {
     callback_ = std::move(callback);
   } else {
diff --git a/net/socket/client_socket_pool.h b/net/socket/client_socket_pool.h
index 40aba7e..df87580 100644
--- a/net/socket/client_socket_pool.h
+++ b/net/socket/client_socket_pool.h
@@ -25,6 +25,8 @@
 namespace net {
 
 class ClientSocketHandle;
+class HttpAuthController;
+class HttpResponseInfo;
 class NetLogWithSource;
 class StreamSocket;
 
@@ -70,6 +72,17 @@
   // SocketPool's global and per-group socket limits.
   enum class RespectLimits { DISABLED, ENABLED };
 
+  // ProxyAuthCallback is invoked when there is an auth challenge while
+  // connecting to a tunnel. When |restart_with_auth_callback| is invoked, the
+  // corresponding socket request is guaranteed not to be completed
+  // synchronously, nor will the ProxyAuthCallback be invoked against
+  // synchronously.
+  typedef base::RepeatingCallback<void(
+      const HttpResponseInfo& response,
+      HttpAuthController* auth_controller,
+      base::OnceClosure restart_with_auth_callback)>
+      ProxyAuthCallback;
+
   // Requests a connected socket for a group_name.
   //
   // There are five possible results from calling this function:
@@ -101,6 +114,9 @@
   // Profiling information for the request is saved to |net_log| if non-NULL.
   //
   // If |respect_limits| is DISABLED, priority must be HIGHEST.
+  //
+  // |on_proxy_auth_challenge_callback| currently has no effect, but will be
+  // hooked up in another CL.
   virtual int RequestSocket(const std::string& group_name,
                             const void* params,
                             RequestPriority priority,
@@ -108,6 +124,7 @@
                             RespectLimits respect_limits,
                             ClientSocketHandle* handle,
                             CompletionOnceCallback callback,
+                            const ProxyAuthCallback& proxy_auth_challenge,
                             const NetLogWithSource& net_log) = 0;
 
   // RequestSockets is used to request that |num_sockets| be connected in the
diff --git a/net/socket/client_socket_pool_base.cc b/net/socket/client_socket_pool_base.cc
index 35ce507..24ca35a 100644
--- a/net/socket/client_socket_pool_base.cc
+++ b/net/socket/client_socket_pool_base.cc
@@ -43,6 +43,7 @@
 ClientSocketPoolBaseHelper::Request::Request(
     ClientSocketHandle* handle,
     CompletionOnceCallback callback,
+    const ClientSocketPool::ProxyAuthCallback& proxy_auth_callback,
     RequestPriority priority,
     const SocketTag& socket_tag,
     ClientSocketPool::RespectLimits respect_limits,
@@ -50,6 +51,7 @@
     const NetLogWithSource& net_log)
     : handle_(handle),
       callback_(std::move(callback)),
+      proxy_auth_callback_(proxy_auth_callback),
       priority_(priority),
       respect_limits_(respect_limits),
       flags_(flags),
diff --git a/net/socket/client_socket_pool_base.h b/net/socket/client_socket_pool_base.h
index ce53dca..8dfd865 100644
--- a/net/socket/client_socket_pool_base.h
+++ b/net/socket/client_socket_pool_base.h
@@ -63,7 +63,6 @@
 
 namespace net {
 
-class ClientSocketHandle;
 struct NetLogSource;
 
 namespace internal {
@@ -89,6 +88,7 @@
    public:
     Request(ClientSocketHandle* handle,
             CompletionOnceCallback callback,
+            const ClientSocketPool::ProxyAuthCallback& proxy_auth_callback,
             RequestPriority priority,
             const SocketTag& socket_tag,
             ClientSocketPool::RespectLimits respect_limits,
@@ -100,6 +100,9 @@
     ClientSocketHandle* handle() const { return handle_; }
     bool has_callback() const { return static_cast<bool>(callback_); }
     CompletionOnceCallback release_callback() { return std::move(callback_); }
+    const ClientSocketPool::ProxyAuthCallback& proxy_auth_callback() const {
+      return proxy_auth_callback_;
+    }
     RequestPriority priority() const { return priority_; }
     void set_priority(RequestPriority priority) { priority_ = priority; }
     ClientSocketPool::RespectLimits respect_limits() const {
@@ -130,6 +133,7 @@
 
     ClientSocketHandle* const handle_;
     CompletionOnceCallback callback_;
+    const ClientSocketPool::ProxyAuthCallback proxy_auth_callback_;
     RequestPriority priority_;
     const ClientSocketPool::RespectLimits respect_limits_;
     const Flags flags_;
@@ -679,6 +683,7 @@
    public:
     Request(ClientSocketHandle* handle,
             CompletionOnceCallback callback,
+            const ClientSocketPool::ProxyAuthCallback& proxy_auth_callback,
             RequestPriority priority,
             const SocketTag& socket_tag,
             ClientSocketPool::RespectLimits respect_limits,
@@ -687,6 +692,7 @@
             const NetLogWithSource& net_log)
         : internal::ClientSocketPoolBaseHelper::Request(handle,
                                                         std::move(callback),
+                                                        proxy_auth_callback,
                                                         priority,
                                                         socket_tag,
                                                         respect_limits,
@@ -750,17 +756,20 @@
 
   // RequestSocket bundles up the parameters into a Request and then forwards to
   // ClientSocketPoolBaseHelper::RequestSocket().
-  int RequestSocket(const std::string& group_name,
-                    const scoped_refptr<SocketParams>& params,
-                    RequestPriority priority,
-                    const SocketTag& socket_tag,
-                    ClientSocketPool::RespectLimits respect_limits,
-                    ClientSocketHandle* handle,
-                    CompletionOnceCallback callback,
-                    const NetLogWithSource& net_log) {
-    std::unique_ptr<Request> request(new Request(
-        handle, std::move(callback), priority, socket_tag, respect_limits,
-        internal::ClientSocketPoolBaseHelper::NORMAL, params, net_log));
+  int RequestSocket(
+      const std::string& group_name,
+      const scoped_refptr<SocketParams>& params,
+      RequestPriority priority,
+      const SocketTag& socket_tag,
+      ClientSocketPool::RespectLimits respect_limits,
+      ClientSocketHandle* handle,
+      CompletionOnceCallback callback,
+      const ClientSocketPool::ProxyAuthCallback& proxy_auth_callback,
+      const NetLogWithSource& net_log) {
+    std::unique_ptr<Request> request = std::make_unique<Request>(
+        handle, std::move(callback), proxy_auth_callback, priority, socket_tag,
+        respect_limits, internal::ClientSocketPoolBaseHelper::NORMAL, params,
+        net_log);
     return helper_.RequestSocket(group_name, std::move(request));
   }
 
@@ -771,10 +780,11 @@
                       const scoped_refptr<SocketParams>& params,
                       int num_sockets,
                       const NetLogWithSource& net_log) {
-    const Request request(
-        nullptr /* no handle */, CompletionOnceCallback(), IDLE, SocketTag(),
-        ClientSocketPool::RespectLimits::ENABLED,
-        internal::ClientSocketPoolBaseHelper::NO_IDLE_SOCKETS, params, net_log);
+    const Request request(nullptr /* no handle */, CompletionOnceCallback(),
+                          ClientSocketPool::ProxyAuthCallback(), IDLE,
+                          SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
+                          internal::ClientSocketPoolBaseHelper::NO_IDLE_SOCKETS,
+                          params, net_log);
     helper_.RequestSockets(group_name, request, num_sockets);
   }
 
diff --git a/net/socket/client_socket_pool_base_unittest.cc b/net/socket/client_socket_pool_base_unittest.cc
index 335c26e..ed6d14e 100644
--- a/net/socket/client_socket_pool_base_unittest.cc
+++ b/net/socket/client_socket_pool_base_unittest.cc
@@ -582,12 +582,13 @@
                     RespectLimits respect_limits,
                     ClientSocketHandle* handle,
                     CompletionOnceCallback callback,
+                    const ProxyAuthCallback& proxy_auth_callback,
                     const NetLogWithSource& net_log) override {
     const scoped_refptr<TestSocketParams>* casted_socket_params =
         static_cast<const scoped_refptr<TestSocketParams>*>(params);
-    return base_.RequestSocket(group_name, *casted_socket_params, priority,
-                               socket_tag, respect_limits, handle,
-                               std::move(callback), net_log);
+    return base_.RequestSocket(
+        group_name, *casted_socket_params, priority, socket_tag, respect_limits,
+        handle, std::move(callback), proxy_auth_callback, net_log);
   }
 
   void RequestSockets(const std::string& group_name,
@@ -813,7 +814,9 @@
 
   EXPECT_EQ(OK, handle.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
                             ClientSocketPool::RespectLimits::ENABLED,
-                            callback.callback(), pool_.get(), log.bound()));
+                            callback.callback(),
+                            ClientSocketPool::ProxyAuthCallback(), pool_.get(),
+                            log.bound()));
   EXPECT_TRUE(handle.is_initialized());
   EXPECT_TRUE(handle.socket());
   TestLoadTimingInfoConnectedNotReused(handle);
@@ -848,10 +851,12 @@
   HttpResponseInfo info;
   info.headers = new HttpResponseHeaders(std::string());
   handle.set_ssl_error_response_info(info);
-  EXPECT_EQ(ERR_CONNECTION_FAILED,
-            handle.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
-                        ClientSocketPool::RespectLimits::ENABLED,
-                        callback.callback(), pool_.get(), log.bound()));
+  EXPECT_EQ(
+      ERR_CONNECTION_FAILED,
+      handle.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
+                  ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
+                  ClientSocketPool::ProxyAuthCallback(), pool_.get(),
+                  log.bound()));
   EXPECT_FALSE(handle.socket());
   EXPECT_FALSE(handle.is_ssl_error());
   EXPECT_TRUE(handle.ssl_error_response_info().headers.get() == NULL);
@@ -1183,19 +1188,22 @@
 
   ClientSocketHandle handle;
   TestCompletionCallback callback;
-  EXPECT_EQ(ERR_IO_PENDING,
-            handle.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
-                        ClientSocketPool::RespectLimits::ENABLED,
-                        callback.callback(), pool_.get(), NetLogWithSource()));
+  EXPECT_EQ(
+      ERR_IO_PENDING,
+      handle.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
+                  ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
+                  ClientSocketPool::ProxyAuthCallback(), pool_.get(),
+                  NetLogWithSource()));
 
   ClientSocketHandle handles[4];
   for (size_t i = 0; i < base::size(handles); ++i) {
     TestCompletionCallback callback;
-    EXPECT_EQ(
-        ERR_IO_PENDING,
-        handles[i].Init("b", params_, DEFAULT_PRIORITY, SocketTag(),
-                        ClientSocketPool::RespectLimits::ENABLED,
-                        callback.callback(), pool_.get(), NetLogWithSource()));
+    EXPECT_EQ(ERR_IO_PENDING,
+              handles[i].Init("b", params_, DEFAULT_PRIORITY, SocketTag(),
+                              ClientSocketPool::RespectLimits::ENABLED,
+                              callback.callback(),
+                              ClientSocketPool::ProxyAuthCallback(),
+                              pool_.get(), NetLogWithSource()));
   }
 
   // One will be stalled, cancel all the handles now.
@@ -1216,8 +1224,9 @@
       EXPECT_EQ(OK, handles[i].Init(base::NumberToString(i), params_,
                                     DEFAULT_PRIORITY, SocketTag(),
                                     ClientSocketPool::RespectLimits::ENABLED,
-                                    callbacks[i].callback(), pool_.get(),
-                                    NetLogWithSource()));
+                                    callbacks[i].callback(),
+                                    ClientSocketPool::ProxyAuthCallback(),
+                                    pool_.get(), NetLogWithSource()));
     }
 
     // Force a stalled group.
@@ -1226,8 +1235,9 @@
     EXPECT_EQ(ERR_IO_PENDING,
               stalled_handle.Init("foo", params_, DEFAULT_PRIORITY, SocketTag(),
                                   ClientSocketPool::RespectLimits::ENABLED,
-                                  callback.callback(), pool_.get(),
-                                  NetLogWithSource()));
+                                  callback.callback(),
+                                  ClientSocketPool::ProxyAuthCallback(),
+                                  pool_.get(), NetLogWithSource()));
 
     // Cancel the stalled request.
     stalled_handle.Reset();
@@ -1254,7 +1264,8 @@
                 handles[i].Init(
                     base::NumberToString(i), params_, DEFAULT_PRIORITY,
                     SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
-                    callback.callback(), pool_.get(), NetLogWithSource()));
+                    callback.callback(), ClientSocketPool::ProxyAuthCallback(),
+                    pool_.get(), NetLogWithSource()));
     }
 
     // Force a stalled group.
@@ -1264,8 +1275,9 @@
     EXPECT_EQ(ERR_IO_PENDING,
               stalled_handle.Init("foo", params_, DEFAULT_PRIORITY, SocketTag(),
                                   ClientSocketPool::RespectLimits::ENABLED,
-                                  callback.callback(), pool_.get(),
-                                  NetLogWithSource()));
+                                  callback.callback(),
+                                  ClientSocketPool::ProxyAuthCallback(),
+                                  pool_.get(), NetLogWithSource()));
 
     // Since it is stalled, it should have no connect jobs.
     EXPECT_EQ(0u, pool_->NumConnectJobsInGroup("foo"));
@@ -1310,8 +1322,9 @@
       EXPECT_EQ(OK, handles[i].Init(base::StringPrintf("Take 2: %d", i),
                                     params_, DEFAULT_PRIORITY, SocketTag(),
                                     ClientSocketPool::RespectLimits::ENABLED,
-                                    callback.callback(), pool_.get(),
-                                    NetLogWithSource()));
+                                    callback.callback(),
+                                    ClientSocketPool::ProxyAuthCallback(),
+                                    pool_.get(), NetLogWithSource()));
     }
 
     EXPECT_EQ(kDefaultMaxSockets, client_socket_factory_.allocation_count());
@@ -1322,8 +1335,9 @@
     EXPECT_EQ(ERR_IO_PENDING,
               stalled_handle.Init("foo", params_, DEFAULT_PRIORITY, SocketTag(),
                                   ClientSocketPool::RespectLimits::ENABLED,
-                                  callback.callback(), pool_.get(),
-                                  NetLogWithSource()));
+                                  callback.callback(),
+                                  ClientSocketPool::ProxyAuthCallback(),
+                                  pool_.get(), NetLogWithSource()));
     EXPECT_TRUE(pool_->IsStalled());
 
     // Dropping out of scope will close all handles and return them to idle.
@@ -1347,9 +1361,11 @@
     ClientSocketHandle handle;
     TestCompletionCallback callback;
     EXPECT_EQ(
-        OK, handle.Init(base::NumberToString(i), params_, DEFAULT_PRIORITY,
-                        SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
-                        callback.callback(), pool_.get(), NetLogWithSource()));
+        OK,
+        handle.Init(base::NumberToString(i), params_, DEFAULT_PRIORITY,
+                    SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
+                    callback.callback(), ClientSocketPool::ProxyAuthCallback(),
+                    pool_.get(), NetLogWithSource()));
   }
 
   // Flush all the DoReleaseSocket tasks.
@@ -1364,10 +1380,11 @@
   // "0" is special here, since it should be the first entry in the sorted map,
   // which is the one which we would close an idle socket for.  We shouldn't
   // close an idle socket though, since we should reuse the idle socket.
-  EXPECT_EQ(OK,
-            handle.Init("0", params_, DEFAULT_PRIORITY, SocketTag(),
-                        ClientSocketPool::RespectLimits::ENABLED,
-                        callback.callback(), pool_.get(), NetLogWithSource()));
+  EXPECT_EQ(OK, handle.Init("0", params_, DEFAULT_PRIORITY, SocketTag(),
+                            ClientSocketPool::RespectLimits::ENABLED,
+                            callback.callback(),
+                            ClientSocketPool::ProxyAuthCallback(), pool_.get(),
+                            NetLogWithSource()));
 
   EXPECT_EQ(kDefaultMaxSockets, client_socket_factory_.allocation_count());
   EXPECT_EQ(kDefaultMaxSockets - 1, pool_->IdleSocketCount());
@@ -1435,10 +1452,12 @@
   connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
   ClientSocketHandle handle;
   TestCompletionCallback callback;
-  EXPECT_EQ(ERR_IO_PENDING,
-            handle.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
-                        ClientSocketPool::RespectLimits::ENABLED,
-                        callback.callback(), pool_.get(), NetLogWithSource()));
+  EXPECT_EQ(
+      ERR_IO_PENDING,
+      handle.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
+                  ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
+                  ClientSocketPool::ProxyAuthCallback(), pool_.get(),
+                  NetLogWithSource()));
   handle.Reset();
 }
 
@@ -1449,18 +1468,22 @@
   ClientSocketHandle handle;
   TestCompletionCallback callback;
 
-  EXPECT_EQ(ERR_IO_PENDING,
-            handle.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
-                        ClientSocketPool::RespectLimits::ENABLED,
-                        callback.callback(), pool_.get(), NetLogWithSource()));
+  EXPECT_EQ(
+      ERR_IO_PENDING,
+      handle.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
+                  ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
+                  ClientSocketPool::ProxyAuthCallback(), pool_.get(),
+                  NetLogWithSource()));
 
   handle.Reset();
 
   TestCompletionCallback callback2;
-  EXPECT_EQ(ERR_IO_PENDING,
-            handle.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
-                        ClientSocketPool::RespectLimits::ENABLED,
-                        callback2.callback(), pool_.get(), NetLogWithSource()));
+  EXPECT_EQ(
+      ERR_IO_PENDING,
+      handle.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
+                  ClientSocketPool::RespectLimits::ENABLED,
+                  callback2.callback(), ClientSocketPool::ProxyAuthCallback(),
+                  pool_.get(), NetLogWithSource()));
 
   EXPECT_THAT(callback2.WaitForResult(), IsOk());
   EXPECT_FALSE(callback.have_result());
@@ -1526,9 +1549,10 @@
 
   scoped_refptr<TestSocketParams> params(new TestSocketParams());
   TestCompletionCallback callback;
-  int rv = handle->Init("a", params, LOWEST, SocketTag(),
-                        ClientSocketPool::RespectLimits::ENABLED,
-                        nested_callback->callback(), pool, NetLogWithSource());
+  int rv = handle->Init(
+      "a", params, LOWEST, SocketTag(),
+      ClientSocketPool::RespectLimits::ENABLED, nested_callback->callback(),
+      ClientSocketPool::ProxyAuthCallback(), pool, NetLogWithSource());
   if (rv != ERR_IO_PENDING) {
     DCHECK_EQ(TestConnectJob::kMockJob, next_job_type);
     nested_callback->callback().Run(rv);
@@ -1549,10 +1573,10 @@
   int rv = handle.Init(
       "a", params_, DEFAULT_PRIORITY, SocketTag(),
       ClientSocketPool::RespectLimits::ENABLED,
-      base::Bind(&RequestSocketOnComplete, &handle, pool_.get(),
-                 connect_job_factory_, TestConnectJob::kMockPendingJob,
-                 &second_result_callback),
-      pool_.get(), NetLogWithSource());
+      base::BindOnce(&RequestSocketOnComplete, &handle, pool_.get(),
+                     connect_job_factory_, TestConnectJob::kMockPendingJob,
+                     &second_result_callback),
+      ClientSocketPool::ProxyAuthCallback(), pool_.get(), NetLogWithSource());
   ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
 
   EXPECT_THAT(second_result_callback.WaitForResult(), IsOk());
@@ -1570,10 +1594,10 @@
   int rv = handle.Init(
       "a", params_, DEFAULT_PRIORITY, SocketTag(),
       ClientSocketPool::RespectLimits::ENABLED,
-      base::Bind(&RequestSocketOnComplete, &handle, pool_.get(),
-                 connect_job_factory_, TestConnectJob::kMockPendingJob,
-                 &second_result_callback),
-      pool_.get(), NetLogWithSource());
+      base::BindOnce(&RequestSocketOnComplete, &handle, pool_.get(),
+                     connect_job_factory_, TestConnectJob::kMockPendingJob,
+                     &second_result_callback),
+      ClientSocketPool::ProxyAuthCallback(), pool_.get(), NetLogWithSource());
   ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
 
   EXPECT_THAT(second_result_callback.WaitForResult(), IsOk());
@@ -1658,9 +1682,10 @@
 
   ClientSocketHandle handle;
   TestCompletionCallback callback;
-  int rv = handle.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
-                       ClientSocketPool::RespectLimits::ENABLED,
-                       callback.callback(), pool_.get(), NetLogWithSource());
+  int rv = handle.Init(
+      "a", params_, DEFAULT_PRIORITY, SocketTag(),
+      ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
+      ClientSocketPool::ProxyAuthCallback(), pool_.get(), NetLogWithSource());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
 
   // Cancel the active request.
@@ -1668,7 +1693,8 @@
 
   rv = handle.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
                    ClientSocketPool::RespectLimits::ENABLED,
-                   callback.callback(), pool_.get(), NetLogWithSource());
+                   callback.callback(), ClientSocketPool::ProxyAuthCallback(),
+                   pool_.get(), NetLogWithSource());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
   EXPECT_THAT(callback.WaitForResult(), IsOk());
 
@@ -1682,9 +1708,10 @@
   ClientSocketHandle handle;
   TestCompletionCallback callback;
   BoundTestNetLog log;
-  int rv = handle.Init("a", params_, LOWEST, SocketTag(),
-                       ClientSocketPool::RespectLimits::ENABLED,
-                       callback.callback(), pool_.get(), log.bound());
+  int rv = handle.Init(
+      "a", params_, LOWEST, SocketTag(),
+      ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
+      ClientSocketPool::ProxyAuthCallback(), pool_.get(), log.bound());
   EXPECT_THAT(rv, IsOk());
   handle.Reset();
   EXPECT_EQ(1, pool_->IdleSocketCount());
@@ -1696,18 +1723,21 @@
   TestCompletionCallback callback;
   BoundTestNetLog log;
   ClientSocketHandle handle1;
-  int rv = handle1.Init("a", params_, LOWEST, SocketTag(),
-                        ClientSocketPool::RespectLimits::ENABLED,
-                        callback.callback(), pool_.get(), log.bound());
+  int rv = handle1.Init(
+      "a", params_, LOWEST, SocketTag(),
+      ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
+      ClientSocketPool::ProxyAuthCallback(), pool_.get(), log.bound());
   EXPECT_THAT(rv, IsOk());
   ClientSocketHandle handle2;
   rv = handle2.Init("a", params_, LOWEST, SocketTag(),
                     ClientSocketPool::RespectLimits::ENABLED,
-                    callback.callback(), pool_.get(), log.bound());
+                    callback.callback(), ClientSocketPool::ProxyAuthCallback(),
+                    pool_.get(), log.bound());
   ClientSocketHandle handle3;
   rv = handle3.Init("b", params_, LOWEST, SocketTag(),
                     ClientSocketPool::RespectLimits::ENABLED,
-                    callback.callback(), pool_.get(), log.bound());
+                    callback.callback(), ClientSocketPool::ProxyAuthCallback(),
+                    pool_.get(), log.bound());
   EXPECT_THAT(rv, IsOk());
   handle1.Reset();
   handle2.Reset();
@@ -1722,9 +1752,10 @@
   ClientSocketHandle handle;
   TestCompletionCallback callback;
   BoundTestNetLog log;
-  int rv = handle.Init("a", params_, LOWEST, SocketTag(),
-                       ClientSocketPool::RespectLimits::ENABLED,
-                       callback.callback(), pool_.get(), log.bound());
+  int rv = handle.Init(
+      "a", params_, LOWEST, SocketTag(),
+      ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
+      ClientSocketPool::ProxyAuthCallback(), pool_.get(), log.bound());
   EXPECT_THAT(rv, IsOk());
   StreamSocket* socket = handle.socket();
   handle.Reset();
@@ -1735,7 +1766,8 @@
   ClientSocketHandle handle2;
   rv = handle2.Init("a", params_, LOWEST, SocketTag(),
                     ClientSocketPool::RespectLimits::ENABLED,
-                    callback.callback(), pool_.get(), log.bound());
+                    callback.callback(), ClientSocketPool::ProxyAuthCallback(),
+                    pool_.get(), log.bound());
   EXPECT_THAT(rv, IsOk());
   EXPECT_FALSE(handle2.is_reused());
 }
@@ -1784,9 +1816,10 @@
   ClientSocketHandle handle;
   TestCompletionCallback callback;
   BoundTestNetLog log;
-  int rv = handle.Init("a", params_, LOWEST, SocketTag(),
-                       ClientSocketPool::RespectLimits::ENABLED,
-                       callback.callback(), pool_.get(), log.bound());
+  int rv = handle.Init(
+      "a", params_, LOWEST, SocketTag(),
+      ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
+      ClientSocketPool::ProxyAuthCallback(), pool_.get(), log.bound());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
   EXPECT_EQ(LOAD_STATE_CONNECTING, pool_->GetLoadState("a", &handle));
   TestLoadTimingInfoNotConnected(handle);
@@ -1826,10 +1859,12 @@
   HttpResponseInfo info;
   info.headers = new HttpResponseHeaders(std::string());
   handle.set_ssl_error_response_info(info);
-  EXPECT_EQ(ERR_IO_PENDING,
-            handle.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
-                        ClientSocketPool::RespectLimits::ENABLED,
-                        callback.callback(), pool_.get(), log.bound()));
+  EXPECT_EQ(
+      ERR_IO_PENDING,
+      handle.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
+                  ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
+                  ClientSocketPool::ProxyAuthCallback(), pool_.get(),
+                  log.bound()));
   EXPECT_EQ(LOAD_STATE_CONNECTING, pool_->GetLoadState("a", &handle));
   EXPECT_THAT(callback.WaitForResult(), IsError(ERR_CONNECTION_FAILED));
   EXPECT_FALSE(handle.is_ssl_error());
@@ -1873,16 +1908,19 @@
   ClientSocketHandle handle2;
   TestCompletionCallback callback2;
 
-  EXPECT_EQ(ERR_IO_PENDING,
-            handle.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
-                        ClientSocketPool::RespectLimits::ENABLED,
-                        callback.callback(), pool_.get(), NetLogWithSource()));
+  EXPECT_EQ(
+      ERR_IO_PENDING,
+      handle.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
+                  ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
+                  ClientSocketPool::ProxyAuthCallback(), pool_.get(),
+                  NetLogWithSource()));
   BoundTestNetLog log2;
   EXPECT_EQ(
       ERR_IO_PENDING,
       handle2.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
                    ClientSocketPool::RespectLimits::ENABLED,
-                   callback2.callback(), pool_.get(), NetLogWithSource()));
+                   callback2.callback(), ClientSocketPool::ProxyAuthCallback(),
+                   pool_.get(), NetLogWithSource()));
 
   handle.Reset();
 
@@ -1933,10 +1971,10 @@
   std::vector<TestSocketRequest*> request_order;
   size_t completion_count;  // unused
   TestSocketRequest req1(&request_order, &completion_count);
-  int rv =
-      req1.handle()->Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
-                          ClientSocketPool::RespectLimits::ENABLED,
-                          req1.callback(), pool_.get(), NetLogWithSource());
+  int rv = req1.handle()->Init(
+      "a", params_, DEFAULT_PRIORITY, SocketTag(),
+      ClientSocketPool::RespectLimits::ENABLED, req1.callback(),
+      ClientSocketPool::ProxyAuthCallback(), pool_.get(), NetLogWithSource());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
   EXPECT_THAT(req1.WaitForResult(), IsOk());
 
@@ -1945,14 +1983,16 @@
   connect_job_factory_->set_job_type(TestConnectJob::kMockWaitingJob);
 
   TestSocketRequest req2(&request_order, &completion_count);
-  rv = req2.handle()->Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
-                           ClientSocketPool::RespectLimits::ENABLED,
-                           req2.callback(), pool_.get(), NetLogWithSource());
+  rv = req2.handle()->Init(
+      "a", params_, DEFAULT_PRIORITY, SocketTag(),
+      ClientSocketPool::RespectLimits::ENABLED, req2.callback(),
+      ClientSocketPool::ProxyAuthCallback(), pool_.get(), NetLogWithSource());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
   TestSocketRequest req3(&request_order, &completion_count);
-  rv = req3.handle()->Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
-                           ClientSocketPool::RespectLimits::ENABLED,
-                           req3.callback(), pool_.get(), NetLogWithSource());
+  rv = req3.handle()->Init(
+      "a", params_, DEFAULT_PRIORITY, SocketTag(),
+      ClientSocketPool::RespectLimits::ENABLED, req3.callback(),
+      ClientSocketPool::ProxyAuthCallback(), pool_.get(), NetLogWithSource());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
 
   // Both Requests 2 and 3 are pending.  We release socket 1 which should
@@ -1986,25 +2026,27 @@
   std::vector<TestSocketRequest*> request_order;
   size_t completion_count;  // unused
   TestSocketRequest req1(&request_order, &completion_count);
-  int rv =
-      req1.handle()->Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
-                          ClientSocketPool::RespectLimits::ENABLED,
-                          req1.callback(), pool_.get(), NetLogWithSource());
+  int rv = req1.handle()->Init(
+      "a", params_, DEFAULT_PRIORITY, SocketTag(),
+      ClientSocketPool::RespectLimits::ENABLED, req1.callback(),
+      ClientSocketPool::ProxyAuthCallback(), pool_.get(), NetLogWithSource());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
 
   TestSocketRequest req2(&request_order, &completion_count);
-  rv = req2.handle()->Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
-                           ClientSocketPool::RespectLimits::ENABLED,
-                           req2.callback(), pool_.get(), NetLogWithSource());
+  rv = req2.handle()->Init(
+      "a", params_, DEFAULT_PRIORITY, SocketTag(),
+      ClientSocketPool::RespectLimits::ENABLED, req2.callback(),
+      ClientSocketPool::ProxyAuthCallback(), pool_.get(), NetLogWithSource());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
 
   // The pending job is sync.
   connect_job_factory_->set_job_type(TestConnectJob::kMockJob);
 
   TestSocketRequest req3(&request_order, &completion_count);
-  rv = req3.handle()->Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
-                           ClientSocketPool::RespectLimits::ENABLED,
-                           req3.callback(), pool_.get(), NetLogWithSource());
+  rv = req3.handle()->Init(
+      "a", params_, DEFAULT_PRIORITY, SocketTag(),
+      ClientSocketPool::RespectLimits::ENABLED, req3.callback(),
+      ClientSocketPool::ProxyAuthCallback(), pool_.get(), NetLogWithSource());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
 
   EXPECT_THAT(req1.WaitForResult(), IsError(ERR_CONNECTION_FAILED));
@@ -2024,9 +2066,10 @@
 
   ClientSocketHandle handle;
   TestCompletionCallback callback;
-  int rv = handle.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
-                       ClientSocketPool::RespectLimits::ENABLED,
-                       callback.callback(), pool_.get(), NetLogWithSource());
+  int rv = handle.Init(
+      "a", params_, DEFAULT_PRIORITY, SocketTag(),
+      ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
+      ClientSocketPool::ProxyAuthCallback(), pool_.get(), NetLogWithSource());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
   EXPECT_EQ(LOAD_STATE_CONNECTING, handle.GetLoadState());
 
@@ -2045,9 +2088,10 @@
 
   ClientSocketHandle handle;
   TestCompletionCallback callback;
-  int rv = handle.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
-                       ClientSocketPool::RespectLimits::ENABLED,
-                       callback.callback(), pool_.get(), NetLogWithSource());
+  int rv = handle.Init(
+      "a", params_, DEFAULT_PRIORITY, SocketTag(),
+      ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
+      ClientSocketPool::ProxyAuthCallback(), pool_.get(), NetLogWithSource());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
   client_socket_factory_.SetJobLoadState(0, LOAD_STATE_RESOLVING_HOST);
 
@@ -2055,7 +2099,8 @@
   TestCompletionCallback callback2;
   rv = handle2.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
                     ClientSocketPool::RespectLimits::ENABLED,
-                    callback2.callback(), pool_.get(), NetLogWithSource());
+                    callback2.callback(), ClientSocketPool::ProxyAuthCallback(),
+                    pool_.get(), NetLogWithSource());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
   client_socket_factory_.SetJobLoadState(1, LOAD_STATE_RESOLVING_HOST);
 
@@ -2078,16 +2123,18 @@
 
   ClientSocketHandle handle;
   TestCompletionCallback callback;
-  int rv = handle.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
-                       ClientSocketPool::RespectLimits::ENABLED,
-                       callback.callback(), pool_.get(), NetLogWithSource());
+  int rv = handle.Init(
+      "a", params_, DEFAULT_PRIORITY, SocketTag(),
+      ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
+      ClientSocketPool::ProxyAuthCallback(), pool_.get(), NetLogWithSource());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
 
   ClientSocketHandle handle2;
   TestCompletionCallback callback2;
   rv = handle2.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
                     ClientSocketPool::RespectLimits::ENABLED,
-                    callback2.callback(), pool_.get(), NetLogWithSource());
+                    callback2.callback(), ClientSocketPool::ProxyAuthCallback(),
+                    pool_.get(), NetLogWithSource());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
   client_socket_factory_.SetJobLoadState(1, LOAD_STATE_RESOLVING_HOST);
 
@@ -2108,9 +2155,10 @@
 
   ClientSocketHandle handle;
   TestCompletionCallback callback;
-  int rv = handle.Init("a", params_, MEDIUM, SocketTag(),
-                       ClientSocketPool::RespectLimits::ENABLED,
-                       callback.callback(), pool_.get(), NetLogWithSource());
+  int rv = handle.Init(
+      "a", params_, MEDIUM, SocketTag(),
+      ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
+      ClientSocketPool::ProxyAuthCallback(), pool_.get(), NetLogWithSource());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
   EXPECT_EQ(LOAD_STATE_CONNECTING, handle.GetLoadState());
 
@@ -2120,7 +2168,8 @@
   TestCompletionCallback callback2;
   rv = handle2.Init("a", params_, HIGHEST, SocketTag(),
                     ClientSocketPool::RespectLimits::ENABLED,
-                    callback2.callback(), pool_.get(), NetLogWithSource());
+                    callback2.callback(), ClientSocketPool::ProxyAuthCallback(),
+                    pool_.get(), NetLogWithSource());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
   EXPECT_EQ(LOAD_STATE_WAITING_FOR_AVAILABLE_SOCKET, handle.GetLoadState());
   EXPECT_EQ(LOAD_STATE_CONNECTING, handle2.GetLoadState());
@@ -2150,9 +2199,10 @@
 
   ClientSocketHandle handle;
   TestCompletionCallback callback;
-  int rv = handle.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
-                       ClientSocketPool::RespectLimits::ENABLED,
-                       callback.callback(), pool_.get(), NetLogWithSource());
+  int rv = handle.Init(
+      "a", params_, DEFAULT_PRIORITY, SocketTag(),
+      ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
+      ClientSocketPool::ProxyAuthCallback(), pool_.get(), NetLogWithSource());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
 
   // Request for socket from another pool.
@@ -2160,7 +2210,8 @@
   TestCompletionCallback callback2;
   rv = handle2.Init("b", params_, DEFAULT_PRIORITY, SocketTag(),
                     ClientSocketPool::RespectLimits::ENABLED,
-                    callback2.callback(), pool_.get(), NetLogWithSource());
+                    callback2.callback(), ClientSocketPool::ProxyAuthCallback(),
+                    pool_.get(), NetLogWithSource());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
 
   // Request another socket from the first pool.  Request should stall at the
@@ -2169,7 +2220,8 @@
   TestCompletionCallback callback3;
   rv = handle3.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
                     ClientSocketPool::RespectLimits::ENABLED,
-                    callback2.callback(), pool_.get(), NetLogWithSource());
+                    callback2.callback(), ClientSocketPool::ProxyAuthCallback(),
+                    pool_.get(), NetLogWithSource());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
 
   // The third handle should remain stalled as the other sockets in its group
@@ -2199,10 +2251,12 @@
 
   ClientSocketHandle handle;
   TestCompletionCallback callback;
-  EXPECT_EQ(ERR_PROXY_AUTH_REQUESTED,
-            handle.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
-                        ClientSocketPool::RespectLimits::ENABLED,
-                        callback.callback(), pool_.get(), NetLogWithSource()));
+  EXPECT_EQ(
+      ERR_PROXY_AUTH_REQUESTED,
+      handle.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
+                  ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
+                  ClientSocketPool::ProxyAuthCallback(), pool_.get(),
+                  NetLogWithSource()));
   EXPECT_TRUE(handle.is_initialized());
   EXPECT_TRUE(handle.socket());
 }
@@ -2214,10 +2268,12 @@
       TestConnectJob::kMockPendingRecoverableJob);
   ClientSocketHandle handle;
   TestCompletionCallback callback;
-  EXPECT_EQ(ERR_IO_PENDING,
-            handle.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
-                        ClientSocketPool::RespectLimits::ENABLED,
-                        callback.callback(), pool_.get(), NetLogWithSource()));
+  EXPECT_EQ(
+      ERR_IO_PENDING,
+      handle.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
+                  ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
+                  ClientSocketPool::ProxyAuthCallback(), pool_.get(),
+                  NetLogWithSource()));
   EXPECT_EQ(LOAD_STATE_CONNECTING, pool_->GetLoadState("a", &handle));
   EXPECT_THAT(callback.WaitForResult(), IsError(ERR_PROXY_AUTH_REQUESTED));
   EXPECT_TRUE(handle.is_initialized());
@@ -2231,10 +2287,12 @@
 
   ClientSocketHandle handle;
   TestCompletionCallback callback;
-  EXPECT_EQ(ERR_CONNECTION_FAILED,
-            handle.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
-                        ClientSocketPool::RespectLimits::ENABLED,
-                        callback.callback(), pool_.get(), NetLogWithSource()));
+  EXPECT_EQ(
+      ERR_CONNECTION_FAILED,
+      handle.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
+                  ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
+                  ClientSocketPool::ProxyAuthCallback(), pool_.get(),
+                  NetLogWithSource()));
   EXPECT_FALSE(handle.is_initialized());
   EXPECT_FALSE(handle.socket());
   EXPECT_TRUE(handle.is_ssl_error());
@@ -2248,10 +2306,12 @@
       TestConnectJob::kMockPendingAdditionalErrorStateJob);
   ClientSocketHandle handle;
   TestCompletionCallback callback;
-  EXPECT_EQ(ERR_IO_PENDING,
-            handle.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
-                        ClientSocketPool::RespectLimits::ENABLED,
-                        callback.callback(), pool_.get(), NetLogWithSource()));
+  EXPECT_EQ(
+      ERR_IO_PENDING,
+      handle.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
+                  ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
+                  ClientSocketPool::ProxyAuthCallback(), pool_.get(),
+                  NetLogWithSource()));
   EXPECT_EQ(LOAD_STATE_CONNECTING, pool_->GetLoadState("a", &handle));
   EXPECT_THAT(callback.WaitForResult(), IsError(ERR_CONNECTION_FAILED));
   EXPECT_FALSE(handle.is_initialized());
@@ -2271,9 +2331,10 @@
 
   ClientSocketHandle handle;
   TestCompletionCallback callback;
-  int rv = handle.Init("a", params_, LOWEST, SocketTag(),
-                       ClientSocketPool::RespectLimits::ENABLED,
-                       callback.callback(), pool_.get(), NetLogWithSource());
+  int rv = handle.Init(
+      "a", params_, LOWEST, SocketTag(),
+      ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
+      ClientSocketPool::ProxyAuthCallback(), pool_.get(), NetLogWithSource());
   ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
   EXPECT_EQ(LOAD_STATE_CONNECTING, pool_->GetLoadState("a", &handle));
   ASSERT_THAT(callback.WaitForResult(), IsOk());
@@ -2290,9 +2351,10 @@
   // Request a new socket. This should reuse the old socket and complete
   // synchronously.
   BoundTestNetLog log;
-  rv = handle.Init("a", params_, LOWEST, SocketTag(),
-                   ClientSocketPool::RespectLimits::ENABLED,
-                   CompletionOnceCallback(), pool_.get(), log.bound());
+  rv = handle.Init(
+      "a", params_, LOWEST, SocketTag(),
+      ClientSocketPool::RespectLimits::ENABLED, CompletionOnceCallback(),
+      ClientSocketPool::ProxyAuthCallback(), pool_.get(), log.bound());
   ASSERT_THAT(rv, IsOk());
   EXPECT_TRUE(handle.is_reused());
   TestLoadTimingInfoConnectedReused(handle);
@@ -2320,9 +2382,10 @@
 
   ClientSocketHandle handle;
   TestCompletionCallback callback;
-  int rv = handle.Init("a", params_, LOWEST, SocketTag(),
-                       ClientSocketPool::RespectLimits::ENABLED,
-                       callback.callback(), pool_.get(), NetLogWithSource());
+  int rv = handle.Init(
+      "a", params_, LOWEST, SocketTag(),
+      ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
+      ClientSocketPool::ProxyAuthCallback(), pool_.get(), NetLogWithSource());
   ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
   EXPECT_EQ(LOAD_STATE_CONNECTING, pool_->GetLoadState("a", &handle));
 
@@ -2330,7 +2393,8 @@
   TestCompletionCallback callback2;
   rv = handle2.Init("a", params_, LOWEST, SocketTag(),
                     ClientSocketPool::RespectLimits::ENABLED,
-                    callback2.callback(), pool_.get(), NetLogWithSource());
+                    callback2.callback(), ClientSocketPool::ProxyAuthCallback(),
+                    pool_.get(), NetLogWithSource());
   ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
   EXPECT_EQ(LOAD_STATE_CONNECTING, pool_->GetLoadState("a", &handle2));
 
@@ -2361,7 +2425,8 @@
   TestCompletionCallback callback3;
   rv = handle.Init("a", params_, LOWEST, SocketTag(),
                    ClientSocketPool::RespectLimits::ENABLED,
-                   callback3.callback(), pool_.get(), log.bound());
+                   callback3.callback(), ClientSocketPool::ProxyAuthCallback(),
+                   pool_.get(), log.bound());
   ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
   ASSERT_THAT(callback3.WaitForResult(), IsOk());
   EXPECT_FALSE(handle.is_reused());
@@ -2391,30 +2456,34 @@
 
   ClientSocketHandle handle;
   TestCompletionCallback callback;
-  int rv = handle.Init("a", params_, LOWEST, SocketTag(),
-                       ClientSocketPool::RespectLimits::ENABLED,
-                       callback.callback(), pool_.get(), NetLogWithSource());
+  int rv = handle.Init(
+      "a", params_, LOWEST, SocketTag(),
+      ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
+      ClientSocketPool::ProxyAuthCallback(), pool_.get(), NetLogWithSource());
   EXPECT_THAT(rv, IsOk());
 
   ClientSocketHandle handle2;
   TestCompletionCallback callback2;
   rv = handle2.Init("a", params_, LOWEST, SocketTag(),
                     ClientSocketPool::RespectLimits::ENABLED,
-                    callback2.callback(), pool_.get(), NetLogWithSource());
+                    callback2.callback(), ClientSocketPool::ProxyAuthCallback(),
+                    pool_.get(), NetLogWithSource());
   EXPECT_THAT(rv, IsOk());
 
   ClientSocketHandle handle3;
   TestCompletionCallback callback3;
   rv = handle3.Init("a", params_, LOWEST, SocketTag(),
                     ClientSocketPool::RespectLimits::ENABLED,
-                    callback3.callback(), pool_.get(), NetLogWithSource());
+                    callback3.callback(), ClientSocketPool::ProxyAuthCallback(),
+                    pool_.get(), NetLogWithSource());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
 
   ClientSocketHandle handle4;
   TestCompletionCallback callback4;
   rv = handle4.Init("a", params_, LOWEST, SocketTag(),
                     ClientSocketPool::RespectLimits::ENABLED,
-                    callback4.callback(), pool_.get(), NetLogWithSource());
+                    callback4.callback(), ClientSocketPool::ProxyAuthCallback(),
+                    pool_.get(), NetLogWithSource());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
 
   // Release two disconnected sockets.
@@ -2451,12 +2520,14 @@
   for (int i = 0; i < 2; ++i) {
     EXPECT_EQ(OK, handle_a[i].Init("a", params_, LOWEST, SocketTag(),
                                    ClientSocketPool::RespectLimits::ENABLED,
-                                   callback_a[i].callback(), pool_.get(),
-                                   NetLogWithSource()));
+                                   callback_a[i].callback(),
+                                   ClientSocketPool::ProxyAuthCallback(),
+                                   pool_.get(), NetLogWithSource()));
     EXPECT_EQ(OK, handle_b[i].Init("b", params_, LOWEST, SocketTag(),
                                    ClientSocketPool::RespectLimits::ENABLED,
-                                   callback_b[i].callback(), pool_.get(),
-                                   NetLogWithSource()));
+                                   callback_b[i].callback(),
+                                   ClientSocketPool::ProxyAuthCallback(),
+                                   pool_.get(), NetLogWithSource()));
   }
 
   // Make 4 pending requests, 2 per group.
@@ -2465,13 +2536,15 @@
     EXPECT_EQ(ERR_IO_PENDING,
               handle_a[i].Init("a", params_, LOWEST, SocketTag(),
                                ClientSocketPool::RespectLimits::ENABLED,
-                               callback_a[i].callback(), pool_.get(),
-                               NetLogWithSource()));
+                               callback_a[i].callback(),
+                               ClientSocketPool::ProxyAuthCallback(),
+                               pool_.get(), NetLogWithSource()));
     EXPECT_EQ(ERR_IO_PENDING,
               handle_b[i].Init("b", params_, LOWEST, SocketTag(),
                                ClientSocketPool::RespectLimits::ENABLED,
-                               callback_b[i].callback(), pool_.get(),
-                               NetLogWithSource()));
+                               callback_b[i].callback(),
+                               ClientSocketPool::ProxyAuthCallback(),
+                               pool_.get(), NetLogWithSource()));
   }
 
   // Release b's socket first.  The order is important, because in
@@ -2555,11 +2628,12 @@
       handle_.Reset();
 
     scoped_refptr<TestSocketParams> con_params(new TestSocketParams());
-    EXPECT_EQ(
-        expected_result_,
-        handle2_.Init("a", con_params, DEFAULT_PRIORITY, SocketTag(),
-                      ClientSocketPool::RespectLimits::ENABLED,
-                      CompletionOnceCallback(), pool_, NetLogWithSource()));
+    EXPECT_EQ(expected_result_,
+              handle2_.Init("a", con_params, DEFAULT_PRIORITY, SocketTag(),
+                            ClientSocketPool::RespectLimits::ENABLED,
+                            CompletionOnceCallback(),
+                            ClientSocketPool::ProxyAuthCallback(), pool_,
+                            NetLogWithSource()));
   }
 
   TestClientSocketPool* const pool_;
@@ -2587,7 +2661,8 @@
       ERR_IO_PENDING,
       req.handle()->Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
                          ClientSocketPool::RespectLimits::ENABLED,
-                         req.callback(), pool_.get(), NetLogWithSource()));
+                         req.callback(), ClientSocketPool::ProxyAuthCallback(),
+                         pool_.get(), NetLogWithSource()));
   // The next job should complete synchronously
   connect_job_factory_->set_job_type(TestConnectJob::kMockJob);
 
@@ -2612,10 +2687,12 @@
 
   ClientSocketHandle handle;
   TestCompletionCallback callback;
-  EXPECT_EQ(ERR_IO_PENDING,
-            handle.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
-                        ClientSocketPool::RespectLimits::ENABLED,
-                        callback.callback(), pool_.get(), NetLogWithSource()));
+  EXPECT_EQ(
+      ERR_IO_PENDING,
+      handle.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
+                  ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
+                  ClientSocketPool::ProxyAuthCallback(), pool_.get(),
+                  NetLogWithSource()));
 
   pool_->FlushWithError(ERR_NETWORK_CHANGED);
 
@@ -2629,10 +2706,12 @@
 
   ClientSocketHandle handle;
   TestCompletionCallback callback;
-  EXPECT_EQ(ERR_IO_PENDING,
-            handle.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
-                        ClientSocketPool::RespectLimits::ENABLED,
-                        callback.callback(), pool_.get(), NetLogWithSource()));
+  EXPECT_EQ(
+      ERR_IO_PENDING,
+      handle.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
+                  ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
+                  ClientSocketPool::ProxyAuthCallback(), pool_.get(),
+                  NetLogWithSource()));
   EXPECT_THAT(callback.WaitForResult(), IsOk());
   EXPECT_EQ(ClientSocketHandle::UNUSED, handle.reuse_type());
 
@@ -2641,10 +2720,12 @@
   handle.Reset();
   base::RunLoop().RunUntilIdle();
 
-  EXPECT_EQ(ERR_IO_PENDING,
-            handle.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
-                        ClientSocketPool::RespectLimits::ENABLED,
-                        callback.callback(), pool_.get(), NetLogWithSource()));
+  EXPECT_EQ(
+      ERR_IO_PENDING,
+      handle.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
+                  ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
+                  ClientSocketPool::ProxyAuthCallback(), pool_.get(),
+                  NetLogWithSource()));
   EXPECT_THAT(callback.WaitForResult(), IsOk());
   EXPECT_EQ(ClientSocketHandle::UNUSED, handle.reuse_type());
 }
@@ -2670,11 +2751,12 @@
  private:
   void OnComplete(int result) {
     SetResult(result);
-    EXPECT_EQ(
-        ERR_IO_PENDING,
-        handle_.Init(group_name_, params_, DEFAULT_PRIORITY, SocketTag(),
-                     ClientSocketPool::RespectLimits::ENABLED,
-                     nested_callback_.callback(), pool_, NetLogWithSource()));
+    EXPECT_EQ(ERR_IO_PENDING,
+              handle_.Init(group_name_, params_, DEFAULT_PRIORITY, SocketTag(),
+                           ClientSocketPool::RespectLimits::ENABLED,
+                           nested_callback_.callback(),
+                           ClientSocketPool::ProxyAuthCallback(), pool_,
+                           NetLogWithSource()));
   }
 
   const std::string group_name_;
@@ -2694,10 +2776,12 @@
 
   ClientSocketHandle handle;
   ConnectWithinCallback callback("a", params_, pool_.get());
-  EXPECT_EQ(ERR_IO_PENDING,
-            handle.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
-                        ClientSocketPool::RespectLimits::ENABLED,
-                        callback.callback(), pool_.get(), NetLogWithSource()));
+  EXPECT_EQ(
+      ERR_IO_PENDING,
+      handle.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
+                  ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
+                  ClientSocketPool::ProxyAuthCallback(), pool_.get(),
+                  NetLogWithSource()));
 
   // Second job will be started during the first callback, and will
   // asynchronously complete with OK.
@@ -2714,10 +2798,12 @@
   connect_job_factory_->set_job_type(TestConnectJob::kMockWaitingJob);
   ClientSocketHandle handle;
   TestCompletionCallback callback;
-  EXPECT_EQ(ERR_IO_PENDING,
-            handle.Init("bar", params_, DEFAULT_PRIORITY, SocketTag(),
-                        ClientSocketPool::RespectLimits::ENABLED,
-                        callback.callback(), pool_.get(), NetLogWithSource()));
+  EXPECT_EQ(
+      ERR_IO_PENDING,
+      handle.Init("bar", params_, DEFAULT_PRIORITY, SocketTag(),
+                  ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
+                  ClientSocketPool::ProxyAuthCallback(), pool_.get(),
+                  NetLogWithSource()));
   // The backup timer fires but doesn't start a new ConnectJob while resolving
   // the hostname.
   client_socket_factory_.SetJobLoadState(0, LOAD_STATE_RESOLVING_HOST);
@@ -2742,10 +2828,12 @@
   connect_job_factory_->set_job_type(TestConnectJob::kMockWaitingJob);
   ClientSocketHandle handle;
   TestCompletionCallback callback;
-  EXPECT_EQ(ERR_IO_PENDING,
-            handle.Init("bar", params_, DEFAULT_PRIORITY, SocketTag(),
-                        ClientSocketPool::RespectLimits::ENABLED,
-                        callback.callback(), pool_.get(), NetLogWithSource()));
+  EXPECT_EQ(
+      ERR_IO_PENDING,
+      handle.Init("bar", params_, DEFAULT_PRIORITY, SocketTag(),
+                  ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
+                  ClientSocketPool::ProxyAuthCallback(), pool_.get(),
+                  NetLogWithSource()));
   // The backup timer fires but doesn't start a new ConnectJob while resolving
   // the hostname.
   client_socket_factory_.SetJobLoadState(0, LOAD_STATE_RESOLVING_HOST);
@@ -2772,10 +2860,12 @@
   connect_job_factory_->set_job_type(TestConnectJob::kMockWaitingJob);
   ClientSocketHandle handle;
   TestCompletionCallback callback;
-  EXPECT_EQ(ERR_IO_PENDING,
-            handle.Init("bar", params_, DEFAULT_PRIORITY, SocketTag(),
-                        ClientSocketPool::RespectLimits::ENABLED,
-                        callback.callback(), pool_.get(), NetLogWithSource()));
+  EXPECT_EQ(
+      ERR_IO_PENDING,
+      handle.Init("bar", params_, DEFAULT_PRIORITY, SocketTag(),
+                  ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
+                  ClientSocketPool::ProxyAuthCallback(), pool_.get(),
+                  NetLogWithSource()));
 
   // Start (MaxSockets - 1) connected sockets to reach max sockets.
   connect_job_factory_->set_job_type(TestConnectJob::kMockJob);
@@ -2784,8 +2874,9 @@
     TestCompletionCallback callback;
     EXPECT_EQ(OK, handles[i].Init("bar", params_, DEFAULT_PRIORITY, SocketTag(),
                                   ClientSocketPool::RespectLimits::ENABLED,
-                                  callback.callback(), pool_.get(),
-                                  NetLogWithSource()));
+                                  callback.callback(),
+                                  ClientSocketPool::ProxyAuthCallback(),
+                                  pool_.get(), NetLogWithSource()));
   }
 
   base::RunLoop().RunUntilIdle();
@@ -2809,10 +2900,12 @@
   connect_job_factory_->set_job_type(TestConnectJob::kMockWaitingJob);
   ClientSocketHandle handle;
   TestCompletionCallback callback;
-  EXPECT_EQ(ERR_IO_PENDING,
-            handle.Init("bar", params_, DEFAULT_PRIORITY, SocketTag(),
-                        ClientSocketPool::RespectLimits::ENABLED,
-                        callback.callback(), pool_.get(), NetLogWithSource()));
+  EXPECT_EQ(
+      ERR_IO_PENDING,
+      handle.Init("bar", params_, DEFAULT_PRIORITY, SocketTag(),
+                  ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
+                  ClientSocketPool::ProxyAuthCallback(), pool_.get(),
+                  NetLogWithSource()));
   ASSERT_TRUE(pool_->HasGroup("bar"));
   EXPECT_EQ(1u, pool_->NumConnectJobsInGroup("bar"));
   EXPECT_EQ(0u, pool_->NumNeverAssignedConnectJobsInGroup("bar"));
@@ -2837,10 +2930,12 @@
   connect_job_factory_->set_job_type(TestConnectJob::kMockWaitingJob);
   ClientSocketHandle handle;
   TestCompletionCallback callback;
-  EXPECT_EQ(ERR_IO_PENDING,
-            handle.Init("bar", params_, DEFAULT_PRIORITY, SocketTag(),
-                        ClientSocketPool::RespectLimits::ENABLED,
-                        callback.callback(), pool_.get(), NetLogWithSource()));
+  EXPECT_EQ(
+      ERR_IO_PENDING,
+      handle.Init("bar", params_, DEFAULT_PRIORITY, SocketTag(),
+                  ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
+                  ClientSocketPool::ProxyAuthCallback(), pool_.get(),
+                  NetLogWithSource()));
   connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
   ClientSocketHandle handle2;
   TestCompletionCallback callback2;
@@ -2848,7 +2943,8 @@
       ERR_IO_PENDING,
       handle2.Init("bar", params_, DEFAULT_PRIORITY, SocketTag(),
                    ClientSocketPool::RespectLimits::ENABLED,
-                   callback2.callback(), pool_.get(), NetLogWithSource()));
+                   callback2.callback(), ClientSocketPool::ProxyAuthCallback(),
+                   pool_.get(), NetLogWithSource()));
   ASSERT_TRUE(pool_->HasGroup("bar"));
   EXPECT_EQ(2u, pool_->NumConnectJobsInGroup("bar"));
 
@@ -2871,10 +2967,12 @@
 
   ClientSocketHandle handle1;
   TestCompletionCallback callback;
-  EXPECT_EQ(ERR_IO_PENDING,
-            handle1.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
-                         ClientSocketPool::RespectLimits::ENABLED,
-                         callback.callback(), pool_.get(), NetLogWithSource()));
+  EXPECT_EQ(
+      ERR_IO_PENDING,
+      handle1.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
+                   ClientSocketPool::RespectLimits::ENABLED,
+                   callback.callback(), ClientSocketPool::ProxyAuthCallback(),
+                   pool_.get(), NetLogWithSource()));
   EXPECT_THAT(callback.WaitForResult(), IsOk());
 
   // No idle sockets, no pending jobs.
@@ -2884,10 +2982,12 @@
   // Create a second socket to the same host, but this one will wait.
   connect_job_factory_->set_job_type(TestConnectJob::kMockWaitingJob);
   ClientSocketHandle handle2;
-  EXPECT_EQ(ERR_IO_PENDING,
-            handle2.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
-                         ClientSocketPool::RespectLimits::ENABLED,
-                         callback.callback(), pool_.get(), NetLogWithSource()));
+  EXPECT_EQ(
+      ERR_IO_PENDING,
+      handle2.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
+                   ClientSocketPool::RespectLimits::ENABLED,
+                   callback.callback(), ClientSocketPool::ProxyAuthCallback(),
+                   pool_.get(), NetLogWithSource()));
   // No idle sockets, and one connecting job.
   EXPECT_EQ(0, pool_->IdleSocketCount());
   EXPECT_EQ(1u, pool_->NumConnectJobsInGroup("a"));
@@ -2923,10 +3023,12 @@
 
   ClientSocketHandle handle1;
   TestCompletionCallback callback;
-  EXPECT_EQ(ERR_IO_PENDING,
-            handle1.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
-                         ClientSocketPool::RespectLimits::ENABLED,
-                         callback.callback(), pool_.get(), NetLogWithSource()));
+  EXPECT_EQ(
+      ERR_IO_PENDING,
+      handle1.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
+                   ClientSocketPool::RespectLimits::ENABLED,
+                   callback.callback(), ClientSocketPool::ProxyAuthCallback(),
+                   pool_.get(), NetLogWithSource()));
   EXPECT_THAT(callback.WaitForResult(), IsOk());
 
   // No idle sockets, no pending jobs.
@@ -2936,10 +3038,12 @@
   // Create a second socket to the same host, but this one will wait.
   connect_job_factory_->set_job_type(TestConnectJob::kMockWaitingJob);
   ClientSocketHandle handle2;
-  EXPECT_EQ(ERR_IO_PENDING,
-            handle2.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
-                         ClientSocketPool::RespectLimits::ENABLED,
-                         callback.callback(), pool_.get(), NetLogWithSource()));
+  EXPECT_EQ(
+      ERR_IO_PENDING,
+      handle2.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
+                   ClientSocketPool::RespectLimits::ENABLED,
+                   callback.callback(), ClientSocketPool::ProxyAuthCallback(),
+                   pool_.get(), NetLogWithSource()));
   // No idle sockets, and one connecting job.
   EXPECT_EQ(0, pool_->IdleSocketCount());
   EXPECT_EQ(1u, pool_->NumConnectJobsInGroup("a"));
@@ -2977,10 +3081,12 @@
 
   ClientSocketHandle handle1;
   TestCompletionCallback callback;
-  EXPECT_EQ(ERR_IO_PENDING,
-            handle1.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
-                         ClientSocketPool::RespectLimits::ENABLED,
-                         callback.callback(), pool_.get(), NetLogWithSource()));
+  EXPECT_EQ(
+      ERR_IO_PENDING,
+      handle1.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
+                   ClientSocketPool::RespectLimits::ENABLED,
+                   callback.callback(), ClientSocketPool::ProxyAuthCallback(),
+                   pool_.get(), NetLogWithSource()));
   EXPECT_THAT(callback.WaitForResult(), IsOk());
 
   // No idle sockets, no pending jobs.
@@ -2990,10 +3096,12 @@
   // Create a second socket to the same host, but this one will wait.
   connect_job_factory_->set_job_type(TestConnectJob::kMockWaitingJob);
   ClientSocketHandle handle2;
-  EXPECT_EQ(ERR_IO_PENDING,
-            handle2.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
-                         ClientSocketPool::RespectLimits::ENABLED,
-                         callback.callback(), pool_.get(), NetLogWithSource()));
+  EXPECT_EQ(
+      ERR_IO_PENDING,
+      handle2.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
+                   ClientSocketPool::RespectLimits::ENABLED,
+                   callback.callback(), ClientSocketPool::ProxyAuthCallback(),
+                   pool_.get(), NetLogWithSource()));
   // No idle sockets, and one connecting job.
   EXPECT_EQ(0, pool_->IdleSocketCount());
   EXPECT_EQ(1u, pool_->NumConnectJobsInGroup("a"));
@@ -3038,7 +3146,8 @@
       ERR_IO_PENDING,
       handle1.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
                    ClientSocketPool::RespectLimits::ENABLED,
-                   callback1.callback(), pool_.get(), NetLogWithSource()));
+                   callback1.callback(), ClientSocketPool::ProxyAuthCallback(),
+                   pool_.get(), NetLogWithSource()));
   EXPECT_EQ(1u, pool_->NumConnectJobsInGroup("a"));
 
   // Make the second request synchronously fail.  This should make the Group
@@ -3052,7 +3161,8 @@
       ERR_IO_PENDING,
       handle2.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
                    ClientSocketPool::RespectLimits::ENABLED,
-                   callback2.callback(), pool_.get(), NetLogWithSource()));
+                   callback2.callback(), ClientSocketPool::ProxyAuthCallback(),
+                   pool_.get(), NetLogWithSource()));
 
   EXPECT_EQ(1u, pool_->NumConnectJobsInGroup("a"));
 
@@ -3072,7 +3182,8 @@
       ERR_IO_PENDING,
       handle1.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
                    ClientSocketPool::RespectLimits::ENABLED,
-                   callback1.callback(), pool_.get(), NetLogWithSource()));
+                   callback1.callback(), ClientSocketPool::ProxyAuthCallback(),
+                   pool_.get(), NetLogWithSource()));
 
   ClientSocketHandle handle2;
   TestCompletionCallback callback2;
@@ -3080,14 +3191,16 @@
       ERR_IO_PENDING,
       handle2.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
                    ClientSocketPool::RespectLimits::ENABLED,
-                   callback2.callback(), pool_.get(), NetLogWithSource()));
+                   callback2.callback(), ClientSocketPool::ProxyAuthCallback(),
+                   pool_.get(), NetLogWithSource()));
   ClientSocketHandle handle3;
   TestCompletionCallback callback3;
   EXPECT_EQ(
       ERR_IO_PENDING,
       handle3.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
                    ClientSocketPool::RespectLimits::ENABLED,
-                   callback3.callback(), pool_.get(), NetLogWithSource()));
+                   callback3.callback(), ClientSocketPool::ProxyAuthCallback(),
+                   pool_.get(), NetLogWithSource()));
 
   EXPECT_THAT(callback1.WaitForResult(), IsOk());
   EXPECT_THAT(callback2.WaitForResult(), IsOk());
@@ -3103,18 +3216,21 @@
   handle2.Reset();
   handle3.Reset();
 
-  EXPECT_EQ(
-      OK, handle1.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
-                       ClientSocketPool::RespectLimits::ENABLED,
-                       callback1.callback(), pool_.get(), NetLogWithSource()));
-  EXPECT_EQ(
-      OK, handle2.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
-                       ClientSocketPool::RespectLimits::ENABLED,
-                       callback2.callback(), pool_.get(), NetLogWithSource()));
-  EXPECT_EQ(
-      OK, handle3.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
-                       ClientSocketPool::RespectLimits::ENABLED,
-                       callback3.callback(), pool_.get(), NetLogWithSource()));
+  EXPECT_EQ(OK, handle1.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
+                             ClientSocketPool::RespectLimits::ENABLED,
+                             callback1.callback(),
+                             ClientSocketPool::ProxyAuthCallback(), pool_.get(),
+                             NetLogWithSource()));
+  EXPECT_EQ(OK, handle2.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
+                             ClientSocketPool::RespectLimits::ENABLED,
+                             callback2.callback(),
+                             ClientSocketPool::ProxyAuthCallback(), pool_.get(),
+                             NetLogWithSource()));
+  EXPECT_EQ(OK, handle3.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
+                             ClientSocketPool::RespectLimits::ENABLED,
+                             callback3.callback(),
+                             ClientSocketPool::ProxyAuthCallback(), pool_.get(),
+                             NetLogWithSource()));
 
   EXPECT_TRUE(handle1.socket()->WasEverUsed());
   EXPECT_TRUE(handle2.socket()->WasEverUsed());
@@ -3139,7 +3255,8 @@
       ERR_IO_PENDING,
       handle1.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
                    ClientSocketPool::RespectLimits::ENABLED,
-                   callback1.callback(), pool_.get(), NetLogWithSource()));
+                   callback1.callback(), ClientSocketPool::ProxyAuthCallback(),
+                   pool_.get(), NetLogWithSource()));
 
   ClientSocketHandle handle2;
   TestCompletionCallback callback2;
@@ -3147,7 +3264,8 @@
       ERR_IO_PENDING,
       handle2.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
                    ClientSocketPool::RespectLimits::ENABLED,
-                   callback2.callback(), pool_.get(), NetLogWithSource()));
+                   callback2.callback(), ClientSocketPool::ProxyAuthCallback(),
+                   pool_.get(), NetLogWithSource()));
 
   EXPECT_EQ(2u, pool_->NumConnectJobsInGroup("a"));
   EXPECT_EQ(0u, pool_->NumNeverAssignedConnectJobsInGroup("a"));
@@ -3175,7 +3293,8 @@
       ERR_IO_PENDING,
       handle1.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
                    ClientSocketPool::RespectLimits::ENABLED,
-                   callback1.callback(), pool_.get(), NetLogWithSource()));
+                   callback1.callback(), ClientSocketPool::ProxyAuthCallback(),
+                   pool_.get(), NetLogWithSource()));
 
   ASSERT_TRUE(pool_->HasGroup("a"));
   EXPECT_EQ(1u, pool_->NumConnectJobsInGroup("a"));
@@ -3196,7 +3315,8 @@
       ERR_IO_PENDING,
       handle2.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
                    ClientSocketPool::RespectLimits::ENABLED,
-                   callback2.callback(), pool_.get(), NetLogWithSource()));
+                   callback2.callback(), ClientSocketPool::ProxyAuthCallback(),
+                   pool_.get(), NetLogWithSource()));
 
   EXPECT_EQ(2u, pool_->NumConnectJobsInGroup("a"));
   EXPECT_EQ(0u, pool_->NumNeverAssignedConnectJobsInGroup("a"));
@@ -3225,7 +3345,8 @@
       ERR_IO_PENDING,
       handle1.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
                    ClientSocketPool::RespectLimits::ENABLED,
-                   callback1.callback(), pool_.get(), NetLogWithSource()));
+                   callback1.callback(), ClientSocketPool::ProxyAuthCallback(),
+                   pool_.get(), NetLogWithSource()));
 
   ClientSocketHandle handle2;
   TestCompletionCallback callback2;
@@ -3233,7 +3354,8 @@
       ERR_IO_PENDING,
       handle2.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
                    ClientSocketPool::RespectLimits::ENABLED,
-                   callback2.callback(), pool_.get(), NetLogWithSource()));
+                   callback2.callback(), ClientSocketPool::ProxyAuthCallback(),
+                   pool_.get(), NetLogWithSource()));
 
   ClientSocketHandle handle3;
   TestCompletionCallback callback3;
@@ -3241,7 +3363,8 @@
       ERR_IO_PENDING,
       handle3.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
                    ClientSocketPool::RespectLimits::ENABLED,
-                   callback3.callback(), pool_.get(), NetLogWithSource()));
+                   callback3.callback(), ClientSocketPool::ProxyAuthCallback(),
+                   pool_.get(), NetLogWithSource()));
 
   ASSERT_TRUE(pool_->HasGroup("a"));
   EXPECT_EQ(3u, pool_->NumConnectJobsInGroup("a"));
@@ -3329,7 +3452,8 @@
       ERR_IO_PENDING,
       handle1.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
                    ClientSocketPool::RespectLimits::ENABLED,
-                   callback1.callback(), pool_.get(), NetLogWithSource()));
+                   callback1.callback(), ClientSocketPool::ProxyAuthCallback(),
+                   pool_.get(), NetLogWithSource()));
   ASSERT_THAT(callback1.WaitForResult(), IsOk());
   handle1.Reset();
 
@@ -3357,7 +3481,8 @@
       ERR_IO_PENDING,
       handle1.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
                    ClientSocketPool::RespectLimits::ENABLED,
-                   callback1.callback(), pool_.get(), NetLogWithSource()));
+                   callback1.callback(), ClientSocketPool::ProxyAuthCallback(),
+                   pool_.get(), NetLogWithSource()));
   ASSERT_THAT(callback1.WaitForResult(), IsOk());
 
   ASSERT_TRUE(pool_->HasGroup("a"));
@@ -3443,7 +3568,8 @@
       ERR_IO_PENDING,
       handle1.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
                    ClientSocketPool::RespectLimits::ENABLED,
-                   callback1.callback(), pool_.get(), NetLogWithSource()));
+                   callback1.callback(), ClientSocketPool::ProxyAuthCallback(),
+                   pool_.get(), NetLogWithSource()));
 
   client_socket_factory_.SignalJob(0);
   EXPECT_THAT(callback1.WaitForResult(), IsOk());
@@ -3460,7 +3586,8 @@
       ERR_IO_PENDING,
       handle2.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
                    ClientSocketPool::RespectLimits::ENABLED,
-                   callback2.callback(), pool_.get(), NetLogWithSource()));
+                   callback2.callback(), ClientSocketPool::ProxyAuthCallback(),
+                   pool_.get(), NetLogWithSource()));
   client_socket_factory_.SignalJob(0);
   EXPECT_THAT(callback2.WaitForResult(), IsOk());
 
@@ -3536,7 +3663,8 @@
       ERR_IO_PENDING,
       handle1.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
                    ClientSocketPool::RespectLimits::ENABLED,
-                   callback1.callback(), pool_.get(), NetLogWithSource()));
+                   callback1.callback(), ClientSocketPool::ProxyAuthCallback(),
+                   pool_.get(), NetLogWithSource()));
 
   EXPECT_EQ(1u, pool_->NumConnectJobsInGroup("a"));
   EXPECT_EQ(0u, pool_->NumNeverAssignedConnectJobsInGroup("a"));
@@ -3575,10 +3703,11 @@
 
   ClientSocketHandle handle;
   TestCompletionCallback callback;
-  EXPECT_EQ(OK,
-            handle.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
-                        ClientSocketPool::RespectLimits::ENABLED,
-                        callback.callback(), pool_.get(), NetLogWithSource()));
+  EXPECT_EQ(OK, handle.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
+                            ClientSocketPool::RespectLimits::ENABLED,
+                            callback.callback(),
+                            ClientSocketPool::ProxyAuthCallback(), pool_.get(),
+                            NetLogWithSource()));
 
   // Make sure the idle socket was used.
   EXPECT_EQ(0u, pool_->IdleSocketCountInGroup("a"));
@@ -3605,7 +3734,8 @@
       ERR_IO_PENDING,
       handle1.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
                    ClientSocketPool::RespectLimits::ENABLED,
-                   callback1.callback(), pool_.get(), NetLogWithSource()));
+                   callback1.callback(), ClientSocketPool::ProxyAuthCallback(),
+                   pool_.get(), NetLogWithSource()));
   ASSERT_TRUE(pool_->HasGroup("a"));
   EXPECT_EQ(1u, pool_->NumConnectJobsInGroup("a"));
   EXPECT_EQ(0u, pool_->NumNeverAssignedConnectJobsInGroup("a"));
@@ -3629,12 +3759,14 @@
       ERR_IO_PENDING,
       handle1.Init("b", params_, DEFAULT_PRIORITY, SocketTag(),
                    ClientSocketPool::RespectLimits::ENABLED,
-                   callback1.callback(), pool_.get(), NetLogWithSource()));
+                   callback1.callback(), ClientSocketPool::ProxyAuthCallback(),
+                   pool_.get(), NetLogWithSource()));
   EXPECT_EQ(
       ERR_IO_PENDING,
       handle2.Init("b", params_, DEFAULT_PRIORITY, SocketTag(),
                    ClientSocketPool::RespectLimits::ENABLED,
-                   callback2.callback(), pool_.get(), NetLogWithSource()));
+                   callback2.callback(), ClientSocketPool::ProxyAuthCallback(),
+                   pool_.get(), NetLogWithSource()));
 
   ASSERT_TRUE(pool_->HasGroup("b"));
   EXPECT_EQ(2u, pool_->NumConnectJobsInGroup("b"));
@@ -3730,10 +3862,12 @@
   connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
   ClientSocketHandle handle;
   TestCompletionCallback callback;
-  EXPECT_EQ(ERR_IO_PENDING,
-            handle.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
-                        ClientSocketPool::RespectLimits::ENABLED,
-                        callback.callback(), pool_.get(), NetLogWithSource()));
+  EXPECT_EQ(
+      ERR_IO_PENDING,
+      handle.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
+                  ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
+                  ClientSocketPool::ProxyAuthCallback(), pool_.get(),
+                  NetLogWithSource()));
   // Timer has started, but the backup connect job shouldn't be created yet.
   EXPECT_EQ(1u, pool_->NumConnectJobsInGroup("a"));
   EXPECT_EQ(0u, pool_->NumNeverAssignedConnectJobsInGroup("a"));
@@ -3770,10 +3904,11 @@
   connect_job_factory_->set_job_type(TestConnectJob::kMockFailingJob);
   ClientSocketHandle handle;
   TestCompletionCallback callback;
-  EXPECT_EQ(OK,
-            handle.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
-                        ClientSocketPool::RespectLimits::ENABLED,
-                        callback.callback(), pool_.get(), NetLogWithSource()));
+  EXPECT_EQ(OK, handle.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
+                            ClientSocketPool::RespectLimits::ENABLED,
+                            callback.callback(),
+                            ClientSocketPool::ProxyAuthCallback(), pool_.get(),
+                            NetLogWithSource()));
 
   ASSERT_TRUE(pool_->HasGroup("a"));
   EXPECT_EQ(0u, pool_->NumConnectJobsInGroup("a"));
@@ -3802,7 +3937,8 @@
       ERR_IO_PENDING,
       handle1.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
                    ClientSocketPool::RespectLimits::ENABLED,
-                   callback1.callback(), pool_.get(), NetLogWithSource()));
+                   callback1.callback(), ClientSocketPool::ProxyAuthCallback(),
+                   pool_.get(), NetLogWithSource()));
 
   EXPECT_EQ(1u, pool_->NumConnectJobsInGroup("a"));
   EXPECT_EQ(0u, pool_->NumNeverAssignedConnectJobsInGroup("a"));
@@ -3822,7 +3958,8 @@
       ERR_IO_PENDING,
       handle1.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
                    ClientSocketPool::RespectLimits::ENABLED,
-                   callback1.callback(), pool_.get(), NetLogWithSource()));
+                   callback1.callback(), ClientSocketPool::ProxyAuthCallback(),
+                   pool_.get(), NetLogWithSource()));
 
   EXPECT_EQ(1u, pool_->NumConnectJobsInGroup("a"));
   EXPECT_EQ(0u, pool_->NumNeverAssignedConnectJobsInGroup("a"));
@@ -3835,7 +3972,8 @@
       ERR_IO_PENDING,
       handle2.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
                    ClientSocketPool::RespectLimits::ENABLED,
-                   callback2.callback(), pool_.get(), NetLogWithSource()));
+                   callback2.callback(), ClientSocketPool::ProxyAuthCallback(),
+                   pool_.get(), NetLogWithSource()));
 
   EXPECT_EQ(2u, pool_->NumConnectJobsInGroup("a"));
   EXPECT_EQ(0u, pool_->NumNeverAssignedConnectJobsInGroup("a"));
@@ -3876,7 +4014,8 @@
       ERR_IO_PENDING,
       handle1.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
                    ClientSocketPool::RespectLimits::ENABLED,
-                   callback1.callback(), pool_.get(), NetLogWithSource()));
+                   callback1.callback(), ClientSocketPool::ProxyAuthCallback(),
+                   pool_.get(), NetLogWithSource()));
 
   EXPECT_EQ(1u, pool_->NumConnectJobsInGroup("a"));
   EXPECT_EQ(0u, pool_->NumNeverAssignedConnectJobsInGroup("a"));
@@ -3896,7 +4035,8 @@
       ERR_IO_PENDING,
       handle1.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
                    ClientSocketPool::RespectLimits::ENABLED,
-                   callback1.callback(), pool_.get(), NetLogWithSource()));
+                   callback1.callback(), ClientSocketPool::ProxyAuthCallback(),
+                   pool_.get(), NetLogWithSource()));
 
   EXPECT_EQ(1u, pool_->NumConnectJobsInGroup("a"));
   EXPECT_EQ(0u, pool_->NumNeverAssignedConnectJobsInGroup("a"));
@@ -3912,7 +4052,8 @@
       ERR_IO_PENDING,
       handle2.Init("a", params_, HIGHEST, SocketTag(),
                    ClientSocketPool::RespectLimits::ENABLED,
-                   callback2.callback(), pool_.get(), NetLogWithSource()));
+                   callback2.callback(), ClientSocketPool::ProxyAuthCallback(),
+                   pool_.get(), NetLogWithSource()));
 
   EXPECT_EQ(1u, pool_->NumConnectJobsInGroup("a"));
   EXPECT_EQ(0u, pool_->NumNeverAssignedConnectJobsInGroup("a"));
@@ -3934,8 +4075,9 @@
   EXPECT_EQ(ERR_IO_PENDING,
             handle_lowest.Init("a", params_, LOWEST, SocketTag(),
                                ClientSocketPool::RespectLimits::ENABLED,
-                               callback_lowest.callback(), pool_.get(),
-                               NetLogWithSource()));
+                               callback_lowest.callback(),
+                               ClientSocketPool::ProxyAuthCallback(),
+                               pool_.get(), NetLogWithSource()));
 
   EXPECT_EQ(1u, pool_->NumConnectJobsInGroup("a"));
   EXPECT_EQ(0u, pool_->NumNeverAssignedConnectJobsInGroup("a"));
@@ -3947,8 +4089,9 @@
   EXPECT_EQ(ERR_IO_PENDING,
             handle_highest.Init("a", params_, HIGHEST, SocketTag(),
                                 ClientSocketPool::RespectLimits::ENABLED,
-                                callback_highest.callback(), pool_.get(),
-                                NetLogWithSource()));
+                                callback_highest.callback(),
+                                ClientSocketPool::ProxyAuthCallback(),
+                                pool_.get(), NetLogWithSource()));
 
   EXPECT_EQ(2u, pool_->NumConnectJobsInGroup("a"));
   EXPECT_EQ(0u, pool_->NumNeverAssignedConnectJobsInGroup("a"));
@@ -3960,7 +4103,8 @@
   EXPECT_EQ(ERR_IO_PENDING,
             handle_low.Init("a", params_, LOW, SocketTag(),
                             ClientSocketPool::RespectLimits::ENABLED,
-                            callback_low.callback(), pool_.get(),
+                            callback_low.callback(),
+                            ClientSocketPool::ProxyAuthCallback(), pool_.get(),
                             NetLogWithSource()));
 
   EXPECT_EQ(3u, pool_->NumConnectJobsInGroup("a"));
@@ -3973,8 +4117,9 @@
   EXPECT_EQ(ERR_IO_PENDING,
             handle_lowest2.Init("a", params_, LOWEST, SocketTag(),
                                 ClientSocketPool::RespectLimits::ENABLED,
-                                callback_lowest2.callback(), pool_.get(),
-                                NetLogWithSource()));
+                                callback_lowest2.callback(),
+                                ClientSocketPool::ProxyAuthCallback(),
+                                pool_.get(), NetLogWithSource()));
 
   EXPECT_EQ(3u, pool_->NumConnectJobsInGroup("a"));
   EXPECT_EQ(0u, pool_->NumNeverAssignedConnectJobsInGroup("a"));
@@ -3998,8 +4143,9 @@
   EXPECT_EQ(ERR_IO_PENDING,
             handle_medium.Init("a", params_, MEDIUM, SocketTag(),
                                ClientSocketPool::RespectLimits::ENABLED,
-                               callback_medium.callback(), pool_.get(),
-                               NetLogWithSource()));
+                               callback_medium.callback(),
+                               ClientSocketPool::ProxyAuthCallback(),
+                               pool_.get(), NetLogWithSource()));
 
   EXPECT_EQ(3u, pool_->NumConnectJobsInGroup("a"));
   EXPECT_EQ(0u, pool_->NumNeverAssignedConnectJobsInGroup("a"));
@@ -4027,7 +4173,8 @@
       ERR_IO_PENDING,
       handle1.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
                    ClientSocketPool::RespectLimits::ENABLED,
-                   callback1.callback(), pool_.get(), NetLogWithSource()));
+                   callback1.callback(), ClientSocketPool::ProxyAuthCallback(),
+                   pool_.get(), NetLogWithSource()));
 
   EXPECT_EQ(1u, pool_->NumConnectJobsInGroup("a"));
   EXPECT_EQ(0u, pool_->NumNeverAssignedConnectJobsInGroup("a"));
@@ -4040,7 +4187,8 @@
       ERR_IO_PENDING,
       handle2.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
                    ClientSocketPool::RespectLimits::ENABLED,
-                   callback2.callback(), pool_.get(), NetLogWithSource()));
+                   callback2.callback(), ClientSocketPool::ProxyAuthCallback(),
+                   pool_.get(), NetLogWithSource()));
 
   EXPECT_EQ(1u, pool_->NumConnectJobsInGroup("a"));
   EXPECT_EQ(0u, pool_->NumNeverAssignedConnectJobsInGroup("a"));
@@ -4068,7 +4216,8 @@
       ERR_IO_PENDING,
       handle1.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
                    ClientSocketPool::RespectLimits::ENABLED,
-                   callback1.callback(), pool_.get(), NetLogWithSource()));
+                   callback1.callback(), ClientSocketPool::ProxyAuthCallback(),
+                   pool_.get(), NetLogWithSource()));
 
   EXPECT_EQ(1u, pool_->NumConnectJobsInGroup("a"));
   EXPECT_EQ(0u, pool_->NumNeverAssignedConnectJobsInGroup("a"));
@@ -4083,7 +4232,8 @@
       ERR_IO_PENDING,
       handle2.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
                    ClientSocketPool::RespectLimits::ENABLED,
-                   callback2.callback(), pool_.get(), NetLogWithSource()));
+                   callback2.callback(), ClientSocketPool::ProxyAuthCallback(),
+                   pool_.get(), NetLogWithSource()));
 
   EXPECT_EQ(1u, pool_->NumConnectJobsInGroup("a"));
   EXPECT_EQ(0u, pool_->NumNeverAssignedConnectJobsInGroup("a"));
@@ -4114,7 +4264,8 @@
       ERR_IO_PENDING,
       handle1.Init("a", params_, HIGHEST, SocketTag(),
                    ClientSocketPool::RespectLimits::ENABLED,
-                   callback1.callback(), pool_.get(), NetLogWithSource()));
+                   callback1.callback(), ClientSocketPool::ProxyAuthCallback(),
+                   pool_.get(), NetLogWithSource()));
 
   EXPECT_EQ(1u, pool_->NumConnectJobsInGroup("a"));
   EXPECT_EQ(0u, pool_->NumNeverAssignedConnectJobsInGroup("a"));
@@ -4127,7 +4278,8 @@
       ERR_IO_PENDING,
       handle2.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
                    ClientSocketPool::RespectLimits::ENABLED,
-                   callback2.callback(), pool_.get(), NetLogWithSource()));
+                   callback2.callback(), ClientSocketPool::ProxyAuthCallback(),
+                   pool_.get(), NetLogWithSource()));
 
   EXPECT_EQ(2u, pool_->NumConnectJobsInGroup("a"));
   EXPECT_EQ(0u, pool_->NumNeverAssignedConnectJobsInGroup("a"));
@@ -4165,16 +4317,18 @@
 
   int RequestSocket(TestClientSocketPool* pool) {
     scoped_refptr<TestSocketParams> params(new TestSocketParams());
-    return handle_.Init(group_name_, params, DEFAULT_PRIORITY, SocketTag(),
-                        ClientSocketPool::RespectLimits::ENABLED,
-                        callback_.callback(), pool, NetLogWithSource());
+    return handle_.Init(
+        group_name_, params, DEFAULT_PRIORITY, SocketTag(),
+        ClientSocketPool::RespectLimits::ENABLED, callback_.callback(),
+        ClientSocketPool::ProxyAuthCallback(), pool, NetLogWithSource());
   }
 
   int RequestSocketWithoutLimits(TestClientSocketPool* pool) {
     scoped_refptr<TestSocketParams> params(new TestSocketParams());
-    return handle_.Init(group_name_, params, MAXIMUM_PRIORITY, SocketTag(),
-                        ClientSocketPool::RespectLimits::DISABLED,
-                        callback_.callback(), pool, NetLogWithSource());
+    return handle_.Init(
+        group_name_, params, MAXIMUM_PRIORITY, SocketTag(),
+        ClientSocketPool::RespectLimits::DISABLED, callback_.callback(),
+        ClientSocketPool::ProxyAuthCallback(), pool, NetLogWithSource());
   }
 
   bool ReleaseOneConnection() {
@@ -4236,10 +4390,12 @@
                        &MockLayeredPool::ReleaseOneConnection));
   ClientSocketHandle handle;
   TestCompletionCallback callback;
-  EXPECT_EQ(ERR_IO_PENDING,
-            handle.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
-                        ClientSocketPool::RespectLimits::ENABLED,
-                        callback.callback(), pool_.get(), NetLogWithSource()));
+  EXPECT_EQ(
+      ERR_IO_PENDING,
+      handle.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
+                  ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
+                  ClientSocketPool::ProxyAuthCallback(), pool_.get(),
+                  NetLogWithSource()));
   EXPECT_THAT(callback.WaitForResult(), IsOk());
 }
 
@@ -4257,10 +4413,11 @@
   // has the maximum number of connections already, it's not stalled).
   ClientSocketHandle handle1;
   TestCompletionCallback callback1;
-  EXPECT_EQ(
-      OK, handle1.Init("group1", params_, DEFAULT_PRIORITY, SocketTag(),
-                       ClientSocketPool::RespectLimits::ENABLED,
-                       callback1.callback(), pool_.get(), NetLogWithSource()));
+  EXPECT_EQ(OK, handle1.Init("group1", params_, DEFAULT_PRIORITY, SocketTag(),
+                             ClientSocketPool::RespectLimits::ENABLED,
+                             callback1.callback(),
+                             ClientSocketPool::ProxyAuthCallback(), pool_.get(),
+                             NetLogWithSource()));
 
   MockLayeredPool mock_layered_pool(pool_.get(), "group2");
   EXPECT_THAT(mock_layered_pool.RequestSocket(pool_.get()), IsOk());
@@ -4269,10 +4426,12 @@
                        &MockLayeredPool::ReleaseOneConnection));
   ClientSocketHandle handle;
   TestCompletionCallback callback2;
-  EXPECT_EQ(ERR_IO_PENDING,
-            handle.Init("group2", params_, DEFAULT_PRIORITY, SocketTag(),
-                        ClientSocketPool::RespectLimits::ENABLED,
-                        callback2.callback(), pool_.get(), NetLogWithSource()));
+  EXPECT_EQ(
+      ERR_IO_PENDING,
+      handle.Init("group2", params_, DEFAULT_PRIORITY, SocketTag(),
+                  ClientSocketPool::RespectLimits::ENABLED,
+                  callback2.callback(), ClientSocketPool::ProxyAuthCallback(),
+                  pool_.get(), NetLogWithSource()));
   EXPECT_THAT(callback2.WaitForResult(), IsOk());
 }
 
@@ -4290,10 +4449,11 @@
 
   ClientSocketHandle handle1;
   TestCompletionCallback callback1;
-  EXPECT_EQ(
-      OK, handle1.Init("group1", params_, DEFAULT_PRIORITY, SocketTag(),
-                       ClientSocketPool::RespectLimits::ENABLED,
-                       callback1.callback(), pool_.get(), NetLogWithSource()));
+  EXPECT_EQ(OK, handle1.Init("group1", params_, DEFAULT_PRIORITY, SocketTag(),
+                             ClientSocketPool::RespectLimits::ENABLED,
+                             callback1.callback(),
+                             ClientSocketPool::ProxyAuthCallback(), pool_.get(),
+                             NetLogWithSource()));
 
   MockLayeredPool mock_layered_pool(pool_.get(), "group2");
   EXPECT_THAT(mock_layered_pool.RequestSocket(pool_.get()), IsOk());
@@ -4309,7 +4469,8 @@
       ERR_IO_PENDING,
       handle3.Init("group3", params_, DEFAULT_PRIORITY, SocketTag(),
                    ClientSocketPool::RespectLimits::ENABLED,
-                   callback3.callback(), pool_.get(), NetLogWithSource()));
+                   callback3.callback(), ClientSocketPool::ProxyAuthCallback(),
+                   pool_.get(), NetLogWithSource()));
 
   base::RunLoop().RunUntilIdle();
   EXPECT_FALSE(callback3.have_result());
@@ -4324,7 +4485,8 @@
       ERR_IO_PENDING,
       handle4.Init("group3", params_, DEFAULT_PRIORITY, SocketTag(),
                    ClientSocketPool::RespectLimits::ENABLED,
-                   callback4.callback(), pool_.get(), NetLogWithSource()));
+                   callback4.callback(), ClientSocketPool::ProxyAuthCallback(),
+                   pool_.get(), NetLogWithSource()));
   EXPECT_THAT(callback3.WaitForResult(), IsOk());
   EXPECT_FALSE(callback4.have_result());
 
@@ -4351,10 +4513,11 @@
 
   ClientSocketHandle handle1;
   TestCompletionCallback callback1;
-  EXPECT_EQ(
-      OK, handle1.Init("group1", params_, DEFAULT_PRIORITY, SocketTag(),
-                       ClientSocketPool::RespectLimits::ENABLED,
-                       callback1.callback(), pool_.get(), NetLogWithSource()));
+  EXPECT_EQ(OK, handle1.Init("group1", params_, DEFAULT_PRIORITY, SocketTag(),
+                             ClientSocketPool::RespectLimits::ENABLED,
+                             callback1.callback(),
+                             ClientSocketPool::ProxyAuthCallback(), pool_.get(),
+                             NetLogWithSource()));
 
   MockLayeredPool mock_layered_pool(pool_.get(), "group2");
   EXPECT_THAT(mock_layered_pool.RequestSocket(pool_.get()), IsOk());
@@ -4370,7 +4533,8 @@
       ERR_IO_PENDING,
       handle3.Init("group3", params_, MEDIUM, SocketTag(),
                    ClientSocketPool::RespectLimits::ENABLED,
-                   callback3.callback(), pool_.get(), NetLogWithSource()));
+                   callback3.callback(), ClientSocketPool::ProxyAuthCallback(),
+                   pool_.get(), NetLogWithSource()));
 
   base::RunLoop().RunUntilIdle();
   EXPECT_FALSE(callback3.have_result());
@@ -4384,7 +4548,8 @@
       ERR_IO_PENDING,
       handle4.Init("group3", params_, HIGHEST, SocketTag(),
                    ClientSocketPool::RespectLimits::ENABLED,
-                   callback4.callback(), pool_.get(), NetLogWithSource()));
+                   callback4.callback(), ClientSocketPool::ProxyAuthCallback(),
+                   pool_.get(), NetLogWithSource()));
   EXPECT_THAT(callback4.WaitForResult(), IsOk());
   EXPECT_FALSE(callback3.have_result());
 
@@ -4411,10 +4576,12 @@
                              &MockLayeredPool::ReleaseOneConnection));
   ClientSocketHandle handle;
   TestCompletionCallback callback;
-  EXPECT_EQ(ERR_IO_PENDING,
-            handle.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
-                        ClientSocketPool::RespectLimits::ENABLED,
-                        callback.callback(), pool_.get(), NetLogWithSource()));
+  EXPECT_EQ(
+      ERR_IO_PENDING,
+      handle.Init("a", params_, DEFAULT_PRIORITY, SocketTag(),
+                  ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
+                  ClientSocketPool::ProxyAuthCallback(), pool_.get(),
+                  NetLogWithSource()));
   EXPECT_THAT(callback.WaitForResult(), IsOk());
 }
 
diff --git a/net/socket/client_socket_pool_manager.cc b/net/socket/client_socket_pool_manager.cc
index c16de189..cdd0092 100644
--- a/net/socket/client_socket_pool_manager.cc
+++ b/net/socket/client_socket_pool_manager.cc
@@ -16,7 +16,6 @@
 #include "net/http/http_stream_factory.h"
 #include "net/proxy_resolution/proxy_info.h"
 #include "net/socket/client_socket_handle.h"
-#include "net/socket/client_socket_pool.h"
 #include "net/socket/socks_connect_job.h"
 #include "net/socket/ssl_connect_job.h"
 #include "net/socket/transport_client_socket_pool.h"
@@ -70,25 +69,27 @@
 
 // The meat of the implementation for the InitSocketHandleForHttpRequest,
 // InitSocketHandleForRawConnect and PreconnectSocketsForHttpRequest methods.
-int InitSocketPoolHelper(ClientSocketPoolManager::SocketGroupType group_type,
-                         const HostPortPair& endpoint,
-                         const HttpRequestHeaders& request_extra_headers,
-                         int request_load_flags,
-                         RequestPriority request_priority,
-                         HttpNetworkSession* session,
-                         const ProxyInfo& proxy_info,
-                         quic::QuicTransportVersion quic_version,
-                         const SSLConfig& ssl_config_for_origin,
-                         const SSLConfig& ssl_config_for_proxy,
-                         bool force_tunnel,
-                         PrivacyMode privacy_mode,
-                         const SocketTag& socket_tag,
-                         const NetLogWithSource& net_log,
-                         int num_preconnect_streams,
-                         ClientSocketHandle* socket_handle,
-                         HttpNetworkSession::SocketPoolType socket_pool_type,
-                         const OnHostResolutionCallback& resolution_callback,
-                         CompletionOnceCallback callback) {
+int InitSocketPoolHelper(
+    ClientSocketPoolManager::SocketGroupType group_type,
+    const HostPortPair& endpoint,
+    const HttpRequestHeaders& request_extra_headers,
+    int request_load_flags,
+    RequestPriority request_priority,
+    HttpNetworkSession* session,
+    const ProxyInfo& proxy_info,
+    quic::QuicTransportVersion quic_version,
+    const SSLConfig& ssl_config_for_origin,
+    const SSLConfig& ssl_config_for_proxy,
+    bool force_tunnel,
+    PrivacyMode privacy_mode,
+    const SocketTag& socket_tag,
+    const NetLogWithSource& net_log,
+    int num_preconnect_streams,
+    ClientSocketHandle* socket_handle,
+    HttpNetworkSession::SocketPoolType socket_pool_type,
+    const OnHostResolutionCallback& resolution_callback,
+    CompletionOnceCallback callback,
+    const ClientSocketPool::ProxyAuthCallback& proxy_auth_callback) {
   scoped_refptr<HttpProxySocketParams> http_proxy_params;
   scoped_refptr<SOCKSSocketParams> socks_params;
 
@@ -224,7 +225,7 @@
         TransportClientSocketPool::SocketParams::CreateFromSSLSocketParams(
             ssl_params),
         request_priority, socket_tag, respect_limits, std::move(callback),
-        ssl_pool, net_log);
+        proxy_auth_callback, ssl_pool, net_log);
   }
 
   // Finally, get the connection started.
@@ -245,8 +246,8 @@
         connection_group,
         TransportClientSocketPool::SocketParams::
             CreateFromHttpProxySocketParams(http_proxy_params),
-        request_priority, socket_tag, respect_limits, std::move(callback), pool,
-        net_log);
+        request_priority, socket_tag, respect_limits, std::move(callback),
+        proxy_auth_callback, pool, net_log);
   }
 
   if (proxy_info.is_socks()) {
@@ -265,8 +266,8 @@
         connection_group,
         TransportClientSocketPool::SocketParams::CreateFromSOCKSSocketParams(
             socks_params),
-        request_priority, socket_tag, respect_limits, std::move(callback), pool,
-        net_log);
+        request_priority, socket_tag, respect_limits, std::move(callback),
+        proxy_auth_callback, pool, net_log);
   }
 
   DCHECK(proxy_info.is_direct());
@@ -287,8 +288,8 @@
       connection_group,
       TransportClientSocketPool::SocketParams::CreateFromTransportSocketParams(
           std::move(tcp_params)),
-      request_priority, socket_tag, respect_limits, std::move(callback), pool,
-      net_log);
+      request_priority, socket_tag, respect_limits, std::move(callback),
+      proxy_auth_callback, pool, net_log);
 }
 
 }  // namespace
@@ -387,7 +388,8 @@
     const NetLogWithSource& net_log,
     ClientSocketHandle* socket_handle,
     const OnHostResolutionCallback& resolution_callback,
-    CompletionOnceCallback callback) {
+    CompletionOnceCallback callback,
+    const ClientSocketPool::ProxyAuthCallback& proxy_auth_callback) {
   DCHECK(socket_handle);
   return InitSocketPoolHelper(
       group_type, endpoint, request_extra_headers, request_load_flags,
@@ -395,7 +397,7 @@
       ssl_config_for_origin, ssl_config_for_proxy, /*force_tunnel=*/false,
       privacy_mode, socket_tag, net_log, 0, socket_handle,
       HttpNetworkSession::NORMAL_SOCKET_POOL, resolution_callback,
-      std::move(callback));
+      std::move(callback), proxy_auth_callback);
 }
 
 int InitSocketHandleForWebSocketRequest(
@@ -412,7 +414,8 @@
     const NetLogWithSource& net_log,
     ClientSocketHandle* socket_handle,
     const OnHostResolutionCallback& resolution_callback,
-    CompletionOnceCallback callback) {
+    CompletionOnceCallback callback,
+    const ClientSocketPool::ProxyAuthCallback& proxy_auth_callback) {
   DCHECK(socket_handle);
   return InitSocketPoolHelper(
       group_type, endpoint, request_extra_headers, request_load_flags,
@@ -420,20 +423,22 @@
       ssl_config_for_origin, ssl_config_for_proxy,
       /*force_tunnel=*/true, privacy_mode, SocketTag(), net_log, 0,
       socket_handle, HttpNetworkSession::WEBSOCKET_SOCKET_POOL,
-      resolution_callback, std::move(callback));
+      resolution_callback, std::move(callback), proxy_auth_callback);
 }
 
-int InitSocketHandleForRawConnect(const HostPortPair& host_port_pair,
-                                  HttpNetworkSession* session,
-                                  int request_load_flags,
-                                  RequestPriority request_priority,
-                                  const ProxyInfo& proxy_info,
-                                  const SSLConfig& ssl_config_for_origin,
-                                  const SSLConfig& ssl_config_for_proxy,
-                                  PrivacyMode privacy_mode,
-                                  const NetLogWithSource& net_log,
-                                  ClientSocketHandle* socket_handle,
-                                  CompletionOnceCallback callback) {
+int InitSocketHandleForRawConnect(
+    const HostPortPair& host_port_pair,
+    HttpNetworkSession* session,
+    int request_load_flags,
+    RequestPriority request_priority,
+    const ProxyInfo& proxy_info,
+    const SSLConfig& ssl_config_for_origin,
+    const SSLConfig& ssl_config_for_proxy,
+    PrivacyMode privacy_mode,
+    const NetLogWithSource& net_log,
+    ClientSocketHandle* socket_handle,
+    CompletionOnceCallback callback,
+    const ClientSocketPool::ProxyAuthCallback& proxy_auth_callback) {
   DCHECK(socket_handle);
   HttpRequestHeaders request_extra_headers;
   return InitSocketPoolHelper(
@@ -442,20 +447,22 @@
       proxy_info, quic::QUIC_VERSION_UNSUPPORTED, ssl_config_for_origin,
       ssl_config_for_proxy, /*force_tunnel=*/true, privacy_mode, SocketTag(),
       net_log, 0, socket_handle, HttpNetworkSession::NORMAL_SOCKET_POOL,
-      OnHostResolutionCallback(), std::move(callback));
+      OnHostResolutionCallback(), std::move(callback), proxy_auth_callback);
 }
 
-int InitSocketHandleForTlsConnect(const HostPortPair& endpoint,
-                                  HttpNetworkSession* session,
-                                  int request_load_flags,
-                                  RequestPriority request_priority,
-                                  const ProxyInfo& proxy_info,
-                                  const SSLConfig& ssl_config_for_origin,
-                                  const SSLConfig& ssl_config_for_proxy,
-                                  PrivacyMode privacy_mode,
-                                  const NetLogWithSource& net_log,
-                                  ClientSocketHandle* socket_handle,
-                                  CompletionOnceCallback callback) {
+int InitSocketHandleForTlsConnect(
+    const HostPortPair& endpoint,
+    HttpNetworkSession* session,
+    int request_load_flags,
+    RequestPriority request_priority,
+    const ProxyInfo& proxy_info,
+    const SSLConfig& ssl_config_for_origin,
+    const SSLConfig& ssl_config_for_proxy,
+    PrivacyMode privacy_mode,
+    const NetLogWithSource& net_log,
+    ClientSocketHandle* socket_handle,
+    CompletionOnceCallback callback,
+    const ClientSocketPool::ProxyAuthCallback& proxy_auth_callback) {
   DCHECK(socket_handle);
   HttpRequestHeaders request_extra_headers;
   return InitSocketPoolHelper(
@@ -465,7 +472,7 @@
       ssl_config_for_proxy,
       /*force_tunnel=*/true, privacy_mode, SocketTag(), net_log, 0,
       socket_handle, HttpNetworkSession::NORMAL_SOCKET_POOL,
-      OnHostResolutionCallback(), std::move(callback));
+      OnHostResolutionCallback(), std::move(callback), proxy_auth_callback);
 }
 
 int PreconnectSocketsForHttpRequest(
@@ -487,7 +494,8 @@
       ssl_config_for_origin, ssl_config_for_proxy,
       /*force_tunnel=*/false, privacy_mode, SocketTag(), net_log,
       num_preconnect_streams, NULL, HttpNetworkSession::NORMAL_SOCKET_POOL,
-      OnHostResolutionCallback(), CompletionOnceCallback());
+      OnHostResolutionCallback(), CompletionOnceCallback(),
+      ClientSocketPool::ProxyAuthCallback());
 }
 
 }  // namespace net
diff --git a/net/socket/client_socket_pool_manager.h b/net/socket/client_socket_pool_manager.h
index 91d6b58..ac93da3 100644
--- a/net/socket/client_socket_pool_manager.h
+++ b/net/socket/client_socket_pool_manager.h
@@ -15,6 +15,7 @@
 #include "net/base/net_export.h"
 #include "net/base/request_priority.h"
 #include "net/http/http_network_session.h"
+#include "net/socket/client_socket_pool.h"
 
 namespace base {
 class Value;
@@ -130,7 +131,8 @@
     const NetLogWithSource& net_log,
     ClientSocketHandle* socket_handle,
     const OnHostResolutionCallback& resolution_callback,
-    CompletionOnceCallback callback);
+    CompletionOnceCallback callback,
+    const ClientSocketPool::ProxyAuthCallback& proxy_auth_callback);
 
 // A helper method that uses the passed in proxy information to initialize a
 // ClientSocketHandle with the relevant socket pool. Use this method for
@@ -155,7 +157,8 @@
     const NetLogWithSource& net_log,
     ClientSocketHandle* socket_handle,
     const OnHostResolutionCallback& resolution_callback,
-    CompletionOnceCallback callback);
+    CompletionOnceCallback callback,
+    const ClientSocketPool::ProxyAuthCallback& proxy_auth_callback);
 
 // Deprecated: Please do not use this outside of //net and //services/network.
 // A helper method that uses the passed in proxy information to initialize a
@@ -173,7 +176,8 @@
     PrivacyMode privacy_mode,
     const NetLogWithSource& net_log,
     ClientSocketHandle* socket_handle,
-    CompletionOnceCallback callback);
+    CompletionOnceCallback callback,
+    const ClientSocketPool::ProxyAuthCallback& proxy_auth_callback);
 
 // Deprecated: Please do not use this outside of //net and //services/network.
 // A helper method that uses the passed in proxy information to initialize a
@@ -191,7 +195,8 @@
     PrivacyMode privacy_mode,
     const NetLogWithSource& net_log,
     ClientSocketHandle* socket_handle,
-    CompletionOnceCallback callback);
+    CompletionOnceCallback callback,
+    const ClientSocketPool::ProxyAuthCallback& proxy_auth_callback);
 
 // Similar to InitSocketHandleForHttpRequest except that it initiates the
 // desired number of preconnect streams from the relevant socket pool.
diff --git a/net/socket/client_socket_pool_manager_impl.cc b/net/socket/client_socket_pool_manager_impl.cc
index dcd7affb..d71e7e0 100644
--- a/net/socket/client_socket_pool_manager_impl.cc
+++ b/net/socket/client_socket_pool_manager_impl.cc
@@ -200,7 +200,6 @@
       ssl_socket_pools_for_proxies_.insert(std::make_pair(
           proxy_server,
           std::make_unique<TransportClientSocketPool>(
-
               sockets_per_proxy_server, sockets_per_group,
               unused_idle_socket_timeout(pool_type_), socket_factory_,
               host_resolver_, proxy_delegate_, cert_verifier_,
diff --git a/net/socket/socket_test_util.cc b/net/socket/socket_test_util.cc
index e3c21f1..92ba59ea 100644
--- a/net/socket/socket_test_util.cc
+++ b/net/socket/socket_test_util.cc
@@ -2178,6 +2178,7 @@
     RespectLimits respect_limits,
     ClientSocketHandle* handle,
     CompletionOnceCallback callback,
+    const ProxyAuthCallback& on_auth_callback,
     const NetLogWithSource& net_log) {
   last_request_priority_ = priority;
   std::unique_ptr<StreamSocket> socket =
diff --git a/net/socket/socket_test_util.h b/net/socket/socket_test_util.h
index bc2a43cc..88bbae2ab 100644
--- a/net/socket/socket_test_util.h
+++ b/net/socket/socket_test_util.h
@@ -1146,7 +1146,8 @@
     requests_.push_back(base::WrapUnique(request));
     int rv = request->handle()->Init(
         group_name, socket_params, priority, SocketTag(), respect_limits,
-        request->callback(), socket_pool, NetLogWithSource());
+        request->callback(), ClientSocketPool::ProxyAuthCallback(), socket_pool,
+        NetLogWithSource());
     if (rv != ERR_IO_PENDING)
       request_order_.push_back(request);
     return rv;
@@ -1250,6 +1251,7 @@
                     RespectLimits respect_limits,
                     ClientSocketHandle* handle,
                     CompletionOnceCallback callback,
+                    const ProxyAuthCallback& on_auth_callback,
                     const NetLogWithSource& net_log) override;
   void SetPriority(const std::string& group_name,
                    ClientSocketHandle* handle,
diff --git a/net/socket/ssl_client_socket_pool_unittest.cc b/net/socket/ssl_client_socket_pool_unittest.cc
index 99cf66c..001ffdd2 100644
--- a/net/socket/ssl_client_socket_pool_unittest.cc
+++ b/net/socket/ssl_client_socket_pool_unittest.cc
@@ -202,7 +202,8 @@
       TransportClientSocketPool::SocketParams::CreateFromSSLSocketParams(
           params),
       MEDIUM, SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
-      callback.callback(), pool_.get(), NetLogWithSource());
+      callback.callback(), ClientSocketPool::ProxyAuthCallback(), pool_.get(),
+      NetLogWithSource());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
   EXPECT_FALSE(handle.is_initialized());
   EXPECT_FALSE(handle.socket());
@@ -240,7 +241,8 @@
       TransportClientSocketPool::SocketParams::CreateFromSSLSocketParams(
           params),
       MEDIUM, SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
-      callback.callback(), pool_.get(), NetLogWithSource());
+      callback.callback(), ClientSocketPool::ProxyAuthCallback(), pool_.get(),
+      NetLogWithSource());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
   EXPECT_FALSE(handle.is_initialized());
   EXPECT_FALSE(handle.socket());
diff --git a/net/socket/ssl_connect_job.cc b/net/socket/ssl_connect_job.cc
index 7962ef9..2f9c891 100644
--- a/net/socket/ssl_connect_job.cc
+++ b/net/socket/ssl_connect_job.cc
@@ -306,8 +306,8 @@
       group_name(),
       TransportClientSocketPool::SocketParams::CreateFromHttpProxySocketParams(
           http_proxy_params),
-      priority(), socket_tag(), respect_limits(), callback_, http_proxy_pool_,
-      net_log());
+      priority(), socket_tag(), respect_limits(), callback_,
+      ClientSocketPool::ProxyAuthCallback(), http_proxy_pool_, net_log());
 }
 
 int SSLConnectJob::DoTunnelConnectComplete(int result) {
diff --git a/net/socket/transport_client_socket_pool.cc b/net/socket/transport_client_socket_pool.cc
index 2afe9480..e1b213a 100644
--- a/net/socket/transport_client_socket_pool.cc
+++ b/net/socket/transport_client_socket_pool.cc
@@ -220,14 +220,16 @@
     ssl_config_service_->RemoveObserver(this);
 }
 
-int TransportClientSocketPool::RequestSocket(const std::string& group_name,
-                                             const void* params,
-                                             RequestPriority priority,
-                                             const SocketTag& socket_tag,
-                                             RespectLimits respect_limits,
-                                             ClientSocketHandle* handle,
-                                             CompletionOnceCallback callback,
-                                             const NetLogWithSource& net_log) {
+int TransportClientSocketPool::RequestSocket(
+    const std::string& group_name,
+    const void* params,
+    RequestPriority priority,
+    const SocketTag& socket_tag,
+    RespectLimits respect_limits,
+    ClientSocketHandle* handle,
+    CompletionOnceCallback callback,
+    const ProxyAuthCallback& proxy_auth_callback,
+    const NetLogWithSource& net_log) {
   const scoped_refptr<SocketParams>* casted_params =
       static_cast<const scoped_refptr<SocketParams>*>(params);
 
@@ -235,7 +237,7 @@
 
   return base_.RequestSocket(group_name, *casted_params, priority, socket_tag,
                              respect_limits, handle, std::move(callback),
-                             net_log);
+                             proxy_auth_callback, net_log);
 }
 
 void TransportClientSocketPool::NetLogTcpClientSocketPoolRequestedSocket(
diff --git a/net/socket/transport_client_socket_pool.h b/net/socket/transport_client_socket_pool.h
index 355d709..419ad0d47 100644
--- a/net/socket/transport_client_socket_pool.h
+++ b/net/socket/transport_client_socket_pool.h
@@ -132,6 +132,7 @@
                     RespectLimits respect_limits,
                     ClientSocketHandle* handle,
                     CompletionOnceCallback callback,
+                    const ProxyAuthCallback& proxy_auth_callback,
                     const NetLogWithSource& net_log) override;
   void RequestSockets(const std::string& group_name,
                       const void* params,
diff --git a/net/socket/transport_client_socket_pool_unittest.cc b/net/socket/transport_client_socket_pool_unittest.cc
index cc2cda85..6c731b9 100644
--- a/net/socket/transport_client_socket_pool_unittest.cc
+++ b/net/socket/transport_client_socket_pool_unittest.cc
@@ -195,9 +195,10 @@
 TEST_F(TransportClientSocketPoolTest, Basic) {
   TestCompletionCallback callback;
   ClientSocketHandle handle;
-  int rv = handle.Init("a", params_, LOW, SocketTag(),
-                       ClientSocketPool::RespectLimits::ENABLED,
-                       callback.callback(), &pool_, NetLogWithSource());
+  int rv = handle.Init(
+      "a", params_, LOW, SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
+      callback.callback(), ClientSocketPool::ProxyAuthCallback(), &pool_,
+      NetLogWithSource());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
   EXPECT_FALSE(handle.is_initialized());
   EXPECT_FALSE(handle.socket());
@@ -216,10 +217,12 @@
     RequestPriority priority = static_cast<RequestPriority>(i);
     TestCompletionCallback callback;
     ClientSocketHandle handle;
-    EXPECT_EQ(ERR_IO_PENDING,
-              handle.Init("a", params_, priority, SocketTag(),
-                          ClientSocketPool::RespectLimits::ENABLED,
-                          callback.callback(), &pool_, NetLogWithSource()));
+    EXPECT_EQ(
+        ERR_IO_PENDING,
+        handle.Init("a", params_, priority, SocketTag(),
+                    ClientSocketPool::RespectLimits::ENABLED,
+                    callback.callback(), ClientSocketPool::ProxyAuthCallback(),
+                    &pool_, NetLogWithSource()));
     EXPECT_EQ(priority, host_resolver_->last_request_priority());
   }
 }
@@ -229,44 +232,50 @@
 
   TestCompletionCallback callback1;
   ClientSocketHandle handle1;
-  int rv1 = handle1.Init("a", params_, LOW, SocketTag(),
-                         ClientSocketPool::RespectLimits::ENABLED,
-                         callback1.callback(), &pool_, NetLogWithSource());
+  int rv1 = handle1.Init(
+      "a", params_, LOW, SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
+      callback1.callback(), ClientSocketPool::ProxyAuthCallback(), &pool_,
+      NetLogWithSource());
   EXPECT_THAT(rv1, IsError(ERR_IO_PENDING));
 
   TestCompletionCallback callback2;
   ClientSocketHandle handle2;
-  int rv2 = handle2.Init("a", params_, HIGHEST, SocketTag(),
-                         ClientSocketPool::RespectLimits::ENABLED,
-                         callback2.callback(), &pool_, NetLogWithSource());
+  int rv2 = handle2.Init(
+      "a", params_, HIGHEST, SocketTag(),
+      ClientSocketPool::RespectLimits::ENABLED, callback2.callback(),
+      ClientSocketPool::ProxyAuthCallback(), &pool_, NetLogWithSource());
   EXPECT_THAT(rv2, IsError(ERR_IO_PENDING));
 
   TestCompletionCallback callback3;
   ClientSocketHandle handle3;
-  int rv3 = handle3.Init("a", params_, LOWEST, SocketTag(),
-                         ClientSocketPool::RespectLimits::ENABLED,
-                         callback3.callback(), &pool_, NetLogWithSource());
+  int rv3 = handle3.Init(
+      "a", params_, LOWEST, SocketTag(),
+      ClientSocketPool::RespectLimits::ENABLED, callback3.callback(),
+      ClientSocketPool::ProxyAuthCallback(), &pool_, NetLogWithSource());
   EXPECT_THAT(rv3, IsError(ERR_IO_PENDING));
 
   TestCompletionCallback callback4;
   ClientSocketHandle handle4;
-  int rv4 = handle4.Init("a", params_, MEDIUM, SocketTag(),
-                         ClientSocketPool::RespectLimits::ENABLED,
-                         callback4.callback(), &pool_, NetLogWithSource());
+  int rv4 = handle4.Init(
+      "a", params_, MEDIUM, SocketTag(),
+      ClientSocketPool::RespectLimits::ENABLED, callback4.callback(),
+      ClientSocketPool::ProxyAuthCallback(), &pool_, NetLogWithSource());
   EXPECT_THAT(rv4, IsError(ERR_IO_PENDING));
 
   TestCompletionCallback callback5;
   ClientSocketHandle handle5;
-  int rv5 = handle5.Init("a", params_, HIGHEST, SocketTag(),
-                         ClientSocketPool::RespectLimits::ENABLED,
-                         callback5.callback(), &pool_, NetLogWithSource());
+  int rv5 = handle5.Init(
+      "a", params_, HIGHEST, SocketTag(),
+      ClientSocketPool::RespectLimits::ENABLED, callback5.callback(),
+      ClientSocketPool::ProxyAuthCallback(), &pool_, NetLogWithSource());
   EXPECT_THAT(rv5, IsError(ERR_IO_PENDING));
 
   TestCompletionCallback callback6;
   ClientSocketHandle handle6;
-  int rv6 = handle6.Init("a", params_, LOW, SocketTag(),
-                         ClientSocketPool::RespectLimits::ENABLED,
-                         callback6.callback(), &pool_, NetLogWithSource());
+  int rv6 = handle6.Init(
+      "a", params_, LOW, SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
+      callback6.callback(), ClientSocketPool::ProxyAuthCallback(), &pool_,
+      NetLogWithSource());
   EXPECT_THAT(rv6, IsError(ERR_IO_PENDING));
 
   // New jobs are created for each of the first 6 requests with the
@@ -292,9 +301,10 @@
   // priority request and reprioritizes it to match the new request.
   TestCompletionCallback callback7;
   ClientSocketHandle handle7;
-  int rv7 = handle7.Init("a", params_, HIGHEST, SocketTag(),
-                         ClientSocketPool::RespectLimits::ENABLED,
-                         callback7.callback(), &pool_, NetLogWithSource());
+  int rv7 = handle7.Init(
+      "a", params_, HIGHEST, SocketTag(),
+      ClientSocketPool::RespectLimits::ENABLED, callback7.callback(),
+      ClientSocketPool::ProxyAuthCallback(), &pool_, NetLogWithSource());
   EXPECT_THAT(rv7, IsError(ERR_IO_PENDING));
   // Request  Job  Priority
   // =======  ===  ========
@@ -314,9 +324,10 @@
 
   TestCompletionCallback callback8;
   ClientSocketHandle handle8;
-  int rv8 = handle8.Init("a", params_, HIGHEST, SocketTag(),
-                         ClientSocketPool::RespectLimits::ENABLED,
-                         callback8.callback(), &pool_, NetLogWithSource());
+  int rv8 = handle8.Init(
+      "a", params_, HIGHEST, SocketTag(),
+      ClientSocketPool::RespectLimits::ENABLED, callback8.callback(),
+      ClientSocketPool::ProxyAuthCallback(), &pool_, NetLogWithSource());
   EXPECT_THAT(rv8, IsError(ERR_IO_PENDING));
   // Request  Job  Priority
   // =======  ===  ========
@@ -465,18 +476,20 @@
   // Creates a job which ignores limits whose priority is MAXIMUM_PRIORITY
   TestCompletionCallback callback1;
   ClientSocketHandle handle1;
-  int rv1 = handle1.Init("a", params_, MAXIMUM_PRIORITY, SocketTag(),
-                         ClientSocketPool::RespectLimits::DISABLED,
-                         callback1.callback(), &pool, NetLogWithSource());
+  int rv1 = handle1.Init(
+      "a", params_, MAXIMUM_PRIORITY, SocketTag(),
+      ClientSocketPool::RespectLimits::DISABLED, callback1.callback(),
+      ClientSocketPool::ProxyAuthCallback(), &pool, NetLogWithSource());
   EXPECT_THAT(rv1, IsError(ERR_IO_PENDING));
 
   EXPECT_EQ(MAXIMUM_PRIORITY, host_resolver_->request_priority(1));
 
   TestCompletionCallback callback2;
   ClientSocketHandle handle2;
-  int rv2 = handle2.Init("a", params_, LOW, SocketTag(),
-                         ClientSocketPool::RespectLimits::ENABLED,
-                         callback2.callback(), &pool, NetLogWithSource());
+  int rv2 = handle2.Init(
+      "a", params_, LOW, SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
+      callback2.callback(), ClientSocketPool::ProxyAuthCallback(), &pool,
+      NetLogWithSource());
   EXPECT_THAT(rv2, IsError(ERR_IO_PENDING));
 
   // handle2 gets assigned the job, but it is not changed to match the request
@@ -494,10 +507,12 @@
       TransportClientSocketPool::SocketParams::CreateFromTransportSocketParams(
           base::MakeRefCounted<TransportSocketParams>(
               host_port_pair, false, OnHostResolutionCallback())));
-  EXPECT_EQ(ERR_IO_PENDING,
-            handle.Init("a", dest, kDefaultPriority, SocketTag(),
-                        ClientSocketPool::RespectLimits::ENABLED,
-                        callback.callback(), &pool_, NetLogWithSource()));
+  EXPECT_EQ(
+      ERR_IO_PENDING,
+      handle.Init("a", dest, kDefaultPriority, SocketTag(),
+                  ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
+                  ClientSocketPool::ProxyAuthCallback(), &pool_,
+                  NetLogWithSource()));
   EXPECT_THAT(callback.WaitForResult(), IsError(ERR_NAME_NOT_RESOLVED));
   ASSERT_EQ(1u, handle.connection_attempts().size());
   EXPECT_TRUE(handle.connection_attempts()[0].endpoint.address().empty());
@@ -510,10 +525,12 @@
       MockTransportClientSocketFactory::MOCK_FAILING_CLIENT_SOCKET);
   TestCompletionCallback callback;
   ClientSocketHandle handle;
-  EXPECT_EQ(ERR_IO_PENDING,
-            handle.Init("a", params_, kDefaultPriority, SocketTag(),
-                        ClientSocketPool::RespectLimits::ENABLED,
-                        callback.callback(), &pool_, NetLogWithSource()));
+  EXPECT_EQ(
+      ERR_IO_PENDING,
+      handle.Init("a", params_, kDefaultPriority, SocketTag(),
+                  ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
+                  ClientSocketPool::ProxyAuthCallback(), &pool_,
+                  NetLogWithSource()));
   EXPECT_THAT(callback.WaitForResult(), IsError(ERR_CONNECTION_FAILED));
   ASSERT_EQ(1u, handle.connection_attempts().size());
   EXPECT_EQ("127.0.0.1:80",
@@ -523,10 +540,12 @@
 
   // Make the host resolutions complete synchronously this time.
   host_resolver_->set_synchronous_mode(true);
-  EXPECT_EQ(ERR_CONNECTION_FAILED,
-            handle.Init("a", params_, kDefaultPriority, SocketTag(),
-                        ClientSocketPool::RespectLimits::ENABLED,
-                        callback.callback(), &pool_, NetLogWithSource()));
+  EXPECT_EQ(
+      ERR_CONNECTION_FAILED,
+      handle.Init("a", params_, kDefaultPriority, SocketTag(),
+                  ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
+                  ClientSocketPool::ProxyAuthCallback(), &pool_,
+                  NetLogWithSource()));
   ASSERT_EQ(1u, handle.connection_attempts().size());
   EXPECT_EQ("127.0.0.1:80",
             handle.connection_attempts()[0].endpoint.ToString());
@@ -636,10 +655,12 @@
 TEST_F(TransportClientSocketPoolTest, CancelRequestClearGroup) {
   TestCompletionCallback callback;
   ClientSocketHandle handle;
-  EXPECT_EQ(ERR_IO_PENDING,
-            handle.Init("a", params_, kDefaultPriority, SocketTag(),
-                        ClientSocketPool::RespectLimits::ENABLED,
-                        callback.callback(), &pool_, NetLogWithSource()));
+  EXPECT_EQ(
+      ERR_IO_PENDING,
+      handle.Init("a", params_, kDefaultPriority, SocketTag(),
+                  ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
+                  ClientSocketPool::ProxyAuthCallback(), &pool_,
+                  NetLogWithSource()));
   handle.Reset();
 }
 
@@ -649,14 +670,18 @@
   ClientSocketHandle handle2;
   TestCompletionCallback callback2;
 
-  EXPECT_EQ(ERR_IO_PENDING,
-            handle.Init("a", params_, kDefaultPriority, SocketTag(),
-                        ClientSocketPool::RespectLimits::ENABLED,
-                        callback.callback(), &pool_, NetLogWithSource()));
-  EXPECT_EQ(ERR_IO_PENDING,
-            handle2.Init("a", params_, kDefaultPriority, SocketTag(),
-                         ClientSocketPool::RespectLimits::ENABLED,
-                         callback2.callback(), &pool_, NetLogWithSource()));
+  EXPECT_EQ(
+      ERR_IO_PENDING,
+      handle.Init("a", params_, kDefaultPriority, SocketTag(),
+                  ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
+                  ClientSocketPool::ProxyAuthCallback(), &pool_,
+                  NetLogWithSource()));
+  EXPECT_EQ(
+      ERR_IO_PENDING,
+      handle2.Init("a", params_, kDefaultPriority, SocketTag(),
+                   ClientSocketPool::RespectLimits::ENABLED,
+                   callback2.callback(), ClientSocketPool::ProxyAuthCallback(),
+                   &pool_, NetLogWithSource()));
 
   handle.Reset();
 
@@ -669,18 +694,22 @@
       MockTransportClientSocketFactory::MOCK_PENDING_CLIENT_SOCKET);
   ClientSocketHandle handle;
   TestCompletionCallback callback;
-  EXPECT_EQ(ERR_IO_PENDING,
-            handle.Init("a", params_, kDefaultPriority, SocketTag(),
-                        ClientSocketPool::RespectLimits::ENABLED,
-                        callback.callback(), &pool_, NetLogWithSource()));
+  EXPECT_EQ(
+      ERR_IO_PENDING,
+      handle.Init("a", params_, kDefaultPriority, SocketTag(),
+                  ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
+                  ClientSocketPool::ProxyAuthCallback(), &pool_,
+                  NetLogWithSource()));
 
   handle.Reset();
 
   TestCompletionCallback callback2;
-  EXPECT_EQ(ERR_IO_PENDING,
-            handle.Init("a", params_, kDefaultPriority, SocketTag(),
-                        ClientSocketPool::RespectLimits::ENABLED,
-                        callback2.callback(), &pool_, NetLogWithSource()));
+  EXPECT_EQ(
+      ERR_IO_PENDING,
+      handle.Init("a", params_, kDefaultPriority, SocketTag(),
+                  ClientSocketPool::RespectLimits::ENABLED,
+                  callback2.callback(), ClientSocketPool::ProxyAuthCallback(),
+                  &pool_, NetLogWithSource()));
 
   host_resolver_->set_synchronous_mode(true);
   // At this point, handle has two ConnectingSockets out for it.  Due to the
@@ -790,7 +819,8 @@
                       OnHostResolutionCallback())));
       int rv = handle_->Init("a", dest, LOWEST, SocketTag(),
                              ClientSocketPool::RespectLimits::ENABLED,
-                             callback(), pool_, NetLogWithSource());
+                             callback(), ClientSocketPool::ProxyAuthCallback(),
+                             pool_, NetLogWithSource());
       EXPECT_THAT(rv, IsOk());
     }
   }
@@ -810,9 +840,10 @@
           base::MakeRefCounted<TransportSocketParams>(
               HostPortPair("www.google.com", 80), false,
               OnHostResolutionCallback())));
-  int rv = handle.Init("a", dest, LOWEST, SocketTag(),
-                       ClientSocketPool::RespectLimits::ENABLED,
-                       callback.callback(), &pool_, NetLogWithSource());
+  int rv = handle.Init(
+      "a", dest, LOWEST, SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
+      callback.callback(), ClientSocketPool::ProxyAuthCallback(), &pool_,
+      NetLogWithSource());
   ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
 
   // The callback is going to request "www.google.com". We want it to complete
@@ -875,9 +906,10 @@
 TEST_F(TransportClientSocketPoolTest, IdleSocketLoadTiming) {
   TestCompletionCallback callback;
   ClientSocketHandle handle;
-  int rv = handle.Init("a", params_, LOW, SocketTag(),
-                       ClientSocketPool::RespectLimits::ENABLED,
-                       callback.callback(), &pool_, NetLogWithSource());
+  int rv = handle.Init(
+      "a", params_, LOW, SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
+      callback.callback(), ClientSocketPool::ProxyAuthCallback(), &pool_,
+      NetLogWithSource());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
   EXPECT_FALSE(handle.is_initialized());
   EXPECT_FALSE(handle.socket());
@@ -896,7 +928,8 @@
 
   rv = handle.Init("a", params_, LOW, SocketTag(),
                    ClientSocketPool::RespectLimits::ENABLED,
-                   callback.callback(), &pool_, NetLogWithSource());
+                   callback.callback(), ClientSocketPool::ProxyAuthCallback(),
+                   &pool_, NetLogWithSource());
   EXPECT_THAT(rv, IsOk());
   EXPECT_EQ(0, pool_.IdleSocketCount());
   TestLoadTimingInfoConnectedReused(handle);
@@ -905,9 +938,10 @@
 TEST_F(TransportClientSocketPoolTest, CloseIdleSocketsOnIPAddressChange) {
   TestCompletionCallback callback;
   ClientSocketHandle handle;
-  int rv = handle.Init("a", params_, LOW, SocketTag(),
-                       ClientSocketPool::RespectLimits::ENABLED,
-                       callback.callback(), &pool_, NetLogWithSource());
+  int rv = handle.Init(
+      "a", params_, LOW, SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
+      callback.callback(), ClientSocketPool::ProxyAuthCallback(), &pool_,
+      NetLogWithSource());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
   EXPECT_FALSE(handle.is_initialized());
   EXPECT_FALSE(handle.socket());
@@ -934,9 +968,10 @@
 TEST_F(TransportClientSocketPoolTest, CloseIdleSocketsOnSSLConfigChange) {
   TestCompletionCallback callback;
   ClientSocketHandle handle;
-  int rv = handle.Init("a", params_, LOW, SocketTag(),
-                       ClientSocketPool::RespectLimits::ENABLED,
-                       callback.callback(), &pool_, NetLogWithSource());
+  int rv = handle.Init(
+      "a", params_, LOW, SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
+      callback.callback(), ClientSocketPool::ProxyAuthCallback(), &pool_,
+      NetLogWithSource());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
   EXPECT_FALSE(handle.is_initialized());
   EXPECT_FALSE(handle.socket());
@@ -991,9 +1026,10 @@
 
     TestCompletionCallback callback;
     ClientSocketHandle handle;
-    int rv = handle.Init("b", params_, LOW, SocketTag(),
-                         ClientSocketPool::RespectLimits::ENABLED,
-                         callback.callback(), &pool_, NetLogWithSource());
+    int rv = handle.Init(
+        "b", params_, LOW, SocketTag(),
+        ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
+        ClientSocketPool::ProxyAuthCallback(), &pool_, NetLogWithSource());
     EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
     EXPECT_FALSE(handle.is_initialized());
     EXPECT_FALSE(handle.socket());
@@ -1034,9 +1070,10 @@
 
     TestCompletionCallback callback;
     ClientSocketHandle handle;
-    int rv = handle.Init("c", params_, LOW, SocketTag(),
-                         ClientSocketPool::RespectLimits::ENABLED,
-                         callback.callback(), &pool_, NetLogWithSource());
+    int rv = handle.Init(
+        "c", params_, LOW, SocketTag(),
+        ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
+        ClientSocketPool::ProxyAuthCallback(), &pool_, NetLogWithSource());
     EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
     EXPECT_FALSE(handle.is_initialized());
     EXPECT_FALSE(handle.socket());
@@ -1081,9 +1118,10 @@
 
   TestCompletionCallback callback;
   ClientSocketHandle handle;
-  int rv = handle.Init("b", params_, LOW, SocketTag(),
-                       ClientSocketPool::RespectLimits::ENABLED,
-                       callback.callback(), &pool_, NetLogWithSource());
+  int rv = handle.Init(
+      "b", params_, LOW, SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
+      callback.callback(), ClientSocketPool::ProxyAuthCallback(), &pool_,
+      NetLogWithSource());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
   EXPECT_FALSE(handle.is_initialized());
   EXPECT_FALSE(handle.socket());
@@ -1130,9 +1168,10 @@
 
   TestCompletionCallback callback;
   ClientSocketHandle handle;
-  int rv = handle.Init("b", params_, LOW, SocketTag(),
-                       ClientSocketPool::RespectLimits::ENABLED,
-                       callback.callback(), &pool_, NetLogWithSource());
+  int rv = handle.Init(
+      "b", params_, LOW, SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
+      callback.callback(), ClientSocketPool::ProxyAuthCallback(), &pool_,
+      NetLogWithSource());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
   EXPECT_FALSE(handle.is_initialized());
   EXPECT_FALSE(handle.socket());
@@ -1191,9 +1230,10 @@
     socket_factory.AddSocketDataProvider(data.data_provider());
     ClientSocketHandle handle;
     TestCompletionCallback callback;
-    int rv = handle.Init("a", socks_params, LOW, SocketTag(),
-                         ClientSocketPool::RespectLimits::ENABLED,
-                         callback.callback(), &pool, NetLogWithSource());
+    int rv = handle.Init(
+        "a", socks_params, LOW, SocketTag(),
+        ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
+        ClientSocketPool::ProxyAuthCallback(), &pool, NetLogWithSource());
     EXPECT_THAT(callback.GetResult(rv), IsOk());
     EXPECT_TRUE(handle.is_initialized());
     EXPECT_TRUE(handle.socket());
@@ -1240,9 +1280,10 @@
           base::MakeRefCounted<TransportSocketParams>(
               test_server.host_port_pair(), false, OnHostResolutionCallback()));
   TestCompletionCallback callback;
-  int rv = handle.Init("a", params, LOW, tag1,
-                       ClientSocketPool::RespectLimits::ENABLED,
-                       callback.callback(), &pool, NetLogWithSource());
+  int rv = handle.Init(
+      "a", params, LOW, tag1, ClientSocketPool::RespectLimits::ENABLED,
+      callback.callback(), ClientSocketPool::ProxyAuthCallback(), &pool,
+      NetLogWithSource());
   EXPECT_THAT(callback.GetResult(rv), IsOk());
   EXPECT_TRUE(handle.socket());
   EXPECT_TRUE(handle.socket()->IsConnected());
@@ -1254,7 +1295,8 @@
   old_traffic = GetTaggedBytes(tag_val2);
   rv = handle.Init("a", params, LOW, tag2,
                    ClientSocketPool::RespectLimits::ENABLED,
-                   callback.callback(), &pool, NetLogWithSource());
+                   callback.callback(), ClientSocketPool::ProxyAuthCallback(),
+                   &pool, NetLogWithSource());
   EXPECT_THAT(rv, IsOk());
   EXPECT_TRUE(handle.socket());
   EXPECT_TRUE(handle.socket()->IsConnected());
@@ -1276,13 +1318,15 @@
   TestCompletionCallback callback2;
   rv = handle.Init("a", params, LOW, tag1,
                    ClientSocketPool::RespectLimits::ENABLED,
-                   callback2.callback(), &pool, NetLogWithSource());
+                   callback2.callback(), ClientSocketPool::ProxyAuthCallback(),
+                   &pool, NetLogWithSource());
   EXPECT_TRUE(rv == OK || rv == ERR_IO_PENDING) << "Result: " << rv;
   // Abort and request socket with |tag2|.
   handle.Reset();
   rv = handle.Init("a", params, LOW, tag2,
                    ClientSocketPool::RespectLimits::ENABLED,
-                   callback.callback(), &pool, NetLogWithSource());
+                   callback.callback(), ClientSocketPool::ProxyAuthCallback(),
+                   &pool, NetLogWithSource());
   EXPECT_THAT(callback.GetResult(rv), IsOk());
   EXPECT_TRUE(handle.socket());
   EXPECT_TRUE(handle.socket()->IsConnected());
@@ -1300,7 +1344,8 @@
   // TODO(pauljensen): remove when crbug.com/800731 fixed.
   rv = handle.Init("a", params, LOW, tag1,
                    ClientSocketPool::RespectLimits::ENABLED,
-                   callback.callback(), &pool, NetLogWithSource());
+                   callback.callback(), ClientSocketPool::ProxyAuthCallback(),
+                   &pool, NetLogWithSource());
   EXPECT_THAT(rv, IsOk());
   // Disconnect socket to prevent reuse.
   handle.socket()->Disconnect();
@@ -1312,11 +1357,13 @@
   TestCompletionCallback callback_high_pri;
   rv = handle.Init("a", params, LOW, tag1,
                    ClientSocketPool::RespectLimits::ENABLED,
-                   callback.callback(), &pool, NetLogWithSource());
+                   callback.callback(), ClientSocketPool::ProxyAuthCallback(),
+                   &pool, NetLogWithSource());
   EXPECT_TRUE(rv == OK || rv == ERR_IO_PENDING) << "Result: " << rv;
   int rv_high_pri = handle_high_pri.Init(
       "a", params, HIGHEST, tag2, ClientSocketPool::RespectLimits::ENABLED,
-      callback_high_pri.callback(), &pool, NetLogWithSource());
+      callback_high_pri.callback(), ClientSocketPool::ProxyAuthCallback(),
+      &pool, NetLogWithSource());
   EXPECT_THAT(callback_high_pri.GetResult(rv_high_pri), IsOk());
   EXPECT_TRUE(handle_high_pri.socket());
   EXPECT_TRUE(handle_high_pri.socket()->IsConnected());
@@ -1370,9 +1417,10 @@
   data_sync.data_provider()->set_connect_data(MockConnect(SYNCHRONOUS, OK));
   socket_factory.AddSocketDataProvider(data_sync.data_provider());
   ClientSocketHandle handle;
-  int rv = handle.Init("a", socks_params, LOW, tag1,
-                       ClientSocketPool::RespectLimits::ENABLED,
-                       CompletionOnceCallback(), &pool, NetLogWithSource());
+  int rv = handle.Init(
+      "a", socks_params, LOW, tag1, ClientSocketPool::RespectLimits::ENABLED,
+      CompletionOnceCallback(), ClientSocketPool::ProxyAuthCallback(), &pool,
+      NetLogWithSource());
   EXPECT_THAT(rv, IsOk());
   EXPECT_TRUE(handle.is_initialized());
   EXPECT_TRUE(handle.socket());
@@ -1383,9 +1431,10 @@
   // Test socket is tagged when reused synchronously.
   StreamSocket* socket = handle.socket();
   handle.Reset();
-  rv = handle.Init("a", socks_params, LOW, tag2,
-                   ClientSocketPool::RespectLimits::ENABLED,
-                   CompletionOnceCallback(), &pool, NetLogWithSource());
+  rv = handle.Init(
+      "a", socks_params, LOW, tag2, ClientSocketPool::RespectLimits::ENABLED,
+      CompletionOnceCallback(), ClientSocketPool::ProxyAuthCallback(), &pool,
+      NetLogWithSource());
   EXPECT_THAT(rv, IsOk());
   EXPECT_TRUE(handle.socket());
   EXPECT_TRUE(handle.socket()->IsConnected());
@@ -1400,7 +1449,8 @@
   TestCompletionCallback callback;
   rv = handle.Init("a", socks_params, LOW, tag1,
                    ClientSocketPool::RespectLimits::ENABLED,
-                   callback.callback(), &pool, NetLogWithSource());
+                   callback.callback(), ClientSocketPool::ProxyAuthCallback(),
+                   &pool, NetLogWithSource());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
   EXPECT_THAT(callback.WaitForResult(), IsOk());
   EXPECT_TRUE(handle.is_initialized());
@@ -1412,9 +1462,10 @@
   // Test socket is tagged when reused after being created asynchronously.
   socket = handle.socket();
   handle.Reset();
-  rv = handle.Init("a", socks_params, LOW, tag2,
-                   ClientSocketPool::RespectLimits::ENABLED,
-                   CompletionOnceCallback(), &pool, NetLogWithSource());
+  rv = handle.Init(
+      "a", socks_params, LOW, tag2, ClientSocketPool::RespectLimits::ENABLED,
+      CompletionOnceCallback(), ClientSocketPool::ProxyAuthCallback(), &pool,
+      NetLogWithSource());
   EXPECT_THAT(rv, IsOk());
   EXPECT_TRUE(handle.socket());
   EXPECT_TRUE(handle.socket()->IsConnected());
@@ -1463,7 +1514,8 @@
       TransportClientSocketPool::SocketParams::CreateFromSSLSocketParams(
           params),
       LOW, tag1, ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
-      &pool_for_real_sockets_, NetLogWithSource());
+      ClientSocketPool::ProxyAuthCallback(), &pool_for_real_sockets_,
+      NetLogWithSource());
   EXPECT_THAT(callback.GetResult(rv), IsOk());
   EXPECT_TRUE(handle.socket());
   EXPECT_TRUE(handle.socket()->IsConnected());
@@ -1479,7 +1531,8 @@
       TransportClientSocketPool::SocketParams::CreateFromSSLSocketParams(
           params),
       LOW, tag2, ClientSocketPool::RespectLimits::ENABLED, callback2.callback(),
-      &pool_for_real_sockets_, NetLogWithSource());
+      ClientSocketPool::ProxyAuthCallback(), &pool_for_real_sockets_,
+      NetLogWithSource());
   EXPECT_THAT(rv, IsOk());
   EXPECT_TRUE(handle.socket());
   EXPECT_TRUE(handle.socket()->IsConnected());
@@ -1537,7 +1590,8 @@
       TransportClientSocketPool::SocketParams::CreateFromSSLSocketParams(
           params),
       LOW, tag1, ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
-      &pool_for_real_sockets_, NetLogWithSource());
+      ClientSocketPool::ProxyAuthCallback(), &pool_for_real_sockets_,
+      NetLogWithSource());
   EXPECT_TRUE(rv == OK || rv == ERR_IO_PENDING) << "Result: " << rv;
   // Abort and request socket with |tag2|.
   handle.Reset();
@@ -1547,7 +1601,8 @@
       TransportClientSocketPool::SocketParams::CreateFromSSLSocketParams(
           params),
       LOW, tag2, ClientSocketPool::RespectLimits::ENABLED, callback2.callback(),
-      &pool_for_real_sockets_, NetLogWithSource());
+      ClientSocketPool::ProxyAuthCallback(), &pool_for_real_sockets_,
+      NetLogWithSource());
   EXPECT_THAT(callback2.GetResult(rv), IsOk());
   EXPECT_TRUE(handle.socket());
   EXPECT_TRUE(handle.socket()->IsConnected());
@@ -1606,8 +1661,9 @@
                          TransportClientSocketPool::SocketParams::
                              CreateFromTransportSocketParams(tcp_params),
                          LOW, tag1, ClientSocketPool::RespectLimits::ENABLED,
-                         callback.callback(), &pool_for_real_sockets_,
-                         NetLogWithSource());
+                         callback.callback(),
+                         ClientSocketPool::ProxyAuthCallback(),
+                         &pool_for_real_sockets_, NetLogWithSource());
     EXPECT_THAT(callback.GetResult(rv), IsOk());
     EXPECT_TRUE(tcp_handle.socket());
     EXPECT_TRUE(tcp_handle.socket()->IsConnected());
@@ -1619,14 +1675,16 @@
       TransportClientSocketPool::SocketParams::CreateFromSSLSocketParams(
           params),
       LOW, tag1, ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
-      &pool_for_real_sockets_, NetLogWithSource());
+      ClientSocketPool::ProxyAuthCallback(), &pool_for_real_sockets_,
+      NetLogWithSource());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
   rv = handle.Init(
       kGroupName,
       TransportClientSocketPool::SocketParams::CreateFromSSLSocketParams(
           params),
       LOW, tag2, ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
-      &pool_for_real_sockets_, NetLogWithSource());
+      ClientSocketPool::ProxyAuthCallback(), &pool_for_real_sockets_,
+      NetLogWithSource());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
   // Cancel first request.
   handle_to_be_canceled.Reset();
diff --git a/net/socket/websocket_transport_client_socket_pool.cc b/net/socket/websocket_transport_client_socket_pool.cc
index 7463cd6..454960c 100644
--- a/net/socket/websocket_transport_client_socket_pool.cc
+++ b/net/socket/websocket_transport_client_socket_pool.cc
@@ -114,6 +114,7 @@
     RespectLimits respect_limits,
     ClientSocketHandle* handle,
     CompletionOnceCallback callback,
+    const ProxyAuthCallback& proxy_auth_callback,
     const NetLogWithSource& request_net_log) {
   DCHECK(params);
   CHECK(!callback.is_null());
@@ -130,7 +131,8 @@
       respect_limits == ClientSocketPool::RespectLimits::ENABLED) {
     request_net_log.AddEvent(NetLogEventType::SOCKET_POOL_STALLED_MAX_SOCKETS);
     stalled_request_queue_.emplace_back(casted_params, priority, handle,
-                                        std::move(callback), request_net_log);
+                                        std::move(callback),
+                                        proxy_auth_callback, request_net_log);
     auto iterator = stalled_request_queue_.end();
     --iterator;
     DCHECK_EQ(handle, iterator->handle);
@@ -469,7 +471,7 @@
                       // Stalled requests can't have |respect_limits|
                       // DISABLED.
                       RespectLimits::ENABLED, request.handle, copyable_callback,
-                      request.net_log);
+                      request.proxy_auth_callback, request.net_log);
 
     // ActivateStalledRequest() never returns synchronously, so it is never
     // called re-entrantly.
@@ -525,11 +527,13 @@
     RequestPriority priority,
     ClientSocketHandle* handle,
     CompletionOnceCallback callback,
+    const ProxyAuthCallback& proxy_auth_callback,
     const NetLogWithSource& net_log)
     : params(params),
       priority(priority),
       handle(handle),
       callback(std::move(callback)),
+      proxy_auth_callback(proxy_auth_callback),
       net_log(net_log) {}
 
 WebSocketTransportClientSocketPool::StalledRequest::StalledRequest(
diff --git a/net/socket/websocket_transport_client_socket_pool.h b/net/socket/websocket_transport_client_socket_pool.h
index 6c52b2b..4f9598a 100644
--- a/net/socket/websocket_transport_client_socket_pool.h
+++ b/net/socket/websocket_transport_client_socket_pool.h
@@ -80,6 +80,7 @@
                     RespectLimits respect_limits,
                     ClientSocketHandle* handle,
                     CompletionOnceCallback callback,
+                    const ProxyAuthCallback& proxy_auth_callback,
                     const NetLogWithSource& net_log) override;
   void RequestSockets(const std::string& group_name,
                       const void* params,
@@ -149,6 +150,7 @@
                    RequestPriority priority,
                    ClientSocketHandle* handle,
                    CompletionOnceCallback callback,
+                   const ProxyAuthCallback& proxy_auth_callback,
                    const NetLogWithSource& net_log);
     StalledRequest(StalledRequest&& other);
     ~StalledRequest();
@@ -157,6 +159,7 @@
     const RequestPriority priority;
     ClientSocketHandle* const handle;
     CompletionOnceCallback callback;
+    ProxyAuthCallback proxy_auth_callback;
     const NetLogWithSource net_log;
   };
 
diff --git a/net/socket/websocket_transport_client_socket_pool_unittest.cc b/net/socket/websocket_transport_client_socket_pool_unittest.cc
index 6d6525a6..13d6678 100644
--- a/net/socket/websocket_transport_client_socket_pool_unittest.cc
+++ b/net/socket/websocket_transport_client_socket_pool_unittest.cc
@@ -146,9 +146,10 @@
 TEST_F(WebSocketTransportClientSocketPoolTest, Basic) {
   TestCompletionCallback callback;
   ClientSocketHandle handle;
-  int rv = handle.Init("a", params_, LOW, SocketTag(),
-                       ClientSocketPool::RespectLimits::ENABLED,
-                       callback.callback(), &pool_, NetLogWithSource());
+  int rv = handle.Init(
+      "a", params_, LOW, SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
+      callback.callback(), ClientSocketPool::ProxyAuthCallback(), &pool_,
+      NetLogWithSource());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
   EXPECT_FALSE(handle.is_initialized());
   EXPECT_FALSE(handle.socket());
@@ -166,10 +167,12 @@
     RequestPriority priority = static_cast<RequestPriority>(i);
     TestCompletionCallback callback;
     ClientSocketHandle handle;
-    EXPECT_EQ(ERR_IO_PENDING,
-              handle.Init("a", params_, priority, SocketTag(),
-                          ClientSocketPool::RespectLimits::ENABLED,
-                          callback.callback(), &pool_, NetLogWithSource()));
+    EXPECT_EQ(
+        ERR_IO_PENDING,
+        handle.Init("a", params_, priority, SocketTag(),
+                    ClientSocketPool::RespectLimits::ENABLED,
+                    callback.callback(), ClientSocketPool::ProxyAuthCallback(),
+                    &pool_, NetLogWithSource()));
     EXPECT_EQ(priority, host_resolver_->last_request_priority());
   }
 }
@@ -183,10 +186,12 @@
       TransportClientSocketPool::SocketParams::CreateFromTransportSocketParams(
           base::MakeRefCounted<TransportSocketParams>(
               host_port_pair, false, OnHostResolutionCallback())));
-  EXPECT_EQ(ERR_IO_PENDING,
-            handle.Init("a", dest, kDefaultPriority, SocketTag(),
-                        ClientSocketPool::RespectLimits::ENABLED,
-                        callback.callback(), &pool_, NetLogWithSource()));
+  EXPECT_EQ(
+      ERR_IO_PENDING,
+      handle.Init("a", dest, kDefaultPriority, SocketTag(),
+                  ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
+                  ClientSocketPool::ProxyAuthCallback(), &pool_,
+                  NetLogWithSource()));
   EXPECT_THAT(callback.WaitForResult(), IsError(ERR_NAME_NOT_RESOLVED));
 }
 
@@ -195,18 +200,22 @@
       MockTransportClientSocketFactory::MOCK_FAILING_CLIENT_SOCKET);
   TestCompletionCallback callback;
   ClientSocketHandle handle;
-  EXPECT_EQ(ERR_IO_PENDING,
-            handle.Init("a", params_, kDefaultPriority, SocketTag(),
-                        ClientSocketPool::RespectLimits::ENABLED,
-                        callback.callback(), &pool_, NetLogWithSource()));
+  EXPECT_EQ(
+      ERR_IO_PENDING,
+      handle.Init("a", params_, kDefaultPriority, SocketTag(),
+                  ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
+                  ClientSocketPool::ProxyAuthCallback(), &pool_,
+                  NetLogWithSource()));
   EXPECT_THAT(callback.WaitForResult(), IsError(ERR_CONNECTION_FAILED));
 
   // Make the host resolutions complete synchronously this time.
   host_resolver_->set_synchronous_mode(true);
-  EXPECT_EQ(ERR_CONNECTION_FAILED,
-            handle.Init("a", params_, kDefaultPriority, SocketTag(),
-                        ClientSocketPool::RespectLimits::ENABLED,
-                        callback.callback(), &pool_, NetLogWithSource()));
+  EXPECT_EQ(
+      ERR_CONNECTION_FAILED,
+      handle.Init("a", params_, kDefaultPriority, SocketTag(),
+                  ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
+                  ClientSocketPool::ProxyAuthCallback(), &pool_,
+                  NetLogWithSource()));
 }
 
 TEST_F(WebSocketTransportClientSocketPoolTest, PendingRequestsFinishFifo) {
@@ -280,10 +289,12 @@
 TEST_F(WebSocketTransportClientSocketPoolTest, CancelRequestClearGroup) {
   TestCompletionCallback callback;
   ClientSocketHandle handle;
-  EXPECT_EQ(ERR_IO_PENDING,
-            handle.Init("a", params_, kDefaultPriority, SocketTag(),
-                        ClientSocketPool::RespectLimits::ENABLED,
-                        callback.callback(), &pool_, NetLogWithSource()));
+  EXPECT_EQ(
+      ERR_IO_PENDING,
+      handle.Init("a", params_, kDefaultPriority, SocketTag(),
+                  ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
+                  ClientSocketPool::ProxyAuthCallback(), &pool_,
+                  NetLogWithSource()));
   handle.Reset();
 }
 
@@ -293,14 +304,18 @@
   ClientSocketHandle handle2;
   TestCompletionCallback callback2;
 
-  EXPECT_EQ(ERR_IO_PENDING,
-            handle.Init("a", params_, kDefaultPriority, SocketTag(),
-                        ClientSocketPool::RespectLimits::ENABLED,
-                        callback.callback(), &pool_, NetLogWithSource()));
-  EXPECT_EQ(ERR_IO_PENDING,
-            handle2.Init("a", params_, kDefaultPriority, SocketTag(),
-                         ClientSocketPool::RespectLimits::ENABLED,
-                         callback2.callback(), &pool_, NetLogWithSource()));
+  EXPECT_EQ(
+      ERR_IO_PENDING,
+      handle.Init("a", params_, kDefaultPriority, SocketTag(),
+                  ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
+                  ClientSocketPool::ProxyAuthCallback(), &pool_,
+                  NetLogWithSource()));
+  EXPECT_EQ(
+      ERR_IO_PENDING,
+      handle2.Init("a", params_, kDefaultPriority, SocketTag(),
+                   ClientSocketPool::RespectLimits::ENABLED,
+                   callback2.callback(), ClientSocketPool::ProxyAuthCallback(),
+                   &pool_, NetLogWithSource()));
 
   handle.Reset();
 
@@ -313,18 +328,22 @@
       MockTransportClientSocketFactory::MOCK_PENDING_CLIENT_SOCKET);
   ClientSocketHandle handle;
   TestCompletionCallback callback;
-  EXPECT_EQ(ERR_IO_PENDING,
-            handle.Init("a", params_, kDefaultPriority, SocketTag(),
-                        ClientSocketPool::RespectLimits::ENABLED,
-                        callback.callback(), &pool_, NetLogWithSource()));
+  EXPECT_EQ(
+      ERR_IO_PENDING,
+      handle.Init("a", params_, kDefaultPriority, SocketTag(),
+                  ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
+                  ClientSocketPool::ProxyAuthCallback(), &pool_,
+                  NetLogWithSource()));
 
   handle.Reset();
 
   TestCompletionCallback callback2;
-  EXPECT_EQ(ERR_IO_PENDING,
-            handle.Init("a", params_, kDefaultPriority, SocketTag(),
-                        ClientSocketPool::RespectLimits::ENABLED,
-                        callback2.callback(), &pool_, NetLogWithSource()));
+  EXPECT_EQ(
+      ERR_IO_PENDING,
+      handle.Init("a", params_, kDefaultPriority, SocketTag(),
+                  ClientSocketPool::RespectLimits::ENABLED,
+                  callback2.callback(), ClientSocketPool::ProxyAuthCallback(),
+                  &pool_, NetLogWithSource()));
 
   host_resolver_->set_synchronous_mode(true);
   // At this point, handle has two ConnectingSockets out for it.  Due to the
@@ -398,9 +417,10 @@
           base::MakeRefCounted<TransportSocketParams>(
               HostPortPair("www.google.com", 80), false,
               OnHostResolutionCallback())));
-  int rv = handle->Init("a", dest, LOWEST, SocketTag(),
-                        ClientSocketPool::RespectLimits::ENABLED,
-                        nested_callback->callback(), pool, NetLogWithSource());
+  int rv = handle->Init(
+      "a", dest, LOWEST, SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
+      nested_callback->callback(), ClientSocketPool::ProxyAuthCallback(), pool,
+      NetLogWithSource());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
   if (ERR_IO_PENDING != rv)
     nested_callback->callback().Run(rv);
@@ -417,11 +437,11 @@
               HostPortPair("www.google.com", 80), false,
               OnHostResolutionCallback())));
   TestCompletionCallback second_result_callback;
-  int rv = handle.Init("a", dest, LOWEST, SocketTag(),
-                       ClientSocketPool::RespectLimits::ENABLED,
-                       base::Bind(&RequestSocketOnComplete, &handle, &pool_,
-                                  &second_result_callback),
-                       &pool_, NetLogWithSource());
+  int rv = handle.Init(
+      "a", dest, LOWEST, SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
+      base::BindOnce(&RequestSocketOnComplete, &handle, &pool_,
+                     &second_result_callback),
+      ClientSocketPool::ProxyAuthCallback(), &pool_, NetLogWithSource());
   ASSERT_THAT(rv, IsError(ERR_IO_PENDING));
   EXPECT_THAT(second_result_callback.WaitForResult(), IsOk());
 
@@ -492,9 +512,10 @@
 TEST_F(WebSocketTransportClientSocketPoolTest, LockReleasedOnHandleDelete) {
   TestCompletionCallback callback;
   std::unique_ptr<ClientSocketHandle> handle(new ClientSocketHandle);
-  int rv = handle->Init("a", params_, LOW, SocketTag(),
-                        ClientSocketPool::RespectLimits::ENABLED,
-                        callback.callback(), &pool_, NetLogWithSource());
+  int rv = handle->Init(
+      "a", params_, LOW, SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
+      callback.callback(), ClientSocketPool::ProxyAuthCallback(), &pool_,
+      NetLogWithSource());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
 
   EXPECT_THAT(StartRequest("a", kDefaultPriority), IsError(ERR_IO_PENDING));
@@ -566,9 +587,10 @@
 
   TestCompletionCallback callback;
   ClientSocketHandle handle;
-  int rv = handle.Init("a", params_, LOW, SocketTag(),
-                       ClientSocketPool::RespectLimits::ENABLED,
-                       callback.callback(), &pool, NetLogWithSource());
+  int rv = handle.Init(
+      "a", params_, LOW, SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
+      callback.callback(), ClientSocketPool::ProxyAuthCallback(), &pool,
+      NetLogWithSource());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
   EXPECT_FALSE(handle.is_initialized());
   EXPECT_FALSE(handle.socket());
@@ -614,9 +636,10 @@
 
   TestCompletionCallback callback;
   ClientSocketHandle handle;
-  int rv = handle.Init("a", params_, LOW, SocketTag(),
-                       ClientSocketPool::RespectLimits::ENABLED,
-                       callback.callback(), &pool, NetLogWithSource());
+  int rv = handle.Init(
+      "a", params_, LOW, SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
+      callback.callback(), ClientSocketPool::ProxyAuthCallback(), &pool,
+      NetLogWithSource());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
   EXPECT_FALSE(handle.is_initialized());
   EXPECT_FALSE(handle.socket());
@@ -652,9 +675,10 @@
 
   TestCompletionCallback callback;
   ClientSocketHandle handle;
-  int rv = handle.Init("a", params_, LOW, SocketTag(),
-                       ClientSocketPool::RespectLimits::ENABLED,
-                       callback.callback(), &pool, NetLogWithSource());
+  int rv = handle.Init(
+      "a", params_, LOW, SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
+      callback.callback(), ClientSocketPool::ProxyAuthCallback(), &pool,
+      NetLogWithSource());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
   EXPECT_FALSE(handle.is_initialized());
   EXPECT_FALSE(handle.socket());
@@ -688,9 +712,10 @@
 
   TestCompletionCallback callback;
   ClientSocketHandle handle;
-  int rv = handle.Init("a", params_, LOW, SocketTag(),
-                       ClientSocketPool::RespectLimits::ENABLED,
-                       callback.callback(), &pool, NetLogWithSource());
+  int rv = handle.Init(
+      "a", params_, LOW, SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
+      callback.callback(), ClientSocketPool::ProxyAuthCallback(), &pool,
+      NetLogWithSource());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
   EXPECT_FALSE(handle.is_initialized());
   EXPECT_FALSE(handle.socket());
@@ -735,9 +760,10 @@
   host_resolver_->set_synchronous_mode(true);
   TestCompletionCallback callback;
   ClientSocketHandle handle;
-  int rv = handle.Init("a", params_, LOW, SocketTag(),
-                       ClientSocketPool::RespectLimits::ENABLED,
-                       callback.callback(), &pool, NetLogWithSource());
+  int rv = handle.Init(
+      "a", params_, LOW, SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
+      callback.callback(), ClientSocketPool::ProxyAuthCallback(), &pool,
+      NetLogWithSource());
   EXPECT_THAT(rv, IsOk());
   ASSERT_TRUE(handle.socket());
 
@@ -777,9 +803,10 @@
 
   TestCompletionCallback callback;
   ClientSocketHandle handle;
-  int rv = handle.Init("a", params_, LOW, SocketTag(),
-                       ClientSocketPool::RespectLimits::ENABLED,
-                       callback.callback(), &pool, NetLogWithSource());
+  int rv = handle.Init(
+      "a", params_, LOW, SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
+      callback.callback(), ClientSocketPool::ProxyAuthCallback(), &pool,
+      NetLogWithSource());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
   EXPECT_FALSE(handle.socket());
 
@@ -819,9 +846,10 @@
 
   TestCompletionCallback callback;
   ClientSocketHandle handle;
-  int rv = handle.Init("a", params_, LOW, SocketTag(),
-                       ClientSocketPool::RespectLimits::ENABLED,
-                       callback.callback(), &pool, NetLogWithSource());
+  int rv = handle.Init(
+      "a", params_, LOW, SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
+      callback.callback(), ClientSocketPool::ProxyAuthCallback(), &pool,
+      NetLogWithSource());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
   ASSERT_FALSE(handle.socket());
 
@@ -877,9 +905,10 @@
   TestCompletionCallback callback;
   ClientSocketHandle handle;
   base::TimeTicks start(base::TimeTicks::Now());
-  int rv = handle.Init("a", params_, LOW, SocketTag(),
-                       ClientSocketPool::RespectLimits::ENABLED,
-                       callback.callback(), &pool, NetLogWithSource());
+  int rv = handle.Init(
+      "a", params_, LOW, SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
+      callback.callback(), ClientSocketPool::ProxyAuthCallback(), &pool,
+      NetLogWithSource());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
 
   EXPECT_THAT(callback.WaitForResult(), IsError(ERR_CONNECTION_FAILED));
@@ -921,9 +950,10 @@
   TestCompletionCallback callback;
   ClientSocketHandle handle;
 
-  int rv = handle.Init("a", params_, LOW, SocketTag(),
-                       ClientSocketPool::RespectLimits::ENABLED,
-                       callback.callback(), &pool, NetLogWithSource());
+  int rv = handle.Init(
+      "a", params_, LOW, SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
+      callback.callback(), ClientSocketPool::ProxyAuthCallback(), &pool,
+      NetLogWithSource());
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
 
   EXPECT_THAT(callback.WaitForResult(), IsError(ERR_TIMED_OUT));
diff --git a/net/spdy/spdy_session_unittest.cc b/net/spdy/spdy_session_unittest.cc
index f63490b5..3b13c99 100644
--- a/net/spdy/spdy_session_unittest.cc
+++ b/net/spdy/spdy_session_unittest.cc
@@ -3556,7 +3556,9 @@
                                   CreateFromTransportSocketParams(params2),
                               DEFAULT_PRIORITY, SocketTag(),
                               ClientSocketPool::RespectLimits::ENABLED,
-                              callback2.callback(), pool, NetLogWithSource()));
+                              callback2.callback(),
+                              ClientSocketPool::ProxyAuthCallback(), pool,
+                              NetLogWithSource()));
   EXPECT_TRUE(pool->IsStalled());
 
   // The socket pool should close the connection asynchronously and establish a
@@ -3638,7 +3640,9 @@
                                   CreateFromTransportSocketParams(params3),
                               DEFAULT_PRIORITY, SocketTag(),
                               ClientSocketPool::RespectLimits::ENABLED,
-                              callback3.callback(), pool, NetLogWithSource()));
+                              callback3.callback(),
+                              ClientSocketPool::ProxyAuthCallback(), pool,
+                              NetLogWithSource()));
   EXPECT_TRUE(pool->IsStalled());
 
   // The socket pool should close the connection asynchronously and establish a
@@ -3718,7 +3722,9 @@
                                   CreateFromTransportSocketParams(params2),
                               DEFAULT_PRIORITY, SocketTag(),
                               ClientSocketPool::RespectLimits::ENABLED,
-                              callback2.callback(), pool, NetLogWithSource()));
+                              callback2.callback(),
+                              ClientSocketPool::ProxyAuthCallback(), pool,
+                              NetLogWithSource()));
   EXPECT_TRUE(pool->IsStalled());
 
   // Running the message loop should cause the socket pool to ask the SPDY
diff --git a/net/spdy/spdy_stream.cc b/net/spdy/spdy_stream.cc
index ccb43198..f871d64 100644
--- a/net/spdy/spdy_stream.cc
+++ b/net/spdy/spdy_stream.cc
@@ -106,7 +106,6 @@
       request_time_(base::Time::Now()),
       response_state_(READY_FOR_HEADERS),
       io_state_(STATE_IDLE),
-      response_status_(OK),
       net_log_(net_log),
       raw_received_bytes_(0),
       raw_sent_bytes_(0),
@@ -686,7 +685,6 @@
       status = OK;
     }
   }
-  response_status_ = status;
   Delegate* delegate = delegate_;
   delegate_ = NULL;
   if (delegate)
diff --git a/net/spdy/spdy_stream.h b/net/spdy/spdy_stream.h
index 0080022..2f591751 100644
--- a/net/spdy/spdy_stream.h
+++ b/net/spdy/spdy_stream.h
@@ -370,8 +370,6 @@
   // yet.
   bool IsReservedRemote() const;
 
-  int response_status() const { return response_status_; }
-
   void AddRawReceivedBytes(size_t received_bytes);
   void AddRawSentBytes(size_t sent_bytes);
 
@@ -512,10 +510,6 @@
 
   State io_state_;
 
-  // Since we buffer the response, we also buffer the response status.
-  // Not valid until the stream is closed.
-  int response_status_;
-
   NetLogWithSource net_log_;
 
   base::TimeTicks send_time_;
diff --git a/net/spdy/spdy_test_util_common.cc b/net/spdy/spdy_test_util_common.cc
index e4ea0a5..dc60022 100644
--- a/net/spdy/spdy_test_util_common.cc
+++ b/net/spdy/spdy_test_util_common.cc
@@ -503,7 +503,7 @@
       TransportClientSocketPool::SocketParams::CreateFromSSLSocketParams(
           ssl_params),
       MEDIUM, key.socket_tag(), ClientSocketPool::RespectLimits::ENABLED,
-      callback.callback(),
+      callback.callback(), ClientSocketPool::ProxyAuthCallback(),
       http_session->GetTransportSocketPool(
           HttpNetworkSession::NORMAL_SOCKET_POOL),
       net_log);
diff --git a/net/third_party/quic/core/crypto/transport_parameters.h b/net/third_party/quic/core/crypto/transport_parameters.h
index da4379e..cc5f4017 100644
--- a/net/third_party/quic/core/crypto/transport_parameters.h
+++ b/net/third_party/quic/core/crypto/transport_parameters.h
@@ -82,6 +82,7 @@
 // |perspective| indicates whether the input came from a client or a server.
 // This method returns true if the input was successfully parsed, and false if
 // it could not be parsed.
+// TODO(nharper): Write fuzz tests for this method.
 QUIC_EXPORT_PRIVATE bool ParseTransportParameters(const uint8_t* in,
                                                   size_t in_len,
                                                   Perspective perspective,
diff --git a/net/third_party/quic/core/frames/quic_retire_connection_id_frame.cc b/net/third_party/quic/core/frames/quic_retire_connection_id_frame.cc
index ebf252ca..936fd8fd 100644
--- a/net/third_party/quic/core/frames/quic_retire_connection_id_frame.cc
+++ b/net/third_party/quic/core/frames/quic_retire_connection_id_frame.cc
@@ -1,3 +1,7 @@
+// Copyright (c) 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
 #include "net/third_party/quic/core/frames/quic_retire_connection_id_frame.h"
 #include "net/third_party/quic/core/quic_constants.h"
 
diff --git a/net/third_party/quic/core/frames/quic_retire_connection_id_frame.h b/net/third_party/quic/core/frames/quic_retire_connection_id_frame.h
index bc3abbe5..6cc08736 100644
--- a/net/third_party/quic/core/frames/quic_retire_connection_id_frame.h
+++ b/net/third_party/quic/core/frames/quic_retire_connection_id_frame.h
@@ -1,3 +1,7 @@
+// Copyright (c) 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
 #ifndef NET_THIRD_PARTY_QUIC_CORE_FRAMES_QUIC_RETIRE_CONNECTION_ID_FRAME_H_
 #define NET_THIRD_PARTY_QUIC_CORE_FRAMES_QUIC_RETIRE_CONNECTION_ID_FRAME_H_
 
diff --git a/net/third_party/quic/core/http/end_to_end_test.cc b/net/third_party/quic/core/http/end_to_end_test.cc
index 97173edc..918155a 100644
--- a/net/third_party/quic/core/http/end_to_end_test.cc
+++ b/net/third_party/quic/core/http/end_to_end_test.cc
@@ -61,7 +61,6 @@
 #include "net/third_party/quic/tools/quic_server.h"
 #include "net/third_party/quic/tools/quic_simple_client_stream.h"
 #include "net/third_party/quic/tools/quic_simple_server_stream.h"
-#include "net/tools/epoll_server/epoll_server.h"
 
 using spdy::kV3LowestPriority;
 using spdy::SETTINGS_MAX_HEADER_LIST_SIZE;
@@ -458,8 +457,6 @@
       server_thread_->server()->SetPreSharedKey(pre_shared_key_server_);
     }
     server_thread_->Initialize();
-    server_address_ =
-        QuicSocketAddress(server_address_.host(), server_thread_->GetPort());
     QuicDispatcher* dispatcher =
         QuicServerPeer::GetDispatcher(server_thread_->server());
     QuicDispatcherPeer::UseWriter(dispatcher, server_writer_);
diff --git a/net/third_party/quic/core/http/http_encoder_test.cc b/net/third_party/quic/core/http/http_encoder_test.cc
index b1566cb..4fe38152f 100644
--- a/net/third_party/quic/core/http/http_encoder_test.cc
+++ b/net/third_party/quic/core/http/http_encoder_test.cc
@@ -91,7 +91,6 @@
   SettingsFrame settings;
   settings.values[3] = 2;
   settings.values[6] = 5;
-  // clang-format off
   char output[] = {
       // length
       0x06,
@@ -108,7 +107,6 @@
       // content
       0x05,
   };
-  // clang-format on
   std::unique_ptr<char[]> buffer;
   uint64_t length = encoder_.SerializeSettingsFrame(settings, &buffer);
   EXPECT_EQ(QUIC_ARRAYSIZE(output), length);
diff --git a/net/third_party/quic/core/http/quic_spdy_session_test.cc b/net/third_party/quic/core/http/quic_spdy_session_test.cc
index e08fffc1..1a3489f 100644
--- a/net/third_party/quic/core/http/quic_spdy_session_test.cc
+++ b/net/third_party/quic/core/http/quic_spdy_session_test.cc
@@ -1009,7 +1009,7 @@
   // Create and inject a STOP_SENDING frame. In GOOGLE QUIC, receiving a
   // RST_STREAM frame causes a two-way close. For IETF QUIC, RST_STREAM causes a
   // one-way close.
-  if (transport_version() == QUIC_VERSION_99) {
+  if (IsVersion99()) {
     // Only needed for version 99/IETF QUIC.
     QuicStopSendingFrame stop_sending(
         kInvalidControlFrameId, GetNthClientInitiatedBidirectionalId(0),
@@ -1241,7 +1241,7 @@
       .WillRepeatedly(Invoke(&session_, &TestSession::ClearControlFrame));
   if (!IsVersion99()) {
     // For version99 the call to OnStreamReset happens as a result of receiving
-    // the STOP SENDING, so set up the EXPECT there.
+    // the STOP_SENDING, so set up the EXPECT there.
     EXPECT_CALL(*connection_, OnStreamReset(stream->id(), _));
   }
   QuicRstStreamFrame rst_frame(kInvalidControlFrameId, stream->id(),
@@ -1250,7 +1250,7 @@
   // Create and inject a STOP_SENDING frame. In GOOGLE QUIC, receiving a
   // RST_STREAM frame causes a two-way close. For IETF QUIC, RST_STREAM causes a
   // one-way close.
-  if (transport_version() == QUIC_VERSION_99) {
+  if (IsVersion99()) {
     // Only needed for version 99/IETF QUIC.
     QuicStopSendingFrame stop_sending(
         kInvalidControlFrameId, stream->id(),
diff --git a/net/third_party/quic/core/qpack/offline/qpack_offline_decoder_bin.cc b/net/third_party/quic/core/qpack/offline/qpack_offline_decoder_bin.cc
index edc6d7db..ffc165d 100644
--- a/net/third_party/quic/core/qpack/offline/qpack_offline_decoder_bin.cc
+++ b/net/third_party/quic/core/qpack/offline/qpack_offline_decoder_bin.cc
@@ -7,23 +7,26 @@
 #include <cstddef>
 #include <iostream>
 
-#include "base/command_line.h"
+#include "net/third_party/quic/platform/api/quic_flags.h"
 #include "net/third_party/quic/platform/api/quic_logging.h"
 #include "net/third_party/quic/platform/api/quic_string_piece.h"
 
 int main(int argc, char* argv[]) {
-  base::CommandLine::Init(argc, argv);
+  const char* usage =
+      "Usage: qpack_offline_decoder input_filename expected_headers_filename "
+      "....";
+  std::vector<quic::QuicString> args =
+      quic::QuicParseCommandLineFlags(usage, argc, argv);
 
-  if (argc < 3 || argc % 2 != 1) {
-    QUIC_LOG(ERROR) << "Usage: " << argv[0]
-                    << " input_filename expected_headers_filename ...";
+  if (args.size() < 2 || args.size() % 2 != 0) {
+    quic::QuicPrintCommandLineFlagHelp(usage);
     return 1;
   }
 
-  int i;
-  for (i = 0; 2 * i + 1 < argc; ++i) {
-    const quic::QuicStringPiece input_filename(argv[2 * i + 1]);
-    const quic::QuicStringPiece expected_headers_filename(argv[2 * i + 2]);
+  size_t i;
+  for (i = 0; 2 * i < args.size(); ++i) {
+    const quic::QuicStringPiece input_filename(args[2 * i]);
+    const quic::QuicStringPiece expected_headers_filename(args[2 * i + 1]);
 
     // Every file represents a different connection,
     // therefore every file needs a fresh decoding context.
diff --git a/net/third_party/quic/core/quic_connection.cc b/net/third_party/quic/core/quic_connection.cc
index 3889542f..11542f7 100644
--- a/net/third_party/quic/core/quic_connection.cc
+++ b/net/third_party/quic/core/quic_connection.cc
@@ -14,9 +14,7 @@
 #include <set>
 #include <utility>
 
-#include "base/format_macros.h"
 #include "base/macros.h"
-#include "base/metrics/histogram_macros.h"
 #include "net/third_party/quic/core/crypto/crypto_protocol.h"
 #include "net/third_party/quic/core/crypto/quic_decrypter.h"
 #include "net/third_party/quic/core/crypto/quic_encrypter.h"
diff --git a/net/third_party/quic/core/quic_connection_test.cc b/net/third_party/quic/core/quic_connection_test.cc
index 8123fbb..9f90794 100644
--- a/net/third_party/quic/core/quic_connection_test.cc
+++ b/net/third_party/quic/core/quic_connection_test.cc
@@ -9,11 +9,7 @@
 #include <ostream>
 #include <utility>
 
-#include "base/bind.h"
-#include "base/callback.h"
 #include "base/macros.h"
-#include "net/base/net_errors.h"
-#include "net/test/gtest_util.h"
 #include "net/third_party/quic/core/congestion_control/loss_detection_interface.h"
 #include "net/third_party/quic/core/congestion_control/send_algorithm_interface.h"
 #include "net/third_party/quic/core/crypto/null_encrypter.h"
@@ -23,6 +19,7 @@
 #include "net/third_party/quic/core/quic_simple_buffer_allocator.h"
 #include "net/third_party/quic/core/quic_types.h"
 #include "net/third_party/quic/core/quic_utils.h"
+#include "net/third_party/quic/platform/api/quic_error_code_wrappers.h"
 #include "net/third_party/quic/platform/api/quic_expect_bug.h"
 #include "net/third_party/quic/platform/api/quic_flags.h"
 #include "net/third_party/quic/platform/api/quic_logging.h"
@@ -44,7 +41,6 @@
 #include "net/third_party/quic/test_tools/simple_data_producer.h"
 #include "net/third_party/quic/test_tools/simple_quic_framer.h"
 #include "net/third_party/quic/test_tools/simple_session_notifier.h"
-#include "testing/gmock_mutant.h"
 
 using testing::_;
 using testing::AnyNumber;
@@ -335,11 +331,10 @@
     }
     if (next_packet_too_large_) {
       next_packet_too_large_ = false;
-      return WriteResult(WRITE_STATUS_ERROR, net::ERR_MSG_TOO_BIG);
+      return WriteResult(WRITE_STATUS_ERROR, QUIC_EMSGSIZE);
     }
     if (always_get_packet_too_large_) {
-      LOG(ERROR) << "RETURNING TOO BIG";
-      return WriteResult(WRITE_STATUS_ERROR, net::ERR_MSG_TOO_BIG);
+      return WriteResult(WRITE_STATUS_ERROR, QUIC_EMSGSIZE);
     }
     if (IsWriteBlocked()) {
       return WriteResult(is_write_blocked_data_buffered_
diff --git a/net/third_party/quic/core/quic_control_frame_manager.cc b/net/third_party/quic/core/quic_control_frame_manager.cc
index 1218f1a..ecd6d04 100644
--- a/net/third_party/quic/core/quic_control_frame_manager.cc
+++ b/net/third_party/quic/core/quic_control_frame_manager.cc
@@ -67,13 +67,6 @@
       QuicFrame(new QuicBlockedFrame(++last_control_frame_id_, id)));
 }
 
-void QuicControlFrameManager::WriteOrBufferStopSending(uint16_t code,
-                                                       QuicStreamId stream_id) {
-  QUIC_DVLOG(1) << "Writing STOP_SENDING_FRAME";
-  WriteOrBufferQuicFrame(QuicFrame(
-      new QuicStopSendingFrame(++last_control_frame_id_, stream_id, code)));
-}
-
 void QuicControlFrameManager::WriteOrBufferStreamIdBlocked(QuicStreamId id) {
   QUIC_DVLOG(1) << "Writing STREAM_ID_BLOCKED Frame";
   QUIC_CODE_COUNT(stream_id_blocked_transmits);
@@ -88,6 +81,13 @@
       QuicFrame(QuicMaxStreamIdFrame(++last_control_frame_id_, id)));
 }
 
+void QuicControlFrameManager::WriteOrBufferStopSending(uint16_t code,
+                                                       QuicStreamId stream_id) {
+  QUIC_DVLOG(1) << "Writing STOP_SENDING_FRAME";
+  WriteOrBufferQuicFrame(QuicFrame(
+      new QuicStopSendingFrame(++last_control_frame_id_, stream_id, code)));
+}
+
 void QuicControlFrameManager::WritePing() {
   QUIC_DVLOG(1) << "Writing PING_FRAME";
   if (HasBufferedFrames()) {
diff --git a/net/third_party/quic/core/quic_epoll_alarm_factory.cc b/net/third_party/quic/core/quic_epoll_alarm_factory.cc
index e04e8dcd..a5285738 100644
--- a/net/third_party/quic/core/quic_epoll_alarm_factory.cc
+++ b/net/third_party/quic/core/quic_epoll_alarm_factory.cc
@@ -4,8 +4,6 @@
 
 #include "net/third_party/quic/core/quic_epoll_alarm_factory.h"
 
-#include "net/tools/epoll_server/epoll_server.h"
-
 namespace quic {
 
 namespace {
@@ -68,10 +66,9 @@
     QuicConnectionArena* arena) {
   if (arena != nullptr) {
     return arena->New<QuicEpollAlarm>(epoll_server_, std::move(delegate));
-  } else {
+  }
     return QuicArenaScopedPtr<QuicAlarm>(
         new QuicEpollAlarm(epoll_server_, std::move(delegate)));
-  }
 }
 
 }  // namespace quic
diff --git a/net/third_party/quic/core/quic_epoll_alarm_factory.h b/net/third_party/quic/core/quic_epoll_alarm_factory.h
index 6c95bbf..055bf46 100644
--- a/net/third_party/quic/core/quic_epoll_alarm_factory.h
+++ b/net/third_party/quic/core/quic_epoll_alarm_factory.h
@@ -10,13 +10,9 @@
 #include "net/third_party/quic/core/quic_one_block_arena.h"
 #include "net/third_party/quic/platform/api/quic_epoll.h"
 
-namespace quic {}  // namespace quic
-namespace net {
-class EpollServer;
-}  // namespace net
 namespace quic {
 
-// Creates alarms that use the supplied net::EpollServer for timing and firing.
+// Creates alarms that use the supplied EpollServer for timing and firing.
 class QuicEpollAlarmFactory : public QuicAlarmFactory {
  public:
   explicit QuicEpollAlarmFactory(QuicEpollServer* eps);
diff --git a/net/third_party/quic/core/quic_epoll_connection_helper.cc b/net/third_party/quic/core/quic_epoll_connection_helper.cc
index 248dba60..3d5b996b 100644
--- a/net/third_party/quic/core/quic_epoll_connection_helper.cc
+++ b/net/third_party/quic/core/quic_epoll_connection_helper.cc
@@ -9,7 +9,6 @@
 
 #include "net/third_party/quic/core/crypto/quic_random.h"
 #include "net/third_party/quic/platform/impl/quic_socket_utils.h"
-#include "net/tools/epoll_server/epoll_server.h"
 
 namespace quic {
 
diff --git a/net/third_party/quic/core/quic_epoll_connection_helper.h b/net/third_party/quic/core/quic_epoll_connection_helper.h
index 91c506e..55832aa6 100644
--- a/net/third_party/quic/core/quic_epoll_connection_helper.h
+++ b/net/third_party/quic/core/quic_epoll_connection_helper.h
@@ -11,7 +11,6 @@
 #include <sys/types.h>
 #include <set>
 
-#include "base/macros.h"
 #include "net/third_party/quic/core/quic_connection.h"
 #include "net/third_party/quic/core/quic_default_packet_writer.h"
 #include "net/third_party/quic/core/quic_packet_writer.h"
@@ -21,8 +20,8 @@
 #include "net/third_party/quic/platform/api/quic_epoll.h"
 #include "net/third_party/quic/platform/impl/quic_epoll_clock.h"
 
-namespace quic {}  // namespace quic
 namespace quic {
+
 class QuicRandom;
 
 using QuicStreamBufferAllocator = SimpleBufferAllocator;
@@ -43,8 +42,6 @@
   QuicBufferAllocator* GetStreamSendBufferAllocator() override;
 
  private:
-  friend class QuicConnectionPeer;
-
   const QuicEpollClock clock_;
   QuicRandom* random_generator_;
   // Set up allocators.  They take up minimal memory before use.
diff --git a/net/third_party/quic/core/quic_session.cc b/net/third_party/quic/core/quic_session.cc
index 9fd8fa3..3f5a0380 100644
--- a/net/third_party/quic/core/quic_session.cc
+++ b/net/third_party/quic/core/quic_session.cc
@@ -231,6 +231,7 @@
       static_cast<quic::QuicRstStreamErrorCode>(frame.application_error_code),
       stream->stream_bytes_written(),
       /*close_write_side_only=*/true);
+
   return true;
 }
 
@@ -659,6 +660,7 @@
 
 void QuicSession::CloseStreamInner(QuicStreamId stream_id, bool locally_reset) {
   QUIC_DVLOG(1) << ENDPOINT << "Closing stream " << stream_id;
+
   DynamicStreamMap::iterator it = dynamic_stream_map_.find(stream_id);
   if (it == dynamic_stream_map_.end()) {
     // When CloseStreamInner has been called recursively (via
@@ -1145,6 +1147,11 @@
     return handler;
   }
 
+  // TODO(fkastenholz): If we are creating a new stream and we have
+  // sent a goaway, we should ignore the stream creation. Need to
+  // add code to A) test if goaway was sent ("if (goaway_sent_)") and
+  // B) reject stream creation ("return nullptr")
+
   if (!MaybeIncreaseLargestPeerStreamId(stream_id)) {
     return StreamHandler();
   }
diff --git a/net/third_party/quic/core/quic_stream_id_manager.cc b/net/third_party/quic/core/quic_stream_id_manager.cc
index 3e87ade..4c0b811 100644
--- a/net/third_party/quic/core/quic_stream_id_manager.cc
+++ b/net/third_party/quic/core/quic_stream_id_manager.cc
@@ -4,6 +4,7 @@
 #include "net/third_party/quic/core/quic_stream_id_manager.h"
 
 #include "net/third_party/quic/core/quic_connection.h"
+#include "net/third_party/quic/core/quic_constants.h"
 #include "net/third_party/quic/core/quic_session.h"
 #include "net/third_party/quic/core/quic_utils.h"
 #include "net/third_party/quic/platform/api/quic_flag_utils.h"
diff --git a/net/third_party/quic/core/quic_stream_test.cc b/net/third_party/quic/core/quic_stream_test.cc
index 3b64f22..e26b1719 100644
--- a/net/third_party/quic/core/quic_stream_test.cc
+++ b/net/third_party/quic/core/quic_stream_test.cc
@@ -1023,6 +1023,7 @@
       &iov, 1, session_->connection()->helper()->GetStreamSendBufferAllocator(),
       1024);
   QuicConsumedData consumed = stream_->WriteMemSlices(storage.ToSpan(), false);
+
   // There is no buffered data before, all data should be consumed without
   // respecting buffered data upper limit.
   EXPECT_EQ(data.length(), consumed.bytes_consumed);
diff --git a/net/third_party/quic/platform/api/quic_client_stats.h b/net/third_party/quic/platform/api/quic_client_stats.h
index 274f2ac0..9e46e624 100644
--- a/net/third_party/quic/platform/api/quic_client_stats.h
+++ b/net/third_party/quic/platform/api/quic_client_stats.h
@@ -5,6 +5,7 @@
 #ifndef NET_THIRD_PARTY_QUIC_PLATFORM_API_QUIC_CLIENT_STATS_H_
 #define NET_THIRD_PARTY_QUIC_PLATFORM_API_QUIC_CLIENT_STATS_H_
 
+#include <string>
 #include "net/third_party/quic/platform/impl/quic_client_stats_impl.h"
 
 namespace quic {
diff --git a/net/third_party/quic/test_tools/packet_dropping_test_writer.h b/net/third_party/quic/test_tools/packet_dropping_test_writer.h
index 5f7e6a19..a365408 100644
--- a/net/third_party/quic/test_tools/packet_dropping_test_writer.h
+++ b/net/third_party/quic/test_tools/packet_dropping_test_writer.h
@@ -5,12 +5,9 @@
 #ifndef NET_THIRD_PARTY_QUIC_TEST_TOOLS_PACKET_DROPPING_TEST_WRITER_H_
 #define NET_THIRD_PARTY_QUIC_TEST_TOOLS_PACKET_DROPPING_TEST_WRITER_H_
 
-#include <stddef.h>
-#include <stdint.h>
-
+#include <cstdint>
 #include <list>
 #include <memory>
-#include <string>
 
 #include "base/macros.h"
 #include "net/third_party/quic/core/quic_alarm.h"
diff --git a/net/third_party/quic/test_tools/quic_spdy_stream_peer.h b/net/third_party/quic/test_tools/quic_spdy_stream_peer.h
index 097e0a6..e56eeb4 100644
--- a/net/third_party/quic/test_tools/quic_spdy_stream_peer.h
+++ b/net/third_party/quic/test_tools/quic_spdy_stream_peer.h
@@ -1,7 +1,7 @@
 // Copyright (c) 2019 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
-//
+
 #ifndef NET_THIRD_PARTY_QUIC_TEST_TOOLS_QUIC_SPDY_STREAM_PEER_H_
 #define NET_THIRD_PARTY_QUIC_TEST_TOOLS_QUIC_SPDY_STREAM_PEER_H_
 
diff --git a/net/third_party/quic/test_tools/quic_test_client.cc b/net/third_party/quic/test_tools/quic_test_client.cc
index 6bcd99d7..a2d8d283 100644
--- a/net/third_party/quic/test_tools/quic_test_client.cc
+++ b/net/third_party/quic/test_tools/quic_test_client.cc
@@ -608,7 +608,7 @@
 }
 
 bool QuicTestClient::WaitUntil(int timeout_ms, std::function<bool()> trigger) {
-  int64_t timeout_us = timeout_ms * base::Time::kMicrosecondsPerMillisecond;
+  int64_t timeout_us = timeout_ms * kNumMicrosPerMilli;
   int64_t old_timeout_us = epoll_server()->timeout_in_us();
   if (timeout_us > 0) {
     epoll_server()->set_timeout_in_us(timeout_us);
diff --git a/net/third_party/quic/test_tools/quic_test_client.h b/net/third_party/quic/test_tools/quic_test_client.h
index 9b90e5a..176351b 100644
--- a/net/third_party/quic/test_tools/quic_test_client.h
+++ b/net/third_party/quic/test_tools/quic_test_client.h
@@ -282,33 +282,6 @@
 
   void set_client(MockableQuicClient* client) { client_.reset(client); }
 
-  // PerStreamState of a stream is updated when it is closed.
-  struct PerStreamState {
-    PerStreamState(const PerStreamState& other);
-    PerStreamState(QuicRstStreamErrorCode stream_error,
-                   bool response_complete,
-                   bool response_headers_complete,
-                   const spdy::SpdyHeaderBlock& response_headers,
-                   const spdy::SpdyHeaderBlock& preliminary_headers,
-                   const QuicString& response,
-                   const spdy::SpdyHeaderBlock& response_trailers,
-                   uint64_t bytes_read,
-                   uint64_t bytes_written,
-                   int64_t response_body_size);
-    ~PerStreamState();
-
-    QuicRstStreamErrorCode stream_error;
-    bool response_complete;
-    bool response_headers_complete;
-    spdy::SpdyHeaderBlock response_headers;
-    spdy::SpdyHeaderBlock preliminary_headers;
-    QuicString response;
-    spdy::SpdyHeaderBlock response_trailers;
-    uint64_t bytes_read;
-    uint64_t bytes_written;
-    int64_t response_body_size;
-  };
-
   // Given |uri|, populates the fields in |headers| for a simple GET
   // request. If |uri| is a relative URL, the QuicServerId will be
   // use to specify the authority.
@@ -347,6 +320,33 @@
     QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener_;
   };
 
+  // PerStreamState of a stream is updated when it is closed.
+  struct PerStreamState {
+    PerStreamState(const PerStreamState& other);
+    PerStreamState(QuicRstStreamErrorCode stream_error,
+                   bool response_complete,
+                   bool response_headers_complete,
+                   const spdy::SpdyHeaderBlock& response_headers,
+                   const spdy::SpdyHeaderBlock& preliminary_headers,
+                   const QuicString& response,
+                   const spdy::SpdyHeaderBlock& response_trailers,
+                   uint64_t bytes_read,
+                   uint64_t bytes_written,
+                   int64_t response_body_size);
+    ~PerStreamState();
+
+    QuicRstStreamErrorCode stream_error;
+    bool response_complete;
+    bool response_headers_complete;
+    spdy::SpdyHeaderBlock response_headers;
+    spdy::SpdyHeaderBlock preliminary_headers;
+    QuicString response;
+    spdy::SpdyHeaderBlock response_trailers;
+    uint64_t bytes_read;
+    uint64_t bytes_written;
+    int64_t response_body_size;
+  };
+
   bool HaveActiveStream();
 
   // Read oldest received response and remove it from closed_stream_states_.
diff --git a/net/third_party/quic/test_tools/quic_test_utils.h b/net/third_party/quic/test_tools/quic_test_utils.h
index a09ffe1..2249b08 100644
--- a/net/third_party/quic/test_tools/quic_test_utils.h
+++ b/net/third_party/quic/test_tools/quic_test_utils.h
@@ -14,7 +14,6 @@
 #include <vector>
 
 #include "base/macros.h"
-#include "net/test/gtest_util.h"
 #include "net/third_party/quic/core/congestion_control/loss_detection_interface.h"
 #include "net/third_party/quic/core/congestion_control/send_algorithm_interface.h"
 #include "net/third_party/quic/core/http/quic_client_push_promise_index.h"
diff --git a/net/third_party/quic/test_tools/simulator/switch.cc b/net/third_party/quic/test_tools/simulator/switch.cc
index a4464043..f26f96c 100644
--- a/net/third_party/quic/test_tools/simulator/switch.cc
+++ b/net/third_party/quic/test_tools/simulator/switch.cc
@@ -4,7 +4,6 @@
 
 #include <cinttypes>
 
-#include "base/format_macros.h"
 #include "net/third_party/quic/platform/api/quic_ptr_util.h"
 #include "net/third_party/quic/platform/api/quic_str_cat.h"
 #include "net/third_party/quic/test_tools/simulator/switch.h"
@@ -17,10 +16,9 @@
                SwitchPortNumber port_count,
                QuicByteCount queue_capacity) {
   for (size_t port_number = 1; port_number <= port_count; port_number++) {
-    ports_.emplace_back(
-        simulator,
-        QuicStringPrintf("%s (port %" PRIuS ")", name.c_str(), port_number),
-        this, port_number, queue_capacity);
+    ports_.emplace_back(simulator,
+                        QuicStrCat(name, " (port ", port_number, ")"), this,
+                        port_number, queue_capacity);
   }
 }
 
diff --git a/net/third_party/quic/tools/quic_client.cc b/net/third_party/quic/tools/quic_client.cc
index ab6b449..32f42cb 100644
--- a/net/third_party/quic/tools/quic_client.cc
+++ b/net/third_party/quic/tools/quic_client.cc
@@ -9,9 +9,7 @@
 #include <string.h>
 #include <sys/epoll.h>
 #include <sys/socket.h>
-#include <unistd.h>
 
-#include "base/run_loop.h"
 #include "net/third_party/quic/core/crypto/quic_random.h"
 #include "net/third_party/quic/core/http/spdy_utils.h"
 #include "net/third_party/quic/core/quic_connection.h"
@@ -30,10 +28,6 @@
 #define SO_RXQ_OVFL 40
 #endif
 
-// TODO(rtenneti): Add support for MMSG_MORE.
-#define MMSG_MORE 0
-using std::string;
-
 namespace quic {
 
 QuicClient::QuicClient(QuicSocketAddress server_address,
diff --git a/net/third_party/quic/tools/quic_client_epoll_network_helper.cc b/net/third_party/quic/tools/quic_client_epoll_network_helper.cc
index f05d3ca..7922446 100644
--- a/net/third_party/quic/tools/quic_client_epoll_network_helper.cc
+++ b/net/third_party/quic/tools/quic_client_epoll_network_helper.cc
@@ -29,9 +29,6 @@
 #define SO_RXQ_OVFL 40
 #endif
 
-// TODO(rtenneti): Add support for MMSG_MORE.
-#define MMSG_MORE 0
-
 namespace quic {
 
 namespace {
diff --git a/net/third_party/quic/tools/quic_client_epoll_network_helper.h b/net/third_party/quic/tools/quic_client_epoll_network_helper.h
index b96f5b3..0fb0ee0 100644
--- a/net/third_party/quic/tools/quic_client_epoll_network_helper.h
+++ b/net/third_party/quic/tools/quic_client_epoll_network_helper.h
@@ -12,19 +12,14 @@
 #include <memory>
 #include <string>
 
-#include "base/command_line.h"
 #include "base/macros.h"
 #include "net/third_party/quic/core/http/quic_client_push_promise_index.h"
-#include "net/third_party/quic/core/http/quic_spdy_client_session.h"
-#include "net/third_party/quic/core/http/quic_spdy_stream.h"
 #include "net/third_party/quic/core/quic_config.h"
 #include "net/third_party/quic/core/quic_packet_reader.h"
 #include "net/third_party/quic/core/quic_process_packet_interface.h"
 #include "net/third_party/quic/platform/api/quic_containers.h"
 #include "net/third_party/quic/platform/api/quic_epoll.h"
 #include "net/third_party/quic/tools/quic_client_base.h"
-#include "net/third_party/quic/tools/quic_spdy_client_base.h"
-#include "net/tools/epoll_server/epoll_server.h"
 
 namespace quic {
 
diff --git a/net/third_party/quic/tools/quic_memory_cache_backend.h b/net/third_party/quic/tools/quic_memory_cache_backend.h
index b584f4bb..9891ed9 100644
--- a/net/third_party/quic/tools/quic_memory_cache_backend.h
+++ b/net/third_party/quic/tools/quic_memory_cache_backend.h
@@ -56,7 +56,6 @@
 
    protected:
     void HandleXOriginalUrl();
-    void HandlePushUrls(const std::vector<QuicStringPiece>& push_urls);
     QuicStringPiece RemoveScheme(QuicStringPiece url);
 
     QuicString file_name_;
@@ -69,7 +68,6 @@
    private:
     QuicStringPiece host_;
     QuicStringPiece path_;
-    QuicMemoryCacheBackend* cache_;
   };
 
   QuicMemoryCacheBackend();
diff --git a/net/third_party/quic/tools/quic_simple_server_backend.h b/net/third_party/quic/tools/quic_simple_server_backend.h
index 3089a5b..a1f9e166 100644
--- a/net/third_party/quic/tools/quic_simple_server_backend.h
+++ b/net/third_party/quic/tools/quic_simple_server_backend.h
@@ -10,6 +10,7 @@
 namespace spdy {
 class SpdyHeaderBlock;
 }  // namespace spdy
+
 namespace quic {
 
 // This interface implements the functionality to fetch a response
diff --git a/net/third_party/quic/tools/quic_simple_server_session_test.cc b/net/third_party/quic/tools/quic_simple_server_session_test.cc
index acfb0706..ccfea15 100644
--- a/net/third_party/quic/tools/quic_simple_server_session_test.cc
+++ b/net/third_party/quic/tools/quic_simple_server_session_test.cc
@@ -8,7 +8,6 @@
 #include <memory>
 
 #include "base/macros.h"
-#include "net/test/gtest_util.h"
 #include "net/third_party/quic/core/crypto/quic_crypto_server_config.h"
 #include "net/third_party/quic/core/crypto/quic_random.h"
 #include "net/third_party/quic/core/proto/cached_network_parameters.pb.h"
@@ -254,7 +253,7 @@
     // Create and inject a STOP_SENDING frame. In GOOGLE QUIC, receiving a
     // RST_STREAM frame causes a two-way close. For IETF QUIC, RST_STREAM causes
     // a one-way close.
-    if (connection_->transport_version() != QUIC_VERSION_99) {
+    if (!IsVersion99()) {
       // Only needed for version 99/IETF QUIC.
       return;
     }
diff --git a/net/third_party/quic/tools/quic_simple_server_stream_test.cc b/net/third_party/quic/tools/quic_simple_server_stream_test.cc
index 0f506eb..f15571c7 100644
--- a/net/third_party/quic/tools/quic_simple_server_stream_test.cc
+++ b/net/third_party/quic/tools/quic_simple_server_stream_test.cc
@@ -8,7 +8,6 @@
 #include <memory>
 #include <utility>
 
-#include "net/test/gtest_util.h"
 #include "net/third_party/quic/core/http/spdy_utils.h"
 #include "net/third_party/quic/core/quic_utils.h"
 #include "net/third_party/quic/core/tls_server_handshaker.h"
@@ -25,8 +24,6 @@
 #include "net/third_party/quic/tools/quic_backend_response.h"
 #include "net/third_party/quic/tools/quic_memory_cache_backend.h"
 #include "net/third_party/quic/tools/quic_simple_server_session.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
 
 using testing::_;
 using testing::AnyNumber;
@@ -635,7 +632,7 @@
   QuicRstStreamFrame rst_frame(kInvalidControlFrameId, stream_->id(),
                                QUIC_STREAM_CANCELLED, 1234);
   stream_->OnStreamReset(rst_frame);
-  if (connection_->transport_version() == QUIC_VERSION_99) {
+  if (IsVersion99()) {
     // For V99 receiving a RST_STREAM causes a 1-way close; the test requires
     // a full close. A CloseWriteSide closes the other half of the stream.
     // Everything should then work properly.
diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc
index e8aad11..5c960a8 100644
--- a/net/url_request/url_request_unittest.cc
+++ b/net/url_request/url_request_unittest.cc
@@ -7053,42 +7053,6 @@
 
 #if BUILDFLAG(ENABLE_REPORTING)
 
-TEST_F(URLRequestTestHTTP, NetworkErrorLogging_DontReportIfNetworkNotAccessed) {
-  EmbeddedTestServer https_test_server(net::EmbeddedTestServer::TYPE_HTTPS);
-  https_test_server.AddDefaultHandlers(base::FilePath(kTestFilePath));
-  ASSERT_TRUE(https_test_server.Start());
-  GURL request_url = https_test_server.GetURL("/cachetime");
-
-  TestNetworkErrorLoggingService nel_service;
-  TestURLRequestContext context(true);
-  context.set_network_error_logging_service(&nel_service);
-  context.Init();
-
-  // Populate the cache.
-  TestDelegate d;
-  std::unique_ptr<URLRequest> request(context.CreateRequest(
-      request_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
-  request->Start();
-  d.RunUntilComplete();
-
-  ASSERT_EQ(1u, nel_service.errors().size());
-  const TestNetworkErrorLoggingService::RequestDetails& error =
-      nel_service.errors()[0];
-  EXPECT_EQ(request_url, error.uri);
-  EXPECT_EQ(200, error.status_code);
-  EXPECT_EQ(OK, error.type);
-
-  request = context.CreateRequest(request_url, DEFAULT_PRIORITY, &d,
-                                  TRAFFIC_ANNOTATION_FOR_TESTS);
-  request->Start();
-  d.RunUntilComplete();
-
-  EXPECT_FALSE(request->response_info().network_accessed);
-  EXPECT_TRUE(request->response_info().was_cached);
-  // No additional NEL report was generated.
-  EXPECT_EQ(1u, nel_service.errors().size());
-}
-
 TEST_F(URLRequestTestHTTP, NetworkErrorLogging_BasicSuccess) {
   EmbeddedTestServer https_test_server(net::EmbeddedTestServer::TYPE_HTTPS);
   https_test_server.ServeFilesFromSourceDirectory(
@@ -7172,33 +7136,6 @@
   EXPECT_EQ(OK, error2.type);
 }
 
-TEST_F(URLRequestTestHTTP, NetworkErrorLogging_RedirectWithoutLocationHeader) {
-  EmbeddedTestServer https_test_server(net::EmbeddedTestServer::TYPE_HTTPS);
-  https_test_server.ServeFilesFromSourceDirectory(
-      base::FilePath(kTestFilePath));
-  ASSERT_TRUE(https_test_server.Start());
-  GURL request_url = https_test_server.GetURL("/308-without-location-header");
-
-  TestNetworkErrorLoggingService nel_service;
-  TestURLRequestContext context(true);
-  context.set_network_error_logging_service(&nel_service);
-  context.Init();
-
-  TestDelegate d;
-  std::unique_ptr<URLRequest> request(context.CreateRequest(
-      request_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
-  request->Start();
-  d.RunUntilComplete();
-
-  ASSERT_EQ(1u, nel_service.errors().size());
-  const TestNetworkErrorLoggingService::RequestDetails& error =
-      nel_service.errors()[0];
-  EXPECT_EQ(request_url, error.uri);
-  EXPECT_EQ(308, error.status_code);
-  // The body of the response was successfully read.
-  EXPECT_EQ(OK, error.type);
-}
-
 TEST_F(URLRequestTestHTTP, NetworkErrorLogging_Auth) {
   EmbeddedTestServer https_test_server(net::EmbeddedTestServer::TYPE_HTTPS);
   https_test_server.AddDefaultHandlers(base::FilePath(kTestFilePath));
@@ -7230,62 +7167,7 @@
   EXPECT_EQ(OK, error2.type);
 }
 
-TEST_F(URLRequestTestHTTP, NetworkErrorLogging_304Response) {
-  EmbeddedTestServer https_test_server(net::EmbeddedTestServer::TYPE_HTTPS);
-  https_test_server.AddDefaultHandlers(base::FilePath(kTestFilePath));
-  ASSERT_TRUE(https_test_server.Start());
-  GURL request_url = https_test_server.GetURL("/auth-basic");
-
-  TestNetworkErrorLoggingService nel_service;
-  TestURLRequestContext context(true);
-  context.set_network_error_logging_service(&nel_service);
-  context.Init();
-
-  // populate the cache
-  {
-    TestDelegate d;
-    d.set_credentials(AuthCredentials(kUser, kSecret));
-    std::unique_ptr<URLRequest> r(context.CreateRequest(
-        request_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
-    r->Start();
-    d.RunUntilComplete();
-  }
-  ASSERT_EQ(2u, nel_service.errors().size());
-  const TestNetworkErrorLoggingService::RequestDetails& error1 =
-      nel_service.errors()[0];
-  EXPECT_EQ(request_url, error1.uri);
-  EXPECT_EQ(401, error1.status_code);
-  EXPECT_EQ(OK, error1.type);
-  const TestNetworkErrorLoggingService::RequestDetails& error2 =
-      nel_service.errors()[1];
-  EXPECT_EQ(request_url, error2.uri);
-  EXPECT_EQ(200, error2.status_code);
-  EXPECT_EQ(OK, error2.type);
-
-  // repeat request with end-to-end validation.  since auth-basic results in a
-  // cachable page, we expect this test to result in a 304.  in which case, the
-  // response should be fetched from the cache.
-  {
-    TestDelegate d;
-    d.set_credentials(AuthCredentials(kUser, kSecret));
-    std::unique_ptr<URLRequest> r(context.CreateRequest(
-        request_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
-    r->SetLoadFlags(LOAD_VALIDATE_CACHE);
-    r->Start();
-    d.RunUntilComplete();
-
-    // Should be the same cached document.
-    EXPECT_TRUE(r->was_cached());
-  }
-  ASSERT_EQ(3u, nel_service.errors().size());
-  const TestNetworkErrorLoggingService::RequestDetails& error3 =
-      nel_service.errors()[2];
-  EXPECT_EQ(request_url, error3.uri);
-  EXPECT_EQ(304, error3.status_code);
-  EXPECT_EQ(OK, error3.type);
-}
-
-TEST_F(URLRequestTestHTTP, NetworkErrorLogging_CancelInResponseStarted) {
+TEST_F(URLRequestTestHTTP, NetworkErrorLogging_Cancel) {
   EmbeddedTestServer https_test_server(net::EmbeddedTestServer::TYPE_HTTPS);
   https_test_server.ServeFilesFromSourceDirectory(
       base::FilePath(kTestFilePath));
@@ -7309,63 +7191,6 @@
       nel_service.errors()[0];
   EXPECT_EQ(request_url, error.uri);
   EXPECT_EQ(200, error.status_code);
-  // Headers were received and the body should have been read but was not.
-  EXPECT_EQ(ERR_ABORTED, error.type);
-}
-
-TEST_F(URLRequestTestHTTP, NetworkErrorLogging_CancelOnDataReceived) {
-  EmbeddedTestServer https_test_server(net::EmbeddedTestServer::TYPE_HTTPS);
-  https_test_server.ServeFilesFromSourceDirectory(
-      base::FilePath(kTestFilePath));
-  ASSERT_TRUE(https_test_server.Start());
-  GURL request_url = https_test_server.GetURL("/simple.html");
-
-  TestNetworkErrorLoggingService nel_service;
-  TestURLRequestContext context(true);
-  context.set_network_error_logging_service(&nel_service);
-  context.Init();
-
-  TestDelegate d;
-  d.set_cancel_in_received_data(true);
-  std::unique_ptr<URLRequest> request(context.CreateRequest(
-      request_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
-  request->Start();
-  d.RunUntilComplete();
-
-  ASSERT_EQ(1u, nel_service.errors().size());
-  const TestNetworkErrorLoggingService::RequestDetails& error =
-      nel_service.errors()[0];
-  EXPECT_EQ(request_url, error.uri);
-  EXPECT_EQ(200, error.status_code);
-  // Data was received but the body was not completely read.
-  EXPECT_EQ(ERR_ABORTED, error.type);
-}
-
-TEST_F(URLRequestTestHTTP, NetworkErrorLogging_CancelRedirect) {
-  EmbeddedTestServer https_test_server(net::EmbeddedTestServer::TYPE_HTTPS);
-  https_test_server.ServeFilesFromSourceDirectory(
-      base::FilePath(kTestFilePath));
-  ASSERT_TRUE(https_test_server.Start());
-  GURL request_url = https_test_server.GetURL("/redirect-test.html");
-
-  TestNetworkErrorLoggingService nel_service;
-  TestURLRequestContext context(true);
-  context.set_network_error_logging_service(&nel_service);
-  context.Init();
-
-  TestDelegate d;
-  d.set_cancel_in_received_redirect(true);
-  std::unique_ptr<URLRequest> request(context.CreateRequest(
-      request_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
-  request->Start();
-  d.RunUntilComplete();
-
-  ASSERT_EQ(1u, nel_service.errors().size());
-  const TestNetworkErrorLoggingService::RequestDetails& error =
-      nel_service.errors()[0];
-  EXPECT_EQ(request_url, error.uri);
-  EXPECT_EQ(302, error.status_code);
-  // A valid HTTP response was received, even though the request was cancelled.
   EXPECT_EQ(OK, error.type);
 }
 
diff --git a/net/websockets/websocket_basic_stream_adapters_test.cc b/net/websockets/websocket_basic_stream_adapters_test.cc
index 610b884..f399a61e 100644
--- a/net/websockets/websocket_basic_stream_adapters_test.cc
+++ b/net/websockets/websocket_basic_stream_adapters_test.cc
@@ -97,8 +97,8 @@
         TransportClientSocketPool::SocketParams::CreateFromSSLSocketParams(
             ssl_params_),
         MEDIUM, SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
-        callback.callback(), socket_pool_manager_->GetTransportSocketPool(),
-        net_log_);
+        callback.callback(), ClientSocketPool::ProxyAuthCallback(),
+        socket_pool_manager_->GetTransportSocketPool(), net_log_);
     rv = callback.GetResult(rv);
     return rv == OK;
   }
diff --git a/net/websockets/websocket_basic_stream_test.cc b/net/websockets/websocket_basic_stream_test.cc
index 1c6e6fc..fc4bd5c 100644
--- a/net/websockets/websocket_basic_stream_test.cc
+++ b/net/websockets/websocket_basic_stream_test.cc
@@ -123,10 +123,10 @@
 
     auto transport_socket = std::make_unique<ClientSocketHandle>();
     scoped_refptr<MockTransportSocketParams> params;
-    transport_socket->Init("a", params, MEDIUM, SocketTag(),
-                           ClientSocketPool::RespectLimits::ENABLED,
-                           CompletionOnceCallback(), &pool_,
-                           NetLogWithSource());
+    transport_socket->Init(
+        "a", params, MEDIUM, SocketTag(),
+        ClientSocketPool::RespectLimits::ENABLED, CompletionOnceCallback(),
+        ClientSocketPool::ProxyAuthCallback(), &pool_, NetLogWithSource());
     return transport_socket;
   }
 
diff --git a/net/websockets/websocket_handshake_stream_create_helper_test.cc b/net/websockets/websocket_handshake_stream_create_helper_test.cc
index a3df7944..619dfaf 100644
--- a/net/websockets/websocket_handshake_stream_create_helper_test.cc
+++ b/net/websockets/websocket_handshake_stream_create_helper_test.cc
@@ -68,9 +68,10 @@
       const std::string& return_to_read) {
     socket_factory_maker_.SetExpectations(expect_written, return_to_read);
     auto socket_handle = std::make_unique<ClientSocketHandle>();
-    socket_handle->Init("a", scoped_refptr<MockTransportSocketParams>(), MEDIUM,
-                        SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
-                        CompletionOnceCallback(), &pool_, NetLogWithSource());
+    socket_handle->Init(
+        "a", scoped_refptr<MockTransportSocketParams>(), MEDIUM, SocketTag(),
+        ClientSocketPool::RespectLimits::ENABLED, CompletionOnceCallback(),
+        ClientSocketPool::ProxyAuthCallback(), &pool_, NetLogWithSource());
     return socket_handle;
   }
 
diff --git a/printing/BUILD.gn b/printing/BUILD.gn
index 60fdbaf..39164b8 100644
--- a/printing/BUILD.gn
+++ b/printing/BUILD.gn
@@ -208,6 +208,14 @@
         "backend/print_backend_cups.cc",
         "backend/print_backend_cups.h",
       ]
+
+      # We still build the utils for fuzzing.
+      if (use_fuzzing_engine) {
+        sources += [
+          "backend/cups_ipp_util.cc",
+          "backend/cups_ipp_util.h",
+        ]
+      }
     }
   }
 
diff --git a/printing/buildflags/buildflags.gni b/printing/buildflags/buildflags.gni
index c2edd93d..d5c572ee 100644
--- a/printing/buildflags/buildflags.gni
+++ b/printing/buildflags/buildflags.gni
@@ -4,6 +4,7 @@
 
 import("//build/config/chromecast_build.gni")
 import("//build/config/features.gni")
+import("//build/config/sanitizers/sanitizers.gni")
 
 declare_args() {
   # Enable basic printing support and UI.
@@ -15,5 +16,10 @@
   # enable_basic_printing within the same declare_args() block.
   enable_print_preview = !is_android && !is_chromecast && !is_ios && !is_fuchsia
 
-  use_cups = (is_desktop_linux || is_mac) && !is_chromecast && !is_fuchsia
+  if (use_fuzzing_engine) {
+    # For fuzzing, just restrict to chromeos and linux.
+    use_cups = is_linux
+  } else {
+    use_cups = (is_desktop_linux || is_mac) && !is_chromecast && !is_fuchsia
+  }
 }
diff --git a/remoting/signaling/ftl_client.cc b/remoting/signaling/ftl_client.cc
index f954251a..d69b096 100644
--- a/remoting/signaling/ftl_client.cc
+++ b/remoting/signaling/ftl_client.cc
@@ -7,19 +7,8 @@
 #include "base/guid.h"
 #include "build/build_config.h"
 #include "google_apis/google_api_keys.h"
-
-// TODO(crbug.com/933949): Remove suppression once gRPC is fixed.
-#if defined(__clang__)
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wextra-semi"
-#endif
-
 #include "third_party/grpc/src/include/grpcpp/grpcpp.h"
 
-#if defined(__clang__)
-#pragma clang diagnostic pop  // -Wextra-semi
-#endif
-
 namespace {
 
 constexpr char kChromotingAppIdentifier[] = "CRD";
diff --git a/remoting/signaling/ftl_client.h b/remoting/signaling/ftl_client.h
index d9b143d..fce6e4dc 100644
--- a/remoting/signaling/ftl_client.h
+++ b/remoting/signaling/ftl_client.h
@@ -8,19 +8,7 @@
 #include <memory>
 
 #include "base/macros.h"
-
-// TODO(crbug.com/933949): Remove suppression once gRPC is fixed.
-#if defined(__clang__)
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wextra-semi"
-#endif
-
 #include "remoting/signaling/ftl_services.grpc.pb.h"
-
-#if defined(__clang__)
-#pragma clang diagnostic pop  // -Wextra-semi
-#endif
-
 #include "third_party/grpc/src/include/grpcpp/support/status.h"
 
 namespace remoting {
diff --git a/sandbox/win/src/resolver_32.cc b/sandbox/win/src/resolver_32.cc
index 4da25235..6f47b681 100644
--- a/sandbox/win/src/resolver_32.cc
+++ b/sandbox/win/src/resolver_32.cc
@@ -46,7 +46,7 @@
     opcodes_6 = 0xc35a;
     extra_argument = 0;
     interceptor_function = 0;
-  };
+  }
   ULONG opcodes_1;  // = 0x5208ec83
   ULONG opcodes_2;  // = 0x0c24548b
   ULONG opcodes_3;  // = 0x08245489
diff --git a/sandbox/win/src/service_resolver_32.cc b/sandbox/win/src/service_resolver_32.cc
index de1b804e..d95ce00 100644
--- a/sandbox/win/src/service_resolver_32.cc
+++ b/sandbox/win/src/service_resolver_32.cc
@@ -156,7 +156,7 @@
 
 #pragma pack(pop)
 
-};  // namespace
+}  // namespace
 
 namespace sandbox {
 
diff --git a/sandbox/win/src/sidestep/ia32_modrm_map.cpp b/sandbox/win/src/sidestep/ia32_modrm_map.cpp
index 89bc189..c66421f 100644
--- a/sandbox/win/src/sidestep/ia32_modrm_map.cpp
+++ b/sandbox/win/src/sidestep/ia32_modrm_map.cpp
@@ -89,4 +89,4 @@
   /* r/m == 111 */ { false, false, OS_ZERO },
 };
 
-};  // namespace sidestep
+}  // namespace sidestep
diff --git a/sandbox/win/src/sidestep/ia32_opcode_map.cpp b/sandbox/win/src/sidestep/ia32_opcode_map.cpp
index b7d8a60..6cd232c 100644
--- a/sandbox/win/src/sidestep/ia32_opcode_map.cpp
+++ b/sandbox/win/src/sidestep/ia32_opcode_map.cpp
@@ -1156,4 +1156,4 @@
   /* 24 */ {s_opcode_byte_after_0fc7, 3, 0x07, 0, 0x01}
 };
 
-};  // namespace sidestep
+}  // namespace sidestep
diff --git a/sandbox/win/src/sidestep/mini_disassembler.h b/sandbox/win/src/sidestep/mini_disassembler.h
index 5dcd951d..eae6538 100644
--- a/sandbox/win/src/sidestep/mini_disassembler.h
+++ b/sandbox/win/src/sidestep/mini_disassembler.h
@@ -148,6 +148,6 @@
   bool got_f2_prefix_, got_f3_prefix_, got_66_prefix_;
 };
 
-};  // namespace sidestep
+}  // namespace sidestep
 
 #endif  // SANDBOX_SRC_SIDESTEP_MINI_DISASSEMBLER_H__
diff --git a/sandbox/win/src/sidestep/mini_disassembler_types.h b/sandbox/win/src/sidestep/mini_disassembler_types.h
index 4181055..a9e7c98a 100644
--- a/sandbox/win/src/sidestep/mini_disassembler_types.h
+++ b/sandbox/win/src/sidestep/mini_disassembler_types.h
@@ -192,6 +192,6 @@
   OperandSize operand_size_;
 };
 
-};  // namespace sidestep
+}  // namespace sidestep
 
 #endif  // SANDBOX_SRC_SIDESTEP_MINI_DISASSEMBLER_TYPES_H__
diff --git a/sandbox/win/src/sidestep/preamble_patcher.h b/sandbox/win/src/sidestep/preamble_patcher.h
index fd49e5c..3d7afbc1 100644
--- a/sandbox/win/src/sidestep/preamble_patcher.h
+++ b/sandbox/win/src/sidestep/preamble_patcher.h
@@ -107,6 +107,6 @@
                                         size_t* bytes_needed);
 };
 
-};  // namespace sidestep
+}  // namespace sidestep
 
 #endif  // SANDBOX_SRC_SIDESTEP_PREAMBLE_PATCHER_H__
diff --git a/sandbox/win/src/sidestep/preamble_patcher_with_stub.cpp b/sandbox/win/src/sidestep/preamble_patcher_with_stub.cpp
index b501600..cbe98d0 100644
--- a/sandbox/win/src/sidestep/preamble_patcher_with_stub.cpp
+++ b/sandbox/win/src/sidestep/preamble_patcher_with_stub.cpp
@@ -176,6 +176,6 @@
   return SIDESTEP_SUCCESS;
 }
 
-};  // namespace sidestep
+}  // namespace sidestep
 
 #undef ASSERT
diff --git a/services/network/network_context.cc b/services/network/network_context.cc
index b27f121..e84a273 100644
--- a/services/network/network_context.cc
+++ b/services/network/network_context.cc
@@ -2008,6 +2008,11 @@
         certificate_report_sender_.get());
   }
 
+#if defined(OS_ANDROID)
+  result.url_request_context->set_check_cleartext_permitted(
+      params_->check_clear_text_permitted);
+#endif  // defined(OS_ANDROID)
+
 #if BUILDFLAG(IS_CT_SUPPORTED)
   if (params_->enable_expect_ct_reporting) {
     LazyCreateExpectCTReporter(result.url_request_context.get());
diff --git a/services/network/proxy_resolving_client_socket.cc b/services/network/proxy_resolving_client_socket.cc
index 509ad145..9f9a5d9 100644
--- a/services/network/proxy_resolving_client_socket.cc
+++ b/services/network/proxy_resolving_client_socket.cc
@@ -299,14 +299,16 @@
         proxy_info_, ssl_config_, ssl_config_, net::PRIVACY_MODE_DISABLED,
         net_log_, socket_handle_.get(),
         base::BindRepeating(&ProxyResolvingClientSocket::OnIOComplete,
-                            base::Unretained(this)));
+                            base::Unretained(this)),
+        net::ClientSocketPool::ProxyAuthCallback());
   }
   return net::InitSocketHandleForRawConnect(
       host_port_pair, network_session_, request_load_flags, request_priority,
       proxy_info_, ssl_config_, ssl_config_, net::PRIVACY_MODE_DISABLED,
       net_log_, socket_handle_.get(),
       base::BindRepeating(&ProxyResolvingClientSocket::OnIOComplete,
-                          base::Unretained(this)));
+                          base::Unretained(this)),
+      net::ClientSocketPool::ProxyAuthCallback());
 }
 
 int ProxyResolvingClientSocket::DoInitConnectionComplete(int result) {
diff --git a/services/network/public/mojom/network_context.mojom b/services/network/public/mojom/network_context.mojom
index b6979e9..e467e9f 100644
--- a/services/network/public/mojom/network_context.mojom
+++ b/services/network/public/mojom/network_context.mojom
@@ -202,6 +202,12 @@
   // Must be false if built without FTP support.
   bool enable_ftp_url_support = false;
 
+  // Whether or not to check the Android platform's cleartext policy for
+  // requests. Under some conditions, Android may advise us to block cleartext
+  // traffic.
+  [EnableIf=is_android]
+  bool check_clear_text_permitted = false;
+
   // True if the "Certificate Transparency in Chrome" policy (see
   // https://github.com/chromium/ct-policy/blob/master/ct_policy.md) should
   // be enforced for certificates and connections.
diff --git a/skia/tools/fuzzers/fuzzer_environment.cc b/skia/tools/fuzzers/fuzzer_environment.cc
index 72f10a7..5653efd 100644
--- a/skia/tools/fuzzers/fuzzer_environment.cc
+++ b/skia/tools/fuzzers/fuzzer_environment.cc
@@ -16,4 +16,4 @@
 };
 
 static Environment env;
-};  // namespace
+}  // namespace
diff --git a/storage/browser/quota/quota_manager.cc b/storage/browser/quota/quota_manager.cc
index bf98887..fe150e8 100644
--- a/storage/browser/quota/quota_manager.cc
+++ b/storage/browser/quota/quota_manager.cc
@@ -879,12 +879,13 @@
     scoped_refptr<base::SingleThreadTaskRunner> io_thread,
     scoped_refptr<SpecialStoragePolicy> special_storage_policy,
     const GetQuotaSettingsFunc& get_settings_function)
-    : is_incognito_(is_incognito),
+    : RefCountedDeleteOnSequence<QuotaManager>(io_thread),
+      is_incognito_(is_incognito),
       profile_path_(profile_path),
       proxy_(new QuotaManagerProxy(this, io_thread)),
       db_disabled_(false),
       eviction_disabled_(false),
-      io_thread_(std::move(io_thread)),
+      io_thread_(io_thread),
       db_runner_(base::CreateSequencedTaskRunnerWithTraits(
           {base::MayBlock(), base::TaskPriority::USER_VISIBLE,
            base::TaskShutdownBehavior::BLOCK_SHUTDOWN})),
@@ -1796,14 +1797,6 @@
   db_disabled_ = !success;
 }
 
-void QuotaManager::DeleteOnCorrectThread() const {
-  if (!io_thread_->BelongsToCurrentThread() &&
-      io_thread_->DeleteSoon(FROM_HERE, this)) {
-    return;
-  }
-  delete this;
-}
-
 void QuotaManager::PostTaskAndReplyWithResultForDBThread(
     const base::Location& from_here,
     base::OnceCallback<bool(QuotaDatabase*)> task,
diff --git a/storage/browser/quota/quota_manager.h b/storage/browser/quota/quota_manager.h
index 188a436..8866660 100644
--- a/storage/browser/quota/quota_manager.h
+++ b/storage/browser/quota/quota_manager.h
@@ -21,6 +21,7 @@
 #include "base/files/file_path.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
+#include "base/memory/ref_counted_delete_on_sequence.h"
 #include "base/memory/weak_ptr.h"
 #include "base/optional.h"
 #include "base/sequence_checker.h"
@@ -108,7 +109,7 @@
 class COMPONENT_EXPORT(STORAGE_BROWSER) QuotaManager
     : public QuotaTaskObserver,
       public QuotaEvictionHandler,
-      public base::RefCountedThreadSafe<QuotaManager, QuotaManagerDeleter> {
+      public base::RefCountedDeleteOnSequence<QuotaManager> {
  public:
   using UsageAndQuotaCallback = base::OnceCallback<
       void(blink::mojom::QuotaStatusCode, int64_t usage, int64_t quota)>;
@@ -265,7 +266,7 @@
 
  private:
   friend class base::DeleteHelper<QuotaManager>;
-  friend class base::RefCountedThreadSafe<QuotaManager, QuotaManagerDeleter>;
+  friend class base::RefCountedDeleteOnSequence<QuotaManager>;
   friend class content::QuotaManagerTest;
   friend class content::StorageMonitorTest;
   friend class content::MockQuotaManager;
@@ -487,12 +488,6 @@
   DISALLOW_COPY_AND_ASSIGN(QuotaManager);
 };
 
-struct QuotaManagerDeleter {
-  static void Destruct(const QuotaManager* manager) {
-    manager->DeleteOnCorrectThread();
-  }
-};
-
 }  // namespace storage
 
 #endif  // STORAGE_BROWSER_QUOTA_QUOTA_MANAGER_H_
diff --git a/styleguide/c++/c++.md b/styleguide/c++/c++.md
index 04f046f..09b10ae0 100644
--- a/styleguide/c++/c++.md
+++ b/styleguide/c++/c++.md
@@ -178,31 +178,32 @@
 ## Types
 
   * Use `size_t` for object and allocation sizes, object counts, array and
-    pointer offsets, vector indices, and so on. The signed types are incorrect
-    and unsafe for these purposes (e.g. integer overflow behavior for signed
-    types is undefined in the C and C++ standards, while the behavior is
-    defined for unsigned types.) The C++ STL is a guide here: they use `size_t`
-    and `foo::size_type` for very good reasons.
+    pointer offsets, vector indices, and so on. The signed types are
+    incorrect and unsafe for these purposes (e.g. integer overflow behavior for
+    signed types is undefined in the C and C++ standards, while the behavior is
+    defined for unsigned types). The C++ STL and libc are good guides here: they
+    use `size_t` and `foo::size_type` for very good reasons.
 
   * Use `size_t` directly in preference to `std::string::size_type` and similar.
 
   * Occasionally classes may have a good reason to use a type other than `size_t`
     for one of these concepts, e.g. as a storage space optimization. In these
-    cases, continue to use `size_t` in public-facing function declarations.
+    cases, continue to use `size_t` in public-facing function declarations,
+    and continue to use unsigned types internally (e.g. `uint32_t`).
 
   * Be aware that `size_t` (object sizes and indices), `off_t` (file offsets),
     `ptrdiff_t` (the difference between two pointer values), `intptr_t` (an
     integer type large enough to hold the value of a pointer), `uint32_t`,
     `uint64_t`, and so on are not necessarily the same. Use the right type for
-    your purpose.
+    your purpose. `CheckedNumeric` is an ergonomic way to perform safe
+    arithmetic and casting with and between these different types.
 
   * Follow [Google C++ casting
     conventions](https://google.github.io/styleguide/cppguide.html#Casting)
     to convert arithmetic types when you know the conversion is safe. Use
-    `checked_cast<>()` (from `base/numerics/safe_conversions.h`) when you
-    need to enforce via `CHECK()` that the source value is in-range for the
-    destination type. Use `saturated_cast<>()` (from the same file) if you
-    instead wish to clamp out-of-range values.
+    `checked_cast<T>` (from `base/numerics/safe_conversions.h`) when you need to
+    `CHECK` that the source value is in range for the destination type. Use
+    `saturated_cast<T>` if you instead wish to clamp out-of-range values.
 
   * Do not use unsigned types to mean "this value should never be < 0". For
     that, use assertions or run-time checks (as appropriate).
@@ -213,7 +214,7 @@
 
   * When passing values across network or process boundaries, use
     explicitly-sized types for safety, since the sending and receiving ends may
-    not have been compiled with the same sizes for things like int and
+    not have been compiled with the same sizes for things like `int` and
     `size_t`. However, to the greatest degree possible, avoid letting these
     sized types bleed through the APIs of the layers in question.
 
diff --git a/testing/buildbot/chromium.clang.json b/testing/buildbot/chromium.clang.json
index 91b9fa2..0b2ba7f 100644
--- a/testing/buildbot/chromium.clang.json
+++ b/testing/buildbot/chromium.clang.json
@@ -291,16 +291,6 @@
         "test": "headless_browsertests"
       },
       {
-        "args": [
-          "--enable-features=NetworkService"
-        ],
-        "name": "network_service_headless_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "headless_browsertests"
-      },
-      {
         "swarming": {
           "can_use_on_swarming_builders": true
         },
@@ -1114,21 +1104,6 @@
         "test": "headless_browsertests"
       },
       {
-        "args": [
-          "--enable-features=NetworkService"
-        ],
-        "name": "network_service_headless_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Windows-10-15063"
-            }
-          ]
-        },
-        "test": "headless_browsertests"
-      },
-      {
         "swarming": {
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
@@ -2226,21 +2201,6 @@
         "test": "headless_browsertests"
       },
       {
-        "args": [
-          "--enable-features=NetworkService"
-        ],
-        "name": "network_service_headless_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Windows-10-15063"
-            }
-          ]
-        },
-        "test": "headless_browsertests"
-      },
-      {
         "swarming": {
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
@@ -3326,21 +3286,6 @@
         "test": "headless_browsertests"
       },
       {
-        "args": [
-          "--enable-features=NetworkService"
-        ],
-        "name": "network_service_headless_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Windows-10-15063"
-            }
-          ]
-        },
-        "test": "headless_browsertests"
-      },
-      {
         "swarming": {
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
@@ -9432,16 +9377,6 @@
         "test": "headless_browsertests"
       },
       {
-        "args": [
-          "--enable-features=NetworkService"
-        ],
-        "name": "network_service_headless_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "headless_browsertests"
-      },
-      {
         "swarming": {
           "can_use_on_swarming_builders": true
         },
@@ -10124,17 +10059,6 @@
       },
       {
         "args": [
-          "--enable-features=NetworkService",
-          "--test-launcher-print-test-stdio=always"
-        ],
-        "name": "network_service_headless_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "headless_browsertests"
-      },
-      {
-        "args": [
           "--test-launcher-print-test-stdio=always"
         ],
         "swarming": {
@@ -10824,16 +10748,6 @@
         "test": "headless_browsertests"
       },
       {
-        "args": [
-          "--enable-features=NetworkService"
-        ],
-        "name": "network_service_headless_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "headless_browsertests"
-      },
-      {
         "swarming": {
           "can_use_on_swarming_builders": true
         },
@@ -11383,16 +11297,6 @@
         "test": "headless_browsertests"
       },
       {
-        "args": [
-          "--enable-features=NetworkService"
-        ],
-        "name": "network_service_headless_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "headless_browsertests"
-      },
-      {
         "swarming": {
           "can_use_on_swarming_builders": true
         },
@@ -11950,16 +11854,6 @@
         "test": "headless_browsertests"
       },
       {
-        "args": [
-          "--enable-features=NetworkService"
-        ],
-        "name": "network_service_headless_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "headless_browsertests"
-      },
-      {
         "swarming": {
           "can_use_on_swarming_builders": true
         },
@@ -12517,16 +12411,6 @@
         "test": "headless_browsertests"
       },
       {
-        "args": [
-          "--enable-features=NetworkService"
-        ],
-        "name": "network_service_headless_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "headless_browsertests"
-      },
-      {
         "swarming": {
           "can_use_on_swarming_builders": true
         },
@@ -13085,16 +12969,6 @@
         "test": "headless_browsertests"
       },
       {
-        "args": [
-          "--enable-features=NetworkService"
-        ],
-        "name": "network_service_headless_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "headless_browsertests"
-      },
-      {
         "swarming": {
           "can_use_on_swarming_builders": true
         },
@@ -13631,16 +13505,6 @@
         "test": "headless_browsertests"
       },
       {
-        "args": [
-          "--enable-features=NetworkService"
-        ],
-        "name": "network_service_headless_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "headless_browsertests"
-      },
-      {
         "swarming": {
           "can_use_on_swarming_builders": true
         },
@@ -14368,17 +14232,6 @@
       },
       {
         "args": [
-          "--enable-features=NetworkService",
-          "--test-launcher-print-test-stdio=always"
-        ],
-        "name": "network_service_headless_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "headless_browsertests"
-      },
-      {
-        "args": [
           "--test-launcher-print-test-stdio=always"
         ],
         "swarming": {
@@ -15015,16 +14868,6 @@
         "test": "headless_browsertests"
       },
       {
-        "args": [
-          "--enable-features=NetworkService"
-        ],
-        "name": "network_service_headless_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "headless_browsertests"
-      },
-      {
         "swarming": {
           "can_use_on_swarming_builders": true
         },
@@ -15643,16 +15486,6 @@
         "test": "headless_browsertests"
       },
       {
-        "args": [
-          "--enable-features=NetworkService"
-        ],
-        "name": "network_service_headless_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "headless_browsertests"
-      },
-      {
         "swarming": {
           "can_use_on_swarming_builders": true
         },
@@ -16271,16 +16104,6 @@
         "test": "headless_browsertests"
       },
       {
-        "args": [
-          "--enable-features=NetworkService"
-        ],
-        "name": "network_service_headless_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "headless_browsertests"
-      },
-      {
         "swarming": {
           "can_use_on_swarming_builders": true
         },
@@ -16899,16 +16722,6 @@
         "test": "headless_browsertests"
       },
       {
-        "args": [
-          "--enable-features=NetworkService"
-        ],
-        "name": "network_service_headless_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "headless_browsertests"
-      },
-      {
         "swarming": {
           "can_use_on_swarming_builders": true
         },
@@ -17527,16 +17340,6 @@
         "test": "headless_browsertests"
       },
       {
-        "args": [
-          "--enable-features=NetworkService"
-        ],
-        "name": "network_service_headless_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "headless_browsertests"
-      },
-      {
         "swarming": {
           "can_use_on_swarming_builders": true
         },
@@ -18155,16 +17958,6 @@
         "test": "headless_browsertests"
       },
       {
-        "args": [
-          "--enable-features=NetworkService"
-        ],
-        "name": "network_service_headless_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "headless_browsertests"
-      },
-      {
         "swarming": {
           "can_use_on_swarming_builders": true
         },
@@ -18783,16 +18576,6 @@
         "test": "headless_browsertests"
       },
       {
-        "args": [
-          "--enable-features=NetworkService"
-        ],
-        "name": "network_service_headless_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "headless_browsertests"
-      },
-      {
         "swarming": {
           "can_use_on_swarming_builders": true
         },
@@ -19411,16 +19194,6 @@
         "test": "headless_browsertests"
       },
       {
-        "args": [
-          "--enable-features=NetworkService"
-        ],
-        "name": "network_service_headless_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "headless_browsertests"
-      },
-      {
         "swarming": {
           "can_use_on_swarming_builders": true
         },
@@ -20039,16 +19812,6 @@
         "test": "headless_browsertests"
       },
       {
-        "args": [
-          "--enable-features=NetworkService"
-        ],
-        "name": "network_service_headless_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "headless_browsertests"
-      },
-      {
         "swarming": {
           "can_use_on_swarming_builders": true
         },
@@ -20667,16 +20430,6 @@
         "test": "headless_browsertests"
       },
       {
-        "args": [
-          "--enable-features=NetworkService"
-        ],
-        "name": "network_service_headless_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "headless_browsertests"
-      },
-      {
         "swarming": {
           "can_use_on_swarming_builders": true
         },
@@ -21270,16 +21023,6 @@
         "test": "headless_browsertests"
       },
       {
-        "args": [
-          "--enable-features=NetworkService"
-        ],
-        "name": "network_service_headless_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "headless_browsertests"
-      },
-      {
         "swarming": {
           "can_use_on_swarming_builders": true
         },
@@ -22077,21 +21820,6 @@
         "test": "headless_browsertests"
       },
       {
-        "args": [
-          "--enable-features=NetworkService"
-        ],
-        "name": "network_service_headless_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Windows-10"
-            }
-          ]
-        },
-        "test": "headless_browsertests"
-      },
-      {
         "swarming": {
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index 74062ec..93054fa 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -645,16 +645,6 @@
         "test": "headless_browsertests"
       },
       {
-        "args": [
-          "--enable-features=NetworkService"
-        ],
-        "name": "network_service_headless_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "headless_browsertests"
-      },
-      {
         "swarming": {
           "can_use_on_swarming_builders": true
         },
@@ -2677,16 +2667,6 @@
         "test": "headless_browsertests"
       },
       {
-        "args": [
-          "--enable-features=NetworkService"
-        ],
-        "name": "network_service_headless_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "headless_browsertests"
-      },
-      {
         "swarming": {
           "can_use_on_swarming_builders": false
         },
@@ -6126,16 +6106,6 @@
         "test": "headless_browsertests"
       },
       {
-        "args": [
-          "--enable-features=NetworkService"
-        ],
-        "name": "network_service_headless_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "headless_browsertests"
-      },
-      {
         "swarming": {
           "can_use_on_swarming_builders": true
         },
@@ -6880,17 +6850,6 @@
         "test": "headless_browsertests"
       },
       {
-        "args": [
-          "--enable-features=NetworkService"
-        ],
-        "isolate_coverage_data": true,
-        "name": "network_service_headless_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "headless_browsertests"
-      },
-      {
         "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
@@ -10219,16 +10178,6 @@
         "test": "headless_browsertests"
       },
       {
-        "args": [
-          "--enable-features=NetworkService"
-        ],
-        "name": "network_service_headless_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "headless_browsertests"
-      },
-      {
         "swarming": {
           "can_use_on_swarming_builders": true
         },
@@ -11319,23 +11268,6 @@
         "test": "headless_browsertests"
       },
       {
-        "args": [
-          "--enable-features=NetworkService"
-        ],
-        "name": "network_service_headless_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "8086:0a2e",
-              "os": "Mac-10.14"
-            }
-          ],
-          "expiration": 21600
-        },
-        "test": "headless_browsertests"
-      },
-      {
         "swarming": {
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
diff --git a/testing/buildbot/chromium.linux.json b/testing/buildbot/chromium.linux.json
index 22185c6..ab1db71 100644
--- a/testing/buildbot/chromium.linux.json
+++ b/testing/buildbot/chromium.linux.json
@@ -1333,16 +1333,6 @@
         "test": "headless_browsertests"
       },
       {
-        "args": [
-          "--enable-features=NetworkService"
-        ],
-        "name": "network_service_headless_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "headless_browsertests"
-      },
-      {
         "swarming": {
           "can_use_on_swarming_builders": true
         },
@@ -2083,16 +2073,6 @@
         "test": "headless_browsertests"
       },
       {
-        "args": [
-          "--enable-features=NetworkService"
-        ],
-        "name": "network_service_headless_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "headless_browsertests"
-      },
-      {
         "swarming": {
           "can_use_on_swarming_builders": true
         },
@@ -2794,16 +2774,6 @@
         "test": "headless_browsertests"
       },
       {
-        "args": [
-          "--enable-features=NetworkService"
-        ],
-        "name": "network_service_headless_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "headless_browsertests"
-      },
-      {
         "swarming": {
           "can_use_on_swarming_builders": true
         },
@@ -3687,21 +3657,6 @@
         "test": "headless_browsertests"
       },
       {
-        "args": [
-          "--enable-features=NetworkService"
-        ],
-        "name": "network_service_headless_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Ubuntu-16.04"
-            }
-          ]
-        },
-        "test": "headless_browsertests"
-      },
-      {
         "swarming": {
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
diff --git a/testing/buildbot/chromium.mac.json b/testing/buildbot/chromium.mac.json
index 949639e3..f631435 100644
--- a/testing/buildbot/chromium.mac.json
+++ b/testing/buildbot/chromium.mac.json
@@ -515,22 +515,6 @@
         "test": "headless_browsertests"
       },
       {
-        "args": [
-          "--enable-features=NetworkService"
-        ],
-        "name": "network_service_headless_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "none",
-              "os": "Mac-10.10"
-            }
-          ]
-        },
-        "test": "headless_browsertests"
-      },
-      {
         "swarming": {
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
@@ -1676,22 +1660,6 @@
         "test": "headless_browsertests"
       },
       {
-        "args": [
-          "--enable-features=NetworkService"
-        ],
-        "name": "network_service_headless_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "none",
-              "os": "Mac-10.11"
-            }
-          ]
-        },
-        "test": "headless_browsertests"
-      },
-      {
         "swarming": {
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
@@ -2837,22 +2805,6 @@
         "test": "headless_browsertests"
       },
       {
-        "args": [
-          "--enable-features=NetworkService"
-        ],
-        "name": "network_service_headless_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "8086:0a2e",
-              "os": "Mac-10.12.6"
-            }
-          ]
-        },
-        "test": "headless_browsertests"
-      },
-      {
         "swarming": {
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
@@ -3998,22 +3950,6 @@
         "test": "headless_browsertests"
       },
       {
-        "args": [
-          "--enable-features=NetworkService"
-        ],
-        "name": "network_service_headless_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "none",
-              "os": "Mac-10.13"
-            }
-          ]
-        },
-        "test": "headless_browsertests"
-      },
-      {
         "swarming": {
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
@@ -5152,22 +5088,6 @@
         "test": "headless_browsertests"
       },
       {
-        "args": [
-          "--enable-features=NetworkService"
-        ],
-        "name": "network_service_headless_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "none",
-              "os": "Mac-10.13"
-            }
-          ]
-        },
-        "test": "headless_browsertests"
-      },
-      {
         "swarming": {
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
diff --git a/testing/buildbot/chromium.memory.json b/testing/buildbot/chromium.memory.json
index 55c77398..e7c24922 100644
--- a/testing/buildbot/chromium.memory.json
+++ b/testing/buildbot/chromium.memory.json
@@ -3061,17 +3061,6 @@
       },
       {
         "args": [
-          "--enable-features=NetworkService",
-          "--test-launcher-print-test-stdio=always"
-        ],
-        "name": "network_service_headless_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "headless_browsertests"
-      },
-      {
-        "args": [
           "--test-launcher-print-test-stdio=always"
         ],
         "swarming": {
@@ -3815,16 +3804,6 @@
         "test": "headless_browsertests"
       },
       {
-        "args": [
-          "--enable-features=NetworkService"
-        ],
-        "name": "network_service_headless_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "headless_browsertests"
-      },
-      {
         "swarming": {
           "can_use_on_swarming_builders": true
         },
@@ -7271,23 +7250,6 @@
       },
       {
         "args": [
-          "--enable-features=NetworkService",
-          "--test-launcher-print-test-stdio=always"
-        ],
-        "name": "network_service_headless_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "cpu": "x86-64",
-              "os": "Ubuntu-14.04"
-            }
-          ]
-        },
-        "test": "headless_browsertests"
-      },
-      {
-        "args": [
           "--test-launcher-print-test-stdio=always"
         ],
         "swarming": {
@@ -8333,17 +8295,6 @@
       },
       {
         "args": [
-          "--enable-features=NetworkService",
-          "--test-launcher-print-test-stdio=always"
-        ],
-        "name": "network_service_headless_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "headless_browsertests"
-      },
-      {
-        "args": [
           "--test-launcher-print-test-stdio=always"
         ],
         "swarming": {
@@ -9097,17 +9048,6 @@
       },
       {
         "args": [
-          "--enable-features=NetworkService",
-          "--test-launcher-print-test-stdio=always"
-        ],
-        "name": "network_service_headless_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "headless_browsertests"
-      },
-      {
-        "args": [
           "--test-launcher-print-test-stdio=always"
         ],
         "swarming": {
@@ -10083,21 +10023,6 @@
         "test": "headless_browsertests"
       },
       {
-        "args": [
-          "--enable-features=NetworkService"
-        ],
-        "name": "network_service_headless_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Windows-10-15063"
-            }
-          ]
-        },
-        "test": "headless_browsertests"
-      },
-      {
         "swarming": {
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
diff --git a/testing/buildbot/chromium.win.json b/testing/buildbot/chromium.win.json
index 43333734..9f7d924 100644
--- a/testing/buildbot/chromium.win.json
+++ b/testing/buildbot/chromium.win.json
@@ -336,16 +336,6 @@
         "test": "headless_browsertests"
       },
       {
-        "args": [
-          "--enable-features=NetworkService"
-        ],
-        "name": "network_service_headless_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "headless_browsertests"
-      },
-      {
         "swarming": {
           "can_use_on_swarming_builders": true
         },
@@ -1384,22 +1374,6 @@
         "test": "headless_browsertests"
       },
       {
-        "args": [
-          "--enable-features=NetworkService"
-        ],
-        "name": "network_service_headless_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "cpu": "x86-64",
-              "os": "Windows-10-15063"
-            }
-          ]
-        },
-        "test": "headless_browsertests"
-      },
-      {
         "swarming": {
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
@@ -2573,22 +2547,6 @@
         "test": "headless_browsertests"
       },
       {
-        "args": [
-          "--enable-features=NetworkService"
-        ],
-        "name": "network_service_headless_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "cpu": "x86-64",
-              "os": "Windows-10-15063"
-            }
-          ]
-        },
-        "test": "headless_browsertests"
-      },
-      {
         "swarming": {
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
@@ -3689,16 +3647,6 @@
         "test": "headless_browsertests"
       },
       {
-        "args": [
-          "--enable-features=NetworkService"
-        ],
-        "name": "network_service_headless_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "headless_browsertests"
-      },
-      {
         "swarming": {
           "can_use_on_swarming_builders": true
         },
@@ -4456,16 +4404,6 @@
         "test": "headless_browsertests"
       },
       {
-        "args": [
-          "--enable-features=NetworkService"
-        ],
-        "name": "network_service_headless_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "headless_browsertests"
-      },
-      {
         "swarming": {
           "can_use_on_swarming_builders": true
         },
diff --git a/testing/buildbot/filters/mojo.fyi.network_webview_instrumentation_test_apk.filter b/testing/buildbot/filters/mojo.fyi.network_webview_instrumentation_test_apk.filter
index ebff8b3..c79f0da 100644
--- a/testing/buildbot/filters/mojo.fyi.network_webview_instrumentation_test_apk.filter
+++ b/testing/buildbot/filters/mojo.fyi.network_webview_instrumentation_test_apk.filter
@@ -8,9 +8,6 @@
 # tests are also running with NS IP. Multiprocess webview currently does not
 # support running NS OOP, https://crbug.com/882650
 
-# Uncategorized timeouts or test failures.
--org.chromium.android_webview.test.AwContentsStaticsTest.testSetCheckClearTextPermittedTrue
-
 # https://crbug.com/893566
 -org.chromium.android_webview.test.AwContentsClientShouldInterceptRequestTest.testBaseUrlOfLoadDataSentInRefererHeader
 -org.chromium.android_webview.test.AwContentsClientShouldInterceptRequestTest.testCalledForUnsupportedSchemes
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl
index b89d92b9..79bf410 100644
--- a/testing/buildbot/test_suites.pyl
+++ b/testing/buildbot/test_suites.pyl
@@ -3994,12 +3994,6 @@
       'cronet_tests': {},
       'cronet_unittests': {},
       'headless_browsertests': {},
-      'network_service_headless_browsertests': {
-        'args': [
-          '--enable-features=NetworkService',
-        ],
-        'test': 'headless_browsertests',
-      },
       'headless_unittests': {},
     },
 
diff --git a/testing/buildbot/tryserver.chromium.linux.json b/testing/buildbot/tryserver.chromium.linux.json
index 90f517f..a1e52d61e 100644
--- a/testing/buildbot/tryserver.chromium.linux.json
+++ b/testing/buildbot/tryserver.chromium.linux.json
@@ -315,17 +315,6 @@
         "test": "headless_browsertests"
       },
       {
-        "args": [
-          "--enable-features=NetworkService"
-        ],
-        "isolate_coverage_data": true,
-        "name": "network_service_headless_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "headless_browsertests"
-      },
-      {
         "isolate_coverage_data": true,
         "swarming": {
           "can_use_on_swarming_builders": true
diff --git a/testing/iossim/iossim.mm b/testing/iossim/iossim.mm
index a6ac57b..1cf3be2 100644
--- a/testing/iossim/iossim.mm
+++ b/testing/iossim/iossim.mm
@@ -273,11 +273,8 @@
 
   if (xctest_path) {
     [testTargetName setValue:xctest_path forKey:@"TestBundlePath"];
-    NSString* inject =
-        @"__PLATFORMS__/iPhoneSimulator.platform/Developer/Library/"
-        @"PrivateFrameworks/IDEBundleInjection.framework/"
-        @"IDEBundleInjection:__PLATFORMS__/iPhoneSimulator.platform/Developer/"
-        @"usr/lib/libXCTestBundleInject.dylib";
+    NSString* inject = @"__PLATFORMS__/iPhoneSimulator.platform/Developer/"
+                       @"usr/lib/libXCTestBundleInject.dylib";
     [testingEnvironmentVariables setValue:inject
                                    forKey:@"DYLD_INSERT_LIBRARIES"];
     [testingEnvironmentVariables
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index 857e314c..02ac9e2 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -401,29 +401,6 @@
             ]
         }
     ],
-    "AndroidInProductHelpPreviewsOmniboxUI": [
-        {
-            "platforms": [
-                "android"
-            ],
-            "experiments": [
-                {
-                    "name": "EnabledTracking",
-                    "params": {
-                        "availability": "any",
-                        "event_preview_loaded": "name:preview_page_load;comparator:>=1;window:90;storage:360",
-                        "event_trigger": "name:previews_verbose_iph_triggered;comparator:<2;window:90;storage:360",
-                        "event_used": "name:previews_verbose_status_opened;comparator:==0;window:90;storage:360",
-                        "session_rate": "==0",
-                        "tracking_only": "true"
-                    },
-                    "enable_features": [
-                        "IPH_PreviewsOmniboxUI"
-                    ]
-                }
-            ]
-        }
-    ],
     "AndroidInProductHelpTranslateMenuButton": [
         {
             "platforms": [
@@ -2320,6 +2297,24 @@
             ]
         }
     ],
+    "InspectRarContent": [
+        {
+            "platforms": [
+                "chromeos",
+                "linux",
+                "mac",
+                "windows"
+            ],
+            "experiments": [
+                {
+                    "name": "Enabled",
+                    "enable_features": [
+                        "InspectRarContent"
+                    ]
+                }
+            ]
+        }
+    ],
     "InstanceID": [
         {
             "platforms": [
@@ -3774,8 +3769,20 @@
             ],
             "experiments": [
                 {
-                    "name": "Enabled_20190214",
+                    "name": "Enabled_OverridePH_20190221",
+                    "params": {
+                        "availability": "any",
+                        "blacklisted_path_suffixes": ".apk,.avi,.gif,.gifv,.jpeg,.jpg,.mp3,.mp4,.mpeg,.pdf,.png,.webm,.webp",
+                        "event_preview_loaded": "name:preview_page_load;comparator:>=1;window:90;storage:360",
+                        "event_trigger": "name:previews_verbose_iph_triggered;comparator:<2;window:90;storage:360",
+                        "event_used": "name:previews_verbose_status_opened;comparator:==0;window:90;storage:360",
+                        "override_pagehints": "true",
+                        "session_rate": "==0",
+                        "tracking_only": "true"
+                    },
                     "enable_features": [
+                        "AndroidOmniboxPreviewsBadge",
+                        "IPH_PreviewsOmniboxUI",
                         "LitePageServerPreviews"
                     ]
                 }
@@ -4811,6 +4818,26 @@
             ]
         }
     ],
+    "SyncScryptCustomPassphrase": [
+        {
+            "platforms": [
+                "android",
+                "chromeos",
+                "ios",
+                "linux",
+                "mac",
+                "windows"
+            ],
+            "experiments": [
+                {
+                    "name": "Enabled",
+                    "enable_features": [
+                        "SyncUseScryptForNewCustomPassphrases"
+                    ]
+                }
+            ]
+        }
+    ],
     "SyncUssBookmarks'": [
         {
             "platforms": [
diff --git a/third_party/abseil-cpp/README.chromium b/third_party/abseil-cpp/README.chromium
index 14007b6..c0b5dee 100644
--- a/third_party/abseil-cpp/README.chromium
+++ b/third_party/abseil-cpp/README.chromium
@@ -4,7 +4,7 @@
 License: Apache 2.0
 License File: LICENSE
 Version: 0
-Revision: 2901ec32a919311384d6ad4194e2d927c06831f7
+Revision: 93d155bc4414f6c121bb1f19dba9fdb27c8943bc
 Security Critical: yes
 
 Description:
diff --git a/third_party/abseil-cpp/absl/container/flat_hash_map.h b/third_party/abseil-cpp/absl/container/flat_hash_map.h
index cc3d8b6..f6d2847 100644
--- a/third_party/abseil-cpp/absl/container/flat_hash_map.h
+++ b/third_party/abseil-cpp/absl/container/flat_hash_map.h
@@ -527,25 +527,26 @@
 
 template <class K, class V>
 struct FlatHashMapPolicy {
-  using slot_type = container_internal::slot_type<K, V>;
+  using slot_policy = container_internal::map_slot_policy<K, V>;
+  using slot_type = typename slot_policy::slot_type;
   using key_type = K;
   using mapped_type = V;
   using init_type = std::pair</*non const*/ key_type, mapped_type>;
 
   template <class Allocator, class... Args>
   static void construct(Allocator* alloc, slot_type* slot, Args&&... args) {
-    slot_type::construct(alloc, slot, std::forward<Args>(args)...);
+    slot_policy::construct(alloc, slot, std::forward<Args>(args)...);
   }
 
   template <class Allocator>
   static void destroy(Allocator* alloc, slot_type* slot) {
-    slot_type::destroy(alloc, slot);
+    slot_policy::destroy(alloc, slot);
   }
 
   template <class Allocator>
   static void transfer(Allocator* alloc, slot_type* new_slot,
                        slot_type* old_slot) {
-    slot_type::transfer(alloc, new_slot, old_slot);
+    slot_policy::transfer(alloc, new_slot, old_slot);
   }
 
   template <class F, class... Args>
diff --git a/third_party/abseil-cpp/absl/container/internal/common.h b/third_party/abseil-cpp/absl/container/internal/common.h
index c781656..aca1a95 100644
--- a/third_party/abseil-cpp/absl/container/internal/common.h
+++ b/third_party/abseil-cpp/absl/container/internal/common.h
@@ -15,6 +15,7 @@
 #ifndef ABSL_CONTAINER_INTERNAL_CONTAINER_H_
 #define ABSL_CONTAINER_INTERNAL_CONTAINER_H_
 
+#include <cassert>
 #include <type_traits>
 
 #include "absl/meta/type_traits.h"
diff --git a/third_party/abseil-cpp/absl/container/internal/container_memory.h b/third_party/abseil-cpp/absl/container/internal/container_memory.h
index 35b691c..3a3f970 100644
--- a/third_party/abseil-cpp/absl/container/internal/container_memory.h
+++ b/third_party/abseil-cpp/absl/container/internal/container_memory.h
@@ -311,7 +311,23 @@
 // kMutableKeys. For C++11, the relevant section of the standard is
 // https://timsong-cpp.github.io/cppwp/n3337/class.mem#19 (9.2.19)
 template <class K, class V>
-union slot_type {
+union map_slot_type {
+  map_slot_type() {}
+  ~map_slot_type() = delete;
+  using value_type = std::pair<const K, V>;
+  using mutable_value_type = std::pair<K, V>;
+
+  value_type value;
+  mutable_value_type mutable_value;
+  K key;
+};
+
+template <class K, class V>
+struct map_slot_policy {
+  using slot_type = map_slot_type<K, V>;
+  using value_type = std::pair<const K, V>;
+  using mutable_value_type = std::pair<K, V>;
+
  private:
   static void emplace(slot_type* slot) {
     // The construction of union doesn't do anything at runtime but it allows us
@@ -321,19 +337,17 @@
   // If pair<const K, V> and pair<K, V> are layout-compatible, we can accept one
   // or the other via slot_type. We are also free to access the key via
   // slot_type::key in this case.
-  using kMutableKeys =
-      std::integral_constant<bool,
-                             memory_internal::IsLayoutCompatible<K, V>::value>;
+  using kMutableKeys = memory_internal::IsLayoutCompatible<K, V>;
 
  public:
-  slot_type() {}
-  ~slot_type() = delete;
-  using value_type = std::pair<const K, V>;
-  using mutable_value_type = std::pair<K, V>;
+  static value_type& element(slot_type* slot) { return slot->value; }
+  static const value_type& element(const slot_type* slot) {
+    return slot->value;
+  }
 
-  value_type value;
-  mutable_value_type mutable_value;
-  K key;
+  static const K& key(const slot_type* slot) {
+    return kMutableKeys::value ? slot->key : slot->value.first;
+  }
 
   template <class Allocator, class... Args>
   static void construct(Allocator* alloc, slot_type* slot, Args&&... args) {
diff --git a/third_party/abseil-cpp/absl/container/internal/hashtablez_sampler.h b/third_party/abseil-cpp/absl/container/internal/hashtablez_sampler.h
index 8b81653a5..e2d8f364 100644
--- a/third_party/abseil-cpp/absl/container/internal/hashtablez_sampler.h
+++ b/third_party/abseil-cpp/absl/container/internal/hashtablez_sampler.h
@@ -33,6 +33,7 @@
 
 #include "absl/base/internal/per_thread_tls.h"
 #include "absl/base/optimization.h"
+#include "absl/container/internal/have_sse.h"
 #include "absl/synchronization/mutex.h"
 #include "absl/utility/utility.h"
 
@@ -82,10 +83,24 @@
   void* stack[kMaxStackDepth];
 };
 
+inline void RecordRehashSlow(HashtablezInfo* info, size_t total_probe_length) {
+#if SWISSTABLE_HAVE_SSE2
+  total_probe_length /= 16;
+#else
+  total_probe_length /= 8;
+#endif
+  info->total_probe_length.store(total_probe_length, std::memory_order_relaxed);
+  info->num_erases.store(0, std::memory_order_relaxed);
+}
+
 inline void RecordStorageChangedSlow(HashtablezInfo* info, size_t size,
                                      size_t capacity) {
   info->size.store(size, std::memory_order_relaxed);
   info->capacity.store(capacity, std::memory_order_relaxed);
+  if (size == 0) {
+    // This is a clear, reset the total/num_erases too.
+    RecordRehashSlow(info, 0);
+  }
 }
 
 void RecordInsertSlow(HashtablezInfo* info, size_t hash,
@@ -126,6 +141,11 @@
     RecordStorageChangedSlow(info_, size, capacity);
   }
 
+  inline void RecordRehash(size_t total_probe_length) {
+    if (ABSL_PREDICT_TRUE(info_ == nullptr)) return;
+    RecordRehashSlow(info_, total_probe_length);
+  }
+
   inline void RecordInsert(size_t hash, size_t distance_from_desired) {
     if (ABSL_PREDICT_TRUE(info_ == nullptr)) return;
     RecordInsertSlow(info_, hash, distance_from_desired);
diff --git a/third_party/abseil-cpp/absl/container/internal/hashtablez_sampler_test.cc b/third_party/abseil-cpp/absl/container/internal/hashtablez_sampler_test.cc
index f9ee941a..a6e4ac81 100644
--- a/third_party/abseil-cpp/absl/container/internal/hashtablez_sampler_test.cc
+++ b/third_party/abseil-cpp/absl/container/internal/hashtablez_sampler_test.cc
@@ -145,6 +145,29 @@
   EXPECT_EQ(info.num_erases.load(), 1);
 }
 
+TEST(HashtablezInfoTest, RecordRehash) {
+  HashtablezInfo info;
+  absl::MutexLock l(&info.init_mu);
+  info.PrepareForSampling();
+  RecordInsertSlow(&info, 0x1, 0);
+  RecordInsertSlow(&info, 0x2, kProbeLength);
+  RecordInsertSlow(&info, 0x4, kProbeLength);
+  RecordInsertSlow(&info, 0x8, 2 * kProbeLength);
+  EXPECT_EQ(info.size.load(), 4);
+  EXPECT_EQ(info.total_probe_length.load(), 4);
+
+  RecordEraseSlow(&info);
+  RecordEraseSlow(&info);
+  EXPECT_EQ(info.size.load(), 2);
+  EXPECT_EQ(info.total_probe_length.load(), 4);
+  EXPECT_EQ(info.num_erases.load(), 2);
+
+  RecordRehashSlow(&info, 3 * kProbeLength);
+  EXPECT_EQ(info.size.load(), 2);
+  EXPECT_EQ(info.total_probe_length.load(), 3);
+  EXPECT_EQ(info.num_erases.load(), 0);
+}
+
 TEST(HashtablezSamplerTest, SmallSampleParameter) {
   SetHashtablezEnabled(true);
   SetHashtablezSampleParameter(100);
diff --git a/third_party/abseil-cpp/absl/container/internal/raw_hash_set.h b/third_party/abseil-cpp/absl/container/internal/raw_hash_set.h
index a5d0cae..33f8f8f 100644
--- a/third_party/abseil-cpp/absl/container/internal/raw_hash_set.h
+++ b/third_party/abseil-cpp/absl/container/internal/raw_hash_set.h
@@ -936,7 +936,7 @@
       reset_growth_left();
     }
     assert(empty());
-    infoz_.RecordStorageChanged(size_, capacity_);
+    infoz_.RecordStorageChanged(0, capacity_);
   }
 
   // This overload kicks in when the argument is an rvalue of insertable and
@@ -1226,7 +1226,7 @@
     if (n == 0 && capacity_ == 0) return;
     if (n == 0 && size_ == 0) {
       destroy_slots();
-      infoz_.RecordStorageChanged(size_, capacity_);
+      infoz_.RecordStorageChanged(0, 0);
       return;
     }
     // bitor is a faster way of doing `max` here. We will round up to the next
@@ -1483,11 +1483,14 @@
     capacity_ = new_capacity;
     initialize_slots();
 
+    size_t total_probe_length = 0;
     for (size_t i = 0; i != old_capacity; ++i) {
       if (IsFull(old_ctrl[i])) {
         size_t hash = PolicyTraits::apply(HashElement{hash_ref()},
                                           PolicyTraits::element(old_slots + i));
-        size_t new_i = find_first_non_full(hash).offset;
+        auto target = find_first_non_full(hash);
+        size_t new_i = target.offset;
+        total_probe_length += target.probe_length;
         set_ctrl(new_i, H2(hash));
         PolicyTraits::transfer(&alloc_ref(), slots_ + new_i, old_slots + i);
       }
@@ -1499,6 +1502,7 @@
       Deallocate<Layout::Alignment()>(&alloc_ref(), old_ctrl,
                                       layout.AllocSize());
     }
+    infoz_.RecordRehash(total_probe_length);
   }
 
   void drop_deletes_without_resize() ABSL_ATTRIBUTE_NOINLINE {
@@ -1522,12 +1526,15 @@
     ConvertDeletedToEmptyAndFullToDeleted(ctrl_, capacity_);
     typename std::aligned_storage<sizeof(slot_type), alignof(slot_type)>::type
         raw;
+    size_t total_probe_length = 0;
     slot_type* slot = reinterpret_cast<slot_type*>(&raw);
     for (size_t i = 0; i != capacity_; ++i) {
       if (!IsDeleted(ctrl_[i])) continue;
       size_t hash = PolicyTraits::apply(HashElement{hash_ref()},
                                         PolicyTraits::element(slots_ + i));
-      size_t new_i = find_first_non_full(hash).offset;
+      auto target = find_first_non_full(hash);
+      size_t new_i = target.offset;
+      total_probe_length += target.probe_length;
 
       // Verify if the old and new i fall within the same group wrt the hash.
       // If they do, we don't need to move the object as it falls already in the
@@ -1560,6 +1567,7 @@
       }
     }
     reset_growth_left();
+    infoz_.RecordRehash(total_probe_length);
   }
 
   void rehash_and_grow_if_necessary() {
diff --git a/third_party/abseil-cpp/absl/copts/AbseilConfigureCopts.cmake b/third_party/abseil-cpp/absl/copts/AbseilConfigureCopts.cmake
index 6fde775..f68895d 100644
--- a/third_party/abseil-cpp/absl/copts/AbseilConfigureCopts.cmake
+++ b/third_party/abseil-cpp/absl/copts/AbseilConfigureCopts.cmake
@@ -1,6 +1,9 @@
 # See absl/copts/copts.py and absl/copts/generate_copts.py
 include(GENERATED_AbseilCopts)
 
+set(ABSL_LSAN_LINKOPTS "")
+set(ABSL_HAVE_LSAN OFF)
+
 if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
   set(ABSL_DEFAULT_COPTS "${GCC_FLAGS}")
   set(ABSL_TEST_COPTS "${GCC_FLAGS};${GCC_TEST_FLAGS}")
@@ -10,6 +13,14 @@
   set(ABSL_DEFAULT_COPTS "${LLVM_FLAGS}")
   set(ABSL_TEST_COPTS "${LLVM_FLAGS};${LLVM_TEST_FLAGS}")
   set(ABSL_EXCEPTIONS_FLAG "${LLVM_EXCEPTIONS_FLAGS}")
+  if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
+    # AppleClang doesn't have lsan
+    # https://developer.apple.com/documentation/code_diagnostics
+    if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 3.5)
+      set(ABSL_LSAN_LINKOPTS "-fsanitize=leak")
+      set(ABSL_HAVE_LSAN ON)
+    endif()
+  endif()
 elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
   set(ABSL_DEFAULT_COPTS "${MSVC_FLAGS}")
   set(ABSL_TEST_COPTS "${MSVC_FLAGS};${MSVC_TEST_FLAGS}")
diff --git a/third_party/abseil-cpp/absl/debugging/CMakeLists.txt b/third_party/abseil-cpp/absl/debugging/CMakeLists.txt
index 4c1fc50..3451152 100644
--- a/third_party/abseil-cpp/absl/debugging/CMakeLists.txt
+++ b/third_party/abseil-cpp/absl/debugging/CMakeLists.txt
@@ -199,11 +199,6 @@
   PUBLIC
 )
 
-# TODO(cohenjon) Move into the copts code.
-if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
-  set(ABSL_LSAN_LINKOPTS "-fsanitize=leak")
-endif()
-
 absl_cc_library(
   NAME
     leak_check_api_enabled_for_testing
@@ -212,7 +207,7 @@
   SRCS
     "leak_check.cc"
   COPTS
-    $<$<BOOL:${ABSL_USING_CLANG}>:-DLEAK_SANITIZER>
+    $<$<BOOL:${ABSL_HAVE_LSAN}>:-DLEAK_SANITIZER>
   TESTONLY
 )
 
@@ -234,7 +229,7 @@
   SRCS
     "leak_check_test.cc"
   COPTS
-    "$<$<CXX_COMPILER_ID:Clang>:-DABSL_EXPECT_LEAK_SANITIZER>"
+    "$<$<BOOL:${ABSL_HAVE_LSAN}>:-DABSL_EXPECT_LEAK_SANITIZER>"
   LINKOPTS
     "${ABSL_LSAN_LINKOPTS}"
   DEPS
diff --git a/third_party/abseil-cpp/absl/hash/hash_test.cc b/third_party/abseil-cpp/absl/hash/hash_test.cc
index a5af93a..2c9e46b 100644
--- a/third_party/abseil-cpp/absl/hash/hash_test.cc
+++ b/third_party/abseil-cpp/absl/hash/hash_test.cc
@@ -135,6 +135,36 @@
       std::make_tuple(&i, ptr, nullptr, ptr + 1, n)));
 }
 
+TEST(HashValueTest, PointerAlignment) {
+  // We want to make sure that pointer alignment will not cause bits to be
+  // stuck.
+
+  constexpr size_t kTotalSize = 1 << 20;
+  std::unique_ptr<char[]> data(new char[kTotalSize]);
+  constexpr size_t kLog2NumValues = 5;
+  constexpr size_t kNumValues = 1 << kLog2NumValues;
+
+  for (size_t align = 1; align < kTotalSize / kNumValues;
+       align < 8 ? align += 1 : align < 1024 ? align += 8 : align += 32) {
+    SCOPED_TRACE(align);
+    ASSERT_LE(align * kNumValues, kTotalSize);
+
+    size_t bits_or = 0;
+    size_t bits_and = ~size_t{};
+
+    for (size_t i = 0; i < kNumValues; ++i) {
+      size_t hash = absl::Hash<void*>()(data.get() + i * align);
+      bits_or |= hash;
+      bits_and &= hash;
+    }
+
+    // Limit the scope to the bits we would be using for Swisstable.
+    constexpr size_t kMask = (1 << (kLog2NumValues + 7)) - 1;
+    size_t stuck_bits = (~bits_or | bits_and) & kMask;
+    EXPECT_EQ(stuck_bits, 0) << "0x" << std::hex << stuck_bits;
+  }
+}
+
 // TODO(EricWF): MSVC 15 has a bug that causes it to incorrectly evaluate the
 // SFINAE in internal/hash.h, causing this test to fail.
 #if !defined(_MSC_VER)
diff --git a/third_party/abseil-cpp/absl/hash/internal/hash.h b/third_party/abseil-cpp/absl/hash/internal/hash.h
index ba6d746..bd07677a 100644
--- a/third_party/abseil-cpp/absl/hash/internal/hash.h
+++ b/third_party/abseil-cpp/absl/hash/internal/hash.h
@@ -264,7 +264,12 @@
 // AbslHashValue() for hashing pointers
 template <typename H, typename T>
 H AbslHashValue(H hash_state, T* ptr) {
-  return hash_internal::hash_bytes(std::move(hash_state), ptr);
+  auto v = reinterpret_cast<uintptr_t>(ptr);
+  // Due to alignment, pointers tend to have low bits as zero, and the next few
+  // bits follow a pattern since they are also multiples of some base value.
+  // Mixing the pointer twice helps prevent stuck low bits for certain alignment
+  // values.
+  return H::combine(std::move(hash_state), v, v);
 }
 
 // AbslHashValue() for hashing nullptr_t
diff --git a/third_party/abseil-cpp/absl/memory/memory.h b/third_party/abseil-cpp/absl/memory/memory.h
index 8bf4fe8..75506a7 100644
--- a/third_party/abseil-cpp/absl/memory/memory.h
+++ b/third_party/abseil-cpp/absl/memory/memory.h
@@ -646,7 +646,7 @@
     : memory_internal::ExtractOrT<memory_internal::GetIsNothrow, Alloc,
                                   std::false_type> {};
 
-#if ABSL_ALLOCATOR_NOTHROW
+#if defined(ABSL_ALLOCATOR_NOTHROW) && ABSL_ALLOCATOR_NOTHROW
 template <typename T>
 struct allocator_is_nothrow<std::allocator<T>> : std::true_type {};
 struct default_allocator_is_nothrow : std::true_type {};
diff --git a/third_party/abseil-cpp/absl/strings/match.h b/third_party/abseil-cpp/absl/strings/match.h
index 6e8ed10f..3a4fefd 100644
--- a/third_party/abseil-cpp/absl/strings/match.h
+++ b/third_party/abseil-cpp/absl/strings/match.h
@@ -74,13 +74,13 @@
 
 // StartsWithIgnoreCase()
 //
-// Returns whether a given ASCII string `text` starts with `starts_with`,
+// Returns whether a given ASCII string `text` starts with `prefix`,
 // ignoring case in the comparison.
 bool StartsWithIgnoreCase(absl::string_view text, absl::string_view prefix);
 
 // EndsWithIgnoreCase()
 //
-// Returns whether a given ASCII string `text` ends with `ends_with`, ignoring
+// Returns whether a given ASCII string `text` ends with `suffix`, ignoring
 // case in the comparison.
 bool EndsWithIgnoreCase(absl::string_view text, absl::string_view suffix);
 
diff --git a/third_party/abseil-cpp/absl/strings/str_split.h b/third_party/abseil-cpp/absl/strings/str_split.h
index c7eb280..86effd3 100644
--- a/third_party/abseil-cpp/absl/strings/str_split.h
+++ b/third_party/abseil-cpp/absl/strings/str_split.h
@@ -72,22 +72,23 @@
 //   - `MaxSplits`
 //
 //
-// A Delimiter's Find() member function will be passed the input text that is to
-// be split and the position to begin searching for the next delimiter in the
-// input text. The returned absl::string_view should refer to the next
-// occurrence (after pos) of the represented delimiter; this returned
-// absl::string_view represents the next location where the input string should
-// be broken. The returned absl::string_view may be zero-length if the Delimiter
-// does not represent a part of the string (e.g., a fixed-length delimiter). If
-// no delimiter is found in the given text, a zero-length absl::string_view
-// referring to text.end() should be returned (e.g.,
-// absl::string_view(text.end(), 0)). It is important that the returned
-// absl::string_view always be within the bounds of input text given as an
+// A Delimiter's `Find()` member function will be passed an input `text` that is
+// to be split and a position (`pos`) to begin searching for the next delimiter
+// in `text`. The returned absl::string_view should refer to the next occurrence
+// (after `pos`) of the represented delimiter; this returned absl::string_view
+// represents the next location where the input `text` should be broken.
+//
+// The returned absl::string_view may be zero-length if the Delimiter does not
+// represent a part of the string (e.g., a fixed-length delimiter). If no
+// delimiter is found in the input `text`, a zero-length absl::string_view
+// referring to `text.end()` should be returned (e.g.,
+// `text.substr(text.size())`). It is important that the returned
+// absl::string_view always be within the bounds of the input `text` given as an
 // argument--it must not refer to a string that is physically located outside of
 // the given string.
 //
 // The following example is a simple Delimiter object that is created with a
-// single char and will look for that char in the text passed to the Find()
+// single char and will look for that char in the text passed to the `Find()`
 // function:
 //
 //   struct SimpleDelimiter {
@@ -96,9 +97,9 @@
 //     absl::string_view Find(absl::string_view text, size_t pos) {
 //       auto found = text.find(c_, pos);
 //       if (found == absl::string_view::npos)
-//         return absl::string_view(text.end(), 0);
+//         return text.substr(text.size());
 //
-//       return absl::string_view(text, found, 1);
+//       return text.substr(found, 1);
 //     }
 //   };
 
diff --git a/third_party/abseil-cpp/absl/utility/utility.h b/third_party/abseil-cpp/absl/utility/utility.h
index aef4baa..104ec82 100644
--- a/third_party/abseil-cpp/absl/utility/utility.h
+++ b/third_party/abseil-cpp/absl/utility/utility.h
@@ -234,25 +234,33 @@
 //
 // Example:
 //
-//   class Foo{void Bar(int);};
-//   void user_function(int, string);
-//   void user_function(std::unique_ptr<Foo>);
+//   class Foo {
+//    public:
+//     void Bar(int);
+//   };
+//   void user_function1(int, string);
+//   void user_function2(std::unique_ptr<Foo>);
+//   auto user_lambda = [](int, int) {};
 //
 //   int main()
 //   {
 //       std::tuple<int, string> tuple1(42, "bar");
-//       // Invokes the user function overload on int, string.
-//       absl::apply(&user_function, tuple1);
+//       // Invokes the first user function on int, string.
+//       absl::apply(&user_function1, tuple1);
 //
-//       auto foo = absl::make_unique<Foo>();
-//       std::tuple<Foo*, int> tuple2(foo.get(), 42);
-//       // Invokes the method Bar on foo with one argument 42.
-//       absl::apply(&Foo::Bar, foo.get(), 42);
-//
-//       std::tuple<std::unique_ptr<Foo>> tuple3(absl::make_unique<Foo>());
+//       std::tuple<std::unique_ptr<Foo>> tuple2(absl::make_unique<Foo>());
 //       // Invokes the user function that takes ownership of the unique
 //       // pointer.
-//       absl::apply(&user_function, std::move(tuple));
+//       absl::apply(&user_function2, std::move(tuple2));
+//
+//       auto foo = absl::make_unique<Foo>();
+//       std::tuple<Foo*, int> tuple3(foo.get(), 42);
+//       // Invokes the method Bar on foo with one argument, 42.
+//       absl::apply(&Foo::Bar, tuple3);
+//
+//       std::tuple<int, int> tuple4(8, 9);
+//       // Invokes a lambda.
+//       absl::apply(user_lambda, tuple4);
 //   }
 template <typename Functor, typename Tuple>
 auto apply(Functor&& functor, Tuple&& t)
diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc
index 0024bee..d654727 100644
--- a/third_party/blink/common/features.cc
+++ b/third_party/blink/common/features.cc
@@ -48,7 +48,7 @@
 // Enable a new compositing mode called BlinkGenPropertyTrees where Blink
 // generates the compositor property trees. See: https://crbug.com/836884.
 const base::Feature kBlinkGenPropertyTrees{"BlinkGenPropertyTrees",
-                                           base::FEATURE_DISABLED_BY_DEFAULT};
+                                           base::FEATURE_ENABLED_BY_DEFAULT};
 
 // Enable LayoutNG.
 const base::Feature kLayoutNG{"LayoutNG", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc
index 54cb519..3d888b9 100644
--- a/third_party/blink/renderer/core/dom/document.cc
+++ b/third_party/blink/renderer/core/dom/document.cc
@@ -5148,7 +5148,11 @@
 }
 
 void Document::EnqueueScrollEndEventForNode(Node* target) {
-  Event* scroll_end_event = Event::Create(event_type_names::kScrollend);
+  // Mimic bubbling behavior of scroll event for consistency.
+  Event* scroll_end_event =
+      target->IsDocumentNode()
+          ? Event::CreateBubble(event_type_names::kScrollend)
+          : Event::Create(event_type_names::kScrollend);
   scroll_end_event->SetTarget(target);
   EnsureScriptedAnimationController().EnqueuePerFrameEvent(scroll_end_event);
 }
@@ -5156,8 +5160,10 @@
 void Document::EnqueueOverscrollEventForNode(Node* target,
                                              double delta_x,
                                              double delta_y) {
-  Event* overscroll_event =
-      OverscrollEvent::Create(event_type_names::kOverscroll, delta_x, delta_y);
+  // Mimic bubbling behavior of scroll event for consistency.
+  bool bubbles = target->IsDocumentNode();
+  Event* overscroll_event = OverscrollEvent::Create(
+      event_type_names::kOverscroll, bubbles, delta_x, delta_y);
   overscroll_event->SetTarget(target);
   EnsureScriptedAnimationController().EnqueuePerFrameEvent(overscroll_event);
 }
diff --git a/third_party/blink/renderer/core/events/overscroll_event.cc b/third_party/blink/renderer/core/events/overscroll_event.cc
index d171cb0..41ece7756 100644
--- a/third_party/blink/renderer/core/events/overscroll_event.cc
+++ b/third_party/blink/renderer/core/events/overscroll_event.cc
@@ -6,15 +6,17 @@
 
 namespace blink {
 OverscrollEvent::OverscrollEvent(const AtomicString& type,
+                                 bool bubbles,
                                  double delta_x,
                                  double delta_y)
-    : Event(type, Bubbles::kNo, Cancelable::kNo),
+    : Event(type, (bubbles ? Bubbles::kYes : Bubbles::kNo), Cancelable::kNo),
       delta_x_(delta_x),
       delta_y_(delta_y) {}
 
 OverscrollEvent::OverscrollEvent(const AtomicString& type,
+                                 bool bubbles,
                                  const OverscrollEventInit* initializer)
-    : Event(type, Bubbles::kNo, Cancelable::kNo),
+    : Event(type, (bubbles ? Bubbles::kYes : Bubbles::kNo), Cancelable::kNo),
       delta_x_(initializer->deltaX()),
       delta_y_(initializer->deltaY()) {}
 
diff --git a/third_party/blink/renderer/core/events/overscroll_event.h b/third_party/blink/renderer/core/events/overscroll_event.h
index ab7cffe..7b7e2b1 100644
--- a/third_party/blink/renderer/core/events/overscroll_event.h
+++ b/third_party/blink/renderer/core/events/overscroll_event.h
@@ -15,17 +15,25 @@
 
  public:
   static OverscrollEvent* Create(const AtomicString& type,
+                                 bool bubbles,
                                  double delta_x,
                                  double delta_y) {
-    return MakeGarbageCollected<OverscrollEvent>(type, delta_x, delta_y);
+    return MakeGarbageCollected<OverscrollEvent>(type, bubbles, delta_x,
+                                                 delta_y);
   }
   static OverscrollEvent* Create(const AtomicString& type,
+                                 bool bubbles,
                                  const OverscrollEventInit* initializer) {
-    return MakeGarbageCollected<OverscrollEvent>(type, initializer);
+    return MakeGarbageCollected<OverscrollEvent>(type, bubbles, initializer);
   }
 
-  OverscrollEvent(const AtomicString&, double delta_x, double delta_y);
-  OverscrollEvent(const AtomicString&, const OverscrollEventInit*);
+  OverscrollEvent(const AtomicString&,
+                  bool bubbles,
+                  double delta_x,
+                  double delta_y);
+  OverscrollEvent(const AtomicString&,
+                  bool bubbles,
+                  const OverscrollEventInit*);
 
   double deltaX() const { return delta_x_; }
   double deltaY() const { return delta_y_; }
diff --git a/third_party/blink/renderer/core/events/overscroll_event.idl b/third_party/blink/renderer/core/events/overscroll_event.idl
index a29ed0f..6d67d990 100644
--- a/third_party/blink/renderer/core/events/overscroll_event.idl
+++ b/third_party/blink/renderer/core/events/overscroll_event.idl
@@ -5,7 +5,7 @@
 // TODO(sahel): Add link to w3c. https://crbugs.com/907601
 
 [
-    Constructor(DOMString type, optional OverscrollEventInit eventInitDict),
+    Constructor(DOMString type, boolean bubbles, optional OverscrollEventInit eventInitDict),
     RuntimeEnabled=OverscrollCustomization
 ] interface OverscrollEvent : Event {
     readonly attribute double deltaX;
diff --git a/third_party/blink/renderer/core/frame/local_frame_view.cc b/third_party/blink/renderer/core/frame/local_frame_view.cc
index dc5aeeea..1646975 100644
--- a/third_party/blink/renderer/core/frame/local_frame_view.cc
+++ b/third_party/blink/renderer/core/frame/local_frame_view.cc
@@ -2601,7 +2601,9 @@
     auto* web_local_frame_impl = WebLocalFrameImpl::FromFrame(frame_);
     bool has_dev_tools_overlays =
         web_local_frame_impl && web_local_frame_impl->HasDevToolsOverlays();
-    if (GetLayoutView()->Layer()->NeedsRepaint() || has_dev_tools_overlays) {
+    if (!GetLayoutView()->Layer()->NeedsRepaint() && !has_dev_tools_overlays) {
+      paint_controller_->UpdateUMACountsOnFullyCached();
+    } else {
       GraphicsContext graphics_context(*paint_controller_);
       if (RuntimeEnabledFeatures::PrintBrowserEnabled())
         graphics_context.SetPrinting(true);
@@ -2689,6 +2691,8 @@
 
   if (RuntimeEnabledFeatures::FirstContentfulPaintPlusPlusEnabled())
     GetPaintTimingDetector().NotifyPaintFinished();
+
+  PaintController::ReportUMACounts();
 }
 
 const cc::Layer* LocalFrameView::RootCcLayer() const {
diff --git a/third_party/blink/renderer/core/layout/layout_flexible_box.cc b/third_party/blink/renderer/core/layout/layout_flexible_box.cc
index 251a195..3634f20 100644
--- a/third_party/blink/renderer/core/layout/layout_flexible_box.cc
+++ b/third_party/blink/renderer/core/layout/layout_flexible_box.cc
@@ -523,10 +523,12 @@
   // If our height is auto, make sure that our returned height is unaffected by
   // earlier layouts by returning the shrink-to-fit size.
   if (!CrossAxisLengthIsDefinite(child, child.StyleRef().LogicalWidth())) {
+    LayoutUnit available_size =
+        ContentLogicalWidth() - child.MarginLogicalWidth();
     MinMaxSize sizes{child.MinPreferredLogicalWidth(),
                      child.MaxPreferredLogicalWidth()};
-    return sizes.ShrinkToFit(ContentLogicalWidth() -
-                             child.MarginLogicalWidth());
+    return child.ConstrainLogicalWidthByMinMax(
+        sizes.ShrinkToFit(available_size), available_size, this);
   }
 
   return child.LogicalWidth();
diff --git a/third_party/blink/renderer/devtools/front_end/resources/ServiceWorkersView.js b/third_party/blink/renderer/devtools/front_end/resources/ServiceWorkersView.js
index d4bd116d..6297481 100644
--- a/third_party/blink/renderer/devtools/front_end/resources/ServiceWorkersView.js
+++ b/third_party/blink/renderer/devtools/front_end/resources/ServiceWorkersView.js
@@ -20,6 +20,8 @@
 
     /** @type {!Map<!SDK.ServiceWorkerRegistration, !Resources.ServiceWorkersView.Section>} */
     this._sections = new Map();
+    /** @type {symbol} */
+    this._registrationSymbol = Symbol('Resources.ServiceWorkersView');
 
     /** @type {?SDK.ServiceWorkerManager} */
     this._manager = null;
@@ -113,6 +115,33 @@
     this._securityOriginManager = null;
   }
 
+
+  /**
+   * @param {!SDK.ServiceWorkerRegistration} registration
+   * @return {number}
+   */
+  _getTimeStamp(registration) {
+    const versions = registration.versionsByMode();
+
+    let timestamp = 0;
+
+    const active = versions.get(SDK.ServiceWorkerVersion.Modes.Active);
+    const installing = versions.get(SDK.ServiceWorkerVersion.Modes.Installing);
+    const waiting = versions.get(SDK.ServiceWorkerVersion.Modes.Waiting);
+    const redundant = versions.get(SDK.ServiceWorkerVersion.Modes.Redundant);
+
+    if (active)
+      timestamp = active.scriptResponseTime;
+    else if (waiting)
+      timestamp = waiting.scriptResponseTime;
+    else if (installing)
+      timestamp = installing.scriptResponseTime;
+    else if (redundant)
+      timestamp = redundant.scriptResponseTime;
+
+    return timestamp;
+  }
+
   _updateSectionVisibility() {
     let hasOthers = false;
     let hasThis = false;
@@ -131,6 +160,13 @@
       this._updateRegistration(registration, true);
     }
 
+    this._currentWorkersView.sortSections((a, b) => {
+      const aTimestamp = this._getTimeStamp(a[this._registrationSymbol]);
+      const bTimestamp = this._getTimeStamp(b[this._registrationSymbol]);
+      // the newest (largest timestamp value) should be the first
+      return bTimestamp - aTimestamp;
+    });
+
     const scorer = new Sources.FilePathScoreFunction(this._filter.value());
     this._otherWorkersView.sortSections((a, b) => {
       const cmp = scorer.score(b.title(), null) - scorer.score(a.title(), null);
@@ -198,9 +234,10 @@
     let section = this._sections.get(registration);
     if (!section) {
       const title = Resources.ServiceWorkersView._displayScopeURL(registration.scopeURL);
+      const uiSection = this._getReportViewForOrigin(registration.securityOrigin).appendSection(title);
+      uiSection[this._registrationSymbol] = registration;
       section = new Resources.ServiceWorkersView.Section(
-          /** @type {!SDK.ServiceWorkerManager} */ (this._manager),
-          this._getReportViewForOrigin(registration.securityOrigin).appendSection(title), registration);
+          /** @type {!SDK.ServiceWorkerManager} */ (this._manager), uiSection, registration);
       this._sections.set(registration, section);
     }
     if (skipUpdate)
diff --git a/third_party/blink/renderer/platform/graphics/graphics_layer.cc b/third_party/blink/renderer/platform/graphics/graphics_layer.cc
index 2c3200c..a6b7d6ae 100644
--- a/third_party/blink/renderer/platform/graphics/graphics_layer.cc
+++ b/third_party/blink/renderer/platform/graphics/graphics_layer.cc
@@ -385,6 +385,7 @@
       !client_.NeedsRepaint(*this) &&
       !GetPaintController().CacheIsAllInvalid() &&
       previous_interest_rect_ == *interest_rect) {
+    GetPaintController().UpdateUMACountsOnFullyCached();
     return false;
   }
 
diff --git a/third_party/blink/renderer/platform/graphics/paint/display_item_raster_invalidator_test.cc b/third_party/blink/renderer/platform/graphics/paint/display_item_raster_invalidator_test.cc
index d3d659c3..170ebdb 100644
--- a/third_party/blink/renderer/platform/graphics/paint/display_item_raster_invalidator_test.cc
+++ b/third_party/blink/renderer/platform/graphics/paint/display_item_raster_invalidator_test.cc
@@ -287,7 +287,7 @@
   DrawRect(context, first, kForegroundType, FloatRect(100, 100, 150, 150));
   DrawRect(context, second, kBackgroundType, FloatRect(150, 250, 100, 100));
   DrawRect(context, second, kForegroundType, FloatRect(150, 250, 100, 100));
-  EXPECT_EQ(0, NumCachedNewItems());
+  EXPECT_EQ(0u, NumCachedNewItems());
 
   EXPECT_THAT(
       GenerateRasterInvalidations(),
diff --git a/third_party/blink/renderer/platform/graphics/paint/drawing_recorder_test.cc b/third_party/blink/renderer/platform/graphics/paint/drawing_recorder_test.cc
index 7d9ded94..33ee5925 100644
--- a/third_party/blink/renderer/platform/graphics/paint/drawing_recorder_test.cc
+++ b/third_party/blink/renderer/platform/graphics/paint/drawing_recorder_test.cc
@@ -58,7 +58,7 @@
   DrawNothing(context, client, kBackgroundType);
   DrawRect(context, client, kForegroundType, kBounds);
 
-  EXPECT_EQ(2, NumCachedNewItems());
+  EXPECT_EQ(2u, NumCachedNewItems());
 
   CommitAndFinishCycle();
 
diff --git a/third_party/blink/renderer/platform/graphics/paint/paint_controller.cc b/third_party/blink/renderer/platform/graphics/paint/paint_controller.cc
index 640e28b..4cdd66d9 100644
--- a/third_party/blink/renderer/platform/graphics/paint/paint_controller.cc
+++ b/third_party/blink/renderer/platform/graphics/paint/paint_controller.cc
@@ -6,6 +6,7 @@
 
 #include <memory>
 #include "base/auto_reset.h"
+#include "base/metrics/histogram_macros.h"
 #include "third_party/blink/renderer/platform/graphics/logging_canvas.h"
 #include "third_party/blink/renderer/platform/graphics/paint/drawing_display_item.h"
 #include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
@@ -131,6 +132,7 @@
   }
 
   num_cached_new_items_ += markers->end - markers->start;
+  ++num_cached_new_subsequences_;
 
   if (RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled()) {
     DCHECK(!IsCheckingUnderInvalidation());
@@ -369,9 +371,7 @@
       return i;
     }
     if (item.IsCacheable()) {
-#if DCHECK_IS_ON()
       ++num_indexed_items_;
-#endif
       AddToIndicesByClientMap(item.Client(), i, out_of_order_item_indices_);
       next_item_to_index_ = i + 1;
     }
@@ -474,7 +474,11 @@
                "num_non_cached_new_items",
                (int)new_display_item_list_.size() - num_cached_new_items_);
 
+  if (usage_ == kMultiplePaints)
+    UpdateUMACounts();
+
   num_cached_new_items_ = 0;
+  num_cached_new_subsequences_ = 0;
 #if DCHECK_IS_ON()
   new_display_item_indices_by_client_.clear();
   new_paint_chunk_indices_by_client_.clear();
@@ -499,10 +503,10 @@
   // We'll allocate the initial buffer when we start the next paint.
   new_display_item_list_ = DisplayItemList(0);
 
+  num_indexed_items_ = 0;
 #if DCHECK_IS_ON()
   num_sequential_matches_ = 0;
   num_out_of_order_matches_ = 0;
-  num_indexed_items_ = 0;
 #endif
 }
 
@@ -739,4 +743,52 @@
 }
 #endif
 
+size_t PaintController::sum_num_items_ = 0;
+size_t PaintController::sum_num_cached_items_ = 0;
+size_t PaintController::sum_num_indexed_items_ = 0;
+size_t PaintController::sum_num_subsequences_ = 0;
+size_t PaintController::sum_num_cached_subsequences_ = 0;
+
+void PaintController::UpdateUMACounts() {
+  DCHECK_EQ(usage_, kMultiplePaints);
+  sum_num_items_ += new_display_item_list_.size();
+  sum_num_cached_items_ += num_cached_new_items_;
+  sum_num_indexed_items_ += num_indexed_items_;
+  sum_num_subsequences_ += new_cached_subsequences_.size();
+  sum_num_cached_subsequences_ += num_cached_new_subsequences_;
+}
+
+void PaintController::UpdateUMACountsOnFullyCached() {
+  DCHECK_EQ(usage_, kMultiplePaints);
+  int num_items = GetDisplayItemList().size();
+  sum_num_items_ += num_items;
+  sum_num_cached_items_ += num_items;
+  // Don't change sum_num_indexed_items_.
+
+  int num_subsequences = current_cached_subsequences_.size();
+  sum_num_subsequences_ += num_subsequences;
+  sum_num_cached_subsequences_ += num_subsequences;
+}
+
+void PaintController::ReportUMACounts() {
+  static const int kReportThreshold = 1000;
+  if (sum_num_items_ < kReportThreshold)
+    return;
+
+  UMA_HISTOGRAM_PERCENTAGE("Blink.Paint.CachedItemPercentage",
+                           sum_num_cached_items_ * 100 / sum_num_items_);
+  UMA_HISTOGRAM_PERCENTAGE("Blink.Paint.IndexedItemPercentage",
+                           sum_num_indexed_items_ * 100 / sum_num_items_);
+  if (sum_num_subsequences_) {
+    UMA_HISTOGRAM_PERCENTAGE(
+        "Blink.Paint.CachedSubsequencePercentage",
+        sum_num_cached_subsequences_ * 100 / sum_num_subsequences_);
+  }
+  sum_num_items_ = 0;
+  sum_num_cached_items_ = 0;
+  sum_num_indexed_items_ = 0;
+  sum_num_subsequences_ = 0;
+  sum_num_cached_subsequences_ = 0;
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/graphics/paint/paint_controller.h b/third_party/blink/renderer/platform/graphics/paint/paint_controller.h
index 082f5d0..8b3d800 100644
--- a/third_party/blink/renderer/platform/graphics/paint/paint_controller.h
+++ b/third_party/blink/renderer/platform/graphics/paint/paint_controller.h
@@ -70,7 +70,7 @@
 
   ~PaintController();
 
-  // For SPv1 only.
+  // For pre-PaintAfterPaint only.
   void InvalidateAll();
   bool CacheIsAllInvalid() const;
 
@@ -244,6 +244,13 @@
   unsigned CurrentFragment() const { return current_fragment_; }
   void SetCurrentFragment(unsigned fragment) { current_fragment_ = fragment; }
 
+  // The client may skip a paint when nothing changed. In the case, the client
+  // calls this method to update UMA counts as a fully cached paint.
+  void UpdateUMACountsOnFullyCached();
+  // Reports the accumulated counts as UMA metrics, and reset them, if we have
+  // enough data to report.
+  static void ReportUMACounts();
+
  private:
   friend class PaintControllerTestBase;
   friend class PaintControllerPaintTestBase;
@@ -341,6 +348,8 @@
   void ShowDebugDataInternal(DisplayItemList::JsonFlags) const;
 #endif
 
+  void UpdateUMACounts();
+
   Usage usage_;
 
   // The last paint artifact after CommitNewDisplayItems().
@@ -360,9 +369,10 @@
   // A stack recording current frames' first paints.
   Vector<FrameFirstPaint> frame_first_paints_;
 
-  int skipping_cache_count_ = 0;
+  unsigned skipping_cache_count_ = 0;
 
-  int num_cached_new_items_ = 0;
+  size_t num_cached_new_items_ = 0;
+  size_t num_cached_new_subsequences_ = 0;
 
   // Stores indices to valid cacheable display items in
   // current_paint_artifact_.GetDisplayItemList() that have not been matched by
@@ -382,10 +392,10 @@
   // requests.
   size_t next_item_to_index_ = 0;
 
+  size_t num_indexed_items_ = 0;
 #if DCHECK_IS_ON()
-  int num_sequential_matches_ = 0;
-  int num_out_of_order_matches_ = 0;
-  int num_indexed_items_ = 0;
+  size_t num_sequential_matches_ = 0;
+  size_t num_out_of_order_matches_ = 0;
 
   // This is used to check duplicated ids during CreateAndAppend().
   IndicesByClientMap new_display_item_indices_by_client_;
@@ -412,6 +422,18 @@
 
   unsigned current_fragment_ = 0;
 
+  // Accumulated counts for UMA metrics. Updated by UpdateUMACounts() and
+  // UpdateUMACountsOnFullyCached(), and reported as UMA metrics and reset by
+  // ReportUMACounts(). The accumulation is mainly for pre-CompositeAfterPaint
+  // to weigh big and small GraphicsLayers properly when calculating the
+  // percentage UMA data. Also avoid reporting too frequently, to make the
+  // metrics more meaningful.
+  static size_t sum_num_items_;
+  static size_t sum_num_cached_items_;
+  static size_t sum_num_indexed_items_;
+  static size_t sum_num_subsequences_;
+  static size_t sum_num_cached_subsequences_;
+
   class DisplayItemListAsJSON;
 
   DISALLOW_COPY_AND_ASSIGN(PaintController);
diff --git a/third_party/blink/renderer/platform/graphics/paint/paint_controller_test.cc b/third_party/blink/renderer/platform/graphics/paint/paint_controller_test.cc
index f1ba39a..861ec09 100644
--- a/third_party/blink/renderer/platform/graphics/paint/paint_controller_test.cc
+++ b/third_party/blink/renderer/platform/graphics/paint/paint_controller_test.cc
@@ -63,7 +63,8 @@
   DrawRect(context, second, kBackgroundType, FloatRect(100, 100, 200, 200));
   DrawRect(context, first, kForegroundType, FloatRect(100, 100, 300, 300));
 
-  EXPECT_EQ(0, NumCachedNewItems());
+  EXPECT_EQ(0u, NumCachedNewItems());
+  EXPECT_EQ(0u, NumCachedNewSubsequences());
 
   CommitAndFinishCycle();
 
@@ -77,11 +78,12 @@
   DrawRect(context, first, kBackgroundType, FloatRect(100, 100, 300, 300));
   DrawRect(context, first, kForegroundType, FloatRect(100, 100, 300, 300));
 
-  EXPECT_EQ(2, NumCachedNewItems());
+  EXPECT_EQ(2u, NumCachedNewItems());
+  EXPECT_EQ(0u, NumCachedNewSubsequences());
+  EXPECT_EQ(1u, NumIndexedItems());
 #if DCHECK_IS_ON()
-  EXPECT_EQ(2, NumSequentialMatches());
-  EXPECT_EQ(0, NumOutOfOrderMatches());
-  EXPECT_EQ(1, NumIndexedItems());
+  EXPECT_EQ(2u, NumSequentialMatches());
+  EXPECT_EQ(0u, NumOutOfOrderMatches());
 #endif
 
   CommitAndFinishCycle();
@@ -123,11 +125,13 @@
   DrawRect(context, unaffected, kBackgroundType, FloatRect(300, 300, 10, 10));
   DrawRect(context, unaffected, kForegroundType, FloatRect(300, 300, 10, 10));
 
-  EXPECT_EQ(6, NumCachedNewItems());
+  EXPECT_EQ(6u, NumCachedNewItems());
+  EXPECT_EQ(0u, NumCachedNewSubsequences());
+  EXPECT_EQ(2u, NumIndexedItems());  // first
 #if DCHECK_IS_ON()
-  EXPECT_EQ(5, NumSequentialMatches());  // second, first foreground, unaffected
-  EXPECT_EQ(1, NumOutOfOrderMatches());  // first
-  EXPECT_EQ(2, NumIndexedItems());       // first
+  EXPECT_EQ(5u,
+            NumSequentialMatches());  // second, first foreground, unaffected
+  EXPECT_EQ(1u, NumOutOfOrderMatches());  // first
 #endif
 
   CommitAndFinishCycle();
@@ -174,11 +178,12 @@
   DrawRect(context, unaffected, kBackgroundType, FloatRect(300, 300, 10, 10));
   DrawRect(context, unaffected, kForegroundType, FloatRect(300, 300, 10, 10));
 
-  EXPECT_EQ(4, NumCachedNewItems());
+  EXPECT_EQ(4u, NumCachedNewItems());
+  EXPECT_EQ(0u, NumCachedNewSubsequences());
+  EXPECT_EQ(2u, NumIndexedItems());
 #if DCHECK_IS_ON()
-  EXPECT_EQ(4, NumSequentialMatches());  // second, unaffected
-  EXPECT_EQ(0, NumOutOfOrderMatches());
-  EXPECT_EQ(2, NumIndexedItems());
+  EXPECT_EQ(4u, NumSequentialMatches());  // second, unaffected
+  EXPECT_EQ(0u, NumOutOfOrderMatches());
 #endif
 
   CommitAndFinishCycle();
@@ -214,11 +219,12 @@
   DrawRect(context, third, kBackgroundType, FloatRect(125, 100, 200, 50));
   DrawRect(context, second, kBackgroundType, FloatRect(100, 100, 50, 200));
 
-  EXPECT_EQ(2, NumCachedNewItems());
+  EXPECT_EQ(2u, NumCachedNewItems());
+  EXPECT_EQ(0u, NumCachedNewSubsequences());
+  EXPECT_EQ(0u, NumIndexedItems());
 #if DCHECK_IS_ON()
-  EXPECT_EQ(2, NumSequentialMatches());  // first, second
-  EXPECT_EQ(0, NumOutOfOrderMatches());
-  EXPECT_EQ(0, NumIndexedItems());
+  EXPECT_EQ(2u, NumSequentialMatches());  // first, second
+  EXPECT_EQ(0u, NumOutOfOrderMatches());
 #endif
 
   CommitAndFinishCycle();
@@ -263,11 +269,12 @@
   DrawRect(context, second, kForegroundType, FloatRect(100, 100, 50, 200));
   DrawRect(context, third, kForegroundType, FloatRect(300, 100, 50, 50));
 
-  EXPECT_EQ(4, NumCachedNewItems());
+  EXPECT_EQ(4u, NumCachedNewItems());
+  EXPECT_EQ(0u, NumCachedNewSubsequences());
+  EXPECT_EQ(2u, NumIndexedItems());
 #if DCHECK_IS_ON()
-  EXPECT_EQ(4, NumSequentialMatches());
-  EXPECT_EQ(0, NumOutOfOrderMatches());
-  EXPECT_EQ(2, NumIndexedItems());
+  EXPECT_EQ(4u, NumSequentialMatches());
+  EXPECT_EQ(0u, NumOutOfOrderMatches());
 #endif
 
   CommitAndFinishCycle();
@@ -305,7 +312,8 @@
   DrawRect(context, first, kForegroundType, FloatRect(100, 100, 150, 150));
   DrawRect(context, second, kBackgroundType, FloatRect(150, 250, 100, 100));
   DrawRect(context, second, kForegroundType, FloatRect(150, 250, 100, 100));
-  EXPECT_EQ(0, NumCachedNewItems());
+  EXPECT_EQ(0u, NumCachedNewItems());
+  EXPECT_EQ(0u, NumCachedNewSubsequences());
   CommitAndFinishCycle();
 
   EXPECT_THAT(GetPaintController().GetDisplayItemList(),
@@ -319,11 +327,12 @@
   DrawRect(context, second, kBackgroundType, FloatRect(150, 250, 100, 100));
   DrawRect(context, second, kForegroundType, FloatRect(150, 250, 100, 100));
 
-  EXPECT_EQ(2, NumCachedNewItems());
+  EXPECT_EQ(2u, NumCachedNewItems());
+  EXPECT_EQ(0u, NumCachedNewSubsequences());
+  EXPECT_EQ(2u, NumIndexedItems());
 #if DCHECK_IS_ON()
-  EXPECT_EQ(2, NumSequentialMatches());
-  EXPECT_EQ(0, NumOutOfOrderMatches());
-  EXPECT_EQ(2, NumIndexedItems());
+  EXPECT_EQ(2u, NumSequentialMatches());
+  EXPECT_EQ(0u, NumOutOfOrderMatches());
 #endif
 
   CommitAndFinishCycle();
@@ -357,7 +366,8 @@
   DrawRect(context, first, kForegroundType, FloatRect(150, 150, 100, 100));
   DrawRect(context, second, kBackgroundType, FloatRect(200, 200, 50, 50));
   DrawRect(context, second, kForegroundType, FloatRect(200, 200, 50, 50));
-  EXPECT_EQ(0, NumCachedNewItems());
+  EXPECT_EQ(0u, NumCachedNewItems());
+  EXPECT_EQ(0u, NumCachedNewSubsequences());
   CommitAndFinishCycle();
 
   EXPECT_THAT(GetPaintController().GetDisplayItemList(),
@@ -373,7 +383,8 @@
   second.Invalidate();
   DrawRect(context, first, kBackgroundType, FloatRect(100, 100, 150, 150));
   DrawRect(context, first, kForegroundType, FloatRect(100, 100, 150, 150));
-  EXPECT_EQ(0, NumCachedNewItems());
+  EXPECT_EQ(0u, NumCachedNewItems());
+  EXPECT_EQ(0u, NumCachedNewSubsequences());
   CommitAndFinishCycle();
 
   EXPECT_THAT(GetPaintController().GetDisplayItemList(),
@@ -723,11 +734,12 @@
         context, container1));
   }
 
-  EXPECT_EQ(8, NumCachedNewItems());
+  EXPECT_EQ(8u, NumCachedNewItems());
+  EXPECT_EQ(2u, NumCachedNewSubsequences());
+  EXPECT_EQ(0u, NumIndexedItems());
 #if DCHECK_IS_ON()
-  EXPECT_EQ(0, NumSequentialMatches());
-  EXPECT_EQ(0, NumOutOfOrderMatches());
-  EXPECT_EQ(0, NumIndexedItems());
+  EXPECT_EQ(0u, NumSequentialMatches());
+  EXPECT_EQ(0u, NumOutOfOrderMatches());
 #endif
 
   CommitAndFinishCycle();
@@ -825,11 +837,12 @@
                                                             kForegroundType));
   }
 
-  EXPECT_EQ(6, NumCachedNewItems());
+  EXPECT_EQ(6u, NumCachedNewItems());
+  EXPECT_EQ(1u, NumCachedNewSubsequences());
+  EXPECT_EQ(0u, NumIndexedItems());
 #if DCHECK_IS_ON()
-  EXPECT_EQ(2, NumSequentialMatches());
-  EXPECT_EQ(0, NumOutOfOrderMatches());
-  EXPECT_EQ(0, NumIndexedItems());
+  EXPECT_EQ(2u, NumSequentialMatches());
+  EXPECT_EQ(0u, NumOutOfOrderMatches());
 #endif
 
   CommitAndFinishCycle();
@@ -965,11 +978,12 @@
                                                          container2_properties);
   DrawRect(context, container2, kBackgroundType, FloatRect(100, 200, 100, 100));
 
-  EXPECT_EQ(4, NumCachedNewItems());
+  EXPECT_EQ(4u, NumCachedNewItems());
+  EXPECT_EQ(0u, NumCachedNewSubsequences());
+  EXPECT_EQ(1u, NumIndexedItems());
 #if DCHECK_IS_ON()
-  EXPECT_EQ(3, NumSequentialMatches());
-  EXPECT_EQ(1, NumOutOfOrderMatches());
-  EXPECT_EQ(1, NumIndexedItems());
+  EXPECT_EQ(3u, NumSequentialMatches());
+  EXPECT_EQ(1u, NumOutOfOrderMatches());
 #endif
 
   CommitAndFinishCycle();
@@ -1171,11 +1185,12 @@
              FloatRect(100, 100, 100, 100));
   }
 
-  EXPECT_EQ(2, NumCachedNewItems());
+  EXPECT_EQ(2u, NumCachedNewItems());
+  EXPECT_EQ(1u, NumCachedNewSubsequences());
+  EXPECT_EQ(0u, NumIndexedItems());
 #if DCHECK_IS_ON()
-  EXPECT_EQ(0, NumSequentialMatches());
-  EXPECT_EQ(0, NumOutOfOrderMatches());
-  EXPECT_EQ(0, NumIndexedItems());
+  EXPECT_EQ(0u, NumSequentialMatches());
+  EXPECT_EQ(0u, NumOutOfOrderMatches());
 #endif
 
   CommitAndFinishCycle();
@@ -1252,11 +1267,12 @@
   DrawRect(context, content, kForegroundType, rect2);
   GetPaintController().EndSkippingCache();
 
-  EXPECT_EQ(1, NumCachedNewItems());
+  EXPECT_EQ(1u, NumCachedNewItems());
+  EXPECT_EQ(0u, NumCachedNewSubsequences());
+  EXPECT_EQ(0u, NumIndexedItems());
 #if DCHECK_IS_ON()
-  EXPECT_EQ(1, NumSequentialMatches());
-  EXPECT_EQ(0, NumOutOfOrderMatches());
-  EXPECT_EQ(0, NumIndexedItems());
+  EXPECT_EQ(1u, NumSequentialMatches());
+  EXPECT_EQ(0u, NumOutOfOrderMatches());
 #endif
 
   CommitAndFinishCycle();
@@ -1349,11 +1365,12 @@
   GetPaintController().EndSkippingCache();
   DrawRect(context, content, kForegroundType, rect3);
 
-  EXPECT_EQ(0, NumCachedNewItems());
+  EXPECT_EQ(0u, NumCachedNewItems());
+  EXPECT_EQ(0u, NumCachedNewSubsequences());
+  EXPECT_EQ(0u, NumIndexedItems());
 #if DCHECK_IS_ON()
-  EXPECT_EQ(0, NumSequentialMatches());
-  EXPECT_EQ(0, NumOutOfOrderMatches());
-  EXPECT_EQ(0, NumIndexedItems());
+  EXPECT_EQ(0u, NumSequentialMatches());
+  EXPECT_EQ(0u, NumOutOfOrderMatches());
 #endif
 
   CommitAndFinishCycle();
@@ -1494,7 +1511,8 @@
   DrawRect(context, third, kBackgroundType, FloatRect(100, 100, 100, 100));
   DrawRect(context, fourth, kBackgroundType, FloatRect(100, 100, 50, 50));
 
-  EXPECT_EQ(0, NumCachedNewItems());
+  EXPECT_EQ(0u, NumCachedNewItems());
+  EXPECT_EQ(0u, NumCachedNewSubsequences());
   CommitAndFinishCycle();
   EXPECT_THAT(GetPaintController().GetDisplayItemList(),
               ElementsAre(IsSameId(&first, kBackgroundType),
@@ -1512,12 +1530,13 @@
   DrawRect(context, third, kBackgroundType, FloatRect(100, 100, 100, 100));
   DrawRect(context, fourth, kBackgroundType, FloatRect(100, 100, 50, 50));
 
-  EXPECT_EQ(2, NumCachedNewItems());
-#if DCHECK_IS_ON()
-  EXPECT_EQ(2, NumSequentialMatches());
-  EXPECT_EQ(0, NumOutOfOrderMatches());
+  EXPECT_EQ(2u, NumCachedNewItems());
+  EXPECT_EQ(0u, NumCachedNewSubsequences());
   // We indexed "first" and "second" when finding the cached item for "third".
-  EXPECT_EQ(2, NumIndexedItems());
+  EXPECT_EQ(2u, NumIndexedItems());
+#if DCHECK_IS_ON()
+  EXPECT_EQ(2u, NumSequentialMatches());
+  EXPECT_EQ(0u, NumOutOfOrderMatches());
 #endif
 
   CommitAndFinishCycle();
@@ -1536,12 +1555,13 @@
   DrawRect(context, third, kBackgroundType, FloatRect(100, 100, 100, 100));
   DrawRect(context, fourth, kBackgroundType, FloatRect(100, 100, 50, 50));
 
-  EXPECT_EQ(2, NumCachedNewItems());
-#if DCHECK_IS_ON()
-  EXPECT_EQ(2, NumSequentialMatches());
-  EXPECT_EQ(0, NumOutOfOrderMatches());
+  EXPECT_EQ(2u, NumCachedNewItems());
+  EXPECT_EQ(0u, NumCachedNewSubsequences());
   // We indexed "third" and "fourth" when finding the cached item for "first".
-  EXPECT_EQ(2, NumIndexedItems());
+  EXPECT_EQ(2u, NumIndexedItems());
+#if DCHECK_IS_ON()
+  EXPECT_EQ(2u, NumSequentialMatches());
+  EXPECT_EQ(0u, NumOutOfOrderMatches());
 #endif
 
   CommitAndFinishCycle();
diff --git a/third_party/blink/renderer/platform/graphics/paint/paint_controller_test.h b/third_party/blink/renderer/platform/graphics/paint/paint_controller_test.h
index 572b17be..e4def4a 100644
--- a/third_party/blink/renderer/platform/graphics/paint/paint_controller_test.h
+++ b/third_party/blink/renderer/platform/graphics/paint/paint_controller_test.h
@@ -55,18 +55,22 @@
 
   PaintController& GetPaintController() { return *paint_controller_; }
 
-  int NumCachedNewItems() const {
+  size_t NumCachedNewItems() const {
     return paint_controller_->num_cached_new_items_;
   }
-
+  size_t NumCachedNewSubsequences() const {
+    return paint_controller_->num_cached_new_subsequences_;
+  }
+  size_t NumIndexedItems() const {
+    return paint_controller_->num_indexed_items_;
+  }
 #if DCHECK_IS_ON()
-  int NumSequentialMatches() const {
+  size_t NumSequentialMatches() const {
     return paint_controller_->num_sequential_matches_;
   }
-  int NumOutOfOrderMatches() const {
+  size_t NumOutOfOrderMatches() const {
     return paint_controller_->num_out_of_order_matches_;
   }
-  int NumIndexedItems() const { return paint_controller_->num_indexed_items_; }
 #endif
 
   void InvalidateAll() { paint_controller_->InvalidateAllForTesting(); }
diff --git a/third_party/blink/renderer/platform/graphics/paint_invalidation_reason.h b/third_party/blink/renderer/platform/graphics/paint_invalidation_reason.h
index b257a69..64d1d7c 100644
--- a/third_party/blink/renderer/platform/graphics/paint_invalidation_reason.h
+++ b/third_party/blink/renderer/platform/graphics/paint_invalidation_reason.h
@@ -59,10 +59,6 @@
     PaintInvalidationReason);
 
 inline bool IsFullPaintInvalidationReason(PaintInvalidationReason reason) {
-  // LayoutNG fully invalidates selections on NGPaintFragments.
-  // TODO(wangxianzhu): Move kSelection after kFull for LayoutNG.
-  if (RuntimeEnabledFeatures::LayoutNGEnabled())
-    return reason >= PaintInvalidationReason::kSelection;
   return reason >= PaintInvalidationReason::kFull;
 }
 
diff --git a/third_party/blink/web_tests/LeakExpectations b/third_party/blink/web_tests/LeakExpectations
index f3cd6d4..3da36dd 100644
--- a/third_party/blink/web_tests/LeakExpectations
+++ b/third_party/blink/web_tests/LeakExpectations
@@ -93,6 +93,11 @@
 #Sheriff 2019-02-21
 crbug.com/934144 [ Linux ] http/tests/devtools/tracing/timeline-misc/timeline-flame-chart-automatically-size-window.js [ Pass Leak ]
 
+#Sheriff 2019-02-25
+crbug.com/894651 [ Linux ] virtual/bidi-caret-affinity/editing/selection/modify_move/move_left_word_09_rtl_multi_line.html [ Failure Leak ]
+crbug.com/894651 [ Linux ] virtual/bidi-caret-affinity/editing/selection/modify_move/move_right_word_09_ltr_multi_line.html [ Failure Leak ]
+crbug.com/894651 [ Linux ] virtual/bidi-caret-affinity/editing/selection/modify_move/move_right_word_09_rtl_multi_line.html [ Failure Leak ]
+
 ###########################################################################
 # WARNING: Memory leaks must be fixed asap. Sheriff is expected to revert #
 # culprit CLs instead of suppressing the leaks. If you have any question, #
diff --git a/third_party/blink/web_tests/NeverFixTests b/third_party/blink/web_tests/NeverFixTests
index 69ef5b5..8a775d1 100644
--- a/third_party/blink/web_tests/NeverFixTests
+++ b/third_party/blink/web_tests/NeverFixTests
@@ -992,7 +992,6 @@
 external/wpt/css/css-backgrounds/background-size/vector/wide--cover--percent-width-nonpercent-height-viewbox.html [ WontFix ]
 external/wpt/css/css-backgrounds/background-size/vector/wide--cover--percent-width-omitted-height-viewbox.html [ WontFix ]
 external/wpt/css/css-backgrounds/background-size/vector/wide--cover--percent-width-percent-height-viewbox.html [ WontFix ]
-external/wpt/css/css-backgrounds/border-image-5.html [ WontFix ]
 external/wpt/css/css-backgrounds/border-image-6.html [ WontFix ]
 external/wpt/css/css-backgrounds/border-image-repeat-round.html [ WontFix ]
 external/wpt/css/css-backgrounds/border-image-round-and-stretch.html [ WontFix ]
diff --git a/third_party/blink/web_tests/SlowTests b/third_party/blink/web_tests/SlowTests
index aa819c3..b94541b3 100644
--- a/third_party/blink/web_tests/SlowTests
+++ b/third_party/blink/web_tests/SlowTests
@@ -1076,9 +1076,6 @@
 crbug.com/874695 virtual/gpu-rasterization/images/image-page-injected-script-crash.html [ Slow ]
 crbug.com/874695 virtual/gpu-rasterization/images/webp-color-profile-lossless.html [ Slow ]
 crbug.com/874695 virtual/layout_ng_experimental/fast/pagination/short-pages-tall-content.html [ Slow ]
-crbug.com/874695 virtual/mojo-blob-urls/external/wpt/FileAPI/url/sandboxed-iframe.html [ Slow ]
-crbug.com/874695 virtual/mojo-blob-urls/external/wpt/FileAPI/url/url-format.any.html [ Slow ]
-crbug.com/874695 virtual/mojo-blob-urls/external/wpt/FileAPI/url/url-format.any.worker.html [ Slow ]
 crbug.com/874695 virtual/mouseevent_fractional/fast/events/middleClickAutoscroll-nested-divs-forbidden.html [ Slow ]
 crbug.com/874695 virtual/mouseevent_fractional/fast/events/touch/gesture/gesture-click.html [ Slow ]
 crbug.com/874695 virtual/mouseevent_fractional/fast/events/touch/touch-slider-no-js-touch-listener.html [ Slow ]
@@ -1400,3 +1397,7 @@
 crbug.com/933550 external/wpt/webusb/idlharness.https.any.worker.html [ Slow ]
 
 crbug.com/927183 [ Mac10.13 ] external/wpt/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_navigation_download_allow_downloads_without_user_activation.sub.tentative.html [ Slow ]
+
+crbug.com/874695 external/wpt/FileAPI/url/sandboxed-iframe.html [ Slow ]
+crbug.com/874695 external/wpt/FileAPI/url/url-format.any.html [ Slow ]
+crbug.com/874695 external/wpt/FileAPI/url/url-format.any.worker.html [ Slow ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index 17f1ad7..78d2d67 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -5811,9 +5811,6 @@
 # Sheriff 2019-01-25
 crbug.com/925325 [ Mac ] storage/indexeddb/index-population.html [ Pass Failure ]
 
-crbug.com/v8/8319 external/wpt/wasm/jsapi/module/customSections.any.html [ Pass Failure ]
-crbug.com/v8/8319 external/wpt/wasm/jsapi/module/customSections.any.worker.html [ Pass Failure ]
-
 # Disabled until FreezeFramesOnVisiblity feature enabled by default.
 crbug.com/907125 external/wpt/lifecycle/child-display-none.tentative.html [ Skip ]
 
@@ -5885,6 +5882,12 @@
 crbug.com/935587 [ Mac ] virtual/video-surface-layer/media/stable/video-object-fit-stable.html [ Failure Pass ]
 crbug.com/935595 virtual/video-surface-layer/media/autoplay-muted.html [ Timeout Pass ]
 crbug.com/935638 fast/dom/rtl-scroll-to-leftmost-and-resize.html [ Timeout Pass ]
+crbug.com/935689 [ Mac ] external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/counter-styles-3/symbols-function-invalid.html [ Failure ]
+crbug.com/935689 [ Mac ] external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/counter-styles-3/system-additive-invalid.html [ Failure ]
+crbug.com/935689 [ Mac ] external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/counter-styles-3/system-fixed-invalid.html [ Failure ]
+crbug.com/935689 [ Mac ] external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/counter-styles-3/system-numeric-invalid.html [ Failure ]
+crbug.com/935689 [ Mac ] external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/counter-styles-3/system-symbolic-invalid.html [ Failure ]
+crbug.com/935690 [ Mac ] virtual/video-surface-layer/media/video-played-ranges-1.html [ Failure ]
 
 # Device Sensor Events are being restricted to secure browsing contexts, but the change is still gated on a runtime flag.
 crbug.com/932078 http/tests/security/powerfulFeatureRestrictions/device-orientation-future-behavior-on-insecure-origin.html [ Skip ]
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json
index 3653e633..56911d62 100644
--- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json
+++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json
@@ -28706,10 +28706,6 @@
       [
        "/css/CSS2/text/text-indent-wrap-001-ref-inline-margin.xht",
        "=="
-      ],
-      [
-       "/css/CSS2/text/text-indent-wrap-001-notref-block-margin.xht",
-       "!="
       ]
      ],
      {}
@@ -34163,6 +34159,30 @@
      {}
     ]
    ],
+   "css/css-backgrounds/border-bottom-left-radius-004.xht": [
+    [
+     "/css/css-backgrounds/border-bottom-left-radius-004.xht",
+     [
+      [
+       "/css/css-backgrounds/border-bottom-left-radius-004-ref.xht",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-backgrounds/border-bottom-left-radius-005.xht": [
+    [
+     "/css/css-backgrounds/border-bottom-left-radius-005.xht",
+     [
+      [
+       "/css/css-backgrounds/border-bottom-left-radius-005-ref.xht",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
    "css/css-backgrounds/border-bottom-left-radius-010.xht": [
     [
      "/css/css-backgrounds/border-bottom-left-radius-010.xht",
@@ -34211,6 +34231,30 @@
      {}
     ]
    ],
+   "css/css-backgrounds/border-bottom-right-radius-004.xht": [
+    [
+     "/css/css-backgrounds/border-bottom-right-radius-004.xht",
+     [
+      [
+       "/css/css-backgrounds/border-bottom-right-radius-004-ref.xht",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-backgrounds/border-bottom-right-radius-005.xht": [
+    [
+     "/css/css-backgrounds/border-bottom-right-radius-005.xht",
+     [
+      [
+       "/css/css-backgrounds/border-bottom-right-radius-005-ref.xht",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
    "css/css-backgrounds/border-bottom-right-radius-010.xht": [
     [
      "/css/css-backgrounds/border-bottom-right-radius-010.xht",
@@ -34295,24 +34339,12 @@
      {}
     ]
    ],
-   "css/css-backgrounds/border-image-5.html": [
-    [
-     "/css/css-backgrounds/border-image-5.html",
-     [
-      [
-       "/css/css-backgrounds/support/reftest-border-image-5.png",
-       "=="
-      ]
-     ],
-     {}
-    ]
-   ],
    "css/css-backgrounds/border-image-6.html": [
     [
      "/css/css-backgrounds/border-image-6.html",
      [
       [
-       "/css/css-backgrounds/support/reftest-border-image-5.png",
+       "/css/css-backgrounds/border-image-6-ref.html",
        "=="
       ]
      ],
@@ -34667,6 +34699,30 @@
      {}
     ]
    ],
+   "css/css-backgrounds/border-top-left-radius-004.xht": [
+    [
+     "/css/css-backgrounds/border-top-left-radius-004.xht",
+     [
+      [
+       "/css/css-backgrounds/border-top-left-radius-004-ref.xht",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-backgrounds/border-top-left-radius-005.xht": [
+    [
+     "/css/css-backgrounds/border-top-left-radius-005.xht",
+     [
+      [
+       "/css/css-backgrounds/border-top-left-radius-005-ref.xht",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
    "css/css-backgrounds/border-top-left-radius-010.xht": [
     [
      "/css/css-backgrounds/border-top-left-radius-010.xht",
@@ -34715,6 +34771,30 @@
      {}
     ]
    ],
+   "css/css-backgrounds/border-top-right-radius-004.xht": [
+    [
+     "/css/css-backgrounds/border-top-right-radius-004.xht",
+     [
+      [
+       "/css/css-backgrounds/border-top-right-radius-004-ref.xht",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-backgrounds/border-top-right-radius-005.xht": [
+    [
+     "/css/css-backgrounds/border-top-right-radius-005.xht",
+     [
+      [
+       "/css/css-backgrounds/border-top-right-radius-005-ref.xht",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
    "css/css-backgrounds/border-top-right-radius-010.xht": [
     [
      "/css/css-backgrounds/border-top-right-radius-010.xht",
@@ -41459,6 +41539,18 @@
      {}
     ]
    ],
+   "css/css-flexbox/flex-wrap-004.html": [
+    [
+     "/css/css-flexbox/flex-wrap-004.html",
+     [
+      [
+       "/css/reference/ref-filled-green-100px-square.xht",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
    "css/css-flexbox/flexbox-flex-direction-column-reverse.htm": [
     [
      "/css/css-flexbox/flexbox-flex-direction-column-reverse.htm",
@@ -49356,7 +49448,7 @@
      "/css/css-images/multiple-position-color-stop-conic.html",
      [
       [
-       "/css/css-images/support/100x100-blue-green.html",
+       "/css/css-images/reference/100x100-blue-green.html",
        "=="
       ]
      ],
@@ -49380,7 +49472,7 @@
      "/css/css-images/multiple-position-color-stop-linear.html",
      [
       [
-       "/css/css-images/support/100x100-blue-green.html",
+       "/css/css-images/reference/100x100-blue-green.html",
        "=="
       ]
      ],
@@ -49404,7 +49496,7 @@
      "/css/css-images/multiple-position-color-stop-radial.html",
      [
       [
-       "/css/css-images/support/100x100-blue-green.html",
+       "/css/css-images/reference/100x100-blue-green.html",
        "=="
       ]
      ],
@@ -55200,7 +55292,7 @@
      "/css/css-namespaces/prefix-001.xml",
      [
       [
-       "/css/css-namespaces/reftest/ref-lime-1.xml",
+       "/css/css-namespaces/reference/ref-lime-1.xml",
        "=="
       ]
      ],
@@ -55212,7 +55304,7 @@
      "/css/css-namespaces/prefix-002.xml",
      [
       [
-       "/css/css-namespaces/reftest/ref-lime-1.xml",
+       "/css/css-namespaces/reference/ref-lime-1.xml",
        "=="
       ]
      ],
@@ -55224,7 +55316,7 @@
      "/css/css-namespaces/prefix-003.xml",
      [
       [
-       "/css/css-namespaces/reftest/ref-lime-1-generic.xml",
+       "/css/css-namespaces/reference/ref-lime-1-generic.xml",
        "=="
       ]
      ],
@@ -55236,7 +55328,7 @@
      "/css/css-namespaces/prefix-004.xml",
      [
       [
-       "/css/css-namespaces/reftest/ref-lime-2-generic.xml",
+       "/css/css-namespaces/reference/ref-lime-2-generic.xml",
        "=="
       ]
      ],
@@ -55248,7 +55340,7 @@
      "/css/css-namespaces/prefix-005.xml",
      [
       [
-       "/css/css-namespaces/reftest/ref-lime-2-generic.xml",
+       "/css/css-namespaces/reference/ref-lime-2-generic.xml",
        "=="
       ]
      ],
@@ -55260,7 +55352,7 @@
      "/css/css-namespaces/prefix-006.xml",
      [
       [
-       "/css/css-namespaces/reftest/ref-lime-2.xml",
+       "/css/css-namespaces/reference/ref-lime-2.xml",
        "=="
       ]
      ],
@@ -55272,7 +55364,7 @@
      "/css/css-namespaces/scope-001.xml",
      [
       [
-       "/css/css-namespaces/reftest/ref-lime-1.xml",
+       "/css/css-namespaces/reference/ref-lime-1.xml",
        "=="
       ]
      ],
@@ -55284,7 +55376,7 @@
      "/css/css-namespaces/scope-002.xml",
      [
       [
-       "/css/css-namespaces/reftest/ref-lime-1.xml",
+       "/css/css-namespaces/reference/ref-lime-1.xml",
        "=="
       ]
      ],
@@ -55296,7 +55388,7 @@
      "/css/css-namespaces/syntax-001.xml",
      [
       [
-       "/css/css-namespaces/reftest/ref-lime-1-block.xml",
+       "/css/css-namespaces/reference/ref-lime-1-block.xml",
        "=="
       ]
      ],
@@ -55308,7 +55400,7 @@
      "/css/css-namespaces/syntax-002.xml",
      [
       [
-       "/css/css-namespaces/reftest/ref-lime-1-block.xml",
+       "/css/css-namespaces/reference/ref-lime-1-block.xml",
        "=="
       ]
      ],
@@ -55320,7 +55412,7 @@
      "/css/css-namespaces/syntax-003.xml",
      [
       [
-       "/css/css-namespaces/reftest/ref-lime-5.xml",
+       "/css/css-namespaces/reference/ref-lime-5.xml",
        "=="
       ]
      ],
@@ -55332,7 +55424,7 @@
      "/css/css-namespaces/syntax-004.xml",
      [
       [
-       "/css/css-namespaces/reftest/ref-lime-1.xml",
+       "/css/css-namespaces/reference/ref-lime-1.xml",
        "=="
       ]
      ],
@@ -55344,7 +55436,7 @@
      "/css/css-namespaces/syntax-005.xml",
      [
       [
-       "/css/css-namespaces/reftest/ref-lime-5.xml",
+       "/css/css-namespaces/reference/ref-lime-5.xml",
        "=="
       ]
      ],
@@ -55356,7 +55448,7 @@
      "/css/css-namespaces/syntax-006.xml",
      [
       [
-       "/css/css-namespaces/reftest/ref-lime-1.xml",
+       "/css/css-namespaces/reference/ref-lime-1.xml",
        "=="
       ]
      ],
@@ -55368,7 +55460,7 @@
      "/css/css-namespaces/syntax-007.xml",
      [
       [
-       "/css/css-namespaces/reftest/ref-lime-1.xml",
+       "/css/css-namespaces/reference/ref-lime-1.xml",
        "=="
       ]
      ],
@@ -55380,7 +55472,7 @@
      "/css/css-namespaces/syntax-008.xml",
      [
       [
-       "/css/css-namespaces/reftest/ref-lime-2.xml",
+       "/css/css-namespaces/reference/ref-lime-2.xml",
        "=="
       ]
      ],
@@ -55392,7 +55484,7 @@
      "/css/css-namespaces/syntax-009.xml",
      [
       [
-       "/css/css-namespaces/reftest/ref-lime-1.xml",
+       "/css/css-namespaces/reference/ref-lime-1.xml",
        "=="
       ]
      ],
@@ -55404,7 +55496,7 @@
      "/css/css-namespaces/syntax-010.xml",
      [
       [
-       "/css/css-namespaces/reftest/ref-lime-3.xml",
+       "/css/css-namespaces/reference/ref-lime-3.xml",
        "=="
       ]
      ],
@@ -55416,7 +55508,7 @@
      "/css/css-namespaces/syntax-011.xml",
      [
       [
-       "/css/css-namespaces/reftest/ref-lime-6.xml",
+       "/css/css-namespaces/reference/ref-lime-6.xml",
        "=="
       ]
      ],
@@ -55428,7 +55520,7 @@
      "/css/css-namespaces/syntax-012.xml",
      [
       [
-       "/css/css-namespaces/reftest/ref-lime-3.xml",
+       "/css/css-namespaces/reference/ref-lime-3.xml",
        "=="
       ]
      ],
@@ -55440,7 +55532,7 @@
      "/css/css-namespaces/syntax-013.xml",
      [
       [
-       "/css/css-namespaces/reftest/ref-lime-5.xml",
+       "/css/css-namespaces/reference/ref-lime-5.xml",
        "=="
       ]
      ],
@@ -55452,7 +55544,7 @@
      "/css/css-namespaces/syntax-014.xml",
      [
       [
-       "/css/css-namespaces/reftest/ref-lime-3.xml",
+       "/css/css-namespaces/reference/ref-lime-3.xml",
        "=="
       ]
      ],
@@ -55464,7 +55556,7 @@
      "/css/css-namespaces/syntax-015.xml",
      [
       [
-       "/css/css-namespaces/reftest/ref-lime-1.xml",
+       "/css/css-namespaces/reference/ref-lime-1.xml",
        "=="
       ]
      ],
@@ -73220,7 +73312,7 @@
      "/css/css-transforms/transform-3d-rotateY-stair-above-001.xht",
      [
       [
-       "/css/css-transforms/reftest/transform-3d-rotateY-stair-above-ref-001.xht",
+       "/css/css-transforms/reference/transform-3d-rotateY-stair-above-ref-001.xht",
        "=="
       ]
      ],
@@ -73232,7 +73324,7 @@
      "/css/css-transforms/transform-3d-rotateY-stair-below-001.xht",
      [
       [
-       "/css/css-transforms/reftest/transform-3d-rotateY-stair-above-ref-001.xht",
+       "/css/css-transforms/reference/transform-3d-rotateY-stair-above-ref-001.xht",
        "=="
       ]
      ],
@@ -73328,7 +73420,7 @@
      "/css/css-transforms/transform-applies-to-001.xht",
      [
       [
-       "/css/css-transforms/reftest/transform-applies-to-001-ref.xht",
+       "/css/css-transforms/reference/transform-applies-to-001-ref.xht",
        "=="
       ]
      ],
@@ -73340,7 +73432,7 @@
      "/css/css-transforms/transform-applies-to-002.xht",
      [
       [
-       "/css/css-transforms/reftest/transform-applies-to-002-ref.xht",
+       "/css/css-transforms/reference/transform-applies-to-002-ref.xht",
        "=="
       ]
      ],
@@ -73452,7 +73544,7 @@
      "/css/css-transforms/transform-box/fill-box-mutation.html",
      [
       [
-       "/css/css-transforms/transform-box/support/greensquare200x200.html",
+       "/css/css-transforms/transform-box/reference/greensquare200x200.html",
        "=="
       ]
      ],
@@ -73464,7 +73556,7 @@
      "/css/css-transforms/transform-box/fill-box.html",
      [
       [
-       "/css/css-transforms/transform-box/support/greensquare200x200.html",
+       "/css/css-transforms/transform-box/reference/greensquare200x200.html",
        "=="
       ]
      ],
@@ -73476,7 +73568,7 @@
      "/css/css-transforms/transform-box/value-changed.html",
      [
       [
-       "/css/css-transforms/transform-box/support/greensquare200x200.html",
+       "/css/css-transforms/transform-box/reference/greensquare200x200.html",
        "=="
       ]
      ],
@@ -73488,7 +73580,7 @@
      "/css/css-transforms/transform-box/view-box-mutation.html",
      [
       [
-       "/css/css-transforms/transform-box/support/greensquare200x200.html",
+       "/css/css-transforms/transform-box/reference/greensquare200x200.html",
        "=="
       ]
      ],
@@ -73500,7 +73592,7 @@
      "/css/css-transforms/transform-box/view-box-nested.html",
      [
       [
-       "/css/css-transforms/transform-box/support/greensquare200x200.html",
+       "/css/css-transforms/transform-box/reference/greensquare200x200.html",
        "=="
       ]
      ],
@@ -73512,7 +73604,7 @@
      "/css/css-transforms/transform-box/view-box-viewbox-nested.html",
      [
       [
-       "/css/css-transforms/transform-box/support/greensquare200x200.html",
+       "/css/css-transforms/transform-box/reference/greensquare200x200.html",
        "=="
       ]
      ],
@@ -73524,7 +73616,7 @@
      "/css/css-transforms/transform-box/view-box-viewbox.html",
      [
       [
-       "/css/css-transforms/transform-box/support/greensquare200x200.html",
+       "/css/css-transforms/transform-box/reference/greensquare200x200.html",
        "=="
       ]
      ],
@@ -73536,7 +73628,7 @@
      "/css/css-transforms/transform-box/view-box.html",
      [
       [
-       "/css/css-transforms/transform-box/support/greensquare200x200.html",
+       "/css/css-transforms/transform-box/reference/greensquare200x200.html",
        "=="
       ]
      ],
@@ -74424,7 +74516,7 @@
      "/css/css-transforms/transform-origin-01.html",
      [
       [
-       "/css/css-transforms/reftest/transform-origin-01-ref.html",
+       "/css/css-transforms/reference/transform-origin-01-ref.html",
        "=="
       ]
      ],
@@ -76954,18 +77046,6 @@
       [
        "/css/css-transforms/transform3d-perspective-origin-ref.html",
        "=="
-      ],
-      [
-       "/css/css-transforms/transform3d-rotatex-perspective-001.html",
-       "!="
-      ],
-      [
-       "/css/css-transforms/transform3d-rotatex-ref.html",
-       "!="
-      ],
-      [
-       "/css/css-transforms/transform-lime-square-ref.html",
-       "!="
       ]
      ],
      {}
@@ -77134,10 +77214,6 @@
       [
        "/css/css-transforms/transform3d-rotatex-ref.html",
        "=="
-      ],
-      [
-       "/css/css-transforms/transform-lime-square-ref.html",
-       "!="
       ]
      ],
      {}
@@ -77166,9 +77242,17 @@
       [
        "/css/css-transforms/transform3d-rotatex-ref.html",
        "=="
-      ],
+      ]
+     ],
+     {}
+    ]
+   ],
+   "css/css-transforms/transform3d-rotatex-perspective-001.html": [
+    [
+     "/css/css-transforms/transform3d-rotatex-perspective-001.html",
+     [
       [
-       "/css/css-transforms/transform-lime-square-ref.html",
+       "/css/css-transforms/transform3d-rotatex-ref.html",
        "!="
       ]
      ],
@@ -77182,10 +77266,6 @@
       [
        "/css/css-transforms/transform3d-rotatex-ref.html",
        "!="
-      ],
-      [
-       "/css/css-transforms/transform-lime-square-ref.html",
-       "!="
       ]
      ],
      {}
@@ -92076,7 +92156,7 @@
      "/css/css-writing-modes/writing-mode-vertical-lr-002.xht",
      [
       [
-       "/css/css-writing-modes/reftest/writing-mode-vertical-lr-002-ref.xht",
+       "/css/css-writing-modes/reference/writing-mode-vertical-lr-002-ref.xht",
        "=="
       ]
      ],
@@ -92088,7 +92168,7 @@
      "/css/css-writing-modes/writing-mode-vertical-rl-001.xht",
      [
       [
-       "/css/css-writing-modes/reftest/writing-mode-vertical-rl-001-ref.xht",
+       "/css/css-writing-modes/reference/writing-mode-vertical-rl-001-ref.xht",
        "=="
       ]
      ],
@@ -92100,7 +92180,7 @@
      "/css/css-writing-modes/writing-mode-vertical-rl-002.xht",
      [
       [
-       "/css/css-writing-modes/reftest/writing-mode-vertical-rl-002-ref.xht",
+       "/css/css-writing-modes/reference/writing-mode-vertical-rl-002-ref.xht",
        "=="
       ]
      ],
@@ -108424,7 +108504,7 @@
      "/svg/embedded/image-embedding-svg-with-viewport-units-inline-style.svg",
      [
       [
-       "/svg/embedded/support/green-rect-100x100.svg",
+       "/svg/embedded/reference/green-rect-100x100.svg",
        "=="
       ]
      ],
@@ -108436,7 +108516,7 @@
      "/svg/embedded/image-embedding-svg-with-viewport-units.svg",
      [
       [
-       "/svg/embedded/support/green-rect-100x100.svg",
+       "/svg/embedded/reference/green-rect-100x100.svg",
        "=="
       ]
      ],
@@ -109408,7 +109488,7 @@
      "/svg/shapes/reftests/disabled-shapes-01.svg",
      [
       [
-       "/svg/shapes/reftests/support/empty.svg",
+       "/svg/shapes/reftests/reference/empty.svg",
        "=="
       ]
      ],
@@ -113077,13 +113157,25 @@
      {}
     ]
    ],
+   "css/CSS2/text/text-indent-wrap-001-notref-block-margin.xht": [
+    [
+     "/css/CSS2/text/text-indent-wrap-001-notref-block-margin.xht",
+     [
+      [
+       "/css/CSS2/text/text-indent-wrap-001-ref-inline-margin.xht",
+       "!="
+      ]
+     ],
+     {}
+    ]
+   ],
    "css/CSS2/text/text-indent-wrap-001-ref-float.xht": [
     [
      "/css/CSS2/text/text-indent-wrap-001-ref-float.xht",
      [
       [
-       "/css/CSS2/text/text-indent-wrap-001-ref-inline-margin.xht",
-       "=="
+       "/css/CSS2/text/text-indent-wrap-001-notref-block-margin.xht",
+       "!="
       ]
      ],
      {}
@@ -113101,294 +113193,6 @@
      {}
     ]
    ],
-   "css/css-backgrounds/border-bottom-left-radius-003.xht": [
-    [
-     "/css/css-backgrounds/border-bottom-left-radius-003.xht",
-     [
-      [
-       "/css/css-backgrounds/border-bottom-left-radius-004.xht",
-       "=="
-      ]
-     ],
-     {}
-    ]
-   ],
-   "css/css-backgrounds/border-bottom-left-radius-004.xht": [
-    [
-     "/css/css-backgrounds/border-bottom-left-radius-004.xht",
-     [
-      [
-       "/css/css-backgrounds/border-bottom-left-radius-003.xht",
-       "=="
-      ]
-     ],
-     {}
-    ]
-   ],
-   "css/css-backgrounds/border-bottom-left-radius-005.xht": [
-    [
-     "/css/css-backgrounds/border-bottom-left-radius-005.xht",
-     [
-      [
-       "/css/css-backgrounds/border-bottom-left-radius-006.xht",
-       "=="
-      ]
-     ],
-     {}
-    ]
-   ],
-   "css/css-backgrounds/border-bottom-left-radius-006.xht": [
-    [
-     "/css/css-backgrounds/border-bottom-left-radius-006.xht",
-     [
-      [
-       "/css/css-backgrounds/border-bottom-left-radius-005.xht",
-       "=="
-      ]
-     ],
-     {}
-    ]
-   ],
-   "css/css-backgrounds/border-bottom-left-radius-007.xht": [
-    [
-     "/css/css-backgrounds/border-bottom-left-radius-007.xht",
-     [
-      [
-       "/css/css-backgrounds/border-bottom-left-radius-009.xht",
-       "=="
-      ]
-     ],
-     {}
-    ]
-   ],
-   "css/css-backgrounds/border-bottom-left-radius-009.xht": [
-    [
-     "/css/css-backgrounds/border-bottom-left-radius-009.xht",
-     [
-      [
-       "/css/css-backgrounds/border-bottom-left-radius-007.xht",
-       "=="
-      ]
-     ],
-     {}
-    ]
-   ],
-   "css/css-backgrounds/border-bottom-right-radius-003.xht": [
-    [
-     "/css/css-backgrounds/border-bottom-right-radius-003.xht",
-     [
-      [
-       "/css/css-backgrounds/border-bottom-right-radius-004.xht",
-       "=="
-      ]
-     ],
-     {}
-    ]
-   ],
-   "css/css-backgrounds/border-bottom-right-radius-004.xht": [
-    [
-     "/css/css-backgrounds/border-bottom-right-radius-004.xht",
-     [
-      [
-       "/css/css-backgrounds/border-bottom-right-radius-003.xht",
-       "=="
-      ]
-     ],
-     {}
-    ]
-   ],
-   "css/css-backgrounds/border-bottom-right-radius-005.xht": [
-    [
-     "/css/css-backgrounds/border-bottom-right-radius-005.xht",
-     [
-      [
-       "/css/css-backgrounds/border-bottom-right-radius-006.xht",
-       "=="
-      ]
-     ],
-     {}
-    ]
-   ],
-   "css/css-backgrounds/border-bottom-right-radius-006.xht": [
-    [
-     "/css/css-backgrounds/border-bottom-right-radius-006.xht",
-     [
-      [
-       "/css/css-backgrounds/border-bottom-right-radius-005.xht",
-       "=="
-      ]
-     ],
-     {}
-    ]
-   ],
-   "css/css-backgrounds/border-bottom-right-radius-007.xht": [
-    [
-     "/css/css-backgrounds/border-bottom-right-radius-007.xht",
-     [
-      [
-       "/css/css-backgrounds/border-bottom-right-radius-009.xht",
-       "=="
-      ]
-     ],
-     {}
-    ]
-   ],
-   "css/css-backgrounds/border-bottom-right-radius-009.xht": [
-    [
-     "/css/css-backgrounds/border-bottom-right-radius-009.xht",
-     [
-      [
-       "/css/css-backgrounds/border-bottom-right-radius-007.xht",
-       "=="
-      ]
-     ],
-     {}
-    ]
-   ],
-   "css/css-backgrounds/border-top-left-radius-003.xht": [
-    [
-     "/css/css-backgrounds/border-top-left-radius-003.xht",
-     [
-      [
-       "/css/css-backgrounds/border-top-left-radius-004.xht",
-       "=="
-      ]
-     ],
-     {}
-    ]
-   ],
-   "css/css-backgrounds/border-top-left-radius-004.xht": [
-    [
-     "/css/css-backgrounds/border-top-left-radius-004.xht",
-     [
-      [
-       "/css/css-backgrounds/border-top-left-radius-003.xht",
-       "=="
-      ]
-     ],
-     {}
-    ]
-   ],
-   "css/css-backgrounds/border-top-left-radius-005.xht": [
-    [
-     "/css/css-backgrounds/border-top-left-radius-005.xht",
-     [
-      [
-       "/css/css-backgrounds/border-top-left-radius-006.xht",
-       "=="
-      ]
-     ],
-     {}
-    ]
-   ],
-   "css/css-backgrounds/border-top-left-radius-006.xht": [
-    [
-     "/css/css-backgrounds/border-top-left-radius-006.xht",
-     [
-      [
-       "/css/css-backgrounds/border-top-left-radius-005.xht",
-       "=="
-      ]
-     ],
-     {}
-    ]
-   ],
-   "css/css-backgrounds/border-top-left-radius-007.xht": [
-    [
-     "/css/css-backgrounds/border-top-left-radius-007.xht",
-     [
-      [
-       "/css/css-backgrounds/border-top-left-radius-009.xht",
-       "=="
-      ]
-     ],
-     {}
-    ]
-   ],
-   "css/css-backgrounds/border-top-left-radius-009.xht": [
-    [
-     "/css/css-backgrounds/border-top-left-radius-009.xht",
-     [
-      [
-       "/css/css-backgrounds/border-top-left-radius-007.xht",
-       "=="
-      ]
-     ],
-     {}
-    ]
-   ],
-   "css/css-backgrounds/border-top-right-radius-003.xht": [
-    [
-     "/css/css-backgrounds/border-top-right-radius-003.xht",
-     [
-      [
-       "/css/css-backgrounds/border-top-right-radius-004.xht",
-       "=="
-      ]
-     ],
-     {}
-    ]
-   ],
-   "css/css-backgrounds/border-top-right-radius-004.xht": [
-    [
-     "/css/css-backgrounds/border-top-right-radius-004.xht",
-     [
-      [
-       "/css/css-backgrounds/border-top-right-radius-003.xht",
-       "=="
-      ]
-     ],
-     {}
-    ]
-   ],
-   "css/css-backgrounds/border-top-right-radius-005.xht": [
-    [
-     "/css/css-backgrounds/border-top-right-radius-005.xht",
-     [
-      [
-       "/css/css-backgrounds/border-top-right-radius-006.xht",
-       "=="
-      ]
-     ],
-     {}
-    ]
-   ],
-   "css/css-backgrounds/border-top-right-radius-006.xht": [
-    [
-     "/css/css-backgrounds/border-top-right-radius-006.xht",
-     [
-      [
-       "/css/css-backgrounds/border-top-right-radius-005.xht",
-       "=="
-      ]
-     ],
-     {}
-    ]
-   ],
-   "css/css-backgrounds/border-top-right-radius-007.xht": [
-    [
-     "/css/css-backgrounds/border-top-right-radius-007.xht",
-     [
-      [
-       "/css/css-backgrounds/border-top-right-radius-009.xht",
-       "=="
-      ]
-     ],
-     {}
-    ]
-   ],
-   "css/css-backgrounds/border-top-right-radius-009.xht": [
-    [
-     "/css/css-backgrounds/border-top-right-radius-009.xht",
-     [
-      [
-       "/css/css-backgrounds/border-top-right-radius-007.xht",
-       "=="
-      ]
-     ],
-     {}
-    ]
-   ],
    "css/css-transforms/2d-rotate-notref.html": [
     [
      "/css/css-transforms/2d-rotate-notref.html",
@@ -113413,9 +113217,9 @@
      {}
     ]
    ],
-   "css/css-transforms/transform3d-rotatex-perspective-001.html": [
+   "css/css-transforms/transform3d-perspective-origin-ref.html": [
     [
-     "/css/css-transforms/transform3d-rotatex-perspective-001.html",
+     "/css/css-transforms/transform3d-perspective-origin-ref.html",
      [
       [
        "/css/css-transforms/transform3d-rotatex-ref.html",
@@ -116097,6 +115901,16 @@
      {}
     ]
    ],
+   "WebIDL/ecmascript-binding/constructors-expected.txt": [
+    [
+     {}
+    ]
+   ],
+   "WebIDL/ecmascript-binding/constructors-support.html": [
+    [
+     {}
+    ]
+   ],
    "WebIDL/ecmascript-binding/default-iterator-object-expected.txt": [
     [
      {}
@@ -126227,11 +126041,6 @@
      {}
     ]
    ],
-   "css/CSS2/text/text-indent-wrap-001-notref-block-margin.xht": [
-    [
-     {}
-    ]
-   ],
    "css/CSS2/text/text-transform-capitalize-001-ref.xht": [
     [
      {}
@@ -127132,6 +126941,31 @@
      {}
     ]
    ],
+   "css/css-backgrounds/border-bottom-left-radius-004-ref.xht": [
+    [
+     {}
+    ]
+   ],
+   "css/css-backgrounds/border-bottom-left-radius-005-ref.xht": [
+    [
+     {}
+    ]
+   ],
+   "css/css-backgrounds/border-bottom-right-radius-004-ref.xht": [
+    [
+     {}
+    ]
+   ],
+   "css/css-backgrounds/border-bottom-right-radius-005-ref.xht": [
+    [
+     {}
+    ]
+   ],
+   "css/css-backgrounds/border-image-6-ref.html": [
+    [
+     {}
+    ]
+   ],
    "css/css-backgrounds/border-image-calc-ref.html": [
     [
      {}
@@ -127202,6 +127036,26 @@
      {}
     ]
    ],
+   "css/css-backgrounds/border-top-left-radius-004-ref.xht": [
+    [
+     {}
+    ]
+   ],
+   "css/css-backgrounds/border-top-left-radius-005-ref.xht": [
+    [
+     {}
+    ]
+   ],
+   "css/css-backgrounds/border-top-right-radius-004-ref.xht": [
+    [
+     {}
+    ]
+   ],
+   "css/css-backgrounds/border-top-right-radius-005-ref.xht": [
+    [
+     {}
+    ]
+   ],
    "css/css-backgrounds/box-shadow/support/box-shadow-blur-definition-001-dark-bound.png": [
     [
      {}
@@ -127827,11 +127681,6 @@
      {}
     ]
    ],
-   "css/css-backgrounds/support/reftest-border-image-5.png": [
-    [
-     {}
-    ]
-   ],
    "css/css-backgrounds/support/ruler-h-50%.png": [
     [
      {}
@@ -139502,7 +139351,7 @@
      {}
     ]
    ],
-   "css/css-images/support/100x100-blue-green.html": [
+   "css/css-images/reference/100x100-blue-green.html": [
     [
      {}
     ]
@@ -141267,42 +141116,42 @@
      {}
     ]
    ],
-   "css/css-namespaces/reftest/ref-lime-1-block.xml": [
+   "css/css-namespaces/reference/ref-lime-1-block.xml": [
     [
      {}
     ]
    ],
-   "css/css-namespaces/reftest/ref-lime-1-generic.xml": [
+   "css/css-namespaces/reference/ref-lime-1-generic.xml": [
     [
      {}
     ]
    ],
-   "css/css-namespaces/reftest/ref-lime-1.xml": [
+   "css/css-namespaces/reference/ref-lime-1.xml": [
     [
      {}
     ]
    ],
-   "css/css-namespaces/reftest/ref-lime-2-generic.xml": [
+   "css/css-namespaces/reference/ref-lime-2-generic.xml": [
     [
      {}
     ]
    ],
-   "css/css-namespaces/reftest/ref-lime-2.xml": [
+   "css/css-namespaces/reference/ref-lime-2.xml": [
     [
      {}
     ]
    ],
-   "css/css-namespaces/reftest/ref-lime-3.xml": [
+   "css/css-namespaces/reference/ref-lime-3.xml": [
     [
      {}
     ]
    ],
-   "css/css-namespaces/reftest/ref-lime-5.xml": [
+   "css/css-namespaces/reference/ref-lime-5.xml": [
     [
      {}
     ]
    ],
-   "css/css-namespaces/reftest/ref-lime-6.xml": [
+   "css/css-namespaces/reference/ref-lime-6.xml": [
     [
      {}
     ]
@@ -146332,6 +146181,26 @@
      {}
     ]
    ],
+   "css/css-transforms/reference/transform-3d-rotateY-stair-above-ref-001.xht": [
+    [
+     {}
+    ]
+   ],
+   "css/css-transforms/reference/transform-applies-to-001-ref.xht": [
+    [
+     {}
+    ]
+   ],
+   "css/css-transforms/reference/transform-applies-to-002-ref.xht": [
+    [
+     {}
+    ]
+   ],
+   "css/css-transforms/reference/transform-origin-01-ref.html": [
+    [
+     {}
+    ]
+   ],
    "css/css-transforms/reference/transform-origin-ref.html": [
     [
      {}
@@ -146427,26 +146296,6 @@
      {}
     ]
    ],
-   "css/css-transforms/reftest/transform-3d-rotateY-stair-above-ref-001.xht": [
-    [
-     {}
-    ]
-   ],
-   "css/css-transforms/reftest/transform-applies-to-001-ref.xht": [
-    [
-     {}
-    ]
-   ],
-   "css/css-transforms/reftest/transform-applies-to-002-ref.xht": [
-    [
-     {}
-    ]
-   ],
-   "css/css-transforms/reftest/transform-origin-01-ref.html": [
-    [
-     {}
-    ]
-   ],
    "css/css-transforms/rotate/reference/svg-rotate-3args-ref.html": [
     [
      {}
@@ -146772,7 +146621,7 @@
      {}
     ]
    ],
-   "css/css-transforms/transform-box/support/greensquare200x200.html": [
+   "css/css-transforms/transform-box/reference/greensquare200x200.html": [
     [
      {}
     ]
@@ -147372,11 +147221,6 @@
      {}
     ]
    ],
-   "css/css-transforms/transform3d-perspective-origin-ref.html": [
-    [
-     {}
-    ]
-   ],
    "css/css-transforms/transform3d-preserve3d-001-ref.html": [
     [
      {}
@@ -151347,17 +151191,17 @@
      {}
     ]
    ],
-   "css/css-writing-modes/reftest/writing-mode-vertical-lr-002-ref.xht": [
+   "css/css-writing-modes/reference/writing-mode-vertical-lr-002-ref.xht": [
     [
      {}
     ]
    ],
-   "css/css-writing-modes/reftest/writing-mode-vertical-rl-001-ref.xht": [
+   "css/css-writing-modes/reference/writing-mode-vertical-rl-001-ref.xht": [
     [
      {}
     ]
    ],
-   "css/css-writing-modes/reftest/writing-mode-vertical-rl-002-ref.xht": [
+   "css/css-writing-modes/reference/writing-mode-vertical-rl-002-ref.xht": [
     [
      {}
     ]
@@ -187512,7 +187356,7 @@
      {}
     ]
    ],
-   "svg/embedded/support/green-rect-100x100.svg": [
+   "svg/embedded/reference/green-rect-100x100.svg": [
     [
      {}
     ]
@@ -187992,7 +187836,7 @@
      {}
     ]
    ],
-   "svg/shapes/reftests/support/empty.svg": [
+   "svg/shapes/reftests/reference/empty.svg": [
     [
      {}
     ]
@@ -203400,6 +203244,12 @@
      {}
     ]
    ],
+   "WebIDL/ecmascript-binding/constructors.html": [
+    [
+     "/WebIDL/ecmascript-binding/constructors.html",
+     {}
+    ]
+   ],
    "WebIDL/ecmascript-binding/default-iterator-object.html": [
     [
      "/WebIDL/ecmascript-binding/default-iterator-object.html",
@@ -299012,12 +298862,6 @@
      {}
     ]
    ],
-   "css/css-backgrounds/border-bottom-left-radius-008.xht": [
-    [
-     "/css/css-backgrounds/border-bottom-left-radius-008.xht",
-     {}
-    ]
-   ],
    "css/css-backgrounds/border-bottom-left-radius-012.xht": [
     [
      "/css/css-backgrounds/border-bottom-left-radius-012.xht",
@@ -299036,12 +298880,6 @@
      {}
     ]
    ],
-   "css/css-backgrounds/border-bottom-right-radius-008.xht": [
-    [
-     "/css/css-backgrounds/border-bottom-right-radius-008.xht",
-     {}
-    ]
-   ],
    "css/css-backgrounds/border-bottom-right-radius-012.xht": [
     [
      "/css/css-backgrounds/border-bottom-right-radius-012.xht",
@@ -299480,12 +299318,6 @@
      {}
     ]
    ],
-   "css/css-backgrounds/border-top-left-radius-008.xht": [
-    [
-     "/css/css-backgrounds/border-top-left-radius-008.xht",
-     {}
-    ]
-   ],
    "css/css-backgrounds/border-top-left-radius-012.xht": [
     [
      "/css/css-backgrounds/border-top-left-radius-012.xht",
@@ -299528,12 +299360,6 @@
      {}
     ]
    ],
-   "css/css-backgrounds/border-top-right-radius-008.xht": [
-    [
-     "/css/css-backgrounds/border-top-right-radius-008.xht",
-     {}
-    ]
-   ],
    "css/css-backgrounds/border-top-right-radius-012.xht": [
     [
      "/css/css-backgrounds/border-top-right-radius-012.xht",
@@ -308569,6 +308395,18 @@
    "e094624c679202bd7035ed1593d83b2686360347",
    "testharness"
   ],
+  "WebIDL/ecmascript-binding/constructors-expected.txt": [
+   "9ef8be0ad8a5e407ae09608e5bd501d7384da6e7",
+   "support"
+  ],
+  "WebIDL/ecmascript-binding/constructors-support.html": [
+   "3b2616170b1d4f48f9dab114e4135222ed10a6ea",
+   "support"
+  ],
+  "WebIDL/ecmascript-binding/constructors.html": [
+   "423e1bed22827b9b7f37781665b01ceb307d00c6",
+   "testharness"
+  ],
   "WebIDL/ecmascript-binding/default-iterator-object-expected.txt": [
    "40d379a74abdaec19ba92004beb2fec2afbafd98",
    "support"
@@ -329906,11 +329744,11 @@
    "visual"
   ],
   "css/CSS2/text/text-indent-wrap-001-notref-block-margin.xht": [
-   "37852d9253c448eae582182756a481a44110fa9e",
-   "support"
+   "fdae290bc6f14ef01605e57a10ed25d3874d7ee3",
+   "reftest_node"
   ],
   "css/CSS2/text/text-indent-wrap-001-ref-float.xht": [
-   "18809f0adbf3a13043812e607654b23dd6a3776f",
+   "8c8c4a5e72d416d95de6b562d8ce9cf0dca282f8",
    "reftest_node"
   ],
   "css/CSS2/text/text-indent-wrap-001-ref-inline-margin.xht": [
@@ -329918,7 +329756,7 @@
    "reftest_node"
   ],
   "css/CSS2/text/text-indent-wrap-001.xht": [
-   "dc4c9b3abd29dd67487db26afee40f7806508cbd",
+   "31c226631ae847f6898126ff65fb6cb47a08e0a6",
    "reftest"
   ],
   "css/CSS2/text/text-transform-001.xht": [
@@ -333869,33 +333707,21 @@
    "5522722e824fb7be4a4547bcdbcaf4496faa1ef1",
    "visual"
   ],
-  "css/css-backgrounds/border-bottom-left-radius-003.xht": [
-   "312211138d23a4aecce6fcbb8638c0b85c179e52",
-   "reftest_node"
+  "css/css-backgrounds/border-bottom-left-radius-004-ref.xht": [
+   "15732f1c068b5890c7f65d2e7b561408cccde8e5",
+   "support"
   ],
   "css/css-backgrounds/border-bottom-left-radius-004.xht": [
-   "01ff790f9d759ab966b728c4161617dbd40628e2",
-   "reftest_node"
+   "92bcec5d16f80f133af406302b932efc8746f8fe",
+   "reftest"
+  ],
+  "css/css-backgrounds/border-bottom-left-radius-005-ref.xht": [
+   "26621b9a75c36b6c119acf7d622c6198b5770ee6",
+   "support"
   ],
   "css/css-backgrounds/border-bottom-left-radius-005.xht": [
-   "04d8a849238eccebdeebaf5dcd97c700fb6416f8",
-   "reftest_node"
-  ],
-  "css/css-backgrounds/border-bottom-left-radius-006.xht": [
-   "8f522644c8498b836c3caed6cd0e8d2f0ed29ac7",
-   "reftest_node"
-  ],
-  "css/css-backgrounds/border-bottom-left-radius-007.xht": [
-   "54bd5bd352f2112695f9b49262d79ca869628f92",
-   "reftest_node"
-  ],
-  "css/css-backgrounds/border-bottom-left-radius-008.xht": [
-   "33876eeb3ba91a3edc946f47ddb81bbdab720c60",
-   "visual"
-  ],
-  "css/css-backgrounds/border-bottom-left-radius-009.xht": [
-   "17df815ff4539f331adb00fab9e8f74eccc089d3",
-   "reftest_node"
+   "cc9fee12108c0c33325f9200d49dc8f30293fbb5",
+   "reftest"
   ],
   "css/css-backgrounds/border-bottom-left-radius-010.xht": [
    "3e7a1788b54919cdde0ec9ffc5e8e5dea8bff5f3",
@@ -333925,33 +333751,21 @@
    "ef6fb222012579f69c94a0b8e8bd0b310d96373b",
    "visual"
   ],
-  "css/css-backgrounds/border-bottom-right-radius-003.xht": [
-   "ba13706e1fc1d6a70f81e6e0f2ee8c4e88287304",
-   "reftest_node"
+  "css/css-backgrounds/border-bottom-right-radius-004-ref.xht": [
+   "8589ee96b117def11640ace8a2daa5f754a45471",
+   "support"
   ],
   "css/css-backgrounds/border-bottom-right-radius-004.xht": [
-   "907ed8255e6d6ab15194012f128f8fd96dc8d789",
-   "reftest_node"
+   "d9bbcf95900a3566233e35657cde1f42eadd887e",
+   "reftest"
+  ],
+  "css/css-backgrounds/border-bottom-right-radius-005-ref.xht": [
+   "9ed21b722270dcb6a73620b40a3b253126fdbdec",
+   "support"
   ],
   "css/css-backgrounds/border-bottom-right-radius-005.xht": [
-   "899b3b585b10ee0e8e2e506849139bf22ebc6cb7",
-   "reftest_node"
-  ],
-  "css/css-backgrounds/border-bottom-right-radius-006.xht": [
-   "d47009d1197066db6d0b753584a5db5d9bb45e69",
-   "reftest_node"
-  ],
-  "css/css-backgrounds/border-bottom-right-radius-007.xht": [
-   "c0d5b733b579572991924950ea935125d59eb2e8",
-   "reftest_node"
-  ],
-  "css/css-backgrounds/border-bottom-right-radius-008.xht": [
-   "b4b7b6e8f7c89964374d6a10c56a1f9d01420dc5",
-   "visual"
-  ],
-  "css/css-backgrounds/border-bottom-right-radius-009.xht": [
-   "633caa5ff246b31b3c205ab1c6eb3b91ebaeb553",
-   "reftest_node"
+   "899125420faaa9f8e3c5fa596490b2b3b546dd3c",
+   "reftest"
   ],
   "css/css-backgrounds/border-bottom-right-radius-010.xht": [
    "76676f89d1ca83470387e988d6ba6b14232bffa1",
@@ -334037,12 +333851,12 @@
    "619b677e114f3e8f842d4539b486e5b56953653f",
    "visual"
   ],
-  "css/css-backgrounds/border-image-5.html": [
-   "4fecfc7bf950ec310d87a7e147e3d058945a2c76",
-   "reftest"
+  "css/css-backgrounds/border-image-6-ref.html": [
+   "f3e3bb79c05336a3fa3aa0abe66260ddc8652884",
+   "support"
   ],
   "css/css-backgrounds/border-image-6.html": [
-   "235d263fac8892b4fdd6010d36dc1363ed423bb6",
+   "bc4cb1386b5cc634539fb4a6cd5c8599ec013f21",
    "reftest"
   ],
   "css/css-backgrounds/border-image-7.html": [
@@ -334461,33 +334275,21 @@
    "58f265ebf6ce40ab05bcf92b7aee17d459390880",
    "visual"
   ],
-  "css/css-backgrounds/border-top-left-radius-003.xht": [
-   "deed8ad6ad1e33e56f85cadae432c42d9274fcfc",
-   "reftest_node"
+  "css/css-backgrounds/border-top-left-radius-004-ref.xht": [
+   "b9c9cdac88267a980456ff69fda5afadb7571f8e",
+   "support"
   ],
   "css/css-backgrounds/border-top-left-radius-004.xht": [
-   "31e06fc2397ac482914b20ae0b285b9b926172d1",
-   "reftest_node"
+   "39e636db6bb62f65926d86525f541d9809dd7382",
+   "reftest"
+  ],
+  "css/css-backgrounds/border-top-left-radius-005-ref.xht": [
+   "f1a1935aa503aed0cd1f34ef586a54d00c3b568a",
+   "support"
   ],
   "css/css-backgrounds/border-top-left-radius-005.xht": [
-   "e4044300e66523813f8a5b18ffbdf313e4fd5287",
-   "reftest_node"
-  ],
-  "css/css-backgrounds/border-top-left-radius-006.xht": [
-   "dc2b9ebfad74ef19f7bd972714eae0644ec8eee9",
-   "reftest_node"
-  ],
-  "css/css-backgrounds/border-top-left-radius-007.xht": [
-   "7111e538fe2d7fed63a296dc3b8fe7c2c2d67595",
-   "reftest_node"
-  ],
-  "css/css-backgrounds/border-top-left-radius-008.xht": [
-   "724075cae1871977261455d6408f1889d4ee5cd7",
-   "visual"
-  ],
-  "css/css-backgrounds/border-top-left-radius-009.xht": [
-   "a5589fa9cc47f6234e42f975ac6f521dfeecb404",
-   "reftest_node"
+   "37af580e067b95a71002590d1ca4fa329ad72b85",
+   "reftest"
   ],
   "css/css-backgrounds/border-top-left-radius-010.xht": [
    "61b55e1f0857adf2ed65017fc4ae02cbe25e1e0e",
@@ -334533,33 +334335,21 @@
    "faaf86bb0bf7bc778d6212857324f773eb54939e",
    "visual"
   ],
-  "css/css-backgrounds/border-top-right-radius-003.xht": [
-   "66ac6caf432c4bdb9a72830222ddfe1a471bc866",
-   "reftest_node"
+  "css/css-backgrounds/border-top-right-radius-004-ref.xht": [
+   "ae031513ae2bbc317d2799d6625186438f15bd59",
+   "support"
   ],
   "css/css-backgrounds/border-top-right-radius-004.xht": [
-   "35bd619341298b526e5982799fd69de8631f6cad",
-   "reftest_node"
+   "cbedad809bad0e99df33044d9319f429d2a4ff8e",
+   "reftest"
+  ],
+  "css/css-backgrounds/border-top-right-radius-005-ref.xht": [
+   "a3303b72c7788651a0d132ef4122230ce8670ced",
+   "support"
   ],
   "css/css-backgrounds/border-top-right-radius-005.xht": [
-   "f44587cef469835d366d63ba86391bdfbaa1cc6e",
-   "reftest_node"
-  ],
-  "css/css-backgrounds/border-top-right-radius-006.xht": [
-   "be52dadfc55c6e0baf05fcd29bc0ad779c1ea4de",
-   "reftest_node"
-  ],
-  "css/css-backgrounds/border-top-right-radius-007.xht": [
-   "5a00a05da79456064d526d99a31cdea84211b84e",
-   "reftest_node"
-  ],
-  "css/css-backgrounds/border-top-right-radius-008.xht": [
-   "0fa67dbc92d21b25709a587bd2ea03fa71c7e205",
-   "visual"
-  ],
-  "css/css-backgrounds/border-top-right-radius-009.xht": [
-   "ec954d6003df3ee174fc5706d6d62659610b2d4d",
-   "reftest_node"
+   "8bd3965de5a3951ab5761d6779323f6e6a47d152",
+   "reftest"
   ],
   "css/css-backgrounds/border-top-right-radius-010.xht": [
    "5f2d5e5eab55bfd86a16e42a440e9773c28d11c5",
@@ -334838,7 +334628,7 @@
    "testharness"
   ],
   "css/css-backgrounds/parsing/border-image-slice-invalid.html": [
-   "c62a43d6b37422ae8ae3ea86b630bf3a38317a2e",
+   "6b6e0e9d610bc6c1b76c9f31d4c1651a783399c9",
    "testharness"
   ],
   "css/css-backgrounds/parsing/border-image-slice-valid.html": [
@@ -335389,10 +335179,6 @@
    "24948d0d0eb4b1178454418d106d5b1e942e69d2",
    "support"
   ],
-  "css/css-backgrounds/support/reftest-border-image-5.png": [
-   "01087f13dc1c239c51ae3569e8ea81ba8db5caff",
-   "support"
-  ],
   "css/css-backgrounds/support/ruler-h-50%.png": [
    "cf2eea6b438a11503a89414cbb2f9f1fde55df0c",
    "support"
@@ -339066,7 +338852,11 @@
    "reftest"
   ],
   "css/css-flexbox/flex-wrap-003.html": [
-   "a76e4449fb2e56a779c45c3a1c1c20ec31a093cf",
+   "b1a6619363aba8fb0b01177c596f4fdbf263fc37",
+   "reftest"
+  ],
+  "css/css-flexbox/flex-wrap-004.html": [
+   "679f62ae3e6659fa5627a3e2fb0276bcf6a13420",
    "reftest"
   ],
   "css/css-flexbox/flex-wrap_nowrap.html": [
@@ -352074,7 +351864,7 @@
    "support"
   ],
   "css/css-images/multiple-position-color-stop-conic.html": [
-   "d1608c0cfe8baa967cb1bdb6cb47b4635bf009b1",
+   "8a7331d08ff53bed6c19d96c95740b57fed43516",
    "reftest"
   ],
   "css/css-images/multiple-position-color-stop-linear-2-ref.html": [
@@ -352086,7 +351876,7 @@
    "reftest"
   ],
   "css/css-images/multiple-position-color-stop-linear.html": [
-   "2e1f9ed7be488a6c6fa68f4bc4252524ddab82b2",
+   "c739a2a71d2dbbc0088df45caac3a679d3d5ab37",
    "reftest"
   ],
   "css/css-images/multiple-position-color-stop-radial-2-ref.html": [
@@ -352098,7 +351888,7 @@
    "reftest"
   ],
   "css/css-images/multiple-position-color-stop-radial.html": [
-   "74e25df788b0736f687f5f6394c31437cc834f57",
+   "4b4fd95c4ec21307eee1e2f287f1b0db1d6d1490",
    "reftest"
   ],
   "css/css-images/parsing/gradient-position-invalid.html": [
@@ -352165,7 +351955,7 @@
    "b9dab78b518138272a1e29a6a2690d13f3e208e1",
    "testharness"
   ],
-  "css/css-images/support/100x100-blue-green.html": [
+  "css/css-images/reference/100x100-blue-green.html": [
    "e4f35c3e430cc2994709f6805576d1fe2c1f9cf3",
    "support"
   ],
@@ -355878,67 +355668,67 @@
    "support"
   ],
   "css/css-namespaces/prefix-001.xml": [
-   "c40bb7f1132c4f239d87871ecbaf03730e403ea3",
+   "eb717139e1dfd0e5a3ddd49a402f3c25f0333a48",
    "reftest"
   ],
   "css/css-namespaces/prefix-002.xml": [
-   "cc78f3f0aaf15088bb22793b58c79a0ef5e80ded",
+   "49ca7c0a9e116803ad7acf970e58bb4d3f92e4b3",
    "reftest"
   ],
   "css/css-namespaces/prefix-003.xml": [
-   "0b6f3293de1fa0118622cbe6e05588a452bfb96c",
+   "2f23ad4c061eba68692d222fbbb3cfea6af9a92b",
    "reftest"
   ],
   "css/css-namespaces/prefix-004.xml": [
-   "70c3bd1ed9bc5882f530f755026c29e42e9e45de",
+   "596d4637f9ba79f67abddef0383f197e66fa1090",
    "reftest"
   ],
   "css/css-namespaces/prefix-005.xml": [
-   "458b5aa3ebc4fd44a0b590de890a58db4b4894c9",
+   "5f7c3cad3d942ca2c81392b3e4ea38866f2da08d",
    "reftest"
   ],
   "css/css-namespaces/prefix-006.xml": [
-   "0bf59915a45b6f51b20dda3d8c79e8ce7f1d15cc",
+   "3cc0ab40f3aa5b91df020dddd2a654620af831bd",
    "reftest"
   ],
-  "css/css-namespaces/reftest/ref-lime-1-block.xml": [
+  "css/css-namespaces/reference/ref-lime-1-block.xml": [
    "c26b6fcf2c17918542e998f20d564f20878f9934",
    "support"
   ],
-  "css/css-namespaces/reftest/ref-lime-1-generic.xml": [
+  "css/css-namespaces/reference/ref-lime-1-generic.xml": [
    "12c5c012d0b17b3ac5c6c0cf3e51ec8420dd12c5",
    "support"
   ],
-  "css/css-namespaces/reftest/ref-lime-1.xml": [
+  "css/css-namespaces/reference/ref-lime-1.xml": [
    "9509a4bd3421226e48421dd643c7f625fd33316c",
    "support"
   ],
-  "css/css-namespaces/reftest/ref-lime-2-generic.xml": [
+  "css/css-namespaces/reference/ref-lime-2-generic.xml": [
    "047be42212bba6b98289c58ba197ad143345c338",
    "support"
   ],
-  "css/css-namespaces/reftest/ref-lime-2.xml": [
+  "css/css-namespaces/reference/ref-lime-2.xml": [
    "f2fa08395fec86944af3135d52ca2de627079cf6",
    "support"
   ],
-  "css/css-namespaces/reftest/ref-lime-3.xml": [
+  "css/css-namespaces/reference/ref-lime-3.xml": [
    "e50faba6b55ae5116c743dd0dd8487deaa78b481",
    "support"
   ],
-  "css/css-namespaces/reftest/ref-lime-5.xml": [
+  "css/css-namespaces/reference/ref-lime-5.xml": [
    "9c45f9de7cbab90d1bff7ee7363454da571e3a81",
    "support"
   ],
-  "css/css-namespaces/reftest/ref-lime-6.xml": [
+  "css/css-namespaces/reference/ref-lime-6.xml": [
    "d67da1ac3945e280b7bc8c5df28cc94899ef5193",
    "support"
   ],
   "css/css-namespaces/scope-001.xml": [
-   "bed4171efa1e95202595b6ffc5bab2c0f405dd8c",
+   "5271096a96432ca6ebd2b2907b7946efc6bc7c46",
    "reftest"
   ],
   "css/css-namespaces/scope-002.xml": [
-   "d25eb81780c1993175fddcfa9257d26dbac8ae66",
+   "ff5a2fec118407764e92d6d8f34496d1db3fd31d",
    "reftest"
   ],
   "css/css-namespaces/support/LOCK": [
@@ -355962,63 +355752,63 @@
    "support"
   ],
   "css/css-namespaces/syntax-001.xml": [
-   "01c57e07c7c1213cfaaaf97330da818016dc6ea8",
+   "83efb665b66cc32409776645b6c53a972e9aebf6",
    "reftest"
   ],
   "css/css-namespaces/syntax-002.xml": [
-   "cb04b9c8d6b1e751e0bd85fc7289a49a9034024b",
+   "30fa8aece35ad7b53ee93bb1c1b11bb02b091e34",
    "reftest"
   ],
   "css/css-namespaces/syntax-003.xml": [
-   "256286eeb1259723d128e0a1db0c4afba70c9520",
+   "1b2eb5f9c08ddb052616646710fb67b28ca018e6",
    "reftest"
   ],
   "css/css-namespaces/syntax-004.xml": [
-   "335bca98d24ac6dfbdb850813c231d196502b9a6",
+   "c4ce372b09c403e54253f944580f9e9f84db6c86",
    "reftest"
   ],
   "css/css-namespaces/syntax-005.xml": [
-   "164bea1ece4875beaf4a7395768cc5f22b503d02",
+   "9d6b0abe945bda36a86eb23a2524b4d2333769f8",
    "reftest"
   ],
   "css/css-namespaces/syntax-006.xml": [
-   "1c5975a852a2c5716460fb43c90511b104a82b20",
+   "09ff0d5916ec30c76ca158b8ac917c7d0df2817a",
    "reftest"
   ],
   "css/css-namespaces/syntax-007.xml": [
-   "6022d1c7e1c3becb94b06eec5109c559d5e40240",
+   "0c651f17d7895200d365d33efd639af46604caa1",
    "reftest"
   ],
   "css/css-namespaces/syntax-008.xml": [
-   "4cb4e233979e46b226f4b782076d0310122f2f7e",
+   "20284e2247c18821d49bd669c0a748a4c45c506b",
    "reftest"
   ],
   "css/css-namespaces/syntax-009.xml": [
-   "9f69fec67e0bc61d6eb30897c207cf82597ecbfc",
+   "edf2f4c9b48951f7ef40e12af32fc724a5032f2f",
    "reftest"
   ],
   "css/css-namespaces/syntax-010.xml": [
-   "e175a7bd3cebdc2a950871c80a0baac0471a61c4",
+   "06b280da792d05a8960cf3434b91b4f7a58d06c3",
    "reftest"
   ],
   "css/css-namespaces/syntax-011.xml": [
-   "e60cbe115ea14bd1be184357539026fb66ad2273",
+   "7d137fc7a546172027f6cb5131b79097e324d7b1",
    "reftest"
   ],
   "css/css-namespaces/syntax-012.xml": [
-   "557ba5065ba8974e03d5d26c1017d2f65804cb5a",
+   "43f211b4dd20a3de24b4440c9ef3efb7fee08d6b",
    "reftest"
   ],
   "css/css-namespaces/syntax-013.xml": [
-   "983e2e62d92b2a593b43067666b1638fd18dfafe",
+   "a7c63e43e092779ec2a0b7084929892cec7cfc99",
    "reftest"
   ],
   "css/css-namespaces/syntax-014.xml": [
-   "d57d8991cc82ee4a988e22aa67a2f436386801ce",
+   "1bdfc265ef603e8dd39436f8a405f16b3bd43bb6",
    "reftest"
   ],
   "css/css-namespaces/syntax-015.xml": [
-   "4460ddf559b157682bd3e8744548f8a24d607334",
+   "d39eb8b3a48d57062f72c435697824ab1c49f8c0",
    "reftest"
   ],
   "css/css-namespaces/syntax-016.xml": [
@@ -368081,6 +367871,22 @@
    "d69df1ba455ae7cf049c68481ecc721676f3f22f",
    "support"
   ],
+  "css/css-transforms/reference/transform-3d-rotateY-stair-above-ref-001.xht": [
+   "9a8d7e85934043bdcd3446f115856cccb6240fbc",
+   "support"
+  ],
+  "css/css-transforms/reference/transform-applies-to-001-ref.xht": [
+   "fe646caebd74d81f7a32da23f9c9ed7af9fb727b",
+   "support"
+  ],
+  "css/css-transforms/reference/transform-applies-to-002-ref.xht": [
+   "b9ef17475b707335d015c17f065fd5a55fb08e7b",
+   "support"
+  ],
+  "css/css-transforms/reference/transform-origin-01-ref.html": [
+   "0e85f3c698f6ce83f016a0a3c82d8796d406b274",
+   "support"
+  ],
   "css/css-transforms/reference/transform-origin-ref.html": [
    "980a273e0d6b7372777cf8af78dcae1283048907",
    "support"
@@ -368157,22 +367963,6 @@
    "12214ad615518b226e8473dc8aec37d258d74b1b",
    "support"
   ],
-  "css/css-transforms/reftest/transform-3d-rotateY-stair-above-ref-001.xht": [
-   "9a8d7e85934043bdcd3446f115856cccb6240fbc",
-   "support"
-  ],
-  "css/css-transforms/reftest/transform-applies-to-001-ref.xht": [
-   "fe646caebd74d81f7a32da23f9c9ed7af9fb727b",
-   "support"
-  ],
-  "css/css-transforms/reftest/transform-applies-to-002-ref.xht": [
-   "b9ef17475b707335d015c17f065fd5a55fb08e7b",
-   "support"
-  ],
-  "css/css-transforms/reftest/transform-origin-01-ref.html": [
-   "0e85f3c698f6ce83f016a0a3c82d8796d406b274",
-   "support"
-  ],
   "css/css-transforms/rotate-180-degrees-001.html": [
    "9532290cde76870ab8e21236a89586ddb9d20ddf",
    "visual"
@@ -369102,11 +368892,11 @@
    "testharness"
   ],
   "css/css-transforms/transform-3d-rotateY-stair-above-001.xht": [
-   "41d8979c4551076ce89f17a5c230719729168497",
+   "9a3aac888feee0854357320c6edf87530c07c536",
    "reftest"
   ],
   "css/css-transforms/transform-3d-rotateY-stair-below-001.xht": [
-   "5a1c1d4699895c8c0cb7e1da4a160afbeaf45d0c",
+   "5224da27fd4ac3d25e1a37f4edfd70a19fec8dec",
    "reftest"
   ],
   "css/css-transforms/transform-abspos-001.html": [
@@ -369142,11 +368932,11 @@
    "support"
   ],
   "css/css-transforms/transform-applies-to-001.xht": [
-   "0036e8e1acf2b806d7af3bdf1d02fc307e53f2fa",
+   "09bb196d533212a7113c27739a418e3ec974045a",
    "reftest"
   ],
   "css/css-transforms/transform-applies-to-002.xht": [
-   "80715d379d4d265516e4312a09a317a5e345b90b",
+   "186d0b74a3a5bab147aa457593b4bf306dc5cbb5",
    "reftest"
   ],
   "css/css-transforms/transform-background-001.html": [
@@ -369198,39 +368988,39 @@
    "support"
   ],
   "css/css-transforms/transform-box/fill-box-mutation.html": [
-   "ae602e3509d0ad066e67a9556db16b5e542ca4cb",
+   "1f0dfd01bb9ab6acf183721f23f8590293e9e32f",
    "reftest"
   ],
   "css/css-transforms/transform-box/fill-box.html": [
-   "eaea02a5dfe7764ff02b591ff66def0fb0965436",
+   "7e9b133aead426b36702e5377c3cd1347e36ff5f",
    "reftest"
   ],
-  "css/css-transforms/transform-box/support/greensquare200x200.html": [
+  "css/css-transforms/transform-box/reference/greensquare200x200.html": [
    "bee8bc70fe5d3ff49f7bd39d473bbb8a230f7d08",
    "support"
   ],
   "css/css-transforms/transform-box/value-changed.html": [
-   "825403ef7b62526aa4ec1c167538e062a1761309",
+   "4aca90a61c1f76a9ee83b912bd20acf31a0e295d",
    "reftest"
   ],
   "css/css-transforms/transform-box/view-box-mutation.html": [
-   "0d4a0ecdc2f9f598503e75a4e9906e680e8f1f81",
+   "d0c85fd59d36e06180bbea07700d6f7bc69e9559",
    "reftest"
   ],
   "css/css-transforms/transform-box/view-box-nested.html": [
-   "7f59777f15b827bbc69003b01ed6a5c6a10d6164",
+   "9e7fc17e2a5bc8c33b412d9f3c6e96caba60009a",
    "reftest"
   ],
   "css/css-transforms/transform-box/view-box-viewbox-nested.html": [
-   "4f667e20ba8103291d9440b097c901dbfe13b6ce",
+   "fc072363e8a30958f5d4d8522ab4feec0a860428",
    "reftest"
   ],
   "css/css-transforms/transform-box/view-box-viewbox.html": [
-   "cd040c1ba33864a2f2a32a452ec7375f69343190",
+   "a69d8092f646310ab6d9bbf9199a9983f9ca6f05",
    "reftest"
   ],
   "css/css-transforms/transform-box/view-box.html": [
-   "3345467c904d4635339adc4c5e96dbabb55320db",
+   "0b5eeda54382bb84ff97480b1852b953f547165d",
    "reftest"
   ],
   "css/css-transforms/transform-compound-001.html": [
@@ -369706,7 +369496,7 @@
    "reftest"
   ],
   "css/css-transforms/transform-origin-01.html": [
-   "c1b6f29a52ac3c001332e4cff77bfab60497dbd7",
+   "d7e1cd34d4556b84935eb0ed897c654d747a0c70",
    "reftest"
   ],
   "css/css-transforms/transform-origin-010.html": [
@@ -370790,12 +370580,12 @@
    "reftest"
   ],
   "css/css-transforms/transform3d-perspective-origin-001.html": [
-   "1a81bc1d4dad70862c5011043293702d19c83a0c",
+   "791d4bd136cc10a29030eb92ae603904a8a79f6a",
    "reftest"
   ],
   "css/css-transforms/transform3d-perspective-origin-ref.html": [
-   "dd0026b8fc1c9eec6695f2eb6a472c78a07a9e08",
-   "support"
+   "e174d7596f7cda83b616da59f1afab059c87b836",
+   "reftest_node"
   ],
   "css/css-transforms/transform3d-preserve3d-001-ref.html": [
    "383bc7a63eb55053bf17948c1c973d80f8f2d352",
@@ -370858,7 +370648,7 @@
    "reftest"
   ],
   "css/css-transforms/transform3d-rotate3d-001.html": [
-   "185346c333c11892378f9c2e6b939fdaac7867e2",
+   "93a46f1c6ab038b92e9bbbe3356d219cd2f1bdf4",
    "reftest"
   ],
   "css/css-transforms/transform3d-rotate3d-002.html": [
@@ -370866,15 +370656,15 @@
    "reftest"
   ],
   "css/css-transforms/transform3d-rotatex-001.html": [
-   "47ad10b388ce192e7dc84734d194572c4bc92d90",
+   "2f75f15cd0d62c9636a7867df221271525be003a",
    "reftest"
   ],
   "css/css-transforms/transform3d-rotatex-perspective-001.html": [
    "6d35cae63262d47dad9eae7aa74486955a1a1740",
-   "reftest_node"
+   "reftest"
   ],
   "css/css-transforms/transform3d-rotatex-perspective-002.html": [
-   "472d0aa854b6d448a9ddc946cdf71eb3ebb04335",
+   "ecf6a2f8d57ebf90e973a5009449edb73415dead",
    "reftest"
   ],
   "css/css-transforms/transform3d-rotatex-perspective-003.html": [
@@ -381689,15 +381479,15 @@
    "204d87a4b6e3ed254d30368761e9638fabcb041f",
    "support"
   ],
-  "css/css-writing-modes/reftest/writing-mode-vertical-lr-002-ref.xht": [
+  "css/css-writing-modes/reference/writing-mode-vertical-lr-002-ref.xht": [
    "496c03d8416e7e9ef2fcca5f8f2ab764a71b9a68",
    "support"
   ],
-  "css/css-writing-modes/reftest/writing-mode-vertical-rl-001-ref.xht": [
+  "css/css-writing-modes/reference/writing-mode-vertical-rl-001-ref.xht": [
    "ed0d5a6c95385e31169f128f3b1d3d827812ea6c",
    "support"
   ],
-  "css/css-writing-modes/reftest/writing-mode-vertical-rl-002-ref.xht": [
+  "css/css-writing-modes/reference/writing-mode-vertical-rl-002-ref.xht": [
    "5dccf5071e82905297c33bde6e019ad4b9c019cd",
    "support"
   ],
@@ -384050,15 +383840,15 @@
    "testharness"
   ],
   "css/css-writing-modes/writing-mode-vertical-lr-002.xht": [
-   "8086296174cbeae4e7ee06415311582118ed839b",
+   "291dff96d39c33d2eb0d1a16eaae71e56355829a",
    "reftest"
   ],
   "css/css-writing-modes/writing-mode-vertical-rl-001.xht": [
-   "0a7839cba0c811a3307784a2a6fcc3128bd6034c",
+   "5a5c7bf2a4eb5343ad7cfe639ace3ef71a6f4397",
    "reftest"
   ],
   "css/css-writing-modes/writing-mode-vertical-rl-002.xht": [
-   "f2d3ab078f9c564c4b0e2ad05ce239fff012760a",
+   "ac77d439d75dc9550494463e167eec52595219bd",
    "reftest"
   ],
   "css/css-writing-modes/writing-mode-vertical-rl-003-ref.htm": [
@@ -453514,14 +453304,14 @@
    "support"
   ],
   "svg/embedded/image-embedding-svg-with-viewport-units-inline-style.svg": [
-   "7880fcf501c032965814e383a93d89a31edda3c5",
+   "7ef2655dc91c815d57d1496d2e5707d54ac94c5d",
    "reftest"
   ],
   "svg/embedded/image-embedding-svg-with-viewport-units.svg": [
-   "6feb54b392f452071f8f4e2d470befee76c03ee6",
+   "653856de21bc50a48d8d2aa55fdaa276f994b8f6",
    "reftest"
   ],
-  "svg/embedded/support/green-rect-100x100.svg": [
+  "svg/embedded/reference/green-rect-100x100.svg": [
    "120941444a4898197d6b6001f9908a6cd48b62ba",
    "support"
   ],
@@ -454718,7 +454508,7 @@
    "reftest"
   ],
   "svg/shapes/reftests/disabled-shapes-01.svg": [
-   "d92eea169a6904c969fa0d6df363324194a1b335",
+   "3091ca7b0152c8580dbe49e2774dd8c5934917fb",
    "reftest"
   ],
   "svg/shapes/reftests/pathlength-001-ref.svg": [
@@ -454745,7 +454535,7 @@
    "506952f54b4b0b59d10a106af50ae61062873e99",
    "reftest"
   ],
-  "svg/shapes/reftests/support/empty.svg": [
+  "svg/shapes/reftests/reference/empty.svg": [
    "0c7be4e2da4480937124138e7dee3e26bd018abe",
    "support"
   ],
diff --git a/third_party/blink/web_tests/external/wpt/WebIDL/ecmascript-binding/constructors-expected.txt b/third_party/blink/web_tests/external/wpt/WebIDL/ecmascript-binding/constructors-expected.txt
new file mode 100644
index 0000000..9ef8be0
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/WebIDL/ecmascript-binding/constructors-expected.txt
@@ -0,0 +1,14 @@
+This is a testharness.js-based test.
+PASS Realm for constructed objects
+PASS Normal constructor in parent window
+PASS Normal constructor in child window
+FAIL Constructor in child window with normal NewTarget from parent window assert_equals: expected "child window" but got "parent window"
+FAIL Constructor in parent window with normal NewTarget from child window assert_equals: expected "parent window" but got "child window"
+PASS Subclass constructor in parent window
+PASS Subclass constructor in child window
+FAIL Subclass constructor in parent window with parent class in child window assert_equals: expected "child window" but got "parent window"
+FAIL Subclass constructor in child window with parent class in parent window assert_equals: expected "parent window" but got "child window"
+FAIL Constructor in child window with bad NewTarget from parent window assert_equals: expected object "[object DOMParser]" but got object "[object Object]"
+FAIL Constructor in parent window with bad NewTarget from child window assert_equals: expected object "[object DOMParser]" but got object "[object Object]"
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/WebIDL/ecmascript-binding/constructors-support.html b/third_party/blink/web_tests/external/wpt/WebIDL/ecmascript-binding/constructors-support.html
new file mode 100644
index 0000000..3b26161
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/WebIDL/ecmascript-binding/constructors-support.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<script>
+window.badNewTarget = function() {};
+badNewTarget.prototype = 8;
+
+window.DOMParserSubclass = class extends DOMParser {}
+window.ForeignDOMParserSubclass = class extends parent.DOMParser {}
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/WebIDL/ecmascript-binding/constructors.html b/third_party/blink/web_tests/external/wpt/WebIDL/ecmascript-binding/constructors.html
new file mode 100644
index 0000000..423e1be
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/WebIDL/ecmascript-binding/constructors.html
@@ -0,0 +1,96 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Realm for constructed objects</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+function object_realm(dp) {
+  // Note that browsers use the URL of the relevant global object's associated
+  // Document.
+  // https://github.com/w3c/DOM-Parsing/issues/46
+  var url = DOMParser.prototype.parseFromString.call(dp, "x", "text/html").documentURI;
+  var file = url.slice(url.lastIndexOf("/") + 1);
+  switch (file) {
+  case "constructors.html":
+    return "parent window";
+  case "constructors-support.html":
+    return "child window";
+  default:
+    return "???";
+  }
+}
+
+async_test(function() {
+  var iframe = document.createElement("iframe");
+  iframe.onload = this.step_func_done(function() {
+    var child = iframe.contentWindow;
+    test(function() {
+      var dp = new DOMParser();
+      assert_equals(Object.getPrototypeOf(dp), DOMParser.prototype);
+      assert_equals(object_realm(dp), "parent window");
+    }, "Normal constructor in parent window");
+
+    test(function() {
+      var dp = new child.DOMParser();
+      assert_equals(Object.getPrototypeOf(dp), child.DOMParser.prototype);
+      assert_equals(object_realm(dp), "child window");
+    }, "Normal constructor in child window");
+
+    test(function() {
+      var dp = Reflect.construct(child.DOMParser, [], DOMParser);
+      assert_equals(Object.getPrototypeOf(dp), DOMParser.prototype);
+      assert_equals(object_realm(dp), "child window");
+    }, "Constructor in child window with normal NewTarget from parent window");
+
+    test(function() {
+      var dp = Reflect.construct(DOMParser, [], child.DOMParser);
+      assert_equals(Object.getPrototypeOf(dp), child.DOMParser.prototype);
+      assert_equals(object_realm(dp), "parent window");
+    }, "Constructor in parent window with normal NewTarget from child window");
+
+    test(function() {
+      class DOMParserSubclass extends DOMParser {}
+      var dp = new DOMParserSubclass();
+      assert_equals(Object.getPrototypeOf(dp), DOMParserSubclass.prototype);
+      assert_equals(object_realm(dp), "parent window");
+    }, "Subclass constructor in parent window");
+
+    test(function() {
+      var dp = new child.DOMParserSubclass();
+      assert_equals(Object.getPrototypeOf(dp), child.DOMParserSubclass.prototype);
+      assert_equals(object_realm(dp), "child window");
+    }, "Subclass constructor in child window");
+
+    test(function() {
+      class ForeignDOMParserSubclass extends child.DOMParser {}
+      var dp = new ForeignDOMParserSubclass();
+      assert_equals(Object.getPrototypeOf(dp), ForeignDOMParserSubclass.prototype);
+      assert_equals(object_realm(dp), "child window");
+    }, "Subclass constructor in parent window with parent class in child window");
+
+    test(function() {
+      var dp = new child.ForeignDOMParserSubclass();
+      assert_equals(Object.getPrototypeOf(dp), child.ForeignDOMParserSubclass.prototype);
+      assert_equals(object_realm(dp), "parent window");
+    }, "Subclass constructor in child window with parent class in parent window");
+
+    test(function() {
+      var badNewTarget = function() {};
+      badNewTarget.prototype = 7;
+
+      var dp = Reflect.construct(child.DOMParser, [], badNewTarget);
+      assert_equals(Object.getPrototypeOf(dp), DOMParser.prototype);
+      assert_equals(object_realm(dp), "child window");
+    }, "Constructor in child window with bad NewTarget from parent window");
+
+    test(function() {
+      var dp = Reflect.construct(DOMParser, [], child.badNewTarget);
+      assert_equals(Object.getPrototypeOf(dp), child.DOMParser.prototype);
+      assert_equals(object_realm(dp), "parent window");
+    }, "Constructor in parent window with bad NewTarget from child window");
+  });
+  iframe.src = "constructors-support.html";
+  document.body.appendChild(iframe);
+});
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/CSS2/text/text-indent-wrap-001-notref-block-margin.xht b/third_party/blink/web_tests/external/wpt/css/CSS2/text/text-indent-wrap-001-notref-block-margin.xht
index 37852d92..fdae290 100644
--- a/third_party/blink/web_tests/external/wpt/css/CSS2/text/text-indent-wrap-001-notref-block-margin.xht
+++ b/third_party/blink/web_tests/external/wpt/css/CSS2/text/text-indent-wrap-001-notref-block-margin.xht
@@ -2,6 +2,7 @@
 <title>CSS Reftest Reference</title>
 <link rel="author" title="L. David Baron" href="https://dbaron.org/" />
 <link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
+<link rel="mismatch" href="text-indent-wrap-001-ref-inline-margin.xht"/>
 <meta name="flags" content="" />
 <style type="text/css">
 p { margin-left: 100px }
diff --git a/third_party/blink/web_tests/external/wpt/css/CSS2/text/text-indent-wrap-001-ref-float.xht b/third_party/blink/web_tests/external/wpt/css/CSS2/text/text-indent-wrap-001-ref-float.xht
index 18809f0a..8c8c4a5 100644
--- a/third_party/blink/web_tests/external/wpt/css/CSS2/text/text-indent-wrap-001-ref-float.xht
+++ b/third_party/blink/web_tests/external/wpt/css/CSS2/text/text-indent-wrap-001-ref-float.xht
@@ -2,7 +2,7 @@
 <title>CSS Reftest Reference</title>
 <link rel="author" title="L. David Baron" href="https://dbaron.org/" />
 <link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
-<link rel="match" href="text-indent-wrap-001-ref-inline-margin.xht"/>
+<link rel="mismatch" href="text-indent-wrap-001-notref-block-margin.xht"/>
 <meta name="flags" content="" />
 <style type="text/css">
 i { float: left; height: 0.3em; width: 100px; }
diff --git a/third_party/blink/web_tests/external/wpt/css/CSS2/text/text-indent-wrap-001.xht b/third_party/blink/web_tests/external/wpt/css/CSS2/text/text-indent-wrap-001.xht
index dc4c9b3a..31c2266 100644
--- a/third_party/blink/web_tests/external/wpt/css/CSS2/text/text-indent-wrap-001.xht
+++ b/third_party/blink/web_tests/external/wpt/css/CSS2/text/text-indent-wrap-001.xht
@@ -4,7 +4,6 @@
 <link rel="author" title="Mozilla Corporation" href="http://mozilla.com/" />
 <link rel="help" href="http://www.w3.org/TR/CSS21/text.html#indentation-prop" />
 <link rel="match" href="text-indent-wrap-001-ref-inline-margin.xht"/>
-<link rel="mismatch" href="text-indent-wrap-001-notref-block-margin.xht"/>
 <meta name="flags" content="" />
 <style type="text/css">
 p { text-indent: 100px }
@@ -15,4 +14,4 @@
 <p><span>This is a long piece of text that will wrap to multiple lines.  This is a long piece of text that will wrap to multiple lines.  This is a long piece of text that will wrap to multiple lines.  This is a long piece of text that will wrap to multiple lines.  This is a long piece of text that will wrap to multiple lines.  This is a long piece of text that will wrap to multiple lines.  This is a long piece of text that will wrap to multiple lines.  This is a long piece of text that will wrap to multiple lines.  This is a long piece of text that will wrap to multiple lines.  This is a long piece of text that will wrap to multiple lines.  This is a long piece of text that will wrap to multiple lines.  This is a long piece of text that will wrap to multiple lines.</span></p>
 
 
-</body></html>
\ No newline at end of file
+</body></html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-bottom-left-radius-003.xht b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-bottom-left-radius-003.xht
deleted file mode 100644
index 31221113..0000000
--- a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-bottom-left-radius-003.xht
+++ /dev/null
@@ -1,64 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-    <head>
-        <title>CSS Test: Borders. Border-bottom-left-radius using two length values: 40px 20px</title>
-		<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-		<meta http-equiv="Content-Style-Type" content="text/css" />
-        <meta http-equiv="Content-Script-Type" content="text/javascript" />
-        <link rel="author" title="Nokia" href="http://www.nokia.com/" />
-        <link rel="help" href="http://www.w3.org/TR/css3-background/#the-border-radius" />
-        <link rel="match" href="border-bottom-left-radius-004.xht" />
-        <meta name="flags" content="" />
-        <meta name="assert" content="To verify border-bottom-left-radius property set to two length values, works as expected" />
-        <style type="text/css">
-        /* <![CDATA[ */
-        	div
-			{
-        		border:2px solid #a1a1a1;
-        		background:#dddddd;
-        		width:200px;
-        		height: 100px;
-        		border-bottom-left-radius: 40px 20px;
-        	}
-        /* ]]> */
-        </style>
-<!--
-        <script type="text/javascript" src="js/css3_test_helper.js"></script>
--->
-    </head>
-    <body>
-		<p>
-			There should be a box with a rounded bottom left corner.
-		</p>
-		 <!-- PASS AND FAIL CRITERIA ARE IN THE LIST BELOW -->
-				<ul>
-					<li>PASS if only bottom left corner is rounded.</li>
-					<li>FAIL if the output is not as expected.</li>
-				</ul>
-
-         <!-- PLACE TEST CONTENT FROM HERE -->
-
-    	<div id="test"></div>
-    	<p><br/></p>
-<!--
-    	<script type="text/javascript">
-        /* <![CDATA[ */
-        	var expectedBorderRadius = "40px 20px";
-
-        	var testResult = check_CSS_property("border-bottom-left-radius", expectedBorderRadius);
-
-        	// if (testResult.pass)
-        	  /* This portion of the code has been removed to ensure that the test case is not automated */
-        	// else
-        		/* This portion of the code has been removed to ensure that the test case is not automated */
-
-
-
-          if (top.FrameEnabled)	top.fnLog(testResult);
-
-        /* ]]> */
-        </script>
--->
-    </body>
-</html>
-
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-bottom-left-radius-004-ref.xht b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-bottom-left-radius-004-ref.xht
new file mode 100644
index 0000000..15732f1
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-bottom-left-radius-004-ref.xht
@@ -0,0 +1,23 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <title>border-bottom-left-radius: 48px 28px reference</title>
+    <style type="text/css">
+      div
+      {
+          width: 200px;
+          height: 100px;
+
+          background: orange;
+          border: 20px solid teal;
+          border-bottom-left-radius: 48px 28px;
+      }
+    </style>
+  </head>
+  <body>
+    <p>The box should have a border-bottom-left-radius of 48px 28px. The
+        horizontal radius should therefore be clearly larger than the
+        vertical radius.</p>
+    <div></div>
+  </body>
+</html>
+
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-bottom-left-radius-004.xht b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-bottom-left-radius-004.xht
index 01ff790..92bcec5 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-bottom-left-radius-004.xht
+++ b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-bottom-left-radius-004.xht
@@ -1,64 +1,25 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 <html xmlns="http://www.w3.org/1999/xhtml">
-    <head>
-        <title>CSS Test: Borders. Border-bottom-left-radius using one percentage value: 20%</title>
-		<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-		<meta http-equiv="Content-Style-Type" content="text/css" />
-        <meta http-equiv="Content-Script-Type" content="text/javascript" />
-        <link rel="author" title="Nokia" href="http://www.nokia.com/" />
-        <link rel="help" href="http://www.w3.org/TR/css3-background/#the-border-radius" />
-        <link rel="match" href="border-bottom-left-radius-003.xht" />
-        <meta name="flags" content="" />
-        <meta name="assert" content="To verify border-bottom-left-radius property set to percentage value, works as expected" />
-        <style type="text/css">
-        /* <![CDATA[ */
-        	div
-            {
-        		border:2px solid #a1a1a1;
-        		background:#dddddd;
-        		width:200px;
-        		height: 100px;
-        		border-bottom-left-radius: 20%;
-        	}
-        /* ]]> */
-        </style>
-<!--
-        <script type="text/javascript" src="js/css3_test_helper.js"></script>
--->
-    </head>
-    <body>
-    	<p>
-			There should be a box with a rounded bottom left corner.
-		</p>
-		 <!-- PASS AND FAIL CRITERIA ARE IN THE LIST BELOW -->
-				<ul>
-					<li>PASS if only bottom left corner is rounded.</li>
-					<li>FAIL if the output is not as expected.</li>
-				</ul>
+  <head>
+    <title>border-bottom-left-radius using one percentage</title>
+    <link rel="match" href="border-bottom-left-radius-004-ref.xht" />
+    <link rel="help" href="https://drafts.csswg.org/css-backgrounds/#border-radius" />
+    <style type="text/css">
+      div
+      {
+          width: 200px;
+          height: 100px;
 
-         <!-- PLACE TEST CONTENT FROM HERE -->
-
-    	<div id="test"></div>
-    	<p><br/></p>
-<!--
-    	<script type="text/javascript">
-        /* <![CDATA[ */
-        	var expectedBorderRadius = "20%";
-
-        	var testResult = check_CSS_property("border-bottom-left-radius", expectedBorderRadius);
-
-        	// if (testResult.pass)
-        	  /* This portion of the code has been removed to ensure that the test case is not automated */
-        	// else
-        		/* This portion of the code has been removed to ensure that the test case is not automated */
-
-
-
-          if (top.FrameEnabled)	top.fnLog(testResult);
-
-        /* ]]> */
-       </script>
--->
-    </body>
+          background: orange;
+          border: 20px solid teal;
+          border-bottom-left-radius: 20%;
+      }
+    </style>
+  </head>
+  <body>
+    <p>The box should have a border-bottom-left-radius of 48px 28px. The
+        horizontal radius should therefore be clearly larger than the
+        vertical radius.</p>
+    <div></div>
+  </body>
 </html>
 
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-bottom-left-radius-005-ref.xht b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-bottom-left-radius-005-ref.xht
new file mode 100644
index 0000000..26621b9
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-bottom-left-radius-005-ref.xht
@@ -0,0 +1,22 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <title>border-bottom-left-radius: 48px 14px reference</title>
+    <style type="text/css">
+      div
+      {
+          width: 200px;
+          height: 100px;
+
+          background: orange;
+          border: 20px solid teal;
+          border-bottom-left-radius: 48px 14px;
+      }
+    </style>
+  </head>
+  <body>
+    <p>The box should have a border-bottom-left-radius of 48px 14px. The
+        horizontal radius should therefore be clearly larger than the
+        vertical radius.</p>
+    <div></div>
+  </body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-bottom-left-radius-005.xht b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-bottom-left-radius-005.xht
index 04d8a84..cc9fee1 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-bottom-left-radius-005.xht
+++ b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-bottom-left-radius-005.xht
@@ -1,63 +1,24 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 <html xmlns="http://www.w3.org/1999/xhtml">
-    <head>
-        <title>CSS Test: Borders. Border-bottom-left-radius using two percentage values: 20% 30%</title>
-		<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-		<meta http-equiv="Content-Style-Type" content="text/css" />
-        <meta http-equiv="Content-Script-Type" content="text/javascript" />
-        <link rel="author" title="Nokia" href="http://www.nokia.com/" />
-        <link rel="help" href="http://www.w3.org/TR/css3-background/#the-border-radius" />
-        <link rel="match" href="border-bottom-left-radius-006.xht" />
-        <meta name="flags" content="" />
-        <meta name="assert" content="To verify border-bottom-left-radius property set to two precentage value, works as expected" />
-        <style type="text/css">
-        /* <![CDATA[ */
-        	div
-          {
-        		border:2px solid #a1a1a1;
-        		background:#dddddd;
-        		width:200px;
-        		height: 100px;
-        		border-bottom-left-radius: 20% 30%;
-        	}
-        /* ]]> */
-        </style>
-<!--
-        <script type="text/javascript" src="js/css3_test_helper.js"></script>
--->
-    </head>
-    <body>
-    	<p>
-			There should be a box with a rounded bottom left corner.
-		</p>
-		 <!-- PASS AND FAIL CRITERIA ARE IN THE LIST BELOW -->
-				<ul>
-					<li>PASS if only bottom left corner is rounded.</li>
-					<li>FAIL if the output is not as expected.</li>
-				</ul>
+  <head>
+    <title>border-bottom-left-radius using two percentages</title>
+    <link rel="match" href="border-bottom-left-radius-005-ref.xht" />
+    <link rel="help" href="https://drafts.csswg.org/css-backgrounds/#border-radius" />
+    <style type="text/css">
+      div
+      {
+          width: 200px;
+          height: 100px;
 
-         <!-- PLACE TEST CONTENT FROM HERE -->
-    	<div id="test"></div>
-    	<p><br/></p>
-<!--
-    	<script type="text/javascript">
-        /* <![CDATA[ */
-        	var expectedBorderRadius = "20% 30%";
-
-        	var testResult = check_CSS_property("border-bottom-left-radius", expectedBorderRadius);
-
-        	// if (testResult.pass)
-        	  /* This portion of the code has been removed to ensure that the test case is not automated */
-        	// else
-        		/* This portion of the code has been removed to ensure that the test case is not automated */
-
-
-
-          if (top.FrameEnabled)	top.fnLog(testResult);
-
-        /* ]]> */
-        </script>
--->
-    </body>
+          background: orange;
+          border: 20px solid teal;
+          border-bottom-left-radius: 20% 10%;
+      }
+    </style>
+  </head>
+  <body>
+    <p>The box should have a border-bottom-left-radius of 48px 14px. The
+        horizontal radius should therefore be clearly larger than the
+        vertical radius.</p>
+    <div></div>
+  </body>
 </html>
-
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-bottom-left-radius-006.xht b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-bottom-left-radius-006.xht
deleted file mode 100644
index 8f522644..0000000
--- a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-bottom-left-radius-006.xht
+++ /dev/null
@@ -1,63 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-    <head>
-        <title>CSS Test: Borders. Border-bottom-left-radius using two values: 40px 30%</title>
-		<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-		<meta http-equiv="Content-Style-Type" content="text/css" />
-        <meta http-equiv="Content-Script-Type" content="text/javascript" />
-        <link rel="author" title="Nokia" href="http://www.nokia.com/" />
-        <link rel="help" href="http://www.w3.org/TR/css3-background/#the-border-radius" />
-        <link rel="match" href="border-bottom-left-radius-005.xht" />
-        <meta name="flags" content="" />
-        <meta name="assert" content="To verify border-bottom-left-radius property set to two values in different unit, works fine" />
-        <style type="text/css">
-        /* <![CDATA[ */
-        	div
-           {
-        		border:2px solid #a1a1a1;
-        		background:#dddddd;
-        		width:200px;
-        		height: 100px;
-        		border-bottom-left-radius: 40px 30%;
-        	}
-        /* ]]> */
-      </style>
-<!--
-        <script type="text/javascript" src="js/css3_test_helper.js"></script>
--->
-    </head>
-    <body>
-    	<p>
-			There should be a box with a rounded bottom left corner.
-		</p>
-		 <!-- PASS AND FAIL CRITERIA ARE IN THE LIST BELOW -->
-				<ul>
-					<li>PASS if only bottom left corner is rounded.</li>
-					<li>FAIL if the output is not as expected.</li>
-				</ul>
-
-         <!-- PLACE TEST CONTENT FROM HERE -->
-    	<div id="test"></div>
-    	<p><br/></p>
-<!--
-    	<script type="text/javascript">
-        /* <![CDATA[ */
-        	var expectedBorderRadius = "40px 30%";
-
-        	var testResult = check_CSS_property("border-bottom-left-radius", expectedBorderRadius);
-
-        	// if (testResult.pass)
-        	  /* This portion of the code has been removed to ensure that the test case is not automated */
-        	// else
-        		/* This portion of the code has been removed to ensure that the test case is not automated */
-
-
-
-          if (top.FrameEnabled)	top.fnLog(testResult);
-
-        /* ]]> */
-        </script>
--->
-    </body>
-</html>
-
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-bottom-left-radius-007.xht b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-bottom-left-radius-007.xht
deleted file mode 100644
index 54bd5bd..0000000
--- a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-bottom-left-radius-007.xht
+++ /dev/null
@@ -1,63 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-    <head>
-        <title>CSS Test: Borders. Border-bottom-left-radius using two values: 20% 25px</title>
-		<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-		<meta http-equiv="Content-Style-Type" content="text/css" />
-        <meta http-equiv="Content-Script-Type" content="text/javascript" />
-        <link rel="author" title="Nokia" href="http://www.nokia.com/" />
-        <link rel="help" href="http://www.w3.org/TR/css3-background/#the-border-radius" />
-        <link rel="match" href="border-bottom-left-radius-009.xht" />
-        <meta name="flags" content="" />
-        <meta name="assert" content="To verify border-bottom-left-radius property set to two values in different unit, works fine" />
-        <style type="text/css">
-        /* <![CDATA[ */
-        	div
-            {
-        		border:2px solid #a1a1a1;
-        		background:#dddddd;
-        		width:200px;
-        		height: 100px;
-        		border-bottom-left-radius: 20% 25px;
-        	}
-        /* ]]> */
-        </style>
-<!--
-        <script type="text/javascript" src="js/css3_test_helper.js"></script>
--->
-    </head>
-    <body>
-    	<p>
-			There should be a box with a rounded bottom left corner.
-		</p>
-		 <!-- PASS AND FAIL CRITERIA ARE IN THE LIST BELOW -->
-				<ul>
-					<li>PASS if only bottom left corner is rounded.</li>
-					<li>FAIL if the output is not as expected.</li>
-				</ul>
-
-         <!-- PLACE TEST CONTENT FROM HERE -->
-    	<div id="test"></div>
-    	<p><br/></p>
-<!--
-    	<script type="text/javascript">
-        /* <![CDATA[ */
-        	var expectedBorderRadius = "20% 25px";
-
-        	var testResult = check_CSS_property("border-bottom-left-radius", expectedBorderRadius);
-
-        	// if (testResult.pass)
-        	  /* This portion of the code has been removed to ensure that the test case is not automated */
-        	// else
-        		/* This portion of the code has been removed to ensure that the test case is not automated */
-
-
-
-          if (top.FrameEnabled)	top.fnLog(testResult);
-
-        /* ]]> */
-       </script>
--->
-    </body>
-</html>
-
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-bottom-left-radius-008.xht b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-bottom-left-radius-008.xht
deleted file mode 100644
index 33876eeb..0000000
--- a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-bottom-left-radius-008.xht
+++ /dev/null
@@ -1,62 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-    <head>
-        <title>CSS Test: Borders. Border-bottom-left-radius using two values: 4em 30%</title>
-		<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-		<meta http-equiv="Content-Style-Type" content="text/css" />
-        <meta http-equiv="Content-Script-Type" content="text/javascript" />
-        <link rel="author" title="Nokia" href="http://www.nokia.com/" />
-        <link rel="help" href="http://www.w3.org/TR/css3-background/#the-border-radius" />
-        <meta name="flags" content="" />
-        <meta name="assert" content="To verify border-bottom-left-radius property set to two values in different units, works fine" />
-        <style type="text/css">
-        /* <![CDATA[ */
-        	div
-            {
-        		border:2px solid #a1a1a1;
-        		background:#dddddd;
-        		width:200px;
-        		height: 100px;
-        		border-bottom-left-radius: 4em 30%;
-        	}
-        /* ]]> */
-        </style>
-<!--
-        <script type="text/javascript" src="js/css3_test_helper.js"></script>
--->
-    </head>
-    <body>
-    	<p>
-			There should be a box with a rounded bottom left corner.
-		</p>
-		 <!-- PASS AND FAIL CRITERIA ARE IN THE LIST BELOW -->
-				<ul>
-					<li>PASS if only bottom left corner is rounded.</li>
-					<li>FAIL if the output is not as expected.</li>
-				</ul>
-
-         <!-- PLACE TEST CONTENT FROM HERE -->
-    	<div id="test"></div>
-    	<p><br/></p>
-<!--
-    	<script type="text/javascript">
-        /* <![CDATA[ */
-        	var expectedBorderRadius = "64px 30%";
-
-        	var testResult = check_CSS_property("border-bottom-left-radius", expectedBorderRadius);
-
-        	// if (testResult.pass)
-        	  /* This portion of the code has been removed to ensure that the test case is not automated */
-        	// else
-        		/* This portion of the code has been removed to ensure that the test case is not automated */
-
-
-
-          if (top.FrameEnabled)	top.fnLog(testResult);
-
-        /* ]]> */
-        </script>
--->
-    </body>
-</html>
-
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-bottom-left-radius-009.xht b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-bottom-left-radius-009.xht
deleted file mode 100644
index 17df815f..0000000
--- a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-bottom-left-radius-009.xht
+++ /dev/null
@@ -1,67 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-    <head>
-        <title>CSS Test: Borders. Border-bottom-left-radius using &quot;inherit&quot;</title>
-		<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-		<meta http-equiv="Content-Style-Type" content="text/css" />
-        <meta http-equiv="Content-Script-Type" content="text/javascript" />
-        <link rel="author" title="Nokia" href="http://www.nokia.com/" />
-        <link rel="help" href="http://www.w3.org/TR/css3-background/#the-border-radius" />
-        <link rel="match" href="border-bottom-left-radius-007.xht" />
-       <meta name="flags" content="" />
-        <meta name="assert" content="To verify if inherit feature works, when assigned to border-bottom-left-radius" />
-        <style type="text/css">
-        /* <![CDATA[ */
-        	body
-        	{
-        		border-bottom-left-radius: 20% 25px;
-        	}
-        	div
-            {
-        		border:2px solid #a1a1a1;
-        		background:#dddddd;
-        		width:200px;
-        		height: 100px;
-        		border-bottom-left-radius: inherit;
-        	}
-        /* ]]> */
-        </style>
-<!--
-        <script type="text/javascript" src="js/css3_test_helper.js"></script>
--->
-    </head>
-    <body>
-    	<p>
-			There should be a box with a rounded bottom left corner.
-		</p>
-		 <!-- PASS AND FAIL CRITERIA ARE IN THE LIST BELOW -->
-				<ul>
-					<li>PASS if only bottom left corner is rounded.</li>
-					<li>FAIL if the output is not as expected.</li>
-				</ul>
-
-         <!-- PLACE TEST CONTENT FROM HERE -->
-    	<div id="test"></div>
-    	<p><br/></p>
-<!--
-    	<script type="text/javascript">
-        /* <![CDATA[ */
-        	var expectedBorderRadius = "20% 25px";
-
-        	var testResult = check_CSS_property("border-bottom-left-radius", expectedBorderRadius);
-
-        	// if (testResult.pass)
-        	  /* This portion of the code has been removed to ensure that the test case is not automated */
-        	// else
-        		/* This portion of the code has been removed to ensure that the test case is not automated */
-
-
-
-          if (top.FrameEnabled)	top.fnLog(testResult);
-
-        /* ]]> */
-        </script>
--->
-    </body>
-</html>
-
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-bottom-right-radius-003.xht b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-bottom-right-radius-003.xht
deleted file mode 100644
index ba13706..0000000
--- a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-bottom-right-radius-003.xht
+++ /dev/null
@@ -1,63 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-    <head>
-        <title>CSS Test: Borders. Border-bottom-right-radius using two length values: 40px 20px</title>
-		<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-		<meta http-equiv="Content-Style-Type" content="text/css" />
-        <meta http-equiv="Content-Script-Type" content="text/javascript" />
-        <link rel="author" title="Nokia" href="http://www.nokia.com/" />
-        <link rel="help" href="http://www.w3.org/TR/css3-background/#the-border-radius" />
-        <link rel="match" href="border-bottom-right-radius-004.xht" />
-        <meta name="flags" content="" />
-        <meta name="assert" content="To verify border-bottom-right-radius property set with two length values, works as expected" />
-        <style type="text/css">
-        /* <![CDATA[ */
-        	div
-            {
-        		border:2px solid #a1a1a1;
-        		background:#dddddd;
-        		width:200px;
-        		height: 100px;
-        		border-bottom-right-radius: 40px 20px;
-        	}
-        /* ]]> */
-        </style>
-<!--
-        <script type="text/javascript" src="js/css3_test_helper.js"></script>
--->
-    </head>
-    <body>
-    	 <p>
-			There should be a box with a rounded bottom right corner.
-		 </p>
-		 <!-- PASS AND FAIL CRITERIA ARE IN THE LIST BELOW -->
-				<ul>
-					<li>PASS if only bottom right corner is rounded.</li>
-					<li>FAIL if the output is not as expected.</li>
-				</ul>
-
-         <!-- PLACE TEST CONTENT FROM HERE -->
-    	<div id="test"></div>
-    	<p><br/></p>
-<!--
-    	<script type="text/javascript">
-        /* <![CDATA[ */
-        	var expectedBorderRadius = "40px 20px";
-
-        	var testResult = check_CSS_property("border-bottom-right-radius", expectedBorderRadius);
-
-        	// if (testResult.pass)
-        	  /* This portion of the code has been removed to ensure that the test case is not automated */
-        	// else
-        		/* This portion of the code has been removed to ensure that the test case is not automated */
-
-
-
-          if (top.FrameEnabled)	top.fnLog(testResult);
-
-        /* ]]> */
-       </script>
--->
-    </body>
-</html>
-
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-bottom-right-radius-004-ref.xht b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-bottom-right-radius-004-ref.xht
new file mode 100644
index 0000000..8589ee96
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-bottom-right-radius-004-ref.xht
@@ -0,0 +1,23 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <title>border-bottom-right-radius: 48px 28px reference</title>
+    <style type="text/css">
+      div
+      {
+          width: 200px;
+          height: 100px;
+
+          background: orange;
+          border: 20px solid teal;
+          border-bottom-right-radius: 48px 28px;
+      }
+    </style>
+  </head>
+  <body>
+    <p>The box should have a border-bottom-right-radius of 48px 28px. The
+        horizontal radius should therefore be clearly larger than the
+        vertical radius.</p>
+    <div></div>
+  </body>
+</html>
+
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-bottom-right-radius-004.xht b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-bottom-right-radius-004.xht
index 907ed82..d9bbcf95 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-bottom-right-radius-004.xht
+++ b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-bottom-right-radius-004.xht
@@ -1,63 +1,25 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 <html xmlns="http://www.w3.org/1999/xhtml">
-    <head>
-        <title>CSS Test: Borders. Border-bottom-right-radius using one percentage value: 20%</title>
-		<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-		<meta http-equiv="Content-Style-Type" content="text/css" />
-        <meta http-equiv="Content-Script-Type" content="text/javascript" />
-        <link rel="author" title="Nokia" href="http://www.nokia.com/" />
-        <link rel="help" href="http://www.w3.org/TR/css3-background/#the-border-radius" />
-        <link rel="match" href="border-bottom-right-radius-003.xht" />
-        <meta name="flags" content="" />
-        <meta name="assert" content="To verify border-bottom-right-radius property set with one percentage value, works as expected" />
-        <style type="text/css">
-        /* <![CDATA[ */
-        	div
-          {
-        		border:2px solid #a1a1a1;
-        		background:#dddddd;
-        		width:200px;
-        		height: 100px;
-        		border-bottom-right-radius: 20%;
-        	}
-        /* ]]> */
-        </style>
-<!--
-        <script type="text/javascript" src="js/css3_test_helper.js"></script>
--->
-    </head>
-    <body>
-    	<p>
-			There should be a box with a rounded bottom right corner.
-		</p>
-		 <!-- PASS AND FAIL CRITERIA ARE IN THE LIST BELOW -->
-				<ul>
-					<li>PASS if only bottom right corner is rounded.</li>
-					<li>FAIL if the output is not as expected.</li>
-				</ul>
+  <head>
+    <title>border-bottom-right-radius using one percentage</title>
+    <link rel="match" href="border-bottom-right-radius-004-ref.xht" />
+    <link rel="help" href="https://drafts.csswg.org/css-backgrounds/#border-radius" />
+    <style type="text/css">
+      div
+      {
+          width: 200px;
+          height: 100px;
 
-         <!-- PLACE TEST CONTENT FROM HERE -->
-    	<div id="test"></div>
-    	<p><br/></p>
-<!--
-    	<script type="text/javascript">
-        /* <![CDATA[ */
-        	var expectedBorderRadius = "20%";
-
-        	var testResult = check_CSS_property("border-bottom-right-radius", expectedBorderRadius);
-
-        	// if (testResult.pass)
-        	  /* This portion of the code has been removed to ensure that the test case is not automated */
-        	// else
-        		/* This portion of the code has been removed to ensure that the test case is not automated */
-
-
-
-          if (top.FrameEnabled)	top.fnLog(testResult);
-
-        /* ]]> */
-        </script>
--->
-    </body>
+          background: orange;
+          border: 20px solid teal;
+          border-bottom-right-radius: 20%;
+      }
+    </style>
+  </head>
+  <body>
+    <p>The box should have a border-bottom-right-radius of 48px 28px. The
+        horizontal radius should therefore be clearly larger than the
+        vertical radius.</p>
+    <div></div>
+  </body>
 </html>
 
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-bottom-right-radius-005-ref.xht b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-bottom-right-radius-005-ref.xht
new file mode 100644
index 0000000..9ed21b7
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-bottom-right-radius-005-ref.xht
@@ -0,0 +1,22 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <title>border-bottom-right-radius: 48px 14px reference</title>
+    <style type="text/css">
+      div
+      {
+          width: 200px;
+          height: 100px;
+
+          background: orange;
+          border: 20px solid teal;
+          border-bottom-right-radius: 48px 14px;
+      }
+    </style>
+  </head>
+  <body>
+    <p>The box should have a border-bottom-right-radius of 48px 14px. The
+        horizontal radius should therefore be clearly larger than the
+        vertical radius.</p>
+    <div></div>
+  </body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-bottom-right-radius-005.xht b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-bottom-right-radius-005.xht
index 899b3b5..89912542 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-bottom-right-radius-005.xht
+++ b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-bottom-right-radius-005.xht
@@ -1,63 +1,24 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 <html xmlns="http://www.w3.org/1999/xhtml">
-    <head>
-        <title>CSS Test: Borders. Border-bottom-right-radius using two percentage value: 20% 30%</title>
-		<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-		<meta http-equiv="Content-Style-Type" content="text/css" />
-        <meta http-equiv="Content-Script-Type" content="text/javascript" />
-        <link rel="author" title="Nokia" href="http://www.nokia.com/" />
-        <link rel="help" href="http://www.w3.org/TR/css3-background/#the-border-radius" />
-        <link rel="match" href="border-bottom-right-radius-006.xht" />
-        <meta name="flags" content="" />
-        <meta name="assert" content="To verify border-bottom-right-radius property set with two percentage value works as expected" />
-        <style type="text/css">
-        /* <![CDATA[ */
-        	div
-            {
-        		border:2px solid #a1a1a1;
-        		background:#dddddd;
-        		width:200px;
-        		height: 100px;
-        		border-bottom-right-radius: 20% 30%;
-        	}
-        /* ]]> */
-        </style>
-<!--
-        <script type="text/javascript" src="js/css3_test_helper.js"></script>
--->
-    </head>
-    <body>
-    	<p>
-			There should be a box with a rounded bottom right corner.
-		</p>
-		 <!-- PASS AND FAIL CRITERIA ARE IN THE LIST BELOW -->
-				<ul>
-					<li>PASS if only bottom right corner is rounded.</li>
-					<li>FAIL if the output is not as expected.</li>
-				</ul>
+  <head>
+    <title>border-bottom-right-radius using two percentages</title>
+    <link rel="match" href="border-bottom-right-radius-005-ref.xht" />
+    <link rel="help" href="https://drafts.csswg.org/css-backgrounds/#border-radius" />
+    <style type="text/css">
+      div
+      {
+          width: 200px;
+          height: 100px;
 
-         <!-- PLACE TEST CONTENT FROM HERE -->
-    	<div id="test"></div>
-    	<p><br/></p>
-<!--
-    	<script type="text/javascript">
-        /* <![CDATA[ */
-        	var expectedBorderRadius = "20% 30%";
-
-        	var testResult = check_CSS_property("border-bottom-right-radius", expectedBorderRadius);
-
-        	// if (testResult.pass)
-        	  /* This portion of the code has been removed to ensure that the test case is not automated */
-        	// else
-        		/* This portion of the code has been removed to ensure that the test case is not automated */
-
-
-
-          if (top.FrameEnabled)	top.fnLog(testResult);
-
-        /* ]]> */
-        </script>
--->
-    </body>
+          background: orange;
+          border: 20px solid teal;
+          border-bottom-right-radius: 20% 10%;
+      }
+    </style>
+  </head>
+  <body>
+    <p>The box should have a border-bottom-right-radius of 48px 14px. The
+        horizontal radius should therefore be clearly larger than the
+        vertical radius.</p>
+    <div></div>
+  </body>
 </html>
-
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-bottom-right-radius-006.xht b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-bottom-right-radius-006.xht
deleted file mode 100644
index d47009d..0000000
--- a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-bottom-right-radius-006.xht
+++ /dev/null
@@ -1,63 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-    <head>
-        <title>CSS Test: Borders. Border-bottom-right-radius using two value: 40px 30%</title>
-		<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-		<meta http-equiv="Content-Style-Type" content="text/css" />
-        <meta http-equiv="Content-Script-Type" content="text/javascript" />
-        <link rel="author" title="Nokia" href="http://www.nokia.com/" />
-        <link rel="help" href="http://www.w3.org/TR/css3-background/#the-border-radius" />
-        <link rel="match" href="border-bottom-right-radius-005.xht" />
-        <meta name="flags" content="" />
-        <meta name="assert" content="To verify border-bottom-right-radius property set to two value with different unit, works as expected"/>
-        <style type="text/css">
-        /* <![CDATA[ */
-        	div
-            {
-        		border:2px solid #a1a1a1;
-        		background:#dddddd;
-        		width:200px;
-        		height: 100px;
-        		border-bottom-right-radius: 40px 30%;
-        	}
-        /* ]]> */
-        </style>
-<!--
-        <script type="text/javascript" src="js/css3_test_helper.js"></script>
--->
-    </head>
-    <body>
-    	<p>
-			There should be a box with a rounded bottom right corner.
-		</p>
-		 <!-- PASS AND FAIL CRITERIA ARE IN THE LIST BELOW -->
-				<ul>
-					<li>PASS if only bottom right corner is rounded.</li>
-					<li>FAIL if the output is not as expected.</li>
-				</ul>
-
-         <!-- PLACE TEST CONTENT FROM HERE -->
-    	<div id="test"></div>
-    	<p><br/></p>
-<!--
-    	<script type="text/javascript">
-        /* <![CDATA[ */
-        	var expectedBorderRadius = "40px 30%";
-
-        	var testResult = check_CSS_property("border-bottom-right-radius", expectedBorderRadius);
-
-        	// if (testResult.pass)
-        	  /* This portion of the code has been removed to ensure that the test case is not automated */
-        	// else
-        		/* This portion of the code has been removed to ensure that the test case is not automated */
-
-
-
-          if (top.FrameEnabled)	top.fnLog(testResult);
-
-        /* ]]> */
-        </script>
--->
-    </body>
-</html>
-
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-bottom-right-radius-007.xht b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-bottom-right-radius-007.xht
deleted file mode 100644
index c0d5b73..0000000
--- a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-bottom-right-radius-007.xht
+++ /dev/null
@@ -1,63 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-    <head>
-        <title>CSS Test: Borders. Border-bottom-right-radius using two value: 20% 25px</title>
-		<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-		<meta http-equiv="Content-Style-Type" content="text/css" />
-        <meta http-equiv="Content-Script-Type" content="text/javascript" />
-        <link rel="author" title="Nokia" href="http://www.nokia.com/" />
-        <link rel="help" href="http://www.w3.org/TR/css3-background/#the-border-radius" />
-        <link rel="match" href="border-bottom-right-radius-009.xht" />
-        <meta name="flags" content="" />
-        <meta name="assert" content="To verify border-bottom-right-radius property set to two value with different unit, works as expected" />
-        <style type="text/css">
-        /* <![CDATA[ */
-        	div
-            {
-        		border:2px solid #a1a1a1;
-        		background:#dddddd;
-        		width:200px;
-        		height: 100px;
-        		border-bottom-right-radius: 20% 25px;
-        	}
-        /* ]]> */
-        </style>
-<!--
-        <script type="text/javascript" src="js/css3_test_helper.js"></script>
--->
-    </head>
-    <body>
-    	<p>
-			There should be a box with a rounded bottom right corner.
-		</p>
-		 <!-- PASS AND FAIL CRITERIA ARE IN THE LIST BELOW -->
-				<ul>
-					<li>PASS if only bottom right corner is rounded.</li>
-					<li>FAIL if the output is not as expected.</li>
-				</ul>
-
-         <!-- PLACE TEST CONTENT FROM HERE -->
-    	<div id="test"></div>
-    	<p><br/></p>
-<!--
-    	<script type="text/javascript">
-        /* <![CDATA[ */
-        	var expectedBorderRadius = "20% 25px";
-
-        	var testResult = check_CSS_property("border-bottom-right-radius", expectedBorderRadius);
-
-        	// if (testResult.pass)
-        	  /* This portion of the code has been removed to ensure that the test case is not automated */
-        	// else
-        		/* This portion of the code has been removed to ensure that the test case is not automated */
-
-
-
-          if (top.FrameEnabled)	top.fnLog(testResult);
-
-        /* ]]> */
-        </script>
--->
-    </body>
-</html>
-
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-bottom-right-radius-008.xht b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-bottom-right-radius-008.xht
deleted file mode 100644
index b4b7b6e..0000000
--- a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-bottom-right-radius-008.xht
+++ /dev/null
@@ -1,62 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-    <head>
-        <title>CSS Test: Borders. Border-bottom-right-radius using two values: 4em 30%</title>
-		<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-		<meta http-equiv="Content-Style-Type" content="text/css" />
-        <meta http-equiv="Content-Script-Type" content="text/javascript" />
-        <link rel="author" title="Nokia" href="http://www.nokia.com/" />
-        <link rel="help" href="http://www.w3.org/TR/css3-background/#the-border-radius" />
-        <meta name="flags" content="" />
-        <meta name="assert" content="To verify border-bottom-right-radius property set to two values with different units, works as expected" />
-        <style type="text/css">
-        /* <![CDATA[ */
-        	div
-            {
-        		border:2px solid #a1a1a1;
-        		background:#dddddd;
-        		width:200px;
-        		height: 100px;
-        		border-bottom-right-radius: 4em 30%;
-        	}
-        /* ]]> */
-        </style>
-<!--
-        <script type="text/javascript" src="js/css3_test_helper.js"></script>
--->
-    </head>
-    <body>
-    	<p>
-			There should be a box with a rounded bottom right corner.
-		</p>
-		 <!-- PASS AND FAIL CRITERIA ARE IN THE LIST BELOW -->
-				<ul>
-					<li>PASS if only bottom right corner is rounded.</li>
-					<li>FAIL if the output is not as expected.</li>
-				</ul>
-
-         <!-- PLACE TEST CONTENT FROM HERE -->
-    	<div id="test"></div>
-    	<p><br/></p>
-<!--
-    	<script type="text/javascript">
-        /* <![CDATA[ */
-        	var expectedBorderRadius = "64px 30%";
-
-        	var testResult = check_CSS_property("border-bottom-right-radius", expectedBorderRadius);
-
-        	// if (testResult.pass)
-        	  /* This portion of the code has been removed to ensure that the test case is not automated */
-        	// else
-        		/* This portion of the code has been removed to ensure that the test case is not automated */
-
-
-
-          if (top.FrameEnabled)	top.fnLog(testResult);
-
-        /* ]]> */
-        </script>
--->
-    </body>
-</html>
-
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-bottom-right-radius-009.xht b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-bottom-right-radius-009.xht
deleted file mode 100644
index 633caa5..0000000
--- a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-bottom-right-radius-009.xht
+++ /dev/null
@@ -1,67 +0,0 @@
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-    <head>
-        <title>CSS Test: Borders. Border-bottom-right-radius using &quot;inherit&quot;</title>
-		<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-		<meta http-equiv="Content-Style-Type" content="text/css" />
-        <meta http-equiv="Content-Script-Type" content="text/javascript" />
-        <link rel="author" title="Nokia" href="http://www.nokia.com/" />
-        <link rel="help" href="http://www.w3.org/TR/css3-background/#the-border-radius" />
-        <link rel="match" href="border-bottom-right-radius-007.xht" />
-        <meta name="flags" content="" />
-        <meta name="assert" content="To verify if inherit feature works, when assigned to &quot;border&ndash;bottom&ndash;right&ndash;radius&quot; property" />
-        <style type="text/css">
-        /* <![CDATA[ */
-        	body
-        	{
-        		border-bottom-right-radius: 20% 25px;
-        	}
-        	div
-            {
-        		border:2px solid #a1a1a1;
-        		background:#dddddd;
-        		width:200px;
-        		height: 100px;
-        		border-bottom-right-radius: inherit;
-        	}
-        /* ]]> */
-        </style>
-<!--
-        <script type="text/javascript" src="js/css3_test_helper.js"></script>
--->
-    </head>
-    <body>
-    	<p>
-			There should be a box with a rounded bottom right corner.
-		</p>
-		 <!-- PASS AND FAIL CRITERIA ARE IN THE LIST BELOW -->
-				<ul>
-					<li>PASS if only bottom right corner is rounded.</li>
-					<li>FAIL if the output is not as expected.</li>
-				</ul>
-
-         <!-- PLACE TEST CONTENT FROM HERE -->
-    	<div id="test"></div>
-    	<p><br/></p>
-<!--
-    	<script type="text/javascript">
-        /* <![CDATA[ */
-        	var expectedBorderRadius = "20% 25px";
-
-        	var testResult = check_CSS_property("border-bottom-right-radius", expectedBorderRadius);
-
-        	// if (testResult.pass)
-        	  /* This portion of the code has been removed to ensure that the test case is not automated */
-        	// else
-        		/* This portion of the code has been removed to ensure that the test case is not automated */
-
-
-
-          if (top.FrameEnabled)	top.fnLog(testResult);
-
-        /* ]]> */
-       </script>
--->
-    </body>
-</html>
-
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-image-5.html b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-image-5.html
deleted file mode 100644
index 4fecfc7..0000000
--- a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-image-5.html
+++ /dev/null
@@ -1,47 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-    <meta charset="utf-8">
-    <title>
-        CSS Border and Background: border-image #5 border-image-slice
-    </title>
-    <meta name="assert" content="Negative values for the the border-image-slice property should not be supported" />
-
-    <link rel="author" title="Jérémie Patonnier" href="mailto:jeremie@patonnier.net" / >
-
-    <link rel="help" href="http://www.w3.org/TR/css3-background/#border-image-slice">
-
-    <link rel="match" href="support/reftest-border-image-5.png" />
-
-    <style type="text/css">
-
-        #filler {
-            background-color : #009900;
-            width : 40px;
-            height: 40px;
-        }
-
-        #test {
-            border : 10px solid red;
-            width  : 40px;
-            height : 40px;
-
-            border-image-source: url(support/img-ref-1.png);
-            border-image-slice : -10;
-        }
-
-    </style>
-
-</head>
-<body>
-
-    <p>
-        Pass if the green square have smaller green squares at its corners and <strong>no</strong> red.
-    </p>
-
-    <div id="test">
-        <div id="filler"></div>
-    </div>
-
-</body>
-</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-image-6-ref.html b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-image-6-ref.html
new file mode 100644
index 0000000..f3e3bb7
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-image-6-ref.html
@@ -0,0 +1,69 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8">
+    <title>border-image-6-ref</title>
+
+    <style type="text/css">
+      #container {
+          position: relative;
+
+          width: 60px;
+          height: 60px;
+      }
+
+      #filler {
+          position: absolute;
+          top: 10px;
+          left: 10px;
+
+          width: 40px;
+          height: 40px;
+
+          background-color: #090;
+      }
+
+      .small {
+          position: absolute;
+
+          width: 10px;
+          height: 10px;
+
+          /* orange appears here to make it super-clear if this doesn't load */
+          background: url(support/img-ref-1.png) orange;
+      }
+
+      .small.top {
+          top: 0;
+      }
+
+      .small.bottom {
+          bottom: 0;
+      }
+
+      .small.left {
+          left: 0;
+      }
+
+      .small.right {
+          right: 0;
+      }
+    </style>
+
+  </head>
+  <body>
+
+    <p>
+      Pass if the green square have smaller green squares at its corners and <strong>no</strong> red borders.
+    </p>
+
+    <div id="container">
+      <div id="filler"></div>
+      <div class="small top left"></div>
+      <div class="small top right"></div>
+      <div class="small bottom left"></div>
+      <div class="small bottom right"></div>
+    </div>
+
+  </body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-image-6.html b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-image-6.html
index 235d263..bc4cb13 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-image-6.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-image-6.html
@@ -11,7 +11,7 @@
 
     <link rel="help" href="http://www.w3.org/TR/css3-background/#border-image-slice">
 
-    <link rel="match" href="support/reftest-border-image-5.png" />
+    <link rel="match" href="border-image-6-ref.html" />
 
     <style type="text/css">
 
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-top-left-radius-003.xht b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-top-left-radius-003.xht
deleted file mode 100644
index deed8ad..0000000
--- a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-top-left-radius-003.xht
+++ /dev/null
@@ -1,62 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-    <head>
-        <title>CSS Test: Borders. Border-top-left-radius using two length values: 40px 20px</title>
-        <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
-        <meta http-equiv="Content-Style-Type" content="text/css"/>
-        <meta http-equiv="Content-Script-Type" content="text/javascript"/>
-        <link rel="author" title="Nokia" href="http://www.nokia.com/"/>
-        <link rel="help" href="http://www.w3.org/TR/css3-background/#the-border-radius"/>
-        <link rel="match" href="border-top-left-radius-004.xht" />
-        <meta name="flags" content=""/>
-        <meta name="assert" content="To verify border-top-left-radius property set to two length values, works fine"/>
-        <style type="text/css">
-        /* <![CDATA[ */
-        	div
-          {
-        		border:2px solid #a1a1a1;
-        		background:#dddddd;
-        		width:200px;
-        		height: 100px;
-        		border-top-left-radius: 40px 20px;
-        	}
-        /* ]]> */
-        </style>
-<!--
-        <script type="text/javascript" src="js/css3_test_helper.js"></script>
--->
-    </head>
-    <body>
-		<p>
-			There should be a box with a rounded top left corner.
-		</p>
-		 <!-- PASS AND FAIL CRITERIA ARE IN THE LIST BELOW -->
-        <ul>
-            <li>PASS if only top left corner is rounded.</li>
-            <li>FAIL if the output is not as expected.</li>
-        </ul>
-
-         <!-- PLACE TEST CONTENT FROM HERE -->
-
-    	<div id="test"></div>
-    	<p><br/></p>
-<!--
-    	<script type="text/javascript">
-        /* <![CDATA[ */
-        	var expectedBorderRadius = "40px 20px";
-
-        	var testResult = check_CSS_property("border-top-left-radius", expectedBorderRadius);
-
-        	/* if (testResult.pass)
-        	  // This portion of the code has been removed to ensure that the test case is not automated
-        	else {
-        		// This portion of the code has been removed to ensure that the test case is not automated
-          } */
-
-          if (top.FrameEnabled)	top.fnLog(testResult);
-         /* ]]> */
-        </script>
--->
-    </body>
-</html>
-
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-top-left-radius-004-ref.xht b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-top-left-radius-004-ref.xht
new file mode 100644
index 0000000..b9c9cdac
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-top-left-radius-004-ref.xht
@@ -0,0 +1,23 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <title>border-top-left-radius: 48px 28px reference</title>
+    <style type="text/css">
+      div
+      {
+          width: 200px;
+          height: 100px;
+
+          background: orange;
+          border: 20px solid teal;
+          border-top-left-radius: 48px 28px;
+      }
+    </style>
+  </head>
+  <body>
+    <p>The box should have a border-top-left-radius of 48px 28px. The
+        horizontal radius should therefore be clearly larger than the
+        vertical radius.</p>
+    <div></div>
+  </body>
+</html>
+
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-top-left-radius-004.xht b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-top-left-radius-004.xht
index 31e06fc..39e636d 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-top-left-radius-004.xht
+++ b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-top-left-radius-004.xht
@@ -1,62 +1,25 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 <html xmlns="http://www.w3.org/1999/xhtml">
-    <head>
-        <title>CSS Test: Borders. Border-top-left-radius using one percentage value: 20%</title>
-        <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
-        <meta http-equiv="Content-Style-Type" content="text/css"/>
-        <meta http-equiv="Content-Script-Type" content="text/javascript"/>
-        <link rel="author" title="Nokia" href="http://www.nokia.com/"/>
-        <link rel="help" href="http://www.w3.org/TR/css3-background/#the-border-radius"/>
-        <link rel="match" href="border-top-left-radius-003.xht" />
-        <meta name="flags" content=""/>
-        <meta name="assert" content="To verify border-top-left-radius property set to one percentage value, works fine"/>
-        <style type="text/css">
-        /* <![CDATA[ */
-        	div
-          {
-        		border:2px solid #a1a1a1;
-        		background:#dddddd;
-        		width:200px;
-        		height: 100px;
-        		border-top-left-radius: 20%;
-        	}
-        /* ]]> */
-        </style>
-<!--
-        <script type="text/javascript" src="js/css3_test_helper.js"></script>
--->
-    </head>
-    <body>
-		<p>
-			There should be a box with a rounded top left corner.
-		</p>
-		 <!-- PASS AND FAIL CRITERIA ARE IN THE LIST BELOW -->
-        <ul>
-            <li>PASS if only top left corner is rounded.</li>
-            <li>FAIL if the output is not as expected.</li>
-        </ul>
+  <head>
+    <title>border-top-left-radius using one percentage</title>
+    <link rel="match" href="border-top-left-radius-004-ref.xht" />
+    <link rel="help" href="https://drafts.csswg.org/css-backgrounds/#border-radius" />
+    <style type="text/css">
+      div
+      {
+          width: 200px;
+          height: 100px;
 
-         <!-- PLACE TEST CONTENT FROM HERE -->
-
-    	<div id="test"></div>
-    	<p><br/></p>
-<!--
-    	<script type="text/javascript">
-        /* <![CDATA[ */
-        	var expectedBorderRadius = "20%";
-
-        	var testResult = check_CSS_property("border-top-left-radius", expectedBorderRadius);
-
-        	/* if (testResult.pass)
-        	  // This portion of the code has been removed to ensure that the test case is not automated
-        	else {
-        		// This portion of the code has been removed to ensure that the test case is not automated
-          } */
-
-          if (top.FrameEnabled)	top.fnLog(testResult);
-        /* ]]> */
-        </script>
--->
-    </body>
+          background: orange;
+          border: 20px solid teal;
+          border-top-left-radius: 20%;
+      }
+    </style>
+  </head>
+  <body>
+    <p>The box should have a border-top-left-radius of 48px 28px. The
+        horizontal radius should therefore be clearly larger than the
+        vertical radius.</p>
+    <div></div>
+  </body>
 </html>
 
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-top-left-radius-005-ref.xht b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-top-left-radius-005-ref.xht
new file mode 100644
index 0000000..f1a1935
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-top-left-radius-005-ref.xht
@@ -0,0 +1,22 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <title>border-top-left-radius: 48px 14px reference</title>
+    <style type="text/css">
+      div
+      {
+          width: 200px;
+          height: 100px;
+
+          background: orange;
+          border: 20px solid teal;
+          border-top-left-radius: 48px 14px;
+      }
+    </style>
+  </head>
+  <body>
+    <p>The box should have a border-top-left-radius of 48px 14px. The
+        horizontal radius should therefore be clearly larger than the
+        vertical radius.</p>
+    <div></div>
+  </body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-top-left-radius-005.xht b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-top-left-radius-005.xht
index e404430..37af580 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-top-left-radius-005.xht
+++ b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-top-left-radius-005.xht
@@ -1,62 +1,24 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 <html xmlns="http://www.w3.org/1999/xhtml">
-    <head>
-        <title>CSS Test: Borders. Border-top-left-radius using two percentage values: 20% 30%</title>
-        <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
-        <meta http-equiv="Content-Style-Type" content="text/css"/>
-        <meta http-equiv="Content-Script-Type" content="text/javascript"/>
-        <link rel="author" title="Nokia" href="http://www.nokia.com/"/>
-        <link rel="help" href="http://www.w3.org/TR/css3-background/#the-border-radius"/>
-        <link rel="match" href="border-top-left-radius-006.xht" />
-        <meta name="flags" content=""/>
-        <meta name="assert" content="To verify border-top-left-radius property set to two percentage values, works fine"/>
-        <style type="text/css">
-        /* <![CDATA[ */
-        	div
-          {
-        		border:2px solid #a1a1a1;
-        		background:#dddddd;
-        		width:200px;
-        		height: 100px;
-        		border-top-left-radius: 20% 30%;
-        	}
-         /* ]]> */
-        </style>
-<!--
-        <script type="text/javascript" src="js/css3_test_helper.js"></script>
--->
-    </head>
-    <body>
-		<p>
-			There should be a box with a rounded top left corner.
-		</p>
-		 <!-- PASS AND FAIL CRITERIA ARE IN THE LIST BELOW -->
-        <ul>
-            <li>PASS if only top left corner is rounded.</li>
-            <li>FAIL if the output is not as expected.</li>
-        </ul>
+  <head>
+    <title>border-top-left-radius using two percentages</title>
+    <link rel="match" href="border-top-left-radius-005-ref.xht" />
+    <link rel="help" href="https://drafts.csswg.org/css-backgrounds/#border-radius" />
+    <style type="text/css">
+      div
+      {
+          width: 200px;
+          height: 100px;
 
-         <!-- PLACE TEST CONTENT FROM HERE -->
-
-    	<div id="test"></div>
-    	<p><br/></p>
-<!--
-    	<script type="text/javascript">
-         /* <![CDATA[ */
-        	var expectedBorderRadius = "20% 30%";
-
-        	var testResult = check_CSS_property("border-top-left-radius", expectedBorderRadius);
-
-        	/* if (testResult.pass)
-        	  // This portion of the code has been removed to ensure that the test case is not automated
-        	else {
-        		// This portion of the code has been removed to ensure that the test case is not automated
-          } */
-
-          if (top.FrameEnabled)	top.fnLog(testResult);
-        /* ]]> */
-        </script>
--->
-    </body>
+          background: orange;
+          border: 20px solid teal;
+          border-top-left-radius: 20% 10%;
+      }
+    </style>
+  </head>
+  <body>
+    <p>The box should have a border-top-left-radius of 48px 14px. The
+        horizontal radius should therefore be clearly larger than the
+        vertical radius.</p>
+    <div></div>
+  </body>
 </html>
-
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-top-left-radius-006.xht b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-top-left-radius-006.xht
deleted file mode 100644
index dc2b9ebf..0000000
--- a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-top-left-radius-006.xht
+++ /dev/null
@@ -1,62 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-    <head>
-        <title>CSS Test: Borders. Border-top-left-radius using two values: 40px 30%</title>
-        <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
-        <meta http-equiv="Content-Style-Type" content="text/css"/>
-        <meta http-equiv="Content-Script-Type" content="text/javascript"/>
-        <link rel="author" title="Nokia" href="http://www.nokia.com/"/>
-        <link rel="help" href="http://www.w3.org/TR/css3-background/#the-border-radius"/>
-        <link rel="match" href="border-top-left-radius-005.xht" />
-        <meta name="flags" content=""/>
-        <meta name="assert" content="To verify border-top-left-radius property set to two values with different units, works fine"/>
-        <style type="text/css">
-        /* <![CDATA[ */
-        	div
-          {
-        		border:2px solid #a1a1a1;
-        		background:#dddddd;
-        		width:200px;
-        		height: 100px;
-        		border-top-left-radius: 40px 30%;
-        	}
-         /* ]]> */
-        </style>
-<!--
-        <script type="text/javascript" src="js/css3_test_helper.js"></script>
--->
-    </head>
-    <body>
-		<p>
-			There should be a box with a rounded top left corner.
-		</p>
-		 <!-- PASS AND FAIL CRITERIA ARE IN THE LIST BELOW -->
-        <ul>
-            <li>PASS if only top left corner is rounded.</li>
-            <li>FAIL if the output is not as expected.</li>
-        </ul>
-
-         <!-- PLACE TEST CONTENT FROM HERE -->
-
-    	<div id="test"></div>
-    	<p><br/></p>
-<!--
-    	<script type="text/javascript">
-        /* <![CDATA[ */
-        	var expectedBorderRadius = "40px 30%";
-
-        	var testResult = check_CSS_property("border-top-left-radius", expectedBorderRadius);
-
-        	/* if (testResult.pass)
-        	  // This portion of the code has been removed to ensure that the test case is not automated
-        	else {
-        		// This portion of the code has been removed to ensure that the test case is not automated
-          } */
-
-          if (top.FrameEnabled)	top.fnLog(testResult);
-        /* ]]> */
-        </script>
--->
-    </body>
-</html>
-
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-top-left-radius-007.xht b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-top-left-radius-007.xht
deleted file mode 100644
index 7111e538..0000000
--- a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-top-left-radius-007.xht
+++ /dev/null
@@ -1,62 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-    <head>
-        <title>CSS Test: Borders. Border-top-left-radius using two values: 20% 25px</title>
-        <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
-        <meta http-equiv="Content-Style-Type" content="text/css"/>
-        <meta http-equiv="Content-Script-Type" content="text/javascript"/>
-        <link rel="author" title="Nokia" href="http://www.nokia.com/"/>
-        <link rel="help" href="http://www.w3.org/TR/css3-background/#the-border-radius"/>
-        <link rel="match" href="border-top-left-radius-009.xht" />
-        <meta name="flags" content=""/>
-        <meta name="assert" content="To verify border-top-left-radius property set to two values with different units, works fine"/>
-        <style type="text/css">
-        /* <![CDATA[ */
-        	div
-          {
-        		border:2px solid #a1a1a1;
-        		background:#dddddd;
-        		width:200px;
-        		height: 100px;
-        		border-top-left-radius: 20% 25px;
-        	}
-         /* ]]> */
-        </style>
-<!--
-        <script type="text/javascript" src="js/css3_test_helper.js"></script>
--->
-    </head>
-    <body>
-		<p>
-			There should be a box with a rounded top left corner.
-		</p>
-		 <!-- PASS AND FAIL CRITERIA ARE IN THE LIST BELOW -->
-        <ul>
-            <li>PASS if only top left corner is rounded.</li>
-            <li>FAIL if the output is not as expected.</li>
-        </ul>
-
-         <!-- PLACE TEST CONTENT FROM HERE -->
-
-    	<div id="test"></div>
-    	<p><br/></p>
-<!--
-    	<script type="text/javascript">
-        /* <![CDATA[ */
-        	var expectedBorderRadius = "20% 25px";
-
-        	var testResult = check_CSS_property("border-top-left-radius", expectedBorderRadius);
-
-        	/* if (testResult.pass)
-        	  // This portion of the code has been removed to ensure that the test case is not automated
-        	else {
-        		// This portion of the code has been removed to ensure that the test case is not automated
-          } */
-
-          if (top.FrameEnabled)	top.fnLog(testResult);
-         /* ]]> */
-        </script>
--->
-    </body>
-</html>
-
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-top-left-radius-008.xht b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-top-left-radius-008.xht
deleted file mode 100644
index 724075c..0000000
--- a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-top-left-radius-008.xht
+++ /dev/null
@@ -1,59 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-    <head>
-        <title>CSS Test: Borders. Border-top-left-radius using two values: 4em 30%</title>
-        <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
-        <meta http-equiv="Content-Style-Type" content="text/css"/>
-        <meta http-equiv="Content-Script-Type" content="text/javascript"/>
-        <link rel="author" title="Nokia" href="http://www.nokia.com/"/>
-        <link rel="help" href="http://www.w3.org/TR/css3-background/#the-border-radius"/>
-        <meta name="flags" content=""/>
-        <meta name="assert" content="To verify border-top-left-radius property set to two values with different units, works fine"/>
-        <style type="text/css">
-        /* <![CDATA[ */
-        	div
-          {
-        		border:2px solid #a1a1a1;
-        		background:#dddddd;
-        		width:200px;
-        		height: 100px;
-        		border-top-left-radius: 4em 30%;
-        	}
-         /* ]]> */
-        </style>
-<!--
-        <script type="text/javascript" src="js/css3_test_helper.js"></script>
--->
-    </head>
-    <body>
-        <p id="testdetails">
-        </p>
-        <p>
-            There should be a box with a rounded top left corner.</p>
-        <ul>
-            <li>PASS if only top left corner is rounded.</li>
-            <li>FAIL if the output is not as expected.</li>
-        </ul>
-
-
-    	<div id="test"></div>
-<!--
-    	<script type="text/javascript">
-         /* <![CDATA[ */
-        	var expectedBorderRadius = "64px 30%";
-
-        	var testResult = check_CSS_property("border-top-left-radius", expectedBorderRadius);
-
-        	/* if (testResult.pass)
-        	  // This portion of the code has been removed to ensure that the test case is not automated
-        	else {
-        		// This portion of the code has been removed to ensure that the test case is not automated
-          } */
-
-          if (top.FrameEnabled)	top.fnLog(testResult);
-         /* ]]> */
-        </script>
--->
-    </body>
-</html>
-
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-top-left-radius-009.xht b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-top-left-radius-009.xht
deleted file mode 100644
index a5589fa9..0000000
--- a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-top-left-radius-009.xht
+++ /dev/null
@@ -1,66 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-    <head>
-        <title>CSS Test: Borders. Border-top-left-radius using &quot;inherit&quot;</title>
-        <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
-        <meta http-equiv="Content-Style-Type" content="text/css"/>
-        <meta http-equiv="Content-Script-Type" content="text/javascript"/>
-        <link rel="author" title="Nokia" href="http://www.nokia.com/"/>
-        <link rel="help" href="http://www.w3.org/TR/css3-background/#the-border-radius"/>
-        <link rel="match" href="border-top-left-radius-007.xht" />
-        <meta name="flags" content=""/>
-        <meta name="assert" content="To verify inherit feature works, when it is assigned to border-top-left-radius."/>
-        <style type="text/css">
-        /* <![CDATA[ */
-        	body
-        	{
-        		border-top-left-radius: 20% 25px;
-        	}
-        	div
-          {
-        		border:2px solid #a1a1a1;
-        		background:#dddddd;
-        		width:200px;
-        		height: 100px;
-        		border-top-left-radius: inherit;
-        	}
-        /* ]]> */
-        </style>
-<!--
-        <script type="text/javascript" src="js/css3_test_helper.js"></script>
--->
-    </head>
-    <body>
-		<p>
-			There should be a box with a rounded top left corner.
-		</p>
-		 <!-- PASS AND FAIL CRITERIA ARE IN THE LIST BELOW -->
-        <ul>
-            <li>PASS if only top left corner is rounded.</li>
-            <li>FAIL if the output is not as expected.</li>
-        </ul>
-
-         <!-- PLACE TEST CONTENT FROM HERE -->
-
-    	<div id="test"></div>
-    	<p><br/></p>
-<!--
-    	<script type="text/javascript">
-        /* <![CDATA[ */
-        	var expectedBorderRadius = "20% 25px";
-
-        	var testResult = check_CSS_property("border-top-left-radius", expectedBorderRadius);
-
-        	/* if (testResult.pass)
-        	  // This portion of the code has been removed to ensure that the test case is not automated
-        	else {
-        		// This portion of the code has been removed to ensure that the test case is not automated
-          } */
-
-          if (top.FrameEnabled)	top.fnLog(testResult);
-         /* ]]> */
-        </script>
--->
-    </body>
-</html>
-
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-top-right-radius-003.xht b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-top-right-radius-003.xht
deleted file mode 100644
index 66ac6ca..0000000
--- a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-top-right-radius-003.xht
+++ /dev/null
@@ -1,62 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-    <head>
-        <title>CSS Test: Borders. Border-top-right-radius using two length values: 40px 20px</title>
-        <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
-        <meta http-equiv="Content-Style-Type" content="text/css"/>
-        <meta http-equiv="Content-Script-Type" content="text/javascript"/>
-        <link rel="author" title="Nokia" href="http://www.nokia.com/"/>
-        <link rel="help" href="http://www.w3.org/TR/css3-background/#the-border-radius"/>
-        <link rel="match" href="border-top-right-radius-004.xht" />
-        <meta name="flags" content=""/>
-        <meta name="assert" content="To verify border-top-right-radius property set to two length values, works fine"/>
-        <style type="text/css">
-        /* <![CDATA[ */
-        	div
-          {
-        		border:2px solid #a1a1a1;
-        		background:#dddddd;
-        		width:200px;
-        		height: 100px;
-        		border-top-right-radius: 40px 20px;
-        	}
-         /* ]]> */
-        </style>
-<!--
-        <script type="text/javascript" src="js/css3_test_helper.js"></script>
--->
-    </head>
-    <body>
-		<p>
-			There should be a box with a rounded top right corner.
-		</p>
-		 <!-- PASS AND FAIL CRITERIA ARE IN THE LIST BELOW -->
-        <ul>
-            <li>PASS if only top left corner is rounded.</li>
-            <li>FAIL if the output is not as expected.</li>
-        </ul>
-
-         <!-- PLACE TEST CONTENT FROM HERE -->
-
-    	<div id="test"></div>
-    	<p><br/></p>
-<!--
-    	<script type="text/javascript">
-         /* <![CDATA[ */
-        	var expectedBorderRadius = "40px 20px";
-
-        	var testResult = check_CSS_property("border-top-right-radius", expectedBorderRadius);
-
-        	/* if (testResult.pass)
-        	  // This portion of the code has been removed to ensure that the test case is not automated
-        	else {
-        		// This portion of the code has been removed to ensure that the test case is not automated
-          } */
-
-          if (top.FrameEnabled)	top.fnLog(testResult);
-        /* ]]> */
-        </script>
--->
-    </body>
-</html>
-
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-top-right-radius-004-ref.xht b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-top-right-radius-004-ref.xht
new file mode 100644
index 0000000..ae03151
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-top-right-radius-004-ref.xht
@@ -0,0 +1,22 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <title>border-top-right-radius: 48px 28px reference</title>
+    <style type="text/css">
+      div
+      {
+          width: 200px;
+          height: 100px;
+
+          background: orange;
+          border: 20px solid teal;
+          border-top-right-radius: 48px 28px;
+      }
+    </style>
+  </head>
+  <body>
+    <p>The box should have a border-top-right-radius of 48px 28px. The
+        horizontal radius should therefore be clearly larger than the
+        vertical radius.</p>
+    <div></div>
+  </body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-top-right-radius-004.xht b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-top-right-radius-004.xht
index 35bd619..cbedad8 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-top-right-radius-004.xht
+++ b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-top-right-radius-004.xht
@@ -1,62 +1,24 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 <html xmlns="http://www.w3.org/1999/xhtml">
-    <head>
-        <title>CSS Test: Borders. Border-top-right-radius using one percentage value: 20%</title>
-        <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
-        <meta http-equiv="Content-Style-Type" content="text/css"/>
-        <meta http-equiv="Content-Script-Type" content="text/javascript"/>
-        <link rel="author" title="Nokia" href="http://www.nokia.com/"/>
-        <link rel="help" href="http://www.w3.org/TR/css3-background/#the-border-radius"/>
-        <link rel="match" href="border-top-right-radius-003.xht" />
-        <meta name="flags" content=""/>
-        <meta name="assert" content="To verify border-top-right-radius property set to one percentage value, works fine"/>
-        <style type="text/css">
-        /* <![CDATA[ */
-        	div
-          {
-        		border:2px solid #a1a1a1;
-        		background:#dddddd;
-        		width:200px;
-        		height: 100px;
-        		border-top-right-radius: 20%;
-        	}
-         /* ]]> */
-        </style>
-<!--
-        <script type="text/javascript" src="js/css3_test_helper.js"></script>
--->
-    </head>
-    <body>
-		<p>
-			There should be a box with a rounded top right corner.
-		</p>
-		 <!-- PASS AND FAIL CRITERIA ARE IN THE LIST BELOW -->
-        <ul>
-            <li>PASS if only top left corner is rounded.</li>
-            <li>FAIL if the output is not as expected.</li>
-        </ul>
+  <head>
+    <title>border-top-right-radius using one percentage</title>
+    <link rel="match" href="border-top-right-radius-004-ref.xht" />
+    <link rel="help" href="https://drafts.csswg.org/css-backgrounds/#border-radius" />
+    <style type="text/css">
+      div
+      {
+          width: 200px;
+          height: 100px;
 
-         <!-- PLACE TEST CONTENT FROM HERE -->
-
-    	<div id="test"></div>
-    	<p><br/></p>
-<!--
-    	<script type="text/javascript">
-        /* <![CDATA[ */
-        	var expectedBorderRadius = "20%";
-
-        	var testResult = check_CSS_property("border-top-right-radius", expectedBorderRadius);
-
-        	/* if (testResult.pass)
-        	  // This portion of the code has been removed to ensure that the test case is not automated
-        	else {
-        		// This portion of the code has been removed to ensure that the test case is not automated
-          } */
-
-          if (top.FrameEnabled)	top.fnLog(testResult);
-         /* ]]> */
-        </script>
--->
-    </body>
+          background: orange;
+          border: 20px solid teal;
+          border-top-right-radius: 20%;
+      }
+    </style>
+  </head>
+  <body>
+    <p>The box should have a border-top-right-radius of 48px 28px. The
+        horizontal radius should therefore be clearly larger than the
+        vertical radius.</p>
+    <div></div>
+  </body>
 </html>
-
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-top-right-radius-005-ref.xht b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-top-right-radius-005-ref.xht
new file mode 100644
index 0000000..a3303b72
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-top-right-radius-005-ref.xht
@@ -0,0 +1,22 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <title>border-top-right-radius: 48px 14px reference</title>
+    <style type="text/css">
+      div
+      {
+          width: 200px;
+          height: 100px;
+
+          background: orange;
+          border: 20px solid teal;
+          border-top-right-radius: 48px 14px;
+      }
+    </style>
+  </head>
+  <body>
+    <p>The box should have a border-top-right-radius of 48px 14px. The
+        horizontal radius should therefore be clearly larger than the
+        vertical radius.</p>
+    <div></div>
+  </body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-top-right-radius-005.xht b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-top-right-radius-005.xht
index f44587c..8bd3965 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-top-right-radius-005.xht
+++ b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-top-right-radius-005.xht
@@ -1,62 +1,24 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 <html xmlns="http://www.w3.org/1999/xhtml">
-    <head>
-        <title>CSS Test: Borders. Border-top-right-radius using two percentage values: 20% 30%</title>
-        <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
-        <meta http-equiv="Content-Style-Type" content="text/css"/>
-        <meta http-equiv="Content-Script-Type" content="text/javascript"/>
-        <link rel="author" title="Nokia" href="http://www.nokia.com/"/>
-        <link rel="help" href="http://www.w3.org/TR/css3-background/#the-border-radius"/>
-        <link rel="match" href="border-top-right-radius-006.xht" />
-        <meta name="flags" content=""/>
-        <meta name="assert" content="To verify border-top-right-radius property set to two percentage values, works fine"/>
-        <style type="text/css">
-        /* <![CDATA[ */
-        	div
-          {
-        		border:2px solid #a1a1a1;
-        		background:#dddddd;
-        		width:200px;
-        		height: 100px;
-        		border-top-right-radius: 20% 30%;
-        	}
-        /* ]]> */
-        </style>
-<!--
-        <script type="text/javascript" src="js/css3_test_helper.js"></script>
--->
-    </head>
-    <body>
-		<p>
-			There should be a box with a rounded top right corner.
-		</p>
-		 <!-- PASS AND FAIL CRITERIA ARE IN THE LIST BELOW -->
-        <ul>
-            <li>PASS if only top left corner is rounded.</li>
-            <li>FAIL if the output is not as expected.</li>
-        </ul>
+  <head>
+    <title>border-top-right-radius using two percentages</title>
+    <link rel="match" href="border-top-right-radius-005-ref.xht" />
+    <link rel="help" href="https://drafts.csswg.org/css-backgrounds/#border-radius" />
+    <style type="text/css">
+      div
+      {
+          width: 200px;
+          height: 100px;
 
-         <!-- PLACE TEST CONTENT FROM HERE -->
-
-    	<div id="test"></div>
-    	<p><br/></p>
-<!--
-    	<script type="text/javascript">
-        /* <![CDATA[ */
-        	var expectedBorderRadius = "20% 30%";
-
-        	var testResult = check_CSS_property("border-top-right-radius", expectedBorderRadius);
-
-        	/* if (testResult.pass)
-        	  // This portion of the code has been removed to ensure that the test case is not automated
-        	else {
-        		// This portion of the code has been removed to ensure that the test case is not automated
-          } */
-
-          if (top.FrameEnabled)	top.fnLog(testResult);
-        /* ]]> */
-        </script>
--->
-    </body>
+          background: orange;
+          border: 20px solid teal;
+          border-top-right-radius: 20% 10%;
+      }
+    </style>
+  </head>
+  <body>
+    <p>The box should have a border-top-right-radius of 48px 14px. The
+        horizontal radius should therefore be clearly larger than the
+        vertical radius.</p>
+    <div></div>
+  </body>
 </html>
-
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-top-right-radius-006.xht b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-top-right-radius-006.xht
deleted file mode 100644
index be52dad..0000000
--- a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-top-right-radius-006.xht
+++ /dev/null
@@ -1,62 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-    <head>
-        <title>CSS Test: Borders. Border-top-right-radius using two values: 40px 30%</title>
-        <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
-        <meta http-equiv="Content-Style-Type" content="text/css"/>
-        <meta http-equiv="Content-Script-Type" content="text/javascript"/>
-        <link rel="author" title="Nokia" href="http://www.nokia.com/"/>
-        <link rel="help" href="http://www.w3.org/TR/css3-background/#the-border-radius"/>
-        <link rel="match" href="border-top-right-radius-005.xht" />
-        <meta name="flags" content=""/>
-        <meta name="assert" content="To verify border-top-right-radius property set to two values with different units, works fine"/>
-        <style type="text/css">
-        /* <![CDATA[ */
-        	div
-          {
-        		border:2px solid #a1a1a1;
-        		background:#dddddd;
-        		width:200px;
-        		height: 100px;
-        		border-top-right-radius: 40px 30%;
-        	}
-        /* ]]> */
-        </style>
-<!--
-        <script type="text/javascript" src="js/css3_test_helper.js"></script>
--->
-    </head>
-    <body>
-		<p>
-			There should be a box with a rounded top right corner.
-		</p>
-		 <!-- PASS AND FAIL CRITERIA ARE IN THE LIST BELOW -->
-        <ul>
-            <li>PASS if only top left corner is rounded.</li>
-            <li>FAIL if the output is not as expected.</li>
-        </ul>
-
-         <!-- PLACE TEST CONTENT FROM HERE -->
-
-    	<div id="test"></div>
-    	<p><br/></p>
-<!--
-    	<script type="text/javascript">
-        /* <![CDATA[ */
-        	var expectedBorderRadius = "40px 30%";
-
-        	var testResult = check_CSS_property("border-top-right-radius", expectedBorderRadius);
-
-        	/* if (testResult.pass)
-        	  // This portion of the code has been removed to ensure that the test case is not automated
-        	else {
-        		// This portion of the code has been removed to ensure that the test case is not automated
-          } */
-
-          if (top.FrameEnabled)	top.fnLog(testResult);
-         /* ]]> */
-        </script>
--->
-    </body>
-</html>
-
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-top-right-radius-007.xht b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-top-right-radius-007.xht
deleted file mode 100644
index 5a00a05..0000000
--- a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-top-right-radius-007.xht
+++ /dev/null
@@ -1,62 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-    <head>
-        <title>CSS Test: Borders. Border-top-right-radius using two values: 20% 25px</title>
-        <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
-        <meta http-equiv="Content-Style-Type" content="text/css"/>
-        <meta http-equiv="Content-Script-Type" content="text/javascript"/>
-        <link rel="author" title="Nokia" href="http://www.nokia.com/"/>
-        <link rel="help" href="http://www.w3.org/TR/css3-background/#the-border-radius"/>
-        <link rel="match" href="border-top-right-radius-009.xht" />
-        <meta name="flags" content=""/>
-        <meta name="assert" content="To verify border-top-right-radius property set to two values with different units, works fine"/>
-        <style type="text/css">
-        /* <![CDATA[ */
-        	div
-          {
-        		border:2px solid #a1a1a1;
-        		background:#dddddd;
-        		width:200px;
-        		height: 100px;
-        		border-top-right-radius: 20% 25px;
-        	}
-        /* ]]> */
-        </style>
-<!--
-        <script type="text/javascript" src="js/css3_test_helper.js"></script>
--->
-    </head>
-    <body>
-		<p>
-			There should be a box with a rounded top right corner.
-		</p>
-		 <!-- PASS AND FAIL CRITERIA ARE IN THE LIST BELOW -->
-        <ul>
-            <li>PASS if only top left corner is rounded.</li>
-            <li>FAIL if the output is not as expected.</li>
-        </ul>
-
-         <!-- PLACE TEST CONTENT FROM HERE -->
-
-    	<div id="test"></div>
-    	<p><br/></p>
-<!--
-    	<script type="text/javascript">
-        /* <![CDATA[ */
-        	var expectedBorderRadius = "20% 25px";
-
-        	var testResult = check_CSS_property("border-top-right-radius", expectedBorderRadius);
-
-        	/* if (testResult.pass)
-        	  // This portion of the code has been removed to ensure that the test case is not automated
-        	else {
-        		// This portion of the code has been removed to ensure that the test case is not automated
-          } */
-
-          if (top.FrameEnabled)	top.fnLog(testResult);
-         /* ]]> */
-        </script>
--->
-    </body>
-</html>
-
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-top-right-radius-008.xht b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-top-right-radius-008.xht
deleted file mode 100644
index 0fa67dbc..0000000
--- a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-top-right-radius-008.xht
+++ /dev/null
@@ -1,59 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-    <head>
-        <title>CSS Test: Borders. Border-top-right-radius using two values: 4em 30%</title>
-        <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
-        <meta http-equiv="Content-Style-Type" content="text/css"/>
-        <meta http-equiv="Content-Script-Type" content="text/javascript"/>
-        <link rel="author" title="Nokia" href="http://www.nokia.com/"/>
-        <link rel="help" href="http://www.w3.org/TR/css3-background/#the-border-radius"/>
-        <meta name="flags" content=""/>
-        <meta name="assert" content="To verify border-top-right-radius property set to two values with different units, works fine"/>
-        <style type="text/css">
-        /* <![CDATA[ */
-        	div
-          {
-        		border:2px solid #a1a1a1;
-        		background:#dddddd;
-        		width:200px;
-        		height: 100px;
-        		border-top-right-radius: 4em 30%;
-        	}
-         /* ]]> */
-        </style>
-<!--
-        <script type="text/javascript" src="js/css3_test_helper.js"></script>
--->
-    </head>
-    <body>
-         <p id="testdetails">
-        </p>
-        <p>
-            There should be a box with a rounded top right corner.</p>
-        <ul>
-            <li>PASS if only top right corner is rounded.</li>
-            <li>FAIL if the output is not as expected.</li>
-        </ul>
-
-
-    	<div id="test"></div>
-<!--
-    	<script type="text/javascript">
-        /* <![CDATA[ */
-        	var expectedBorderRadius = "64px 30%";
-
-        	var testResult = check_CSS_property("border-top-right-radius", expectedBorderRadius);
-
-        	/* if (testResult.pass)
-        	  // This portion of the code has been removed to ensure that the test case is not automated
-        	else {
-        		// This portion of the code has been removed to ensure that the test case is not automated
-          } */
-
-          if (top.FrameEnabled)	top.fnLog(testResult);
-         /* ]]> */
-        </script>
--->
-    </body>
-</html>
-
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-top-right-radius-009.xht b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-top-right-radius-009.xht
deleted file mode 100644
index ec954d6..0000000
--- a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-top-right-radius-009.xht
+++ /dev/null
@@ -1,66 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-    <head>
-        <title>CSS Test: Borders. Border-top-right-radius using &quot;inherit&quot;</title>
-        <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
-        <meta http-equiv="Content-Style-Type" content="text/css"/>
-        <meta http-equiv="Content-Script-Type" content="text/javascript"/>
-        <link rel="author" title="Nokia" href="http://www.nokia.com/"/>
-        <link rel="help" href="http://www.w3.org/TR/css3-background/#the-border-radius"/>
-        <link rel="match" href="border-top-right-radius-007.xht" />
-        <meta name="flags" content=""/>
-        <meta name="assert" content="To verify inherit feature works, when it is assigned to border-top-right-radius."/>
-        <style type="text/css">
-        /* <![CDATA[ */
-        	body
-        	{
-        		border-top-right-radius: 20% 25px;
-        	}
-        	div
-          {
-        		border:2px solid #a1a1a1;
-        		background:#dddddd;
-        		width:200px;
-        		height: 100px;
-        		border-top-right-radius: inherit;
-        	}
-         /* ]]> */
-        </style>
-<!--
-        <script type="text/javascript" src="js/css3_test_helper.js"></script>
--->
-    </head>
-    <body>
-		<p>
-			There should be a box with a rounded top right corner.
-		</p>
-		 <!-- PASS AND FAIL CRITERIA ARE IN THE LIST BELOW -->
-        <ul>
-            <li>PASS if only top left corner is rounded.</li>
-            <li>FAIL if the output is not as expected.</li>
-        </ul>
-
-         <!-- PLACE TEST CONTENT FROM HERE -->
-
-    	<div id="test"></div>
-    	<p><br/></p>
-<!--
-    	<script type="text/javascript">
-         /* <![CDATA[ */
-        	var expectedBorderRadius = "20% 25px";
-
-        	var testResult = check_CSS_property("border-top-right-radius", expectedBorderRadius);
-
-        	/* if (testResult.pass)
-        	  // This portion of the code has been removed to ensure that the test case is not automated
-        	else {
-        		// This portion of the code has been removed to ensure that the test case is not automated
-          } */
-
-          if (top.FrameEnabled)	top.fnLog(testResult);
-        /* ]]> */
-        </script>
--->
-    </body>
-</html>
-
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/parsing/border-image-slice-invalid.html b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/parsing/border-image-slice-invalid.html
index c62a43d..6b6e0e9d 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/parsing/border-image-slice-invalid.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/parsing/border-image-slice-invalid.html
@@ -20,6 +20,8 @@
 test_invalid_value("border-image-slice", "1 2 3 4 5");
 
 test_invalid_value("border-image-slice", "1% fill 2%");
+
+test_invalid_value("border-image-slice", "-10");
 </script>
 </body>
 </html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/support/reftest-border-image-5.png b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/support/reftest-border-image-5.png
deleted file mode 100644
index 01087f1..0000000
--- a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/support/reftest-border-image-5.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/external/wpt/css/css-flexbox/flex-wrap-005.html b/third_party/blink/web_tests/external/wpt/css/css-flexbox/flex-wrap-005.html
new file mode 100644
index 0000000..fb897f2
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-flexbox/flex-wrap-005.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<link rel="author" title="Google LLC" href="http://www.google.com" />
+<link rel="help" href="https://drafts.csswg.org/css-flexbox/#cross-sizing" />
+<title>css-flexbox: Tests that we size items in a wrapping column flexbox as fit-content</title>
+<link rel="match" href="../reference/ref-filled-green-100px-square.xht" />
+<meta name="assert" content="The flexbox here should have one flex line, 100px by 100px. The flex items overflow but are transparent." />
+
+<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+
+<!-- This makes sure that we only see green if the flex items are sized correctly -->
+<div style="position: absolute; width: 100px; height: 100px; background: green;"></div>
+
+<div style="display: flex; flex-direction: column; flex-wrap: wrap; width: 200px; height: 100px; line-height: 20px; align-content: flex-start;">
+  <div style="background-color: red; height: 100px; max-width: 50%; align-self: center;">
+    <!-- These zero-height divs give the flex item a min-content width of
+         50px and a max-content width of 250px -->
+    <div style="width: 50px; display: inline-block;"></div>
+    <div style="width: 50px; display: inline-block;"></div>
+    <div style="width: 50px; display: inline-block;"></div>
+    <div style="width: 50px; display: inline-block;"></div>
+    <div style="width: 50px; display: inline-block;"></div>
+  </div>
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-images/multiple-position-color-stop-conic.html b/third_party/blink/web_tests/external/wpt/css/css-images/multiple-position-color-stop-conic.html
index d1608c0c..8a7331d0 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-images/multiple-position-color-stop-conic.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-images/multiple-position-color-stop-conic.html
@@ -2,7 +2,7 @@
 <title>Conic gradient with a two position color stop</title>
 <link rel="help" href="https://drafts.csswg.org/css-images-4/#color-stop-syntax">
 <meta name="assert" content="A color stop with two positions create a hard transition">
-<link rel="match" href="support/100x100-blue-green.html">
+<link rel="match" href="reference/100x100-blue-green.html">
 <style>
 #target {
   width: 100px;
diff --git a/third_party/blink/web_tests/external/wpt/css/css-images/multiple-position-color-stop-linear.html b/third_party/blink/web_tests/external/wpt/css/css-images/multiple-position-color-stop-linear.html
index 2e1f9ed7..c739a2a 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-images/multiple-position-color-stop-linear.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-images/multiple-position-color-stop-linear.html
@@ -2,7 +2,7 @@
 <title>Linear gradient with a two position color stop</title>
 <link rel="help" href="https://drafts.csswg.org/css-images-4/#color-stop-syntax">
 <meta name="assert" content="A color stop with two positions create a hard transition">
-<link rel="match" href="support/100x100-blue-green.html">
+<link rel="match" href="reference/100x100-blue-green.html">
 <style>
 #target {
   width: 100px;
diff --git a/third_party/blink/web_tests/external/wpt/css/css-images/multiple-position-color-stop-radial.html b/third_party/blink/web_tests/external/wpt/css/css-images/multiple-position-color-stop-radial.html
index 74e25df7..4b4fd95 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-images/multiple-position-color-stop-radial.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-images/multiple-position-color-stop-radial.html
@@ -2,7 +2,7 @@
 <title>Radial gradient with a two position color stop</title>
 <link rel="help" href="https://drafts.csswg.org/css-images-4/#color-stop-syntax">
 <meta name="assert" content="A color stop with two positions create a hard transition">
-<link rel="match" href="support/100x100-blue-green.html">
+<link rel="match" href="reference/100x100-blue-green.html">
 <style>
 #target {
   width: 100px;
diff --git a/third_party/blink/web_tests/external/wpt/css/css-images/support/100x100-blue-green.html b/third_party/blink/web_tests/external/wpt/css/css-images/reference/100x100-blue-green.html
similarity index 100%
rename from third_party/blink/web_tests/external/wpt/css/css-images/support/100x100-blue-green.html
rename to third_party/blink/web_tests/external/wpt/css/css-images/reference/100x100-blue-green.html
diff --git a/third_party/blink/web_tests/external/wpt/css/css-namespaces/prefix-001.xml b/third_party/blink/web_tests/external/wpt/css/css-namespaces/prefix-001.xml
index c40bb7f1..eb71713 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-namespaces/prefix-001.xml
+++ b/third_party/blink/web_tests/external/wpt/css/css-namespaces/prefix-001.xml
@@ -3,7 +3,7 @@
   <link rel="author" title="Anne van Kesteren" href="http://annevankesteren.nl/"/>
   <link rel="author" title="Opera Software ASA" href="http://opera.com/"/>
   <link rel="help" href="http://www.w3.org/TR/css-namespaces-3/#prefixes"/>
-  <link rel="match" href="reftest/ref-lime-1.xml"/>
+  <link rel="match" href="reference/ref-lime-1.xml"/>
   <title>CSS Namespaces Test Suite: prefix case-sensitivity</title>
   <style>
    @namespace Foo "y";
diff --git a/third_party/blink/web_tests/external/wpt/css/css-namespaces/prefix-002.xml b/third_party/blink/web_tests/external/wpt/css/css-namespaces/prefix-002.xml
index cc78f3f0..49ca7c0 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-namespaces/prefix-002.xml
+++ b/third_party/blink/web_tests/external/wpt/css/css-namespaces/prefix-002.xml
@@ -3,7 +3,7 @@
   <link rel="author" title="Anne van Kesteren" href="http://annevankesteren.nl/"/>
   <link rel="author" title="Opera Software ASA" href="http://opera.com/"/>
   <link rel="help" href="http://www.w3.org/TR/css-namespaces-3/#prefixes"/>
-  <link rel="match" href="reftest/ref-lime-1.xml"/>
+  <link rel="match" href="reference/ref-lime-1.xml"/>
   <title>CSS Namespaces Test Suite: empty string prefix (Explicit element namespace)</title>
   <style>
    @namespace foo "";
diff --git a/third_party/blink/web_tests/external/wpt/css/css-namespaces/prefix-003.xml b/third_party/blink/web_tests/external/wpt/css/css-namespaces/prefix-003.xml
index 0b6f329..2f23ad4 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-namespaces/prefix-003.xml
+++ b/third_party/blink/web_tests/external/wpt/css/css-namespaces/prefix-003.xml
@@ -3,7 +3,7 @@
   <link rel="author" title="Anne van Kesteren" href="http://annevankesteren.nl/"/>
   <link rel="author" title="Opera Software ASA" href="http://opera.com/"/>
   <link rel="help" href="http://www.w3.org/TR/css-namespaces-3/#prefixes"/>
-  <link rel="match" href="reftest/ref-lime-1-generic.xml"/>
+  <link rel="match" href="reference/ref-lime-1-generic.xml"/>
   <title>CSS Namespaces Test Suite: empty string prefix (Implied element namespace)</title>
   <style>
    @namespace foo "";
diff --git a/third_party/blink/web_tests/external/wpt/css/css-namespaces/prefix-004.xml b/third_party/blink/web_tests/external/wpt/css/css-namespaces/prefix-004.xml
index 70c3bd1ed..596d463 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-namespaces/prefix-004.xml
+++ b/third_party/blink/web_tests/external/wpt/css/css-namespaces/prefix-004.xml
@@ -3,7 +3,7 @@
   <link rel="author" title="Anne van Kesteren" href="http://annevankesteren.nl/"/>
   <link rel="author" title="Opera Software ASA" href="http://opera.com/"/>
   <link rel="help" href="http://www.w3.org/TR/css-namespaces-3/#prefixes"/>
-  <link rel="match" href="reftest/ref-lime-2-generic.xml"/>
+  <link rel="match" href="reference/ref-lime-2-generic.xml"/>
   <title>CSS Namespaces Test Suite: empty string default namespace</title>
   <style>
    @namespace "";
diff --git a/third_party/blink/web_tests/external/wpt/css/css-namespaces/prefix-005.xml b/third_party/blink/web_tests/external/wpt/css/css-namespaces/prefix-005.xml
index 458b5aa3..5f7c3ca 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-namespaces/prefix-005.xml
+++ b/third_party/blink/web_tests/external/wpt/css/css-namespaces/prefix-005.xml
@@ -4,7 +4,7 @@
   <link rel="author" title="Opera Software ASA" href="http://opera.com/"/>
   <link rel="author" title="Boris Zbarsky" href="https://bugzilla.mozilla.org/show_bug.cgi?id=458381#c4"/>
   <link rel="help" href="http://www.w3.org/TR/css-namespaces-3/#prefixes"/>
-  <link rel="match" href="reftest/ref-lime-2-generic.xml"/>
+  <link rel="match" href="reference/ref-lime-2-generic.xml"/>
   <title>CSS Namespaces Test Suite: no default namespace</title>
   <style>
    @namespace x "test";
diff --git a/third_party/blink/web_tests/external/wpt/css/css-namespaces/prefix-006.xml b/third_party/blink/web_tests/external/wpt/css/css-namespaces/prefix-006.xml
index 0bf5991..3cc0ab4 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-namespaces/prefix-006.xml
+++ b/third_party/blink/web_tests/external/wpt/css/css-namespaces/prefix-006.xml
@@ -3,7 +3,7 @@
   <link rel="author" title="Anne van Kesteren" href="http://annevankesteren.nl/"/>
   <link rel="author" title="Opera Software ASA" href="http://opera.com/"/>
   <link rel="help" href="http://www.w3.org/TR/css-namespaces-3/#prefixes"/>
-  <link rel="match" href="reftest/ref-lime-2.xml"/>
+  <link rel="match" href="reference/ref-lime-2.xml"/>
   <title>CSS Namespaces Test Suite: no prefix</title>
   <style>
    @namespace "test";
diff --git a/third_party/blink/web_tests/external/wpt/css/css-namespaces/reftest/ref-lime-1-block.xml b/third_party/blink/web_tests/external/wpt/css/css-namespaces/reference/ref-lime-1-block.xml
similarity index 100%
rename from third_party/blink/web_tests/external/wpt/css/css-namespaces/reftest/ref-lime-1-block.xml
rename to third_party/blink/web_tests/external/wpt/css/css-namespaces/reference/ref-lime-1-block.xml
diff --git a/third_party/blink/web_tests/external/wpt/css/css-namespaces/reftest/ref-lime-1-generic.xml b/third_party/blink/web_tests/external/wpt/css/css-namespaces/reference/ref-lime-1-generic.xml
similarity index 100%
rename from third_party/blink/web_tests/external/wpt/css/css-namespaces/reftest/ref-lime-1-generic.xml
rename to third_party/blink/web_tests/external/wpt/css/css-namespaces/reference/ref-lime-1-generic.xml
diff --git a/third_party/blink/web_tests/external/wpt/css/css-namespaces/reftest/ref-lime-1.xml b/third_party/blink/web_tests/external/wpt/css/css-namespaces/reference/ref-lime-1.xml
similarity index 100%
rename from third_party/blink/web_tests/external/wpt/css/css-namespaces/reftest/ref-lime-1.xml
rename to third_party/blink/web_tests/external/wpt/css/css-namespaces/reference/ref-lime-1.xml
diff --git a/third_party/blink/web_tests/external/wpt/css/css-namespaces/reftest/ref-lime-2-generic.xml b/third_party/blink/web_tests/external/wpt/css/css-namespaces/reference/ref-lime-2-generic.xml
similarity index 100%
rename from third_party/blink/web_tests/external/wpt/css/css-namespaces/reftest/ref-lime-2-generic.xml
rename to third_party/blink/web_tests/external/wpt/css/css-namespaces/reference/ref-lime-2-generic.xml
diff --git a/third_party/blink/web_tests/external/wpt/css/css-namespaces/reftest/ref-lime-2.xml b/third_party/blink/web_tests/external/wpt/css/css-namespaces/reference/ref-lime-2.xml
similarity index 100%
rename from third_party/blink/web_tests/external/wpt/css/css-namespaces/reftest/ref-lime-2.xml
rename to third_party/blink/web_tests/external/wpt/css/css-namespaces/reference/ref-lime-2.xml
diff --git a/third_party/blink/web_tests/external/wpt/css/css-namespaces/reftest/ref-lime-3.xml b/third_party/blink/web_tests/external/wpt/css/css-namespaces/reference/ref-lime-3.xml
similarity index 100%
rename from third_party/blink/web_tests/external/wpt/css/css-namespaces/reftest/ref-lime-3.xml
rename to third_party/blink/web_tests/external/wpt/css/css-namespaces/reference/ref-lime-3.xml
diff --git a/third_party/blink/web_tests/external/wpt/css/css-namespaces/reftest/ref-lime-5.xml b/third_party/blink/web_tests/external/wpt/css/css-namespaces/reference/ref-lime-5.xml
similarity index 100%
rename from third_party/blink/web_tests/external/wpt/css/css-namespaces/reftest/ref-lime-5.xml
rename to third_party/blink/web_tests/external/wpt/css/css-namespaces/reference/ref-lime-5.xml
diff --git a/third_party/blink/web_tests/external/wpt/css/css-namespaces/reftest/ref-lime-6.xml b/third_party/blink/web_tests/external/wpt/css/css-namespaces/reference/ref-lime-6.xml
similarity index 100%
rename from third_party/blink/web_tests/external/wpt/css/css-namespaces/reftest/ref-lime-6.xml
rename to third_party/blink/web_tests/external/wpt/css/css-namespaces/reference/ref-lime-6.xml
diff --git a/third_party/blink/web_tests/external/wpt/css/css-namespaces/scope-001.xml b/third_party/blink/web_tests/external/wpt/css/css-namespaces/scope-001.xml
index bed4171..5271096a9 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-namespaces/scope-001.xml
+++ b/third_party/blink/web_tests/external/wpt/css/css-namespaces/scope-001.xml
@@ -3,7 +3,7 @@
   <link rel="author" title="Anne van Kesteren" href="http://annevankesteren.nl/"/>
   <link rel="author" title="Opera Software ASA" href="http://opera.com/"/>
   <link rel="help" href="http://www.w3.org/TR/css-namespaces-3/#scope"/>
-  <link rel="match" href="reftest/ref-lime-1.xml"/>
+  <link rel="match" href="reference/ref-lime-1.xml"/>
   <meta name="flags" content="invalid"/>
   <title>CSS Namespaces Test Suite: scope &lt;style></title>
   <style>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-namespaces/scope-002.xml b/third_party/blink/web_tests/external/wpt/css/css-namespaces/scope-002.xml
index d25eb81..ff5a2fe 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-namespaces/scope-002.xml
+++ b/third_party/blink/web_tests/external/wpt/css/css-namespaces/scope-002.xml
@@ -3,7 +3,7 @@
   <link rel="author" title="Anne van Kesteren" href="http://annevankesteren.nl/"/>
   <link rel="author" title="Opera Software ASA" href="http://opera.com/"/>
   <link rel="help" href="http://www.w3.org/TR/css-namespaces-3/#scope"/>
-  <link rel="match" href="reftest/ref-lime-1.xml"/>
+  <link rel="match" href="reference/ref-lime-1.xml"/>
   <title>CSS Namespaces Test Suite: scope @import</title>
   <style>
    test { background:lime }
diff --git a/third_party/blink/web_tests/external/wpt/css/css-namespaces/syntax-001.xml b/third_party/blink/web_tests/external/wpt/css/css-namespaces/syntax-001.xml
index 01c57e0..83efb66 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-namespaces/syntax-001.xml
+++ b/third_party/blink/web_tests/external/wpt/css/css-namespaces/syntax-001.xml
@@ -3,7 +3,7 @@
   <link rel="author" title="Anne van Kesteren" href="http://annevankesteren.nl/"/>
   <link rel="author" title="Opera Software ASA" href="http://opera.com/"/>
   <link rel="help" href="http://www.w3.org/TR/css-namespaces-3/#syntax"/>
-  <link rel="match" href="reftest/ref-lime-1-block.xml"/>
+  <link rel="match" href="reference/ref-lime-1-block.xml"/>
   <title>CSS Namespaces Test Suite: @namespace case-insensitivity</title>
   <style>
    @NAmespace x "http://www.w3.org/1999/xhtml";
diff --git a/third_party/blink/web_tests/external/wpt/css/css-namespaces/syntax-002.xml b/third_party/blink/web_tests/external/wpt/css/css-namespaces/syntax-002.xml
index cb04b9c..30fa8aec 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-namespaces/syntax-002.xml
+++ b/third_party/blink/web_tests/external/wpt/css/css-namespaces/syntax-002.xml
@@ -3,7 +3,7 @@
   <link rel="author" title="Anne van Kesteren" href="http://annevankesteren.nl/"/>
   <link rel="author" title="Opera Software ASA" href="http://opera.com/"/>
   <link rel="help" href="http://www.w3.org/TR/css-namespaces-3/#syntax"/>
-  <link rel="match" href="reftest/ref-lime-1-block.xml"/>
+  <link rel="match" href="reference/ref-lime-1-block.xml"/>
   <title>CSS Namespaces Test Suite: @namespace syntax with escapes</title>
   <style>
    @\N\000041 mes\pac\65  x "http://www.w3.org/1999/xhtml";
diff --git a/third_party/blink/web_tests/external/wpt/css/css-namespaces/syntax-003.xml b/third_party/blink/web_tests/external/wpt/css/css-namespaces/syntax-003.xml
index 256286ee..1b2eb5f 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-namespaces/syntax-003.xml
+++ b/third_party/blink/web_tests/external/wpt/css/css-namespaces/syntax-003.xml
@@ -3,7 +3,7 @@
   <link rel="author" title="Anne van Kesteren" href="http://annevankesteren.nl/"/>
   <link rel="author" title="Opera Software ASA" href="http://opera.com/"/>
   <link rel="help" href="http://www.w3.org/TR/css-namespaces-3/#syntax"/>
-  <link rel="match" href="reftest/ref-lime-5.xml"/>
+  <link rel="match" href="reference/ref-lime-5.xml"/>
   <title>CSS Namespaces Test Suite: @namespace default namespace syntax</title>
   <style>
    *|test { background:red }
diff --git a/third_party/blink/web_tests/external/wpt/css/css-namespaces/syntax-004.xml b/third_party/blink/web_tests/external/wpt/css/css-namespaces/syntax-004.xml
index 335bca98..c4ce372 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-namespaces/syntax-004.xml
+++ b/third_party/blink/web_tests/external/wpt/css/css-namespaces/syntax-004.xml
@@ -3,7 +3,7 @@
   <link rel="author" title="Anne van Kesteren" href="http://annevankesteren.nl/"/>
   <link rel="author" title="Opera Software ASA" href="http://opera.com/"/>
   <link rel="help" href="http://www.w3.org/TR/css-namespaces-3/#syntax"/>
-  <link rel="match" href="reftest/ref-lime-1.xml"/>
+  <link rel="match" href="reference/ref-lime-1.xml"/>
   <title>CSS Namespaces Test Suite: @namespace url() with escape</title>
   <style>
    @namespace u\00072l("test");
diff --git a/third_party/blink/web_tests/external/wpt/css/css-namespaces/syntax-005.xml b/third_party/blink/web_tests/external/wpt/css/css-namespaces/syntax-005.xml
index 164bea1..9d6b0ab 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-namespaces/syntax-005.xml
+++ b/third_party/blink/web_tests/external/wpt/css/css-namespaces/syntax-005.xml
@@ -3,7 +3,7 @@
   <link rel="author" title="Anne van Kesteren" href="http://annevankesteren.nl/"/>
   <link rel="author" title="Opera Software ASA" href="http://opera.com/"/>
   <link rel="help" href="http://www.w3.org/TR/css-namespaces-3/#syntax"/>
-  <link rel="match" href="reftest/ref-lime-5.xml"/>
+  <link rel="match" href="reference/ref-lime-5.xml"/>
   <title>CSS Namespaces Test Suite: @namespace string and url() syntax</title>
   <style>
    test { background:red }
diff --git a/third_party/blink/web_tests/external/wpt/css/css-namespaces/syntax-006.xml b/third_party/blink/web_tests/external/wpt/css/css-namespaces/syntax-006.xml
index 1c5975a..09ff0d5 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-namespaces/syntax-006.xml
+++ b/third_party/blink/web_tests/external/wpt/css/css-namespaces/syntax-006.xml
@@ -3,7 +3,7 @@
   <link rel="author" title="Anne van Kesteren" href="http://annevankesteren.nl/"/>
   <link rel="author" title="Opera Software ASA" href="http://opera.com/"/>
   <link rel="help" href="http://www.w3.org/TR/css-namespaces-3/#syntax"/>
-  <link rel="match" href="reftest/ref-lime-1.xml"/>
+  <link rel="match" href="reference/ref-lime-1.xml"/>
   <meta name="flags" content="invalid"/>
   <title>CSS Namespaces Test Suite: invalid ordering of @namespace and @import</title>
   <style>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-namespaces/syntax-007.xml b/third_party/blink/web_tests/external/wpt/css/css-namespaces/syntax-007.xml
index 6022d1c..0c651f1 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-namespaces/syntax-007.xml
+++ b/third_party/blink/web_tests/external/wpt/css/css-namespaces/syntax-007.xml
@@ -3,7 +3,7 @@
   <link rel="author" title="Anne van Kesteren" href="http://annevankesteren.nl/"/>
   <link rel="author" title="Opera Software ASA" href="http://opera.com/"/>
   <link rel="help" href="http://www.w3.org/TR/css-namespaces-3/#syntax"/>
-  <link rel="match" href="reftest/ref-lime-1.xml"/>
+  <link rel="match" href="reference/ref-lime-1.xml"/>
   <title>CSS Namespaces Test Suite: @namespace and @charset</title>
   <link rel="stylesheet" href="support/syntax-007.css"/>
  </head>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-namespaces/syntax-008.xml b/third_party/blink/web_tests/external/wpt/css/css-namespaces/syntax-008.xml
index 4cb4e233..20284e2 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-namespaces/syntax-008.xml
+++ b/third_party/blink/web_tests/external/wpt/css/css-namespaces/syntax-008.xml
@@ -3,7 +3,7 @@
   <link rel="author" title="Anne van Kesteren" href="http://annevankesteren.nl/"/>
   <link rel="author" title="Opera Software ASA" href="http://opera.com/"/>
   <link rel="help" href="http://www.w3.org/TR/css-namespaces-3/#syntax"/>
-  <link rel="match" href="reftest/ref-lime-2.xml"/>
+  <link rel="match" href="reference/ref-lime-2.xml"/>
   <title>CSS Namespaces Test Suite: escapes in prefix</title>
   <style>
    @namespace \72x url("test");
diff --git a/third_party/blink/web_tests/external/wpt/css/css-namespaces/syntax-009.xml b/third_party/blink/web_tests/external/wpt/css/css-namespaces/syntax-009.xml
index 9f69fec..edf2f4c 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-namespaces/syntax-009.xml
+++ b/third_party/blink/web_tests/external/wpt/css/css-namespaces/syntax-009.xml
@@ -3,7 +3,7 @@
   <link rel="author" title="Anne van Kesteren" href="http://annevankesteren.nl/"/>
   <link rel="author" title="Opera Software ASA" href="http://opera.com/"/>
   <link rel="help" href="http://www.w3.org/TR/css-namespaces-3/#syntax"/>
-  <link rel="match" href="reftest/ref-lime-1.xml"/>
+  <link rel="match" href="reference/ref-lime-1.xml"/>
   <title>CSS Namespaces Test Suite: escaped vertical bar in qualified name</title>
   <style>
    @namespace x "test";
diff --git a/third_party/blink/web_tests/external/wpt/css/css-namespaces/syntax-010.xml b/third_party/blink/web_tests/external/wpt/css/css-namespaces/syntax-010.xml
index e175a7b..06b280d 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-namespaces/syntax-010.xml
+++ b/third_party/blink/web_tests/external/wpt/css/css-namespaces/syntax-010.xml
@@ -3,7 +3,7 @@
   <link rel="author" title="Anne van Kesteren" href="http://annevankesteren.nl/"/>
   <link rel="author" title="Opera Software ASA" href="http://opera.com/"/>
   <link rel="help" href="http://www.w3.org/TR/css-namespaces-3/#syntax"/>
-  <link rel="match" href="reftest/ref-lime-3.xml"/>
+  <link rel="match" href="reference/ref-lime-3.xml"/>
   <meta name="flags" content="invalid"/>
   <title>CSS Namespaces Test Suite: duplicate @namespace declarations</title>
   <style>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-namespaces/syntax-011.xml b/third_party/blink/web_tests/external/wpt/css/css-namespaces/syntax-011.xml
index e60cbe1..7d137fc 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-namespaces/syntax-011.xml
+++ b/third_party/blink/web_tests/external/wpt/css/css-namespaces/syntax-011.xml
@@ -3,7 +3,7 @@
   <link rel="author" title="Anne van Kesteren" href="http://annevankesteren.nl/"/>
   <link rel="author" title="Opera Software ASA" href="http://opera.com/"/>
   <link rel="help" href="http://www.w3.org/TR/css-namespaces-3/#syntax"/>
-  <link rel="match" href="reftest/ref-lime-6.xml"/>
+  <link rel="match" href="reference/ref-lime-6.xml"/>
   <title>CSS Namespaces Test Suite: string comparison (no URI resolving)</title>
   <style>
    @namespace url("http://example.com/");
diff --git a/third_party/blink/web_tests/external/wpt/css/css-namespaces/syntax-012.xml b/third_party/blink/web_tests/external/wpt/css/css-namespaces/syntax-012.xml
index 557ba506..43f211b4 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-namespaces/syntax-012.xml
+++ b/third_party/blink/web_tests/external/wpt/css/css-namespaces/syntax-012.xml
@@ -3,7 +3,7 @@
   <link rel="author" title="Anne van Kesteren" href="http://annevankesteren.nl/"/>
   <link rel="author" title="Opera Software ASA" href="http://opera.com/"/>
   <link rel="help" href="http://www.w3.org/TR/css-namespaces-3/#syntax"/>
-  <link rel="match" href="reftest/ref-lime-3.xml"/>
+  <link rel="match" href="reference/ref-lime-3.xml"/>
   <title>CSS Namespaces Test Suite: whitespace and comment handling</title>
   <style>
    test { background:red }
diff --git a/third_party/blink/web_tests/external/wpt/css/css-namespaces/syntax-013.xml b/third_party/blink/web_tests/external/wpt/css/css-namespaces/syntax-013.xml
index 983e2e62d..a7c63e4 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-namespaces/syntax-013.xml
+++ b/third_party/blink/web_tests/external/wpt/css/css-namespaces/syntax-013.xml
@@ -4,7 +4,7 @@
   <link rel="author" title="Opera Software ASA" href="http://opera.com/"/>
   <link rel="author" title="Elika J. Etemad" href="http://fantasai.inkedblade.net/contact"/>
   <link rel="help" href="http://www.w3.org/TR/css-namespaces-3/#syntax"/>
-  <link rel="match" href="reftest/ref-lime-5.xml"/>
+  <link rel="match" href="reference/ref-lime-5.xml"/>
   <meta name="flags" content="invalid"/>
   <title>CSS Namespaces Test Suite: @namespace error handling</title>
   <style>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-namespaces/syntax-014.xml b/third_party/blink/web_tests/external/wpt/css/css-namespaces/syntax-014.xml
index d57d899..1bdfc26 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-namespaces/syntax-014.xml
+++ b/third_party/blink/web_tests/external/wpt/css/css-namespaces/syntax-014.xml
@@ -3,7 +3,7 @@
   <link rel="author" title="Anne van Kesteren" href="http://annevankesteren.nl/"/>
   <link rel="author" title="Opera Software ASA" href="http://opera.com/"/>
   <link rel="help" href="http://www.w3.org/TR/css-namespaces-3/#syntax"/>
-  <link rel="match" href="reftest/ref-lime-3.xml"/>
+  <link rel="match" href="reference/ref-lime-3.xml"/>
   <meta name="flags" content="invalid"/>
   <title>CSS Namespaces Test Suite: @namespace and invalid at-rules</title>
   <style>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-namespaces/syntax-015.xml b/third_party/blink/web_tests/external/wpt/css/css-namespaces/syntax-015.xml
index 4460ddf..d39eb8b 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-namespaces/syntax-015.xml
+++ b/third_party/blink/web_tests/external/wpt/css/css-namespaces/syntax-015.xml
@@ -3,7 +3,7 @@
   <link rel="author" title="Anne van Kesteren" href="http://annevankesteren.nl/"/>
   <link rel="author" title="Opera Software ASA" href="http://opera.com/"/>
   <link rel="help" href="http://www.w3.org/TR/css-namespaces-3/#syntax"/>
-  <link rel="match" href="reftest/ref-lime-1.xml"/>
+  <link rel="match" href="reference/ref-lime-1.xml"/>
   <title>CSS Namespaces Test Suite: invalid URI</title>
   <style>
    @namespace x url("test");
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/reftest/transform-3d-rotateY-stair-above-ref-001.xht b/third_party/blink/web_tests/external/wpt/css/css-transforms/reference/transform-3d-rotateY-stair-above-ref-001.xht
similarity index 100%
rename from third_party/blink/web_tests/external/wpt/css/css-transforms/reftest/transform-3d-rotateY-stair-above-ref-001.xht
rename to third_party/blink/web_tests/external/wpt/css/css-transforms/reference/transform-3d-rotateY-stair-above-ref-001.xht
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/reftest/transform-applies-to-001-ref.xht b/third_party/blink/web_tests/external/wpt/css/css-transforms/reference/transform-applies-to-001-ref.xht
similarity index 100%
rename from third_party/blink/web_tests/external/wpt/css/css-transforms/reftest/transform-applies-to-001-ref.xht
rename to third_party/blink/web_tests/external/wpt/css/css-transforms/reference/transform-applies-to-001-ref.xht
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/reftest/transform-applies-to-002-ref.xht b/third_party/blink/web_tests/external/wpt/css/css-transforms/reference/transform-applies-to-002-ref.xht
similarity index 100%
rename from third_party/blink/web_tests/external/wpt/css/css-transforms/reftest/transform-applies-to-002-ref.xht
rename to third_party/blink/web_tests/external/wpt/css/css-transforms/reference/transform-applies-to-002-ref.xht
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/reftest/transform-origin-01-ref.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/reference/transform-origin-01-ref.html
similarity index 100%
rename from third_party/blink/web_tests/external/wpt/css/css-transforms/reftest/transform-origin-01-ref.html
rename to third_party/blink/web_tests/external/wpt/css/css-transforms/reference/transform-origin-01-ref.html
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-3d-rotateY-stair-above-001.xht b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-3d-rotateY-stair-above-001.xht
index 41d8979..9a3aac8 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-3d-rotateY-stair-above-001.xht
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-3d-rotateY-stair-above-001.xht
@@ -4,7 +4,7 @@
   <title>CSS Test: rotateY with perspective produces a trapezoid</title>
   <link rel="author" title="Apple Inc." href="http://www.apple.com/"/>
   <link rel="help" href="http://www.w3.org/TR/css-transforms-2/#3d-transform-rendering"/>
-  <link rel="match" href="reftest/transform-3d-rotateY-stair-above-ref-001.xht"/>
+  <link rel="match" href="reference/transform-3d-rotateY-stair-above-ref-001.xht"/>
   <meta name="flags" content="" />
   <meta name="assert" content="A rotateY transform with perspective
   should result in a trapezoid."/>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-3d-rotateY-stair-below-001.xht b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-3d-rotateY-stair-below-001.xht
index 5a1c1d4..5224da27 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-3d-rotateY-stair-below-001.xht
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-3d-rotateY-stair-below-001.xht
@@ -4,7 +4,7 @@
   <title>CSS Test: rotateY with perspective produces a trapezoid</title>
   <link rel="author" title="Apple Inc." href="http://www.apple.com/"/>
   <link rel="help" href="http://www.w3.org/TR/css-transforms-2/#3d-transform-rendering"/>
-  <link rel="match" href="reftest/transform-3d-rotateY-stair-above-ref-001.xht"/>
+  <link rel="match" href="reference/transform-3d-rotateY-stair-above-ref-001.xht"/>
   <meta name="flags" content="" />
   <meta name="assert" content="A rotateY transform with perspective
   should result in a trapezoid."/>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-applies-to-001.xht b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-applies-to-001.xht
index 0036e8e1..09bb196d 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-applies-to-001.xht
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-applies-to-001.xht
@@ -4,7 +4,7 @@
   <title>CSS Test: transform applied to elements with 'display' set to 'block'</title>
   <link rel="author" title="Apple Inc." href="http://www.apple.com/"/>
   <link rel="help" href="http://www.w3.org/TR/css-transforms-1/#transform-property"/>
-  <link rel="match" href="reftest/transform-applies-to-001-ref.xht"/>
+  <link rel="match" href="reference/transform-applies-to-001-ref.xht"/>
   <meta name="flags" content="" />
   <meta name="assert" content="The 'transform' property applies to elements with 'display' set to 'block'."/>
   <style type="text/css"><![CDATA[
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-applies-to-002.xht b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-applies-to-002.xht
index 80715d3..186d0b7 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-applies-to-002.xht
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-applies-to-002.xht
@@ -4,7 +4,7 @@
   <title>CSS Test: Transform does not apply to non-replaced inline elements</title>
   <link rel="author" title="Apple Inc." href="http://www.apple.com/"/>
   <link rel="help" href="http://www.w3.org/TR/css-transforms-1/#transform-property"/>
-  <link rel="match" href="reftest/transform-applies-to-002-ref.xht"/>
+  <link rel="match" href="reference/transform-applies-to-002-ref.xht"/>
   <meta name="flags" content="ahem" />
   <meta name="assert" content="The 'transform' property does not apply to non-replaced inline elements."/>
   <style type="text/css"><![CDATA[
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-box/fill-box-mutation.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-box/fill-box-mutation.html
index ae602e35..1f0dfd01 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-box/fill-box-mutation.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-box/fill-box-mutation.html
@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <html class="reftest-wait">
 <title>transform-box: fill-box, shape mutated</title>
-<link rel="match" href="support/greensquare200x200.html">
+<link rel="match" href="reference/greensquare200x200.html">
 <link rel="help" href="https://drafts.csswg.org/css-transforms/#transform-box">
 <style>
 #target {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-box/fill-box.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-box/fill-box.html
index eaea02a..7e9b133a 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-box/fill-box.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-box/fill-box.html
@@ -1,6 +1,6 @@
 <!DOCTYPE html>
 <title>transform-box: fill-box</title>
-<link rel="match" href="support/greensquare200x200.html">
+<link rel="match" href="reference/greensquare200x200.html">
 <link rel="help" href="https://drafts.csswg.org/css-transforms/#transform-box">
 <style>
 svg {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-box/support/greensquare200x200.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-box/reference/greensquare200x200.html
similarity index 100%
rename from third_party/blink/web_tests/external/wpt/css/css-transforms/transform-box/support/greensquare200x200.html
rename to third_party/blink/web_tests/external/wpt/css/css-transforms/transform-box/reference/greensquare200x200.html
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-box/value-changed.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-box/value-changed.html
index 825403ef..4aca90a6 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-box/value-changed.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-box/value-changed.html
@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <html class="reftest-wait">
 <title>transform-box: value change from 'view-box' to 'fill-box'</title>
-<link rel="match" href="support/greensquare200x200.html">
+<link rel="match" href="reference/greensquare200x200.html">
 <link rel="help" href="https://drafts.csswg.org/css-transforms/#transform-box">
 <p>There should be a green 200x200 rectangle below, and no red.</p>
 <svg width="400" height="200">
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-box/view-box-mutation.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-box/view-box-mutation.html
index 0d4a0ec..d0c85fd5 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-box/view-box-mutation.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-box/view-box-mutation.html
@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <html class="reftest-wait">
 <title>transform-box: view-box, viewport mutated</title>
-<link rel="match" href="support/greensquare200x200.html">
+<link rel="match" href="reference/greensquare200x200.html">
 <link rel="help" href="https://drafts.csswg.org/css-transforms/#transform-box">
 <style>
 #target {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-box/view-box-nested.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-box/view-box-nested.html
index 7f59777..9e7fc17 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-box/view-box-nested.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-box/view-box-nested.html
@@ -1,6 +1,6 @@
 <!DOCTYPE html>
 <title>transform-box: view-box, relative to nested viewport</title>
-<link rel="match" href="support/greensquare200x200.html">
+<link rel="match" href="reference/greensquare200x200.html">
 <link rel="help" href="https://drafts.csswg.org/css-transforms/#transform-box">
 <style>
 #target {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-box/view-box-viewbox-nested.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-box/view-box-viewbox-nested.html
index 4f667e2..fc072363 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-box/view-box-viewbox-nested.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-box/view-box-viewbox-nested.html
@@ -1,6 +1,6 @@
 <!DOCTYPE html>
 <title>transform-box: view-box, relative to viewport defined by nested viewBox</title>
-<link rel="match" href="support/greensquare200x200.html">
+<link rel="match" href="reference/greensquare200x200.html">
 <link rel="help" href="https://drafts.csswg.org/css-transforms/#transform-box">
 <style>
 #target {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-box/view-box-viewbox.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-box/view-box-viewbox.html
index cd040c1..a69d809 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-box/view-box-viewbox.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-box/view-box-viewbox.html
@@ -1,6 +1,6 @@
 <!DOCTYPE html>
 <title>transform-box: view-box, relative to viewport defined by viewBox</title>
-<link rel="match" href="support/greensquare200x200.html">
+<link rel="match" href="reference/greensquare200x200.html">
 <link rel="help" href="https://drafts.csswg.org/css-transforms/#transform-box">
 <style>
 #target {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-box/view-box.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-box/view-box.html
index 3345467..0b5eeda5 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-box/view-box.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-box/view-box.html
@@ -1,6 +1,6 @@
 <!DOCTYPE html>
 <title>transform-box: view-box</title>
-<link rel="match" href="support/greensquare200x200.html">
+<link rel="match" href="reference/greensquare200x200.html">
 <link rel="help" href="https://drafts.csswg.org/css-transforms/#transform-box">
 <style>
 svg {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin-01.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin-01.html
index c1b6f29..d7e1cd3 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin-01.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin-01.html
@@ -4,7 +4,7 @@
     <title>CSS Test: SVG Transform using transform-origin</title>
     <link rel="author" title="CJ Gammon" href="mailto:gammon@adobe.com">
     <link rel="help" href="http://www.w3.org/TR/css-transforms-1/#transform-origin-property">
-    <link rel="match" href="reftest/transform-origin-01-ref.html">
+    <link rel="match" href="reference/transform-origin-01-ref.html">
     <meta name="assert" content="If only one value is specified, the second value is assumed to be 'center'">
     <style type="text/css">
         #container{
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform3d-perspective-origin-001.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform3d-perspective-origin-001.html
index 1a81bc1..791d4bd 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform3d-perspective-origin-001.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform3d-perspective-origin-001.html
@@ -9,9 +9,6 @@
     the same as 'perspective-origin: top left', different from no
     'perspective-origin', and different from no perspective or no transform.">
     <link rel="match" href="transform3d-perspective-origin-ref.html">
-    <link rel="mismatch" href="transform3d-rotatex-perspective-001.html">
-    <link rel="mismatch" href="transform3d-rotatex-ref.html">
-    <link rel="mismatch" href="transform-lime-square-ref.html">
   </head>
   <body>
     <div style="perspective: 1000px; perspective-origin: 0 0;">
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform3d-perspective-origin-ref.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform3d-perspective-origin-ref.html
index dd0026b..e174d75 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform3d-perspective-origin-ref.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform3d-perspective-origin-ref.html
@@ -4,6 +4,7 @@
     <title>CSS Reftest Reference</title>
     <link rel="author" title="Matt Woodrow" href="mailto:mwoodrow@mozilla.com">
     <link rel="author" title="Aryeh Gregor" href="mailto:ayg@aryeh.name">
+    <link rel="mismatch" href="transform3d-rotatex-ref.html">
   </head>
   <body>
     <div style="perspective: 1000px; perspective-origin: top left;">
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform3d-rotate3d-001.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform3d-rotate3d-001.html
index 185346c3..93a46f1c 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform3d-rotate3d-001.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform3d-rotate3d-001.html
@@ -9,7 +9,6 @@
     <meta name="assert" content="This tests that rotate3d(1, 0, 0, 45deg) is
     the same as rotatex(45deg).">
     <link rel="match" href="transform3d-rotatex-ref.html">
-    <link rel="mismatch" href="transform-lime-square-ref.html">
   </head>
   <body>
     <div style="transform: rotate3d(1, 0, 0, 45deg); width: 100px;
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform3d-rotatex-001.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform3d-rotatex-001.html
index 47ad10b..2f75f15 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform3d-rotatex-001.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform3d-rotatex-001.html
@@ -10,7 +10,6 @@
     <meta name="assert" content="This tests that rotatex(45deg) rotatey(360deg)
     rotatex(360deg) is the same as rotatex(45deg).">
     <link rel="match" href="transform3d-rotatex-ref.html">
-    <link rel="mismatch" href="transform-lime-square-ref.html">
   </head>
   <body>
     <div style="transform: rotatex(45deg) rotatey(360deg) rotatex(360deg);
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform3d-rotatex-perspective-002.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform3d-rotatex-perspective-002.html
index 472d0aa..ecf6a2f 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform3d-rotatex-perspective-002.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform3d-rotatex-perspective-002.html
@@ -11,7 +11,6 @@
     when combined with rotatex() (i.e., is not equivalent to simply omitting
     the perspective).">
     <link rel="mismatch" href="transform3d-rotatex-ref.html">
-    <link rel="mismatch" href="transform-lime-square-ref.html">
   </head>
   <body>
     <div style="perspective: 1000px;">
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/reftest/writing-mode-vertical-lr-002-ref.xht b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/reference/writing-mode-vertical-lr-002-ref.xht
similarity index 100%
rename from third_party/blink/web_tests/external/wpt/css/css-writing-modes/reftest/writing-mode-vertical-lr-002-ref.xht
rename to third_party/blink/web_tests/external/wpt/css/css-writing-modes/reference/writing-mode-vertical-lr-002-ref.xht
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/reftest/writing-mode-vertical-rl-001-ref.xht b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/reference/writing-mode-vertical-rl-001-ref.xht
similarity index 100%
rename from third_party/blink/web_tests/external/wpt/css/css-writing-modes/reftest/writing-mode-vertical-rl-001-ref.xht
rename to third_party/blink/web_tests/external/wpt/css/css-writing-modes/reference/writing-mode-vertical-rl-001-ref.xht
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/reftest/writing-mode-vertical-rl-002-ref.xht b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/reference/writing-mode-vertical-rl-002-ref.xht
similarity index 100%
rename from third_party/blink/web_tests/external/wpt/css/css-writing-modes/reftest/writing-mode-vertical-rl-002-ref.xht
rename to third_party/blink/web_tests/external/wpt/css/css-writing-modes/reference/writing-mode-vertical-rl-002-ref.xht
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vertical-lr-002.xht b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vertical-lr-002.xht
index 8086296..291dff96 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vertical-lr-002.xht
+++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vertical-lr-002.xht
@@ -6,7 +6,7 @@
     <link rel="author" title="Yoshifumi Kawai" href="mailto:kawai@est.co.jp" />
     <link rel="reviewer" title="Elika J. Etemad" href="http://fantasai.inkedblade.net/contact"/>
     <link rel="help" title="CSS3 Writing modes: 3.1. Block Flow Direction: the 'writing-mode' property" href="http://www.w3.org/TR/css-writing-modes-3/#propdef-writing-mode" />
-    <link rel="match" href="reftest/writing-mode-vertical-lr-002-ref.xht"/>
+    <link rel="match" href="reference/writing-mode-vertical-lr-002-ref.xht"/>
     <meta name="flags" content="ahem" />
     <meta content="This tests the block flow direction. The writing mode is vertical, and the block flow is left to right." />
     <style type="text/css"><![CDATA[
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vertical-rl-001.xht b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vertical-rl-001.xht
index 0a7839c..5a5c7bf2 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vertical-rl-001.xht
+++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vertical-rl-001.xht
@@ -6,7 +6,7 @@
     <link rel="author" title="Yoshifumi Kawai" href="mailto:kawai@est.co.jp" />
     <link rel="reviewer" title="Elika J. Etemad" href="http://fantasai.inkedblade.net/contact"/>
     <link rel="help" title="CSS3 Writing modes: 3.1. Block Flow Direction: the 'writing-mode' property" href="http://www.w3.org/TR/css-writing-modes-3/#propdef-writing-mode" />
-    <link rel="match" href="reftest/writing-mode-vertical-rl-001-ref.xht"/>
+    <link rel="match" href="reference/writing-mode-vertical-rl-001-ref.xht"/>
     <meta name="flags" content="ahem" />
     <meta content="This tests the block flow direction. The writing mode is vertical, and the block flow is right to left." />
     <style type="text/css"><![CDATA[
diff --git a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vertical-rl-002.xht b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vertical-rl-002.xht
index f2d3ab0..ac77d43 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vertical-rl-002.xht
+++ b/third_party/blink/web_tests/external/wpt/css/css-writing-modes/writing-mode-vertical-rl-002.xht
@@ -6,7 +6,7 @@
     <link rel="author" title="Yoshifumi Kawai" href="mailto:kawai@est.co.jp" />
     <link rel="reviewer" title="Elika J. Etemad" href="http://fantasai.inkedblade.net/contact"/>
     <link rel="help" title="CSS3 Writing modes: 3.1. Block Flow Direction: the 'writing-mode' property" href="http://www.w3.org/TR/css-writing-modes-3/#propdef-writing-mode" />
-    <link rel="match" href="reftest/writing-mode-vertical-rl-002-ref.xht"/>
+    <link rel="match" href="reference/writing-mode-vertical-rl-002-ref.xht"/>
     <meta name="flags" content="ahem" />
     <meta content="This tests the block flow direction. The writing mode is vertical, and the block flow is right to left." />
     <style type="text/css"><![CDATA[
diff --git a/third_party/blink/web_tests/external/wpt/svg/embedded/image-embedding-svg-with-viewport-units-inline-style.svg b/third_party/blink/web_tests/external/wpt/svg/embedded/image-embedding-svg-with-viewport-units-inline-style.svg
index 7880fcf..7ef2655 100644
--- a/third_party/blink/web_tests/external/wpt/svg/embedded/image-embedding-svg-with-viewport-units-inline-style.svg
+++ b/third_party/blink/web_tests/external/wpt/svg/embedded/image-embedding-svg-with-viewport-units-inline-style.svg
@@ -3,7 +3,7 @@
      xmlns:h="http://www.w3.org/1999/xhtml">
   <metadata>
     <title>&lt;image&gt; embedding SVG image with viewport units</title>
-    <h:link rel="match" href="support/green-rect-100x100.svg"/>
+    <h:link rel="match" href="reference/green-rect-100x100.svg"/>
   </metadata>
   <image xlink:href="data:image/svg+xml,&lt;svg xmlns='http://www.w3.org/2000/svg'&gt;&lt;rect style='width: 50vw; height: 50vh' fill='green'/&gt;&lt;/svg&gt;"
          width="200" height="200"/>
diff --git a/third_party/blink/web_tests/external/wpt/svg/embedded/image-embedding-svg-with-viewport-units.svg b/third_party/blink/web_tests/external/wpt/svg/embedded/image-embedding-svg-with-viewport-units.svg
index 6feb54b..653856d 100644
--- a/third_party/blink/web_tests/external/wpt/svg/embedded/image-embedding-svg-with-viewport-units.svg
+++ b/third_party/blink/web_tests/external/wpt/svg/embedded/image-embedding-svg-with-viewport-units.svg
@@ -3,7 +3,7 @@
      xmlns:h="http://www.w3.org/1999/xhtml">
   <metadata>
     <title>&lt;image&gt; embedding SVG image with viewport units</title>
-    <h:link rel="match" href="support/green-rect-100x100.svg"/>
+    <h:link rel="match" href="reference/green-rect-100x100.svg"/>
   </metadata>
   <image xlink:href="data:image/svg+xml,&lt;svg xmlns='http://www.w3.org/2000/svg'&gt;&lt;rect width='50vw' height='50vh' fill='green'/&gt;&lt;/svg&gt;"
          width="200" height="200"/>
diff --git a/third_party/blink/web_tests/external/wpt/svg/embedded/support/green-rect-100x100.svg b/third_party/blink/web_tests/external/wpt/svg/embedded/reference/green-rect-100x100.svg
similarity index 100%
rename from third_party/blink/web_tests/external/wpt/svg/embedded/support/green-rect-100x100.svg
rename to third_party/blink/web_tests/external/wpt/svg/embedded/reference/green-rect-100x100.svg
diff --git a/third_party/blink/web_tests/external/wpt/svg/shapes/reftests/disabled-shapes-01.svg b/third_party/blink/web_tests/external/wpt/svg/shapes/reftests/disabled-shapes-01.svg
index d92eea1..3091ca7b 100644
--- a/third_party/blink/web_tests/external/wpt/svg/shapes/reftests/disabled-shapes-01.svg
+++ b/third_party/blink/web_tests/external/wpt/svg/shapes/reftests/disabled-shapes-01.svg
@@ -4,7 +4,7 @@
     <h:link rel="help" href="https://svgwg.org/svg2-draft/shapes.html#RectElement"/>
     <h:link rel="help" href="https://svgwg.org/svg2-draft/shapes.html#CircleElement"/>
     <h:link rel="help" href="https://svgwg.org/svg2-draft/shapes.html#EllipseElement"/>
-    <h:link rel="match" href="support/empty.svg"/>
+    <h:link rel="match" href="reference/empty.svg"/>
   </metadata>
   <g stroke="red" stroke-width="100">
     <g transform="translate(50, 50)">
diff --git a/third_party/blink/web_tests/external/wpt/svg/shapes/reftests/support/empty.svg b/third_party/blink/web_tests/external/wpt/svg/shapes/reftests/reference/empty.svg
similarity index 100%
rename from third_party/blink/web_tests/external/wpt/svg/shapes/reftests/support/empty.svg
rename to third_party/blink/web_tests/external/wpt/svg/shapes/reftests/reference/empty.svg
diff --git a/third_party/blink/web_tests/external/wpt/wasm/jsapi/module/customSections.any-expected.txt b/third_party/blink/web_tests/external/wpt/wasm/jsapi/module/customSections.any-expected.txt
index 10bee6b..e69de29 100644
--- a/third_party/blink/web_tests/external/wpt/wasm/jsapi/module/customSections.any-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/wasm/jsapi/module/customSections.any-expected.txt
@@ -1,12 +0,0 @@
-This is a testharness.js-based test.
-PASS Missing arguments
-PASS Non-Module arguments
-PASS Branding
-PASS Empty module
-PASS Empty module: array caching
-PASS Custom sections
-PASS Custom sections with surrogate pairs
-FAIL Custom sections with U+FFFD assert_equals: expected 1 but got 0
-PASS Stray argument
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/wasm/jsapi/module/customSections.any.worker-expected.txt b/third_party/blink/web_tests/external/wpt/wasm/jsapi/module/customSections.any.worker-expected.txt
index 10bee6b..e69de29 100644
--- a/third_party/blink/web_tests/external/wpt/wasm/jsapi/module/customSections.any.worker-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/wasm/jsapi/module/customSections.any.worker-expected.txt
@@ -1,12 +0,0 @@
-This is a testharness.js-based test.
-PASS Missing arguments
-PASS Non-Module arguments
-PASS Branding
-PASS Empty module
-PASS Empty module: array caching
-PASS Custom sections
-PASS Custom sections with surrogate pairs
-FAIL Custom sections with U+FFFD assert_equals: expected 1 but got 0
-PASS Stray argument
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/fast/scrolling/events/overscroll-event-fired-to-document.html b/third_party/blink/web_tests/fast/scrolling/events/overscroll-event-fired-to-document.html
index 5728c26..3f7d8fc 100644
--- a/third_party/blink/web_tests/fast/scrolling/events/overscroll-event-fired-to-document.html
+++ b/third_party/blink/web_tests/fast/scrolling/events/overscroll-event-fired-to-document.html
@@ -42,7 +42,8 @@
 var overscrolled_y_delta = 0;
 function onOverscroll(event) {
   assert_false(event.cancelable);
-  assert_false(event.bubbles);
+  // overscroll events are bubbled when the target node is document.
+  assert_true(event.bubbles);
   overscrolled_x_delta = event.deltaX;
   overscrolled_y_delta = event.deltaY;
 }
diff --git a/third_party/blink/web_tests/fast/scrolling/events/overscroll-event-fired-to-window.html b/third_party/blink/web_tests/fast/scrolling/events/overscroll-event-fired-to-window.html
new file mode 100644
index 0000000..c0da609
--- /dev/null
+++ b/third_party/blink/web_tests/fast/scrolling/events/overscroll-event-fired-to-window.html
@@ -0,0 +1,59 @@
+<!DOCTYPE HTML>
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
+<script src="../../../resources/gesture-util.js"></script>
+<style>
+#targetDiv {
+  width: 200px;
+  height: 200px;
+  overflow: scroll;
+}
+
+#innerDiv {
+  width: 400px;
+  height: 400px;
+}
+</style>
+
+<body style="margin:0">
+<div id="targetDiv">
+  <div id="innerDiv">
+  </div>
+</div>
+</body>
+
+<script>
+if (window.internals)
+  internals.runtimeFlags.overscrollCustomizationEnabled = true;
+
+var target_div = document.getElementById('targetDiv');
+var rect = target_div.getBoundingClientRect();
+var x = rect.left + rect.width / 2;
+var y = rect.top + rect.height / 2;
+
+function scrollUp() {
+  return smoothScroll(1000, x, y, GestureSourceType.TOUCH_INPUT, "up");
+}
+
+var window_received_autoscroll = false;
+function onOverscroll(event) {
+  assert_false(event.cancelable);
+  // overscroll events targetting document are bubbled to the window.
+  assert_true(event.bubbles);
+  window_received_autoscroll = true;
+}
+window.addEventListener("overscroll", onOverscroll);
+
+promise_test (async (t) => {
+  // Make sure that no overscroll event is sent to target_div.
+  target_div.addEventListener("overscroll",
+      t.unreached_func("target_div got unexpected overscroll event."));
+
+  await waitForCompositorCommit();
+
+  // Scroll up on target div and wait for the window to get overscroll event.
+  await scrollUp();
+  await waitFor(() => { return window_received_autoscroll; },
+      'Window did not receive overscroll event after scroll up on target.');
+}, 'Tests that the window gets overscroll event when no element scrolls.');
+</script>
diff --git a/third_party/blink/web_tests/fast/scrolling/events/scrollend-event-fired-to-document.html b/third_party/blink/web_tests/fast/scrolling/events/scrollend-event-fired-to-document.html
index 7e7ea2a8..09d47a8 100644
--- a/third_party/blink/web_tests/fast/scrolling/events/scrollend-event-fired-to-document.html
+++ b/third_party/blink/web_tests/fast/scrolling/events/scrollend-event-fired-to-document.html
@@ -44,12 +44,14 @@
 var vertical_scrollend_arrived = false;
 function onHorizontalScrollEnd(event) {
   assert_false(event.cancelable);
-  assert_false(event.bubbles);
+  // scrollend events are bubbled when the target node is document.
+  assert_true(event.bubbles);
   horizontal_scrollend_arrived = true;
 }
 function onVerticalScrollEnd(event) {
   assert_false(event.cancelable);
-  assert_false(event.bubbles);
+  // scrollend events are bubbled when the target node is document.
+  assert_true(event.bubbles);
   vertical_scrollend_arrived = true;
 }
 document.addEventListener("scrollend", onHorizontalScrollEnd);
diff --git a/third_party/blink/web_tests/fast/scrolling/events/scrollend-event-fired-to-window.html b/third_party/blink/web_tests/fast/scrolling/events/scrollend-event-fired-to-window.html
new file mode 100644
index 0000000..4b01c4e6
--- /dev/null
+++ b/third_party/blink/web_tests/fast/scrolling/events/scrollend-event-fired-to-window.html
@@ -0,0 +1,61 @@
+<!DOCTYPE HTML>
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
+<script src="../../../resources/gesture-util.js"></script>
+<style>
+#targetDiv {
+  width: 200px;
+  height: 200px;
+  overflow: scroll;
+}
+
+#innerDiv {
+  width: 400px;
+  height: 400px;
+}
+</style>
+
+<body style="margin:0">
+<div id="targetDiv">
+  <div id="innerDiv">
+  </div>
+</div>
+</body>
+
+<script>
+if (window.internals)
+  internals.runtimeFlags.overscrollCustomizationEnabled = true;
+
+var target_div = document.getElementById('targetDiv');
+var rect = target_div.getBoundingClientRect();
+var x = rect.left + rect.width / 2;
+var y = rect.top + rect.height / 2;
+
+function scrollUp() {
+  return smoothScroll(1000, x, y, GestureSourceType.TOUCH_INPUT, "up",
+      SPEED_INSTANT);
+}
+
+var scrollend_arrived = false;
+function onScrollEnd(event) {
+  assert_false(event.cancelable);
+  // scrollend events targetting document are bubbled to the window.
+  assert_true(event.bubbles);
+  scrollend_arrived = true;
+}
+window.addEventListener("scrollend", onScrollEnd);
+
+promise_test (async (t) => {
+  // Make sure that no scrollend event is sent to target_div.
+  target_div.addEventListener("scrollend",
+      t.unreached_func("target_div got unexpected scrollend event."));
+
+  await waitForCompositorCommit();
+
+  // Scroll up on target div and wait for the doc to get scrollend event.
+  await scrollUp();
+  await waitFor(() => { return scrollend_arrived; },
+      'Window did not receive scrollend event after scroll up on target.');
+  assert_equals(target_div.scrollTop, 0);
+}, 'Tests that the window gets scrollend event when no element scrolls.');
+</script>
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/repaint-across-writing-mode-boundary-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/repaint-across-writing-mode-boundary-expected.txt
index a1eb1dc..6cf00f0 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/repaint-across-writing-mode-boundary-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/repaint-across-writing-mode-boundary-expected.txt
@@ -19,7 +19,7 @@
       "paintInvalidations": [
         {
           "object": "NGPhysicalTextFragment '\u7B2C\u4E00\u6BB5\u843D paragraph 1'",
-          "rect": [548, 80, 24, 182],
+          "rect": [549, 191, 21, 36],
           "reason": "selection"
         }
       ]
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/selection/selection-clear-after-move-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/selection/selection-clear-after-move-expected.txt
new file mode 100644
index 0000000..48a2a87
--- /dev/null
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/selection/selection-clear-after-move-expected.txt
@@ -0,0 +1,29 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "drawsContent": false,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutImage IMG",
+          "rect": [100, 300, 50, 51],
+          "reason": "selection"
+        }
+      ]
+    }
+  ]
+}
+
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/selection/selection-in-composited-scrolling-container-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/selection/selection-in-composited-scrolling-container-expected.txt
index 334b04e..09a0829d 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/selection/selection-in-composited-scrolling-container-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/selection/selection-in-composited-scrolling-container-expected.txt
@@ -28,14 +28,14 @@
           "reason": "paint property change"
         },
         {
-          "object": "InlineTextBox 'test test test'",
-          "rect": [10, 11, 56, 16],
-          "reason": "selection"
-        },
-        {
           "object": "LayoutBlockFlow DIV",
           "rect": [10, 11, 56, 16],
           "reason": "paint property change"
+        },
+        {
+          "object": "InlineTextBox 'test test test'",
+          "rect": [18, 11, 26, 16],
+          "reason": "selection"
         }
       ]
     }
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/selection/selection-in-non-composited-scrolling-container-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/selection/selection-in-non-composited-scrolling-container-expected.txt
index 91fc6664..e144691 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/selection/selection-in-non-composited-scrolling-container-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/selection/selection-in-non-composited-scrolling-container-expected.txt
@@ -23,14 +23,14 @@
           "reason": "subtree"
         },
         {
-          "object": "InlineTextBox 'test test test'",
-          "rect": [10, 11, 57, 16],
-          "reason": "selection"
-        },
-        {
           "object": "LayoutBlockFlow DIV",
           "rect": [10, 11, 57, 16],
           "reason": "paint property change"
+        },
+        {
+          "object": "InlineTextBox 'test test test'",
+          "rect": [31, 11, 26, 16],
+          "reason": "selection"
         }
       ]
     }
diff --git a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/selection/text-selection-rect-in-overflow-2-expected.txt b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/selection/text-selection-rect-in-overflow-2-expected.txt
index a413880..c61497a5 100644
--- a/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/selection/text-selection-rect-in-overflow-2-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/enable-blink-features=LayoutNG/paint/invalidation/selection/text-selection-rect-in-overflow-2-expected.txt
@@ -19,7 +19,7 @@
       "paintInvalidations": [
         {
           "object": "NGPhysicalTextFragment 'Should have blue, not gray, highlight'",
-          "rect": [18, 18, 234, 20],
+          "rect": [18, 18, 233, 20],
           "reason": "selection"
         }
       ]
diff --git a/third_party/blink/web_tests/http/tests/devtools/service-workers/service-workers-view-expected.txt b/third_party/blink/web_tests/http/tests/devtools/service-workers/service-workers-view-expected.txt
index 9733a2a8..cca1dc5 100644
--- a/third_party/blink/web_tests/http/tests/devtools/service-workers/service-workers-view-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/service-workers/service-workers-view-expected.txt
@@ -17,6 +17,20 @@
 Sync
 Sync
 Register ServiceWorker for scope2
+127.0.0.1/devtools/service-workers/resources/scope2
+Update
+Unregister
+Source
+service-worker-empty.js
+Received
+Status
+#N activated and is running
+stop
+Clients
+Push
+Push
+Sync
+Sync
 127.0.0.1/devtools/service-workers/resources/scope1
 Update
 Unregister
@@ -31,6 +45,7 @@
 Push
 Sync
 Sync
+Unregister ServiceWorker for scope1
 127.0.0.1/devtools/service-workers/resources/scope2
 Update
 Unregister
@@ -45,7 +60,6 @@
 Push
 Sync
 Sync
-Unegister ServiceWorker for scope1
 127.0.0.1/devtools/service-workers/resources/scope1 - deleted
 Update
 Unregister
@@ -59,19 +73,5 @@
 Push
 Sync
 Sync
-127.0.0.1/devtools/service-workers/resources/scope2
-Update
-Unregister
-Source
-service-worker-empty.js
-Received
-Status
-#N activated and is running
-stop
-Clients
-Push
-Push
-Sync
-Sync
-Unegister ServiceWorker for scope1
+Unregister ServiceWorker for scope2
 
diff --git a/third_party/blink/web_tests/http/tests/devtools/service-workers/service-workers-view.js b/third_party/blink/web_tests/http/tests/devtools/service-workers/service-workers-view.js
index 47cbabfa..2d67701 100644
--- a/third_party/blink/web_tests/http/tests/devtools/service-workers/service-workers-view.js
+++ b/third_party/blink/web_tests/http/tests/devtools/service-workers/service-workers-view.js
@@ -28,12 +28,12 @@
       } else if (step == 1 && registration.scopeURL == scope2 && version.isActivated() && version.isRunning()) {
         ++step;
         TestRunner.addResult(ApplicationTestRunner.dumpServiceWorkersView());
-        TestRunner.addResult('Unegister ServiceWorker for scope1');
+        TestRunner.addResult('Unregister ServiceWorker for scope1');
         ApplicationTestRunner.unregisterServiceWorker(scope1);
       } else if (step == 2 && registration.scopeURL == scope1 && version.isRedundant() && version.isRunning()) {
         ++step;
         TestRunner.addResult(ApplicationTestRunner.dumpServiceWorkersView());
-        TestRunner.addResult('Unegister ServiceWorker for scope1');
+        TestRunner.addResult('Unregister ServiceWorker for scope2');
         ApplicationTestRunner.unregisterServiceWorker(scope2);
       } else if (step == 3 && registration.scopeURL == scope2 && version.isRedundant()) {
         ++step;
diff --git a/third_party/crashpad/README.chromium b/third_party/crashpad/README.chromium
index 19dadd7..a7681dd4 100644
--- a/third_party/crashpad/README.chromium
+++ b/third_party/crashpad/README.chromium
@@ -2,7 +2,7 @@
 Short Name: crashpad
 URL: https://crashpad.chromium.org/
 Version: unknown
-Revision: 39e458b331b7ea09a20b1efbc001dee82b203bf2
+Revision: 99bf283e54d049b6f5d2ad5522c6e3094b7156b4
 License: Apache 2.0
 License File: crashpad/LICENSE
 Security Critical: yes
diff --git a/third_party/crashpad/crashpad/client/crashpad_client.h b/third_party/crashpad/crashpad/client/crashpad_client.h
index ea0e7b6..8bf43ac 100644
--- a/third_party/crashpad/crashpad/client/crashpad_client.h
+++ b/third_party/crashpad/crashpad/client/crashpad_client.h
@@ -188,6 +188,97 @@
       const std::map<std::string, std::string>& annotations,
       const std::vector<std::string>& arguments,
       int socket);
+
+  //! \brief Installs a signal handler to start a Crashpad handler process by
+  //!     loading it with `/system/bin/linker`.
+  //!
+  //! This method is only supported by Android Q+.
+  //!
+  //! \param[in] handler_trampoline The path to a Crashpad handler trampoline
+  //!     executable, possibly located within an apk, e.g.
+  //!     "/data/app/myapk.apk!/myabi/libcrashpad_handler_trampoline.so".
+  //! \param[in] handler_library The name of a library exporting the symbol
+  //!     `CrashpadHandlerMain()`. The path to this library must be present in
+  //!     `LD_LIBRARY_PATH`.
+  //! \param[in] is_64_bit `true` if \a handler_trampoline and \a
+  //!     handler_library are 64-bit objects. They must have the same bitness.
+  //! \param[in] env A vector of environment variables of the form `var=value`
+  //!     defining the environment in which to execute `app_process`. If this
+  //!     value is `nullptr`, the application's environment at the time of the
+  //!     crash will be used.
+  //! \param[in] database The path to a Crashpad database. The handler will be
+  //!     started with this path as its `--database` argument.
+  //! \param[in] metrics_dir The path to an already existing directory where
+  //!     metrics files can be stored. The handler will be started with this
+  //!     path as its `--metrics-dir` argument.
+  //! \param[in] url The URL of an upload server. The handler will be started
+  //!     with this URL as its `--url` argument.
+  //! \param[in] annotations Process annotations to set in each crash report.
+  //!     The handler will be started with an `--annotation` argument for each
+  //!     element in this map.
+  //! \param[in] arguments Additional arguments to pass to the Crashpad handler.
+  //!     Arguments passed in other parameters and arguments required to perform
+  //!     the handshake are the responsibility of this method, and must not be
+  //!     specified in this parameter.
+  //!
+  //! \return `true` on success, `false` on failure with a message logged.
+  static bool StartHandlerWithLinkerAtCrash(
+      const std::string& handler_trampoline,
+      const std::string& handler_library,
+      bool is_64_bit,
+      const std::vector<std::string>* env,
+      const base::FilePath& database,
+      const base::FilePath& metrics_dir,
+      const std::string& url,
+      const std::map<std::string, std::string>& annotations,
+      const std::vector<std::string>& arguments);
+
+  //! \brief Starts a Crashpad handler process with an initial client by loading
+  //!     it with `/system/bin/linker`.
+  //!
+  //! This method is only supported by Android Q+.
+  //!
+  //! \param[in] handler_trampoline The path to a Crashpad handler trampoline
+  //!     executable, possibly located within an apk, e.g.
+  //!     "/data/app/myapk.apk!/myabi/libcrashpad_handler_trampoline.so".
+  //! \param[in] handler_library The name of a library exporting the symbol
+  //!     `CrashpadHandlerMain()`. The path to this library must be present in
+  //!     `LD_LIBRARY_PATH`.
+  //! \param[in] is_64_bit `true` if \a handler_trampoline and \a
+  //!     handler_library are 64-bit objects. They must have the same bitness.
+  //! \param[in] env A vector of environment variables of the form `var=value`
+  //!     defining the environment in which to execute `app_process`. If this
+  //!     value is `nullptr`, the application's current environment will be
+  //!     used.
+  //! \param[in] database The path to a Crashpad database. The handler will be
+  //!     started with this path as its `--database` argument.
+  //! \param[in] metrics_dir The path to an already existing directory where
+  //!     metrics files can be stored. The handler will be started with this
+  //!     path as its `--metrics-dir` argument.
+  //! \param[in] url The URL of an upload server. The handler will be started
+  //!     with this URL as its `--url` argument.
+  //! \param[in] annotations Process annotations to set in each crash report.
+  //!     The handler will be started with an `--annotation` argument for each
+  //!     element in this map.
+  //! \param[in] arguments Additional arguments to pass to the Crashpad handler.
+  //!     Arguments passed in other parameters and arguments required to perform
+  //!     the handshake are the responsibility of this method, and must not be
+  //!     specified in this parameter.
+  //! \param[in] socket The server end of a socket pair. The client end should
+  //!     be used with an ExceptionHandlerClient.
+  //!
+  //! \return `true` on success, `false` on failure with a message logged.
+  static bool StartHandlerWithLinkerForClient(
+      const std::string& handler_trampoline,
+      const std::string& handler_library,
+      bool is_64_bit,
+      const std::vector<std::string>* env,
+      const base::FilePath& database,
+      const base::FilePath& metrics_dir,
+      const std::string& url,
+      const std::map<std::string, std::string>& annotations,
+      const std::vector<std::string>& arguments,
+      int socket);
 #endif  // OS_ANDROID || DOXYGEN
 
 #if defined(OS_LINUX) || defined(OS_ANDROID) || DOXYGEN
diff --git a/third_party/crashpad/crashpad/client/crashpad_client_linux.cc b/third_party/crashpad/crashpad/client/crashpad_client_linux.cc
index 556a91f..fe5798a 100644
--- a/third_party/crashpad/crashpad/client/crashpad_client_linux.cc
+++ b/third_party/crashpad/crashpad/client/crashpad_client_linux.cc
@@ -77,6 +77,36 @@
   return argv;
 }
 
+std::vector<std::string> BuildArgsToLaunchWithLinker(
+    const std::string& handler_trampoline,
+    const std::string& handler_library,
+    bool is_64_bit,
+    const base::FilePath& database,
+    const base::FilePath& metrics_dir,
+    const std::string& url,
+    const std::map<std::string, std::string>& annotations,
+    const std::vector<std::string>& arguments,
+    int socket) {
+  std::vector<std::string> argv;
+  if (is_64_bit) {
+    argv.push_back("/system/bin/linker64");
+  } else {
+    argv.push_back("/system/bin/linker");
+  }
+  argv.push_back(handler_trampoline);
+  argv.push_back(handler_library);
+
+  std::vector<std::string> handler_argv = BuildHandlerArgvStrings(
+      base::FilePath(), database, metrics_dir, url, annotations, arguments);
+
+  if (socket != kInvalidFileHandle) {
+    handler_argv.push_back(FormatArgumentInt("initial-client-fd", socket));
+  }
+
+  argv.insert(argv.end(), handler_argv.begin() + 1, handler_argv.end());
+  return argv;
+}
+
 #endif  // OS_ANDROID
 
 // Launches a single use handler to snapshot this process.
@@ -251,6 +281,61 @@
   return DoubleForkAndExec(argv, env, socket, false, nullptr);
 }
 
+// static
+bool CrashpadClient::StartHandlerWithLinkerAtCrash(
+    const std::string& handler_trampoline,
+    const std::string& handler_library,
+    bool is_64_bit,
+    const std::vector<std::string>* env,
+    const base::FilePath& database,
+    const base::FilePath& metrics_dir,
+    const std::string& url,
+    const std::map<std::string, std::string>& annotations,
+    const std::vector<std::string>& arguments) {
+  std::vector<std::string> argv =
+      BuildArgsToLaunchWithLinker(handler_trampoline,
+                                  handler_library,
+                                  is_64_bit,
+                                  database,
+                                  metrics_dir,
+                                  url,
+                                  annotations,
+                                  arguments,
+                                  kInvalidFileHandle);
+  auto signal_handler = LaunchAtCrashHandler::Get();
+  if (signal_handler->Initialize(&argv, env)) {
+    DCHECK(!g_crash_handler);
+    g_crash_handler = signal_handler;
+    return true;
+  }
+  return false;
+}
+
+// static
+bool CrashpadClient::StartHandlerWithLinkerForClient(
+    const std::string& handler_trampoline,
+    const std::string& handler_library,
+    bool is_64_bit,
+    const std::vector<std::string>* env,
+    const base::FilePath& database,
+    const base::FilePath& metrics_dir,
+    const std::string& url,
+    const std::map<std::string, std::string>& annotations,
+    const std::vector<std::string>& arguments,
+    int socket) {
+  std::vector<std::string> argv =
+      BuildArgsToLaunchWithLinker(handler_trampoline,
+                                  handler_library,
+                                  is_64_bit,
+                                  database,
+                                  metrics_dir,
+                                  url,
+                                  annotations,
+                                  arguments,
+                                  socket);
+  return DoubleForkAndExec(argv, env, socket, false, nullptr);
+}
+
 #endif
 
 // static
diff --git a/third_party/crashpad/crashpad/handler/BUILD.gn b/third_party/crashpad/crashpad/handler/BUILD.gn
index 32d4d6c..bbd68ab1 100644
--- a/third_party/crashpad/crashpad/handler/BUILD.gn
+++ b/third_party/crashpad/crashpad/handler/BUILD.gn
@@ -166,6 +166,21 @@
       "$root_out_dir/libcrashpad_handler.so",
     ]
   }
+
+  crashpad_executable("crashpad_handler_trampoline") {
+    set_sources_assignment_filter([])
+    output_name = "libcrashpad_handler_trampoline.so"
+
+    sources = [
+      "linux/handler_trampoline.cc",
+    ]
+
+    ldflags = [ "-llog" ]
+
+    if (crashpad_is_in_chromium) {
+      no_default_deps = true
+    }
+  }
 }
 
 crashpad_executable("crashpad_handler_test_extended_handler") {
diff --git a/third_party/crashpad/crashpad/handler/handler_main.cc b/third_party/crashpad/crashpad/handler/handler_main.cc
index b3e0a68..31686b3 100644
--- a/third_party/crashpad/crashpad/handler/handler_main.cc
+++ b/third_party/crashpad/crashpad/handler/handler_main.cc
@@ -497,6 +497,18 @@
 
 }  // namespace
 
+#if defined(OS_ANDROID)
+
+extern "C" {
+__attribute__((visibility("default"), used)) int CrashpadHandlerMain(
+    int argc,
+    char* argv[]) {
+  return HandlerMain(argc, argv, nullptr);
+}
+}  // extern "C"
+
+#endif  // OS_ANDROID
+
 int HandlerMain(int argc,
                 char* argv[],
                 const UserStreamDataSources* user_stream_sources) {
diff --git a/third_party/crashpad/crashpad/handler/linux/handler_trampoline.cc b/third_party/crashpad/crashpad/handler/linux/handler_trampoline.cc
new file mode 100644
index 0000000..3453563
--- /dev/null
+++ b/third_party/crashpad/crashpad/handler/linux/handler_trampoline.cc
@@ -0,0 +1,45 @@
+// Copyright 2019 The Crashpad Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <android/log.h>
+#include <dlfcn.h>
+#include <stdlib.h>
+
+// The first argument passed to the trampoline is the name of the native library
+// exporting the symbol `CrashpadHandlerMain`. The remaining arguments are the
+// same as for `HandlerMain()`.
+int main(int argc, char* argv[]) {
+  static constexpr char kTag[] = "crashpad";
+
+  if (argc < 2) {
+    __android_log_print(ANDROID_LOG_FATAL, kTag, "usage: %s <path>", argv[0]);
+    return EXIT_FAILURE;
+  }
+
+  void* handle = dlopen(argv[1], RTLD_LAZY | RTLD_GLOBAL);
+  if (!handle) {
+    __android_log_print(ANDROID_LOG_FATAL, kTag, "dlopen: %s", dlerror());
+    return EXIT_FAILURE;
+  }
+
+  using MainType = int (*)(int, char*[]);
+  MainType crashpad_main =
+      reinterpret_cast<MainType>(dlsym(handle, "CrashpadHandlerMain"));
+  if (!crashpad_main) {
+    __android_log_print(ANDROID_LOG_FATAL, kTag, "dlsym: %s", dlerror());
+    return EXIT_FAILURE;
+  }
+
+  return crashpad_main(argc - 1, argv + 1);
+}
diff --git a/third_party/crashpad/crashpad/snapshot/win/process_reader_win_test.cc b/third_party/crashpad/crashpad/snapshot/win/process_reader_win_test.cc
index 1880c871..de22008 100644
--- a/third_party/crashpad/crashpad/snapshot/win/process_reader_win_test.cc
+++ b/third_party/crashpad/crashpad/snapshot/win/process_reader_win_test.cc
@@ -130,7 +130,7 @@
 
     void ThreadMain() override {
       done_->Wait();
-    };
+    }
 
    private:
     Semaphore* done_;
diff --git a/third_party/crashpad/crashpad/test/multiprocess.h b/third_party/crashpad/crashpad/test/multiprocess.h
index 9a221bb3..61df98b5 100644
--- a/third_party/crashpad/crashpad/test/multiprocess.h
+++ b/third_party/crashpad/crashpad/test/multiprocess.h
@@ -15,6 +15,7 @@
 #ifndef CRASHPAD_TEST_MULTIPROCESS_H_
 #define CRASHPAD_TEST_MULTIPROCESS_H_
 
+#include <stdint.h>
 #include <sys/types.h>
 
 #include "base/macros.h"
@@ -28,6 +29,12 @@
 struct MultiprocessInfo;
 }  // namespace internal
 
+#if defined(OS_FUCHSIA)
+using ReturnCodeType = int64_t;
+#else
+using ReturnCodeType = int;
+#endif
+
 //! \brief Manages a multiprocess test.
 //!
 //! These tests are `fork()`-based. The parent and child processes are able to
@@ -76,7 +83,7 @@
 
   //! \brief Sets the expected termination reason and code.
   //!
-  //! The default expected termination reasaon is
+  //! The default expected termination reason is
   //! TerminationReason::kTerminationNormal, and the default expected
   //! termination code is `EXIT_SUCCESS` (`0`).
   //!
@@ -91,7 +98,8 @@
   //!     TerminationReason::kTerminationSignal, this is the signal that is
   //!     expected to kill the child. On Linux platforms, SIG_DFL will be
   //!     installed for \a code in the child process.
-  void SetExpectedChildTermination(TerminationReason reason, int code);
+  void SetExpectedChildTermination(TerminationReason reason,
+                                   ReturnCodeType code);
 
 #if !defined(OS_WIN)
   //! \brief Sets termination reason and code appropriately for a child that
@@ -211,7 +219,7 @@
   virtual void MultiprocessChild() = 0;
 
   internal::MultiprocessInfo* info_;
-  int code_;
+  ReturnCodeType code_;
   TerminationReason reason_;
 
   DISALLOW_COPY_AND_ASSIGN(Multiprocess);
diff --git a/third_party/crashpad/crashpad/test/multiprocess_exec_fuchsia.cc b/third_party/crashpad/crashpad/test/multiprocess_exec_fuchsia.cc
index 9c68b7f..eff522b0 100644
--- a/third_party/crashpad/crashpad/test/multiprocess_exec_fuchsia.cc
+++ b/third_party/crashpad/crashpad/test/multiprocess_exec_fuchsia.cc
@@ -87,7 +87,7 @@
 }
 
 void Multiprocess::SetExpectedChildTermination(TerminationReason reason,
-                                               int code) {
+                                               ReturnCodeType code) {
   EXPECT_EQ(info_, nullptr)
       << "SetExpectedChildTermination() must be called before Run()";
   reason_ = reason;
@@ -95,7 +95,15 @@
 }
 
 void Multiprocess::SetExpectedChildTerminationBuiltinTrap() {
-  SetExpectedChildTermination(kTerminationNormal, -1);
+  // TODO(scottmg): Once
+  // https://fuchsia-review.googlesource.com/c/fuchsia/+/256771 lands, remove
+  // this #ifdef, and always use ZX_TASK_RETCODE_EXCEPTION_KILL.
+#if defined(ZX_TASK_RETCODE_EXCEPTION_KILL)
+  constexpr ReturnCodeType kExpectedReturnCode = ZX_TASK_RETCODE_EXCEPTION_KILL;
+#else
+  constexpr ReturnCodeType kExpectedReturnCode = -1;
+#endif
+  SetExpectedChildTermination(kTerminationNormal, kExpectedReturnCode);
 }
 
 Multiprocess::~Multiprocess() {
diff --git a/third_party/crashpad/crashpad/test/multiprocess_exec_win.cc b/third_party/crashpad/crashpad/test/multiprocess_exec_win.cc
index 3897818..b75f8f57 100644
--- a/third_party/crashpad/crashpad/test/multiprocess_exec_win.cc
+++ b/third_party/crashpad/crashpad/test/multiprocess_exec_win.cc
@@ -58,7 +58,7 @@
 }
 
 void Multiprocess::SetExpectedChildTermination(TerminationReason reason,
-                                               int code) {
+                                               ReturnCodeType code) {
   EXPECT_EQ(info_, nullptr)
       << "SetExpectedChildTermination() must be called before Run()";
   reason_ = reason;
diff --git a/third_party/crashpad/crashpad/test/multiprocess_posix.cc b/third_party/crashpad/crashpad/test/multiprocess_posix.cc
index 2e0c3856..d2de3184 100644
--- a/third_party/crashpad/crashpad/test/multiprocess_posix.cc
+++ b/third_party/crashpad/crashpad/test/multiprocess_posix.cc
@@ -154,7 +154,7 @@
 }
 
 void Multiprocess::SetExpectedChildTermination(TerminationReason reason,
-                                               int code) {
+                                               ReturnCodeType code) {
   EXPECT_EQ(info_, nullptr)
       << "SetExpectedChildTermination() must be called before Run()";
   reason_ = reason;
diff --git a/third_party/crashpad/crashpad/util/posix/scoped_mmap.cc b/third_party/crashpad/crashpad/util/posix/scoped_mmap.cc
index 4860cecb..0965fd67 100644
--- a/third_party/crashpad/crashpad/util/posix/scoped_mmap.cc
+++ b/third_party/crashpad/crashpad/util/posix/scoped_mmap.cc
@@ -19,6 +19,7 @@
 #include <algorithm>
 
 #include "base/logging.h"
+#include "base/numerics/safe_conversions.h"
 #include "base/numerics/safe_math.h"
 
 namespace {
@@ -54,9 +55,12 @@
   if (addr == MAP_FAILED) {
     DCHECK_EQ(len, 0u);
   } else {
+    // Round |len| up to the next page.
+    const size_t kPageMask = base::checked_cast<size_t>(getpagesize()) - 1;
+    len = (len + kPageMask) & ~kPageMask;
+
     DCHECK_NE(len, 0u);
     DCHECK_EQ(new_addr % getpagesize(), 0u);
-    DCHECK_EQ(len % getpagesize(), 0u);
     DCHECK((base::CheckedNumeric<uintptr_t>(new_addr) + (len - 1)).IsValid());
   }
 
diff --git a/third_party/crashpad/crashpad/util/posix/scoped_mmap_test.cc b/third_party/crashpad/crashpad/util/posix/scoped_mmap_test.cc
index 5c69e7e4..e32fa159 100644
--- a/third_party/crashpad/crashpad/util/posix/scoped_mmap_test.cc
+++ b/third_party/crashpad/crashpad/util/posix/scoped_mmap_test.cc
@@ -294,6 +294,94 @@
   EXPECT_DEATH_CRASH(cookie.Check(), "");
 }
 
+TEST(ScopedMmapDeathTest, NotIntegralNumberOfPages) {
+  ScopedMmap mapping;
+  EXPECT_FALSE(mapping.is_valid());
+  EXPECT_EQ(mapping.addr(), MAP_FAILED);
+  EXPECT_EQ(mapping.len(), 0u);
+
+  ASSERT_TRUE(mapping.Reset());
+  EXPECT_FALSE(mapping.is_valid());
+
+  // Establishing a half-page mapping actually establishes a single page.
+  const size_t kPageSize = base::checked_cast<size_t>(getpagesize());
+  const size_t kHalfPageSize = kPageSize / 2;
+  ASSERT_TRUE(ScopedMmapResetMmap(&mapping, kHalfPageSize));
+  EXPECT_TRUE(mapping.is_valid());
+  EXPECT_NE(mapping.addr(), MAP_FAILED);
+  EXPECT_EQ(mapping.len(), kPageSize);
+
+  TestCookie cookie;
+  cookie.SetUp(mapping.addr_as<uint64_t*>());
+
+  // Shrinking a one-page mapping to a half page is a no-op.
+  void* orig_addr = mapping.addr();
+  ASSERT_TRUE(mapping.ResetAddrLen(orig_addr, kHalfPageSize));
+  EXPECT_TRUE(mapping.is_valid());
+  EXPECT_EQ(mapping.addr(), orig_addr);
+  EXPECT_EQ(mapping.len(), kPageSize);
+
+  EXPECT_EQ(cookie.Observed(), cookie.Expected());
+
+  // Same thing shrinking it to a single byte, or one byte less than a whole
+  // page.
+  ASSERT_TRUE(mapping.ResetAddrLen(orig_addr, 1));
+  EXPECT_TRUE(mapping.is_valid());
+  EXPECT_EQ(mapping.addr(), orig_addr);
+  EXPECT_EQ(mapping.len(), kPageSize);
+
+  EXPECT_EQ(cookie.Observed(), cookie.Expected());
+
+  ASSERT_TRUE(mapping.ResetAddrLen(orig_addr, kPageSize - 1));
+  EXPECT_TRUE(mapping.is_valid());
+  EXPECT_EQ(mapping.addr(), orig_addr);
+  EXPECT_EQ(mapping.len(), kPageSize);
+
+  EXPECT_EQ(cookie.Observed(), cookie.Expected());
+
+  // Shrinking a two-page mapping to a half page frees the second page but
+  // leaves the first alone.
+  ASSERT_TRUE(ScopedMmapResetMmap(&mapping, 2 * kPageSize));
+  EXPECT_TRUE(mapping.is_valid());
+  EXPECT_NE(mapping.addr(), MAP_FAILED);
+  EXPECT_EQ(mapping.len(), 2 * kPageSize);
+
+  TestCookie two_cookies[2];
+  for (size_t index = 0; index < base::size(two_cookies); ++index) {
+    two_cookies[index].SetUp(reinterpret_cast<uint64_t*>(
+        mapping.addr_as<uintptr_t>() + index * kPageSize));
+  }
+
+  orig_addr = mapping.addr();
+  ASSERT_TRUE(mapping.ResetAddrLen(orig_addr, kHalfPageSize));
+  EXPECT_TRUE(mapping.is_valid());
+  EXPECT_EQ(mapping.addr(), orig_addr);
+  EXPECT_EQ(mapping.len(), kPageSize);
+
+  EXPECT_EQ(two_cookies[0].Observed(), two_cookies[0].Expected());
+  EXPECT_DEATH_CRASH(two_cookies[1].Check(), "");
+
+  // Shrinking a two-page mapping to a page and a half is a no-op.
+  ASSERT_TRUE(ScopedMmapResetMmap(&mapping, 2 * kPageSize));
+  EXPECT_TRUE(mapping.is_valid());
+  EXPECT_NE(mapping.addr(), MAP_FAILED);
+  EXPECT_EQ(mapping.len(), 2 * kPageSize);
+
+  for (size_t index = 0; index < base::size(two_cookies); ++index) {
+    two_cookies[index].SetUp(reinterpret_cast<uint64_t*>(
+        mapping.addr_as<uintptr_t>() + index * kPageSize));
+  }
+
+  orig_addr = mapping.addr();
+  ASSERT_TRUE(mapping.ResetAddrLen(orig_addr, kPageSize + kHalfPageSize));
+  EXPECT_TRUE(mapping.is_valid());
+  EXPECT_EQ(mapping.addr(), orig_addr);
+  EXPECT_EQ(mapping.len(), 2 * kPageSize);
+
+  EXPECT_EQ(two_cookies[0].Observed(), two_cookies[0].Expected());
+  EXPECT_EQ(two_cookies[1].Observed(), two_cookies[1].Expected());
+}
+
 TEST(ScopedMmapDeathTest, Mprotect) {
   ScopedMmap mapping;
 
diff --git a/third_party/flatbuffers/BUILD.gn b/third_party/flatbuffers/BUILD.gn
index 3b4ac1b..d0f35bc 100644
--- a/third_party/flatbuffers/BUILD.gn
+++ b/third_party/flatbuffers/BUILD.gn
@@ -84,9 +84,6 @@
     ":compiler_files",
     ":flatbuffers",
   ]
-  # TODO(https://crbug.com/934834): Re-enable chromium_code for this.
-  configs -= [ "//build/config/compiler:chromium_code" ]
-  configs += [ "//build/config/compiler:no_chromium_code" ]
 }
 
 # The following is just for testing.
@@ -114,9 +111,6 @@
     ":flatbuffers",
     ":flatbuffers_samplebuffer",
   ]
-  # TODO(https://crbug.com/934834): Re-enable chromium_code for this.
-  configs -= [ "//build/config/compiler:chromium_code" ]
-  configs += [ "//build/config/compiler:no_chromium_code" ]
   data = [
     "src/tests/",
   ]
diff --git a/third_party/flatbuffers/README.chromium b/third_party/flatbuffers/README.chromium
index 7905758..ffff618 100644
--- a/third_party/flatbuffers/README.chromium
+++ b/third_party/flatbuffers/README.chromium
@@ -1,8 +1,8 @@
 Name: FlatBuffers
 Short Name: flatbuffers
 URL: https://github.com/google/flatbuffers
-Version: 4f32cbf268a8ad469974b9453924a3582dbf2f30
-Date: 2019-02-20
+Version: 9bf9b18f0a705dfd6d50b98056463a55de6a1bf9
+Date: 2019-02-25
 License: Apache 2.0
 License File: LICENSE
 Security Critical: yes
diff --git a/third_party/grpc/BUILD.gn b/third_party/grpc/BUILD.gn
index a7583bf..76ba9eebb 100644
--- a/third_party/grpc/BUILD.gn
+++ b/third_party/grpc/BUILD.gn
@@ -25,6 +25,9 @@
 config("nanopb_config") {
   include_dirs = [ "src/third_party/nanopb" ]
   defines = [ "PB_FIELD_32BIT=1" ]
+  if (is_mac || is_ios) {
+    defines += [ "PB_NO_PACKED_STRUCTS=1" ]
+  }
 }
 
 # The gRPC library. Note that server side code will not be built. You probably
diff --git a/third_party/grpc/METADATA b/third_party/grpc/METADATA
index 8f3dfa5..d497ae2 100644
--- a/third_party/grpc/METADATA
+++ b/third_party/grpc/METADATA
@@ -13,7 +13,7 @@
     type: GIT
     value: "https://github.com/grpc/grpc"
   }
-  version: "318c67782a752a8324233ff95e594a19f85578a7"
-  last_upgrade_date { year: 2019 month: 2 day: 3 }
+  version: "e60c4fc034815ac2cff62da047e7144172237036"
+  last_upgrade_date { year: 2019 month: 2 day: 25 }
   license_type: NOTICE
 }
diff --git a/third_party/grpc/README.chromium b/third_party/grpc/README.chromium
index d96e9c29..b9443286 100644
--- a/third_party/grpc/README.chromium
+++ b/third_party/grpc/README.chromium
@@ -2,7 +2,7 @@
 URL: https://github.com/grpc/grpc
 Version: 0
 Date: Feb 3, 2019
-Revision: 318c67782a752a8324233ff95e594a19f85578a7
+Revision: e60c4fc034815ac2cff62da047e7144172237036
 License: Apache 2.0
 License File: NOT_SHIPPED
 Security Critical: yes
diff --git a/third_party/libvpx/README.chromium b/third_party/libvpx/README.chromium
index 1c20d7a..45030df2 100644
--- a/third_party/libvpx/README.chromium
+++ b/third_party/libvpx/README.chromium
@@ -5,9 +5,9 @@
 License File: source/libvpx/LICENSE
 Security Critical: yes
 
-Date: Wednesday February 20 2019
+Date: Monday February 25 2019
 Branch: master
-Commit: 986b2bef7f475543a441cf9aa5a3ca55dd57ccae
+Commit: 2d403737b88f76ce8410237a8eb682cc556ac302
 
 Description:
 Contains the sources used to compile libvpx binaries used by Google Chrome and
diff --git a/third_party/libvpx/source/config/vpx_version.h b/third_party/libvpx/source/config/vpx_version.h
index 13973ca..2a7b26d8 100644
--- a/third_party/libvpx/source/config/vpx_version.h
+++ b/third_party/libvpx/source/config/vpx_version.h
@@ -2,7 +2,7 @@
 #define VERSION_MAJOR  1
 #define VERSION_MINOR  8
 #define VERSION_PATCH  0
-#define VERSION_EXTRA  "173-g986b2bef7f"
+#define VERSION_EXTRA  "178-g2d403737b8"
 #define VERSION_PACKED ((VERSION_MAJOR<<16)|(VERSION_MINOR<<8)|(VERSION_PATCH))
-#define VERSION_STRING_NOSP "v1.8.0-173-g986b2bef7f"
-#define VERSION_STRING      " v1.8.0-173-g986b2bef7f"
+#define VERSION_STRING_NOSP "v1.8.0-178-g2d403737b8"
+#define VERSION_STRING      " v1.8.0-178-g2d403737b8"
diff --git a/tools/code_coverage/coverage.py b/tools/code_coverage/coverage.py
index 7cf2d3d..16e5f55 100755
--- a/tools/code_coverage/coverage.py
+++ b/tools/code_coverage/coverage.py
@@ -799,6 +799,16 @@
   os.makedirs(coverage_utils.GetCoverageReportRootDirPath(OUTPUT_DIR))
 
 
+def _SetMacXcodePath():
+  """Set DEVELOPER_DIR to the path to hermetic Xcode.app on Mac OS X."""
+  if sys.platform != 'darwin':
+    return
+
+  xcode_path = os.path.join(SRC_ROOT_PATH, 'build', 'mac_files', 'Xcode.app')
+  if os.path.exists(xcode_path):
+    os.environ['DEVELOPER_DIR'] = xcode_path
+
+
 def _ParseCommandArguments():
   """Adds and parses relevant arguments for tool comands.
 
@@ -986,6 +996,11 @@
     profdata_file_path = args.profdata_file
     binary_paths = _GetBinaryPathsFromTargets(args.targets, args.build_dir)
 
+  # DEVELOPER_DIR needs to be set when Xcode isn't in a standard location
+  # and xcode-select wasn't run.  This path needs to be set prior to calling
+  # otool which happens on mac in coverage_utils.GetSharedLibraries().
+  _SetMacXcodePath()
+
   binary_paths.extend(
       coverage_utils.GetSharedLibraries(binary_paths, BUILD_DIR))
 
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index b3dafa6c..6a37c8d 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -11308,6 +11308,37 @@
   </summary>
 </histogram>
 
+<histogram name="Blink.Paint.CachedItemPercentage" units="%">
+  <owner>paint-dev@chromium.org</owner>
+  <summary>
+    Percentage of cached display items among all display items. Higher value
+    means higher performance beause of less paint invalidation. Recorded when we
+    finish updating paint in the Blink document lifecycle if we have enough data
+    to report.
+  </summary>
+</histogram>
+
+<histogram name="Blink.Paint.CachedSubsequencePercentage" units="%">
+  <owner>paint-dev@chromium.org</owner>
+  <summary>
+    Percentage of cached subsequences of display items among all subsequences.
+    Higher value means higher performance beause of less subsequence
+    invalidation. Recorded when we finish updating paint in the Blink document
+    lifecycle if we have enough data to report.
+  </summary>
+</histogram>
+
+<histogram name="Blink.Paint.IndexedItemPercentage" units="%">
+  <owner>paint-dev@chromium.org</owner>
+  <summary>
+    Percentage of display items that are put into the index because of
+    out-of-order display item matching. Higher value means lower performance
+    beause of the cost of out-of-order matching and indexing. Recorded when we
+    finish updating paint in the Blink document lifecycle if we have enough data
+    to report.
+  </summary>
+</histogram>
+
 <histogram name="Blink.Paint.UpdateTime" units="microseconds">
   <owner>paint-dev@chromium.org</owner>
   <summary>
@@ -75663,7 +75694,7 @@
 </histogram>
 
 <histogram name="Omnibox.DocumentSuggest.ResultCount" units="count"
-    expires_after="M74">
+    expires_after="M77">
   <owner>mpearson@chromium.org</owner>
   <owner>jdonnelly@chromium.org</owner>
   <owner>skare@chromium.org</owner>
@@ -82405,6 +82436,10 @@
 
 <histogram name="PasswordManager.SyncCredentialFiltered"
     enum="CredentialFilteredType">
+  <obsolete>
+    Password manager no longer supports this behavior and the code that could
+    generate values in this histogram is gone as of M74.
+  </obsolete>
   <owner>battre@chromium.org</owner>
   <owner>vasilii@chromium.org</owner>
   <summary>
diff --git a/ui/accessibility/BUILD.gn b/ui/accessibility/BUILD.gn
index 2222a8e..40daff9 100644
--- a/ui/accessibility/BUILD.gn
+++ b/ui/accessibility/BUILD.gn
@@ -25,6 +25,12 @@
   output_prefix = "ui_accessibility_ax_mojom"
 }
 
+mojom("ax_constants_mojo") {
+  sources = [
+    "ax_constants.mojom",
+  ]
+}
+
 jumbo_component("accessibility") {
   sources = [
     "accessibility_switches.cc",
@@ -114,6 +120,7 @@
   defines = [ "ACCESSIBILITY_IMPLEMENTATION" ]
 
   public_deps = [
+    ":ax_constants_mojo",
     ":ax_enums_mojo",
     "//base",
     "//base:i18n",
@@ -238,6 +245,7 @@
 
   deps = [
     ":accessibility",
+    ":ax_constants_mojo",
     ":ax_enums_mojo",
     ":test_support",
     "//base",
diff --git a/ui/accessibility/ax_constants.mojom b/ui/accessibility/ax_constants.mojom
new file mode 100644
index 0000000..29c1abe
--- /dev/null
+++ b/ui/accessibility/ax_constants.mojom
@@ -0,0 +1,13 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.

+// Use of this source code is governed by a BSD-style license that can be

+// found in the LICENSE file.

+

+module ax.mojom;

+

+// https://www.w3.org/TR/wai-aria-1.1/#aria-rowcount

+// https://www.w3.org/TR/wai-aria-1.1/#aria-colcount

+// If the total number of (rows|columns) is unknown, authors MUST set the

+// value of aria-(rowcount|colcount) to -1 to indicate that the value should not

+// be calculated by the user agent.

+// See: AXTableInfo

+const int32 kUnknownAriaColumnOrRowCount = -1;

diff --git a/ui/accessibility/ax_node.cc b/ui/accessibility/ax_node.cc
index 85c53f4ec..3471795 100644
--- a/ui/accessibility/ax_node.cc
+++ b/ui/accessibility/ax_node.cc
@@ -242,18 +242,18 @@
   return table_info->row_count;
 }
 
-int32_t AXNode::GetTableAriaColCount() const {
+base::Optional<int32_t> AXNode::GetTableAriaColCount() const {
   AXTableInfo* table_info = tree_->GetTableInfo(this);
   if (!table_info)
-    return 0;
+    return base::nullopt;
 
   return table_info->aria_col_count;
 }
 
-int32_t AXNode::GetTableAriaRowCount() const {
+base::Optional<int32_t> AXNode::GetTableAriaRowCount() const {
   AXTableInfo* table_info = tree_->GetTableInfo(this);
   if (!table_info)
-    return 0;
+    return base::nullopt;
 
   return table_info->aria_row_count;
 }
@@ -278,6 +278,14 @@
   return tree_->GetFromId(table_info->unique_cell_ids[index]);
 }
 
+AXNode* AXNode::GetTableCaption() const {
+  AXTableInfo* table_info = tree_->GetTableInfo(this);
+  if (!table_info)
+    return nullptr;
+
+  return tree_->GetFromId(table_info->caption_id);
+}
+
 AXNode* AXNode::GetTableCellFromCoords(int32_t row_index,
                                        int32_t col_index) const {
   AXTableInfo* table_info = tree_->GetTableInfo(this);
diff --git a/ui/accessibility/ax_node.h b/ui/accessibility/ax_node.h
index 6383650..d18546a 100644
--- a/ui/accessibility/ax_node.h
+++ b/ui/accessibility/ax_node.h
@@ -236,9 +236,10 @@
   bool IsTable() const;
   int32_t GetTableColCount() const;
   int32_t GetTableRowCount() const;
-  int32_t GetTableAriaColCount() const;
-  int32_t GetTableAriaRowCount() const;
+  base::Optional<int32_t> GetTableAriaColCount() const;
+  base::Optional<int32_t> GetTableAriaRowCount() const;
   int32_t GetTableCellCount() const;
+  AXNode* GetTableCaption() const;
   AXNode* GetTableCellFromIndex(int32_t index) const;
   AXNode* GetTableCellFromCoords(int32_t row_index, int32_t col_index) const;
   void GetTableColHeaderNodeIds(int32_t col_index,
diff --git a/ui/accessibility/ax_role_properties.cc b/ui/accessibility/ax_role_properties.cc
index 2eefede6d..bc3f219a 100644
--- a/ui/accessibility/ax_role_properties.cc
+++ b/ui/accessibility/ax_role_properties.cc
@@ -412,4 +412,37 @@
   }
 }
 
+bool ShouldHaveReadonlyStateByDefault(const ax::mojom::Role role) {
+  switch (role) {
+    case ax::mojom::Role::kArticle:
+    case ax::mojom::Role::kDefinition:
+    case ax::mojom::Role::kDescriptionList:
+    case ax::mojom::Role::kDescriptionListTerm:
+    case ax::mojom::Role::kDocument:
+    case ax::mojom::Role::kGraphicsDocument:
+    case ax::mojom::Role::kImage:
+    case ax::mojom::Role::kImageMap:
+    case ax::mojom::Role::kList:
+    case ax::mojom::Role::kListItem:
+    case ax::mojom::Role::kProgressIndicator:
+    case ax::mojom::Role::kRootWebArea:
+    case ax::mojom::Role::kTerm:
+    case ax::mojom::Role::kTimer:
+    case ax::mojom::Role::kToolbar:
+    case ax::mojom::Role::kTooltip:
+    case ax::mojom::Role::kWebArea:
+      return true;
+
+    case ax::mojom::Role::kGrid:
+      // TODO(aleventhal) this changed between ARIA 1.0 and 1.1,
+      // need to determine whether grids/treegrids should really be readonly
+      // or editable by default
+      break;
+
+    default:
+      break;
+  }
+  return false;
+}
+
 }  // namespace ui
diff --git a/ui/accessibility/ax_role_properties.h b/ui/accessibility/ax_role_properties.h
index a9ea967e..4c0e660e7 100644
--- a/ui/accessibility/ax_role_properties.h
+++ b/ui/accessibility/ax_role_properties.h
@@ -102,6 +102,8 @@
 // Automation.
 AX_EXPORT bool IsUIASelectable(const ax::mojom::Role role);
 
+// Returns true if the node should be read only by default
+AX_EXPORT bool ShouldHaveReadonlyStateByDefault(const ax::mojom::Role role);
 }  // namespace ui
 
 #endif  // UI_ACCESSIBILITY_AX_ROLE_PROPERTIES_H_
diff --git a/ui/accessibility/ax_table_info.cc b/ui/accessibility/ax_table_info.cc
index d4e9f40b..7466c2f 100644
--- a/ui/accessibility/ax_table_info.cc
+++ b/ui/accessibility/ax_table_info.cc
@@ -4,6 +4,7 @@
 
 #include "ui/accessibility/ax_table_info.h"
 
+#include "ui/accessibility/ax_constants.mojom.h"
 #include "ui/accessibility/ax_node.h"
 #include "ui/accessibility/ax_role_properties.h"
 #include "ui/accessibility/ax_tree.h"
@@ -41,20 +42,22 @@
 // We only recursively check for the following roles in between a table and
 // its rows: generic containers like <div>, any nodes that are ignored, and
 // table sections (which have Role::kGroup).
-void FindRowsAndThenCells(
-    AXNode* node,
-    std::vector<AXNode*>* row_nodes,
-    std::vector<std::vector<AXNode*>>* cell_nodes_per_row) {
+void FindRowsAndThenCells(AXNode* node,
+                          std::vector<AXNode*>* row_nodes,
+                          std::vector<std::vector<AXNode*>>* cell_nodes_per_row,
+                          int32_t& caption_node_id) {
   for (AXNode* child : node->children()) {
     if (child->data().HasState(ax::mojom::State::kIgnored) ||
         child->data().role == ax::mojom::Role::kGenericContainer ||
         child->data().role == ax::mojom::Role::kGroup) {
-      FindRowsAndThenCells(child, row_nodes, cell_nodes_per_row);
+      FindRowsAndThenCells(child, row_nodes, cell_nodes_per_row,
+                           caption_node_id);
     } else if (child->data().role == ax::mojom::Role::kRow) {
       row_nodes->push_back(child);
       cell_nodes_per_row->push_back(std::vector<AXNode*>());
       FindCellsInRow(child, &cell_nodes_per_row->back());
-    }
+    } else if (child->data().role == ax::mojom::Role::kCaption)
+      caption_node_id = child->id();
   }
 }
 
@@ -92,7 +95,9 @@
 
   std::vector<AXNode*> row_nodes;
   std::vector<std::vector<AXNode*>> cell_nodes_per_row;
-  FindRowsAndThenCells(table_node_, &row_nodes, &cell_nodes_per_row);
+  caption_id = 0;
+  FindRowsAndThenCells(table_node_, &row_nodes, &cell_nodes_per_row,
+                       caption_id);
   DCHECK_EQ(cell_nodes_per_row.size(), row_nodes.size());
 
   // Get the optional row and column count from the table. If we encounter
@@ -102,10 +107,16 @@
       std::max(0, node_data.GetIntAttribute(IntAttribute::kTableRowCount));
   col_count =
       std::max(0, node_data.GetIntAttribute(IntAttribute::kTableColumnCount));
-  aria_row_count =
-      std::max(0, node_data.GetIntAttribute(IntAttribute::kAriaRowCount));
-  aria_col_count =
-      std::max(0, node_data.GetIntAttribute(IntAttribute::kAriaColumnCount));
+
+  int32_t aria_rows = node_data.GetIntAttribute(IntAttribute::kAriaRowCount);
+  aria_row_count = (aria_rows != ax::mojom::kUnknownAriaColumnOrRowCount)
+                       ? base::Optional<int32_t>(std::max(0, aria_rows))
+                       : base::nullopt;
+
+  int32_t aria_cols = node_data.GetIntAttribute(IntAttribute::kAriaColumnCount);
+  aria_col_count = (aria_cols != ax::mojom::kUnknownAriaColumnOrRowCount)
+                       ? base::Optional<int32_t>(std::max(0, aria_cols))
+                       : base::nullopt;
 
   // Iterate over the cells and build up an array of CellData
   // entries, one for each cell. Compute the actual row and column
@@ -234,6 +245,7 @@
       // Ensure the ARIA col index is incrementing.
       cell_data.aria_col_index =
           std::max(cell_data.aria_col_index, current_aria_col_index);
+      current_aria_col_index = cell_data.aria_col_index;
 
       // Update the row count and col count for the whole table to make
       // sure they're large enough to fit this cell, including its spans.
@@ -241,11 +253,14 @@
       // whereas all other indices are zero-based.
       row_count = std::max(row_count, cell_data.row_index + cell_data.row_span);
       col_count = std::max(col_count, cell_data.col_index + cell_data.col_span);
-      aria_row_count = std::max(
-          aria_row_count, current_aria_row_index + cell_data.row_span - 1);
-      aria_col_count = std::max(
-          aria_col_count, current_aria_col_index + cell_data.col_span - 1);
-
+      if (aria_row_count) {
+        aria_row_count = std::max(
+            (*aria_row_count), current_aria_row_index + cell_data.row_span - 1);
+      }
+      if (aria_col_count) {
+        aria_col_count = std::max(
+            (*aria_col_count), current_aria_col_index + cell_data.col_span - 1);
+      }
       // Update |current_col_index| to reflect the next available index after
       // this cell including its colspan. The next column index in this row
       // must be at least this large. Same for the current ARIA col index.
diff --git a/ui/accessibility/ax_table_info.h b/ui/accessibility/ax_table_info.h
index 030f8e3..3cc67d0 100644
--- a/ui/accessibility/ax_table_info.h
+++ b/ui/accessibility/ax_table_info.h
@@ -9,6 +9,7 @@
 #include <unordered_map>
 #include <vector>
 
+#include "base/optional.h"
 #include "ui/accessibility/ax_export.h"
 
 namespace ui {
@@ -62,6 +63,9 @@
   // All header cells.
   std::vector<int32_t> all_headers;
 
+  // The id of the element with the caption tag or ARIA role.
+  int32_t caption_id;
+
   // 2-D array of [row][column] -> cell node ID.
   // This may contain duplicates if there is a rowspan or
   // colspan. The entry is empty (zero) only if the cell
@@ -87,8 +91,8 @@
 
   // The ARIA row count and column count, if any ARIA table or grid
   // attributes are used in the table at all.
-  int32_t aria_row_count = 0;
-  int32_t aria_col_count = 0;
+  base::Optional<int32_t> aria_row_count = 0;
+  base::Optional<int32_t> aria_col_count = 0;
 
  private:
   AXTableInfo(AXTree* tree, AXNode* table_node);
diff --git a/ui/accessibility/mojom/BUILD.gn b/ui/accessibility/mojom/BUILD.gn
index 65d4a61..1f67d5a 100644
--- a/ui/accessibility/mojom/BUILD.gn
+++ b/ui/accessibility/mojom/BUILD.gn
@@ -19,6 +19,7 @@
 
   public_deps = [
     "//mojo/public/mojom/base",
+    "//ui/accessibility:ax_constants_mojo",
     "//ui/accessibility:ax_enums_mojo",
     "//ui/gfx/geometry/mojo",
     "//ui/gfx/mojo",
diff --git a/ui/accessibility/platform/ax_platform_node_auralinux.cc b/ui/accessibility/platform/ax_platform_node_auralinux.cc
index 89eb3f33a..9cf8e576 100644
--- a/ui/accessibility/platform/ax_platform_node_auralinux.cc
+++ b/ui/accessibility/platform/ax_platform_node_auralinux.cc
@@ -17,6 +17,8 @@
 #include "base/no_destructor.h"
 #include "base/optional.h"
 #include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
 #include "base/strings/sys_string_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "ui/accessibility/ax_action_data.h"
@@ -1366,6 +1368,199 @@
     nullptr};
 
 //
+// AtkTable interface.
+//
+
+static AtkObject* AXPlatformNodeAuraLinuxRefAt(AtkTable* table,
+                                               gint row,
+                                               gint column) {
+  if (auto* obj = AtkObjectToAXPlatformNodeAuraLinux(ATK_OBJECT(table))) {
+    if (AXPlatformNodeBase* cell = obj->GetTableCell(row, column)) {
+      if (AtkObject* atk_cell = cell->GetNativeViewAccessible()) {
+        g_object_ref(atk_cell);
+        return atk_cell;
+      }
+    }
+  }
+
+  return nullptr;
+}
+
+static gint AXPlatformNodeAuraLinuxGetIndexAt(AtkTable* table,
+                                              gint row,
+                                              gint column) {
+  if (auto* obj = AtkObjectToAXPlatformNodeAuraLinux(ATK_OBJECT(table))) {
+    if (auto* cell = obj->GetTableCell(row, column))
+      return cell->GetTableCellIndex();
+  }
+
+  return -1;
+}
+
+static gint AXPlatformNodeAuraLinuxGetColumnAtIndex(AtkTable* table,
+                                                    gint index) {
+  if (auto* obj = AtkObjectToAXPlatformNodeAuraLinux(ATK_OBJECT(table))) {
+    if (auto* cell = obj->GetTableCell(index))
+      return cell->GetTableColumn();
+  }
+
+  return -1;
+}
+
+static gint AXPlatformNodeAuraLinuxGetRowAtIndex(AtkTable* table, gint index) {
+  if (auto* obj = AtkObjectToAXPlatformNodeAuraLinux(ATK_OBJECT(table))) {
+    if (auto* cell = obj->GetTableCell(index))
+      return cell->GetTableRow();
+  }
+
+  return -1;
+}
+
+static gint AXPlatformNodeAuraLinuxGetNColumns(AtkTable* table) {
+  if (auto* obj = AtkObjectToAXPlatformNodeAuraLinux(ATK_OBJECT(table)))
+    return obj->GetTableColumnCount();
+
+  return 0;
+}
+
+static gint AXPlatformNodeAuraLinuxGetNRows(AtkTable* table) {
+  if (auto* obj = AtkObjectToAXPlatformNodeAuraLinux(ATK_OBJECT(table)))
+    return obj->GetTableRowCount();
+
+  return 0;
+}
+
+static gint AXPlatformNodeAuraLinuxGetColumnExtentAt(AtkTable* table,
+                                                     gint row,
+                                                     gint column) {
+  if (auto* obj = AtkObjectToAXPlatformNodeAuraLinux(ATK_OBJECT(table))) {
+    if (auto* cell = obj->GetTableCell(row, column))
+      return cell->GetTableColumnSpan();
+  }
+
+  return 0;
+}
+
+static gint AXPlatformNodeAuraLinuxGetRowExtentAt(AtkTable* table,
+                                                  gint row,
+                                                  gint column) {
+  if (auto* obj = AtkObjectToAXPlatformNodeAuraLinux(ATK_OBJECT(table))) {
+    if (auto* cell = obj->GetTableCell(row, column))
+      return cell->GetTableRowSpan();
+  }
+
+  return 0;
+}
+
+static AtkObject* AXPlatformNodeAuraLinuxGetColumnHeader(AtkTable* table,
+                                                         gint column) {
+  auto* obj = AtkObjectToAXPlatformNodeAuraLinux(ATK_OBJECT(table));
+  if (!obj)
+    return nullptr;
+
+  // AtkTable supports only one column header object. So return the first one
+  // we find. In the case of multiple headers, ATs can fall back on the column
+  // description.
+  std::vector<int32_t> ids = obj->GetDelegate()->GetColHeaderNodeIds(column);
+  for (const auto& node_id : ids) {
+    if (AXPlatformNode* header = obj->GetDelegate()->GetFromNodeID(node_id)) {
+      if (AtkObject* atk_header = header->GetNativeViewAccessible()) {
+        g_object_ref(atk_header);
+        return atk_header;
+      }
+    }
+  }
+
+  return nullptr;
+}
+
+static AtkObject* AXPlatformNodeAuraLinuxGetRowHeader(AtkTable* table,
+                                                      gint row) {
+  auto* obj = AtkObjectToAXPlatformNodeAuraLinux(ATK_OBJECT(table));
+  if (!obj)
+    return nullptr;
+
+  // AtkTable supports only one row header object. So return the first one
+  // we find. In the case of multiple headers, ATs can fall back on the row
+  // description.
+  std::vector<int32_t> ids = obj->GetDelegate()->GetRowHeaderNodeIds(row);
+  for (const auto& node_id : ids) {
+    if (AXPlatformNode* header = obj->GetDelegate()->GetFromNodeID(node_id)) {
+      if (AtkObject* atk_header = header->GetNativeViewAccessible()) {
+        g_object_ref(atk_header);
+        return atk_header;
+      }
+    }
+  }
+
+  return nullptr;
+}
+
+static AtkObject* AXPlatformNodeAuraLinuxGetCaption(AtkTable* table) {
+  if (auto* obj = AtkObjectToAXPlatformNodeAuraLinux(ATK_OBJECT(table))) {
+    if (auto* caption = obj->GetTableCaption())
+      return caption->GetNativeViewAccessible();
+  }
+
+  return nullptr;
+}
+
+static const gchar* BuildDescriptionFromHeaders(
+    AXPlatformNodeDelegate* delegate,
+    std::vector<int32_t>& ids) {
+  std::vector<std::string> names;
+  for (const auto& node_id : ids) {
+    if (AXPlatformNode* header = delegate->GetFromNodeID(node_id)) {
+      if (AtkObject* atk_header = header->GetNativeViewAccessible())
+        names.push_back(atk_object_get_name(atk_header));
+    }
+  }
+
+  std::string result = base::JoinString(names, " ");
+  return g_strdup(result.c_str());
+}
+
+static const gchar* AXPlatformNodeAuraLinuxGetColumnDescription(AtkTable* table,
+                                                                gint column) {
+  auto* obj = AtkObjectToAXPlatformNodeAuraLinux(ATK_OBJECT(table));
+  if (!obj)
+    return nullptr;
+
+  std::vector<int32_t> ids = obj->GetDelegate()->GetColHeaderNodeIds(column);
+  return BuildDescriptionFromHeaders(obj->GetDelegate(), ids);
+}
+
+static const gchar* AXPlatformNodeAuraLinuxGetRowDescription(AtkTable* table,
+                                                             gint row) {
+  auto* obj = AtkObjectToAXPlatformNodeAuraLinux(ATK_OBJECT(table));
+  if (!obj)
+    return nullptr;
+
+  std::vector<int32_t> ids = obj->GetDelegate()->GetRowHeaderNodeIds(row);
+  return BuildDescriptionFromHeaders(obj->GetDelegate(), ids);
+}
+
+static void AXTableInterfaceBaseInit(AtkTableIface* iface) {
+  iface->ref_at = AXPlatformNodeAuraLinuxRefAt;
+  iface->get_index_at = AXPlatformNodeAuraLinuxGetIndexAt;
+  iface->get_column_at_index = AXPlatformNodeAuraLinuxGetColumnAtIndex;
+  iface->get_row_at_index = AXPlatformNodeAuraLinuxGetRowAtIndex;
+  iface->get_n_columns = AXPlatformNodeAuraLinuxGetNColumns;
+  iface->get_n_rows = AXPlatformNodeAuraLinuxGetNRows;
+  iface->get_column_extent_at = AXPlatformNodeAuraLinuxGetColumnExtentAt;
+  iface->get_row_extent_at = AXPlatformNodeAuraLinuxGetRowExtentAt;
+  iface->get_column_header = AXPlatformNodeAuraLinuxGetColumnHeader;
+  iface->get_row_header = AXPlatformNodeAuraLinuxGetRowHeader;
+  iface->get_caption = AXPlatformNodeAuraLinuxGetCaption;
+  iface->get_column_description = AXPlatformNodeAuraLinuxGetColumnDescription;
+  iface->get_row_description = AXPlatformNodeAuraLinuxGetRowDescription;
+}
+
+static const GInterfaceInfo TableInfo = {
+    reinterpret_cast<GInterfaceInitFunc>(AXTableInterfaceBaseInit), nullptr,
+    nullptr};
+
+//
 // The rest of the AXPlatformNodeAtk code, not specific to one
 // of the Atk* interfaces.
 //
@@ -1490,6 +1685,9 @@
   if (IsContainerWithSelectableChildren(GetData().role))
     interface_mask |= 1 << ATK_SELECTION_INTERFACE;
 
+  if (role == ATK_ROLE_TABLE)
+    interface_mask |= 1 << ATK_TABLE_INTERFACE;
+
   return interface_mask;
 }
 
@@ -1535,6 +1733,8 @@
     g_type_add_interface_static(type, ATK_TYPE_WINDOW, &WindowInfo);
   if (interface_mask_ & (1 << ATK_SELECTION_INTERFACE))
     g_type_add_interface_static(type, ATK_TYPE_SELECTION, &SelectionInfo);
+  if (interface_mask_ & (1 << ATK_TABLE_INTERFACE))
+    g_type_add_interface_static(type, ATK_TYPE_TABLE, &TableInfo);
 
   return type;
 }
@@ -2260,6 +2460,73 @@
     dict->SetString(attribute->name, attribute->value);
   }
   atk_attribute_set_free(attributes);
+
+  // Properties obtained via AtkTable.
+  auto table_properties = std::make_unique<base::ListValue>();
+  if (ATK_IS_TABLE(atk_object_)) {
+    AtkTable* table = ATK_TABLE(atk_object_);
+
+    // Column details.
+    int n_cols = atk_table_get_n_columns(table);
+    table_properties->AppendString(base::StringPrintf("cols=%i", n_cols));
+
+    std::vector<std::string> col_headers;
+    for (int i = 0; i < n_cols; i++) {
+      std::string header = atk_table_get_column_description(table, i);
+      if (!header.empty())
+        col_headers.push_back(base::StringPrintf("'%s'", header.c_str()));
+    }
+
+    if (!col_headers.size())
+      col_headers.push_back("NONE");
+
+    table_properties->AppendString(base::StringPrintf(
+        "headers=(%s);", base::JoinString(col_headers, ", ").c_str()));
+
+    // Row details.
+    int n_rows = atk_table_get_n_rows(table);
+    table_properties->AppendString(base::StringPrintf("rows=%i", n_rows));
+
+    std::vector<std::string> row_headers;
+    for (int i = 0; i < n_rows; i++) {
+      std::string header = atk_table_get_row_description(table, i);
+      if (!header.empty())
+        row_headers.push_back(base::StringPrintf("'%s'", header.c_str()));
+    }
+
+    if (!row_headers.size())
+      row_headers.push_back("NONE");
+
+    table_properties->AppendString(base::StringPrintf(
+        "headers=(%s);", base::JoinString(row_headers, ", ").c_str()));
+
+    // Caption details.
+    AtkObject* caption = atk_table_get_caption(table);
+    table_properties->AppendString(
+        base::StringPrintf("caption=%s;", caption ? "true" : "false"));
+
+    // Summarize information about the cells from the table's perspective here.
+    // TODO(jdiggs): When AtkTableCell is implemented, we will use it to output
+    // specifics on a per-cell basis.
+    std::vector<std::string> span_info;
+    for (int r = 0; r < n_rows; r++) {
+      for (int c = 0; c < n_cols; c++) {
+        int row_span = atk_table_get_row_extent_at(table, r, c);
+        int col_span = atk_table_get_column_extent_at(table, r, c);
+        if (row_span != 1 || col_span != 1) {
+          span_info.push_back(base::StringPrintf("cell at %i,%i: %ix%i", r, c,
+                                                 row_span, col_span));
+        }
+      }
+    }
+    if (!span_info.size())
+      span_info.push_back("all: 1x1");
+
+    table_properties->AppendString(base::StringPrintf(
+        "spans=(%s)", base::JoinString(span_info, ", ").c_str()));
+  }
+
+  dict->Set("table", std::move(table_properties));
 }
 
 gfx::NativeViewAccessible AXPlatformNodeAuraLinux::GetNativeViewAccessible() {
diff --git a/ui/accessibility/platform/ax_platform_node_base.cc b/ui/accessibility/platform/ax_platform_node_base.cc
index ba8e8392..ecf80a0 100644
--- a/ui/accessibility/platform/ax_platform_node_base.cc
+++ b/ui/accessibility/platform/ax_platform_node_base.cc
@@ -427,6 +427,18 @@
   return table;
 }
 
+AXPlatformNodeBase* AXPlatformNodeBase::GetTableCaption() const {
+  if (!delegate_)
+    return nullptr;
+
+  AXPlatformNodeBase* table = GetTable();
+  if (!table)
+    return nullptr;
+
+  DCHECK(table->delegate_);
+  return static_cast<AXPlatformNodeBase*>(table->delegate_->GetTableCaption());
+}
+
 AXPlatformNodeBase* AXPlatformNodeBase::GetTableCell(int index) const {
   if (!delegate_)
     return nullptr;
@@ -486,6 +498,18 @@
   return int{table->delegate_->GetTableColCount()};
 }
 
+base::Optional<int32_t> AXPlatformNodeBase::GetTableAriaColumnCount() const {
+  if (!delegate_)
+    return base::nullopt;
+
+  AXPlatformNodeBase* table = GetTable();
+  if (!table)
+    return base::nullopt;
+
+  DCHECK(table->delegate_);
+  return table->delegate_->GetTableAriaColCount();
+}
+
 int AXPlatformNodeBase::GetTableColumnSpan() const {
   if (!delegate_)
     return 1;
@@ -514,6 +538,18 @@
   return int{table->delegate_->GetTableRowCount()};
 }
 
+base::Optional<int32_t> AXPlatformNodeBase::GetTableAriaRowCount() const {
+  if (!delegate_)
+    return base::nullopt;
+
+  AXPlatformNodeBase* table = GetTable();
+  if (!table)
+    return base::nullopt;
+
+  DCHECK(table->delegate_);
+  return table->delegate_->GetTableAriaRowCount();
+}
+
 int AXPlatformNodeBase::GetTableRowSpan() const {
   if (!delegate_)
     return 1;
diff --git a/ui/accessibility/platform/ax_platform_node_base.h b/ui/accessibility/platform/ax_platform_node_base.h
index 0b2b491..1b93da5 100644
--- a/ui/accessibility/platform/ax_platform_node_base.h
+++ b/ui/accessibility/platform/ax_platform_node_base.h
@@ -112,6 +112,9 @@
   // Returns the table or ARIA grid if inside one.
   AXPlatformNodeBase* GetTable() const;
 
+  // If inside an HTML or ARIA table, returns the object containing the caption.
+  AXPlatformNodeBase* GetTableCaption() const;
+
   // If inside a table or ARIA grid, returns the cell found at the given index.
   // Indices are in row major order and each cell is counted once regardless of
   // its span.
@@ -137,6 +140,10 @@
   // otherwise returns 0.
   int GetTableColumnCount() const;
 
+  // If inside a table or ARIA grid, returns the number of ARIA columns,
+  // otherwise returns nullopt.
+  base::Optional<int32_t> GetTableAriaColumnCount() const;
+
   // If inside a table or ARIA grid, returns the number of physical columns that
   // this cell spans. If not a cell, returns 0.
   int GetTableColumnSpan() const;
@@ -151,6 +158,10 @@
   // otherwise returns 0.
   int GetTableRowCount() const;
 
+  // If inside a table or ARIA grid, returns the number of ARIA rows,
+  // otherwise returns nullopt.
+  base::Optional<int32_t> GetTableAriaRowCount() const;
+
   // If inside a table or ARIA grid, returns the number of physical rows that
   // this cell spans. If not a cell, returns 0.
   int GetTableRowSpan() const;
diff --git a/ui/accessibility/platform/ax_platform_node_delegate.h b/ui/accessibility/platform/ax_platform_node_delegate.h
index 3cc239d2..7596667 100644
--- a/ui/accessibility/platform/ax_platform_node_delegate.h
+++ b/ui/accessibility/platform/ax_platform_node_delegate.h
@@ -95,6 +95,9 @@
   // Get whether this node is offscreen.
   virtual bool IsOffscreen() const = 0;
 
+  // Get whether this node is in web content.
+  virtual bool IsWebContent() const = 0;
+
   virtual AXPlatformNode* GetFromNodeID(int32_t id) = 0;
 
   // Given a node ID attribute (one where IsNodeIdIntAttribute is true), return
@@ -130,8 +133,8 @@
   virtual bool IsTable() const = 0;
   virtual int32_t GetTableColCount() const = 0;
   virtual int32_t GetTableRowCount() const = 0;
-  virtual int32_t GetTableAriaColCount() const = 0;
-  virtual int32_t GetTableAriaRowCount() const = 0;
+  virtual base::Optional<int32_t> GetTableAriaColCount() const = 0;
+  virtual base::Optional<int32_t> GetTableAriaRowCount() const = 0;
   virtual int32_t GetTableCellCount() const = 0;
   virtual const std::vector<int32_t> GetColHeaderNodeIds() const = 0;
   virtual const std::vector<int32_t> GetColHeaderNodeIds(
@@ -139,6 +142,7 @@
   virtual const std::vector<int32_t> GetRowHeaderNodeIds() const = 0;
   virtual const std::vector<int32_t> GetRowHeaderNodeIds(
       int32_t row_index) const = 0;
+  virtual AXPlatformNode* GetTableCaption() = 0;
 
   // Table row-like nodes.
   virtual bool IsTableRow() const = 0;
diff --git a/ui/accessibility/platform/ax_platform_node_delegate_base.cc b/ui/accessibility/platform/ax_platform_node_delegate_base.cc
index 8fab20f..bb661c84 100644
--- a/ui/accessibility/platform/ax_platform_node_delegate_base.cc
+++ b/ui/accessibility/platform/ax_platform_node_delegate_base.cc
@@ -7,6 +7,7 @@
 #include <vector>
 
 #include "base/no_destructor.h"
+#include "ui/accessibility/ax_constants.mojom.h"
 #include "ui/accessibility/ax_node_data.h"
 #include "ui/accessibility/ax_role_properties.h"
 #include "ui/accessibility/ax_tree_data.h"
@@ -85,12 +86,22 @@
   return GetData().GetIntAttribute(ax::mojom::IntAttribute::kTableColumnCount);
 }
 
-int32_t AXPlatformNodeDelegateBase::GetTableAriaColCount() const {
-  return GetData().GetIntAttribute(ax::mojom::IntAttribute::kAriaColumnCount);
+base::Optional<int32_t> AXPlatformNodeDelegateBase::GetTableAriaColCount()
+    const {
+  int32_t aria_column_count =
+      GetData().GetIntAttribute(ax::mojom::IntAttribute::kAriaColumnCount);
+  if (aria_column_count == ax::mojom::kUnknownAriaColumnOrRowCount)
+    return base::nullopt;
+  return aria_column_count;
 }
 
-int32_t AXPlatformNodeDelegateBase::GetTableAriaRowCount() const {
-  return GetData().GetIntAttribute(ax::mojom::IntAttribute::kAriaRowCount);
+base::Optional<int32_t> AXPlatformNodeDelegateBase::GetTableAriaRowCount()
+    const {
+  int32_t aria_row_count =
+      GetData().GetIntAttribute(ax::mojom::IntAttribute::kAriaRowCount);
+  if (aria_row_count == ax::mojom::kUnknownAriaColumnOrRowCount)
+    return base::nullopt;
+  return aria_row_count;
 }
 
 int32_t AXPlatformNodeDelegateBase::GetTableCellCount() const {
@@ -117,6 +128,10 @@
   return {};
 }
 
+AXPlatformNode* AXPlatformNodeDelegateBase::GetTableCaption() {
+  return nullptr;
+}
+
 bool AXPlatformNodeDelegateBase::IsTableRow() const {
   return ui::IsTableRow(GetData().role);
 }
@@ -194,6 +209,10 @@
   return false;
 }
 
+bool AXPlatformNodeDelegateBase::IsWebContent() const {
+  return false;
+}
+
 AXPlatformNode* AXPlatformNodeDelegateBase::GetTargetNodeForRelation(
     ax::mojom::IntAttribute attr) {
   DCHECK(IsNodeIdIntAttribute(attr));
diff --git a/ui/accessibility/platform/ax_platform_node_delegate_base.h b/ui/accessibility/platform/ax_platform_node_delegate_base.h
index 726dfc0..87117aa 100644
--- a/ui/accessibility/platform/ax_platform_node_delegate_base.h
+++ b/ui/accessibility/platform/ax_platform_node_delegate_base.h
@@ -73,6 +73,9 @@
   // Get whether this node is offscreen.
   bool IsOffscreen() const override;
 
+  // Get whether this node is in web content.
+  bool IsWebContent() const override;
+
   AXPlatformNode* GetFromNodeID(int32_t id) override;
 
   // Given a node ID attribute (one where IsNodeIdIntAttribute is true), return
@@ -108,8 +111,8 @@
   bool IsTable() const override;
   int32_t GetTableColCount() const override;
   int32_t GetTableRowCount() const override;
-  int32_t GetTableAriaColCount() const override;
-  int32_t GetTableAriaRowCount() const override;
+  base::Optional<int32_t> GetTableAriaColCount() const override;
+  base::Optional<int32_t> GetTableAriaRowCount() const override;
   int32_t GetTableCellCount() const override;
   const std::vector<int32_t> GetColHeaderNodeIds() const override;
   const std::vector<int32_t> GetColHeaderNodeIds(
@@ -117,6 +120,7 @@
   const std::vector<int32_t> GetRowHeaderNodeIds() const override;
   const std::vector<int32_t> GetRowHeaderNodeIds(
       int32_t row_index) const override;
+  AXPlatformNode* GetTableCaption() override;
 
   // Table row-like nodes.
   bool IsTableRow() const override;
diff --git a/ui/accessibility/platform/ax_platform_node_unittest.cc b/ui/accessibility/platform/ax_platform_node_unittest.cc
index 672f874f..1b7d06b 100644
--- a/ui/accessibility/platform/ax_platform_node_unittest.cc
+++ b/ui/accessibility/platform/ax_platform_node_unittest.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "ui/accessibility/platform/ax_platform_node_unittest.h"
+#include "ui/accessibility/ax_constants.mojom.h"
 
 namespace ui {
 
@@ -283,4 +284,67 @@
   return update;
 }
 
+AXTreeUpdate AXPlatformNodeTest::BuildAriaColumnAndRowCountGrids() {
+  AXNodeData root;
+  root.id = 1;
+  root.role = ax::mojom::Role::kNone;
+
+  // Empty Grid
+  AXNodeData empty_grid;
+  empty_grid.id = 2;
+  empty_grid.role = ax::mojom::Role::kGrid;
+  root.child_ids.push_back(empty_grid.id);
+
+  // Grid with a cell that defines aria-rowindex (4) and aria-colindex (5)
+  AXNodeData rowcolindex_grid;
+  rowcolindex_grid.id = 3;
+  rowcolindex_grid.role = ax::mojom::Role::kGrid;
+  root.child_ids.push_back(rowcolindex_grid.id);
+
+  AXNodeData rowcolindex_row;
+  rowcolindex_row.id = 4;
+  rowcolindex_row.role = ax::mojom::Role::kRow;
+  rowcolindex_grid.child_ids.push_back(rowcolindex_row.id);
+
+  AXNodeData rowcolindex_cell;
+  rowcolindex_cell.id = 5;
+  rowcolindex_cell.role = ax::mojom::Role::kCell;
+  rowcolindex_cell.AddIntAttribute(
+      ax::mojom::IntAttribute::kAriaCellColumnIndex, 5);
+  rowcolindex_cell.AddIntAttribute(ax::mojom::IntAttribute::kAriaCellRowIndex,
+                                   4);
+  rowcolindex_row.child_ids.push_back(rowcolindex_cell.id);
+
+  // Grid that specifies aria-rowcount (2) and aria-colcount (3)
+  AXNodeData rowcolcount_grid;
+  rowcolcount_grid.id = 6;
+  rowcolcount_grid.role = ax::mojom::Role::kGrid;
+  rowcolcount_grid.AddIntAttribute(ax::mojom::IntAttribute::kAriaRowCount, 2);
+  rowcolcount_grid.AddIntAttribute(ax::mojom::IntAttribute::kAriaColumnCount,
+                                   3);
+  root.child_ids.push_back(rowcolcount_grid.id);
+
+  // Grid that specifies aria-rowcount and aria-colcount are (-1)
+  // ax::mojom::kUnknownAriaColumnOrRowCount
+  AXNodeData unknown_grid;
+  unknown_grid.id = 7;
+  unknown_grid.role = ax::mojom::Role::kGrid;
+  unknown_grid.AddIntAttribute(ax::mojom::IntAttribute::kAriaRowCount,
+                               ax::mojom::kUnknownAriaColumnOrRowCount);
+  unknown_grid.AddIntAttribute(ax::mojom::IntAttribute::kAriaColumnCount,
+                               ax::mojom::kUnknownAriaColumnOrRowCount);
+  root.child_ids.push_back(unknown_grid.id);
+
+  AXTreeUpdate update;
+  update.root_id = root.id;
+  update.nodes.push_back(root);
+  update.nodes.push_back(empty_grid);
+  update.nodes.push_back(rowcolindex_grid);
+  update.nodes.push_back(rowcolindex_row);
+  update.nodes.push_back(rowcolindex_cell);
+  update.nodes.push_back(rowcolcount_grid);
+  update.nodes.push_back(unknown_grid);
+  return update;
+}
+
 }  // namespace ui
diff --git a/ui/accessibility/platform/ax_platform_node_unittest.h b/ui/accessibility/platform/ax_platform_node_unittest.h
index d2f8189..c84d292 100644
--- a/ui/accessibility/platform/ax_platform_node_unittest.h
+++ b/ui/accessibility/platform/ax_platform_node_unittest.h
@@ -41,6 +41,7 @@
   AXTreeUpdate BuildContentEditableWithSelectionRange(int32_t start,
                                                       int32_t end);
   AXTreeUpdate Build3X3Table();
+  AXTreeUpdate BuildAriaColumnAndRowCountGrids();
 
   std::unique_ptr<AXTree> tree_;
 };
diff --git a/ui/accessibility/platform/ax_platform_node_win.cc b/ui/accessibility/platform/ax_platform_node_win.cc
index 9c5c982..79d1e38 100644
--- a/ui/accessibility/platform/ax_platform_node_win.cc
+++ b/ui/accessibility/platform/ax_platform_node_win.cc
@@ -1642,13 +1642,23 @@
 
 IFACEMETHODIMP AXPlatformNodeWin::get_RowCount(int* result) {
   UIA_VALIDATE_CALL_1_ARG(result);
-  *result = GetTableRowCount();
+
+  base::Optional<int32_t> row_count = GetTableAriaRowCount();
+  if (!row_count)
+    return E_UNEXPECTED;
+
+  *result = *row_count;
   return S_OK;
 }
 
 IFACEMETHODIMP AXPlatformNodeWin::get_ColumnCount(int* result) {
   UIA_VALIDATE_CALL_1_ARG(result);
-  *result = GetTableColumnCount();
+
+  base::Optional<int32_t> column_count = GetTableAriaColumnCount();
+  if (!column_count)
+    return E_UNEXPECTED;
+
+  *result = *column_count;
   return S_OK;
 }
 
@@ -1969,7 +1979,11 @@
 IFACEMETHODIMP AXPlatformNodeWin::get_RowOrColumnMajor(
     RowOrColumnMajor* result) {
   UIA_VALIDATE_CALL_1_ARG(result);
-  return E_NOTIMPL;
+
+  // Tables and ARIA grids are always in row major order
+  // see AXPlatformNodeBase::GetTableCell
+  *result = RowOrColumnMajor_RowMajor;
+  return S_OK;
 }
 
 //
@@ -2035,6 +2049,71 @@
 }
 
 //
+// IWindowProvider implementation.
+//
+
+IFACEMETHODIMP AXPlatformNodeWin::SetVisualState(
+    WindowVisualState window_visual_state) {
+  DVLOG(1) << __func__;
+  UIA_VALIDATE_CALL();
+  return UIA_E_NOTSUPPORTED;
+}
+
+IFACEMETHODIMP AXPlatformNodeWin::Close() {
+  DVLOG(1) << __func__;
+  UIA_VALIDATE_CALL();
+  return UIA_E_NOTSUPPORTED;
+}
+
+IFACEMETHODIMP AXPlatformNodeWin::WaitForInputIdle(int milliseconds,
+                                                   BOOL* result) {
+  DVLOG(1) << __func__;
+  UIA_VALIDATE_CALL_1_ARG(result);
+  return UIA_E_NOTSUPPORTED;
+}
+
+IFACEMETHODIMP AXPlatformNodeWin::get_CanMaximize(BOOL* result) {
+  DVLOG(1) << __func__;
+  UIA_VALIDATE_CALL_1_ARG(result);
+  return UIA_E_NOTSUPPORTED;
+}
+
+IFACEMETHODIMP AXPlatformNodeWin::get_CanMinimize(BOOL* result) {
+  DVLOG(1) << __func__;
+  UIA_VALIDATE_CALL_1_ARG(result);
+  return UIA_E_NOTSUPPORTED;
+}
+
+IFACEMETHODIMP AXPlatformNodeWin::get_IsModal(BOOL* result) {
+  DVLOG(1) << __func__;
+  UIA_VALIDATE_CALL_1_ARG(result);
+
+  *result = GetBoolAttribute(ax::mojom::BoolAttribute::kModal);
+
+  return S_OK;
+}
+
+IFACEMETHODIMP AXPlatformNodeWin::get_WindowVisualState(
+    WindowVisualState* result) {
+  DVLOG(1) << __func__;
+  UIA_VALIDATE_CALL_1_ARG(result);
+  return UIA_E_NOTSUPPORTED;
+}
+
+IFACEMETHODIMP AXPlatformNodeWin::get_WindowInteractionState(
+    WindowInteractionState* result) {
+  DVLOG(1) << __func__;
+  UIA_VALIDATE_CALL_1_ARG(result);
+  return UIA_E_NOTSUPPORTED;
+}
+
+IFACEMETHODIMP AXPlatformNodeWin::get_IsTopmost(BOOL* result) {
+  DVLOG(1) << __func__;
+  UIA_VALIDATE_CALL_1_ARG(result);
+  return UIA_E_NOTSUPPORTED;
+}
+
+//
 // IRangeValueProvider implementation.
 //
 
@@ -3475,6 +3554,10 @@
       break;
 
     case UIA_WindowPatternId:
+      if (HasBoolAttribute(ax::mojom::BoolAttribute::kModal)) {
+        AddRef();
+        *result = static_cast<IWindowProvider*>(this);
+      }
       break;
 
     // Overlap with MSAA, not supported.
@@ -3586,7 +3669,8 @@
 
     case UIA_IsContentElementPropertyId:
     case UIA_IsControlElementPropertyId:
-      // TODO(suproteem)
+      result->vt = VT_BOOL;
+      result->boolVal = IsUIAControl() ? VARIANT_TRUE : VARIANT_FALSE;
       break;
 
     case UIA_IsDataValidForFormPropertyId:
@@ -3624,6 +3708,17 @@
       break;
 
     case UIA_LabeledByPropertyId:
+      relation_attribute = ax::mojom::IntListAttribute::kLabelledbyIds;
+      for (int32_t id : GetIntListAttribute(relation_attribute)) {
+        auto* node_win = GetDelegate()->GetFromNodeID(id);
+        if (node_win) {
+          DCHECK(node_win);
+          result->vt = VT_UNKNOWN;
+          result->punkVal = node_win->GetNativeViewAccessible();
+          result->punkVal->AddRef();
+          break;
+        }
+      }
       break;
 
     case UIA_LocalizedControlTypePropertyId:
@@ -5171,7 +5266,7 @@
       // even if the node data isn't marked as read only, as long as the
       // node is not editable.
       if (!data.HasState(ax::mojom::State::kRichlyEditable) &&
-          ShouldNodeHaveReadonlyStateByDefault(data))
+          ShouldHaveReadonlyStateByDefault(data.role))
         properties.push_back(L"readonly=true");
       break;
   }
@@ -5728,6 +5823,60 @@
   return UIA_DocumentControlTypeId;
 }
 
+bool AXPlatformNodeWin::IsUIAControl() const {
+  // UIA provides multiple "views": raw, content and control. We only want to
+  // populate the content and control views with items that make sense to
+  // traverse over.
+  if (GetDelegate()->IsWebContent()) {
+    if (IsTextOnlyObject()) {
+      // A text leaf can be a UIAControl, but text inside of a heading, link,
+      // button, etc. where the role allows the name to be generated from the
+      // content is not. We want to avoid reading out a button, moving to the
+      // next item, and then reading out the button's text child, causing the
+      // text to be effectively repeated.
+      auto* parent = FromNativeViewAccessible(GetDelegate()->GetParent());
+      while (parent) {
+        const ui::AXNodeData& data = parent->GetData();
+        switch (data.role) {
+          case ax::mojom::Role::kButton:
+          case ax::mojom::Role::kCell:
+          case ax::mojom::Role::kCheckBox:
+          case ax::mojom::Role::kColumnHeader:
+          case ax::mojom::Role::kGroup:
+          case ax::mojom::Role::kHeading:
+          case ax::mojom::Role::kLineBreak:
+          case ax::mojom::Role::kLink:
+          case ax::mojom::Role::kListBoxOption:
+          case ax::mojom::Role::kListItem:
+          case ax::mojom::Role::kMenuItem:
+          case ax::mojom::Role::kMenuItemCheckBox:
+          case ax::mojom::Role::kMenuItemRadio:
+          case ax::mojom::Role::kMenuListOption:
+          case ax::mojom::Role::kRadioButton:
+          case ax::mojom::Role::kRow:
+          case ax::mojom::Role::kRowHeader:
+          case ax::mojom::Role::kStaticText:
+          case ax::mojom::Role::kSwitch:
+          case ax::mojom::Role::kTab:
+          case ax::mojom::Role::kTooltip:
+          case ax::mojom::Role::kTreeItem:
+            return false;
+          default:
+            break;
+        }
+        parent = FromNativeViewAccessible(parent->GetParent());
+      }
+    }
+    return true;
+  }
+  // non web-content case
+  const ui::AXNodeData& data = GetData();
+  return !(ui::ShouldHaveReadonlyStateByDefault(data.role) ||
+           data.GetRestriction() == ax::mojom::Restriction::kReadOnly ||
+           data.HasState(ax::mojom::State::kInvisible) ||
+           data.role == ax::mojom::Role::kIgnored);
+}
+
 base::string16 AXPlatformNodeWin::GetValue() const {
   base::string16 value = AXPlatformNodeBase::GetValue();
 
@@ -5742,41 +5891,6 @@
   return value;
 }
 
-bool AXPlatformNodeWin::ShouldNodeHaveReadonlyStateByDefault(
-    const AXNodeData& data) const {
-  switch (data.role) {
-    case ax::mojom::Role::kArticle:
-    case ax::mojom::Role::kDefinition:
-    case ax::mojom::Role::kDescriptionList:
-    case ax::mojom::Role::kDescriptionListTerm:
-    case ax::mojom::Role::kDocument:
-    case ax::mojom::Role::kGraphicsDocument:
-    case ax::mojom::Role::kImage:
-    case ax::mojom::Role::kImageMap:
-    case ax::mojom::Role::kList:
-    case ax::mojom::Role::kListItem:
-    case ax::mojom::Role::kProgressIndicator:
-    case ax::mojom::Role::kRootWebArea:
-    case ax::mojom::Role::kTerm:
-    case ax::mojom::Role::kTimer:
-    case ax::mojom::Role::kToolbar:
-    case ax::mojom::Role::kTooltip:
-    case ax::mojom::Role::kWebArea:
-      return true;
-
-    case ax::mojom::Role::kGrid:
-      // TODO(aleventhal) this changed between ARIA 1.0 and 1.1,
-      // need to determine whether grids/treegrids should really be readonly
-      // or editable by default
-      // msaa_state |= STATE_SYSTEM_READONLY;
-      break;
-
-    default:
-      break;
-  }
-  return false;
-}
-
 bool AXPlatformNodeWin::ShouldNodeHaveFocusableState(
     const AXNodeData& data) const {
   switch (data.role) {
@@ -5920,7 +6034,7 @@
       // even if the node data isn't marked as read only, as long as the
       // node is not editable.
       if (!data.HasState(ax::mojom::State::kRichlyEditable) &&
-          ShouldNodeHaveReadonlyStateByDefault(data))
+          ShouldHaveReadonlyStateByDefault(data.role))
         msaa_state |= STATE_SYSTEM_READONLY;
       break;
   }
diff --git a/ui/accessibility/platform/ax_platform_node_win.h b/ui/accessibility/platform/ax_platform_node_win.h
index 6f33fbf..97f5ddce 100644
--- a/ui/accessibility/platform/ax_platform_node_win.h
+++ b/ui/accessibility/platform/ax_platform_node_win.h
@@ -260,6 +260,7 @@
                         public ITableProvider,
                         public IToggleProvider,
                         public IValueProvider,
+                        public IWindowProvider,
                         public AXPlatformNodeBase {
  public:
   BEGIN_COM_MAP(AXPlatformNodeWin)
@@ -293,6 +294,7 @@
     COM_INTERFACE_ENTRY(ITableProvider)
     COM_INTERFACE_ENTRY(IToggleProvider)
     COM_INTERFACE_ENTRY(IValueProvider)
+    COM_INTERFACE_ENTRY(IWindowProvider)
     COM_INTERFACE_ENTRY(IServiceProvider)
   END_COM_MAP()
 
@@ -595,6 +597,29 @@
   IFACEMETHODIMP get_Value(BSTR* result) override;
 
   //
+  // IWindowProvider methods.
+  //
+
+  IFACEMETHODIMP SetVisualState(WindowVisualState window_visual_state) override;
+
+  IFACEMETHODIMP Close() override;
+
+  IFACEMETHODIMP WaitForInputIdle(int milliseconds, BOOL* result) override;
+
+  IFACEMETHODIMP get_CanMaximize(BOOL* result) override;
+
+  IFACEMETHODIMP get_CanMinimize(BOOL* result) override;
+
+  IFACEMETHODIMP get_IsModal(BOOL* result) override;
+
+  IFACEMETHODIMP get_WindowVisualState(WindowVisualState* result) override;
+
+  IFACEMETHODIMP get_WindowInteractionState(
+      WindowInteractionState* result) override;
+
+  IFACEMETHODIMP get_IsTopmost(BOOL* result) override;
+
+  //
   // IRangeValueProvider methods.
   //
 
@@ -887,6 +912,8 @@
 
   LONG ComputeUIAControlType();
 
+  bool IsUIAControl() const;
+
   // AXPlatformNodeBase overrides.
   void Dispose() override;
 
@@ -965,7 +992,6 @@
  private:
   int MSAAEvent(ax::mojom::Event event);
   bool IsWebAreaForPresentationalIframe();
-  bool ShouldNodeHaveReadonlyStateByDefault(const AXNodeData& data) const;
   bool ShouldNodeHaveFocusableState(const AXNodeData& data) const;
 
   HRESULT GetStringAttributeAsBstr(ax::mojom::StringAttribute attribute,
diff --git a/ui/accessibility/platform/ax_platform_node_win_unittest.cc b/ui/accessibility/platform/ax_platform_node_win_unittest.cc
index a966c1f..a095f3e 100644
--- a/ui/accessibility/platform/ax_platform_node_win_unittest.cc
+++ b/ui/accessibility/platform/ax_platform_node_win_unittest.cc
@@ -2900,6 +2900,224 @@
   EXPECT_EQ(2, offset);
 }
 
+TEST_F(AXPlatformNodeWinTest, TestIGridProviderGetRowCount) {
+  Init(BuildAriaColumnAndRowCountGrids());
+
+  // Empty Grid
+  ComPtr<IGridProvider> grid1_provider =
+      QueryInterfaceFromNode<IGridProvider>(GetRootNode()->children()[0]);
+
+  // Grid with a cell that defines aria-rowindex (4) and aria-colindex (5)
+  ComPtr<IGridProvider> grid2_provider =
+      QueryInterfaceFromNode<IGridProvider>(GetRootNode()->children()[1]);
+
+  // Grid that specifies aria-rowcount (2) and aria-colcount (3)
+  ComPtr<IGridProvider> grid3_provider =
+      QueryInterfaceFromNode<IGridProvider>(GetRootNode()->children()[2]);
+
+  // Grid that specifies aria-rowcount and aria-colcount are both (-1)
+  ComPtr<IGridProvider> grid4_provider =
+      QueryInterfaceFromNode<IGridProvider>(GetRootNode()->children()[3]);
+
+  int row_count;
+
+  EXPECT_HRESULT_SUCCEEDED(grid1_provider->get_RowCount(&row_count));
+  EXPECT_EQ(row_count, 0);
+
+  EXPECT_HRESULT_SUCCEEDED(grid2_provider->get_RowCount(&row_count));
+  EXPECT_EQ(row_count, 4);
+
+  EXPECT_HRESULT_SUCCEEDED(grid3_provider->get_RowCount(&row_count));
+  EXPECT_EQ(row_count, 2);
+
+  EXPECT_EQ(E_UNEXPECTED, grid4_provider->get_RowCount(&row_count));
+}
+
+TEST_F(AXPlatformNodeWinTest, TestIGridProviderGetColumnCount) {
+  Init(BuildAriaColumnAndRowCountGrids());
+
+  // Empty Grid
+  ComPtr<IGridProvider> grid1_provider =
+      QueryInterfaceFromNode<IGridProvider>(GetRootNode()->children()[0]);
+
+  // Grid with a cell that defines aria-rowindex (4) and aria-colindex (5)
+  ComPtr<IGridProvider> grid2_provider =
+      QueryInterfaceFromNode<IGridProvider>(GetRootNode()->children()[1]);
+
+  // Grid that specifies aria-rowcount (2) and aria-colcount (3)
+  ComPtr<IGridProvider> grid3_provider =
+      QueryInterfaceFromNode<IGridProvider>(GetRootNode()->children()[2]);
+
+  // Grid that specifies aria-rowcount and aria-colcount are both (-1)
+  ComPtr<IGridProvider> grid4_provider =
+      QueryInterfaceFromNode<IGridProvider>(GetRootNode()->children()[3]);
+
+  int column_count;
+
+  EXPECT_HRESULT_SUCCEEDED(grid1_provider->get_ColumnCount(&column_count));
+  EXPECT_EQ(column_count, 0);
+
+  EXPECT_HRESULT_SUCCEEDED(grid2_provider->get_ColumnCount(&column_count));
+  EXPECT_EQ(column_count, 5);
+
+  EXPECT_HRESULT_SUCCEEDED(grid3_provider->get_ColumnCount(&column_count));
+  EXPECT_EQ(column_count, 3);
+
+  EXPECT_EQ(E_UNEXPECTED, grid4_provider->get_ColumnCount(&column_count));
+}
+
+TEST_F(AXPlatformNodeWinTest, TestIGridProviderGetItem) {
+  AXNodeData root;
+  root.id = 1;
+  root.role = ax::mojom::Role::kGrid;
+  root.AddIntAttribute(ax::mojom::IntAttribute::kAriaRowCount, 1);
+  root.AddIntAttribute(ax::mojom::IntAttribute::kAriaColumnCount, 1);
+
+  AXNodeData row1;
+  row1.id = 2;
+  row1.role = ax::mojom::Role::kRow;
+  root.child_ids.push_back(row1.id);
+
+  AXNodeData cell1;
+  cell1.id = 3;
+  cell1.role = ax::mojom::Role::kCell;
+  row1.child_ids.push_back(cell1.id);
+
+  Init(root, row1, cell1);
+
+  ComPtr<IGridProvider> root_igridprovider(
+      QueryInterfaceFromNode<IGridProvider>(GetRootNode()));
+
+  ComPtr<IRawElementProviderSimple> cell1_irawelementprovidersimple(
+      QueryInterfaceFromNode<IRawElementProviderSimple>(
+          GetRootNode()->children()[0]->children()[0]));
+
+  IRawElementProviderSimple* grid_item = nullptr;
+  EXPECT_HRESULT_SUCCEEDED(root_igridprovider->GetItem(0, 0, &grid_item));
+  EXPECT_NE(nullptr, grid_item);
+  EXPECT_EQ(cell1_irawelementprovidersimple.Get(), grid_item);
+}
+
+TEST_F(AXPlatformNodeWinTest, TestITableProviderGetColumnHeaders) {
+  AXNodeData root;
+  root.id = 1;
+  root.role = ax::mojom::Role::kTable;
+
+  AXNodeData row1;
+  row1.id = 2;
+  row1.role = ax::mojom::Role::kRow;
+  root.child_ids.push_back(row1.id);
+
+  AXNodeData column_header;
+  column_header.id = 3;
+  column_header.role = ax::mojom::Role::kColumnHeader;
+  row1.child_ids.push_back(column_header.id);
+
+  AXNodeData row_header;
+  row_header.id = 4;
+  row_header.role = ax::mojom::Role::kRowHeader;
+  row1.child_ids.push_back(row_header.id);
+
+  Init(root, row1, column_header, row_header);
+
+  ComPtr<ITableProvider> root_itableprovider(
+      QueryInterfaceFromNode<ITableProvider>(GetRootNode()));
+
+  ComPtr<IRawElementProviderSimple> column_header_irawelementprovidersimple(
+      QueryInterfaceFromNode<IRawElementProviderSimple>(
+          GetRootNode()->children()[0]->children()[0]));
+
+  SAFEARRAY* safearray = nullptr;
+  EXPECT_HRESULT_SUCCEEDED(root_itableprovider->GetColumnHeaders(&safearray));
+  EXPECT_NE(nullptr, safearray);
+  EXPECT_EQ(1U, ::SafeArrayGetDim(safearray));
+  EXPECT_EQ(sizeof(IRawElementProviderSimple*),
+            ::SafeArrayGetElemsize(safearray));
+
+  long array_lbound;
+  EXPECT_HRESULT_SUCCEEDED(::SafeArrayGetLBound(safearray, 1, &array_lbound));
+  EXPECT_EQ(0, array_lbound);
+
+  long array_ubound;
+  EXPECT_HRESULT_SUCCEEDED(::SafeArrayGetUBound(safearray, 1, &array_ubound));
+  EXPECT_EQ(0, array_ubound);
+
+  long index = 0;
+  CComPtr<IRawElementProviderSimple> array_element;
+  EXPECT_HRESULT_SUCCEEDED(
+      ::SafeArrayGetElement(safearray, &index, &array_element));
+  EXPECT_NE(nullptr, array_element);
+  EXPECT_EQ(array_element, column_header_irawelementprovidersimple.Get());
+}
+
+TEST_F(AXPlatformNodeWinTest, TestITableProviderGetRowHeaders) {
+  AXNodeData root;
+  root.id = 1;
+  root.role = ax::mojom::Role::kTable;
+
+  AXNodeData row1;
+  row1.id = 2;
+  row1.role = ax::mojom::Role::kRow;
+  root.child_ids.push_back(row1.id);
+
+  AXNodeData column_header;
+  column_header.id = 3;
+  column_header.role = ax::mojom::Role::kColumnHeader;
+  row1.child_ids.push_back(column_header.id);
+
+  AXNodeData row_header;
+  row_header.id = 4;
+  row_header.role = ax::mojom::Role::kRowHeader;
+  row1.child_ids.push_back(row_header.id);
+
+  Init(root, row1, column_header, row_header);
+
+  ComPtr<ITableProvider> root_itableprovider(
+      QueryInterfaceFromNode<ITableProvider>(GetRootNode()));
+
+  ComPtr<IRawElementProviderSimple> row_header_irawelementprovidersimple(
+      QueryInterfaceFromNode<IRawElementProviderSimple>(
+          GetRootNode()->children()[0]->children()[1]));
+
+  SAFEARRAY* safearray = nullptr;
+  EXPECT_HRESULT_SUCCEEDED(root_itableprovider->GetRowHeaders(&safearray));
+  EXPECT_NE(nullptr, safearray);
+  EXPECT_EQ(1U, ::SafeArrayGetDim(safearray));
+  EXPECT_EQ(sizeof(IRawElementProviderSimple*),
+            ::SafeArrayGetElemsize(safearray));
+
+  long array_lbound;
+  EXPECT_HRESULT_SUCCEEDED(::SafeArrayGetLBound(safearray, 1, &array_lbound));
+  EXPECT_EQ(0, array_lbound);
+
+  long array_ubound;
+  EXPECT_HRESULT_SUCCEEDED(::SafeArrayGetUBound(safearray, 1, &array_ubound));
+  EXPECT_EQ(0, array_ubound);
+
+  long index = 0;
+  CComPtr<IRawElementProviderSimple> array_element;
+  EXPECT_HRESULT_SUCCEEDED(
+      ::SafeArrayGetElement(safearray, &index, &array_element));
+  EXPECT_NE(nullptr, array_element);
+  EXPECT_EQ(array_element, row_header_irawelementprovidersimple.Get());
+}
+
+TEST_F(AXPlatformNodeWinTest, TestITableProviderGetRowOrColumnMajor) {
+  AXNodeData root;
+  root.id = 1;
+  root.role = ax::mojom::Role::kTable;
+
+  Init(root);
+
+  ComPtr<ITableProvider> root_itableprovider(
+      QueryInterfaceFromNode<ITableProvider>(GetRootNode()));
+
+  RowOrColumnMajor row_or_column_major;
+  EXPECT_HRESULT_SUCCEEDED(
+      root_itableprovider->get_RowOrColumnMajor(&row_or_column_major));
+  EXPECT_EQ(row_or_column_major, RowOrColumnMajor_RowMajor);
+}
+
 TEST_F(AXPlatformNodeWinTest, TestUIAGetPropertySimple) {
   AXNodeData root;
   root.SetName("fake name");
@@ -3027,6 +3245,34 @@
                                    UIA_NamePropertyId, expected_names);
 }
 
+TEST_F(AXPlatformNodeWinTest, TestGetPropertyValue_LabeledByTest) {
+  AXNodeData root;
+  root.role = ax::mojom::Role::kListItem;
+  root.id = 1;
+  std::vector<int32_t> labeledby_ids = {2};
+  root.AddIntListAttribute(ax::mojom::IntListAttribute::kLabelledbyIds,
+                           labeledby_ids);
+
+  AXNodeData referenced_node;
+  referenced_node.SetName("Name");
+  referenced_node.role = ax::mojom::Role::kNone;
+  referenced_node.id = 2;
+
+  root.child_ids.push_back(referenced_node.id);
+  Init(root, referenced_node);
+
+  ComPtr<IRawElementProviderSimple> root_node =
+      GetRootIRawElementProviderSimple();
+  ScopedVariant propertyValue;
+  EXPECT_EQ(S_OK, root_node->GetPropertyValue(UIA_LabeledByPropertyId,
+                                              propertyValue.Receive()));
+  ASSERT_EQ(propertyValue.type(), VT_UNKNOWN);
+  ComPtr<IRawElementProviderSimple> referenced_element;
+  EXPECT_EQ(S_OK, propertyValue.ptr()->punkVal->QueryInterface(
+                      IID_PPV_ARGS(&referenced_element)));
+  EXPECT_UIA_BSTR_EQ(referenced_element, UIA_NamePropertyId, L"Name");
+}
+
 TEST_F(AXPlatformNodeWinTest, TestUIAGetProviderOptions) {
   AXNodeData root_data;
   Init(root_data);
@@ -3144,6 +3390,119 @@
   EXPECT_HRESULT_SUCCEEDED(::SafeArrayDestroy(runtime_id));
 }
 
+TEST_F(AXPlatformNodeWinTest, TestUIAIWindowProviderGetIsModalUnset) {
+  AXNodeData root;
+  root.id = 0;
+  root.role = ax::mojom::Role::kRootWebArea;
+  Init(root);
+
+  ComPtr<IRawElementProviderSimple> raw_element_provider_simple =
+      GetRootIRawElementProviderSimple();
+  ComPtr<IWindowProvider> window_provider;
+  EXPECT_HRESULT_SUCCEEDED(raw_element_provider_simple->GetPatternProvider(
+      UIA_WindowPatternId, &window_provider));
+  ASSERT_EQ(nullptr, window_provider.Get());
+}
+
+TEST_F(AXPlatformNodeWinTest, TestUIAIWindowProviderGetIsModalFalse) {
+  AXNodeData root;
+  root.id = 0;
+  root.role = ax::mojom::Role::kRootWebArea;
+  root.AddBoolAttribute(ax::mojom::BoolAttribute::kModal, false);
+  Init(root);
+
+  ComPtr<IRawElementProviderSimple> raw_element_provider_simple =
+      GetRootIRawElementProviderSimple();
+  ComPtr<IWindowProvider> window_provider;
+  EXPECT_HRESULT_SUCCEEDED(raw_element_provider_simple->GetPatternProvider(
+      UIA_WindowPatternId, &window_provider));
+  ASSERT_NE(nullptr, window_provider.Get());
+
+  BOOL is_modal;
+  EXPECT_HRESULT_SUCCEEDED(window_provider->get_IsModal(&is_modal));
+  ASSERT_FALSE(is_modal);
+}
+
+TEST_F(AXPlatformNodeWinTest, TestUIAIWindowProviderGetIsModalTrue) {
+  AXNodeData root;
+  root.id = 0;
+  root.role = ax::mojom::Role::kRootWebArea;
+  root.AddBoolAttribute(ax::mojom::BoolAttribute::kModal, true);
+  Init(root);
+
+  ComPtr<IRawElementProviderSimple> raw_element_provider_simple =
+      GetRootIRawElementProviderSimple();
+  ComPtr<IWindowProvider> window_provider;
+  EXPECT_HRESULT_SUCCEEDED(raw_element_provider_simple->GetPatternProvider(
+      UIA_WindowPatternId, &window_provider));
+  ASSERT_NE(nullptr, window_provider.Get());
+
+  BOOL is_modal;
+  EXPECT_HRESULT_SUCCEEDED(window_provider->get_IsModal(&is_modal));
+  ASSERT_TRUE(is_modal);
+}
+
+TEST_F(AXPlatformNodeWinTest, TestUIAIWindowProviderInvalidArgument) {
+  AXNodeData root;
+  root.id = 0;
+  root.role = ax::mojom::Role::kRootWebArea;
+  root.AddBoolAttribute(ax::mojom::BoolAttribute::kModal, true);
+  Init(root);
+
+  ComPtr<IRawElementProviderSimple> raw_element_provider_simple =
+      GetRootIRawElementProviderSimple();
+  ComPtr<IWindowProvider> window_provider;
+  EXPECT_HRESULT_SUCCEEDED(raw_element_provider_simple->GetPatternProvider(
+      UIA_WindowPatternId, &window_provider));
+  ASSERT_NE(nullptr, window_provider.Get());
+
+  ASSERT_EQ(E_INVALIDARG, window_provider->WaitForInputIdle(0, nullptr));
+  ASSERT_EQ(E_INVALIDARG, window_provider->get_CanMaximize(nullptr));
+  ASSERT_EQ(E_INVALIDARG, window_provider->get_CanMinimize(nullptr));
+  ASSERT_EQ(E_INVALIDARG, window_provider->get_IsModal(nullptr));
+  ASSERT_EQ(E_INVALIDARG, window_provider->get_WindowVisualState(nullptr));
+  ASSERT_EQ(E_INVALIDARG, window_provider->get_WindowInteractionState(nullptr));
+  ASSERT_EQ(E_INVALIDARG, window_provider->get_IsTopmost(nullptr));
+}
+
+TEST_F(AXPlatformNodeWinTest, TestUIAIWindowProviderNotSupported) {
+  AXNodeData root;
+  root.id = 0;
+  root.role = ax::mojom::Role::kRootWebArea;
+  root.AddBoolAttribute(ax::mojom::BoolAttribute::kModal, true);
+  Init(root);
+
+  ComPtr<IRawElementProviderSimple> raw_element_provider_simple =
+      GetRootIRawElementProviderSimple();
+  ComPtr<IWindowProvider> window_provider;
+  EXPECT_HRESULT_SUCCEEDED(raw_element_provider_simple->GetPatternProvider(
+      UIA_WindowPatternId, &window_provider));
+  ASSERT_NE(nullptr, window_provider.Get());
+
+  BOOL bool_result;
+  WindowVisualState window_visual_state_result;
+  WindowInteractionState window_interaction_state_result;
+
+  ASSERT_EQ(static_cast<HRESULT>(UIA_E_NOTSUPPORTED),
+            window_provider->SetVisualState(
+                WindowVisualState::WindowVisualState_Normal));
+  ASSERT_EQ(static_cast<HRESULT>(UIA_E_NOTSUPPORTED), window_provider->Close());
+  ASSERT_EQ(static_cast<HRESULT>(UIA_E_NOTSUPPORTED),
+            window_provider->WaitForInputIdle(0, &bool_result));
+  ASSERT_EQ(static_cast<HRESULT>(UIA_E_NOTSUPPORTED),
+            window_provider->get_CanMaximize(&bool_result));
+  ASSERT_EQ(static_cast<HRESULT>(UIA_E_NOTSUPPORTED),
+            window_provider->get_CanMinimize(&bool_result));
+  ASSERT_EQ(
+      static_cast<HRESULT>(UIA_E_NOTSUPPORTED),
+      window_provider->get_WindowVisualState(&window_visual_state_result));
+  ASSERT_EQ(static_cast<HRESULT>(UIA_E_NOTSUPPORTED),
+            window_provider->get_WindowInteractionState(
+                &window_interaction_state_result));
+  ASSERT_EQ(static_cast<HRESULT>(UIA_E_NOTSUPPORTED),
+            window_provider->get_IsTopmost(&bool_result));
+}
+
 TEST_F(AXPlatformNodeWinTest, TestUIANavigate) {
   AXNodeData root_data;
   root_data.id = 0;
@@ -3402,6 +3761,8 @@
       QueryInterfaceFromNode<IValueProvider>(GetRootNode());
   ComPtr<IRangeValueProvider> range_value_provider =
       QueryInterfaceFromNode<IRangeValueProvider>(GetRootNode());
+  ComPtr<IWindowProvider> window_provider =
+      QueryInterfaceFromNode<IWindowProvider>(GetRootNode());
 
   tree_.reset(new AXTree());
 
@@ -3555,6 +3916,27 @@
             toggle_provider->Toggle());
   EXPECT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
             toggle_provider->get_ToggleState(&toggle_state));
+
+  // IWindowProvider
+  ASSERT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
+            window_provider->SetVisualState(
+                WindowVisualState::WindowVisualState_Normal));
+  ASSERT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
+            window_provider->Close());
+  ASSERT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
+            window_provider->WaitForInputIdle(0, nullptr));
+  ASSERT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
+            window_provider->get_CanMaximize(nullptr));
+  ASSERT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
+            window_provider->get_CanMinimize(nullptr));
+  ASSERT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
+            window_provider->get_IsModal(nullptr));
+  ASSERT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
+            window_provider->get_WindowVisualState(nullptr));
+  ASSERT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
+            window_provider->get_WindowInteractionState(nullptr));
+  ASSERT_EQ(static_cast<HRESULT>(UIA_E_ELEMENTNOTAVAILABLE),
+            window_provider->get_IsTopmost(nullptr));
 }
 
 }  // namespace ui
diff --git a/ui/accessibility/platform/test_ax_node_wrapper.cc b/ui/accessibility/platform/test_ax_node_wrapper.cc
index ae328c9..4605c57 100644
--- a/ui/accessibility/platform/test_ax_node_wrapper.cc
+++ b/ui/accessibility/platform/test_ax_node_wrapper.cc
@@ -227,11 +227,11 @@
   return node_->GetTableColCount();
 }
 
-int TestAXNodeWrapper::GetTableAriaRowCount() const {
+base::Optional<int32_t> TestAXNodeWrapper::GetTableAriaRowCount() const {
   return node_->GetTableAriaRowCount();
 }
 
-int TestAXNodeWrapper::GetTableAriaColCount() const {
+base::Optional<int32_t> TestAXNodeWrapper::GetTableAriaColCount() const {
   return node_->GetTableAriaColCount();
 }
 
diff --git a/ui/accessibility/platform/test_ax_node_wrapper.h b/ui/accessibility/platform/test_ax_node_wrapper.h
index 9993b5d..01cdd73 100644
--- a/ui/accessibility/platform/test_ax_node_wrapper.h
+++ b/ui/accessibility/platform/test_ax_node_wrapper.h
@@ -53,8 +53,8 @@
   bool IsTable() const override;
   int GetTableRowCount() const override;
   int GetTableColCount() const override;
-  int GetTableAriaColCount() const override;
-  int GetTableAriaRowCount() const override;
+  base::Optional<int32_t> GetTableAriaColCount() const override;
+  base::Optional<int32_t> GetTableAriaRowCount() const override;
   int GetTableCellCount() const override;
   const std::vector<int32_t> GetColHeaderNodeIds() const override;
   const std::vector<int32_t> GetColHeaderNodeIds(
diff --git a/ui/aura/BUILD.gn b/ui/aura/BUILD.gn
index 434042f..59441b0 100644
--- a/ui/aura/BUILD.gn
+++ b/ui/aura/BUILD.gn
@@ -221,6 +221,10 @@
     ]
   }
 
+  if (is_win) {
+    libs = [ "wtsapi32.lib" ]
+  }
+
   if (use_ozone) {
     deps += [ "//ui/ozone" ]
     public += [ "screen_ozone.h" ]
diff --git a/ui/aura/native_window_occlusion_tracker_win.cc b/ui/aura/native_window_occlusion_tracker_win.cc
index 24b0fc5a..3d4a226 100644
--- a/ui/aura/native_window_occlusion_tracker_win.cc
+++ b/ui/aura/native_window_occlusion_tracker_win.cc
@@ -99,7 +99,10 @@
            base::TaskPriority::USER_VISIBLE,
            // Occlusion calculation doesn't need to happen on shutdown.
            // event hooks should also be cleaned up by Windows.
-           base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})) {
+           base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})),
+      session_change_observer_(
+          base::BindRepeating(&NativeWindowOcclusionTrackerWin::OnSessionChange,
+                              base::Unretained(this))) {
   occlusion_calculator_ = std::make_unique<WindowOcclusionCalculator>(
       update_occlusion_task_runner_, base::SequencedTaskRunnerHandle::Get());
 }
@@ -186,6 +189,19 @@
   }
 }
 
+void NativeWindowOcclusionTrackerWin::OnSessionChange(WPARAM status_code) {
+  if (status_code == WTS_SESSION_LOCK) {
+    // Tell all root windows that they're occluded.
+    for (const auto& root_window_hwnd_pair : hwnd_root_window_map_) {
+      root_window_hwnd_pair.second->GetHost()->SetNativeWindowOcclusionState(
+          Window::OcclusionState::OCCLUDED);
+    }
+  }
+  // Other session changes don't need to trigger occlusion calculation. In
+  // particular, UNLOCK will cause a foreground window change, which will
+  // trigger an occlusion calculation on its own.
+}
+
 NativeWindowOcclusionTrackerWin::WindowOcclusionCalculator::
     WindowOcclusionCalculator(
         scoped_refptr<base::SequencedTaskRunner> task_runner,
diff --git a/ui/aura/native_window_occlusion_tracker_win.h b/ui/aura/native_window_occlusion_tracker_win.h
index a6a5ae5..2c65f7dc 100644
--- a/ui/aura/native_window_occlusion_tracker_win.h
+++ b/ui/aura/native_window_occlusion_tracker_win.h
@@ -8,6 +8,7 @@
 #include <windows.h>
 #include <winuser.h>
 
+#include <memory>
 #include <vector>
 
 #include "base/containers/flat_map.h"
@@ -18,6 +19,7 @@
 #include "ui/aura/aura_export.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_observer.h"
+#include "ui/base/win/session_change_observer.h"
 
 namespace aura {
 
@@ -199,6 +201,10 @@
   void UpdateOcclusionState(const base::flat_map<HWND, Window::OcclusionState>&
                                 root_window_hwnds_occlusion_state);
 
+  // This is called with session changed notifications. If the screen is locked,
+  // it marks app windows as occluded.
+  void OnSessionChange(WPARAM status_code);
+
   // Task runner to call ComputeNativeWindowOcclusionStatus, and to handle
   // Windows event notifications, off of the UI thread.
   const scoped_refptr<base::SequencedTaskRunner> update_occlusion_task_runner_;
@@ -213,6 +219,9 @@
 
   std::unique_ptr<WindowOcclusionCalculator> occlusion_calculator_;
 
+  // Manages observation of Windows Session Change messages.
+  ui::SessionChangeObserver session_change_observer_;
+
   DISALLOW_COPY_AND_ASSIGN(NativeWindowOcclusionTrackerWin);
 };
 
diff --git a/ui/base/BUILD.gn b/ui/base/BUILD.gn
index 9c82c36..33dc6528 100644
--- a/ui/base/BUILD.gn
+++ b/ui/base/BUILD.gn
@@ -282,6 +282,8 @@
     "win/mouse_wheel_util.h",
     "win/scoped_ole_initializer.cc",
     "win/scoped_ole_initializer.h",
+    "win/session_change_observer.cc",
+    "win/session_change_observer.h",
     "win/shell.cc",
     "win/shell.h",
     "win/touch_input.cc",
@@ -345,7 +347,11 @@
   }
 
   if (is_mac) {
-    sources += [ "accelerators/media_keys_listener_mac.mm" ]
+    sources += [
+      "accelerators/media_keys_listener_mac.mm",
+      "accelerators/remote_command_media_keys_listener_mac.h",
+      "accelerators/remote_command_media_keys_listener_mac.mm",
+    ]
   } else if (is_win) {
     sources += [
       "accelerators/global_media_keys_listener_win.cc",
@@ -535,6 +541,7 @@
       "d2d1.lib",
       "dwmapi.lib",
       "oleacc.lib",
+      "wtsapi32.lib",
     ]
   } else {
     if (!use_aura) {
@@ -546,7 +553,10 @@
   }
 
   if (is_mac) {
-    deps += [ "//third_party/mozilla" ]
+    deps += [
+      "//third_party/mozilla",
+      "//ui/base/now_playing",
+    ]
 
     libs += [
       "Accelerate.framework",
@@ -825,6 +835,7 @@
 
 test("ui_base_unittests") {
   sources = [
+    "accelerators/remote_command_media_keys_listener_mac_unittest.mm",
     "class_property_unittest.cc",
     "l10n/l10n_util_mac_unittest.mm",
     "l10n/l10n_util_unittest.cc",
@@ -1019,6 +1030,7 @@
     deps += [
       ":ui_unittests_framework",
       "//third_party/mozilla",
+      "//ui/base/now_playing:test_support",
     ]
   }
 
diff --git a/ui/base/accelerators/media_keys_listener_mac.mm b/ui/base/accelerators/media_keys_listener_mac.mm
index b48fa8e6..fe6aa25 100644
--- a/ui/base/accelerators/media_keys_listener_mac.mm
+++ b/ui/base/accelerators/media_keys_listener_mac.mm
@@ -12,6 +12,7 @@
 
 #include "base/containers/flat_set.h"
 #include "ui/base/accelerators/accelerator.h"
+#include "ui/base/accelerators/remote_command_media_keys_listener_mac.h"
 
 namespace ui {
 
@@ -218,6 +219,17 @@
 std::unique_ptr<MediaKeysListener> MediaKeysListener::Create(
     MediaKeysListener::Delegate* delegate,
     MediaKeysListener::Scope scope) {
+  // For Mac OS 10.12.2 or later, we want to use MPRemoteCommandCenter for
+  // getting media keys globally.
+  if (@available(macOS 10.12.2, *)) {
+    if (scope == Scope::kGlobal) {
+      auto listener =
+          std::make_unique<RemoteCommandMediaKeysListenerMac>(delegate);
+      listener->Initialize();
+      return std::move(listener);
+    }
+  }
+
   return std::make_unique<MediaKeysListenerImpl>(delegate, scope);
 }
 
diff --git a/ui/base/accelerators/remote_command_media_keys_listener_mac.h b/ui/base/accelerators/remote_command_media_keys_listener_mac.h
new file mode 100644
index 0000000..e077175
--- /dev/null
+++ b/ui/base/accelerators/remote_command_media_keys_listener_mac.h
@@ -0,0 +1,70 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_BASE_ACCELERATORS_REMOTE_COMMAND_MEDIA_KEYS_LISTENER_MAC_H_
+#define UI_BASE_ACCELERATORS_REMOTE_COMMAND_MEDIA_KEYS_LISTENER_MAC_H_
+
+#include "base/containers/flat_set.h"
+#include "ui/base/accelerators/media_keys_listener.h"
+#include "ui/base/now_playing/remote_command_center_delegate_observer.h"
+#include "ui/base/ui_base_export.h"
+#include "ui/events/keycodes/keyboard_codes.h"
+
+namespace now_playing {
+class RemoteCommandCenterDelegate;
+}  // namespace now_playing
+
+namespace ui {
+
+// Implementation of MediaKeysListener that uses MPRemoteCommandCenter to
+// globally listen for media key presses. It only allows for a single instance
+// to be created in order to prevent conflicts from multiple listeners.
+class UI_BASE_EXPORT API_AVAILABLE(macos(10.12.2))
+    RemoteCommandMediaKeysListenerMac
+    : public MediaKeysListener,
+      public now_playing::RemoteCommandCenterDelegateObserver {
+ public:
+  explicit RemoteCommandMediaKeysListenerMac(
+      MediaKeysListener::Delegate* delegate);
+  ~RemoteCommandMediaKeysListenerMac() override;
+
+  static bool has_instance() { return has_instance_; }
+
+  // Connects with the RemoteCommandCenterDelegate.
+  void Initialize();
+
+  // MediaKeysListener implementation.
+  bool StartWatchingMediaKey(KeyboardCode key_code) override;
+  void StopWatchingMediaKey(KeyboardCode key_code) override;
+
+  // now_playing::RemoteCommandCenterDelegateObserver implementation.
+  void OnNext() override;
+  void OnPrevious() override;
+  void OnPause() override;
+  void OnPlayPause() override;
+  void OnStop() override;
+  void OnPlay() override;
+
+  void SetRemoteCommandCenterDelegateForTesting(
+      now_playing::RemoteCommandCenterDelegate* delegate) {
+    remote_command_center_delegate_ = delegate;
+  }
+
+ private:
+  static bool has_instance_;
+
+  // Sends |key_code| to the delegate if it's being listened to.
+  void MaybeSend(KeyboardCode key_code);
+
+  MediaKeysListener::Delegate* delegate_;
+  base::flat_set<KeyboardCode> key_codes_;
+  now_playing::RemoteCommandCenterDelegate* remote_command_center_delegate_ =
+      nullptr;
+
+  DISALLOW_COPY_AND_ASSIGN(RemoteCommandMediaKeysListenerMac);
+};
+
+}  // namespace ui
+
+#endif  // UI_BASE_ACCELERATORS_REMOTE_COMMAND_MEDIA_KEYS_LISTENER_MAC_H_
diff --git a/ui/base/accelerators/remote_command_media_keys_listener_mac.mm b/ui/base/accelerators/remote_command_media_keys_listener_mac.mm
new file mode 100644
index 0000000..ddcc5442
--- /dev/null
+++ b/ui/base/accelerators/remote_command_media_keys_listener_mac.mm
@@ -0,0 +1,125 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/base/accelerators/remote_command_media_keys_listener_mac.h"
+
+#include "base/mac/mac_util.h"
+#include "ui/base/accelerators/accelerator.h"
+#include "ui/base/now_playing/remote_command_center_delegate.h"
+
+namespace ui {
+
+// static
+bool RemoteCommandMediaKeysListenerMac::has_instance_ = false;
+
+RemoteCommandMediaKeysListenerMac::RemoteCommandMediaKeysListenerMac(
+    MediaKeysListener::Delegate* delegate)
+    : delegate_(delegate) {
+  DCHECK(delegate_);
+  DCHECK(!has_instance_);
+  has_instance_ = true;
+}
+
+RemoteCommandMediaKeysListenerMac::~RemoteCommandMediaKeysListenerMac() {
+  has_instance_ = false;
+}
+
+void RemoteCommandMediaKeysListenerMac::Initialize() {
+  if (!remote_command_center_delegate_) {
+    remote_command_center_delegate_ =
+        now_playing::RemoteCommandCenterDelegate::GetInstance();
+  }
+  DCHECK(remote_command_center_delegate_);
+
+  remote_command_center_delegate_->AddObserver(this);
+}
+
+bool RemoteCommandMediaKeysListenerMac::StartWatchingMediaKey(
+    KeyboardCode key_code) {
+  DCHECK(IsMediaKeycode(key_code));
+  DCHECK(remote_command_center_delegate_);
+
+  key_codes_.insert(key_code);
+
+  switch (key_code) {
+    case VKEY_MEDIA_PLAY_PAUSE:
+      remote_command_center_delegate_->SetCanPlay(true);
+      remote_command_center_delegate_->SetCanPause(true);
+      remote_command_center_delegate_->SetCanPlayPause(true);
+      break;
+    case VKEY_MEDIA_STOP:
+      remote_command_center_delegate_->SetCanStop(true);
+      break;
+    case VKEY_MEDIA_NEXT_TRACK:
+      remote_command_center_delegate_->SetCanGoNextTrack(true);
+      break;
+    case VKEY_MEDIA_PREV_TRACK:
+      remote_command_center_delegate_->SetCanGoPreviousTrack(true);
+      break;
+    default:
+      NOTREACHED();
+  }
+
+  return true;
+}
+
+void RemoteCommandMediaKeysListenerMac::StopWatchingMediaKey(
+    KeyboardCode key_code) {
+  DCHECK(IsMediaKeycode(key_code));
+  DCHECK(remote_command_center_delegate_);
+
+  key_codes_.erase(key_code);
+
+  switch (key_code) {
+    case VKEY_MEDIA_PLAY_PAUSE:
+      remote_command_center_delegate_->SetCanPlay(false);
+      remote_command_center_delegate_->SetCanPause(false);
+      remote_command_center_delegate_->SetCanPlayPause(false);
+      break;
+    case VKEY_MEDIA_STOP:
+      remote_command_center_delegate_->SetCanStop(false);
+      break;
+    case VKEY_MEDIA_NEXT_TRACK:
+      remote_command_center_delegate_->SetCanGoNextTrack(false);
+      break;
+    case VKEY_MEDIA_PREV_TRACK:
+      remote_command_center_delegate_->SetCanGoPreviousTrack(false);
+      break;
+    default:
+      NOTREACHED();
+  }
+}
+
+void RemoteCommandMediaKeysListenerMac::OnNext() {
+  MaybeSend(VKEY_MEDIA_NEXT_TRACK);
+}
+
+void RemoteCommandMediaKeysListenerMac::OnPrevious() {
+  MaybeSend(VKEY_MEDIA_PREV_TRACK);
+}
+
+void RemoteCommandMediaKeysListenerMac::OnPause() {
+  MaybeSend(VKEY_MEDIA_PLAY_PAUSE);
+}
+
+void RemoteCommandMediaKeysListenerMac::OnPlayPause() {
+  MaybeSend(VKEY_MEDIA_PLAY_PAUSE);
+}
+
+void RemoteCommandMediaKeysListenerMac::OnStop() {
+  MaybeSend(VKEY_MEDIA_STOP);
+}
+
+void RemoteCommandMediaKeysListenerMac::OnPlay() {
+  MaybeSend(VKEY_MEDIA_PLAY_PAUSE);
+}
+
+void RemoteCommandMediaKeysListenerMac::MaybeSend(KeyboardCode key_code) {
+  if (!key_codes_.contains(key_code))
+    return;
+
+  delegate_->OnMediaKeysAccelerator(Accelerator(key_code, /*modifiers=*/0));
+}
+
+}  // namespace ui
diff --git a/ui/base/accelerators/remote_command_media_keys_listener_mac_unittest.mm b/ui/base/accelerators/remote_command_media_keys_listener_mac_unittest.mm
new file mode 100644
index 0000000..123b3f00
--- /dev/null
+++ b/ui/base/accelerators/remote_command_media_keys_listener_mac_unittest.mm
@@ -0,0 +1,121 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/base/accelerators/remote_command_media_keys_listener_mac.h"
+
+#include "base/callback.h"
+#include "base/mac/scoped_cftyperef.h"
+#include "base/run_loop.h"
+#include "base/test/scoped_task_environment.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/accelerators/accelerator.h"
+#include "ui/base/now_playing/mock_remote_command_center_delegate.h"
+#include "ui/events/event.h"
+
+using testing::_;
+using testing::WithArg;
+
+namespace ui {
+
+namespace {
+
+class MockMediaKeysListenerDelegate : public MediaKeysListener::Delegate {
+ public:
+  MockMediaKeysListenerDelegate() = default;
+  ~MockMediaKeysListenerDelegate() override = default;
+
+  // MediaKeysListener::Delegate implementation.
+  MOCK_METHOD1(OnMediaKeysAccelerator, void(const Accelerator& accelerator));
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(MockMediaKeysListenerDelegate);
+};
+
+}  // anonymous namespace
+
+class RemoteCommandMediaKeysListenerMacTest : public testing::Test {
+ public:
+  RemoteCommandMediaKeysListenerMacTest() = default;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(RemoteCommandMediaKeysListenerMacTest);
+};
+
+TEST_F(RemoteCommandMediaKeysListenerMacTest, SimplePlayPauseTest) {
+  if (@available(macOS 10.12.2, *)) {
+    now_playing::MockRemoteCommandCenterDelegate rcc_delegate;
+    MockMediaKeysListenerDelegate delegate;
+    RemoteCommandMediaKeysListenerMac listener(&delegate);
+    listener.SetRemoteCommandCenterDelegateForTesting(&rcc_delegate);
+
+    EXPECT_CALL(rcc_delegate, AddObserver(&listener));
+    EXPECT_CALL(rcc_delegate, SetCanPlayPause(true));
+    EXPECT_CALL(delegate, OnMediaKeysAccelerator(_))
+        .WillOnce(WithArg<0>([](const Accelerator& accelerator) {
+          EXPECT_EQ(ui::VKEY_MEDIA_PLAY_PAUSE, accelerator.key_code());
+        }));
+
+    listener.Initialize();
+    listener.StartWatchingMediaKey(ui::VKEY_MEDIA_PLAY_PAUSE);
+
+    // Simulate media key press.
+    listener.OnPlayPause();
+  }
+}
+
+TEST_F(RemoteCommandMediaKeysListenerMacTest, KeyCanBeReRegistered) {
+  if (@available(macOS 10.12.2, *)) {
+    now_playing::MockRemoteCommandCenterDelegate rcc_delegate;
+    MockMediaKeysListenerDelegate delegate;
+    RemoteCommandMediaKeysListenerMac listener(&delegate);
+    listener.SetRemoteCommandCenterDelegateForTesting(&rcc_delegate);
+
+    EXPECT_CALL(rcc_delegate, AddObserver(&listener));
+    EXPECT_CALL(rcc_delegate, SetCanGoNextTrack(true)).Times(2);
+    EXPECT_CALL(rcc_delegate, SetCanGoNextTrack(false));
+    EXPECT_CALL(delegate, OnMediaKeysAccelerator(_))
+        .WillOnce(WithArg<0>([](const Accelerator& accelerator) {
+          EXPECT_EQ(ui::VKEY_MEDIA_NEXT_TRACK, accelerator.key_code());
+        }));
+
+    listener.Initialize();
+
+    // Start listening to register the key.
+    listener.StartWatchingMediaKey(ui::VKEY_MEDIA_NEXT_TRACK);
+
+    // Stop listening to unregister the key.
+    listener.StopWatchingMediaKey(ui::VKEY_MEDIA_NEXT_TRACK);
+
+    // Start listening to re-register the key.
+    listener.StartWatchingMediaKey(ui::VKEY_MEDIA_NEXT_TRACK);
+
+    // Simulate media key press.
+    listener.OnNext();
+  }
+}
+
+TEST_F(RemoteCommandMediaKeysListenerMacTest, ListenForMultipleKeys) {
+  if (@available(macOS 10.12.2, *)) {
+    now_playing::MockRemoteCommandCenterDelegate rcc_delegate;
+    MockMediaKeysListenerDelegate delegate;
+    RemoteCommandMediaKeysListenerMac listener(&delegate);
+    listener.SetRemoteCommandCenterDelegateForTesting(&rcc_delegate);
+
+    EXPECT_CALL(rcc_delegate, AddObserver(&listener));
+    EXPECT_CALL(rcc_delegate, SetCanPlayPause(true));
+    EXPECT_CALL(rcc_delegate, SetCanStop(true));
+    EXPECT_CALL(delegate, OnMediaKeysAccelerator(_)).Times(2);
+
+    listener.Initialize();
+    listener.StartWatchingMediaKey(ui::VKEY_MEDIA_PLAY_PAUSE);
+    listener.StartWatchingMediaKey(ui::VKEY_MEDIA_STOP);
+
+    // Simulate media key press.
+    listener.OnPlayPause();
+    listener.OnStop();
+  }
+}
+
+}  // namespace ui
diff --git a/ui/base/now_playing/BUILD.gn b/ui/base/now_playing/BUILD.gn
new file mode 100644
index 0000000..5f17a0e1c
--- /dev/null
+++ b/ui/base/now_playing/BUILD.gn
@@ -0,0 +1,42 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+component("now_playing") {
+  sources = [
+    "remote_command_center_delegate.cc",
+    "remote_command_center_delegate.h",
+    "remote_command_center_delegate_impl.h",
+    "remote_command_center_delegate_impl.mm",
+    "remote_command_center_delegate_ns.h",
+    "remote_command_center_delegate_ns.mm",
+    "remote_command_center_delegate_observer.cc",
+    "remote_command_center_delegate_observer.h",
+  ]
+
+  defines = [ "IS_NOW_PLAYING_IMPL" ]
+
+  deps = [
+    "//base",
+  ]
+
+  libs = [
+    "Foundation.framework",
+    "MediaPlayer.framework",
+  ]
+}
+
+static_library("test_support") {
+  testonly = true
+
+  sources = [
+    "mock_remote_command_center_delegate.cc",
+    "mock_remote_command_center_delegate.h",
+  ]
+
+  deps = [
+    ":now_playing",
+    "//base",
+    "//testing/gmock",
+  ]
+}
diff --git a/ui/base/now_playing/OWNERS b/ui/base/now_playing/OWNERS
new file mode 100644
index 0000000..c48e48e
--- /dev/null
+++ b/ui/base/now_playing/OWNERS
@@ -0,0 +1 @@
+steimel@chromium.org
diff --git a/ui/base/now_playing/README.md b/ui/base/now_playing/README.md
new file mode 100644
index 0000000..d4ddabf
--- /dev/null
+++ b/ui/base/now_playing/README.md
@@ -0,0 +1,10 @@
+This component is used to interface with Mac OS's MPNowPlayingInfoCenter and
+related MediaPlayer API:
+https://developer.apple.com/documentation/mediaplayer/mpnowplayinginfocenter
+
+This includes an interface for MPRemoteCommandCenter, which can be used to
+receive media-related user input (e.g. media keys and actions that are
+available through the MPNowPlayingInfoCenter such as repeat and rating).
+https://developer.apple.com/documentation/mediaplayer/mpremotecommandcenter
+
+Note that these APIs are only available on Mac OS 10.12.2 or later.
diff --git a/ui/base/now_playing/mock_remote_command_center_delegate.cc b/ui/base/now_playing/mock_remote_command_center_delegate.cc
new file mode 100644
index 0000000..a041e30
--- /dev/null
+++ b/ui/base/now_playing/mock_remote_command_center_delegate.cc
@@ -0,0 +1,13 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/base/now_playing/mock_remote_command_center_delegate.h"
+
+namespace now_playing {
+
+MockRemoteCommandCenterDelegate::MockRemoteCommandCenterDelegate() = default;
+
+MockRemoteCommandCenterDelegate::~MockRemoteCommandCenterDelegate() = default;
+
+}  // namespace now_playing
diff --git a/ui/base/now_playing/mock_remote_command_center_delegate.h b/ui/base/now_playing/mock_remote_command_center_delegate.h
new file mode 100644
index 0000000..45c8419
--- /dev/null
+++ b/ui/base/now_playing/mock_remote_command_center_delegate.h
@@ -0,0 +1,40 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_BASE_NOW_PLAYING_MOCK_REMOTE_COMMAND_CENTER_DELEGATE_H_
+#define UI_BASE_NOW_PLAYING_MOCK_REMOTE_COMMAND_CENTER_DELEGATE_H_
+
+#include "base/macros.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "ui/base/now_playing/remote_command_center_delegate.h"
+
+namespace now_playing {
+
+class RemoteCommandCenterDelegateObserver;
+
+// Mock implementation of RemoteCommandCenterDelegate for testing.
+class MockRemoteCommandCenterDelegate : public RemoteCommandCenterDelegate {
+ public:
+  MockRemoteCommandCenterDelegate();
+  ~MockRemoteCommandCenterDelegate();
+
+  // RemoteCommandCenterDelegate implementation.
+  MOCK_METHOD1(AddObserver,
+               void(RemoteCommandCenterDelegateObserver* observer));
+  MOCK_METHOD1(RemoveObserver,
+               void(RemoteCommandCenterDelegateObserver* observer));
+  MOCK_METHOD1(SetCanPlay, void(bool enable));
+  MOCK_METHOD1(SetCanPause, void(bool enable));
+  MOCK_METHOD1(SetCanStop, void(bool enable));
+  MOCK_METHOD1(SetCanPlayPause, void(bool enable));
+  MOCK_METHOD1(SetCanGoNextTrack, void(bool enable));
+  MOCK_METHOD1(SetCanGoPreviousTrack, void(bool enable));
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(MockRemoteCommandCenterDelegate);
+};
+
+}  // namespace now_playing
+
+#endif  // UI_BASE_NOW_PLAYING_MOCK_REMOTE_COMMAND_CENTER_DELEGATE_H_
diff --git a/ui/base/now_playing/remote_command_center_delegate.cc b/ui/base/now_playing/remote_command_center_delegate.cc
new file mode 100644
index 0000000..17e955a3
--- /dev/null
+++ b/ui/base/now_playing/remote_command_center_delegate.cc
@@ -0,0 +1,11 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/base/now_playing/remote_command_center_delegate.h"
+
+namespace now_playing {
+
+RemoteCommandCenterDelegate::~RemoteCommandCenterDelegate() = default;
+
+}  // namespace now_playing
diff --git a/ui/base/now_playing/remote_command_center_delegate.h b/ui/base/now_playing/remote_command_center_delegate.h
new file mode 100644
index 0000000..69722ec
--- /dev/null
+++ b/ui/base/now_playing/remote_command_center_delegate.h
@@ -0,0 +1,50 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_BASE_NOW_PLAYING_REMOTE_COMMAND_CENTER_DELEGATE_H_
+#define UI_BASE_NOW_PLAYING_REMOTE_COMMAND_CENTER_DELEGATE_H_
+
+#include <memory>
+
+#include "base/component_export.h"
+
+namespace now_playing {
+
+class RemoteCommandCenterDelegateObserver;
+
+// The RemoteCommandCenterDelegate connects with Mac OS's MPRemoteCommandCenter,
+// receives remote control events, and propagates those events to listening
+// RemoteCommandCenterDelegateObservers. The RemoteCommandCenterDelegate also
+// tells the MPRemoteCommandCenter which actions are currently available.
+// https://developer.apple.com/documentation/mediaplayer/mpremotecommandcenter
+class COMPONENT_EXPORT(NOW_PLAYING) RemoteCommandCenterDelegate {
+ public:
+  virtual ~RemoteCommandCenterDelegate();
+
+  // Creates and returns an instance of RemoteCommandCenterDelegate. Returns
+  // null if the current version of Mac OS does not support
+  // MPRemoteCommandCenter.
+  static std::unique_ptr<RemoteCommandCenterDelegate> Create();
+
+  // Returns the singleton instance.
+  static RemoteCommandCenterDelegate* GetInstance();
+
+  // Observers receive remote commands from the OS (e.g. media key presses).
+  virtual void AddObserver(RemoteCommandCenterDelegateObserver* observer) = 0;
+  virtual void RemoveObserver(
+      RemoteCommandCenterDelegateObserver* observer) = 0;
+
+  // Used for toggling whether specific media actions are available.
+  // TODO(steimel): Support all remote command actions.
+  virtual void SetCanPlay(bool enable) = 0;
+  virtual void SetCanPause(bool enable) = 0;
+  virtual void SetCanStop(bool enable) = 0;
+  virtual void SetCanPlayPause(bool enable) = 0;
+  virtual void SetCanGoNextTrack(bool enable) = 0;
+  virtual void SetCanGoPreviousTrack(bool enable) = 0;
+};
+
+}  // namespace now_playing
+
+#endif  // UI_BASE_NOW_PLAYING_REMOTE_COMMAND_CENTER_DELEGATE_H_
diff --git a/ui/base/now_playing/remote_command_center_delegate_impl.h b/ui/base/now_playing/remote_command_center_delegate_impl.h
new file mode 100644
index 0000000..37adc31
--- /dev/null
+++ b/ui/base/now_playing/remote_command_center_delegate_impl.h
@@ -0,0 +1,75 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_BASE_NOW_PLAYING_REMOTE_COMMAND_CENTER_DELEGATE_IMPL_H_
+#define UI_BASE_NOW_PLAYING_REMOTE_COMMAND_CENTER_DELEGATE_IMPL_H_
+
+#include "base/component_export.h"
+#include "base/containers/flat_set.h"
+#include "base/mac/scoped_nsobject.h"
+#include "base/observer_list.h"
+#include "ui/base/now_playing/remote_command_center_delegate.h"
+#include "ui/base/now_playing/remote_command_center_delegate_observer.h"
+
+@class RemoteCommandCenterDelegateNS;
+
+namespace now_playing {
+
+// Implementation of RemoteCommandCenterDelegate that wraps an NSObject which
+// interfaces with the MPRemoteCommandCenter.
+class COMPONENT_EXPORT(NOW_PLAYING)
+    API_AVAILABLE(macos(10.12.2)) RemoteCommandCenterDelegateImpl
+    : public RemoteCommandCenterDelegate,
+      RemoteCommandCenterDelegateObserver {
+ public:
+  RemoteCommandCenterDelegateImpl();
+  ~RemoteCommandCenterDelegateImpl() override;
+
+  static RemoteCommandCenterDelegateImpl* GetInstance();
+
+  // RemoteCommandCenterDelegate implementation.
+  void AddObserver(RemoteCommandCenterDelegateObserver* observer) override;
+  void RemoveObserver(RemoteCommandCenterDelegateObserver* observer) override;
+  void SetCanPlay(bool enable) override;
+  void SetCanPause(bool enable) override;
+  void SetCanStop(bool enable) override;
+  void SetCanPlayPause(bool enable) override;
+  void SetCanGoNextTrack(bool enable) override;
+  void SetCanGoPreviousTrack(bool enable) override;
+
+  // RemoteCommandCenterDelegateObserver implementation. Called by
+  // |remote_command_center_delegate_ns_|.
+  void OnNext() override;
+  void OnPrevious() override;
+  void OnPause() override;
+  void OnPlayPause() override;
+  void OnStop() override;
+  void OnPlay() override;
+
+ private:
+  // Used to track which commands we're already listening for.
+  enum class Command {
+    kPlay,
+    kPause,
+    kStop,
+    kPlayPause,
+    kNextTrack,
+    kPreviousTrack,
+  };
+
+  static RemoteCommandCenterDelegateImpl* instance_;
+
+  bool ShouldSetCommandActive(Command command, bool will_enable);
+
+  base::scoped_nsobject<RemoteCommandCenterDelegateNS>
+      remote_command_center_delegate_ns_;
+  base::ObserverList<RemoteCommandCenterDelegateObserver> observers_;
+  base::flat_set<Command> active_commands_;
+
+  DISALLOW_COPY_AND_ASSIGN(RemoteCommandCenterDelegateImpl);
+};
+
+}  // namespace now_playing
+
+#endif  // UI_BASE_NOW_PLAYING_REMOTE_COMMAND_CENTER_DELEGATE_IMPL_H_
diff --git a/ui/base/now_playing/remote_command_center_delegate_impl.mm b/ui/base/now_playing/remote_command_center_delegate_impl.mm
new file mode 100644
index 0000000..cf05d4d
--- /dev/null
+++ b/ui/base/now_playing/remote_command_center_delegate_impl.mm
@@ -0,0 +1,147 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/base/now_playing/remote_command_center_delegate_impl.h"
+
+#include "ui/base/now_playing/remote_command_center_delegate_ns.h"
+
+namespace now_playing {
+
+// static
+RemoteCommandCenterDelegateImpl* RemoteCommandCenterDelegateImpl::instance_ =
+    nullptr;
+
+// static
+RemoteCommandCenterDelegateImpl*
+RemoteCommandCenterDelegateImpl::GetInstance() {
+  return instance_;
+}
+
+// static
+std::unique_ptr<RemoteCommandCenterDelegate>
+RemoteCommandCenterDelegate::Create() {
+  if (@available(macOS 10.12.2, *))
+    return std::make_unique<RemoteCommandCenterDelegateImpl>();
+  return nullptr;
+}
+
+// static
+RemoteCommandCenterDelegate* RemoteCommandCenterDelegate::GetInstance() {
+  if (@available(macOS 10.12.2, *))
+    return RemoteCommandCenterDelegateImpl::GetInstance();
+  return nullptr;
+}
+
+RemoteCommandCenterDelegateImpl::RemoteCommandCenterDelegateImpl() {
+  DCHECK_EQ(nullptr, instance_);
+  instance_ = this;
+  remote_command_center_delegate_ns_.reset(
+      [[RemoteCommandCenterDelegateNS alloc] initWithDelegate:this]);
+}
+
+RemoteCommandCenterDelegateImpl::~RemoteCommandCenterDelegateImpl() {
+  DCHECK_EQ(this, instance_);
+  instance_ = nullptr;
+
+  // Ensure that we unregister from all commands.
+  SetCanPlay(false);
+  SetCanPause(false);
+  SetCanStop(false);
+  SetCanPlayPause(false);
+  SetCanGoNextTrack(false);
+  SetCanGoPreviousTrack(false);
+}
+
+void RemoteCommandCenterDelegateImpl::AddObserver(
+    RemoteCommandCenterDelegateObserver* observer) {
+  observers_.AddObserver(observer);
+}
+
+void RemoteCommandCenterDelegateImpl::RemoveObserver(
+    RemoteCommandCenterDelegateObserver* observer) {
+  observers_.RemoveObserver(observer);
+}
+
+void RemoteCommandCenterDelegateImpl::SetCanPlay(bool enable) {
+  if (!ShouldSetCommandActive(Command::kPlay, enable))
+    return;
+
+  [remote_command_center_delegate_ns_ setCanPlay:enable];
+}
+void RemoteCommandCenterDelegateImpl::SetCanPause(bool enable) {
+  if (!ShouldSetCommandActive(Command::kPause, enable))
+    return;
+
+  [remote_command_center_delegate_ns_ setCanPause:enable];
+}
+void RemoteCommandCenterDelegateImpl::SetCanStop(bool enable) {
+  if (!ShouldSetCommandActive(Command::kStop, enable))
+    return;
+
+  [remote_command_center_delegate_ns_ setCanStop:enable];
+}
+void RemoteCommandCenterDelegateImpl::SetCanPlayPause(bool enable) {
+  if (!ShouldSetCommandActive(Command::kPlayPause, enable))
+    return;
+
+  [remote_command_center_delegate_ns_ setCanPlayPause:enable];
+}
+void RemoteCommandCenterDelegateImpl::SetCanGoNextTrack(bool enable) {
+  if (!ShouldSetCommandActive(Command::kNextTrack, enable))
+    return;
+
+  [remote_command_center_delegate_ns_ setCanGoNextTrack:enable];
+}
+void RemoteCommandCenterDelegateImpl::SetCanGoPreviousTrack(bool enable) {
+  if (!ShouldSetCommandActive(Command::kPreviousTrack, enable))
+    return;
+
+  [remote_command_center_delegate_ns_ setCanGoPreviousTrack:enable];
+}
+
+void RemoteCommandCenterDelegateImpl::OnNext() {
+  DCHECK(active_commands_.contains(Command::kNextTrack));
+  for (RemoteCommandCenterDelegateObserver& observer : observers_)
+    observer.OnNext();
+}
+void RemoteCommandCenterDelegateImpl::OnPrevious() {
+  DCHECK(active_commands_.contains(Command::kPreviousTrack));
+  for (RemoteCommandCenterDelegateObserver& observer : observers_)
+    observer.OnPrevious();
+}
+void RemoteCommandCenterDelegateImpl::OnPause() {
+  DCHECK(active_commands_.contains(Command::kPause));
+  for (RemoteCommandCenterDelegateObserver& observer : observers_)
+    observer.OnPause();
+}
+void RemoteCommandCenterDelegateImpl::OnPlayPause() {
+  DCHECK(active_commands_.contains(Command::kPlayPause));
+  for (RemoteCommandCenterDelegateObserver& observer : observers_)
+    observer.OnPlayPause();
+}
+void RemoteCommandCenterDelegateImpl::OnStop() {
+  DCHECK(active_commands_.contains(Command::kStop));
+  for (RemoteCommandCenterDelegateObserver& observer : observers_)
+    observer.OnStop();
+}
+void RemoteCommandCenterDelegateImpl::OnPlay() {
+  DCHECK(active_commands_.contains(Command::kPlay));
+  for (RemoteCommandCenterDelegateObserver& observer : observers_)
+    observer.OnPlay();
+}
+
+bool RemoteCommandCenterDelegateImpl::ShouldSetCommandActive(Command command,
+                                                             bool will_enable) {
+  if (will_enable == active_commands_.contains(command))
+    return false;
+
+  if (will_enable)
+    active_commands_.insert(command);
+  else
+    active_commands_.erase(command);
+
+  return true;
+}
+
+}  // namespace now_playing
diff --git a/ui/base/now_playing/remote_command_center_delegate_ns.h b/ui/base/now_playing/remote_command_center_delegate_ns.h
new file mode 100644
index 0000000..84e72db
--- /dev/null
+++ b/ui/base/now_playing/remote_command_center_delegate_ns.h
@@ -0,0 +1,38 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_BASE_NOW_PLAYING_REMOTE_COMMAND_CENTER_DELEGATE_NS_H_
+#define UI_BASE_NOW_PLAYING_REMOTE_COMMAND_CENTER_DELEGATE_NS_H_
+
+#import <Cocoa/Cocoa.h>
+#import <MediaPlayer/MediaPlayer.h>
+
+namespace now_playing {
+class RemoteCommandCenterDelegateImpl;
+}  // namespace now_playing
+
+API_AVAILABLE(macos(10.12.2))
+@interface RemoteCommandCenterDelegateNS : NSObject {
+ @private
+  now_playing::RemoteCommandCenterDelegateImpl* delegate_;
+}
+
+- (instancetype)initWithDelegate:
+    (now_playing::RemoteCommandCenterDelegateImpl*)delegate;
+
+// Called by the OS via the MPRemoteCommandCenter.
+- (MPRemoteCommandHandlerStatus)onCommand:(MPRemoteCommandEvent*)event;
+
+// Called by the RemoteCommandCenterDelegateImpl to enable/disable different
+// commands.
+- (void)setCanPlay:(bool)can_play;
+- (void)setCanPause:(bool)can_pause;
+- (void)setCanStop:(bool)can_stop;
+- (void)setCanPlayPause:(bool)can_playpause;
+- (void)setCanGoNextTrack:(bool)can_go_next_track;
+- (void)setCanGoPreviousTrack:(bool)can_go_prev_track;
+
+@end
+
+#endif  // UI_BASE_NOW_PLAYING_REMOTE_COMMAND_CENTER_DELEGATE_NS_H_
diff --git a/ui/base/now_playing/remote_command_center_delegate_ns.mm b/ui/base/now_playing/remote_command_center_delegate_ns.mm
new file mode 100644
index 0000000..7bb97455
--- /dev/null
+++ b/ui/base/now_playing/remote_command_center_delegate_ns.mm
@@ -0,0 +1,128 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/base/now_playing/remote_command_center_delegate_ns.h"
+
+#import <MediaPlayer/MediaPlayer.h>
+
+#include "ui/base/now_playing/remote_command_center_delegate_impl.h"
+
+API_AVAILABLE(macos(10.12.2))
+@interface RemoteCommandCenterDelegateNS ()
+
+- (void)setCommand:(MPRemoteCommand*)command enabled:(bool)enabled;
+- (void)enableCommand:(MPRemoteCommand*)command;
+- (void)disableCommand:(MPRemoteCommand*)command;
+
+@end
+
+@implementation RemoteCommandCenterDelegateNS
+
+- (instancetype)initWithDelegate:
+    (now_playing::RemoteCommandCenterDelegateImpl*)delegate {
+  if (self = [super init]) {
+    delegate_ = delegate;
+
+    // Initialize all commands as disabled.
+    MPRemoteCommandCenter* commandCenter =
+        [MPRemoteCommandCenter sharedCommandCenter];
+    commandCenter.pauseCommand.enabled = NO;
+    commandCenter.playCommand.enabled = NO;
+    commandCenter.stopCommand.enabled = NO;
+    commandCenter.togglePlayPauseCommand.enabled = NO;
+    commandCenter.nextTrackCommand.enabled = NO;
+    commandCenter.previousTrackCommand.enabled = NO;
+    commandCenter.changeRepeatModeCommand.enabled = NO;
+    commandCenter.changeShuffleModeCommand.enabled = NO;
+    commandCenter.changePlaybackRateCommand.enabled = NO;
+    commandCenter.seekBackwardCommand.enabled = NO;
+    commandCenter.seekForwardCommand.enabled = NO;
+    commandCenter.skipBackwardCommand.enabled = NO;
+    commandCenter.skipForwardCommand.enabled = NO;
+    commandCenter.changePlaybackPositionCommand.enabled = NO;
+    commandCenter.ratingCommand.enabled = NO;
+    commandCenter.likeCommand.enabled = NO;
+    commandCenter.dislikeCommand.enabled = NO;
+    commandCenter.bookmarkCommand.enabled = NO;
+    commandCenter.enableLanguageOptionCommand.enabled = NO;
+    commandCenter.disableLanguageOptionCommand.enabled = NO;
+  }
+  return self;
+}
+
+- (MPRemoteCommandHandlerStatus)onCommand:(MPRemoteCommandEvent*)event {
+  MPRemoteCommandCenter* commandCenter =
+      [MPRemoteCommandCenter sharedCommandCenter];
+  if (event.command == commandCenter.pauseCommand) {
+    delegate_->OnPause();
+  } else if (event.command == commandCenter.playCommand) {
+    delegate_->OnPlay();
+  } else if (event.command == commandCenter.stopCommand) {
+    delegate_->OnStop();
+  } else if (event.command == commandCenter.togglePlayPauseCommand) {
+    delegate_->OnPlayPause();
+  } else if (event.command == commandCenter.nextTrackCommand) {
+    delegate_->OnNext();
+  } else if (event.command == commandCenter.previousTrackCommand) {
+    delegate_->OnPrevious();
+  }
+  return MPRemoteCommandHandlerStatusSuccess;
+}
+
+- (void)setCanPlay:(bool)can_play {
+  MPRemoteCommandCenter* commandCenter =
+      [MPRemoteCommandCenter sharedCommandCenter];
+  [self setCommand:commandCenter.playCommand enabled:can_play];
+}
+
+- (void)setCanPause:(bool)can_pause {
+  MPRemoteCommandCenter* commandCenter =
+      [MPRemoteCommandCenter sharedCommandCenter];
+  [self setCommand:commandCenter.pauseCommand enabled:can_pause];
+}
+
+- (void)setCanStop:(bool)can_stop {
+  MPRemoteCommandCenter* commandCenter =
+      [MPRemoteCommandCenter sharedCommandCenter];
+  [self setCommand:commandCenter.stopCommand enabled:can_stop];
+}
+
+- (void)setCanPlayPause:(bool)can_playpause {
+  MPRemoteCommandCenter* commandCenter =
+      [MPRemoteCommandCenter sharedCommandCenter];
+  [self setCommand:commandCenter.togglePlayPauseCommand enabled:can_playpause];
+}
+
+- (void)setCanGoNextTrack:(bool)can_go_next_track {
+  MPRemoteCommandCenter* commandCenter =
+      [MPRemoteCommandCenter sharedCommandCenter];
+  [self setCommand:commandCenter.nextTrackCommand enabled:can_go_next_track];
+}
+
+- (void)setCanGoPreviousTrack:(bool)can_go_prev_track {
+  MPRemoteCommandCenter* commandCenter =
+      [MPRemoteCommandCenter sharedCommandCenter];
+  [self setCommand:commandCenter.previousTrackCommand
+           enabled:can_go_prev_track];
+}
+
+- (void)setCommand:(MPRemoteCommand*)command enabled:(bool)enabled {
+  if (enabled) {
+    [self enableCommand:command];
+  } else {
+    [self disableCommand:command];
+  }
+}
+
+- (void)enableCommand:(MPRemoteCommand*)command {
+  command.enabled = YES;
+  [command addTarget:self action:@selector(onCommand:)];
+}
+
+- (void)disableCommand:(MPRemoteCommand*)command {
+  command.enabled = NO;
+  [command removeTarget:self];
+}
+
+@end
diff --git a/ui/base/now_playing/remote_command_center_delegate_observer.cc b/ui/base/now_playing/remote_command_center_delegate_observer.cc
new file mode 100644
index 0000000..f95517a
--- /dev/null
+++ b/ui/base/now_playing/remote_command_center_delegate_observer.cc
@@ -0,0 +1,15 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/base/now_playing/remote_command_center_delegate_observer.h"
+
+namespace now_playing {
+
+RemoteCommandCenterDelegateObserver::RemoteCommandCenterDelegateObserver() =
+    default;
+
+RemoteCommandCenterDelegateObserver::~RemoteCommandCenterDelegateObserver() =
+    default;
+
+}  // namespace now_playing
diff --git a/ui/base/now_playing/remote_command_center_delegate_observer.h b/ui/base/now_playing/remote_command_center_delegate_observer.h
new file mode 100644
index 0000000..2846f9ff
--- /dev/null
+++ b/ui/base/now_playing/remote_command_center_delegate_observer.h
@@ -0,0 +1,33 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_BASE_NOW_PLAYING_REMOTE_COMMAND_CENTER_DELEGATE_OBSERVER_H_
+#define UI_BASE_NOW_PLAYING_REMOTE_COMMAND_CENTER_DELEGATE_OBSERVER_H_
+
+#include "base/component_export.h"
+#include "base/observer_list_types.h"
+
+namespace now_playing {
+
+// Interface to observe events from the MPRemoteCommandCenter.
+class COMPONENT_EXPORT(NOW_PLAYING) RemoteCommandCenterDelegateObserver
+    : public base::CheckedObserver {
+ public:
+  RemoteCommandCenterDelegateObserver();
+  ~RemoteCommandCenterDelegateObserver() override;
+
+  virtual void OnNext() {}
+  virtual void OnPrevious() {}
+  virtual void OnPause() {}
+  virtual void OnPlayPause() {}
+  virtual void OnStop() {}
+  virtual void OnPlay() {}
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(RemoteCommandCenterDelegateObserver);
+};
+
+}  // namespace now_playing
+
+#endif  // UI_BASE_NOW_PLAYING_REMOTE_COMMAND_CENTER_DELEGATE_OBSERVER_H_
diff --git a/ui/views/win/windows_session_change_observer.cc b/ui/base/win/session_change_observer.cc
similarity index 62%
rename from ui/views/win/windows_session_change_observer.cc
rename to ui/base/win/session_change_observer.cc
index c2de1e1b..9fe8503 100644
--- a/ui/views/win/windows_session_change_observer.cc
+++ b/ui/base/win/session_change_observer.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 "ui/views/win/windows_session_change_observer.h"
+#include "ui/base/win/session_change_observer.h"
 
 #include <wtsapi32.h>
 
@@ -18,30 +18,37 @@
 #include "base/task/post_task.h"
 #include "ui/gfx/win/singleton_hwnd.h"
 #include "ui/gfx/win/singleton_hwnd_observer.h"
-#include "ui/views/views_delegate.h"
 
-namespace views {
+namespace ui {
 
-class WindowsSessionChangeObserver::WtsRegistrationNotificationManager {
+class SessionChangeObserver::WtsRegistrationNotificationManager {
  public:
   static WtsRegistrationNotificationManager* GetInstance() {
     return base::Singleton<WtsRegistrationNotificationManager>::get();
   }
 
   WtsRegistrationNotificationManager() {
-    AddSingletonHwndObserver();
+    DCHECK(!singleton_hwnd_observer_);
+    singleton_hwnd_observer_.reset(new gfx::SingletonHwndObserver(
+        base::BindRepeating(&WtsRegistrationNotificationManager::OnWndProc,
+                            base::Unretained(this))));
+
+    base::OnceClosure wts_register = base::BindOnce(
+        base::IgnoreResult(&WTSRegisterSessionNotification),
+        gfx::SingletonHwnd::GetInstance()->hwnd(), NOTIFY_FOR_THIS_SESSION);
+
+    base::CreateCOMSTATaskRunnerWithTraits({})->PostTask(
+        FROM_HERE, std::move(wts_register));
   }
 
-  ~WtsRegistrationNotificationManager() {
-    RemoveSingletonHwndObserver();
-  }
+  ~WtsRegistrationNotificationManager() { RemoveSingletonHwndObserver(); }
 
-  void AddObserver(WindowsSessionChangeObserver* observer) {
+  void AddObserver(SessionChangeObserver* observer) {
     DCHECK(singleton_hwnd_observer_);
     observer_list_.AddObserver(observer);
   }
 
-  void RemoveObserver(WindowsSessionChangeObserver* observer) {
+  void RemoveObserver(SessionChangeObserver* observer) {
     observer_list_.RemoveObserver(observer);
   }
 
@@ -52,7 +59,7 @@
   void OnWndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) {
     switch (message) {
       case WM_WTSSESSION_CHANGE:
-        for (WindowsSessionChangeObserver& observer : observer_list_)
+        for (SessionChangeObserver& observer : observer_list_)
           observer.OnSessionChange(wparam);
         break;
       case WM_DESTROY:
@@ -61,27 +68,6 @@
     }
   }
 
-  void AddSingletonHwndObserver() {
-    DCHECK(!singleton_hwnd_observer_);
-    singleton_hwnd_observer_.reset(new gfx::SingletonHwndObserver(
-        base::Bind(&WtsRegistrationNotificationManager::OnWndProc,
-                   base::Unretained(this))));
-
-    base::OnceClosure wts_register = base::BindOnce(
-        base::IgnoreResult(&WTSRegisterSessionNotification),
-        gfx::SingletonHwnd::GetInstance()->hwnd(), NOTIFY_FOR_THIS_SESSION);
-
-    // This should probably always be async but it wasn't async in the absence
-    // of a ViewsDelegate prior to the migration to TaskScheduler and making it
-    // async breaks many unrelated views unittests.
-    if (ViewsDelegate::GetInstance()) {
-      base::CreateCOMSTATaskRunnerWithTraits({})->PostTask(
-          FROM_HERE, std::move(wts_register));
-    } else {
-      std::move(wts_register).Run();
-    }
-  }
-
   void RemoveSingletonHwndObserver() {
     if (!singleton_hwnd_observer_)
       return;
@@ -94,37 +80,35 @@
     // Under both cases we are in shutdown, which means no other worker threads
     // can be running.
     WTSUnRegisterSessionNotification(gfx::SingletonHwnd::GetInstance()->hwnd());
-    for (WindowsSessionChangeObserver& observer : observer_list_)
+    for (SessionChangeObserver& observer : observer_list_)
       observer.ClearCallback();
   }
 
-  base::ObserverList<WindowsSessionChangeObserver, true>::Unchecked
-      observer_list_;
+  base::ObserverList<SessionChangeObserver, true>::Unchecked observer_list_;
   std::unique_ptr<gfx::SingletonHwndObserver> singleton_hwnd_observer_;
 
   DISALLOW_COPY_AND_ASSIGN(WtsRegistrationNotificationManager);
 };
 
-WindowsSessionChangeObserver::WindowsSessionChangeObserver(
-    const WtsCallback& callback)
+SessionChangeObserver::SessionChangeObserver(const WtsCallback& callback)
     : callback_(callback) {
   DCHECK(!callback_.is_null());
   WtsRegistrationNotificationManager::GetInstance()->AddObserver(this);
 }
 
-WindowsSessionChangeObserver::~WindowsSessionChangeObserver() {
+SessionChangeObserver::~SessionChangeObserver() {
   ClearCallback();
 }
 
-void WindowsSessionChangeObserver::OnSessionChange(WPARAM wparam) {
+void SessionChangeObserver::OnSessionChange(WPARAM wparam) {
   callback_.Run(wparam);
 }
 
-void WindowsSessionChangeObserver::ClearCallback() {
+void SessionChangeObserver::ClearCallback() {
   if (!callback_.is_null()) {
     callback_.Reset();
     WtsRegistrationNotificationManager::GetInstance()->RemoveObserver(this);
   }
 }
 
-}  // namespace views
+}  // namespace ui
diff --git a/ui/base/win/session_change_observer.h b/ui/base/win/session_change_observer.h
new file mode 100644
index 0000000..4aa3fe4
--- /dev/null
+++ b/ui/base/win/session_change_observer.h
@@ -0,0 +1,39 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_BASE_WIN_SESSION_CHANGE_OBSERVER_H_
+#define UI_BASE_WIN_SESSION_CHANGE_OBSERVER_H_
+
+#include <windows.h>
+
+#include "base/callback.h"
+#include "base/macros.h"
+#include "ui/base/ui_base_export.h"
+
+namespace ui {
+
+// Calls the provided callback on WM_WTSSESSION_CHANGE messages along with
+// managing the tricky business of observing a singleton object.
+class UI_BASE_EXPORT SessionChangeObserver {
+ public:
+  // WPARAM is the wparam passed to the OnWndProc when message is
+  // WM_WTSSESSION_CHANGE.
+  typedef base::RepeatingCallback<void(WPARAM)> WtsCallback;
+  explicit SessionChangeObserver(const WtsCallback& callback);
+  ~SessionChangeObserver();
+
+ private:
+  class WtsRegistrationNotificationManager;
+
+  void OnSessionChange(WPARAM wparam);
+  void ClearCallback();
+
+  WtsCallback callback_;
+
+  DISALLOW_COPY_AND_ASSIGN(SessionChangeObserver);
+};
+
+}  // namespace ui
+
+#endif  // UI_BASE_WIN_SESSION_CHANGE_OBSERVER_H_
diff --git a/ui/display/manager/display_change_observer.cc b/ui/display/manager/display_change_observer.cc
index 3634bc90..0a399ea3 100644
--- a/ui/display/manager/display_change_observer.cc
+++ b/ui/display/manager/display_change_observer.cc
@@ -137,10 +137,6 @@
     }
   }
 
-  ManagedDisplayInfo::ManagedDisplayModeList display_mode_list;
-  for (const auto& display_mode_pair : display_mode_map)
-    display_mode_list.push_back(std::move(display_mode_pair.second));
-
   if (output.native_mode()) {
     const gfx::Size size = native_mode.size();
 
@@ -148,11 +144,18 @@
     DCHECK(it != display_mode_map.end())
         << "Native mode must be part of the mode list.";
 
-    // If the native mode was replaced re-add it.
+    // If the native mode was replaced (e.g. by a mode with similar size but
+    // higher refresh rate), we overwrite that mode with the native mode. The
+    // native mode will always be chosen as the best mode for this size (see
+    // DisplayConfigurator::FindDisplayModeMatchingSize()).
     if (!it->second.native())
-      display_mode_list.push_back(native_mode);
+      it->second = native_mode;
   }
 
+  ManagedDisplayInfo::ManagedDisplayModeList display_mode_list;
+  for (const auto& display_mode_pair : display_mode_map)
+    display_mode_list.push_back(std::move(display_mode_pair.second));
+
   return display_mode_list;
 }
 
diff --git a/ui/display/manager/display_change_observer_unittest.cc b/ui/display/manager/display_change_observer_unittest.cc
index 31fbc4bf9..7cb44526 100644
--- a/ui/display/manager/display_change_observer_unittest.cc
+++ b/ui/display/manager/display_change_observer_unittest.cc
@@ -69,6 +69,8 @@
       FakeDisplaySnapshot::Builder()
           .SetId(123)
           .SetNativeMode(MakeDisplayMode(1920, 1200, false, 60))
+          // Same size as native mode but with higher refresh rate.
+          .AddMode(MakeDisplayMode(1920, 1200, false, 75))
           // All non-interlaced (as would be seen with different refresh rates).
           .AddMode(MakeDisplayMode(1920, 1080, false, 80))
           .AddMode(MakeDisplayMode(1920, 1080, false, 70))
@@ -93,7 +95,7 @@
 
   const bool listing_all_modes = GetParam();
   if (listing_all_modes) {
-    ASSERT_EQ(12u, display_modes.size());
+    ASSERT_EQ(13u, display_modes.size());
     EXPECT_EQ("640x480", display_modes[0].size().ToString());
     EXPECT_TRUE(display_modes[0].is_interlaced());
     EXPECT_EQ(display_modes[0].refresh_rate(), 60);
@@ -135,6 +137,10 @@
     EXPECT_EQ("1920x1200", display_modes[11].size().ToString());
     EXPECT_FALSE(display_modes[11].is_interlaced());
     EXPECT_EQ(display_modes[11].refresh_rate(), 60);
+
+    EXPECT_EQ("1920x1200", display_modes[12].size().ToString());
+    EXPECT_FALSE(display_modes[12].is_interlaced());
+    EXPECT_EQ(display_modes[12].refresh_rate(), 75);
   } else {
     ASSERT_EQ(6u, display_modes.size());
     EXPECT_EQ("640x480", display_modes[0].size().ToString());
@@ -222,16 +228,28 @@
   ManagedDisplayInfo::ManagedDisplayModeList display_modes =
       DisplayChangeObserver::GetExternalManagedDisplayModeList(
           *display_snapshot);
-  ASSERT_EQ(2u, display_modes.size());
-  EXPECT_EQ("1920x1080", display_modes[0].size().ToString());
-  EXPECT_FALSE(display_modes[0].is_interlaced());
-  EXPECT_FALSE(display_modes[0].native());
-  EXPECT_EQ(display_modes[0].refresh_rate(), 60);
 
-  EXPECT_EQ("1920x1080", display_modes[1].size().ToString());
-  EXPECT_TRUE(display_modes[1].is_interlaced());
-  EXPECT_TRUE(display_modes[1].native());
-  EXPECT_EQ(display_modes[1].refresh_rate(), 60);
+  const bool listing_all_modes = GetParam();
+
+  if (listing_all_modes) {
+    ASSERT_EQ(2u, display_modes.size());
+    EXPECT_EQ("1920x1080", display_modes[0].size().ToString());
+    EXPECT_FALSE(display_modes[0].is_interlaced());
+    EXPECT_FALSE(display_modes[0].native());
+    EXPECT_EQ(display_modes[0].refresh_rate(), 60);
+
+    EXPECT_EQ("1920x1080", display_modes[1].size().ToString());
+    EXPECT_TRUE(display_modes[1].is_interlaced());
+    EXPECT_TRUE(display_modes[1].native());
+    EXPECT_EQ(display_modes[1].refresh_rate(), 60);
+  } else {
+    // Only the native mode will be listed.
+    ASSERT_EQ(1u, display_modes.size());
+    EXPECT_EQ("1920x1080", display_modes[0].size().ToString());
+    EXPECT_TRUE(display_modes[0].is_interlaced());
+    EXPECT_TRUE(display_modes[0].native());
+    EXPECT_EQ(display_modes[0].refresh_rate(), 60);
+  }
 }
 
 INSTANTIATE_TEST_CASE_P(,
diff --git a/ui/file_manager/file_manager/foreground/elements/files_quick_view.html b/ui/file_manager/file_manager/foreground/elements/files_quick_view.html
index d9f2c89..dcb8755 100644
--- a/ui/file_manager/file_manager/foreground/elements/files_quick_view.html
+++ b/ui/file_manager/file_manager/foreground/elements/files_quick_view.html
@@ -15,7 +15,7 @@
 <dom-module id="files-quick-view">
   <link rel="import" type="css" href="files_quick_view.css">
   <template>
-    <dialog id="dialog">
+    <dialog id="dialog" on-close="onDialogClose_">
       <div id="toolbar">
         <div class="buttons-group">
            <paper-button on-tap="close" aria-label="$i18n{QUICK_VIEW_CLOSE_BUTTON_LABEL}" tabindex="0" has-tooltip>
diff --git a/ui/file_manager/file_manager/foreground/elements/files_quick_view.js b/ui/file_manager/file_manager/foreground/elements/files_quick_view.js
index 1e9d1a2..e4b3faf 100644
--- a/ui/file_manager/file_manager/foreground/elements/files_quick_view.js
+++ b/ui/file_manager/file_manager/foreground/elements/files_quick_view.js
@@ -36,7 +36,6 @@
   },
 
   listeners: {
-    'close': 'clear',
     'files-safe-media-tap-outside': 'close',
   },
 
@@ -197,4 +196,18 @@
         !this.isAudio_(type) && !this.isHtml_(type, subtype) && !browsable;
   },
 
+  /** @private */
+  onDialogClose_: function(e) {
+    assert(e.target === this.$.dialog);
+
+    this.clear();
+
+    // TODO(dpapad): This is necessary to make the code work both for Polymer 1
+    // and Polymer 2. Remove once migration to Polymer 2 is completed.
+    e.stopPropagation();
+
+    // Catch and re-fire the 'close' event such that it bubbles across Shadow
+    // DOM v1.
+    this.fire('close');
+  }
 });
diff --git a/ui/file_manager/image_loader/piex/.gitignore b/ui/file_manager/image_loader/piex/.gitignore
new file mode 100644
index 0000000..280759f
--- /dev/null
+++ b/ui/file_manager/image_loader/piex/.gitignore
@@ -0,0 +1,7 @@
+images
+node_modules
+package-lock.json
+tests.hash
+tests.log
+a.out.*
+*.bc
diff --git a/ui/file_manager/image_loader/piex/images.sh b/ui/file_manager/image_loader/piex/images.sh
new file mode 100755
index 0000000..e1ad5f9
--- /dev/null
+++ b/ui/file_manager/image_loader/piex/images.sh
@@ -0,0 +1,15 @@
+#!/bin/bash
+
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Fetch the test images into ./images if that directory does not exist.
+[[ -d images ]] && exit 0
+
+read -p "npm run test needs test images: install them now (y/n)? " ANSWER
+case ${ANSWER} in
+  [Yy]*) git clone https://github.com/noell/raw-test-images.git images
+    exit $!;;
+  [Nn]*|*) ;;
+esac
diff --git a/ui/file_manager/image_loader/piex/package.json b/ui/file_manager/image_loader/piex/package.json
new file mode 100644
index 0000000..299a2e5
--- /dev/null
+++ b/ui/file_manager/image_loader/piex/package.json
@@ -0,0 +1,20 @@
+{
+  "name": "piexwasm",
+  "version": "1.0.0",
+  "scripts": {
+    "install": "napa && ./images.sh",
+    "build": "make all",
+    "test": "./tests.sh",
+    "clean": "make clean"
+  },
+  "napa": {
+    "piex": "git+https://android.googlesource.com/platform/external/piex"
+  },
+  "dependencies": {
+    "chalk": "^2.4.2",
+    "commander": "^2.19.0",
+    "http-server": "^0.11.1",
+    "napa": "^3.0.0",
+    "puppeteer": "^1.5.0"
+  }
+}
diff --git a/ui/file_manager/integration_tests/video_player/background.js b/ui/file_manager/integration_tests/video_player/background.js
index 609fa91..afed660d 100644
--- a/ui/file_manager/integration_tests/video_player/background.js
+++ b/ui/file_manager/integration_tests/video_player/background.js
@@ -36,42 +36,41 @@
   });
 
   var appWindow = null;
-  return entriesPromise.then(function(urls) {
-    return remoteCallVideoPlayer.callRemoteTestUtil(
-        'openVideoPlayer', null, [urls]);
-  }).then(function(windowId) {
-    appWindow = windowId;
-    return remoteCallVideoPlayer.waitForElement(appWindow, 'body');
-  }).then(function() {
-    return Promise.all([
-      remoteCallVideoPlayer.waitForElement(
-          appWindow, '#video-player[first-video][last-video]'),
-    ]);
-  }).then(function(args) {
-    return [appWindow, args[0]];
-  });
+  return entriesPromise
+      .then(function(urls) {
+        return remoteCallVideoPlayer.callRemoteTestUtil(
+            'openVideoPlayer', null, [urls]);
+      })
+      .then(function(windowId) {
+        appWindow = windowId;
+        return remoteCallVideoPlayer.waitForElement(appWindow, 'body');
+      })
+      .then(function() {
+        return Promise.all([
+          remoteCallVideoPlayer.waitForElement(
+              appWindow, '#video-player[first-video]'),
+        ]);
+      })
+      .then(function(args) {
+        return [appWindow, args[0]];
+      });
 }
 
 /**
- * Opens video player with a single video.
+ * Open video player with multiple videos and subtitles.
  * @param {string} volumeName Test volume name passed to the addEntries
  *     function. Either 'drive' or 'local'.
  * @param {VolumeManagerCommon.VolumeType} volumeType Volume type.
- * @param {TestEntryInfo} entry File to be opened.
- * @param {TestEntryInfo=} subtitle Subtitle file to be added to volume.
+ * @param {Array<TestEntryInfo>} entries Files to be opened.
+ * @param {Array<TestEntryInfo>=} subtitles Subtitle files to be added to
+ *     volume.
  * @return {Promise} Promise to be fulfilled with the video player element.
  */
-function openSingleVideo(volumeName, volumeType, entry, subtitle = null) {
-  var entries = [entry];
-  if (subtitle) {
-    entries.push(subtitle);
-  }
-  return launch(volumeName, volumeType, entries, [entry]).then(function(args) {
-    var videoPlayer = args[1];
+function openVideos(volumeName, volumeType, entries, subtitles = []) {
+  const allEntries = entries.concat(subtitles);
+  return launch(volumeName, volumeType, allEntries, entries).then((args) => {
+    const videoPlayer = args[1];
 
-    chrome.test.assertTrue('first-video' in videoPlayer.attributes);
-    chrome.test.assertTrue('last-video' in videoPlayer.attributes);
-    chrome.test.assertFalse('multiple' in videoPlayer.attributes);
     chrome.test.assertFalse('disabled' in videoPlayer.attributes);
     return args;
   });
diff --git a/ui/file_manager/integration_tests/video_player/check_elements.js b/ui/file_manager/integration_tests/video_player/check_elements.js
index e379229..95d81dc 100644
--- a/ui/file_manager/integration_tests/video_player/check_elements.js
+++ b/ui/file_manager/integration_tests/video_player/check_elements.js
@@ -9,14 +9,14 @@
  * @return {Promise} Promise to be fulfilled with on success.
  */
 testcase.checkInitialElements = function() {
-    var test = openSingleVideo('local', 'downloads', ENTRIES.world);
-    return test.then(function(args) {
-      var appId = args[0];
-      var videoPlayer = args[1];
-      return Promise.all([
-        remoteCallVideoPlayer.waitForElement(appId, 'html[i18n-processed]'),
-        remoteCallVideoPlayer.waitForElement(appId, 'div#video-player'),
-        remoteCallVideoPlayer.waitForElement(appId, '#video-container > video'),
-      ]);
-    });
+  var test = openVideos('local', 'downloads', [ENTRIES.world]);
+  return test.then(function(args) {
+    var appId = args[0];
+    var videoPlayer = args[1];
+    return Promise.all([
+      remoteCallVideoPlayer.waitForElement(appId, 'html[i18n-processed]'),
+      remoteCallVideoPlayer.waitForElement(appId, 'div#video-player'),
+      remoteCallVideoPlayer.waitForElement(appId, '#video-container > video'),
+    ]);
+  });
 };
diff --git a/ui/file_manager/integration_tests/video_player/click_control_buttons.js b/ui/file_manager/integration_tests/video_player/click_control_buttons.js
index 24e337d..49e207b5 100644
--- a/ui/file_manager/integration_tests/video_player/click_control_buttons.js
+++ b/ui/file_manager/integration_tests/video_player/click_control_buttons.js
@@ -32,7 +32,7 @@
  * @return {Promise} Promise to be fulfilled on success.
  */
 testcase.mediaKeyNative = function() {
-  const openVideo = openSingleVideo('local', 'downloads', ENTRIES.video);
+  const openVideo = openVideos('local', 'downloads', [ENTRIES.video]);
   let appId;
   function ensurePlaying() {
     return waitForFunctionResult('isPlaying', 'video_long.ogv', true);
diff --git a/ui/file_manager/integration_tests/video_player/open_video_files.js b/ui/file_manager/integration_tests/video_player/open_video_files.js
index 33e6e8f..fcfbded38 100644
--- a/ui/file_manager/integration_tests/video_player/open_video_files.js
+++ b/ui/file_manager/integration_tests/video_player/open_video_files.js
@@ -9,7 +9,7 @@
  * @return {Promise} Promise to be fulfilled with on success.
  */
 testcase.openSingleVideoOnDownloads = function() {
-  var test = openSingleVideo('local', 'downloads', ENTRIES.world);
+  var test = openVideos('local', 'downloads', [ENTRIES.world]);
   return test
       .then(function() {
         // Video player starts playing given file automatically.
@@ -26,7 +26,7 @@
  * @return {Promise} Promise to be fulfilled with on success.
  */
 testcase.openSingleVideoOnDrive = function() {
-  var test = openSingleVideo('drive', 'drive', ENTRIES.world);
+  var test = openVideos('drive', 'drive', [ENTRIES.world]);
   return test
       .then(function() {
         // Video player starts playing given file automatically.
@@ -43,7 +43,7 @@
  * @return {Promise} Promise to be fulfilled with on success.
  */
 testcase.openVideoWithSubtitle = async function() {
-  await openSingleVideo('local', 'downloads', ENTRIES.world, ENTRIES.subtitle);
+  await openVideos('local', 'downloads', [ENTRIES.world], [ENTRIES.subtitle]);
   await waitForFunctionResult('isPlaying', 'world.ogv', true);
   await waitForFunctionResult('hasSubtitle', 'world.ogv', true);
 };
@@ -53,7 +53,35 @@
  * @return {Promise} Promise to be fulfilled with on success.
  */
 testcase.openVideoWithoutSubtitle = async function() {
-  await openSingleVideo('local', 'downloads', ENTRIES.video, ENTRIES.subtitle);
+  await openVideos('local', 'downloads', [ENTRIES.video], [ENTRIES.subtitle]);
   await waitForFunctionResult('isPlaying', 'video_long.ogv', true);
   await waitForFunctionResult('hasSubtitle', 'video_long.ogv', false);
 };
+
+/**
+ * Test that if player will auto play next video and handle subtitles correctly.
+ * @return {Promise} Promise to be fulfilled with on success.
+ */
+testcase.openMultipleVideosOnDownloads = async function() {
+  const args = await openVideos(
+      'local', 'downloads', [ENTRIES.world, ENTRIES.video], [ENTRIES.subtitle]);
+  const appId = args[0];
+
+  // Video player should auto play first video.
+  await waitForFunctionResult('isPlaying', 'world.ogv', true);
+  await remoteCallVideoPlayer.waitForElement(
+      appId, '#video-player[first-video]');
+  await remoteCallVideoPlayer.waitForElement(
+      appId, '#video-player:not([last-video])');
+  await waitForFunctionResult('hasSubtitle', 'world.ogv', true);
+
+  // Auto play next video when previous video ends.
+  await waitForFunctionResult('isPlaying', 'video_long.ogv', true);
+  await remoteCallVideoPlayer.waitForElement(
+      appId, '#video-player:not([first-video])');
+  await remoteCallVideoPlayer.waitForElement(
+      appId, '#video-player[last-video]');
+
+  // Subtitle should be cleared
+  await waitForFunctionResult('hasSubtitle', 'video_long.ogv', false);
+};
diff --git a/ui/file_manager/video_player/js/video_player_native_controls.js b/ui/file_manager/video_player/js/video_player_native_controls.js
index 41c61c6e..361fe1de 100644
--- a/ui/file_manager/video_player/js/video_player_native_controls.js
+++ b/ui/file_manager/video_player/js/video_player_native_controls.js
@@ -353,6 +353,11 @@
 
     this.videoElement_.src = videoUrl;
 
+    // Clear all tracks.
+    while (this.videoElement_.firstChild) {
+      this.videoElement_.firstChild.remove();
+    }
+
     const subtitleUrl = await this.searchSubtitle_(videoUrl);
     if (subtitleUrl) {
       const track =
diff --git a/ui/gl/sync_control_vsync_provider.cc b/ui/gl/sync_control_vsync_provider.cc
index 6e49834..79359e7 100644
--- a/ui/gl/sync_control_vsync_provider.cc
+++ b/ui/gl/sync_control_vsync_provider.cc
@@ -78,8 +78,7 @@
             base::TimeTicks::Clock::LINUX_CLOCK_MONOTONIC);
 
   int64_t real_time_in_microseconds =
-      real_time.tv_sec * base::Time::kMicrosecondsPerSecond +
-      real_time.tv_nsec / base::Time::kNanosecondsPerMicrosecond;
+      base::TimeDelta::FromTimeSpec(real_time).InMicroseconds();
   int64_t monotonic_time_in_microseconds =
       monotonic_time.since_origin().InMicroseconds();
 
diff --git a/ui/keyboard/keyboard_controller.cc b/ui/keyboard/keyboard_controller.cc
index e877d8c..26c1201 100644
--- a/ui/keyboard/keyboard_controller.cc
+++ b/ui/keyboard/keyboard_controller.cc
@@ -104,7 +104,7 @@
           {KeyboardControllerState::HIDDEN, KeyboardControllerState::INITIAL},
       };
   return kAllowedStateTransition.count(std::make_pair(from, to)) == 1;
-};
+}
 
 void SetTouchEventLogging(bool enable) {
   // TODO(moshayedi): crbug.com/642863. Revisit when we have mojo interface for
diff --git a/ui/keyboard/queued_container_type.cc b/ui/keyboard/queued_container_type.cc
index e2bcfdf..7aa8d19d 100644
--- a/ui/keyboard/queued_container_type.cc
+++ b/ui/keyboard/queued_container_type.cc
@@ -15,12 +15,12 @@
     : controller_(controller),
       container_type_(container_type),
       bounds_(bounds),
-      callback_(std::move(callback)){};
+      callback_(std::move(callback)) {}
 
 QueuedContainerType::~QueuedContainerType() {
   bool change_successful =
       controller_->GetActiveContainerType() == container_type_;
   std::move(callback_).Run(change_successful);
-};
+}
 
 }  // namespace keyboard
diff --git a/ui/keyboard/queued_display_change.cc b/ui/keyboard/queued_display_change.cc
index 9ec3be67..c97054a 100644
--- a/ui/keyboard/queued_display_change.cc
+++ b/ui/keyboard/queued_display_change.cc
@@ -11,8 +11,8 @@
 
 QueuedDisplayChange::QueuedDisplayChange(const display::Display& display,
                                          const gfx::Rect& new_bounds_in_local)
-    : new_display_(display), new_bounds_in_local_(new_bounds_in_local){};
+    : new_display_(display), new_bounds_in_local_(new_bounds_in_local) {}
 
-QueuedDisplayChange::~QueuedDisplayChange(){};
+QueuedDisplayChange::~QueuedDisplayChange() {}
 
 }  // namespace keyboard
diff --git a/ui/keyboard/test/test_keyboard_layout_delegate.h b/ui/keyboard/test/test_keyboard_layout_delegate.h
index 996baec..a7983278 100644
--- a/ui/keyboard/test/test_keyboard_layout_delegate.h
+++ b/ui/keyboard/test/test_keyboard_layout_delegate.h
@@ -10,7 +10,7 @@
 
 namespace aura {
 class Window;
-};
+}
 
 namespace keyboard {
 
diff --git a/ui/ozone/platform/wayland/wayland_input_method_context_unittest.cc b/ui/ozone/platform/wayland/wayland_input_method_context_unittest.cc
index 39d7664..08bf4b7 100644
--- a/ui/ozone/platform/wayland/wayland_input_method_context_unittest.cc
+++ b/ui/ozone/platform/wayland/wayland_input_method_context_unittest.cc
@@ -36,7 +36,7 @@
   }
   void OnPreeditEnd() override {}
   void OnPreeditStart() override {}
-  void OnDeleteSurroundingText(int32_t index, uint32_t length) override{};
+  void OnDeleteSurroundingText(int32_t index, uint32_t length) override {}
 
   bool was_on_commit_called() { return was_on_commit_called_; }
 
diff --git a/ui/views/BUILD.gn b/ui/views/BUILD.gn
index d2b7f4b..4cb05f34 100644
--- a/ui/views/BUILD.gn
+++ b/ui/views/BUILD.gn
@@ -566,7 +566,6 @@
       "win/hwnd_util.h",
       "win/pen_event_processor.h",
       "win/scoped_fullscreen_visibility.h",
-      "win/windows_session_change_observer.h",
     ]
     sources += [
       "widget/widget_hwnd_utils.cc",
@@ -575,14 +574,12 @@
       "win/hwnd_util_aurawin.cc",
       "win/pen_event_processor.cc",
       "win/scoped_fullscreen_visibility.cc",
-      "win/windows_session_change_observer.cc",
     ]
     libs = [
       "dwmapi.lib",
       "imm32.lib",
       "oleacc.lib",
       "uiautomationcore.lib",
-      "wtsapi32.lib",
     ]
     ldflags = [ "/DELAYLOAD:user32.dll" ]
     deps += [
diff --git a/ui/views/bubble/bubble_border.cc b/ui/views/bubble/bubble_border.cc
index 2629f60..7caa4fb 100644
--- a/ui/views/bubble/bubble_border.cc
+++ b/ui/views/bubble/bubble_border.cc
@@ -231,6 +231,8 @@
     return gfx::Insets();
   if (shadow_ == NO_SHADOW)
     return gfx::Insets(kBorderThicknessDip);
+  if (insets_.has_value())
+    return insets_.value();
   return GetBorderAndShadowInsets(md_shadow_elevation_);
 }
 
diff --git a/ui/views/bubble/bubble_border.h b/ui/views/bubble/bubble_border.h
index 007361a7..8f49292 100644
--- a/ui/views/bubble/bubble_border.h
+++ b/ui/views/bubble/bubble_border.h
@@ -185,6 +185,9 @@
   // Set a flag to avoid the bubble's shadow overlapping the anchor.
   void set_avoid_shadow_overlap(bool value) { avoid_shadow_overlap_ = value; }
 
+  // Sets an explicit insets value to be used.
+  void set_insets(const gfx::Insets& insets) { insets_ = insets; }
+
   // Get the desired widget bounds (in screen coordinates) given the anchor rect
   // and bubble content size; calculated from shadow and arrow image dimensions.
   virtual gfx::Rect GetBounds(const gfx::Rect& anchor_rect,
@@ -249,6 +252,7 @@
   SkColor background_color_;
   bool use_theme_background_color_;
   bool avoid_shadow_overlap_ = false;
+  base::Optional<gfx::Insets> insets_;
 
   DISALLOW_COPY_AND_ASSIGN(BubbleBorder);
 };
diff --git a/ui/views/event_monitor_aura.cc b/ui/views/event_monitor_aura.cc
index d560a66..5909080 100644
--- a/ui/views/event_monitor_aura.cc
+++ b/ui/views/event_monitor_aura.cc
@@ -4,7 +4,10 @@
 
 #include "ui/views/event_monitor_aura.h"
 
+#include <memory>
+
 #include "base/logging.h"
+#include "base/scoped_observer.h"
 #include "ui/aura/env.h"
 #include "ui/aura/window.h"
 #include "ui/events/event_observer.h"
@@ -12,6 +15,38 @@
 
 namespace views {
 
+namespace {
+
+// An EventMonitorAura that removes its event observer on window destruction.
+class WindowMonitorAura : public EventMonitorAura, public aura::WindowObserver {
+ public:
+  WindowMonitorAura(aura::Env* env,
+                    ui::EventObserver* event_observer,
+                    aura::Window* target_window,
+                    const std::set<ui::EventType>& types)
+      : EventMonitorAura(env, event_observer, target_window, types),
+        target_window_(target_window) {
+    window_observer_.Add(target_window);
+  }
+  ~WindowMonitorAura() override = default;
+
+  // aura::WindowObserver:
+  void OnWindowDestroying(aura::Window* window) override {
+    DCHECK_EQ(window, target_window_);
+    window_observer_.Remove(target_window_);
+    target_window_ = nullptr;
+    TearDown();
+  }
+
+ private:
+  aura::Window* target_window_;
+  ScopedObserver<aura::Window, aura::WindowObserver> window_observer_{this};
+
+  DISALLOW_COPY_AND_ASSIGN(WindowMonitorAura);
+};
+
+}  // namespace
+
 // static
 std::unique_ptr<EventMonitor> EventMonitor::CreateApplicationMonitor(
     ui::EventObserver* event_observer,
@@ -26,7 +61,7 @@
     ui::EventObserver* event_observer,
     gfx::NativeWindow target_window,
     const std::set<ui::EventType>& types) {
-  return std::make_unique<EventMonitorAura>(
+  return std::make_unique<WindowMonitorAura>(
       target_window->env(), event_observer, target_window, types);
 }
 
@@ -42,11 +77,17 @@
 }
 
 EventMonitorAura::~EventMonitorAura() {
-  env_->RemoveEventObserver(event_observer_);
+  TearDown();
 }
 
 gfx::Point EventMonitorAura::GetLastMouseLocation() {
   return env_->last_mouse_location();
 }
 
+void EventMonitorAura::TearDown() {
+  if (event_observer_)
+    env_->RemoveEventObserver(event_observer_);
+  event_observer_ = nullptr;
+}
+
 }  // namespace views
diff --git a/ui/views/event_monitor_aura.h b/ui/views/event_monitor_aura.h
index 222b8a1..8f23c005 100644
--- a/ui/views/event_monitor_aura.h
+++ b/ui/views/event_monitor_aura.h
@@ -18,6 +18,7 @@
 
 namespace views {
 
+// Observes events by installing a pre-target handler on the ui::EventTarget.
 class EventMonitorAura : public EventMonitor {
  public:
   EventMonitorAura(aura::Env* env,
@@ -29,6 +30,10 @@
   // EventMonitor:
   gfx::Point GetLastMouseLocation() override;
 
+ protected:
+  // Removes the pre-target handler. Called by window monitors on window close.
+  void TearDown();
+
  private:
   aura::Env* env_;                     // Weak.
   ui::EventObserver* event_observer_;  // Weak. Owned by our owner.
diff --git a/ui/views/event_monitor_unittest.cc b/ui/views/event_monitor_unittest.cc
index fdda456..398b364 100644
--- a/ui/views/event_monitor_unittest.cc
+++ b/ui/views/event_monitor_unittest.cc
@@ -112,6 +112,18 @@
   monitor.reset();
 }
 
+TEST_F(EventMonitorTest, WindowMonitorTornDownOnWindowClose) {
+  Widget* widget2 = CreateTopLevelNativeWidget();
+  widget2->Show();
+
+  std::unique_ptr<EventMonitor> monitor(EventMonitor::CreateWindowMonitor(
+      &observer_, widget2->GetNativeWindow(), {ui::ET_MOUSE_PRESSED}));
+
+  // Closing the widget before destroying the monitor should not crash.
+  widget2->CloseNow();
+  monitor.reset();
+}
+
 namespace {
 class DeleteOtherOnEventObserver : public ui::EventObserver {
  public:
diff --git a/ui/views/win/hwnd_message_handler.cc b/ui/views/win/hwnd_message_handler.cc
index a71728f..6fa8cd0 100644
--- a/ui/views/win/hwnd_message_handler.cc
+++ b/ui/views/win/hwnd_message_handler.cc
@@ -38,6 +38,7 @@
 #include "ui/base/win/internal_constants.h"
 #include "ui/base/win/lock_state.h"
 #include "ui/base/win/mouse_wheel_util.h"
+#include "ui/base/win/session_change_observer.h"
 #include "ui/base/win/shell.h"
 #include "ui/base/win/touch_input.h"
 #include "ui/display/win/dpi.h"
@@ -59,7 +60,6 @@
 #include "ui/views/win/fullscreen_handler.h"
 #include "ui/views/win/hwnd_message_handler_delegate.h"
 #include "ui/views/win/scoped_fullscreen_visibility.h"
-#include "ui/views/win/windows_session_change_observer.h"
 
 namespace views {
 namespace {
@@ -1596,9 +1596,9 @@
 
   delegate_->HandleCreate();
 
-  windows_session_change_observer_.reset(new WindowsSessionChangeObserver(
-      base::Bind(&HWNDMessageHandler::OnSessionChange,
-                 base::Unretained(this))));
+  session_change_observer_ =
+      std::make_unique<ui::SessionChangeObserver>(base::BindRepeating(
+          &HWNDMessageHandler::OnSessionChange, base::Unretained(this)));
 
   dpi_ = display::win::ScreenWin::GetDPIForHWND(hwnd());
 
@@ -1608,7 +1608,7 @@
 
 void HWNDMessageHandler::OnDestroy() {
   ::RemoveProp(hwnd(), ui::kWindowTranslucent);
-  windows_session_change_observer_.reset(nullptr);
+  session_change_observer_.reset(nullptr);
   delegate_->HandleDestroying();
   // If the window going away is a fullscreen window then remove its references
   // from the full screen window map.
diff --git a/ui/views/win/hwnd_message_handler.h b/ui/views/win/hwnd_message_handler.h
index ab13771..925996e3 100644
--- a/ui/views/win/hwnd_message_handler.h
+++ b/ui/views/win/hwnd_message_handler.h
@@ -44,13 +44,13 @@
 class InputMethod;
 class TextInputClient;
 class ViewProp;
+class SessionChangeObserver;
 }  // namespace ui
 
 namespace views {
 
 class FullscreenHandler;
 class HWNDMessageHandlerDelegate;
-class WindowsSessionChangeObserver;
 
 // These two messages aren't defined in winuser.h, but they are sent to windows
 // with captions. They appear to paint the window caption and frame.
@@ -708,8 +708,7 @@
   uint32_t current_window_size_message_ = 0;
 
   // Manages observation of Windows Session Change messages.
-  std::unique_ptr<WindowsSessionChangeObserver>
-      windows_session_change_observer_;
+  std::unique_ptr<ui::SessionChangeObserver> session_change_observer_;
 
   // Some assistive software need to track the location of the caret.
   std::unique_ptr<ui::AXSystemCaretWin> ax_system_caret_;
diff --git a/ui/views/win/windows_session_change_observer.h b/ui/views/win/windows_session_change_observer.h
deleted file mode 100644
index 38a3e08..0000000
--- a/ui/views/win/windows_session_change_observer.h
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_VIEWS_WIN_WINDOWS_SESSION_CHANGE_OBSERVER_H_
-#define UI_VIEWS_WIN_WINDOWS_SESSION_CHANGE_OBSERVER_H_
-
-#include <windows.h>
-
-#include "base/callback.h"
-#include "base/macros.h"
-
-namespace views {
-
-// Calls the provided callback on WM_WTSSESSION_CHANGE messages along with
-// managing the tricky business of observing a singleton object.
-class WindowsSessionChangeObserver {
- public:
-  typedef base::Callback<void(WPARAM)> WtsCallback;
-  explicit WindowsSessionChangeObserver(const WtsCallback& callback);
-  ~WindowsSessionChangeObserver();
-
- private:
-  class WtsRegistrationNotificationManager;
-
-  void OnSessionChange(WPARAM wparam);
-  void ClearCallback();
-
-  WtsCallback callback_;
-
-  DISALLOW_COPY_AND_ASSIGN(WindowsSessionChangeObserver);
-};
-
-}  // namespace views
-
-#endif  // UI_VIEWS_WIN_WINDOWS_SESSION_CHANGE_OBSERVER_H_