diff --git a/.gitignore b/.gitignore
index c6edf62..ed339d5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -158,6 +158,7 @@
 /chrome_elf/chrome_elf_resources.xml
 /chromecast/internal
 /chromeos/assistant/internal
+/cipd_cache/
 /clank
 /cloud_print/cloud_print_version_resources.xml
 /components/chrome_settings_proto_generated_compile.xml
diff --git a/DEPS b/DEPS
index 8c372fc..c7e8b6f 100644
--- a/DEPS
+++ b/DEPS
@@ -126,7 +126,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
-  'pdfium_revision': 'e4d73cba3c140f1d2fc5972c8cceb0d16af993ac',
+  'pdfium_revision': '7a01ce9f279be713947a74afe036aff495010371',
   # 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.
@@ -162,11 +162,11 @@
   # 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': 'c9718952e5d02e7003820e47503e9f9335f4a8c4',
+  'catapult_revision': 'eca23c365a07863178be2918fb2c97b23fa97381',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
-  'libfuzzer_revision': 'fda403cf93ecb8792cb1d061564d89a6553ca020',
+  'libfuzzer_revision': '873dc11d9a5281034e2cb74d0e87e9149a0e1045',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling devtools-node-modules
   # and whatever else without interference from each other.
@@ -286,7 +286,7 @@
   },
 
   'src/ios/third_party/material_components_ios/src': {
-      'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + '7e7ca3549d8e21c8749c3daf1f9a6dce5be840d3',
+      'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + '8fad5e937124a6b81415cb4fbc12dbef746af8e1',
       'condition': 'checkout_ios',
   },
 
@@ -540,7 +540,7 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '8e6f58c7e6150115b7885ba69c45bffb70fca9c3',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'e05f18d47735f3bc3f5808d0ce38a452b82d95e8',
 
   'src/third_party/devtools-node-modules':
     Var('chromium_git') + '/external/github.com/ChromeDevTools/devtools-node-modules' + '@' + Var('devtools_node_modules_revision'),
@@ -1007,7 +1007,7 @@
     Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '5e83981c2c44f24109b96b555d6865d481e0c609',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + 'ed51a6e6655a1d7f76b5b855d6589464ae95d830',
+    Var('webrtc_git') + '/src.git' + '@' + '2d611628313788e96a23d375db0a1b17fb6869e4',
 
   'src/third_party/xdg-utils': {
       'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d',
@@ -1041,7 +1041,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@fcf6e2b9826aaa0e8fa8f93d2239d351e162843c',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@119a08e0d996d388b87a41005af840f3344c6f88',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/PRESUBMIT.py b/PRESUBMIT.py
index 8d6e626..390701e 100644
--- a/PRESUBMIT.py
+++ b/PRESUBMIT.py
@@ -656,7 +656,8 @@
 _KNOWN_ROBOTS = set(
     '%s-chromium-autoroll@skia-buildbots.google.com.iam.gserviceaccount.com' % s
     for s in ('afdo', 'angle', 'catapult', 'chromite', 'depot-tools',
-              'fuchsia-sdk', 'nacl', 'pdfium', 'skia', 'src-internal', 'webrtc')
+              'fuchsia-sdk', 'nacl', 'pdfium', 'perfetto', 'skia',
+              'src-internal', 'webrtc')
   ) | set('%s@appspot.gserviceaccount.com' % s for s in ('findit-for-me',))
 
 
diff --git a/ash/app_list/app_list_controller_impl.cc b/ash/app_list/app_list_controller_impl.cc
index 4da849a..6aaac12 100644
--- a/ash/app_list/app_list_controller_impl.cc
+++ b/ash/app_list/app_list_controller_impl.cc
@@ -39,8 +39,6 @@
 
 namespace ash {
 
-// TODO(hejq): Get rid of AppListPresenterDelegateFactory and pass in
-// ash::AppListPresenterDelegate directly.
 AppListControllerImpl::AppListControllerImpl()
     : presenter_(std::make_unique<AppListPresenterDelegate>(), this),
       keyboard_observer_(this),
@@ -536,8 +534,11 @@
 
 void AppListControllerImpl::StartSearch(const base::string16& raw_query) {
   last_raw_query_ = raw_query;
-  if (client_)
-    client_->StartSearch(raw_query);
+  if (client_) {
+    base::string16 query;
+    base::TrimWhitespace(raw_query, base::TRIM_ALL, &query);
+    client_->StartSearch(query);
+  }
 }
 
 void AppListControllerImpl::OpenSearchResult(const std::string& result_id,
diff --git a/ash/app_list/model/folder_image.cc b/ash/app_list/model/folder_image.cc
index 387204c7..7484b49c 100644
--- a/ash/app_list/model/folder_image.cc
+++ b/ash/app_list/model/folder_image.cc
@@ -4,10 +4,12 @@
 
 #include "ash/app_list/model/folder_image.h"
 
+#include <memory>
 #include <vector>
 
 #include "ash/app_list/model/app_list_item.h"
 #include "ash/app_list/model/app_list_item_list.h"
+#include "ash/public/cpp/app_list/app_list_constants.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -27,9 +29,6 @@
 constexpr int kItemIconDimension = 16;
 constexpr float kFolderBubbleRadius = 23;
 constexpr float kFolderBubbleOffsetY = 1;
-// Keep this consistent with |kGridIconDimension| in app_list_constants.cc.
-// TODO(hejq): Figure out a way to consolidate the two.
-constexpr int kGridIconDimension = 48;
 
 // Gets the size of a small app icon inside the folder icon.
 gfx::Size ItemIconSize() {
diff --git a/ash/app_list/test/test_app_list_client.h b/ash/app_list/test/test_app_list_client.h
index 0ef6b11..f0e3702 100644
--- a/ash/app_list/test/test_app_list_client.h
+++ b/ash/app_list/test/test_app_list_client.h
@@ -23,7 +23,7 @@
   mojom::AppListClientPtr CreateInterfacePtrAndBind();
 
   // ash::mojom::AppListClient:
-  void StartSearch(const base::string16& raw_query) override {}
+  void StartSearch(const base::string16& trimmed_query) override {}
   void OpenSearchResult(const std::string& result_id,
                         int event_flags) override {}
   void InvokeSearchResultAction(const std::string& result_id,
diff --git a/ash/components/shortcut_viewer/shortcut_viewer_application.cc b/ash/components/shortcut_viewer/shortcut_viewer_application.cc
index 39e7860..62956a6 100644
--- a/ash/components/shortcut_viewer/shortcut_viewer_application.cc
+++ b/ash/components/shortcut_viewer/shortcut_viewer_application.cc
@@ -6,12 +6,15 @@
 
 #include "ash/components/shortcut_viewer/last_window_closed_observer.h"
 #include "ash/components/shortcut_viewer/views/keyboard_shortcut_view.h"
+#include "ash/public/cpp/mus_property_mirror_ash.h"
+#include "ash/public/cpp/window_properties.h"
 #include "base/time/time.h"
 #include "base/trace_event/trace_event.h"
 #include "services/service_manager/public/cpp/connector.h"
 #include "services/service_manager/public/cpp/service_context.h"
 #include "ui/events/devices/input_device_manager.h"
 #include "ui/views/mus/aura_init.h"
+#include "ui/views/mus/mus_client.h"
 
 namespace keyboard_shortcut_viewer {
 
@@ -38,6 +41,16 @@
     return;
   }
 
+  views::MusClient* mus_client = views::MusClient::Get();
+  aura::WindowTreeClientDelegate* delegate = mus_client;
+
+  // Registers ash specific window properties to be transported.
+  ash::RegisterWindowProperties(delegate->GetPropertyConverter());
+
+  // Setup property mirror between window and host.
+  mus_client->SetMusPropertyMirror(
+      std::make_unique<ash::MusPropertyMirrorAsh>());
+
   // Quit the application when the window is closed.
   last_window_closed_observer_ = std::make_unique<LastWindowClosedObserver>(
       context()->CreateQuitClosure());
diff --git a/ash/public/cpp/app_list/app_list_constants.cc b/ash/public/cpp/app_list/app_list_constants.cc
index 4e2b9c8b..5659d90 100644
--- a/ash/public/cpp/app_list/app_list_constants.cc
+++ b/ash/public/cpp/app_list/app_list_constants.cc
@@ -92,8 +92,6 @@
 // Preferred number of columns and rows in apps grid.
 const int kPreferredCols = 5;
 const int kPreferredRows = 5;
-// Keep |kGridIconDimension| in folder_image.cc consistent with this.
-// TODO(hejq): Figure out a way to consolidate the two.
 const int kGridIconDimension = 48;
 
 // The preferred app badge icon size.
diff --git a/ash/public/cpp/window_properties.cc b/ash/public/cpp/window_properties.cc
index 1b3fd66..07f0aabd 100644
--- a/ash/public/cpp/window_properties.cc
+++ b/ash/public/cpp/window_properties.cc
@@ -93,8 +93,13 @@
 DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(gfx::ImageSkia,
                                    kFrameImageActiveKey,
                                    nullptr);
+DEFINE_UI_CLASS_PROPERTY_KEY(bool, kHideInOverviewKey, false);
 DEFINE_UI_CLASS_PROPERTY_KEY(bool, kHideShelfWhenFullscreenKey, true);
+DEFINE_UI_CLASS_PROPERTY_KEY(bool,
+                             kIsDeferredTabDraggingTargetWindowKey,
+                             false);
 DEFINE_UI_CLASS_PROPERTY_KEY(bool, kIsDraggingTabsKey, false);
+DEFINE_UI_CLASS_PROPERTY_KEY(bool, kIsShowingInOverviewKey, false);
 DEFINE_UI_CLASS_PROPERTY_KEY(bool, kPanelAttachedKey, true);
 DEFINE_UI_CLASS_PROPERTY_KEY(bool, kRenderTitleAreaProperty, false);
 DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(gfx::Rect,
@@ -105,7 +110,6 @@
                              mojom::WindowStateType::DEFAULT);
 DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(std::string, kShelfIDKey, nullptr);
 DEFINE_UI_CLASS_PROPERTY_KEY(int32_t, kShelfItemTypeKey, TYPE_UNDEFINED);
-DEFINE_UI_CLASS_PROPERTY_KEY(bool, kShowInOverviewKey, true);
 DEFINE_UI_CLASS_PROPERTY_KEY(aura::Window*,
                              kTabDraggingSourceWindowKey,
                              nullptr);
diff --git a/ash/public/cpp/window_properties.h b/ash/public/cpp/window_properties.h
index e68cc90..3c96fcb 100644
--- a/ash/public/cpp/window_properties.h
+++ b/ash/public/cpp/window_properties.h
@@ -59,16 +59,31 @@
 ASH_PUBLIC_EXPORT extern const aura::WindowProperty<gfx::ImageSkia*>* const
     kFrameImageActiveKey;
 
+// A property key to indicate whether we should hide this window in overview
+// mode and Alt + Tab.
+ASH_PUBLIC_EXPORT extern const aura::WindowProperty<bool>* const
+    kHideInOverviewKey;
+
 // Whether the shelf should be hidden when this window is put into fullscreen.
 // Exposed because some windows want to explicitly opt-out of this.
 ASH_PUBLIC_EXPORT extern const aura::WindowProperty<bool>* const
     kHideShelfWhenFullscreenKey;
 
+// If true, the window is the target window for the tab-dragged window. The key
+// is used by overview to show a highlight indication to indicate which overview
+// window the dragged tabs will merge into when the user releases the pointer.
+ASH_PUBLIC_EXPORT extern const aura::WindowProperty<bool>* const
+    kIsDeferredTabDraggingTargetWindowKey;
+
 // If true, the window is a browser window and its tab(s) are currently being
 // dragged.
 ASH_PUBLIC_EXPORT extern const aura::WindowProperty<bool>* const
     kIsDraggingTabsKey;
 
+// If true, the window is currently showing in overview mode.
+ASH_PUBLIC_EXPORT extern const aura::WindowProperty<bool>* const
+    kIsShowingInOverviewKey;
+
 // If true (and the window is a panel), it's attached to its shelf item.
 ASH_PUBLIC_EXPORT extern const aura::WindowProperty<bool>* const
     kPanelAttachedKey;
@@ -98,11 +113,6 @@
 ASH_PUBLIC_EXPORT extern const aura::WindowProperty<int32_t>* const
     kShelfItemTypeKey;
 
-// A property key to indicate whether we should hide this window in overview
-// mode and Alt + Tab.
-ASH_PUBLIC_EXPORT extern const aura::WindowProperty<bool>* const
-    kShowInOverviewKey;
-
 // A property key to store the address of the source window that the drag
 // originated from if the window is currenlty in tab-dragging process.
 ASH_PUBLIC_EXPORT extern const aura::WindowProperty<aura::Window*>* const
diff --git a/ash/public/interfaces/app_list.mojom b/ash/public/interfaces/app_list.mojom
index 87e6e8f21..b52c372 100644
--- a/ash/public/interfaces/app_list.mojom
+++ b/ash/public/interfaces/app_list.mojom
@@ -306,8 +306,8 @@
   //////////////////////////////////////////////////////////////////////////////
   // Interfaces on searching:
   // Triggers a search query.
-  // |raw_query|: the unmodified input texts in the search text field.
-  StartSearch(mojo_base.mojom.String16 raw_query);
+  // |trimmed_query|: the trimmed input texts from the search text field.
+  StartSearch(mojo_base.mojom.String16 trimmed_query);
   // Opens a search result when its view is clicked or pressed.
   // |result_id|: the id of the search result the user wants to open.
   OpenSearchResult(string result_id, int32 event_flags);
diff --git a/ash/wm/mru_window_tracker.cc b/ash/wm/mru_window_tracker.cc
index e1ceb0a..6d46036 100644
--- a/ash/wm/mru_window_tracker.cc
+++ b/ash/wm/mru_window_tracker.cc
@@ -142,7 +142,7 @@
            window->GetRootWindow()
                ->GetChildById(kShellWindowId_AppListContainer)
                ->Contains(window) ||
-           !window->GetProperty(kShowInOverviewKey);
+           window->GetProperty(kHideInOverviewKey);
   };
   window_list.erase(std::remove_if(window_list.begin(), window_list.end(),
                                    window_is_ineligible),
diff --git a/ash/wm/overview/overview_window_drag_controller.cc b/ash/wm/overview/overview_window_drag_controller.cc
index a49c992..486781e 100644
--- a/ash/wm/overview/overview_window_drag_controller.cc
+++ b/ash/wm/overview/overview_window_drag_controller.cc
@@ -168,6 +168,9 @@
     if (std::abs(velocity_y) > kFlingToCloseVelocityThreshold) {
       item_->AnimateAndCloseWindow(
           (location_in_screen - initial_event_location_).y() < 0);
+      did_move_ = false;
+      item_ = nullptr;
+      current_drag_behavior_ = DragBehavior::kNoDrag;
       return;
     }
   }
diff --git a/ash/wm/overview/window_grid.cc b/ash/wm/overview/window_grid.cc
index 365c228..64751518 100644
--- a/ash/wm/overview/window_grid.cc
+++ b/ash/wm/overview/window_grid.cc
@@ -14,6 +14,7 @@
 #include "ash/public/cpp/shelf_types.h"
 #include "ash/public/cpp/shell_window_ids.h"
 #include "ash/public/cpp/wallpaper_types.h"
+#include "ash/public/cpp/window_properties.h"
 #include "ash/public/cpp/window_state_type.h"
 #include "ash/root_window_controller.h"
 #include "ash/screen_util.h"
@@ -481,10 +482,7 @@
 
 void WindowGrid::RemoveItem(WindowSelectorItem* selector_item) {
   auto iter =
-      std::find_if(window_list_.begin(), window_list_.end(),
-                   [selector_item](std::unique_ptr<WindowSelectorItem>& item) {
-                     return (item.get() == selector_item);
-                   });
+      GetWindowSelectorItemIterContainingWindow(selector_item->GetWindow());
   if (iter != window_list_.end()) {
     window_observer_.Remove(selector_item->GetWindow());
     window_state_observer_.Remove(
@@ -569,10 +567,7 @@
 void WindowGrid::OnWindowDestroying(aura::Window* window) {
   window_observer_.Remove(window);
   window_state_observer_.Remove(wm::GetWindowState(window));
-  auto iter = std::find_if(window_list_.begin(), window_list_.end(),
-                           [window](std::unique_ptr<WindowSelectorItem>& item) {
-                             return item->GetWindow() == window;
-                           });
+  auto iter = GetWindowSelectorItemIterContainingWindow(window);
   DCHECK(iter != window_list_.end());
 
   size_t removed_index = iter - window_list_.begin();
@@ -608,10 +603,7 @@
   if (!prepared_for_overview_)
     return;
 
-  auto iter = std::find_if(window_list_.begin(), window_list_.end(),
-                           [window](std::unique_ptr<WindowSelectorItem>& item) {
-                             return item->GetWindow() == window;
-                           });
+  auto iter = GetWindowSelectorItemIterContainingWindow(window);
   DCHECK(iter != window_list_.end());
 
   // Immediately finish any active bounds animation.
@@ -621,6 +613,34 @@
   PositionWindows(false);
 }
 
+void WindowGrid::OnWindowPropertyChanged(aura::Window* window,
+                                         const void* key,
+                                         intptr_t old) {
+  if (key == ash::kIsDeferredTabDraggingTargetWindowKey) {
+    if (window->GetProperty(ash::kIsDeferredTabDraggingTargetWindowKey)) {
+      // Show the selection widget.
+      auto iter = GetWindowSelectorItemIterContainingWindow(window);
+      size_t previous_selected_index = selected_index_;
+      selected_index_ = iter - window_list_.begin();
+      if (previous_selected_index == selected_index_ && selection_widget_)
+        return;
+
+      const WindowSelector::Direction direction =
+          (selected_index_ - previous_selected_index > 0)
+              ? WindowSelector::RIGHT
+              : WindowSelector::LEFT;
+      MoveSelectionWidget(direction,
+                          /*recreate_selection_widget=*/true,
+                          /*out_of_bounds=*/false,
+                          /*animate=*/false);
+    } else {
+      // Remove the selection widget.
+      SelectedWindow()->set_selected(false);
+      selection_widget_.reset();
+    }
+  }
+}
+
 void WindowGrid::OnPostWindowStateTypeChange(wm::WindowState* window_state,
                                              mojom::WindowStateType old_type) {
   // During preparation, window state can change, e.g. updating shelf
@@ -1000,4 +1020,12 @@
   }
 }
 
+std::vector<std::unique_ptr<WindowSelectorItem>>::iterator
+WindowGrid::GetWindowSelectorItemIterContainingWindow(aura::Window* window) {
+  return std::find_if(window_list_.begin(), window_list_.end(),
+                      [window](std::unique_ptr<WindowSelectorItem>& item) {
+                        return item->GetWindow() == window;
+                      });
+}
+
 }  // namespace ash
diff --git a/ash/wm/overview/window_grid.h b/ash/wm/overview/window_grid.h
index 3a115ce1..7a52902 100644
--- a/ash/wm/overview/window_grid.h
+++ b/ash/wm/overview/window_grid.h
@@ -157,6 +157,9 @@
                              const gfx::Rect& old_bounds,
                              const gfx::Rect& new_bounds,
                              ui::PropertyChangeReason reason) override;
+  void OnWindowPropertyChanged(aura::Window* window,
+                               const void* key,
+                               intptr_t old) override;
 
   // wm::WindowStateObserver:
   void OnPostWindowStateTypeChange(wm::WindowState* window_state,
@@ -246,6 +249,10 @@
       bool selected,
       WindowSelector::OverviewTransition transition);
 
+  // Returns the window selector item iterator that contains |window|.
+  std::vector<std::unique_ptr<WindowSelectorItem>>::iterator
+  GetWindowSelectorItemIterContainingWindow(aura::Window* window);
+
   // Root window the grid is in.
   aura::Window* root_window_;
 
diff --git a/ash/wm/overview/window_selector_controller.cc b/ash/wm/overview/window_selector_controller.cc
index 3d575ad3..f82dfec 100644
--- a/ash/wm/overview/window_selector_controller.cc
+++ b/ash/wm/overview/window_selector_controller.cc
@@ -39,7 +39,7 @@
 
 // Returns true if |window| should be hidden when entering overview.
 bool ShouldHideWindowInOverview(const aura::Window* window) {
-  return !window->GetProperty(ash::kShowInOverviewKey);
+  return window->GetProperty(ash::kHideInOverviewKey);
 }
 
 // Returns true if |window| should be excluded from overview.
diff --git a/ash/wm/overview/window_selector_item.cc b/ash/wm/overview/window_selector_item.cc
index 2c10e8c..4b041ef8 100644
--- a/ash/wm/overview/window_selector_item.cc
+++ b/ash/wm/overview/window_selector_item.cc
@@ -8,6 +8,7 @@
 #include <vector>
 
 #include "ash/public/cpp/shell_window_ids.h"
+#include "ash/public/cpp/window_properties.h"
 #include "ash/resources/vector_icons/vector_icons.h"
 #include "ash/shell.h"
 #include "ash/strings/grit/ash_strings.h"
@@ -683,10 +684,12 @@
       ScopedTransformOverviewWindow::GridWindowFillMode::kNormal) {
     backdrop_widget_ = CreateBackdropWidget(window->parent());
   }
+  GetWindow()->SetProperty(ash::kIsShowingInOverviewKey, true);
 }
 
 WindowSelectorItem::~WindowSelectorItem() {
   GetWindow()->RemoveObserver(this);
+  GetWindow()->ClearProperty(ash::kIsShowingInOverviewKey);
 }
 
 aura::Window* WindowSelectorItem::GetWindow() {
diff --git a/ash/wm/overview/window_selector_unittest.cc b/ash/wm/overview/window_selector_unittest.cc
index 2a2aa7d..52d85a1 100644
--- a/ash/wm/overview/window_selector_unittest.cc
+++ b/ash/wm/overview/window_selector_unittest.cc
@@ -929,7 +929,7 @@
   std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
   std::unique_ptr<aura::Window> window2(CreateWindow(bounds));
 
-  window2->SetProperty(ash::kShowInOverviewKey, false);
+  window2->SetProperty(ash::kHideInOverviewKey, true);
 
   // Enter overview.
   ToggleOverview();
diff --git a/ash/wm/splitview/split_view_controller.cc b/ash/wm/splitview/split_view_controller.cc
index 972c969..ccce1c5 100644
--- a/ash/wm/splitview/split_view_controller.cc
+++ b/ash/wm/splitview/split_view_controller.cc
@@ -676,7 +676,7 @@
   observer_ptr->OnSplitViewStateChanged(ToMojomSplitViewState(state_));
 }
 
-void SplitViewController::OnWindowDestroying(aura::Window* window) {
+void SplitViewController::OnWindowDestroyed(aura::Window* window) {
   DCHECK(IsSplitViewModeActive());
   DCHECK(window == left_window_ || window == right_window_);
   auto iter = overview_window_item_bounds_map_.find(window);
@@ -879,14 +879,15 @@
 
 void SplitViewController::StopObserving(SnapPosition snap_position) {
   aura::Window* window = snap_position == LEFT ? left_window_ : right_window_;
+  if (window == left_window_)
+    left_window_ = nullptr;
+  else
+    right_window_ = nullptr;
+
   if (window && window->HasObserver(this)) {
     window->RemoveObserver(this);
     wm::GetWindowState(window)->RemoveObserver(this);
     split_view_divider_->RemoveObservedWindow(window);
-    if (window == left_window_)
-      left_window_ = nullptr;
-    else
-      right_window_ = nullptr;
     Shell::Get()->shadow_controller()->UpdateShadowForWindow(window);
   }
 }
diff --git a/ash/wm/splitview/split_view_controller.h b/ash/wm/splitview/split_view_controller.h
index cb6c79c..11e94d70 100644
--- a/ash/wm/splitview/split_view_controller.h
+++ b/ash/wm/splitview/split_view_controller.h
@@ -152,7 +152,7 @@
   void AddObserver(mojom::SplitViewObserverPtr observer) override;
 
   // aura::WindowObserver:
-  void OnWindowDestroying(aura::Window* window) override;
+  void OnWindowDestroyed(aura::Window* window) override;
   void OnWindowPropertyChanged(aura::Window* window,
                                const void* key,
                                intptr_t old) override;
diff --git a/ash/wm/tablet_mode/tablet_mode_window_manager_unittest.cc b/ash/wm/tablet_mode/tablet_mode_window_manager_unittest.cc
index b770219..643b25e 100644
--- a/ash/wm/tablet_mode/tablet_mode_window_manager_unittest.cc
+++ b/ash/wm/tablet_mode/tablet_mode_window_manager_unittest.cc
@@ -1832,4 +1832,19 @@
   EXPECT_EQ(window->bounds(), rect);
 }
 
+// Test that if a window is currently in tab-dragging process, its window bounds
+// should not updated.
+TEST_F(TabletModeWindowManagerTest, DontChangeBoundsForTabDraggingWindow) {
+  gfx::Rect rect(0, 0, 200, 200);
+  std::unique_ptr<aura::Window> window(
+      CreateWindow(aura::client::WINDOW_TYPE_NORMAL, rect));
+  // Now put the window in tab-dragging process.
+  window->SetProperty(ash::kIsDraggingTabsKey, true);
+
+  TabletModeWindowManager* manager = CreateTabletModeWindowManager();
+  ASSERT_TRUE(manager);
+  EXPECT_EQ(1, manager->GetNumberOfManagedWindows());
+  EXPECT_EQ(window->bounds(), rect);
+}
+
 }  // namespace ash
diff --git a/ash/wm/tablet_mode/tablet_mode_window_resizer.cc b/ash/wm/tablet_mode/tablet_mode_window_resizer.cc
index 6933459..b7c6d471 100644
--- a/ash/wm/tablet_mode/tablet_mode_window_resizer.cc
+++ b/ash/wm/tablet_mode/tablet_mode_window_resizer.cc
@@ -8,7 +8,11 @@
 #include "ash/shell.h"
 #include "ash/shell_port.h"
 #include "ash/wm/drag_details.h"
+#include "ash/wm/overview/window_grid.h"
+#include "ash/wm/overview/window_selector.h"
 #include "ash/wm/overview/window_selector_controller.h"
+#include "ash/wm/overview/window_selector_item.h"
+#include "ash/wm/root_window_finder.h"
 #include "ash/wm/workspace/phantom_window_controller.h"
 #include "ui/aura/window.h"
 #include "ui/base/hit_test.h"
@@ -23,6 +27,26 @@
 // the phantom window.
 constexpr float kThresholdRatio = 0.25;
 
+// Returns true if overview mode is active and |location_in_screen| is contained
+// inside of the overview window grid.
+bool OverviewGridBoundsContains(const gfx::Point& location_in_screen) {
+  if (!Shell::Get()->window_selector_controller()->IsSelecting())
+    return false;
+
+  WindowSelector* window_selector =
+      Shell::Get()->window_selector_controller()->window_selector();
+  WindowGrid* current_grid = window_selector->GetGridWithRootWindow(
+      wm::GetRootWindowAt(location_in_screen));
+  if (!current_grid)
+    return false;
+
+  const auto& windows = current_grid->window_list();
+  gfx::Rect windows_bounds;
+  for (const auto& window_selector_item : windows)
+    windows_bounds.Union(window_selector_item->target_bounds());
+  return windows_bounds.Contains(location_in_screen);
+}
+
 }  // namespace
 
 TabletModeWindowResizer::TabletModeWindowResizer(wm::WindowState* window_state)
@@ -125,6 +149,13 @@
 SplitViewController::SnapPosition
 TabletModeWindowResizer::GetSnapPositionForPhantomWindow(
     const gfx::Point& location_in_parent) const {
+  // If the overview mode is active and |location_in_parent| is contained in
+  // overview window grid, do not show the phantom window.
+  gfx::Point location_in_screen = location_in_parent;
+  ::wm::ConvertPointToScreen(GetTarget()->parent(), &location_in_screen);
+  if (OverviewGridBoundsContains(location_in_screen))
+    return SplitViewController::NONE;
+
   const gfx::Rect work_area_bounds(
       screen_util::GetDisplayWorkAreaBoundsInParent(GetTarget()));
 
@@ -133,8 +164,6 @@
   if (location_in_parent.y() < vertical_threshold)
     return SplitViewController::NONE;
 
-  gfx::Point location_in_screen(location_in_parent);
-  ::wm::ConvertPointToScreen(GetTarget()->parent(), &location_in_screen);
   const int divider_position =
       split_view_controller_->IsSplitViewModeActive()
           ? split_view_controller_->divider_position()
diff --git a/ash/wm/tablet_mode/tablet_mode_window_state.cc b/ash/wm/tablet_mode/tablet_mode_window_state.cc
index 940a99d..30d163d 100644
--- a/ash/wm/tablet_mode/tablet_mode_window_state.cc
+++ b/ash/wm/tablet_mode/tablet_mode_window_state.cc
@@ -17,6 +17,7 @@
 #include "ash/wm/window_animation_types.h"
 #include "ash/wm/window_properties.h"
 #include "ash/wm/window_state_util.h"
+#include "ash/wm/window_util.h"
 #include "ash/wm/wm_event.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_delegate.h"
@@ -204,12 +205,18 @@
                    true /* animated */);
       return;
     case wm::WM_EVENT_SNAP_LEFT:
+      // Set bounds_changed_by_user to true to avoid WindowPositioner to auto
+      // place the window.
+      window_state->set_bounds_changed_by_user(true);
       UpdateWindow(window_state,
                    GetSnappedWindowStateType(
                        window_state, mojom::WindowStateType::LEFT_SNAPPED),
                    false /* animated */);
       return;
     case wm::WM_EVENT_SNAP_RIGHT:
+      // Set bounds_changed_by_user to true to avoid WindowPositioner to auto
+      // place the window.
+      window_state->set_bounds_changed_by_user(true);
       UpdateWindow(window_state,
                    GetSnappedWindowStateType(
                        window_state, mojom::WindowStateType::RIGHT_SNAPPED),
@@ -227,7 +234,7 @@
       if (bounds_in_parent.IsEmpty())
         return;
 
-      if (window_state->is_dragged()) {
+      if (wm::IsDraggingTabs(window_state->window())) {
         window_state->SetBoundsDirect(bounds_in_parent);
       } else if (current_state_type_ == mojom::WindowStateType::MAXIMIZED) {
         // Having a maximized window, it could have been created with an empty
@@ -383,6 +390,11 @@
   if (defer_bounds_updates_)
     return;
 
+  // Do not update window's bounds if it's in tab-dragging process. The bounds
+  // will be updated later when the drag ends.
+  if (wm::IsDraggingTabs(window_state->window()))
+    return;
+
   // Do not update minimized windows bounds until it was unminimized.
   if (current_state_type_ == mojom::WindowStateType::MINIMIZED)
     return;
diff --git a/ash/wm/window_cycle_controller_unittest.cc b/ash/wm/window_cycle_controller_unittest.cc
index d1f0eab..701b216 100644
--- a/ash/wm/window_cycle_controller_unittest.cc
+++ b/ash/wm/window_cycle_controller_unittest.cc
@@ -260,7 +260,7 @@
   modal_window.reset();
   std::unique_ptr<Window> skip_overview_window(
       CreateTestWindowInShellWithId(-3));
-  skip_overview_window->SetProperty(kShowInOverviewKey, false);
+  skip_overview_window->SetProperty(kHideInOverviewKey, true);
   wm::ActivateWindow(window0.get());
   wm::ActivateWindow(skip_overview_window.get());
   wm::ActivateWindow(window1.get());
diff --git a/base/BUILD.gn b/base/BUILD.gn
index ae80ce4..eb424816 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -813,6 +813,7 @@
     "task/sequence_manager/lazy_now.cc",
     "task/sequence_manager/lazy_now.h",
     "task/sequence_manager/sequenced_task_source.h",
+    "task/sequence_manager/task_queue.h",
     "task/sequence_manager/thread_controller.h",
     "task_runner.cc",
     "task_runner.h",
diff --git a/base/android/java/src/org/chromium/base/ApiCompatibilityUtils.java b/base/android/java/src/org/chromium/base/ApiCompatibilityUtils.java
index a85ab39..fc2f600 100644
--- a/base/android/java/src/org/chromium/base/ApiCompatibilityUtils.java
+++ b/base/android/java/src/org/chromium/base/ApiCompatibilityUtils.java
@@ -13,7 +13,6 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
-import android.content.res.ColorStateList;
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.content.res.Resources.NotFoundException;
@@ -563,18 +562,6 @@
     }
 
     /**
-     * @see android.content.res.Resources#getColorStateList(int id).
-     */
-    @SuppressWarnings("deprecation")
-    public static ColorStateList getColorStateList(Resources res, int id) throws NotFoundException {
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
-            return res.getColorStateList(id, null);
-        } else {
-            return res.getColorStateList(id);
-        }
-    }
-
-    /**
      * @see android.widget.TextView#setTextAppearance(int id).
      */
     @SuppressWarnings("deprecation")
diff --git a/base/logging_unittest.cc b/base/logging_unittest.cc
index 9025aaf4..35ceba1 100644
--- a/base/logging_unittest.cc
+++ b/base/logging_unittest.cc
@@ -30,7 +30,13 @@
 #endif  // OS_WIN
 
 #if defined(OS_FUCHSIA)
+#include <zircon/process.h>
+#include <zircon/syscalls.h>
+#include <zircon/syscalls/debug.h>
+#include <zircon/syscalls/exception.h>
+#include <zircon/syscalls/port.h>
 #include "base/fuchsia/fuchsia_logging.h"
+#include "base/fuchsia/scoped_zx_handle.h"
 #endif
 
 namespace logging {
@@ -279,9 +285,127 @@
   EXPECT_NE(addr1, addr3);
   EXPECT_NE(addr2, addr3);
 }
+#elif defined(OS_FUCHSIA)
 
+// CHECK causes a direct crash (without jumping to another function) only in
+// official builds. Unfortunately, continuous test coverage on official builds
+// is lower. Furthermore, since the Fuchsia implementation uses threads, it is
+// not possible to rely on an implementation of CHECK that calls abort(), which
+// takes down the whole process, preventing the thread exception handler from
+// handling the exception. DO_CHECK here falls back on IMMEDIATE_CRASH() in
+// non-official builds, to catch regressions earlier in the CQ.
+#if defined(OFFICIAL_BUILD)
+#define DO_CHECK CHECK
+#else
+#define DO_CHECK(cond) \
+  if (!(cond)) {       \
+    IMMEDIATE_CRASH(); \
+  }
+#endif
+
+static const unsigned int kExceptionPortKey = 1u;
+static const unsigned int kThreadEndedPortKey = 2u;
+
+struct thread_data_t {
+  // For signaling the thread ended properly.
+  zx_handle_t event;
+  // For registering thread termination.
+  zx_handle_t port;
+  // Location where the thread is expected to crash.
+  int death_location;
+};
+
+void* CrashThread(void* arg) {
+  zx_status_t status;
+
+  thread_data_t* data = (thread_data_t*)arg;
+  int death_location = data->death_location;
+
+  // Register the exception handler on the port.
+  status = zx_task_bind_exception_port(zx_thread_self(), data->port,
+                                       kExceptionPortKey, 0);
+  if (status != ZX_OK) {
+    zx_object_signal(data->event, 0, ZX_USER_SIGNAL_0);
+    return nullptr;
+  }
+
+  DO_CHECK(death_location != 1);
+  DO_CHECK(death_location != 2);
+  DO_CHECK(death_location != 3);
+
+  // We should never reach this point, signal the thread incorrectly ended
+  // properly.
+  zx_object_signal(data->event, 0, ZX_USER_SIGNAL_0);
+  return nullptr;
+}
+
+// Runs the CrashThread function in a separate thread.
+void SpawnCrashThread(int death_location, uintptr_t* child_crash_addr) {
+  base::ScopedZxHandle port;
+  base::ScopedZxHandle event;
+  zx_status_t status;
+
+  status = zx_port_create(0, port.receive());
+  ASSERT_EQ(status, ZX_OK);
+  status = zx_event_create(0, event.receive());
+  ASSERT_EQ(status, ZX_OK);
+
+  // Register the thread ended event on the port.
+  status = zx_object_wait_async(event.get(), port.get(), kThreadEndedPortKey,
+                                ZX_USER_SIGNAL_0, ZX_WAIT_ASYNC_ONCE);
+  ASSERT_EQ(status, ZX_OK);
+
+  // Run the thread.
+  thread_data_t thread_data = {event.get(), port.get(), death_location};
+  pthread_t thread;
+  int ret = pthread_create(&thread, nullptr, CrashThread, &thread_data);
+  ASSERT_EQ(ret, 0);
+
+  // Wait on the port.
+  zx_port_packet_t packet;
+  status = zx_port_wait(port.get(), ZX_TIME_INFINITE, &packet);
+  ASSERT_EQ(status, ZX_OK);
+  // Check the thread did crash and not terminate.
+  ASSERT_EQ(packet.key, kExceptionPortKey);
+
+  // Get the crash address.
+  zx_handle_t zircon_thread;
+  status = zx_object_get_child(zx_process_self(), packet.exception.tid,
+                               ZX_RIGHT_SAME_RIGHTS, &zircon_thread);
+  ASSERT_EQ(status, ZX_OK);
+  zx_thread_state_general_regs_t buffer;
+  status = zx_thread_read_state(zircon_thread, ZX_THREAD_STATE_GENERAL_REGS,
+                                &buffer, sizeof(buffer));
+  ASSERT_EQ(status, ZX_OK);
+#if defined(ARCH_CPU_X86_64)
+  *child_crash_addr = static_cast<uintptr_t>(buffer.rip);
+#elif defined(ARCH_CPU_ARM64)
+  *child_crash_addr = static_cast<uintptr_t>(buffer.pc);
+#else
+#error Unsupported architecture
+#endif
+
+  status = zx_task_kill(zircon_thread);
+  ASSERT_EQ(status, ZX_OK);
+}
+
+TEST_F(LoggingTest, CheckCausesDistinctBreakpoints) {
+  uintptr_t child_crash_addr_1 = 0;
+  uintptr_t child_crash_addr_2 = 0;
+  uintptr_t child_crash_addr_3 = 0;
+
+  SpawnCrashThread(1, &child_crash_addr_1);
+  SpawnCrashThread(2, &child_crash_addr_2);
+  SpawnCrashThread(3, &child_crash_addr_3);
+
+  ASSERT_NE(0u, child_crash_addr_1);
+  ASSERT_NE(0u, child_crash_addr_2);
+  ASSERT_NE(0u, child_crash_addr_3);
+  ASSERT_NE(child_crash_addr_1, child_crash_addr_2);
+  ASSERT_NE(child_crash_addr_1, child_crash_addr_3);
+  ASSERT_NE(child_crash_addr_2, child_crash_addr_3);
+}
 #elif defined(OS_POSIX) && !defined(OS_NACL) && !defined(OS_IOS) && \
-    !defined(OS_FUCHSIA) &&                                         \
     (defined(ARCH_CPU_X86_FAMILY) || defined(ARCH_CPU_ARM_FAMILY))
 
 int g_child_crash_pipe;
diff --git a/base/optional.h b/base/optional.h
index c1d11ca..8b570ccd 100644
--- a/base/optional.h
+++ b/base/optional.h
@@ -575,32 +575,32 @@
   }
 
   constexpr const T* operator->() const {
-    CHECK(storage_.is_populated_);
+    DCHECK(storage_.is_populated_);
     return &storage_.value_;
   }
 
   constexpr T* operator->() {
-    CHECK(storage_.is_populated_);
+    DCHECK(storage_.is_populated_);
     return &storage_.value_;
   }
 
   constexpr const T& operator*() const & {
-    CHECK(storage_.is_populated_);
+    DCHECK(storage_.is_populated_);
     return storage_.value_;
   }
 
   constexpr T& operator*() & {
-    CHECK(storage_.is_populated_);
+    DCHECK(storage_.is_populated_);
     return storage_.value_;
   }
 
   constexpr const T&& operator*() const && {
-    CHECK(storage_.is_populated_);
+    DCHECK(storage_.is_populated_);
     return std::move(storage_.value_);
   }
 
   constexpr T&& operator*() && {
-    CHECK(storage_.is_populated_);
+    DCHECK(storage_.is_populated_);
     return std::move(storage_.value_);
   }
 
diff --git a/base/profiler/stack_sampling_profiler.h b/base/profiler/stack_sampling_profiler.h
index 2f9ade5..c268064 100644
--- a/base/profiler/stack_sampling_profiler.h
+++ b/base/profiler/stack_sampling_profiler.h
@@ -23,7 +23,6 @@
 
 namespace base {
 
-class NativeStackSampler;
 class NativeStackSamplerTestDelegate;
 
 // StackSamplingProfiler periodically stops a thread to sample its stack, for
@@ -297,10 +296,6 @@
   // when that sampling is complete and the callback done.
   WaitableEvent profiling_inactive_;
 
-  // Object that does the native sampling. This is created during construction
-  // and later passed to the sampling thread when profiling is started.
-  std::unique_ptr<NativeStackSampler> native_sampler_;
-
   // An ID uniquely identifying this profiler to the sampling thread. This
   // will be an internal "null" value when no collection has been started.
   int profiler_id_;
diff --git a/third_party/blink/renderer/platform/scheduler/base/moveable_auto_lock.h b/base/task/sequence_manager/moveable_auto_lock.h
similarity index 65%
rename from third_party/blink/renderer/platform/scheduler/base/moveable_auto_lock.h
rename to base/task/sequence_manager/moveable_auto_lock.h
index 4065ebe..a80d5f8 100644
--- a/third_party/blink/renderer/platform/scheduler/base/moveable_auto_lock.h
+++ b/base/task/sequence_manager/moveable_auto_lock.h
@@ -1,9 +1,9 @@
-// Copyright 2016 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 THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_MOVEABLE_AUTO_LOCK_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_MOVEABLE_AUTO_LOCK_H_
+#ifndef BASE_TASK_SEQUENCE_MANAGER_MOVEABLE_AUTO_LOCK_H_
+#define BASE_TASK_SEQUENCE_MANAGER_MOVEABLE_AUTO_LOCK_H_
 
 #include "base/synchronization/lock.h"
 
@@ -16,7 +16,7 @@
     lock_.Acquire();
   }
 
-  MoveableAutoLock(MoveableAutoLock&& other)
+  MoveableAutoLock(MoveableAutoLock&& other) noexcept
       : lock_(other.lock_), moved_(other.moved_) {
     lock_.AssertAcquired();
     other.moved_ = true;
@@ -38,4 +38,4 @@
 }  // namespace sequence_manager
 }  // namespace base
 
-#endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_MOVEABLE_AUTO_LOCK_H_
+#endif  // BASE_TASK_SEQUENCE_MANAGER_MOVEABLE_AUTO_LOCK_H_
diff --git a/third_party/blink/renderer/platform/scheduler/base/task_queue.h b/base/task/sequence_manager/task_queue.h
similarity index 86%
rename from third_party/blink/renderer/platform/scheduler/base/task_queue.h
rename to base/task/sequence_manager/task_queue.h
index 1fa4792..1da30484 100644
--- a/third_party/blink/renderer/platform/scheduler/base/task_queue.h
+++ b/base/task/sequence_manager/task_queue.h
@@ -1,9 +1,9 @@
-// Copyright 2015 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 THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_TASK_QUEUE_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_TASK_QUEUE_H_
+#ifndef BASE_TASK_SEQUENCE_MANAGER_TASK_QUEUE_H_
+#define BASE_TASK_SEQUENCE_MANAGER_TASK_QUEUE_H_
 
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
@@ -11,31 +11,37 @@
 #include "base/optional.h"
 #include "base/single_thread_task_runner.h"
 #include "base/synchronization/lock.h"
+#include "base/task/sequence_manager/moveable_auto_lock.h"
 #include "base/threading/platform_thread.h"
 #include "base/time/time.h"
-#include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/scheduler/base/graceful_queue_shutdown_helper.h"
-#include "third_party/blink/renderer/platform/scheduler/base/moveable_auto_lock.h"
+
+// Currently the implementation is located in Blink because scheduler/base move
+// is in progress https://crbug.com/783309.
+// TODO(kraynov): Remove this hack ASAP.
+#ifndef HACKDEF_INCLUDED_FROM_BLINK
+// Need PLATFORM_EXPORT macro.
+#error Use third_party/blink/renderer/platform/scheduler/base/task_queue_forward.h.
+#endif
 
 namespace base {
+
 namespace trace_event {
 class BlameContext;
 }
-}  // namespace base
 
-namespace base {
 namespace sequence_manager {
 
 namespace internal {
 class TaskQueueImpl;
-}
+class GracefulQueueShutdownHelper;
+}  // namespace internal
 
 class TimeDomain;
 class TaskQueueManagerImpl;
 
 class PLATFORM_EXPORT TaskQueue : public SingleThreadTaskRunner {
  public:
-  class PLATFORM_EXPORT Observer {
+  class Observer {
    public:
     virtual ~Observer() = default;
 
@@ -71,10 +77,12 @@
     int task_type;
   };
 
-  // Unregisters the task queue after which no tasks posted to it will run and
-  // the TaskQueueManagerImpl's reference to it will be released soon.
+  // Prepare the task queue to get released.
+  // All tasks posted after this call will be discarded.
   virtual void ShutdownTaskQueue();
 
+  // TODO(scheduler-dev): Could we define a more clear list of priorities?
+  // See https://crbug.com/847858.
   enum QueuePriority {
     // Queues with control priority will run before any other queue, and will
     // explicitly starve other queues. Typically this should only be used for
@@ -183,8 +191,8 @@
   bool HasTaskToRunImmediately() const;
 
   // Returns requested run time of next scheduled wake-up for a delayed task
-  // which is not ready to run. If there are no such tasks or the queue is
-  // disabled (by a QueueEnabledVoter) it returns nullopt.
+  // which is not ready to run. If there are no such tasks (immediate tasks
+  // don't count) or the queue is disabled it returns nullopt.
   // NOTE: this must be called on the thread this TaskQueue was created by.
   Optional<TimeTicks> GetNextScheduledWakeUp();
 
@@ -244,6 +252,9 @@
   // blocked by it.
   void RemoveFence();
 
+  // Returns true if the queue has a fence but it isn't necessarily blocking
+  // execution of tasks (it may be the case if tasks enqueue order hasn't
+  // reached the number set for a fence).
   bool HasActiveFence();
 
   // Returns true if the queue has a fence which is blocking execution of tasks.
@@ -277,7 +288,10 @@
 
   Optional<MoveableAutoLock> AcquireImplReadLockIfNeeded() const;
 
-  // Take |impl_| and untie it from the enclosing task queue.
+  // TaskQueue has ownership of an underlying implementation but in certain
+  // cases (e.g. detached frames) their lifetime may diverge.
+  // This method should be used to take away the impl for graceful shutdown.
+  // TaskQueue will disregard any calls or posting tasks thereafter.
   std::unique_ptr<internal::TaskQueueImpl> TakeTaskQueueImpl();
 
   // |impl_| can be written to on the main thread but can be read from
@@ -303,4 +317,4 @@
 }  // namespace sequence_manager
 }  // namespace base
 
-#endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_TASK_QUEUE_H_
+#endif  // BASE_TASK_SEQUENCE_MANAGER_TASK_QUEUE_H_
diff --git a/base/test/OWNERS b/base/test/OWNERS
index 68077483..9c9069f 100644
--- a/base/test/OWNERS
+++ b/base/test/OWNERS
@@ -1,7 +1,6 @@
 per-file *task_scheduler*=file://base/task_scheduler/OWNERS
 
 # Metrics-related test utilites:
-per-file *histogram_tester*=file://base/metrics/OWNERS
 per-file *scoped_feature_list*=file://base/metrics/OWNERS
 per-file *user_action_tester*=file://base/metrics/OWNERS
 
diff --git a/build/android/buildhooks/BUILD.gn b/build/android/buildhooks/BUILD.gn
index 0ccd4ce..65009143 100644
--- a/build/android/buildhooks/BUILD.gn
+++ b/build/android/buildhooks/BUILD.gn
@@ -43,7 +43,6 @@
 
   jar_excluded_patterns = [ "*/BuildHooksAndroidImpl.class" ]
   no_build_hooks = true
-  proguard_configs = [ "proguard/build_hooks_android_impl.flags" ]
 }
 
 # This default implementation is used if an android_apk target doesn't
diff --git a/build/android/buildhooks/java/org/chromium/build/BuildHooksAndroid.java b/build/android/buildhooks/java/org/chromium/build/BuildHooksAndroid.java
index f6fef20..fdf0a86 100644
--- a/build/android/buildhooks/java/org/chromium/build/BuildHooksAndroid.java
+++ b/build/android/buildhooks/java/org/chromium/build/BuildHooksAndroid.java
@@ -19,79 +19,54 @@
  * implementation is supplied to an android_apk target (via build_hooks_android_impl_deps).
  */
 public abstract class BuildHooksAndroid {
-    private static BuildHooksAndroid sInstance;
-
-    private static BuildHooksAndroid get() {
-        if (sInstance == null) {
-            sInstance = constructBuildHooksAndroidImpl();
-        }
-        return sInstance;
-    }
-
-    // Creates an instance of BuildHooksAndroidImpl using reflection. Why is this necessary?
-    // The downstream version of BuildHooksAndroidImpl pulls a bunch of methods into the main dex
-    // that don't actually need to be there. This happens because there are @MainDex classes that
-    // have Context methods added (via. bytecode rewriting) that call into BuildHooksAndroid.
-    // Creating the instance via. reflection tricks proguard into thinking BuildHooksAndroidImpl
-    // doesn't need to be in the main dex file.
-    private static BuildHooksAndroid constructBuildHooksAndroidImpl() {
-        try {
-            // Not final to avoid inlining. Without this proguard is able to figure out that
-            // BuildHooksAndroidImpl is actually used.
-            String implClazzName = "org.chromium.build.BuildHooksAndroidImpl";
-            Class<?> implClazz = Class.forName(implClazzName);
-            return (BuildHooksAndroid) implClazz.newInstance();
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        }
-    }
+    private static final BuildHooksAndroidImpl sInstance = new BuildHooksAndroidImpl();
 
     public static Resources getResources(Context context) {
-        return get().getResourcesImpl(context);
+        return sInstance.getResourcesImpl(context);
     }
 
     protected abstract Resources getResourcesImpl(Context context);
 
     public static AssetManager getAssets(Context context) {
-        return get().getAssetsImpl(context);
+        return sInstance.getAssetsImpl(context);
     }
 
     protected abstract AssetManager getAssetsImpl(Context context);
 
     public static Resources.Theme getTheme(Context context) {
-        return get().getThemeImpl(context);
+        return sInstance.getThemeImpl(context);
     }
 
     protected abstract Resources.Theme getThemeImpl(Context context);
 
     public static void setTheme(Context context, int theme) {
-        get().setThemeImpl(context, theme);
+        sInstance.setThemeImpl(context, theme);
     }
 
     protected abstract void setThemeImpl(Context context, int theme);
 
     public static Context createConfigurationContext(Context context) {
-        return get().createConfigurationContextImpl(context);
+        return sInstance.createConfigurationContextImpl(context);
     }
 
     protected abstract Context createConfigurationContextImpl(Context context);
 
     public static int getIdentifier(
             Resources resources, String name, String defType, String defPackage) {
-        return get().getIdentifierImpl(resources, name, defType, defPackage);
+        return sInstance.getIdentifierImpl(resources, name, defType, defPackage);
     }
 
     protected abstract int getIdentifierImpl(
             Resources resources, String name, String defType, String defPackage);
 
     public static boolean isEnabled() {
-        return get().isEnabledImpl();
+        return sInstance.isEnabledImpl();
     }
 
     protected abstract boolean isEnabledImpl();
 
     public static void initCustomResources(Context context) {
-        get().initCustomResourcesImpl(context);
+        sInstance.initCustomResourcesImpl(context);
     }
 
     protected abstract void initCustomResourcesImpl(Context context);
@@ -100,7 +75,7 @@
      * Record custom resources related UMA. Requires native library to be loaded.
      */
     public static void maybeRecordResourceMetrics() {
-        get().maybeRecordResourceMetricsImpl();
+        sInstance.maybeRecordResourceMetricsImpl();
     }
 
     protected abstract void maybeRecordResourceMetricsImpl();
diff --git a/build/android/buildhooks/proguard/build_hooks_android_impl.flags b/build/android/buildhooks/proguard/build_hooks_android_impl.flags
deleted file mode 100644
index 62dc1aa0..0000000
--- a/build/android/buildhooks/proguard/build_hooks_android_impl.flags
+++ /dev/null
@@ -1,5 +0,0 @@
-# Copyright 2018 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
--keep class org.chromium.build.BuildHooksAndroidImpl
diff --git a/build/chromeos/run_vm_test.py b/build/chromeos/run_vm_test.py
index 06a05f3..069a788 100755
--- a/build/chromeos/run_vm_test.py
+++ b/build/chromeos/run_vm_test.py
@@ -227,6 +227,7 @@
       child.kill()
   signal.signal(signal.SIGTERM, _kill_child_procs)
   test_proc.wait()
+  rc = test_proc.returncode
 
   # Create a simple json results file for the sanity test if needed. The results
   # will contain only one test ('cros_vm_sanity_test'), and will either be a
@@ -241,7 +242,7 @@
     with open(args.test_launcher_summary_output, 'w') as f:
       json.dump(json_results.GenerateResultsDict([run_results]), f)
 
-  return test_proc.returncode
+  return rc
 
 
 def main():
diff --git a/build/config/fuchsia/build_manifest.py b/build/config/fuchsia/build_manifest.py
index 0fc8b74..bc3df01 100644
--- a/build/config/fuchsia/build_manifest.py
+++ b/build/config/fuchsia/build_manifest.py
@@ -208,15 +208,25 @@
     if not app_found:
       raise Exception('Could not locate executable inside runtime_deps.')
 
+    # Write meta/package manifest file.
     with open(os.path.join(os.path.dirname(output_path), 'package'), 'w') \
         as package_json:
       json.dump({'version': '0', 'name': app_name}, package_json)
       manifest.write('meta/package=%s\n' %
                    os.path.relpath(package_json.name, out_dir))
 
-    manifest.write('meta/sandbox=%s\n' %
-                 os.path.relpath(os.path.join(root_dir, sandbox_policy_path),
-                                 out_dir))
+    # Write component manifest file.
+    with open(os.path.join(os.path.dirname(output_path),
+                           app_name + '.cmx'), 'w') as component_manifest_file:
+      component_manifest = {
+          'program': { 'binary': 'bin/app' },
+          'sandbox': json.load(open(sandbox_policy_path, 'r')),
+      }
+      json.dump(component_manifest, component_manifest_file)
+      manifest.write('meta/%s=%s\n' %
+                     (os.path.basename(component_manifest_file.name),
+                      os.path.relpath(component_manifest_file.name, out_dir)))
+
     depfile.write(
         "%s: %s" % (os.path.relpath(output_path, out_dir),
                     " ".join([os.path.relpath(f, out_dir)
diff --git a/build/util/branding.gni b/build/util/branding.gni
index 2a229f1..cadd1a3 100644
--- a/build/util/branding.gni
+++ b/build/util/branding.gni
@@ -20,8 +20,7 @@
     "bundle_id = \"@MAC_BUNDLE_ID@\" " +
     "creator_code = \"@MAC_CREATOR_CODE@\" " +
     "installer_full_name = \"@PRODUCT_INSTALLER_FULLNAME@\" " +
-    "installer_short_name = \"@PRODUCT_INSTALLER_SHORTNAME@\" " +
-    "team_id = \"@MAC_TEAM_ID@\" "
+    "installer_short_name = \"@PRODUCT_INSTALLER_SHORTNAME@\" "
 
 _branding_file = "//chrome/app/theme/$branding_path_component/BRANDING"
 _result = exec_script("version.py",
@@ -42,5 +41,4 @@
 if (is_mac) {
   chrome_mac_bundle_id = _result.bundle_id
   chrome_mac_creator_code = _result.creator_code
-  chrome_mac_team_id = _result.team_id
 }
diff --git a/chrome/BUILD.gn b/chrome/BUILD.gn
index d6dff68..8b985d5 100644
--- a/chrome/BUILD.gn
+++ b/chrome/BUILD.gn
@@ -33,7 +33,6 @@
   import("//build/linux/extract_symbols.gni")
 } else if (is_mac) {
   import("//build/compiled_action.gni")
-  import("//build/config/mac/base_rules.gni")
   import("//build/config/mac/rules.gni")
   import("//build/config/mac/symbols.gni")
   import("//build/mac/tweak_info_plist.gni")
@@ -797,16 +796,6 @@
     ]
   }
 
-  compile_entitlements("entitlements") {
-    entitlements_templates = [ "app/entitlements.plist" ]
-    output_name = "$target_gen_dir/entitlements.plist"
-    substitutions = [
-      "CHROMIUM_BUNDLE_ID=$chrome_mac_bundle_id",
-      "CHROMIUM_TEAM_ID=$chrome_mac_team_id",
-    ]
-    visibility = [ "//chrome/installer/mac:copies" ]
-  }
-
   mac_app_bundle("chrome_helper_app") {
     output_name = chrome_helper_name
 
diff --git a/chrome/android/chrome_public_apk_tmpl.gni b/chrome/android/chrome_public_apk_tmpl.gni
index a0dbf3d9..e8ee0426 100644
--- a/chrome/android/chrome_public_apk_tmpl.gni
+++ b/chrome/android/chrome_public_apk_tmpl.gni
@@ -79,11 +79,6 @@
           "*R\$*",  # Should not use resources from non-browser process.
         ]
       }
-
-      # Allow targets to append to the default list.
-      if (defined(extra_negative_main_dex_globs)) {
-        negative_main_dex_globs += extra_negative_main_dex_globs
-      }
     }
     if (!is_java_debug) {
       proguard_enabled = true
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedNewTabPage.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedNewTabPage.java
index 6f1caceb..77bf440 100644
--- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedNewTabPage.java
+++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedNewTabPage.java
@@ -10,18 +10,12 @@
 import android.view.View;
 import android.widget.FrameLayout;
 
-import com.google.android.libraries.feed.api.common.ThreadUtils;
 import com.google.android.libraries.feed.api.scope.FeedProcessScope;
 import com.google.android.libraries.feed.api.scope.FeedStreamScope;
 import com.google.android.libraries.feed.api.stream.Stream;
-import com.google.android.libraries.feed.common.time.SystemClockImpl;
 import com.google.android.libraries.feed.host.config.Configuration;
-import com.google.android.libraries.feed.host.config.Configuration.ConfigKey;
-import com.google.android.libraries.feed.host.config.DebugBehavior;
 import com.google.android.libraries.feed.host.stream.CardConfiguration;
 import com.google.android.libraries.feed.host.stream.StreamConfiguration;
-import com.google.android.libraries.feed.hostimpl.logging.LoggingApiImpl;
-import com.google.android.libraries.feed.hostimpl.scheduler.TimeoutScheduler;
 
 import org.chromium.base.ApiCompatibilityUtils;
 import org.chromium.chrome.R;
@@ -34,14 +28,10 @@
 import org.chromium.chrome.browser.suggestions.SuggestionsNavigationDelegateImpl;
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
 
-import java.util.concurrent.Executors;
-
 /**
  * Provides a new tab page that displays an interest feed rendered list of content suggestions.
  */
 public class FeedNewTabPage extends BasicNativePage {
-    private static FeedProcessScope sFeedProcessScope;
-
     private FrameLayout mRootView;
     private String mTitle;
     private FeedImageLoader mImageLoader;
@@ -118,35 +108,18 @@
         super(activity, nativePageHost);
 
         Profile profile = nativePageHost.getActiveTab().getProfile();
-        Configuration configHostApi =
-                new Configuration.Builder()
-                        .put(ConfigKey.FEED_SERVER_HOST, "https://www.google.com")
-                        .put(ConfigKey.FEED_SERVER_PATH_AND_PARAMS,
-                                "/httpservice/noretry/NowStreamService/FeedQuery")
-                        .put(ConfigKey.SESSION_LIFETIME_MS, 300000L)
-                        .build();
-
-        if (sFeedProcessScope == null) {
-            sFeedProcessScope =
-                    new FeedProcessScope
-                            .Builder(configHostApi, Executors.newSingleThreadExecutor(),
-                                    new LoggingApiImpl(), new FeedNetworkBridge(profile),
-                                    new TimeoutScheduler(new ThreadUtils(), new SystemClockImpl(),
-                                            configHostApi),
-                                    DebugBehavior.SILENT)
-                            .build();
-        }
-
+        FeedProcessScope feedProcessScope = FeedProcessScopeFactory.getFeedProcessScope();
         mImageLoader = new FeedImageLoader(profile, activity);
         SuggestionsNavigationDelegateImpl navigationDelegate =
                 new SuggestionsNavigationDelegateImpl(
                         activity, profile, nativePageHost, tabModelSelector);
         FeedStreamScope streamScope =
-                sFeedProcessScope
+                feedProcessScope
                         .createFeedStreamScopeBuilder(activity, mImageLoader,
                                 new FeedActionHandler(navigationDelegate),
                                 new BasicStreamConfiguration(activity.getResources()),
-                                new BasicCardConfiguration(activity.getResources()), configHostApi)
+                                new BasicCardConfiguration(activity.getResources()),
+                                new Configuration.Builder().build())
                         .build();
 
         Stream stream = streamScope.getStream();
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedProcessScopeFactory.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedProcessScopeFactory.java
new file mode 100644
index 0000000..b93965f
--- /dev/null
+++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedProcessScopeFactory.java
@@ -0,0 +1,45 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.feed;
+
+import com.google.android.libraries.feed.api.scope.FeedProcessScope;
+import com.google.android.libraries.feed.host.config.Configuration;
+import com.google.android.libraries.feed.host.config.Configuration.ConfigKey;
+import com.google.android.libraries.feed.host.config.DebugBehavior;
+import com.google.android.libraries.feed.hostimpl.logging.LoggingApiImpl;
+
+import org.chromium.chrome.browser.profiles.Profile;
+
+import java.util.concurrent.Executors;
+
+/**
+ * Holds singleton {@link FeedProcessScope}.
+ */
+public class FeedProcessScopeFactory {
+    private static FeedProcessScope sFeedProcessScope;
+
+    /**
+     * @return The shared {@link FeedProcessScope} instance.
+     */
+    public static FeedProcessScope getFeedProcessScope() {
+        if (sFeedProcessScope == null) {
+            Profile profile = Profile.getLastUsedProfile().getOriginalProfile();
+            Configuration configHostApi =
+                    new Configuration.Builder()
+                            .put(ConfigKey.FEED_SERVER_HOST, "https://www.google.com")
+                            .put(ConfigKey.FEED_SERVER_PATH_AND_PARAMS,
+                                    "/httpservice/noretry/NowStreamService/FeedQuery")
+                            .put(ConfigKey.SESSION_LIFETIME_MS, 300000L)
+                            .build();
+            sFeedProcessScope =
+                    new FeedProcessScope
+                            .Builder(configHostApi, Executors.newSingleThreadExecutor(),
+                                    new LoggingApiImpl(), new FeedNetworkBridge(profile),
+                                    new FeedSchedulerBridge(profile), DebugBehavior.SILENT)
+                            .build();
+        }
+        return sFeedProcessScope;
+    }
+}
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSchedulerBridge.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSchedulerBridge.java
index 1e16567..dc7b882 100644
--- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSchedulerBridge.java
+++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSchedulerBridge.java
@@ -104,9 +104,8 @@
 
     private native long nativeInit(Profile profile);
     private native void nativeDestroy(long nativeFeedSchedulerBridge);
-    private native @NativeRequestBehavior int nativeShouldSessionRequestData(
-            long nativeFeedSchedulerBridge, boolean hasContent, long contentCreationDateTimeMs,
-            boolean hasOutstandingRequest);
+    private native int nativeShouldSessionRequestData(long nativeFeedSchedulerBridge,
+            boolean hasContent, long contentCreationDateTimeMs, boolean hasOutstandingRequest);
     private native void nativeOnReceiveNewContent(long nativeFeedSchedulerBridge);
     private native void nativeOnRequestError(
             long nativeFeedSchedulerBridge, int networkResponseCode);
diff --git a/chrome/android/feed/feed_java_sources.gni b/chrome/android/feed/feed_java_sources.gni
index b0a70cd..d08a933e8 100644
--- a/chrome/android/feed/feed_java_sources.gni
+++ b/chrome/android/feed/feed_java_sources.gni
@@ -13,6 +13,7 @@
     "//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedImageLoaderBridge.java",
     "//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedNetworkBridge.java",
     "//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedNewTabPage.java",
+    "//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedProcessScopeFactory.java",
     "//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSchedulerBridge.java",
     "//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/action/FeedActionHandler.java",
   ]
diff --git a/chrome/android/java/res/layout/accept_languages_item.xml b/chrome/android/java/res/layout/accept_languages_item.xml
index 4379f99..92729a7a 100644
--- a/chrome/android/java/res/layout/accept_languages_item.xml
+++ b/chrome/android/java/res/layout/accept_languages_item.xml
@@ -5,7 +5,7 @@
 
 <LinearLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:chrome="http://schemas.android.com/apk/res-auto"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
     xmlns:tools="http://schemas.android.com/tools"
     android:id="@+id/language_item"
     android:layout_marginStart="0dp"
@@ -46,7 +46,7 @@
         android:paddingEnd="@dimen/selectable_list_layout_row_padding"
         android:background="@null"
         android:src="@drawable/ic_more_vert_black_24dp"
-        chrome:menuWidth="@dimen/pref_languages_item_popup_width"
-        chrome:chrometint="@color/dark_mode_tint"
+        app:menuWidth="@dimen/pref_languages_item_popup_width"
+        app:chrometint="@color/dark_mode_tint"
         tools:ignore="ContentDescription" />
 </LinearLayout>
diff --git a/chrome/android/java/res/layout/accessibility_tab_switcher.xml b/chrome/android/java/res/layout/accessibility_tab_switcher.xml
index 686a7d6..a8ba536d 100644
--- a/chrome/android/java/res/layout/accessibility_tab_switcher.xml
+++ b/chrome/android/java/res/layout/accessibility_tab_switcher.xml
@@ -9,7 +9,6 @@
 <org.chromium.chrome.browser.widget.accessibility.AccessibilityTabModelWrapper
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
-    xmlns:chrome="http://schemas.android.com/apk/res-auto"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:orientation="vertical"
@@ -62,7 +61,7 @@
             android:layout_weight="1"
             android:background="@drawable/btn_bg_holo_active"
             android:src="@drawable/btn_normal_tabs"
-            chrome:chrometint="@color/light_mode_tint"
+            app:chrometint="@color/light_mode_tint"
             android:contentDescription="@string/accessibility_tab_switcher_standard_stack"
             style="?android:attr/borderlessButtonStyle" />
 
@@ -78,7 +77,7 @@
             android:layout_height="wrap_content"
             android:layout_weight="1"
             android:src="@drawable/btn_incognito_tabs"
-            chrome:chrometint="@color/light_mode_tint"
+            app:chrometint="@color/light_mode_tint"
             android:background="@drawable/btn_bg_holo"
             android:contentDescription="@string/accessibility_tab_switcher_incognito_stack"
             style="?android:attr/borderlessButtonStyle" />
diff --git a/chrome/android/java/res/layout/accessibility_tab_switcher_list_item.xml b/chrome/android/java/res/layout/accessibility_tab_switcher_list_item.xml
index 1d138d6..58e3f2b3 100644
--- a/chrome/android/java/res/layout/accessibility_tab_switcher_list_item.xml
+++ b/chrome/android/java/res/layout/accessibility_tab_switcher_list_item.xml
@@ -8,7 +8,7 @@
 
 <org.chromium.chrome.browser.widget.accessibility.AccessibilityTabModelListItem
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:chrome="http://schemas.android.com/apk/res-auto"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
     android:id="@+id/list_item_frame"
     android:layout_width="match_parent"
     android:layout_height="@dimen/accessibility_tab_height">
@@ -51,7 +51,7 @@
             android:padding="4dp"
             android:background="?attr/selectableItemBackground"
             android:src="@drawable/btn_close"
-            chrome:chrometint="@color/light_mode_tint"
+            app:chrometint="@color/light_mode_tint"
             android:gravity="end|center_vertical" />
     </LinearLayout>
 
diff --git a/chrome/android/java/res/layout/account_signin_view.xml b/chrome/android/java/res/layout/account_signin_view.xml
index 17d9c39..fcf1d4f7 100644
--- a/chrome/android/java/res/layout/account_signin_view.xml
+++ b/chrome/android/java/res/layout/account_signin_view.xml
@@ -6,7 +6,7 @@
 -->
 <org.chromium.chrome.browser.signin.AccountSigninView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:chrome="http://schemas.android.com/apk/res-auto"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:background="@color/signin_body_background">
@@ -213,8 +213,8 @@
             android:paddingEnd="@dimen/fre_button_padding"
             android:textAllCaps="true"
             style="@style/WhiteBody"
-            chrome:buttonColor="@color/light_active_color"
-            chrome:buttonRaised="false"/>
+            app:buttonColor="@color/light_active_color"
+            app:buttonRaised="false"/>
 
         <Button
             android:id="@+id/more_button"
diff --git a/chrome/android/java/res/layout/bookmark_add_edit_folder_activity.xml b/chrome/android/java/res/layout/bookmark_add_edit_folder_activity.xml
index 86daf6b..c3397d7 100644
--- a/chrome/android/java/res/layout/bookmark_add_edit_folder_activity.xml
+++ b/chrome/android/java/res/layout/bookmark_add_edit_folder_activity.xml
@@ -5,7 +5,7 @@
 
 <merge
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:chrome="http://schemas.android.com/apk/res-auto"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
     android:minHeight="@dimen/bookmark_minimum_dialog_size_tablet" >
 
     <ScrollView
@@ -32,7 +32,7 @@
                 android:imeOptions="flagNoExtractUi"
                 android:inputType="textCapSentences|textAutoCorrect"
                 android:textAppearance="@style/BlackHeadline1"
-                chrome:alertMessage="@string/bookmark_missing_title"  />
+                app:alertMessage="@string/bookmark_missing_title"  />
 
             <TextView
                 android:layout_width="wrap_content"
diff --git a/chrome/android/java/res/layout/bookmark_edit.xml b/chrome/android/java/res/layout/bookmark_edit.xml
index 2cbd156..1648d5d 100644
--- a/chrome/android/java/res/layout/bookmark_edit.xml
+++ b/chrome/android/java/res/layout/bookmark_edit.xml
@@ -5,7 +5,7 @@
      found in the LICENSE file.
 -->
 <merge xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:chrome="http://schemas.android.com/apk/res-auto" >
+    xmlns:app="http://schemas.android.com/apk/res-auto" >
 
     <ScrollView
         android:id="@+id/scroll_view"
@@ -33,7 +33,7 @@
                     android:imeOptions="flagNoExtractUi"
                     android:inputType="textCapSentences|textAutoCorrect"
                     android:singleLine="true"
-                    chrome:alertMessage="@string/bookmark_missing_title" />
+                    app:alertMessage="@string/bookmark_missing_title" />
             </org.chromium.chrome.browser.widget.CompatibilityTextInputLayout>
 
             <TextView
@@ -69,7 +69,7 @@
                     android:imeOptions="flagNoExtractUi"
                     android:inputType="textUri"
                     android:singleLine="true"
-                    chrome:alertMessage="@string/bookmark_missing_url" />
+                    app:alertMessage="@string/bookmark_missing_url" />
             </org.chromium.chrome.browser.widget.CompatibilityTextInputLayout>
         </LinearLayout>
     </ScrollView>
diff --git a/chrome/android/java/res/layout/bookmark_row_content.xml b/chrome/android/java/res/layout/bookmark_row_content.xml
index badc1a2..0dbe641 100644
--- a/chrome/android/java/res/layout/bookmark_row_content.xml
+++ b/chrome/android/java/res/layout/bookmark_row_content.xml
@@ -5,8 +5,7 @@
      found in the LICENSE file.
 -->
 
-<merge xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:chrome="http://schemas.android.com/apk/res-auto" >
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
 
     <LinearLayout
         android:id="@+id/bookmark_row"
diff --git a/chrome/android/java/res/layout/button_preference_button.xml b/chrome/android/java/res/layout/button_preference_button.xml
index 76e950d..d5dd9ab 100644
--- a/chrome/android/java/res/layout/button_preference_button.xml
+++ b/chrome/android/java/res/layout/button_preference_button.xml
@@ -8,11 +8,11 @@
      See crbug.com/674736 -->
 <org.chromium.ui.widget.ButtonCompat
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:chrome="http://schemas.android.com/apk/res-auto"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
     android:id="@+id/button_preference"
     android:layout_height="wrap_content"
     android:layout_width="wrap_content"
     android:minHeight="40dp"
     android:focusable="false"
     android:textColor="@android:color/white"
-    chrome:buttonColor="@color/pref_accent_color" />
+    app:buttonColor="@color/pref_accent_color" />
diff --git a/chrome/android/java/res/layout/button_preference_layout.xml b/chrome/android/java/res/layout/button_preference_layout.xml
index aac3f17..573e3976 100644
--- a/chrome/android/java/res/layout/button_preference_layout.xml
+++ b/chrome/android/java/res/layout/button_preference_layout.xml
@@ -6,11 +6,10 @@
 <!-- Layout used by ButtonPreference for the button widget style. -->
 <LinearLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:chrome="http://schemas.android.com/apk/res-auto"
     style="@style/PreferenceLayout"
     android:id="@android:id/widget_frame"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:clipToPadding="false"
     android:gravity="center_vertical"
-    android:orientation="vertical" />
+    android:orientation="vertical"/>
diff --git a/chrome/android/java/res/layout/clear_storage.xml b/chrome/android/java/res/layout/clear_storage.xml
index 02898a8..de067072 100644
--- a/chrome/android/java/res/layout/clear_storage.xml
+++ b/chrome/android/java/res/layout/clear_storage.xml
@@ -5,9 +5,9 @@
 
 <org.chromium.chrome.browser.widget.TintedImageView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:chrome="http://schemas.android.com/apk/res-auto"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:contentDescription="@string/webstorage_clear_data_dialog_title"
     android:src="@drawable/ic_delete_white_24dp"
-    chrome:chrometint="@color/blue_mode_tint"/>
+    app:chrometint="@color/blue_mode_tint"/>
diff --git a/chrome/android/java/res/layout/content_suggestions_all_dismissed_card_modern.xml b/chrome/android/java/res/layout/content_suggestions_all_dismissed_card_modern.xml
index 6c612bc..bfd9dd36 100644
--- a/chrome/android/java/res/layout/content_suggestions_all_dismissed_card_modern.xml
+++ b/chrome/android/java/res/layout/content_suggestions_all_dismissed_card_modern.xml
@@ -5,7 +5,7 @@
 
 <RelativeLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:chrome="http://schemas.android.com/apk/res-auto"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:padding="@dimen/snippets_padding"
@@ -35,7 +35,7 @@
         android:gravity="center_horizontal"
         android:text="@string/ntp_title_no_suggestions"
         android:textAppearance="@style/BlackTitle1"
-        chrome:leading="24dp" />
+        app:leading="24dp" />
 
     <org.chromium.ui.widget.TextViewWithLeading
         android:id="@+id/body_text"
@@ -47,7 +47,7 @@
         android:text="@string/ntp_all_dismissed_body_text_morning"
         android:textSize="14sp"
         android:textColor="@color/snippets_text_color"
-        chrome:leading="20dp" />
+        app:leading="20dp" />
 
     <Button
         android:id="@+id/action_button"
diff --git a/chrome/android/java/res/layout/contextual_search_promo_view.xml b/chrome/android/java/res/layout/contextual_search_promo_view.xml
index 8b61e815..c3d984d 100644
--- a/chrome/android/java/res/layout/contextual_search_promo_view.xml
+++ b/chrome/android/java/res/layout/contextual_search_promo_view.xml
@@ -5,7 +5,7 @@
 
 <RelativeLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:chrome="http://schemas.android.com/apk/res-auto"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
     android:id="@+id/contextual_search_promo"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
@@ -44,7 +44,7 @@
         android:textAllCaps="true"
         android:textColor="#FFF"
         android:textSize="14sp"
-        chrome:buttonColor="@color/light_active_color" />
+        app:buttonColor="@color/light_active_color" />
 
     <Button
         android:id="@+id/contextual_search_no_thanks_button"
diff --git a/chrome/android/java/res/layout/contextual_suggestions_toolbar.xml b/chrome/android/java/res/layout/contextual_suggestions_toolbar.xml
index 139e7fa..25171fd 100644
--- a/chrome/android/java/res/layout/contextual_suggestions_toolbar.xml
+++ b/chrome/android/java/res/layout/contextual_suggestions_toolbar.xml
@@ -5,7 +5,7 @@
 
 <org.chromium.chrome.browser.contextual_suggestions.ToolbarView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:chrome="http://schemas.android.com/apk/res-auto"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
     xmlns:tools="http://schemas.android.com/tools"
     android:layout_width="match_parent"
     android:layout_height="wrap_content" >
@@ -21,7 +21,7 @@
         android:src="@drawable/ic_expand_less_black_24dp"
         android:scaleType="center"
         android:visibility="gone"
-        chrome:chrometint="@color/dark_mode_tint" />
+        app:chrometint="@color/dark_mode_tint" />
 
     <LinearLayout
         android:id="@+id/main_content"
@@ -56,7 +56,7 @@
             android:layout_height="match_parent"
             android:background="?attr/selectableItemBackground"
             android:src="@drawable/ic_more_vert_black_24dp"
-            chrome:chrometint="@color/dark_mode_tint"
+            app:chrometint="@color/dark_mode_tint"
             tools:ignore="ContentDescription" />
 
         <org.chromium.chrome.browser.widget.TintedImageButton
diff --git a/chrome/android/java/res/layout/custom_tabs_bottombar.xml b/chrome/android/java/res/layout/custom_tabs_bottombar.xml
index d322e86..3fc7bd3 100644
--- a/chrome/android/java/res/layout/custom_tabs_bottombar.xml
+++ b/chrome/android/java/res/layout/custom_tabs_bottombar.xml
@@ -3,11 +3,11 @@
      Use of this source code is governed by a BSD-style license that can be
      found in the LICENSE file. -->
 <org.chromium.chrome.browser.widget.BoundedLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:chrome="http://schemas.android.com/apk/res-auto"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:orientation="vertical"
-    chrome:maxHeight="@dimen/custom_tabs_bottom_bar_max_height" >
+    app:maxHeight="@dimen/custom_tabs_bottom_bar_max_height" >
 
     <View
         android:id="@+id/bottombar_shadow"
diff --git a/chrome/android/java/res/layout/custom_tabs_toolbar.xml b/chrome/android/java/res/layout/custom_tabs_toolbar.xml
index 1e282760..634bd5e6 100644
--- a/chrome/android/java/res/layout/custom_tabs_toolbar.xml
+++ b/chrome/android/java/res/layout/custom_tabs_toolbar.xml
@@ -5,10 +5,9 @@
 
 <org.chromium.chrome.browser.toolbar.CustomTabToolbar
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:chrome="http://schemas.android.com/apk/res-auto"
     android:id="@+id/toolbar"
     android:layout_width="match_parent"
-    android:layout_height="@dimen/custom_tabs_control_container_height" >
+    android:layout_height="@dimen/custom_tabs_control_container_height">
     <ImageButton
         android:id="@+id/close_button"
         style="@style/ToolbarButton"
diff --git a/chrome/android/java/res/layout/data_reduction_main_menu_item.xml b/chrome/android/java/res/layout/data_reduction_main_menu_item.xml
index a298cef..c55784e 100644
--- a/chrome/android/java/res/layout/data_reduction_main_menu_item.xml
+++ b/chrome/android/java/res/layout/data_reduction_main_menu_item.xml
@@ -5,7 +5,6 @@
 
 <org.chromium.chrome.browser.preferences.datareduction.DataReductionMainMenuItem
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:chrome="http://schemas.android.com/apk/res-auto"
     android:id="@+id/data_reduction_menu_item"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
diff --git a/chrome/android/java/res/layout/data_usage_breakdown.xml b/chrome/android/java/res/layout/data_usage_breakdown.xml
index df02b63..9622d4f 100644
--- a/chrome/android/java/res/layout/data_usage_breakdown.xml
+++ b/chrome/android/java/res/layout/data_usage_breakdown.xml
@@ -5,7 +5,6 @@
 
 <org.chromium.chrome.browser.preferences.datareduction.DataReductionSiteBreakdownView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:settings="http://schemas.android.com/apk/res-auto"
     android:id="@+id/breakdown"
     android:layout_height="wrap_content"
     android:layout_width="match_parent"
diff --git a/chrome/android/java/res/layout/data_usage_breakdown_row.xml b/chrome/android/java/res/layout/data_usage_breakdown_row.xml
index df7f6b29..6f6b9cb 100644
--- a/chrome/android/java/res/layout/data_usage_breakdown_row.xml
+++ b/chrome/android/java/res/layout/data_usage_breakdown_row.xml
@@ -5,7 +5,6 @@
 
 <TableRow
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:settings="http://schemas.android.com/apk/res-auto"
     android:id="@+id/site_row"
     android:layout_width="match_parent">
 
diff --git a/chrome/android/java/res/layout/data_usage_chart.xml b/chrome/android/java/res/layout/data_usage_chart.xml
index 1122d93..ed37e4a 100644
--- a/chrome/android/java/res/layout/data_usage_chart.xml
+++ b/chrome/android/java/res/layout/data_usage_chart.xml
@@ -5,7 +5,7 @@
 
 <org.chromium.third_party.android.datausagechart.ChartDataUsageView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:settings="http://schemas.android.com/apk/res-auto"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
     android:id="@+id/chart"
     android:layout_width="match_parent"
     android:layout_height="@dimen/data_usage_chart_height"
@@ -17,16 +17,16 @@
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:background="@color/data_reduction_chart_background_color"
-        settings:strokeColor="@color/data_reduction_original_color"
-        settings:fillColor="@color/data_reduction_original_color"
-        settings:fillColorSecondary="@color/data_reduction_original_color" />
+        app:strokeColor="@color/data_reduction_original_color"
+        app:fillColor="@color/data_reduction_original_color"
+        app:fillColorSecondary="@color/data_reduction_original_color" />
 
     <org.chromium.third_party.android.datausagechart.ChartNetworkSeriesView
         android:id="@id/compressed_series"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
-        settings:strokeColor="@color/data_reduction_compressed_color"
-        settings:fillColor="@color/data_reduction_compressed_color"
-        settings:fillColorSecondary="@color/data_reduction_compressed_color" />
+        app:strokeColor="@color/data_reduction_compressed_color"
+        app:fillColor="@color/data_reduction_compressed_color"
+        app:fillColorSecondary="@color/data_reduction_compressed_color" />
 
 </org.chromium.third_party.android.datausagechart.ChartDataUsageView>
diff --git a/chrome/android/java/res/layout/default_search_engine_first_run_fragment.xml b/chrome/android/java/res/layout/default_search_engine_first_run_fragment.xml
index 63904d5..37c7c4c 100644
--- a/chrome/android/java/res/layout/default_search_engine_first_run_fragment.xml
+++ b/chrome/android/java/res/layout/default_search_engine_first_run_fragment.xml
@@ -7,7 +7,7 @@
 <!-- Layout used to present a set of default search engines to the user. -->
 <LinearLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:chrome="http://schemas.android.com/apk/res-auto"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:background="@color/signin_body_background"
@@ -82,7 +82,7 @@
         android:textAllCaps="true"
         android:textColor="@android:color/white"
         android:textSize="14sp"
-        chrome:buttonColor="@color/light_active_color"
-        chrome:buttonRaised="false" />
+        app:buttonColor="@color/light_active_color"
+        app:buttonRaised="false" />
 
 </LinearLayout>
diff --git a/chrome/android/java/res/layout/download_item_view.xml b/chrome/android/java/res/layout/download_item_view.xml
index 2c4dff8..8de50d3e 100644
--- a/chrome/android/java/res/layout/download_item_view.xml
+++ b/chrome/android/java/res/layout/download_item_view.xml
@@ -6,7 +6,7 @@
 <!-- Represents a single item in the DownloadHistoryAdapterView. -->
 <view class="org.chromium.chrome.browser.download.ui.DownloadItemView"
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:chrome="http://schemas.android.com/apk/res-auto"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
     android:layout_width="match_parent"
     android:layout_height="wrap_content" >
 
@@ -68,9 +68,9 @@
                     android:layout_below="@+id/filename_progress_view"
                     android:layout_alignParentStart="true"
                     android:layout_toStartOf="@+id/pause_button"
-                    chrome:colorBackground="@color/google_grey_400"
-                    chrome:colorProgress="@color/light_active_color"
-                    chrome:colorSecondaryProgress="@color/google_grey_600" />
+                    app:colorBackground="@color/google_grey_400"
+                    app:colorProgress="@color/light_active_color"
+                    app:colorSecondaryProgress="@color/google_grey_600" />
 
             <TextView
                     android:id="@+id/status_view"
@@ -101,7 +101,7 @@
                     android:background="?attr/selectableItemBackground"
                     android:contentDescription="@string/download_notification_pause_button"
                     android:src="@drawable/ic_pause_white_24dp"
-                    chrome:chrometint="@color/google_grey_600" />
+                    app:chrometint="@color/google_grey_600" />
 
             <org.chromium.chrome.browser.widget.TintedImageButton
                     android:id="@+id/cancel_button"
@@ -115,7 +115,7 @@
                     android:background="?attr/selectableItemBackground"
                     android:contentDescription="@string/download_notification_cancel_button"
                     android:src="@drawable/btn_close"
-                    chrome:chrometint="@color/google_grey_600" />
+                    app:chrometint="@color/google_grey_600" />
         </RelativeLayout>
     </LinearLayout>
 </view>
diff --git a/chrome/android/java/res/layout/download_location_dialog.xml b/chrome/android/java/res/layout/download_location_dialog.xml
index cd37ca6..2755899 100644
--- a/chrome/android/java/res/layout/download_location_dialog.xml
+++ b/chrome/android/java/res/layout/download_location_dialog.xml
@@ -5,7 +5,7 @@
 
 <ScrollView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:tools="http://schemas.android.com/apk/res-auto"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
     android:layout_width="match_parent"
     android:layout_height="wrap_content" >
 
@@ -31,7 +31,7 @@
             <org.chromium.chrome.browser.widget.TintedImageView
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                tools:srcCompat="@drawable/ic_drive_file_24dp"
+                app:srcCompat="@drawable/ic_drive_file_24dp"
                 android:tint="@color/black_alpha_87"
                 style="@style/ListItemStartIcon" />
 
diff --git a/chrome/android/java/res/layout/download_manager_ui_space_widget.xml b/chrome/android/java/res/layout/download_manager_ui_space_widget.xml
index 87c8f9e..8cff29c 100644
--- a/chrome/android/java/res/layout/download_manager_ui_space_widget.xml
+++ b/chrome/android/java/res/layout/download_manager_ui_space_widget.xml
@@ -5,7 +5,7 @@
 
 <LinearLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:chrome="http://schemas.android.com/apk/res-auto"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:paddingTop="11dp"
@@ -34,9 +34,9 @@
             android:layout_height="2dp"
             android:layout_marginTop="8dp"
             android:layout_marginBottom="8dp"
-            chrome:colorBackground="@color/google_grey_300"
-            chrome:colorProgress="@color/google_blue_500_alpha_38_opaque"
-            chrome:colorSecondaryProgress="@color/google_blue_500" />
+            app:colorBackground="@color/google_grey_300"
+            app:colorProgress="@color/google_blue_500_alpha_38_opaque"
+            app:colorSecondaryProgress="@color/google_blue_500" />
 
         <TextView
             android:id="@+id/size_free_and_other_apps"
diff --git a/chrome/android/java/res/layout/empty_background_view_tablet.xml b/chrome/android/java/res/layout/empty_background_view_tablet.xml
index 253b0a73..212b92a 100644
--- a/chrome/android/java/res/layout/empty_background_view_tablet.xml
+++ b/chrome/android/java/res/layout/empty_background_view_tablet.xml
@@ -5,7 +5,7 @@
 
 <org.chromium.chrome.browser.widget.emptybackground.EmptyBackgroundViewTablet
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:chrome="http://schemas.android.com/apk/res-auto"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
     android:id="@+id/empty_container"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
@@ -52,7 +52,7 @@
             android:scaleType="center"
             android:contentDescription="@string/accessibility_toolbar_btn_menu"
             android:paddingStart="2dp"
-            chrome:chrometint="@color/light_mode_tint"
+            app:chrometint="@color/light_mode_tint"
             />
     </LinearLayout>
 </org.chromium.chrome.browser.widget.emptybackground.EmptyBackgroundViewTablet>
diff --git a/chrome/android/java/res/layout/fre_data_reduction_proxy.xml b/chrome/android/java/res/layout/fre_data_reduction_proxy.xml
index d631c4d..9ac58326 100644
--- a/chrome/android/java/res/layout/fre_data_reduction_proxy.xml
+++ b/chrome/android/java/res/layout/fre_data_reduction_proxy.xml
@@ -6,7 +6,7 @@
 -->
 <org.chromium.chrome.browser.firstrun.FirstRunView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:chrome="http://schemas.android.com/apk/res-auto"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
     android:layout_width="match_parent"
     android:layout_height="match_parent">
 
@@ -90,6 +90,6 @@
         android:text="@string/next"
         android:textAllCaps="true"
         style="@style/WhiteBody"
-        chrome:buttonColor="@color/light_active_color"
-        chrome:buttonRaised="false"/>
+        app:buttonColor="@color/light_active_color"
+        app:buttonRaised="false"/>
 </org.chromium.chrome.browser.firstrun.FirstRunView>
\ No newline at end of file
diff --git a/chrome/android/java/res/layout/fre_tosanduma.xml b/chrome/android/java/res/layout/fre_tosanduma.xml
index 532e429..52f4994c 100644
--- a/chrome/android/java/res/layout/fre_tosanduma.xml
+++ b/chrome/android/java/res/layout/fre_tosanduma.xml
@@ -6,7 +6,7 @@
 -->
 <org.chromium.chrome.browser.firstrun.FirstRunView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:chrome="http://schemas.android.com/apk/res-auto"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
     android:layout_width="match_parent"
     android:layout_height="match_parent">
 
@@ -88,8 +88,8 @@
         android:text="@string/fre_accept_continue"
         android:textAllCaps="true"
         style="@style/WhiteBody"
-        chrome:buttonColor="@color/light_active_color"
-        chrome:buttonRaised="false"/>
+        app:buttonColor="@color/light_active_color"
+        app:buttonRaised="false"/>
 
     <!-- Same location as the button; marginButtom is adjusted for the different size. -->
     <ProgressBar
diff --git a/chrome/android/java/res/layout/history_item_view.xml b/chrome/android/java/res/layout/history_item_view.xml
index 00ecbd1..c2bd348 100644
--- a/chrome/android/java/res/layout/history_item_view.xml
+++ b/chrome/android/java/res/layout/history_item_view.xml
@@ -5,7 +5,7 @@
 
 <org.chromium.chrome.browser.history.HistoryItemView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:chrome="http://schemas.android.com/apk/res-auto"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
     android:layout_width="match_parent"
     android:layout_height="wrap_content" >
 
@@ -20,7 +20,7 @@
             style="@style/ListItemEndIconSmall"
             android:contentDescription="@string/remove"
             android:src="@drawable/btn_delete_24dp"
-            chrome:chrometint="@color/light_icon_color" />
+            app:chrometint="@color/light_icon_color" />
     </LinearLayout>
 
 </org.chromium.chrome.browser.history.HistoryItemView>
\ No newline at end of file
diff --git a/chrome/android/java/res/layout/history_toolbar.xml b/chrome/android/java/res/layout/history_toolbar.xml
index a42ce27d..8ad2ff4 100644
--- a/chrome/android/java/res/layout/history_toolbar.xml
+++ b/chrome/android/java/res/layout/history_toolbar.xml
@@ -5,9 +5,8 @@
 
 <org.chromium.chrome.browser.history.HistoryManagerToolbar
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:chrome="http://schemas.android.com/apk/res-auto"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:paddingStart="0dp"
     android:paddingEnd="0dp"
-    style="@style/ModernToolbar" />
\ No newline at end of file
+    style="@style/ModernToolbar"/>
\ No newline at end of file
diff --git a/chrome/android/java/res/layout/item_chooser_dialog.xml b/chrome/android/java/res/layout/item_chooser_dialog.xml
index ffce6fd..aba9003 100644
--- a/chrome/android/java/res/layout/item_chooser_dialog.xml
+++ b/chrome/android/java/res/layout/item_chooser_dialog.xml
@@ -5,7 +5,7 @@
  -->
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:chrome="http://schemas.android.com/apk/res-auto"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
     android:layout_width="fill_parent"
     android:layout_height="fill_parent"
     android:orientation="vertical"
@@ -80,5 +80,5 @@
         android:paddingEnd="16dp"
         android:textAllCaps="true"
         android:textColor="#fff"
-        chrome:buttonColor="@color/pref_accent_color" />
+        app:buttonColor="@color/pref_accent_color" />
 </LinearLayout>
diff --git a/chrome/android/java/res/layout/keyboard_accessory_action.xml b/chrome/android/java/res/layout/keyboard_accessory_action.xml
index 5ad307f3..6508df73 100644
--- a/chrome/android/java/res/layout/keyboard_accessory_action.xml
+++ b/chrome/android/java/res/layout/keyboard_accessory_action.xml
@@ -5,7 +5,7 @@
 
 <org.chromium.ui.widget.ButtonCompat
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:chrome="http://schemas.android.com/apk/res-auto"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
     android:gravity="center"
     android:layout_height="@dimen/keyboard_accessory_action_height"
     android:layout_width="wrap_content"
@@ -18,5 +18,5 @@
     android:textAlignment="center"
     android:textColor="@color/white_alpha_90"
     android:textSize="@dimen/keyboard_accessory_text_size"
-    chrome:buttonColor="@color/google_blue_500"
-    chrome:buttonRaised="false"/>
+    app:buttonColor="@color/google_blue_500"
+    app:buttonRaised="false"/>
diff --git a/chrome/android/java/res/layout/lightweight_fre_tos.xml b/chrome/android/java/res/layout/lightweight_fre_tos.xml
index 0c3fa68..48bb375e 100644
--- a/chrome/android/java/res/layout/lightweight_fre_tos.xml
+++ b/chrome/android/java/res/layout/lightweight_fre_tos.xml
@@ -5,7 +5,7 @@
      found in the LICENSE file.
 -->
 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:chrome="http://schemas.android.com/apk/res-auto"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:orientation="vertical"
@@ -42,8 +42,8 @@
         android:layout_below="@id/lightweight_fre_tos_and_privacy"
         android:paddingEnd="8dp"
         android:paddingStart="8dp"
-        chrome:buttonAlignment="end"
-        chrome:primaryButtonText="@string/fre_accept_continue"
-        chrome:secondaryButtonText="@string/cancel"
-        chrome:stackedMargin="@dimen/fre_stacked_button_margin" />
+        app:buttonAlignment="end"
+        app:primaryButtonText="@string/fre_accept_continue"
+        app:secondaryButtonText="@string/cancel"
+        app:stackedMargin="@dimen/fre_stacked_button_margin" />
 </RelativeLayout>
diff --git a/chrome/android/java/res/layout/list_menu_button.xml b/chrome/android/java/res/layout/list_menu_button.xml
index 944c84f..5672e8ca 100644
--- a/chrome/android/java/res/layout/list_menu_button.xml
+++ b/chrome/android/java/res/layout/list_menu_button.xml
@@ -7,7 +7,7 @@
 
 <org.chromium.chrome.browser.widget.ListMenuButton
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:chrome="http://schemas.android.com/apk/res-auto"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
     xmlns:tools="http://schemas.android.com/tools"
     android:id="@+id/more"
     android:layout_width="wrap_content"
@@ -16,5 +16,5 @@
     android:paddingEnd="@dimen/selectable_list_layout_row_padding"
     android:background="@null"
     android:src="@drawable/ic_more_vert_black_24dp"
-    chrome:chrometint="@color/dark_mode_tint"
+    app:chrometint="@color/dark_mode_tint"
     tools:ignore="ContentDescription" />
diff --git a/chrome/android/java/res/layout/menu_item.xml b/chrome/android/java/res/layout/menu_item.xml
index 43468c083..ab50ef6b 100644
--- a/chrome/android/java/res/layout/menu_item.xml
+++ b/chrome/android/java/res/layout/menu_item.xml
@@ -6,7 +6,7 @@
 -->
 <!-- Layout for each item in the menu popup -->
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:chrome="http://schemas.android.com/apk/res-auto"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
     style="@style/AppMenuItem"
     android:layout_width="match_parent"
     android:layout_height="?android:attr/listPreferredItemHeightSmall" >
@@ -29,5 +29,5 @@
         android:layout_height="match_parent"
         android:layout_gravity="end"
         android:gravity="center_vertical"
-        chrome:chrometint="@null" />
+        app:chrometint="@null" />
 </LinearLayout>
diff --git a/chrome/android/java/res/layout/modal_dialog_view.xml b/chrome/android/java/res/layout/modal_dialog_view.xml
index d5f6f0f3..00d6382b 100644
--- a/chrome/android/java/res/layout/modal_dialog_view.xml
+++ b/chrome/android/java/res/layout/modal_dialog_view.xml
@@ -6,12 +6,12 @@
 <!-- TODO(huayinz): rename menu_bg or change the dialog background to the desired one. -->
 <org.chromium.chrome.browser.widget.BoundedLinearLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:chrome="http://schemas.android.com/apk/res-auto"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:orientation="vertical"
-    chrome:maxWidthLandscape="@dimen/abc_dialog_min_width_major"
-    chrome:maxWidthPortrait="@dimen/abc_dialog_min_width_minor" >
+    app:maxWidthLandscape="@dimen/abc_dialog_min_width_major"
+    app:maxWidthPortrait="@dimen/abc_dialog_min_width_minor" >
 
     <android.support.v7.widget.DialogTitle
         android:id="@+id/title"
@@ -40,7 +40,7 @@
             <org.chromium.ui.widget.TextViewWithLeading
                 android:id="@+id/message"
                 android:textAppearance="@style/BlackBody"
-                chrome:leading="20sp"
+                app:leading="20sp"
                 style="@style/AlertDialogContent" />
 
         </LinearLayout>
diff --git a/chrome/android/java/res/layout/new_tab_page_all_dismissed.xml b/chrome/android/java/res/layout/new_tab_page_all_dismissed.xml
index 17277293..f221d52 100644
--- a/chrome/android/java/res/layout/new_tab_page_all_dismissed.xml
+++ b/chrome/android/java/res/layout/new_tab_page_all_dismissed.xml
@@ -5,7 +5,7 @@
 
 <RelativeLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:chrome="http://schemas.android.com/apk/res-auto"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:padding="@dimen/snippets_padding">
@@ -34,7 +34,7 @@
         android:gravity="center_horizontal"
         android:text="@string/ntp_title_no_suggestions"
         android:textAppearance="@style/BlackTitle1"
-        chrome:leading="24dp" />
+        app:leading="24dp" />
 
     <org.chromium.ui.widget.TextViewWithLeading
         android:id="@+id/body_text"
@@ -46,7 +46,7 @@
         android:text="@string/ntp_all_dismissed_body_text_morning"
         android:textSize="14sp"
         android:textColor="@color/snippets_text_color"
-        chrome:leading="20dp" />
+        app:leading="20dp" />
 
     <Button
         android:id="@+id/action_button"
diff --git a/chrome/android/java/res/layout/new_tab_page_incognito.xml b/chrome/android/java/res/layout/new_tab_page_incognito.xml
index c650ffd..eefc796 100644
--- a/chrome/android/java/res/layout/new_tab_page_incognito.xml
+++ b/chrome/android/java/res/layout/new_tab_page_incognito.xml
@@ -5,7 +5,6 @@
 
 <org.chromium.chrome.browser.ntp.IncognitoNewTabPageView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:chrome="http://schemas.android.com/apk/res-auto"
     android:id="@+id/ntp_content"
     android:layout_width="match_parent"
     android:layout_height="match_parent" >
diff --git a/chrome/android/java/res/layout/new_tab_page_incognito_md.xml b/chrome/android/java/res/layout/new_tab_page_incognito_md.xml
index 443fe80..62465fec 100644
--- a/chrome/android/java/res/layout/new_tab_page_incognito_md.xml
+++ b/chrome/android/java/res/layout/new_tab_page_incognito_md.xml
@@ -5,7 +5,6 @@
 
 <org.chromium.chrome.browser.ntp.IncognitoNewTabPageViewMD
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:chrome="http://schemas.android.com/apk/res-auto"
     android:id="@+id/ntp_content"
     android:layout_width="match_parent"
     android:layout_height="match_parent" >
diff --git a/chrome/android/java/res/layout/new_tab_page_layout.xml b/chrome/android/java/res/layout/new_tab_page_layout.xml
index 5d13a9e..a1ce693 100644
--- a/chrome/android/java/res/layout/new_tab_page_layout.xml
+++ b/chrome/android/java/res/layout/new_tab_page_layout.xml
@@ -4,7 +4,6 @@
      found in the LICENSE file. -->
 <org.chromium.chrome.browser.ntp.NewTabPageLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:chrome="http://schemas.android.com/apk/res-auto"
     android:id="@+id/ntp_content"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
diff --git a/chrome/android/java/res/layout/new_tab_page_snippets_card_large_thumbnail.xml b/chrome/android/java/res/layout/new_tab_page_snippets_card_large_thumbnail.xml
index 9527de30..b956ba8 100644
--- a/chrome/android/java/res/layout/new_tab_page_snippets_card_large_thumbnail.xml
+++ b/chrome/android/java/res/layout/new_tab_page_snippets_card_large_thumbnail.xml
@@ -6,7 +6,6 @@
 <RelativeLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
-    xmlns:chrome="http://schemas.android.com/apk/res-auto"
     xmlns:tools="http://schemas.android.com/tools"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
@@ -31,7 +30,7 @@
             android:layout_weight="1"
             android:ellipsize="end"
             android:textAppearance="@style/BlackTitle1"
-            chrome:leading="22sp" />
+            app:leading="22sp" />
 
         <LinearLayout
             tools:ignore="UseCompoundDrawables"
@@ -83,7 +82,7 @@
                 android:src="@drawable/offline_pin_round"
                 android:contentDescription="@string/accessibility_ntp_offline_badge"
                 android:visibility="gone"
-                chrome:chrometint="#000" />
+                app:chrometint="@android:color/black" />
 
         </LinearLayout>
 
diff --git a/chrome/android/java/res/layout/new_tab_page_status_card.xml b/chrome/android/java/res/layout/new_tab_page_status_card.xml
index 8e15881..7507d73 100644
--- a/chrome/android/java/res/layout/new_tab_page_status_card.xml
+++ b/chrome/android/java/res/layout/new_tab_page_status_card.xml
@@ -5,7 +5,7 @@
 
 <LinearLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:chrome="http://schemas.android.com/apk/res-auto"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
     xmlns:tools="http://schemas.android.com/tools"
     android:id="@+id/status_card_view"
     android:layout_width="match_parent"
@@ -20,7 +20,7 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:textAppearance="@style/BlackTitle1"
-        chrome:leading="24dp"
+        app:leading="24dp"
         tools:text="Status card title"/>
 
     <org.chromium.ui.widget.TextViewWithLeading
@@ -30,7 +30,7 @@
         android:layout_marginTop="8dp"
         android:textSize="14sp"
         android:textColor="@color/snippets_text_color"
-        chrome:leading="20dp"
+        app:leading="20dp"
         tools:text="Status card body can be over multiple lines and quite wide" />
 
     <Button
diff --git a/chrome/android/java/res/layout/ntp_shortcuts.xml b/chrome/android/java/res/layout/ntp_shortcuts.xml
index 0931f8ee..f385df9 100644
--- a/chrome/android/java/res/layout/ntp_shortcuts.xml
+++ b/chrome/android/java/res/layout/ntp_shortcuts.xml
@@ -5,8 +5,7 @@
 
 <LinearLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:chrome="http://schemas.android.com/apk/res-auto"
-    xmlns:tools="http://schemas.android.com/tools"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
     android:id="@+id/shortcuts"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
@@ -34,9 +33,9 @@
             android:drawableStart="@drawable/btn_star_filled"
             android:text="@string/menu_bookmarks"
             android:textAppearance="@style/BlackCaption"
-            chrome:drawableHeight="20sp"
-            chrome:drawableWidth="20sp"
-            chrome:chromeDrawableTint="@color/black_alpha_54"  />
+            app:drawableHeight="20sp"
+            app:drawableWidth="20sp"
+            app:chromeDrawableTint="@color/black_alpha_54"  />
     </FrameLayout>
 
     <FrameLayout
@@ -57,8 +56,8 @@
             android:drawableStart="@drawable/ic_file_download_white_24dp"
             android:text="@string/menu_downloads"
             android:textAppearance="@style/BlackCaption"
-            chrome:drawableHeight="20sp"
-            chrome:drawableWidth="20sp"
-            chrome:chromeDrawableTint="@color/black_alpha_54"  />
+            app:drawableHeight="20sp"
+            app:drawableWidth="20sp"
+            app:chromeDrawableTint="@color/black_alpha_54"  />
     </FrameLayout>
 </LinearLayout>
\ No newline at end of file
diff --git a/chrome/android/java/res/layout/object_permission.xml b/chrome/android/java/res/layout/object_permission.xml
index f502c39..4672ded5 100644
--- a/chrome/android/java/res/layout/object_permission.xml
+++ b/chrome/android/java/res/layout/object_permission.xml
@@ -5,7 +5,6 @@
 
 <ImageView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:chrome="http://schemas.android.com/apk/res-auto"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:contentDescription="@string/website_settings_revoke_device_permission"
diff --git a/chrome/android/java/res/layout/offline_download_header.xml b/chrome/android/java/res/layout/offline_download_header.xml
index 5498c658..255218ef 100644
--- a/chrome/android/java/res/layout/offline_download_header.xml
+++ b/chrome/android/java/res/layout/offline_download_header.xml
@@ -6,7 +6,6 @@
 <!-- Represents the suggested offline pages section header in the DownloadHistoryAdapter. -->
 <view class="org.chromium.chrome.browser.download.ui.OfflineGroupHeaderView"
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:chrome="http://schemas.android.com/apk/res-auto"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content" >
 
diff --git a/chrome/android/java/res/layout/page_info.xml b/chrome/android/java/res/layout/page_info.xml
index 3b83397..05c72c8 100644
--- a/chrome/android/java/res/layout/page_info.xml
+++ b/chrome/android/java/res/layout/page_info.xml
@@ -7,7 +7,7 @@
 -->
 <LinearLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:chrome="http://schemas.android.com/apk/res-auto"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:paddingBottom="8dp"
@@ -65,8 +65,8 @@
         android:text="@string/page_info_instant_app_button"
         android:textSize="14sp"
         android:textColor="@android:color/white"
-        chrome:buttonRaised="false"
-        chrome:buttonColor="@color/app_banner_install_button_bg" />
+        app:buttonRaised="false"
+        app:buttonColor="@color/app_banner_install_button_bg" />
 
     <LinearLayout
         android:id="@+id/page_info_permissions_list"
diff --git a/chrome/android/java/res/layout/page_info_permission_row.xml b/chrome/android/java/res/layout/page_info_permission_row.xml
index ca33e91a..5339f08 100644
--- a/chrome/android/java/res/layout/page_info_permission_row.xml
+++ b/chrome/android/java/res/layout/page_info_permission_row.xml
@@ -5,7 +5,7 @@
 
 <RelativeLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:chrome="http://schemas.android.com/apk/res-auto"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
     android:id="@+id/page_info_permission_row"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
@@ -33,7 +33,7 @@
         android:layout_toEndOf="@id/page_info_permission_icon"
         android:textAppearance="@style/BlueLink2"
         android:visibility="gone"
-        chrome:leading="20dp" />
+        app:leading="20dp" />
 
     <org.chromium.ui.widget.TextViewWithLeading
         android:id="@+id/page_info_permission_subtitle"
@@ -44,5 +44,5 @@
         android:textSize="14sp"
         android:textColor="@color/secondary_text_default_material_light"
         android:visibility="gone"
-        chrome:leading="20dp" />
+        app:leading="20dp" />
 </RelativeLayout>
diff --git a/chrome/android/java/res/layout/payment_request.xml b/chrome/android/java/res/layout/payment_request.xml
index 9f51403..16b4b8a 100644
--- a/chrome/android/java/res/layout/payment_request.xml
+++ b/chrome/android/java/res/layout/payment_request.xml
@@ -8,11 +8,11 @@
 -->
 <org.chromium.chrome.browser.widget.BoundedLinearLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:chrome="http://schemas.android.com/apk/res-auto"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
     android:id="@+id/payment_request"
     android:orientation="vertical"
     android:gravity="center"
-    chrome:maxWidth="@dimen/payments_ui_max_dialog_width"
+    app:maxWidth="@dimen/payments_ui_max_dialog_width"
     android:background="@android:color/white" >
 
     <include layout="@layout/payment_request_header" />
diff --git a/chrome/android/java/res/layout/payment_request_bottom_bar.xml b/chrome/android/java/res/layout/payment_request_bottom_bar.xml
index d0858ad..3a99071f 100644
--- a/chrome/android/java/res/layout/payment_request_bottom_bar.xml
+++ b/chrome/android/java/res/layout/payment_request_bottom_bar.xml
@@ -6,7 +6,7 @@
 <!-- Sits at the bottom of the payment request UI. -->
 <org.chromium.chrome.browser.payments.ui.PaymentRequestBottomBar
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:chrome="http://schemas.android.com/apk/res-auto"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
     android:id="@+id/bottom_bar"
     android:layout_height="wrap_content"
     android:layout_width="match_parent"
@@ -51,6 +51,6 @@
         android:textAllCaps="true"
         android:textColor="@android:color/white"
         android:textSize="14sp"
-        chrome:buttonColor="@color/light_active_color"
-        chrome:buttonRaised="false" />
+        app:buttonColor="@color/light_active_color"
+        app:buttonRaised="false" />
 </org.chromium.chrome.browser.payments.ui.PaymentRequestBottomBar>
\ No newline at end of file
diff --git a/chrome/android/java/res/layout/payment_request_editor.xml b/chrome/android/java/res/layout/payment_request_editor.xml
index fcde67a..c63bc4d 100644
--- a/chrome/android/java/res/layout/payment_request_editor.xml
+++ b/chrome/android/java/res/layout/payment_request_editor.xml
@@ -6,8 +6,7 @@
 <!-- PaymentRequestUI editor dialog. -->
 <RelativeLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:chrome="http://schemas.android.com/apk/res-auto"
-    android:background="@android:color/white" >
+    android:background="@android:color/white">
 
     <!-- Toolbar -->
     <org.chromium.chrome.browser.widget.prefeditor.EditorDialogToolbar
diff --git a/chrome/android/java/res/layout/payment_request_error.xml b/chrome/android/java/res/layout/payment_request_error.xml
index 178c7aa..043a6d7 100644
--- a/chrome/android/java/res/layout/payment_request_error.xml
+++ b/chrome/android/java/res/layout/payment_request_error.xml
@@ -10,11 +10,11 @@
 -->
 <org.chromium.chrome.browser.payments.ui.PaymentRequestUiErrorView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:chrome="http://schemas.android.com/apk/res-auto"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
     android:orientation="vertical"
     android:gravity="center"
     android:background="@drawable/menu_bg"
-    chrome:maxWidth="@dimen/payments_ui_max_dialog_width" >
+    app:maxWidth="@dimen/payments_ui_max_dialog_width" >
 
     <include layout="@layout/payment_request_header" />
 
diff --git a/chrome/android/java/res/layout/promo_dialog_layout.xml b/chrome/android/java/res/layout/promo_dialog_layout.xml
index ce46e3a..7ae4122 100644
--- a/chrome/android/java/res/layout/promo_dialog_layout.xml
+++ b/chrome/android/java/res/layout/promo_dialog_layout.xml
@@ -10,7 +10,7 @@
      layout.
 -->
 <merge xmlns:android="http://schemas.android.com/apk/res/android"
-        xmlns:chrome="http://schemas.android.com/apk/res-auto" >
+        xmlns:app="http://schemas.android.com/apk/res-auto" >
 
     <org.chromium.chrome.browser.widget.PromoDialogLayout
             android:id="@+id/promo_dialog_layout"
@@ -19,7 +19,7 @@
             android:layout_gravity="center"
             android:orientation="vertical"
             android:background="@drawable/menu_bg"
-            chrome:maxWidth="@dimen/dialog_max_width" >
+            app:maxWidth="@dimen/dialog_max_width" >
 
         <org.chromium.chrome.browser.widget.FadingEdgeScrollView
                 android:id="@+id/promo_container"
@@ -53,7 +53,7 @@
                         android:layout_width="wrap_content"
                         android:layout_height="wrap_content"
                         android:orientation="vertical"
-                        chrome:maxWidth="@dimen/promo_dialog_max_content_width" >
+                        app:maxWidth="@dimen/promo_dialog_max_content_width" >
 
                     <TextView
                             android:id="@+id/header"
@@ -88,8 +88,8 @@
                 android:layout_height="wrap_content"
                 android:layout_gravity="end"
                 android:padding="@dimen/promo_dialog_padding"
-                chrome:buttonAlignment="end"
-                chrome:stackedMargin="@dimen/infobar_padding" />
+                app:buttonAlignment="end"
+                app:stackedMargin="@dimen/infobar_padding" />
 
     </org.chromium.chrome.browser.widget.PromoDialogLayout>
 
diff --git a/chrome/android/java/res/layout/sad_tab.xml b/chrome/android/java/res/layout/sad_tab.xml
index 2a61df8c5..dd5af596 100644
--- a/chrome/android/java/res/layout/sad_tab.xml
+++ b/chrome/android/java/res/layout/sad_tab.xml
@@ -8,7 +8,7 @@
 
 <org.chromium.chrome.browser.tab.SadTabView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:chrome="http://schemas.android.com/apk/res-auto"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
     xmlns:tools="http://schemas.android.com/tools"
     tools:ignore="Overdraw"
     android:background="#f7f7f7"
@@ -74,7 +74,7 @@
             android:layout_height="wrap_content"
             android:textColor="#fff"
             android:minWidth="222dp"
-            chrome:buttonColor="@color/light_active_color"
+            app:buttonColor="@color/light_active_color"
             android:layout_gravity="end" />
     </LinearLayout>
 </org.chromium.chrome.browser.tab.SadTabView>
diff --git a/chrome/android/java/res/layout/search_toolbar.xml b/chrome/android/java/res/layout/search_toolbar.xml
index 5269321..84d2ccf 100644
--- a/chrome/android/java/res/layout/search_toolbar.xml
+++ b/chrome/android/java/res/layout/search_toolbar.xml
@@ -5,7 +5,7 @@
 
 <LinearLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:chrome="http://schemas.android.com/apk/res-auto"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
     android:id="@+id/search_view"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
@@ -36,5 +36,5 @@
         android:scaleType="center"
         android:contentDescription="@string/accessibility_toolbar_btn_delete_url"
         android:visibility="invisible"
-        chrome:chrometint="@color/dark_mode_tint" />
+        app:chrometint="@color/dark_mode_tint" />
 </LinearLayout>
diff --git a/chrome/android/java/res/layout/signin_view.xml b/chrome/android/java/res/layout/signin_view.xml
index 34277f23..a48b06571 100644
--- a/chrome/android/java/res/layout/signin_view.xml
+++ b/chrome/android/java/res/layout/signin_view.xml
@@ -4,7 +4,7 @@
      found in the LICENSE file. -->
 <org.chromium.chrome.browser.signin.SigninView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:chrome="http://schemas.android.com/apk/res-auto"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
     xmlns:tools="http://schemas.android.com/tools"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
@@ -29,7 +29,7 @@
                 android:background="@color/signin_header_animation_background"
                 android:contentDescription="@null"
                 android:scaleType="center"
-                chrome:srcCompat="@drawable/signin_header_animation"
+                app:srcCompat="@drawable/signin_header_animation"
                 tools:src="@drawable/signin_header_animation"/>
             <TextView
                 android:id="@+id/signin_title"
@@ -106,7 +106,7 @@
                 android:layout_centerVertical="true"
                 android:layout_marginStart="@dimen/signin_margin_start"
                 android:contentDescription="@null"
-                chrome:srcCompat="@drawable/ic_sync_circle_green_16dp"/>
+                app:srcCompat="@drawable/ic_sync_circle_green_16dp"/>
             <TextView
                 android:id="@+id/signin_sync_description"
                 android:layout_width="match_parent"
@@ -129,7 +129,7 @@
                 android:layout_centerVertical="true"
                 android:layout_marginStart="@dimen/signin_margin_start"
                 android:contentDescription="@null"
-                chrome:srcCompat="@drawable/ic_assistant_16dp"/>
+                app:srcCompat="@drawable/ic_assistant_16dp"/>
             <TextView
                 android:id="@+id/signin_personalization_description"
                 android:layout_width="match_parent"
@@ -152,7 +152,7 @@
                 android:layout_centerVertical="true"
                 android:layout_marginStart="@dimen/signin_margin_start"
                 android:contentDescription="@null"
-                chrome:srcCompat="@drawable/ic_logo_googleg_16dp"/>
+                app:srcCompat="@drawable/ic_logo_googleg_16dp"/>
             <TextView
                 android:id="@+id/signin_google_services_description"
                 android:layout_width="match_parent"
@@ -181,7 +181,7 @@
                 android:layout_marginStart="@dimen/signin_margin_start"
                 android:baseline="12dp"
                 android:contentDescription="@null"
-                chrome:srcCompat="@drawable/ic_settings_grey_16dp"/>
+                app:srcCompat="@drawable/ic_settings_grey_16dp"/>
             <TextView
                 android:id="@+id/signin_details_description"
                 android:layout_width="match_parent"
@@ -227,8 +227,8 @@
             android:paddingStart="@dimen/fre_button_padding"
             android:paddingEnd="@dimen/fre_button_padding"
             android:textAllCaps="true"
-            chrome:buttonColor="@color/light_active_color"
-            chrome:buttonRaised="false"
+            app:buttonColor="@color/light_active_color"
+            app:buttonRaised="false"
             tools:text="@string/signin_accept_button"/>
         <!-- TODO(https://crbug.com/819142): Use textAppearance instead of text* attributes. -->
         <Button
diff --git a/chrome/android/java/res/layout/sync_promo_view.xml b/chrome/android/java/res/layout/sync_promo_view.xml
index ef1de68b..18f307b 100644
--- a/chrome/android/java/res/layout/sync_promo_view.xml
+++ b/chrome/android/java/res/layout/sync_promo_view.xml
@@ -4,7 +4,7 @@
      found in the LICENSE file. -->
 <org.chromium.chrome.browser.signin.SyncPromoView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:chrome="http://schemas.android.com/apk/res-auto"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
     android:layout_width="match_parent"
     android:layout_height="wrap_content" >
 
@@ -46,7 +46,7 @@
                 android:layout_height="wrap_content"
                 android:textAllCaps="true"
                 android:textAppearance="@style/WhiteLink"
-                chrome:buttonColor="@color/light_active_color" />
+                app:buttonColor="@color/light_active_color" />
         </LinearLayout>
 
     </LinearLayout>
diff --git a/chrome/android/java/res/layout/tabular_context_menu_row.xml b/chrome/android/java/res/layout/tabular_context_menu_row.xml
index ca2d96b..896d8d0 100644
--- a/chrome/android/java/res/layout/tabular_context_menu_row.xml
+++ b/chrome/android/java/res/layout/tabular_context_menu_row.xml
@@ -4,14 +4,14 @@
      found in the LICENSE file. -->
 <org.chromium.chrome.browser.widget.BoundedLinearLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:chrome="http://schemas.android.com/apk/res-auto"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
     xmlns:tools="http://schemas.android.com/tools"
     android:orientation="horizontal"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:paddingStart="15dp"
     android:minHeight="40dp"
-    chrome:maxHeight="40dp"
+    app:maxHeight="40dp"
     tools:ignore="UseCompoundDrawables">
     <TextView
         android:id="@+id/context_menu_text"
diff --git a/chrome/android/java/res/layout/textbubble_text_with_image.xml b/chrome/android/java/res/layout/textbubble_text_with_image.xml
index 3c6af448..dc6bcc0 100644
--- a/chrome/android/java/res/layout/textbubble_text_with_image.xml
+++ b/chrome/android/java/res/layout/textbubble_text_with_image.xml
@@ -8,7 +8,7 @@
      why and switch this to use TextViewWithCompoundDrawable. -->
 <LinearLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:chrome="http://schemas.android.com/apk/res-auto"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:orientation="horizontal"
@@ -22,7 +22,7 @@
         android:layout_marginEnd="12dp"
         android:contentDescription="@null"
         android:scaleType="centerInside"
-        chrome:chrometint="@color/white_mode_tint" />
+        app:chrometint="@color/white_mode_tint" />
 
     <TextView
         android:id="@+id/message"
diff --git a/chrome/android/java/res/layout/tile_view_classic.xml b/chrome/android/java/res/layout/tile_view_classic.xml
index e27b15f..4c58ecb 100644
--- a/chrome/android/java/res/layout/tile_view_classic.xml
+++ b/chrome/android/java/res/layout/tile_view_classic.xml
@@ -6,7 +6,7 @@
 <!-- A site suggestion tile. -->
 <org.chromium.chrome.browser.suggestions.TileView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:chrome="http://schemas.android.com/apk/res-auto"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
     android:layout_width="@dimen/tile_view_width"
     android:layout_height="wrap_content"
     android:paddingStart="4dp"
@@ -39,7 +39,7 @@
         android:visibility="gone"
         android:background="@drawable/offline_badge_background"
         android:contentDescription="@string/accessibility_ntp_offline_badge"
-        chrome:chrometint="@color/suggestions_offline_badge_tint"
+        app:chrometint="@color/suggestions_offline_badge_tint"
         android:src="@drawable/offline_pin_round" />
 
     <!-- The title. -->
diff --git a/chrome/android/java/res/layout/tile_view_classic_condensed.xml b/chrome/android/java/res/layout/tile_view_classic_condensed.xml
index 47b310d..79f2187 100644
--- a/chrome/android/java/res/layout/tile_view_classic_condensed.xml
+++ b/chrome/android/java/res/layout/tile_view_classic_condensed.xml
@@ -6,7 +6,7 @@
 <!-- A site suggestion tile. -->
 <org.chromium.chrome.browser.suggestions.TileView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:chrome="http://schemas.android.com/apk/res-auto"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
     android:layout_width="@dimen/tile_view_width_condensed"
     android:layout_height="wrap_content" >
 
@@ -37,7 +37,7 @@
         android:visibility="gone"
         android:background="@drawable/offline_badge_background"
         android:contentDescription="@string/accessibility_ntp_offline_badge"
-        chrome:chrometint="@color/suggestions_offline_badge_tint"
+        app:chrometint="@color/suggestions_offline_badge_tint"
         android:src="@drawable/offline_pin_round" />
 
     <!-- The title. -->
diff --git a/chrome/android/java/res/layout/tile_view_modern.xml b/chrome/android/java/res/layout/tile_view_modern.xml
index e00d335..332a16e 100644
--- a/chrome/android/java/res/layout/tile_view_modern.xml
+++ b/chrome/android/java/res/layout/tile_view_modern.xml
@@ -6,7 +6,7 @@
 <!-- A site suggestion tile. -->
 <org.chromium.chrome.browser.suggestions.TileView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:chrome="http://schemas.android.com/apk/res-auto"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
     android:layout_width="@dimen/tile_view_width"
     android:layout_height="wrap_content"
     android:paddingStart="4dp"
@@ -49,7 +49,7 @@
         android:layout_marginEnd="@dimen/tile_view_offline_badge_margin_end_modern"
         android:visibility="gone"
         android:contentDescription="@string/accessibility_ntp_offline_badge"
-        chrome:srcCompat="@drawable/ic_offline_pin_blue_white" />
+        app:srcCompat="@drawable/ic_offline_pin_blue_white" />
 
     <!-- The title. -->
     <TextView
diff --git a/chrome/android/java/res/layout/tile_view_modern_condensed.xml b/chrome/android/java/res/layout/tile_view_modern_condensed.xml
index 9d4d119a..bba9735a 100644
--- a/chrome/android/java/res/layout/tile_view_modern_condensed.xml
+++ b/chrome/android/java/res/layout/tile_view_modern_condensed.xml
@@ -6,7 +6,7 @@
 <!-- A site suggestion tile. -->
 <org.chromium.chrome.browser.suggestions.TileView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:chrome="http://schemas.android.com/apk/res-auto"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
     android:layout_width="@dimen/tile_view_width_condensed"
     android:layout_height="wrap_content" >
 
@@ -47,7 +47,7 @@
         android:layout_marginEnd="@dimen/tile_view_offline_badge_margin_end_modern_condensed"
         android:visibility="gone"
         android:contentDescription="@string/accessibility_ntp_offline_badge"
-        chrome:srcCompat="@drawable/ic_offline_pin_blue_white" />
+        app:srcCompat="@drawable/ic_offline_pin_blue_white" />
 
     <!-- The title. -->
     <TextView
diff --git a/chrome/android/java/res/layout/title_button_menu_item.xml b/chrome/android/java/res/layout/title_button_menu_item.xml
index 3edbfabe4..40afd21 100644
--- a/chrome/android/java/res/layout/title_button_menu_item.xml
+++ b/chrome/android/java/res/layout/title_button_menu_item.xml
@@ -11,7 +11,7 @@
      * A text label with an icon
 -->
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:chrome="http://schemas.android.com/apk/res-auto"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
     android:layout_width="match_parent"
     android:layout_height="?android:attr/listPreferredItemHeightSmall">
     <TextView
@@ -39,7 +39,7 @@
         android:paddingBottom="8dp"
         android:scaleType="fitCenter"
         android:src="?android:attr/listChoiceIndicatorMultiple"
-        chrome:chrometint="@null" />
+        app:chrometint="@null" />
 
     <!-- Displays an icon. -->
     <org.chromium.chrome.browser.widget.TintedImageButton
@@ -52,5 +52,5 @@
         android:paddingTop="12dp"
         android:paddingBottom="12dp"
         android:scaleType="fitCenter"
-        chrome:chrometint="@null" />
+        app:chrometint="@null" />
 </LinearLayout>
\ No newline at end of file
diff --git a/chrome/android/java/res/layout/toolbar_phone_common.xml b/chrome/android/java/res/layout/toolbar_phone_common.xml
index f34444a..e0603028 100644
--- a/chrome/android/java/res/layout/toolbar_phone_common.xml
+++ b/chrome/android/java/res/layout/toolbar_phone_common.xml
@@ -5,8 +5,7 @@
 
 <!-- The toolbar containing the URL bar, back button, and NTP button.
 -->
-<merge xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:chrome="http://schemas.android.com/apk/res-auto">
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
 
     <org.chromium.chrome.browser.widget.newtab.NewTabButton
         android:id="@+id/new_tab_button"
diff --git a/chrome/android/java/res/layout/translate_menu_item_checked.xml b/chrome/android/java/res/layout/translate_menu_item_checked.xml
index cb0478c9..c5b1ea62 100644
--- a/chrome/android/java/res/layout/translate_menu_item_checked.xml
+++ b/chrome/android/java/res/layout/translate_menu_item_checked.xml
@@ -3,13 +3,14 @@
      Use of this source code is governed by a BSD-style license that can be
      found in the LICENSE file. -->
 
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:orientation="vertical">
+<LinearLayout
+    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"
+    android:orientation="vertical">
 
-    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-        xmlns:chrome="http://schemas.android.com/apk/res-auto"
+    <LinearLayout
         style="@style/AppMenuItem"
         android:layout_width="match_parent"
         android:layout_height="wrap_content" >
@@ -32,7 +33,7 @@
             android:layout_height="match_parent"
             android:layout_gravity="end"
             android:gravity="center_vertical"
-            chrome:chrometint="@color/dark_mode_tint" />
+            app:chrometint="@color/dark_mode_tint" />
 
     </LinearLayout>
 
diff --git a/chrome/android/java/res/layout/update_menu_item.xml b/chrome/android/java/res/layout/update_menu_item.xml
index 1d126ae..7f9e9bf8 100644
--- a/chrome/android/java/res/layout/update_menu_item.xml
+++ b/chrome/android/java/res/layout/update_menu_item.xml
@@ -4,7 +4,7 @@
      found in the LICENSE file.
 -->
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:chrome="http://schemas.android.com/apk/res-auto"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
     style="@style/AppMenuItem"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
@@ -43,6 +43,6 @@
         android:layout_height="match_parent"
         android:layout_gravity="end"
         android:gravity="center_vertical"
-        chrome:chrometint="@null" />
+        app:chrometint="@null" />
 
 </LinearLayout>
\ No newline at end of file
diff --git a/chrome/android/java/res/layout/updating_gms_progress_view.xml b/chrome/android/java/res/layout/updating_gms_progress_view.xml
index 9482385..012a98b8 100644
--- a/chrome/android/java/res/layout/updating_gms_progress_view.xml
+++ b/chrome/android/java/res/layout/updating_gms_progress_view.xml
@@ -5,10 +5,10 @@
 
 <org.chromium.chrome.browser.widget.BoundedLinearLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:chrome="http://schemas.android.com/apk/res-auto"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
     android:gravity="center"
     android:padding="24dp"
-    chrome:maxWidth="312dp"
+    app:maxWidth="312dp"
     style="@style/AlertDialogContent" >
 
     <ProgressBar
diff --git a/chrome/android/java/res/menu/languages_action_bar_menu.xml b/chrome/android/java/res/menu/languages_action_bar_menu.xml
index e998be4..f200ec52 100644
--- a/chrome/android/java/res/menu/languages_action_bar_menu.xml
+++ b/chrome/android/java/res/menu/languages_action_bar_menu.xml
@@ -4,10 +4,11 @@
      found in the LICENSE file. -->
 
 <menu xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:chrome="http://schemas.android.com/apk/res-auto" >
+    xmlns:app="http://schemas.android.com/apk/res-auto" >
+    
     <item
         android:id="@+id/search"
         android:title="@string/search"
-        chrome:showAsAction="always"
-        chrome:actionViewClass="android.support.v7.widget.SearchView"/>
+        app:showAsAction="always"
+        app:actionViewClass="android.support.v7.widget.SearchView"/>
 </menu>
diff --git a/chrome/android/java/res/menu/password_entry_editor_action_bar_menu.xml b/chrome/android/java/res/menu/password_entry_editor_action_bar_menu.xml
index ccd3c82..0eea2151 100644
--- a/chrome/android/java/res/menu/password_entry_editor_action_bar_menu.xml
+++ b/chrome/android/java/res/menu/password_entry_editor_action_bar_menu.xml
@@ -4,12 +4,12 @@
      found in the LICENSE file. -->
 
 <menu xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:chrome="http://schemas.android.com/apk/res-auto" >
+    xmlns:app="http://schemas.android.com/apk/res-auto" >
 
     <item
         android:id="@+id/action_delete_saved_password"
         android:icon="@drawable/ic_delete_white_24dp"
         android:title="@string/password_entry_editor_delete_stored_password_action_title"
         android:contentDescription="@string/password_entry_editor_delete_stored_password"
-        chrome:showAsAction="ifRoom"/>
+        app:showAsAction="ifRoom"/>
 </menu>
diff --git a/chrome/android/java/res/menu/prefeditor_editor_menu.xml b/chrome/android/java/res/menu/prefeditor_editor_menu.xml
index 1b81ca0..56c11153 100644
--- a/chrome/android/java/res/menu/prefeditor_editor_menu.xml
+++ b/chrome/android/java/res/menu/prefeditor_editor_menu.xml
@@ -4,18 +4,18 @@
      found in the LICENSE file. -->
 
 <menu xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:chrome="http://schemas.android.com/apk/res-auto" >
+    xmlns:app="http://schemas.android.com/apk/res-auto" >
 
     <item
         android:id="@+id/delete_menu_id"
         android:icon="@drawable/ic_delete_white_24dp"
         android:title="@string/delete"
-        chrome:showAsAction="ifRoom" />
+        app:showAsAction="ifRoom" />
 
     <item
         android:id="@+id/help_menu_id"
         android:icon="@drawable/ic_help_white_24dp"
         android:title="@string/help"
-        chrome:showAsAction="ifRoom" />
+        app:showAsAction="ifRoom" />
 
 </menu>
diff --git a/chrome/android/java/res/menu/save_password_preferences_action_bar_menu.xml b/chrome/android/java/res/menu/save_password_preferences_action_bar_menu.xml
index 13ff36d1..0a30458 100644
--- a/chrome/android/java/res/menu/save_password_preferences_action_bar_menu.xml
+++ b/chrome/android/java/res/menu/save_password_preferences_action_bar_menu.xml
@@ -4,24 +4,24 @@
      found in the LICENSE file. -->
 
 <menu xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:chrome="http://schemas.android.com/apk/res-auto" >
+    xmlns:app="http://schemas.android.com/apk/res-auto" >
 
     <item
         android:id="@+id/menu_id_search"
         android:icon="@drawable/ic_search"
         android:title="@string/search"
-        chrome:showAsAction="always"
-        chrome:actionViewClass="android.support.v7.widget.SearchView" />
+        app:showAsAction="always"
+        app:actionViewClass="android.support.v7.widget.SearchView" />
 
     <item
         android:id="@id/menu_id_general_help"
         android:icon="@drawable/ic_help_and_feedback"
         android:title="@string/menu_help"
-        chrome:showAsAction="ifRoom"/>
+        app:showAsAction="ifRoom"/>
 
     <item
         android:id="@+id/export_passwords"
         android:title="@string/save_password_preferences_export_action_title"
         android:contentDescription="@string/save_password_preferences_export_action_description"
-        chrome:showAsAction="never"/>
+        app:showAsAction="never"/>
 </menu>
diff --git a/chrome/android/java/res/menu/website_preferences_menu.xml b/chrome/android/java/res/menu/website_preferences_menu.xml
index 04c18e3c..41a4655 100644
--- a/chrome/android/java/res/menu/website_preferences_menu.xml
+++ b/chrome/android/java/res/menu/website_preferences_menu.xml
@@ -4,9 +4,9 @@
      found in the LICENSE file. -->
 
 <menu xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:chrome="http://schemas.android.com/apk/res-auto">
+    xmlns:app="http://schemas.android.com/apk/res-auto">
     <item android:id="@+id/search"
           android:title="@string/search"
-          chrome:showAsAction="always"
-          chrome:actionViewClass="android.support.v7.widget.SearchView" />
+          app:showAsAction="always"
+          app:actionViewClass="android.support.v7.widget.SearchView" />
 </menu>
diff --git a/chrome/android/java/res/xml/clear_browsing_data_preferences_tab.xml b/chrome/android/java/res/xml/clear_browsing_data_preferences_tab.xml
index 2a2634b..e5c0b4c 100644
--- a/chrome/android/java/res/xml/clear_browsing_data_preferences_tab.xml
+++ b/chrome/android/java/res/xml/clear_browsing_data_preferences_tab.xml
@@ -5,13 +5,13 @@
 
 <PreferenceScreen
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:chrome="http://schemas.android.com/apk/res-auto">
+    xmlns:app="http://schemas.android.com/apk/res-auto">
 
     <org.chromium.chrome.browser.preferences.SpinnerPreference
         android:key="time_period_spinner"
         android:persistent="false"
         android:title="@string/clear_browsing_data_tab_period_title"
-        chrome:singleLine="true" />
+        app:singleLine="true" />
 
     <org.chromium.chrome.browser.preferences.ClearBrowsingDataCheckBoxPreference
         android:key="clear_history_checkbox"
diff --git a/chrome/android/java/res/xml/contextual_search_preferences.xml b/chrome/android/java/res/xml/contextual_search_preferences.xml
index 2478b1c..f20942c4 100644
--- a/chrome/android/java/res/xml/contextual_search_preferences.xml
+++ b/chrome/android/java/res/xml/contextual_search_preferences.xml
@@ -5,13 +5,13 @@
 
 <PreferenceScreen
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:chrome="http://schemas.android.com/apk/res-auto">
+    xmlns:app="http://schemas.android.com/apk/res-auto">
 
     <org.chromium.chrome.browser.preferences.ChromeSwitchPreference
         android:key="contextual_search_switch"
         android:summaryOn="@string/text_on"
         android:summaryOff="@string/text_off"
-        chrome:drawDivider="true" />
+        app:drawDivider="true" />
 
     <org.chromium.chrome.browser.preferences.TextMessagePreference
         android:title="@string/contextual_search_description" />
diff --git a/chrome/android/java/res/xml/contextual_suggestions_preferences.xml b/chrome/android/java/res/xml/contextual_suggestions_preferences.xml
index b20de75..d60a4d51 100644
--- a/chrome/android/java/res/xml/contextual_suggestions_preferences.xml
+++ b/chrome/android/java/res/xml/contextual_suggestions_preferences.xml
@@ -5,13 +5,13 @@
 
 <PreferenceScreen
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:chrome="http://schemas.android.com/apk/res-auto">
+    xmlns:app="http://schemas.android.com/apk/res-auto">
 
     <org.chromium.chrome.browser.preferences.ChromeSwitchPreference
         android:key="contextual_suggestions_switch"
         android:summaryOn="@string/text_on"
         android:summaryOff="@string/text_off"
-        chrome:drawDivider="true" />
+        app:drawDivider="true" />
 
     <org.chromium.chrome.browser.preferences.TextMessagePreference
         android:title="@string/contextual_suggestions_description" />
diff --git a/chrome/android/java/res/xml/data_reduction_preferences_off.xml b/chrome/android/java/res/xml/data_reduction_preferences_off.xml
index f6154aaf..b8106717 100644
--- a/chrome/android/java/res/xml/data_reduction_preferences_off.xml
+++ b/chrome/android/java/res/xml/data_reduction_preferences_off.xml
@@ -4,7 +4,7 @@
      found in the LICENSE file. -->
 
 <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
-                  xmlns:chrome="http://schemas.android.com/apk/res-auto" >
+                  xmlns:app="http://schemas.android.com/apk/res-auto" >
 
     <org.chromium.chrome.browser.preferences.TextMessagePreference
         android:title="@string/data_reduction_description" />
@@ -14,5 +14,5 @@
         android:title="@string/data_reduction_caveats_description" />
     <org.chromium.chrome.browser.preferences.LearnMorePreference
         android:key="data_reduction_learn_more"
-        chrome:helpContext="@string/help_context_data_reduction" />
+        app:helpContext="@string/help_context_data_reduction" />
 </PreferenceScreen>
diff --git a/chrome/android/java/res/xml/do_not_track_preferences.xml b/chrome/android/java/res/xml/do_not_track_preferences.xml
index a12a993..18dd6ad5 100644
--- a/chrome/android/java/res/xml/do_not_track_preferences.xml
+++ b/chrome/android/java/res/xml/do_not_track_preferences.xml
@@ -5,13 +5,13 @@
 
 <PreferenceScreen
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:chrome="http://schemas.android.com/apk/res-auto">
+    xmlns:app="http://schemas.android.com/apk/res-auto">
 
     <org.chromium.chrome.browser.preferences.ChromeSwitchPreference
         android:key="do_not_track_switch"
         android:summaryOn="@string/text_on"
         android:summaryOff="@string/text_off"
-        chrome:drawDivider="true" />
+        app:drawDivider="true" />
 
     <org.chromium.chrome.browser.preferences.TextMessagePreference
         android:title="@string/do_not_track_description" />
diff --git a/chrome/android/java/res/xml/homepage_preferences.xml b/chrome/android/java/res/xml/homepage_preferences.xml
index 4ac201e3..a54efc5 100644
--- a/chrome/android/java/res/xml/homepage_preferences.xml
+++ b/chrome/android/java/res/xml/homepage_preferences.xml
@@ -4,8 +4,7 @@
      found in the LICENSE file. -->
 
 <PreferenceScreen
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:chrome="http://schemas.android.com/apk/res-auto">
+    xmlns:android="http://schemas.android.com/apk/res/android">
 
     <org.chromium.chrome.browser.preferences.ChromeSwitchPreference
         android:key="homepage_switch"
diff --git a/chrome/android/java/res/xml/translate_preferences.xml b/chrome/android/java/res/xml/translate_preferences.xml
index 76fa526..9b80ffd7 100644
--- a/chrome/android/java/res/xml/translate_preferences.xml
+++ b/chrome/android/java/res/xml/translate_preferences.xml
@@ -5,13 +5,13 @@
 
 <PreferenceScreen
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:chrome="http://schemas.android.com/apk/res-auto">
+    xmlns:app="http://schemas.android.com/apk/res-auto">
 
     <org.chromium.chrome.browser.preferences.ChromeSwitchPreference
         android:key="translate_switch"
         android:summaryOn="@string/text_on"
         android:summaryOff="@string/text_off"
-        chrome:drawDivider="true" />
+        app:drawDivider="true" />
 
     <org.chromium.chrome.browser.preferences.TextMessagePreference
         android:title="@string/translate_prefs_description" />
diff --git a/chrome/android/java/res/xml/usage_and_crash_reports_preferences.xml b/chrome/android/java/res/xml/usage_and_crash_reports_preferences.xml
index 0660da2..1b444f5 100644
--- a/chrome/android/java/res/xml/usage_and_crash_reports_preferences.xml
+++ b/chrome/android/java/res/xml/usage_and_crash_reports_preferences.xml
@@ -5,19 +5,19 @@
 
 <PreferenceScreen
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:chrome="http://schemas.android.com/apk/res-auto">
+    xmlns:app="http://schemas.android.com/apk/res-auto">
 
     <org.chromium.chrome.browser.preferences.ChromeSwitchPreference
         android:key="usage_and_crash_reports_switch"
         android:summaryOn="@string/text_on"
         android:summaryOff="@string/text_off"
-        chrome:drawDivider="true"/>
+        app:drawDivider="true"/>
 
     <org.chromium.chrome.browser.preferences.TextMessagePreference
         android:title="@string/usage_and_crash_reports_description"/>
 
     <org.chromium.chrome.browser.preferences.LearnMorePreference
         android:key="usage_and_crash_reports_learn_more"
-        chrome:helpContext="@string/help_context_usage_reports"/>
+        app:helpContext="@string/help_context_usage_reports"/>
 
 </PreferenceScreen>
\ No newline at end of file
diff --git a/chrome/android/java/res/xml/website_preferences.xml b/chrome/android/java/res/xml/website_preferences.xml
index 82505c0..4a6e796 100644
--- a/chrome/android/java/res/xml/website_preferences.xml
+++ b/chrome/android/java/res/xml/website_preferences.xml
@@ -5,7 +5,7 @@
 
 <PreferenceScreen
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:chrome="http://schemas.android.com/apk/res-auto"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
     android:title="@string/all_sites">
     <!-- A global toggle, only shown for specific categories that allow turning default values
          for that category on/off.-->
@@ -29,7 +29,7 @@
     <org.chromium.chrome.browser.preferences.LearnMorePreference
         android:key="protected_content_learn_more"
         android:background="?android:attr/listDivider"
-        chrome:helpContext="@string/help_context_protected_content"/>
+        app:helpContext="@string/help_context_protected_content"/>
     <!-- Collapsible headers for sorting preferences. -->
     <org.chromium.chrome.browser.preferences.ExpandablePreferenceGroup
         android:key="blocked_group" />
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/BluetoothChooserDialog.java b/chrome/android/java/src/org/chromium/chrome/browser/BluetoothChooserDialog.java
index b4a6345..11a1ef6 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/BluetoothChooserDialog.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/BluetoothChooserDialog.java
@@ -16,11 +16,11 @@
 import android.location.LocationManager;
 import android.support.graphics.drawable.VectorDrawableCompat;
 import android.support.v4.graphics.drawable.DrawableCompat;
+import android.support.v7.content.res.AppCompatResources;
 import android.text.SpannableString;
 import android.text.TextUtils;
 import android.view.View;
 
-import org.chromium.base.ApiCompatibilityUtils;
 import org.chromium.base.Log;
 import org.chromium.base.VisibleForTesting;
 import org.chromium.base.annotations.CalledByNative;
@@ -155,7 +155,8 @@
 
         Drawable drawable = VectorDrawableCompat.create(res, icon, mActivity.getTheme());
         DrawableCompat.setTintList(drawable,
-                ApiCompatibilityUtils.getColorStateList(res, R.color.item_chooser_row_icon_color));
+                AppCompatResources.getColorStateList(
+                        mActivity, R.color.item_chooser_row_icon_color));
         return drawable;
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuAdapter.java
index d027d0b..d9fb1a9 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuAdapter.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuAdapter.java
@@ -9,6 +9,7 @@
 import android.animation.AnimatorSet;
 import android.animation.ObjectAnimator;
 import android.graphics.drawable.Drawable;
+import android.support.v7.content.res.AppCompatResources;
 import android.text.TextUtils;
 import android.view.LayoutInflater;
 import android.view.MenuItem;
@@ -19,7 +20,6 @@
 import android.widget.ListView;
 import android.widget.TextView;
 
-import org.chromium.base.ApiCompatibilityUtils;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.omaha.UpdateMenuItemHelper;
 import org.chromium.chrome.browser.widget.TintedImageButton;
@@ -286,8 +286,8 @@
 
         // The checkbox must be tinted to make Android consistently style it across OS versions.
         // http://crbug.com/571445
-        button.setTint(ApiCompatibilityUtils.getColorStateList(
-                button.getResources(), R.color.checkbox_tint));
+        button.setTint(
+                AppCompatResources.getColorStateList(button.getContext(), R.color.checkbox_tint));
 
         setupMenuButton(button, item);
     }
@@ -300,8 +300,8 @@
         item.getIcon().setLevel(currentLevel);
 
         if (item.isChecked()) {
-            button.setTint(ApiCompatibilityUtils.getColorStateList(
-                    button.getResources(), R.color.blue_mode_tint));
+            button.setTint(AppCompatResources.getColorStateList(
+                    button.getContext(), R.color.blue_mode_tint));
         }
 
         setupMenuButton(button, item);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkAddEditFolderActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkAddEditFolderActivity.java
index 8922e23..0bb0f140 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkAddEditFolderActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkAddEditFolderActivity.java
@@ -191,7 +191,7 @@
         } else {
             mDeleteButton = menu.add(R.string.bookmark_action_bar_delete)
                                     .setIcon(TintedDrawable.constructTintedDrawable(
-                                            getResources(), R.drawable.ic_delete_white_24dp))
+                                            this, R.drawable.ic_delete_white_24dp))
                                     .setShowAsActionFlags(MenuItem.SHOW_AS_ACTION_IF_ROOM);
         }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkEditActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkEditActivity.java
index ac271060..d1ba157 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkEditActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkEditActivity.java
@@ -118,7 +118,7 @@
     public boolean onCreateOptionsMenu(Menu menu) {
         mDeleteButton = menu.add(R.string.bookmark_action_bar_delete)
                                 .setIcon(TintedDrawable.constructTintedDrawable(
-                                        getResources(), R.drawable.ic_delete_white_24dp))
+                                        this, R.drawable.ic_delete_white_24dp))
                                 .setShowAsActionFlags(MenuItem.SHOW_AS_ACTION_IF_ROOM);
 
         return super.onCreateOptionsMenu(menu);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkFolderRow.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkFolderRow.java
index 957caa20..5c9086d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkFolderRow.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkFolderRow.java
@@ -6,9 +6,9 @@
 
 import android.content.Context;
 import android.content.res.ColorStateList;
+import android.support.v7.content.res.AppCompatResources;
 import android.util.AttributeSet;
 
-import org.chromium.base.ApiCompatibilityUtils;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkItem;
 import org.chromium.components.bookmarks.BookmarkId;
@@ -28,7 +28,7 @@
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
-        setIconDrawable(BookmarkUtils.getFolderIcon(getResources()));
+        setIconDrawable(BookmarkUtils.getFolderIcon(getContext()));
     }
 
     // BookmarkRow implementation.
@@ -52,7 +52,7 @@
 
     @Override
     protected ColorStateList getDefaultIconTint() {
-        return ApiCompatibilityUtils.getColorStateList(
-                getResources(), BookmarkUtils.getFolderIconTint());
+        return AppCompatResources.getColorStateList(
+                getContext(), BookmarkUtils.getFolderIconTint());
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkFolderSelectActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkFolderSelectActivity.java
index 0f443524e..d9cbef78 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkFolderSelectActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkFolderSelectActivity.java
@@ -9,6 +9,7 @@
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
 import android.support.graphics.drawable.VectorDrawableCompat;
+import android.support.v7.content.res.AppCompatResources;
 import android.support.v7.widget.Toolbar;
 import android.view.LayoutInflater;
 import android.view.MenuItem;
@@ -370,13 +371,13 @@
 
             Drawable iconDrawable;
             if (entry.mType == FolderListEntry.TYPE_NORMAL) {
-                iconDrawable = BookmarkUtils.getFolderIcon(view.getResources());
+                iconDrawable = BookmarkUtils.getFolderIcon(view.getContext());
             } else {
                 // For new folder, start_icon is different.
                 VectorDrawableCompat vectorDrawable = VectorDrawableCompat.create(
                         view.getResources(), R.drawable.ic_add, view.getContext().getTheme());
-                vectorDrawable.setTintList(ApiCompatibilityUtils.getColorStateList(
-                        view.getResources(), R.color.dark_mode_tint));
+                vectorDrawable.setTintList(AppCompatResources.getColorStateList(
+                        view.getContext(), R.color.dark_mode_tint));
                 iconDrawable = vectorDrawable;
             }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkUtils.java
index 557db3f1..957d2b3e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkUtils.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkUtils.java
@@ -9,7 +9,6 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.SharedPreferences;
-import android.content.res.Resources;
 import android.net.Uri;
 import android.provider.Browser;
 import android.text.TextUtils;
@@ -267,12 +266,12 @@
     }
 
     /**
-     * @param res {@link Resources} used to retrieve the drawable.
+     * @param context {@link Context} used to retrieve the drawable.
      * @return A {@link TintedDrawable} to use for displaying bookmark folders.
      */
-    public static TintedDrawable getFolderIcon(Resources res) {
+    public static TintedDrawable getFolderIcon(Context context) {
         return TintedDrawable.constructTintedDrawable(
-                res, R.drawable.ic_folder_blue_24dp, getFolderIconTint());
+                context, R.drawable.ic_folder_blue_24dp, getFolderIconTint());
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/NonOverlappingStack.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/NonOverlappingStack.java
index 91b9ee62..e8fef88 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/NonOverlappingStack.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/NonOverlappingStack.java
@@ -12,6 +12,7 @@
 
 import org.chromium.chrome.browser.compositor.animation.CompositorAnimationHandler;
 import org.chromium.chrome.browser.compositor.animation.CompositorAnimator;
+import org.chromium.chrome.browser.compositor.layouts.components.LayoutTab;
 import org.chromium.chrome.browser.compositor.layouts.phone.StackLayoutBase;
 
 import java.lang.annotation.Retention;
@@ -218,6 +219,22 @@
     }
 
     @Override
+    protected void computeTabClippingVisibilityHelper() {
+        // Performance optimization: we don't need to draw any tab other than the centered one, the
+        // one immediately to the left, and the two immediately to the right (we need the second
+        // one for discard animations) since the others can't possibly be on screen.
+        int centeredTab = getCenteredTabIndex();
+        for (int i = 0; i < mStackTabs.length; i++) {
+            LayoutTab layoutTab = mStackTabs[i].getLayoutTab();
+            if (i < centeredTab - 1 || i > centeredTab + 2) {
+                layoutTab.setVisible(false);
+            } else {
+                layoutTab.setVisible(true);
+            }
+        }
+    }
+
+    @Override
     protected int computeReferenceIndex() {
         return -Math.round(mScrollTarget / mSpacing);
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/OverlappingStack.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/OverlappingStack.java
index 6be30d6a..73e961a 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/OverlappingStack.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/OverlappingStack.java
@@ -9,6 +9,7 @@
 
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.compositor.layouts.Layout.Orientation;
+import org.chromium.chrome.browser.compositor.layouts.components.LayoutTab;
 import org.chromium.chrome.browser.compositor.layouts.eventfilter.ScrollDirection;
 import org.chromium.chrome.browser.compositor.layouts.phone.StackLayoutBase;
 import org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation.OverviewAnimationType;
@@ -359,6 +360,125 @@
     }
 
     @Override
+    protected void computeTabClippingVisibilityHelper() {
+        // alpha override, clipping and culling.
+        final boolean portrait = mCurrentMode == Orientation.PORTRAIT;
+
+        // Iterate through each tab starting at the top of the stack and working
+        // backwards. Set the clip on each tab such that it does not extend past
+        // the beginning of the tab above it. clipOffset is used to keep track
+        // of where the previous tab started.
+        float clipOffset;
+        if (portrait) {
+            // portrait LTR & RTL
+            clipOffset = mLayout.getHeight() + StackTab.sStackedTabVisibleSize;
+        } else if (!LocalizationUtils.isLayoutRtl()) {
+            // landscape LTR
+            clipOffset = mLayout.getWidth() + StackTab.sStackedTabVisibleSize;
+        } else {
+            // landscape RTL
+            clipOffset = -StackTab.sStackedTabVisibleSize;
+        }
+
+        for (int i = mStackTabs.length - 1; i >= 0; i--) {
+            LayoutTab layoutTab = mStackTabs[i].getLayoutTab();
+            layoutTab.setVisible(true);
+
+            // Don't bother with clipping tabs that are dying, rotating, with an X offset, or
+            // non-opaque.
+            if (mStackTabs[i].isDying() || mStackTabs[i].getXInStackOffset() != 0.0f
+                    || layoutTab.getAlpha() < 1.0f) {
+                layoutTab.setClipOffset(0.0f, 0.0f);
+                layoutTab.setClipSize(Float.MAX_VALUE, Float.MAX_VALUE);
+                continue;
+            }
+
+            // The beginning, size, and clipped size of the current tab.
+            float tabOffset, tabSize, tabClippedSize, borderAdjustmentSize, insetBorderPadding;
+            if (portrait) {
+                // portrait LTR & RTL
+                tabOffset = layoutTab.getY();
+                tabSize = layoutTab.getScaledContentHeight();
+                tabClippedSize = Math.min(tabSize, clipOffset - tabOffset);
+                borderAdjustmentSize = mBorderTransparentTop;
+                insetBorderPadding = mBorderTopPadding;
+            } else if (!LocalizationUtils.isLayoutRtl()) {
+                // landscape LTR
+                tabOffset = layoutTab.getX();
+                tabSize = layoutTab.getScaledContentWidth();
+                tabClippedSize = Math.min(tabSize, clipOffset - tabOffset);
+                borderAdjustmentSize = mBorderTransparentSide;
+                insetBorderPadding = 0;
+            } else {
+                // landscape RTL
+                tabOffset = layoutTab.getX() + layoutTab.getScaledContentWidth();
+                tabSize = layoutTab.getScaledContentWidth();
+                tabClippedSize = Math.min(tabSize, tabOffset - clipOffset);
+                borderAdjustmentSize = -mBorderTransparentSide;
+                insetBorderPadding = 0;
+            }
+
+            float absBorderAdjustmentSize = Math.abs(borderAdjustmentSize);
+
+            if (tabClippedSize <= absBorderAdjustmentSize) {
+                // If the tab is completed covered, don't bother drawing it at all.
+                layoutTab.setVisible(false);
+                layoutTab.setDrawDecoration(true);
+                mLayout.releaseResourcesForTab(layoutTab);
+            } else {
+                // Fade the tab as it gets too close to the next one. This helps
+                // prevent overlapping shadows from becoming too dark.
+                float fade = MathUtils.clamp(((tabClippedSize - absBorderAdjustmentSize)
+                                                     / StackTab.sStackedTabVisibleSize),
+                        0, 1);
+                layoutTab.setDecorationAlpha(fade);
+
+                // When tabs tilt forward, it will expose more of the tab
+                // underneath. To compensate, make the clipping size larger.
+                // Note, this calculation is only an estimate that seems to
+                // work.
+                float clipScale = 1.0f;
+                if (layoutTab.getTiltX() > 0
+                        || ((!portrait && LocalizationUtils.isLayoutRtl())
+                                           ? layoutTab.getTiltY() < 0
+                                           : layoutTab.getTiltY() > 0)) {
+                    final float tilt =
+                            Math.max(layoutTab.getTiltX(), Math.abs(layoutTab.getTiltY()));
+                    clipScale += (tilt / mMaxOverScrollAngle) * 0.60f;
+                }
+
+                float scaledTabClippedSize = Math.min(tabClippedSize * clipScale, tabSize);
+                // Set the clip
+                layoutTab.setClipOffset((!portrait && LocalizationUtils.isLayoutRtl())
+                                ? (tabSize - scaledTabClippedSize)
+                                : 0,
+                        0);
+                layoutTab.setClipSize(portrait ? Float.MAX_VALUE : scaledTabClippedSize,
+                        portrait ? scaledTabClippedSize : Float.MAX_VALUE);
+            }
+
+            // Clip the next tab where this tab begins.
+            if (i > 0) {
+                LayoutTab nextLayoutTab = mStackTabs[i - 1].getLayoutTab();
+                if (nextLayoutTab.getScale() <= layoutTab.getScale()) {
+                    clipOffset = tabOffset;
+                } else {
+                    clipOffset = tabOffset + tabClippedSize * layoutTab.getScale();
+                }
+
+                // Extend the border just a little bit. Otherwise, the
+                // rounded borders will intersect and make it look like the
+                // content is actually smaller.
+                clipOffset += borderAdjustmentSize;
+
+                if (layoutTab.getBorderAlpha() < 1.f && layoutTab.getToolbarAlpha() < 1.f) {
+                    clipOffset += insetBorderPadding;
+                }
+            }
+        }
+    }
+
+    @Override
     protected int computeReferenceIndex() {
         int centerIndex =
                 getTabIndexAtPositon(mLayout.getWidth() / 2.0f, mLayout.getHeight() / 2.0f);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java
index 20808ad..40f8473 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java
@@ -159,7 +159,7 @@
     private int mOverScrollCounter;
     private float mMaxOverScroll; // This will be updated from dimens.xml
     private float mMaxUnderScroll;
-    private float mMaxOverScrollAngle; // This will be updated from values.xml
+    protected float mMaxOverScrollAngle; // This will be updated from values.xml
     private float mMaxOverScrollSlide;
     private final Interpolator mOverScrollAngleInterpolator =
             new AccelerateDecelerateInterpolator();
@@ -212,10 +212,10 @@
     protected final StackLayoutBase mLayout;
 
     // Border values
-    private float mBorderTransparentTop;
-    private float mBorderTransparentSide;
+    protected float mBorderTransparentTop;
+    protected float mBorderTransparentSide;
     // TODO(dtrainor): Expose 9-patch padding from resource manager.
-    private float mBorderTopPadding;
+    protected float mBorderTopPadding;
     private float mBorderLeftPadding;
 
     private boolean mIsStackForCurrentTabList;
@@ -1468,128 +1468,13 @@
      * ComputeTabPosition pass 5:
      * Computes the clipping, visibility and adjust overall alpha if needed.
      */
-    private void computeTabClippingVisibilityHelper() {
-        // alpha override, clipping and culling.
-        final boolean portrait = mCurrentMode == Orientation.PORTRAIT;
-
-        // Iterate through each tab starting at the top of the stack and working
-        // backwards. Set the clip on each tab such that it does not extend past
-        // the beginning of the tab above it. clipOffset is used to keep track
-        // of where the previous tab started.
-        float clipOffset;
-        if (portrait) {
-            // portrait LTR & RTL
-            clipOffset = mLayout.getHeight() + StackTab.sStackedTabVisibleSize;
-        } else if (!LocalizationUtils.isLayoutRtl()) {
-            // landscape LTR
-            clipOffset = mLayout.getWidth() + StackTab.sStackedTabVisibleSize;
-        } else {
-            // landscape RTL
-            clipOffset = -StackTab.sStackedTabVisibleSize;
-        }
-
-        for (int i = mStackTabs.length - 1; i >= 0; i--) {
-            LayoutTab layoutTab = mStackTabs[i].getLayoutTab();
-            layoutTab.setVisible(true);
-
-            // Don't bother with clipping tabs that are dying, rotating, with an X offset, or
-            // non-opaque.
-            if (mStackTabs[i].isDying() || mStackTabs[i].getXInStackOffset() != 0.0f
-                    || layoutTab.getAlpha() < 1.0f) {
-                layoutTab.setClipOffset(0.0f, 0.0f);
-                layoutTab.setClipSize(Float.MAX_VALUE, Float.MAX_VALUE);
-                continue;
-            }
-
-            // The beginning, size, and clipped size of the current tab.
-            float tabOffset, tabSize, tabClippedSize, borderAdjustmentSize, insetBorderPadding;
-            if (portrait) {
-                // portrait LTR & RTL
-                tabOffset = layoutTab.getY();
-                tabSize = layoutTab.getScaledContentHeight();
-                tabClippedSize = Math.min(tabSize, clipOffset - tabOffset);
-                borderAdjustmentSize = mBorderTransparentTop;
-                insetBorderPadding = mBorderTopPadding;
-            } else if (!LocalizationUtils.isLayoutRtl()) {
-                // landscape LTR
-                tabOffset = layoutTab.getX();
-                tabSize = layoutTab.getScaledContentWidth();
-                tabClippedSize = Math.min(tabSize, clipOffset - tabOffset);
-                borderAdjustmentSize = mBorderTransparentSide;
-                insetBorderPadding = 0;
-            } else {
-                // landscape RTL
-                tabOffset = layoutTab.getX() + layoutTab.getScaledContentWidth();
-                tabSize = layoutTab.getScaledContentWidth();
-                tabClippedSize = Math.min(tabSize, tabOffset - clipOffset);
-                borderAdjustmentSize = -mBorderTransparentSide;
-                insetBorderPadding = 0;
-            }
-
-            float absBorderAdjustmentSize = Math.abs(borderAdjustmentSize);
-
-            if (tabClippedSize <= absBorderAdjustmentSize) {
-                // If the tab is completed covered, don't bother drawing it at all.
-                layoutTab.setVisible(false);
-                layoutTab.setDrawDecoration(true);
-                mLayout.releaseResourcesForTab(layoutTab);
-            } else {
-                // Fade the tab as it gets too close to the next one. This helps
-                // prevent overlapping shadows from becoming too dark.
-                float fade = MathUtils.clamp(((tabClippedSize - absBorderAdjustmentSize)
-                                                     / StackTab.sStackedTabVisibleSize),
-                        0, 1);
-                layoutTab.setDecorationAlpha(fade);
-
-                // When tabs tilt forward, it will expose more of the tab
-                // underneath. To compensate, make the clipping size larger.
-                // Note, this calculation is only an estimate that seems to
-                // work.
-                float clipScale = 1.0f;
-                if (layoutTab.getTiltX() > 0 || ((!portrait && LocalizationUtils.isLayoutRtl())
-                                                                ? layoutTab.getTiltY() < 0
-                                                                : layoutTab.getTiltY() > 0)) {
-                    final float tilt =
-                            Math.max(layoutTab.getTiltX(), Math.abs(layoutTab.getTiltY()));
-                    clipScale += (tilt / mMaxOverScrollAngle) * 0.60f;
-                }
-
-                float scaledTabClippedSize = Math.min(tabClippedSize * clipScale, tabSize);
-                // Set the clip
-                layoutTab.setClipOffset((!portrait && LocalizationUtils.isLayoutRtl())
-                                ? (tabSize - scaledTabClippedSize)
-                                : 0,
-                        0);
-                layoutTab.setClipSize(portrait ? Float.MAX_VALUE : scaledTabClippedSize,
-                        portrait ? scaledTabClippedSize : Float.MAX_VALUE);
-            }
-
-            // Clip the next tab where this tab begins.
-            if (i > 0) {
-                LayoutTab nextLayoutTab = mStackTabs[i - 1].getLayoutTab();
-                if (nextLayoutTab.getScale() <= layoutTab.getScale()) {
-                    clipOffset = tabOffset;
-                } else {
-                    clipOffset = tabOffset + tabClippedSize * layoutTab.getScale();
-                }
-
-                // Extend the border just a little bit. Otherwise, the
-                // rounded borders will intersect and make it look like the
-                // content is actually smaller.
-                clipOffset += borderAdjustmentSize;
-
-                if (layoutTab.getBorderAlpha() < 1.f && layoutTab.getToolbarAlpha() < 1.f) {
-                    clipOffset += insetBorderPadding;
-                }
-            }
-        }
-    }
+    protected abstract void computeTabClippingVisibilityHelper();
 
     /**
      * Computes the index that should be assumed to be the currently centered tab, for purposes of
      * prioritizing which thumbnails to render.
      */
-    abstract protected int computeReferenceIndex();
+    protected abstract int computeReferenceIndex();
 
     /**
      * ComputeTabPosition pass 6:
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ShareContextMenuItem.java b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ShareContextMenuItem.java
index c308319d..0194da6 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ShareContextMenuItem.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ShareContextMenuItem.java
@@ -59,8 +59,8 @@
 
     @Override
     public void getDrawableAsync(Context context, Callback<Drawable> callback) {
-        Drawable drawable = TintedDrawable.constructTintedDrawable(
-                context.getResources(), mIconId, R.color.dark_mode_tint);
+        Drawable drawable =
+                TintedDrawable.constructTintedDrawable(context, mIconId, R.color.dark_mode_tint);
         callback.onResult(drawable);
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ToolbarView.java b/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ToolbarView.java
index 7491395a..4df926cd 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ToolbarView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ToolbarView.java
@@ -5,12 +5,12 @@
 package org.chromium.chrome.browser.contextual_suggestions;
 
 import android.content.Context;
+import android.support.v7.content.res.AppCompatResources;
 import android.util.AttributeSet;
 import android.view.View;
 import android.widget.FrameLayout;
 import android.widget.TextView;
 
-import org.chromium.base.ApiCompatibilityUtils;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.widget.ListMenuButton;
 import org.chromium.chrome.browser.widget.TintedImageView;
@@ -70,7 +70,7 @@
     }
 
     void setArrowTintResourceId(int resourceId) {
-        mArrow.setTint(ApiCompatibilityUtils.getColorStateList(getResources(), resourceId));
+        mArrow.setTint(AppCompatResources.getColorStateList(getContext(), resourceId));
     }
 
     void setSlimPeekEnabled(boolean slimPeekEnabled) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomButtonParams.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomButtonParams.java
index 4bc2348..d4aa91e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomButtonParams.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomButtonParams.java
@@ -7,7 +7,6 @@
 import android.app.PendingIntent;
 import android.content.Context;
 import android.content.Intent;
-import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
@@ -89,11 +88,11 @@
     /**
      * @return The drawable for the customized button.
      */
-    Drawable getIcon(Resources res) {
+    Drawable getIcon(Context context) {
         if (mShouldTint) {
-            return new TintedDrawable(res, mIcon);
+            return new TintedDrawable(context, mIcon);
         } else {
-            return new BitmapDrawable(res, mIcon);
+            return new BitmapDrawable(context.getResources(), mIcon);
         }
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java
index 17e74f88..080c4fb 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java
@@ -409,7 +409,9 @@
             mConnection.cancelSpeculation(mSession);
         }
 
-        getTabModelSelector().getModel(false).addObserver(mTabModelObserver);
+        getTabModelSelector()
+                .getModel(mIntentDataProvider.isIncognito())
+                .addObserver(mTabModelObserver);
 
         boolean successfulStateRestore = false;
         // Attempt to restore the previous tab state if applicable.
@@ -431,7 +433,9 @@
             } else {
                 mMainTab = createMainTab();
             }
-            getTabModelSelector().getModel(false).addTab(mMainTab, 0, mMainTab.getLaunchType());
+            getTabModelSelector()
+                    .getModel(mIntentDataProvider.isIncognito())
+                    .addTab(mMainTab, 0, mMainTab.getLaunchType());
         }
 
         // This cannot be done before because we want to do the reparenting only
@@ -500,7 +504,7 @@
                     int index = mIntentDataProvider.getCustomToolbarButtonIndexForId(id);
                     assert index != -1;
                     getToolbarManager().updateCustomActionButton(
-                            index, params.getIcon(getResources()), description);
+                            index, params.getIcon(CustomTabActivity.this), description);
                 } else {
                     if (mBottomBarDelegate != null) {
                         mBottomBarDelegate.updateBottomBarButtons(params);
@@ -587,8 +591,8 @@
                 getIntent(), IntentHandler.EXTRA_TAB_ID, Tab.INVALID_TAB_ID);
         int parentTabId = IntentUtils.safeGetIntExtra(
                 getIntent(), IntentHandler.EXTRA_PARENT_TAB_ID, Tab.INVALID_TAB_ID);
-        Tab tab = new Tab(assignedTabId, parentTabId, false, getWindowAndroid(),
-                TabLaunchType.FROM_EXTERNAL_APP, null, null);
+        Tab tab = new Tab(assignedTabId, parentTabId, mIntentDataProvider.isIncognito(),
+                getWindowAndroid(), TabLaunchType.FROM_EXTERNAL_APP, null, null);
         if (getIntent().getIntExtra(
                     CustomTabIntentDataProvider.EXTRA_BROWSER_LAUNCH_SOURCE, ACTIVITY_TYPE_OTHER)
                 == ACTIVITY_TYPE_WEBAPK) {
@@ -621,11 +625,13 @@
             webContentsStateOnLaunch = WEBCONTENTS_STATE_TRANSFERRED_WEBCONTENTS;
             webContents.resumeLoadingCreatedWebContents();
         } else {
-            webContents = WarmupManager.getInstance().takeSpareWebContents(false, false);
+            webContents = WarmupManager.getInstance().takeSpareWebContents(
+                    mIntentDataProvider.isIncognito(), false);
             if (webContents != null) {
                 webContentsStateOnLaunch = WEBCONTENTS_STATE_SPARE_WEBCONTENTS;
             } else {
-                webContents = WebContentsFactory.createWebContentsWithWarmRenderer(false, false);
+                webContents = WebContentsFactory.createWebContentsWithWarmRenderer(
+                        mIntentDataProvider.isIncognito(), false);
                 webContentsStateOnLaunch = WEBCONTENTS_STATE_NO_WEBCONTENTS;
             }
         }
@@ -971,7 +977,7 @@
         final List<CustomButtonParams> paramList = mIntentDataProvider.getCustomButtonsOnToolbar();
         for (CustomButtonParams params : paramList) {
             getToolbarManager().addCustomActionButton(
-                    params.getIcon(getResources()), params.getDescription(), v -> {
+                    params.getIcon(this), params.getDescription(), v -> {
                         if (getActivityTab() == null) return;
                         mIntentDataProvider.sendButtonPendingIntentWithUrlAndTitle(
                                 getApplicationContext(), params, getActivityTab().getUrl(),
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabBottomBarDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabBottomBarDelegate.java
index e5c0919..02176f4 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabBottomBarDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabBottomBarDelegate.java
@@ -110,7 +110,7 @@
     public void updateBottomBarButtons(CustomButtonParams params) {
         ImageButton button = (ImageButton) getBottomBarView().findViewById(params.getId());
         button.setContentDescription(params.getDescription());
-        button.setImageDrawable(params.getIcon(mActivity.getResources()));
+        button.setImageDrawable(params.getIcon(mActivity));
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java
index 341c73b..31b4b0f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java
@@ -139,6 +139,9 @@
 
     /** Whether this CustomTabActivity was explicitly started by another Chrome Activity. */
     private boolean mIsOpenedByChrome;
+
+    private boolean mIsIncognito;
+
     /**
      * Add extras to customize menu items for opening payment request UI custom tab from Chrome.
      */
@@ -180,8 +183,8 @@
             bitmap = null;
         }
         if (bitmap == null) {
-            mCloseButtonIcon = TintedDrawable.constructTintedDrawable(
-                    context.getResources(), R.drawable.btn_close);
+            mCloseButtonIcon =
+                    TintedDrawable.constructTintedDrawable(context, R.drawable.btn_close);
         } else {
             mCloseButtonIcon = new BitmapDrawable(context.getResources(), bitmap);
         }
@@ -202,6 +205,8 @@
 
         mIsOpenedByChrome =
                 IntentUtils.safeGetBooleanExtra(intent, EXTRA_IS_OPENED_BY_CHROME, false);
+        mIsIncognito = IntentUtils.safeGetBooleanExtra(
+                intent, IntentHandler.EXTRA_OPEN_NEW_INCOGNITO_TAB, false);
 
         final int requestedUiType =
                 IntentUtils.safeGetIntExtra(intent, EXTRA_UI_TYPE, CUSTOM_TABS_UI_TYPE_DEFAULT);
@@ -580,4 +585,12 @@
     boolean isForPaymentRequest() {
         return mUiType == CUSTOM_TABS_UI_TYPE_PAYMENT_REQUEST;
     }
+
+    /**
+     * @return Whether the custom Tab should be opened in incognito mode.
+     */
+    boolean isIncognito() {
+        // Only open custom tab in incognito mode for payment request.
+        return isTrustedIntent() && mIsOpenedByChrome && isForPaymentRequest() && mIsIncognito;
+    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadInfoBarController.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadInfoBarController.java
index 58baa3a..1067c6c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadInfoBarController.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadInfoBarController.java
@@ -110,6 +110,7 @@
         public ContentId id;
 
         public String message;
+        public String accessibilityMessage;
         public String link;
         public int icon;
 
@@ -618,6 +619,8 @@
         }
 
         setForceReparent(info);
+        setAccessibilityMessage(
+                info, showAccelerating && infoBarState == DownloadInfoBarState.DOWNLOADING);
         showInfoBar(infoBarState, info);
     }
 
@@ -627,6 +630,15 @@
                 mCurrentInfo == null ? null : mCurrentInfo.downloadCount);
     }
 
+    private void setAccessibilityMessage(
+            DownloadProgressInfoBarData info, boolean showAccelerating) {
+        info.accessibilityMessage = info.message;
+        if (!showAccelerating) {
+            info.accessibilityMessage = info.accessibilityMessage + " "
+                    + getContext().getString(R.string.bottom_bar_screen_position);
+        }
+    }
+
     private void clearEndTimerRunnable() {
         mHandler.removeCallbacks(mEndTimerRunnable);
         mEndTimerRunnable = null;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadUtils.java
index 8979bf9c..8328f5c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadUtils.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadUtils.java
@@ -14,6 +14,7 @@
 import android.os.StrictMode;
 import android.support.annotation.IntDef;
 import android.support.annotation.Nullable;
+import android.support.v7.content.res.AppCompatResources;
 import android.text.TextUtils;
 
 import org.chromium.base.ApiCompatibilityUtils;
@@ -1080,8 +1081,7 @@
      * @return a foreground color list.
      */
     public static ColorStateList getIconForegroundColorList(Context context) {
-        return ApiCompatibilityUtils.getColorStateList(
-                context.getResources(), R.color.white_mode_tint);
+        return AppCompatResources.getColorStateList(context, R.color.white_mode_tint);
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/ListItemViewHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/ListItemViewHolder.java
index bcc2be7..7d3bccf3 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/ListItemViewHolder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/ListItemViewHolder.java
@@ -9,6 +9,7 @@
 import android.support.annotation.Nullable;
 import android.support.v4.graphics.drawable.RoundedBitmapDrawable;
 import android.support.v4.graphics.drawable.RoundedBitmapDrawableFactory;
+import android.support.v7.content.res.AppCompatResources;
 import android.support.v7.widget.AppCompatTextView;
 import android.support.v7.widget.RecyclerView.ViewHolder;
 import android.view.LayoutInflater;
@@ -19,7 +20,6 @@
 import android.widget.ImageView;
 import android.widget.TextView;
 
-import org.chromium.base.ApiCompatibilityUtils;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.download.home.list.ListItem.DateListItem;
 import org.chromium.chrome.browser.download.home.list.ListItem.OfflineItemListItem;
@@ -185,8 +185,8 @@
             mThumbnail.getBackground().setLevel(
                     itemView.getResources().getInteger(R.integer.list_item_level_default));
             mThumbnail.setImageResource(mIconId);
-            mThumbnail.setTint(ApiCompatibilityUtils.getColorStateList(
-                    itemView.getResources(), R.color.google_blue_500));
+            mThumbnail.setTint(AppCompatResources.getColorStateList(
+                    itemView.getContext(), R.color.google_blue_500));
         }
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadItemView.java b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadItemView.java
index f843e2f9..98627801 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadItemView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadItemView.java
@@ -10,6 +10,7 @@
 import android.support.annotation.IntDef;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
+import android.support.v7.content.res.AppCompatResources;
 import android.text.TextUtils;
 import android.text.format.Formatter;
 import android.util.AttributeSet;
@@ -119,8 +120,8 @@
         mIconBackgroundResId = R.drawable.list_item_icon_modern_bg;
 
         if (FeatureUtilities.isChromeModernDesignEnabled()) {
-            mIconForegroundColorList = ApiCompatibilityUtils.getColorStateList(
-                    context.getResources(), R.color.dark_mode_tint);
+            mIconForegroundColorList =
+                    AppCompatResources.getColorStateList(context, R.color.dark_mode_tint);
         } else {
             mIconForegroundColorList = DownloadUtils.getIconForegroundColorList(context);
         }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/FilterAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/FilterAdapter.java
index c6740a1..6fddbb7 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/FilterAdapter.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/FilterAdapter.java
@@ -9,6 +9,7 @@
 import android.os.Environment;
 import android.support.annotation.LayoutRes;
 import android.support.graphics.drawable.VectorDrawableCompat;
+import android.support.v7.content.res.AppCompatResources;
 import android.text.SpannableStringBuilder;
 import android.text.Spanned;
 import android.text.style.ForegroundColorSpan;
@@ -79,8 +80,8 @@
         VectorDrawableCompat iconDrawable =
                 VectorDrawableCompat.create(mManagerUi.getActivity().getResources(), iconId,
                         mManagerUi.getActivity().getTheme());
-        iconDrawable.setTintList(ApiCompatibilityUtils.getColorStateList(
-                mManagerUi.getActivity().getResources(), R.color.dark_mode_tint));
+        iconDrawable.setTintList(AppCompatResources.getColorStateList(
+                mManagerUi.getActivity(), R.color.dark_mode_tint));
         labelView.setCompoundDrawablesWithIntrinsicBounds(iconDrawable, null, null, null);
 
         return labelView;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/OfflineGroupHeaderView.java b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/OfflineGroupHeaderView.java
index af42bfb5c..fd68aa2 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/OfflineGroupHeaderView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/OfflineGroupHeaderView.java
@@ -7,6 +7,7 @@
 import android.annotation.SuppressLint;
 import android.content.Context;
 import android.content.res.ColorStateList;
+import android.support.v7.content.res.AppCompatResources;
 import android.text.format.DateUtils;
 import android.text.format.Formatter;
 import android.util.AttributeSet;
@@ -53,8 +54,8 @@
         mIconBackgroundResId = R.drawable.list_item_icon_modern_bg;
 
         if (FeatureUtilities.isChromeModernDesignEnabled()) {
-            mIconForegroundColorList = ApiCompatibilityUtils.getColorStateList(
-                    context.getResources(), R.color.dark_mode_tint);
+            mIconForegroundColorList =
+                    AppCompatResources.getColorStateList(context, R.color.dark_mode_tint);
         } else {
             mIconForegroundColorList = DownloadUtils.getIconForegroundColorList(context);
         }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryItemView.java b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryItemView.java
index e7c48cb..8fc8f8a 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryItemView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryItemView.java
@@ -9,6 +9,7 @@
 import android.graphics.drawable.BitmapDrawable;
 import android.support.annotation.VisibleForTesting;
 import android.support.graphics.drawable.VectorDrawableCompat;
+import android.support.v7.content.res.AppCompatResources;
 import android.util.AttributeSet;
 import android.view.View;
 
@@ -52,8 +53,7 @@
         mEndPadding = context.getResources().getDimensionPixelSize(
                 R.dimen.selectable_list_layout_row_padding);
 
-        mIconColorList = ApiCompatibilityUtils.getColorStateList(
-                context.getResources(), R.color.white_mode_tint);
+        mIconColorList = AppCompatResources.getColorStateList(context, R.color.white_mode_tint);
     }
 
     @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/DownloadProgressInfoBar.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/DownloadProgressInfoBar.java
index 41bd20b..416e69c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/DownloadProgressInfoBar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/DownloadProgressInfoBar.java
@@ -8,8 +8,12 @@
 import android.support.annotation.Nullable;
 import android.support.graphics.drawable.Animatable2Compat;
 import android.support.graphics.drawable.AnimatedVectorDrawableCompat;
+import android.support.v4.view.ViewCompat;
+import android.view.View;
+import android.widget.TextView;
 
 import org.chromium.base.annotations.CalledByNative;
+import org.chromium.chrome.R;
 import org.chromium.chrome.browser.download.DownloadInfoBarController;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.components.offline_items_collection.ContentId;
@@ -110,6 +114,11 @@
         layout.setMessage(mInfo.message);
         layout.appendMessageLinkText(mInfo.link);
 
+        TextView messageView =
+                (TextView) layout.getMessageLayout().findViewById(R.id.infobar_message);
+        messageView.setContentDescription(mInfo.accessibilityMessage);
+        ViewCompat.setAccessibilityLiveRegion(messageView, View.ACCESSIBILITY_LIVE_REGION_POLITE);
+
         if (!mInfo.hasAnimation) {
             layout.getIcon().setImageResource(mInfo.icon);
             return;
@@ -151,6 +160,11 @@
         setLayoutProperties((InfoBarLayout) getView(), info);
     }
 
+    @Override
+    public CharSequence getAccessibilityText() {
+        return null;
+    }
+
     /**
      * Creates and shows the {@link DownloadProgressInfoBar}.
      * @param tab The tab that the {@link DownloadProgressInfoBar} should be shown in.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBarContainerLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBarContainerLayout.java
index 1735ef04..1e02d21 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBarContainerLayout.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBarContainerLayout.java
@@ -12,6 +12,7 @@
 import android.annotation.SuppressLint;
 import android.content.Context;
 import android.content.res.Resources;
+import android.text.TextUtils;
 import android.view.Gravity;
 import android.view.MotionEvent;
 import android.view.View;
@@ -866,6 +867,12 @@
     }
 
     @Override
+    public void announceForAccessibility(CharSequence text) {
+        if (TextUtils.isEmpty(text)) return;
+        super.announceForAccessibility(text);
+    }
+
+    @Override
     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
         super.onLayout(changed, left, top, right, bottom);
         mFloatingBehavior.updateShadowPosition();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/RecentTabsGroupView.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/RecentTabsGroupView.java
index 13ba738f7..b3089798 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/RecentTabsGroupView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/RecentTabsGroupView.java
@@ -55,9 +55,9 @@
         LevelListDrawable collapseIcon = new LevelListDrawable();
         collapseIcon.addLevel(DRAWABLE_LEVEL_COLLAPSED, DRAWABLE_LEVEL_COLLAPSED,
                 TintedDrawable.constructTintedDrawable(
-                        getResources(), R.drawable.ic_expand_more_black_24dp));
+                        getContext(), R.drawable.ic_expand_more_black_24dp));
         TintedDrawable collapse = TintedDrawable.constructTintedDrawable(
-                getResources(), R.drawable.ic_expand_less_black_24dp);
+                getContext(), R.drawable.ic_expand_less_black_24dp);
         collapseIcon.addLevel(DRAWABLE_LEVEL_EXPANDED, DRAWABLE_LEVEL_EXPANDED, collapse);
         mExpandCollapseIcon.setImageDrawable(collapseIcon);
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
index 40e4175..aa9c1b9 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
@@ -20,6 +20,7 @@
 import android.provider.Settings;
 import android.support.annotation.DrawableRes;
 import android.support.annotation.IntDef;
+import android.support.v7.content.res.AppCompatResources;
 import android.text.Editable;
 import android.text.InputType;
 import android.text.TextUtils;
@@ -738,21 +739,6 @@
     }
 
     /**
-     * Updates the omnibox text selection when focused. When displaying a query in the omnibox,
-     * we want to move the cursor to the end of the search terms to more easily refine the search,
-     * and when displaying a URL we select all.
-     */
-    private void updateFocusedUrlBarSelection() {
-        if (!mUrlBar.hasFocus()) return;
-
-        if (mToolbarDataProvider.shouldDisplaySearchTerms()) {
-            mUrlBar.setSelection(mUrlBar.getText().length());
-        } else {
-            selectAll();
-        }
-    }
-
-    /**
      * Triggered when the URL input field has gained or lost focus.
      * @param hasFocus Whether the URL field has gained focus.
      */
@@ -802,7 +788,7 @@
         changeLocationBarIcon();
         updateVerboseStatusVisibility();
         updateLocationBarIconContainerVisibility();
-        updateFocusedUrlBarSelection();
+        if (hasFocus) selectAll();
         mUrlBar.setCursorVisible(hasFocus);
 
         if (!mUrlFocusedWithoutAnimations) handleUrlFocusAnimation(hasFocus);
@@ -1109,7 +1095,7 @@
         if (!mIsTablet) return;
         switch (buttonType) {
             case PAGE:
-                Drawable page = TintedDrawable.constructTintedDrawable(getResources(),
+                Drawable page = TintedDrawable.constructTintedDrawable(getContext(),
                         R.drawable.ic_omnibox_page,
                         mUseDarkColors ? R.color.dark_mode_tint : R.color.light_mode_tint);
                 mNavigationButton.setImageDrawable(page);
@@ -2107,8 +2093,8 @@
         if (updateUseDarkColors() || mIsEmphasizingHttpsScheme != shouldEmphasizeHttpsScheme()) {
             updateSecurityIcon();
         }
-        ColorStateList colorStateList = ApiCompatibilityUtils.getColorStateList(getResources(),
-                mUseDarkColors ? R.color.dark_mode_tint : R.color.light_mode_tint);
+        int id = mUseDarkColors ? R.color.dark_mode_tint : R.color.light_mode_tint;
+        ColorStateList colorStateList = AppCompatResources.getColorStateList(getContext(), id);
         mMicButton.setTint(colorStateList);
         mDeleteButton.setTint(colorStateList);
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/SuggestionView.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/SuggestionView.java
index 120ba1b..3d31e8e8 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/SuggestionView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/SuggestionView.java
@@ -12,6 +12,7 @@
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.drawable.Drawable;
+import android.support.annotation.ColorRes;
 import android.support.annotation.IntDef;
 import android.support.v4.view.ViewCompat;
 import android.support.v7.app.AlertDialog;
@@ -419,10 +420,10 @@
     private void setRefineIcon(boolean invalidateIcon) {
         if (!invalidateIcon && mRefineIcon != null) return;
 
+        @ColorRes
+        int tintId = mUseDarkColors ? R.color.dark_mode_tint : R.color.light_mode_tint;
         mRefineIcon = TintedDrawable.constructTintedDrawable(
-                getResources(), R.drawable.btn_suggestion_refine);
-        mRefineIcon.setTint(ApiCompatibilityUtils.getColorStateList(getResources(),
-                mUseDarkColors ? R.color.dark_mode_tint : R.color.light_mode_tint));
+                getContext(), R.drawable.btn_suggestion_refine, tintId);
         mRefineIcon.setBounds(
                 0, 0,
                 mRefineIcon.getIntrinsicWidth(),
@@ -1050,7 +1051,7 @@
                 default:
                     break;
             }
-            mSuggestionIcon = TintedDrawable.constructTintedDrawable(getResources(), drawableId,
+            mSuggestionIcon = TintedDrawable.constructTintedDrawable(getContext(), drawableId,
                     mUseDarkColors ? R.color.dark_mode_tint : R.color.white_mode_tint);
             mSuggestionIcon.setBounds(
                     0, 0,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/page_info/PageInfoView.java b/chrome/android/java/src/org/chromium/chrome/browser/page_info/PageInfoView.java
index 22dee2a..54ffb4b2 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/page_info/PageInfoView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/page_info/PageInfoView.java
@@ -303,8 +303,8 @@
         ImageView permissionIcon =
                 (ImageView) permissionRow.findViewById(R.id.page_info_permission_icon);
         if (params.iconTintColorResource == 0) {
-            permissionIcon.setImageDrawable(TintedDrawable.constructTintedDrawable(
-                    getContext().getResources(), params.iconResource));
+            permissionIcon.setImageDrawable(
+                    TintedDrawable.constructTintedDrawable(getContext(), params.iconResource));
         } else {
             permissionIcon.setImageResource(params.iconResource);
             permissionIcon.setColorFilter(ApiCompatibilityUtils.getColor(
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestHeader.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestHeader.java
index 0aa0132..6056902 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestHeader.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestHeader.java
@@ -59,8 +59,8 @@
         if (origin.startsWith(UrlConstants.HTTPS_URL_PREFIX)) {
             // Add a lock icon.
             ApiCompatibilityUtils.setCompoundDrawablesRelativeWithIntrinsicBounds(hostName,
-                    TintedDrawable.constructTintedDrawable(mContext.getResources(),
-                            R.drawable.omnibox_https_valid, R.color.google_green_700),
+                    TintedDrawable.constructTintedDrawable(
+                            mContext, R.drawable.omnibox_https_valid, R.color.google_green_700),
                     null, null, null);
 
             // Remove left padding to align left compound drawable with the title. Note that the
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestSection.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestSection.java
index 71f85076..2a74b8e5 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestSection.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestSection.java
@@ -409,9 +409,8 @@
     }
 
     private ImageView createAndAddChevron(ViewGroup parent) {
-        Resources resources = parent.getResources();
-        TintedDrawable chevron = TintedDrawable.constructTintedDrawable(
-                resources, R.drawable.ic_expand_more_black_24dp, R.color.payments_section_chevron);
+        TintedDrawable chevron = TintedDrawable.constructTintedDrawable(parent.getContext(),
+                R.drawable.ic_expand_more_black_24dp, R.color.payments_section_chevron);
 
         ImageView view = new ImageView(parent.getContext());
         view.setImageDrawable(chevron);
@@ -895,7 +894,7 @@
                     }
 
                     TintedDrawable tintedDrawable = TintedDrawable.constructTintedDrawable(
-                            context.getResources(), drawableId, drawableTint);
+                            context, drawableId, drawableTint);
                     ImageButton button = new ImageButton(context);
                     button.setBackground(null);
                     button.setImageDrawable(tintedDrawable);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/datareduction/DataReductionSiteBreakdownView.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/datareduction/DataReductionSiteBreakdownView.java
index 7377b16..cdeb145 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/datareduction/DataReductionSiteBreakdownView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/datareduction/DataReductionSiteBreakdownView.java
@@ -39,6 +39,7 @@
     private int mNumDataUseItemsToDisplay = 10;
 
     private TableLayout mTableLayout;
+    private TextView mDetailsTitle;
     private TextView mHostnameTitle;
     private TextView mDataUsedTitle;
     private TextView mDataSavedTitle;
@@ -53,6 +54,7 @@
     protected void onFinishInflate() {
         super.onFinishInflate();
         mTableLayout = (TableLayout) findViewById(R.id.data_reduction_proxy_breakdown_table);
+        mDetailsTitle = (TextView) findViewById(R.id.data_reduction_data_usage_breakdown_title);
         mHostnameTitle = (TextView) findViewById(R.id.data_reduction_breakdown_site_title);
         mDataUsedTitle = (TextView) findViewById(R.id.data_reduction_breakdown_used_title);
         mDataSavedTitle = (TextView) findViewById(R.id.data_reduction_breakdown_saved_title);
@@ -66,6 +68,8 @@
                 setTextViewUnsortedAttributes(mDataUsedTitle);
                 setTextViewSortedAttributes(mHostnameTitle);
                 Collections.sort(mDataUseItems, new HostnameComparator());
+                mDetailsTitle.setContentDescription(
+                        getContext().getString(R.string.data_reduction_breakdown_hostname_sorted));
                 updateSiteBreakdown();
             }
         });
@@ -79,6 +83,8 @@
                 setTextViewUnsortedAttributes(mDataSavedTitle);
                 setTextViewSortedAttributes(mDataUsedTitle);
                 Collections.sort(mDataUseItems, new DataUsedComparator());
+                mDetailsTitle.setContentDescription(
+                        getContext().getString(R.string.data_reduction_breakdown_data_used_sorted));
                 updateSiteBreakdown();
             }
         });
@@ -92,6 +98,8 @@
                 setTextViewUnsortedAttributes(mDataUsedTitle);
                 setTextViewSortedAttributes(mDataSavedTitle);
                 Collections.sort(mDataUseItems, new DataSavedComparator());
+                mDetailsTitle.setContentDescription(getContext().getString(
+                        R.string.data_reduction_breakdown_data_saved_sorted));
                 updateSiteBreakdown();
             }
         });
@@ -118,6 +126,8 @@
         setTextViewUnsortedAttributes(mDataUsedTitle);
         setTextViewSortedAttributes(mDataSavedTitle);
         Collections.sort(mDataUseItems, new DataSavedComparator());
+        mDetailsTitle.setContentDescription(
+                getContext().getString(R.string.data_reduction_breakdown_data_saved_sorted));
         if (mDataUseItems.size() == 0) {
             setVisibility(GONE);
         } else {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/languages/LanguageListPreference.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/languages/LanguageListPreference.java
index d10c4c6..002e1fd 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/languages/LanguageListPreference.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/languages/LanguageListPreference.java
@@ -144,7 +144,7 @@
         mAddLanguageButton = (TextView) mView.findViewById(R.id.add_language);
         ApiCompatibilityUtils.setCompoundDrawablesRelativeWithIntrinsicBounds(mAddLanguageButton,
                 TintedDrawable.constructTintedDrawable(
-                        getContext().getResources(), R.drawable.plus, R.color.pref_accent_color),
+                        getContext(), R.drawable.plus, R.color.pref_accent_color),
                 null, null, null);
         mAddLanguageButton.setOnClickListener(view -> {
             mLauncher.launchAddLanguage();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/privacy/ClearBrowsingDataPreferences.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/privacy/ClearBrowsingDataPreferences.java
index 4d2ee7f..bc480a3 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/privacy/ClearBrowsingDataPreferences.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/privacy/ClearBrowsingDataPreferences.java
@@ -6,6 +6,7 @@
 
 import android.app.Activity;
 import android.app.ProgressDialog;
+import android.content.Context;
 import android.content.Intent;
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
@@ -57,18 +58,17 @@
     private static class Item implements BrowsingDataCounterCallback,
                                          Preference.OnPreferenceClickListener {
         private static final int MIN_DP_FOR_ICON = 360;
+        private final Context mContext;
         private final ClearBrowsingDataPreferences mParent;
         private final DialogOption mOption;
         private final ClearBrowsingDataCheckBoxPreference mCheckbox;
         private BrowsingDataCounterBridge mCounter;
         private boolean mShouldAnnounceCounterResult;
 
-        public Item(ClearBrowsingDataPreferences parent,
-                    DialogOption option,
-                    ClearBrowsingDataCheckBoxPreference checkbox,
-                    boolean selected,
-                    boolean enabled) {
+        public Item(Context context, ClearBrowsingDataPreferences parent, DialogOption option,
+                ClearBrowsingDataCheckBoxPreference checkbox, boolean selected, boolean enabled) {
             super();
+            mContext = context;
             mParent = parent;
             mOption = option;
             mCheckbox = checkbox;
@@ -83,7 +83,7 @@
             if (dp >= MIN_DP_FOR_ICON) {
                 if (option.iconIsBitmap()) {
                     Drawable icon = TintedDrawable.constructTintedDrawable(
-                            mParent.getResources(), option.getIcon(), R.color.google_grey_600);
+                            mContext, option.getIcon(), R.color.google_grey_600);
                     mCheckbox.setIcon(icon);
                 } else {
                     Drawable icon = VectorDrawableCompat.create(mParent.getResources(),
@@ -525,12 +525,10 @@
                         false);
             }
 
-            mItems[i] = new Item(
-                this,
-                options[i],
-                (ClearBrowsingDataCheckBoxPreference) findPreference(options[i].getPreferenceKey()),
-                isOptionSelectedByDefault(options[i]),
-                enabled);
+            mItems[i] = new Item(getActivity(), this, options[i],
+                    (ClearBrowsingDataCheckBoxPreference) findPreference(
+                            options[i].getPreferenceKey()),
+                    isOptionSelectedByDefault(options[i]), enabled);
         }
 
         // Not all checkboxes defined in the layout are necessarily handled by this class
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SingleCategoryPreferences.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SingleCategoryPreferences.java
index a30f2eb..85438fa7 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SingleCategoryPreferences.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SingleCategoryPreferences.java
@@ -206,7 +206,7 @@
 
         // Set the title and arrow icons for the header.
         allowedGroup.setGroupTitle(resourceId, numAllowed);
-        TintedDrawable icon = TintedDrawable.constructTintedDrawable(getResources(),
+        TintedDrawable icon = TintedDrawable.constructTintedDrawable(getActivity(),
                 mAllowListExpanded ? R.drawable.ic_expand_more_black_24dp
                                    : R.drawable.ic_expand_less_black_24dp);
         allowedGroup.setExpanded(mAllowListExpanded);
@@ -227,7 +227,7 @@
                 ? R.string.website_settings_blocked_group_heading_sound
                 : R.string.website_settings_blocked_group_heading;
         blockedGroup.setGroupTitle(resourceId, numBlocked);
-        TintedDrawable icon = TintedDrawable.constructTintedDrawable(getResources(),
+        TintedDrawable icon = TintedDrawable.constructTintedDrawable(getActivity(),
                 mBlockListExpanded ? R.drawable.ic_expand_more_black_24dp
                                    : R.drawable.ic_expand_less_black_24dp);
         blockedGroup.setExpanded(mBlockListExpanded);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/TabSwitcherButtonView.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/TabSwitcherButtonView.java
index 42f4630d..7de441d8 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/TabSwitcherButtonView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/TabSwitcherButtonView.java
@@ -5,7 +5,6 @@
 package org.chromium.chrome.browser.toolbar;
 
 import android.content.Context;
-import android.content.res.Resources;
 import android.util.AttributeSet;
 import android.widget.ImageView;
 
@@ -29,9 +28,8 @@
     protected void onFinishInflate() {
         super.onFinishInflate();
 
-        Resources resources = getResources();
         mTabSwitcherButtonButtonDrawable =
-                TabSwitcherDrawable.createTabSwitcherDrawable(resources, false);
+                TabSwitcherDrawable.createTabSwitcherDrawable(getContext(), false);
         setImageDrawable(mTabSwitcherButtonButtonDrawable);
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/TabSwitcherDrawable.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/TabSwitcherDrawable.java
index 2d0d743..c693a7ea 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/TabSwitcherDrawable.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/TabSwitcherDrawable.java
@@ -4,17 +4,17 @@
 
 package org.chromium.chrome.browser.toolbar;
 
+import android.content.Context;
 import android.content.res.ColorStateList;
-import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.graphics.Canvas;
 import android.graphics.Paint.Align;
 import android.graphics.Rect;
 import android.graphics.Typeface;
+import android.support.v7.content.res.AppCompatResources;
 import android.text.TextPaint;
 
-import org.chromium.base.ApiCompatibilityUtils;
 import org.chromium.base.VisibleForTesting;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeFeatureList;
@@ -40,27 +40,26 @@
 
     /**
      * Creates a {@link TabSwitcherDrawable}.
-     * @param resources A {@link Resources} instance.
+     * @param context A {@link Context} instance.
      * @param useLight  Whether or not to use light or dark textures and text colors.
      * @return          A {@link TabSwitcherDrawable} instance.
      */
-    public static TabSwitcherDrawable createTabSwitcherDrawable(
-            Resources resources, boolean useLight) {
-        Bitmap icon = BitmapFactory.decodeResource(resources,
+    public static TabSwitcherDrawable createTabSwitcherDrawable(Context context, boolean useLight) {
+        Bitmap icon = BitmapFactory.decodeResource(context.getResources(),
                 FeatureUtilities.isChromeModernDesignEnabled() && !DeviceFormFactor.isTablet()
                         ? R.drawable.btn_tabswitcher_modern
                         : R.drawable.btn_tabswitcher);
-        return new TabSwitcherDrawable(resources, useLight, icon);
+        return new TabSwitcherDrawable(context, useLight, icon);
     }
 
-    private TabSwitcherDrawable(Resources resources, boolean useLight, Bitmap bitmap) {
-        super(resources, bitmap);
-        setTint(ApiCompatibilityUtils.getColorStateList(resources,
-                useLight ? R.color.light_mode_tint : R.color.dark_mode_tint));
+    private TabSwitcherDrawable(Context context, boolean useLight, Bitmap bitmap) {
+        super(context, bitmap);
+        int id = useLight ? R.color.light_mode_tint : R.color.dark_mode_tint;
+        setTint(AppCompatResources.getColorStateList(context, id));
         mSingleDigitTextSize =
-                resources.getDimension(R.dimen.toolbar_tab_count_text_size_1_digit);
+                context.getResources().getDimension(R.dimen.toolbar_tab_count_text_size_1_digit);
         mDoubleDigitTextSize =
-                resources.getDimension(R.dimen.toolbar_tab_count_text_size_2_digit);
+                context.getResources().getDimension(R.dimen.toolbar_tab_count_text_size_2_digit);
 
         mTextPaint = new TextPaint();
         mTextPaint.setAntiAlias(true);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarLayout.java
index ffaba488..6b7621c0 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarLayout.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarLayout.java
@@ -14,6 +14,7 @@
 import android.graphics.drawable.Drawable;
 import android.os.SystemClock;
 import android.support.annotation.Nullable;
+import android.support.v7.content.res.AppCompatResources;
 import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.view.InputDevice;
@@ -98,10 +99,9 @@
      */
     public ToolbarLayout(Context context, AttributeSet attrs) {
         super(context, attrs);
-        mDarkModeTint =
-                ApiCompatibilityUtils.getColorStateList(getResources(), R.color.dark_mode_tint);
+        mDarkModeTint = AppCompatResources.getColorStateList(getContext(), R.color.dark_mode_tint);
         mLightModeTint =
-                ApiCompatibilityUtils.getColorStateList(getResources(), R.color.light_mode_tint);
+                AppCompatResources.getColorStateList(getContext(), R.color.light_mode_tint);
         mProgressBar = createProgressBar();
 
         addOnLayoutChangeListener(new OnLayoutChangeListener() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarModel.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarModel.java
index 8014c95..0f0c37a 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarModel.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarModel.java
@@ -6,12 +6,11 @@
 
 import android.content.Context;
 import android.content.res.ColorStateList;
-import android.content.res.Resources;
 import android.support.annotation.DrawableRes;
 import android.support.annotation.Nullable;
+import android.support.v7.content.res.AppCompatResources;
 import android.text.TextUtils;
 
-import org.chromium.base.ApiCompatibilityUtils;
 import org.chromium.base.ContextUtils;
 import org.chromium.base.VisibleForTesting;
 import org.chromium.base.annotations.CalledByNative;
@@ -353,31 +352,30 @@
     public ColorStateList getSecurityIconColorStateList() {
         int securityLevel = getSecurityLevel();
 
-        Resources resources = mContext.getResources();
         ColorStateList list = null;
         int color = getPrimaryColor();
         boolean needLightIcon = ColorUtils.shouldUseLightForegroundOnBackground(color);
         if (isIncognito() || needLightIcon) {
             // For a dark theme color, use light icons.
-            list = ApiCompatibilityUtils.getColorStateList(resources, R.color.light_mode_tint);
+            list = AppCompatResources.getColorStateList(mContext, R.color.light_mode_tint);
         } else if (!hasTab() || isUsingBrandColor()
                 || ChromeFeatureList.isEnabled(
                            ChromeFeatureList.OMNIBOX_HIDE_SCHEME_DOMAIN_IN_STEADY_STATE)) {
             // For theme colors which are not dark and are also not
             // light enough to warrant an opaque URL bar, use dark
             // icons.
-            list = ApiCompatibilityUtils.getColorStateList(resources, R.color.dark_mode_tint);
+            list = AppCompatResources.getColorStateList(mContext, R.color.dark_mode_tint);
         } else {
             // For the default toolbar color, use a green or red icon.
             if (securityLevel == ConnectionSecurityLevel.DANGEROUS) {
                 assert !shouldDisplaySearchTerms();
-                list = ApiCompatibilityUtils.getColorStateList(resources, R.color.google_red_700);
+                list = AppCompatResources.getColorStateList(mContext, R.color.google_red_700);
             } else if (!shouldDisplaySearchTerms()
                     && (securityLevel == ConnectionSecurityLevel.SECURE
                                || securityLevel == ConnectionSecurityLevel.EV_SECURE)) {
-                list = ApiCompatibilityUtils.getColorStateList(resources, R.color.google_green_700);
+                list = AppCompatResources.getColorStateList(mContext, R.color.google_green_700);
             } else {
-                list = ApiCompatibilityUtils.getColorStateList(resources, R.color.dark_mode_tint);
+                list = AppCompatResources.getColorStateList(mContext, R.color.dark_mode_tint);
             }
         }
         assert list != null : "Missing ColorStateList for Security Button.";
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarPhone.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarPhone.java
index 4aa5a27..9d0038b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarPhone.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarPhone.java
@@ -462,11 +462,10 @@
         mNewTabButton = (NewTabButton) findViewById(R.id.new_tab_button);
 
         mToggleTabStackButton.setClickable(false);
-        Resources resources = getResources();
         mTabSwitcherButtonDrawable =
-                TabSwitcherDrawable.createTabSwitcherDrawable(resources, false);
+                TabSwitcherDrawable.createTabSwitcherDrawable(getContext(), false);
         mTabSwitcherButtonDrawableLight =
-                TabSwitcherDrawable.createTabSwitcherDrawable(resources, true);
+                TabSwitcherDrawable.createTabSwitcherDrawable(getContext(), true);
         mToggleTabStackButton.setImageDrawable(mTabSwitcherButtonDrawable);
         mTabSwitcherModeViews.add(mNewTabButton);
 
@@ -2313,9 +2312,8 @@
                 || ColorUtils.shouldUseLightForegroundOnBackground(getTabThemeColor());
         if (mTabSwitcherAnimationTabStackDrawable == null
                 || mIsOverlayTabStackDrawableLight != useTabStackDrawableLight) {
-            mTabSwitcherAnimationTabStackDrawable =
-                    TabSwitcherDrawable.createTabSwitcherDrawable(
-                            getResources(), useTabStackDrawableLight);
+            mTabSwitcherAnimationTabStackDrawable = TabSwitcherDrawable.createTabSwitcherDrawable(
+                    getContext(), useTabStackDrawableLight);
             int[] stateSet = {android.R.attr.state_enabled};
             mTabSwitcherAnimationTabStackDrawable.setState(stateSet);
             mTabSwitcherAnimationTabStackDrawable.setBounds(
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarTablet.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarTablet.java
index 8aed577f..f02c36e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarTablet.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarTablet.java
@@ -10,6 +10,7 @@
 import android.annotation.SuppressLint;
 import android.content.Context;
 import android.content.res.Resources;
+import android.support.v7.content.res.AppCompatResources;
 import android.util.AttributeSet;
 import android.view.View;
 import android.view.View.OnClickListener;
@@ -103,9 +104,9 @@
         mShowTabStack = AccessibilityUtil.isAccessibilityEnabled();
 
         mTabSwitcherButtonDrawable =
-                TabSwitcherDrawable.createTabSwitcherDrawable(getResources(), false);
+                TabSwitcherDrawable.createTabSwitcherDrawable(getContext(), false);
         mTabSwitcherButtonDrawableLight =
-                TabSwitcherDrawable.createTabSwitcherDrawable(getResources(), true);
+                TabSwitcherDrawable.createTabSwitcherDrawable(getContext(), true);
 
         mAccessibilitySwitcherButton = (ImageButton) findViewById(R.id.tab_switcher_button);
         mAccessibilitySwitcherButton.setImageDrawable(mTabSwitcherButtonDrawable);
@@ -476,10 +477,9 @@
         if (isBookmarked) {
             mBookmarkButton.setImageResource(R.drawable.btn_star_filled);
             // Non-incognito mode shows a blue filled star.
-            mBookmarkButton.setTint(isIncognito()
-                    ? mLightModeTint
-                    : ApiCompatibilityUtils.getColorStateList(
-                            getResources(), R.color.blue_mode_tint));
+            mBookmarkButton.setTint(isIncognito() ? mLightModeTint
+                                                  : AppCompatResources.getColorStateList(
+                                                            getContext(), R.color.blue_mode_tint));
             mBookmarkButton.setContentDescription(getContext().getString(
                     R.string.edit_bookmark));
         } else {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java
index cdfa4c5..67ab22a 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShellDelegate.java
@@ -150,7 +150,6 @@
     private static VrCoreVersionChecker sVrCoreVersionChecker;
     private static Set<Activity> sVrModeEnabledActivitys = new HashSet<>();
     private static boolean sRegisteredDaydreamHook;
-    private static boolean sAddedBlackOverlayView;
     private static boolean sRegisteredVrAssetsComponent;
     private static Boolean sIconComponentEnabled;
 
@@ -962,22 +961,20 @@
     }
 
     private static void addBlackOverlayViewForActivity(ChromeActivity activity) {
-        if (sAddedBlackOverlayView) return;
+        View overlay = activity.getWindow().findViewById(R.id.vr_overlay_view);
+        if (overlay != null) return;
         FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
                 WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT);
         View v = new View(activity);
         v.setId(R.id.vr_overlay_view);
         v.setBackgroundColor(Color.BLACK);
         activity.getWindow().addContentView(v, params);
-        sAddedBlackOverlayView = true;
     }
 
     private static void removeBlackOverlayView(ChromeActivity activity) {
-        if (!sAddedBlackOverlayView) return;
-        View v = activity.getWindow().findViewById(R.id.vr_overlay_view);
-        assert v != null;
-        UiUtils.removeViewFromParent(v);
-        sAddedBlackOverlayView = false;
+        View overlay = activity.getWindow().findViewById(R.id.vr_overlay_view);
+        if (overlay == null) return;
+        UiUtils.removeViewFromParent(overlay);
     }
 
     private static boolean isVrCoreCompatible(final Tab tabToShowInfobarIn) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java
index 347c9bd..23d631f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java
@@ -802,7 +802,7 @@
     private void updateToolbarCloseButtonVisibility() {
         if (WebappBrowserControlsDelegate.shouldShowToolbarCloseButton(this)) {
             getToolbarManager().setCloseButtonDrawable(
-                    TintedDrawable.constructTintedDrawable(getResources(), R.drawable.btn_close));
+                    TintedDrawable.constructTintedDrawable(this, R.drawable.btn_close));
             // Applies light or dark tint to icons depending on the theme color.
             getToolbarManager().getToolbarLayout().getLocationBar().updateVisualsForState();
         } else {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/BoundedLinearLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/BoundedLinearLayout.java
index 50b5d42..8519f51bd 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/widget/BoundedLinearLayout.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/BoundedLinearLayout.java
@@ -19,11 +19,11 @@
  * Example:
  *   <org.chromium.chrome.browser.widget.BoundedLinearLayout
  *       xmlns:android="http://schemas.android.com/apk/res/android"
- *       xmlns:chrome="http://schemas.android.com/apk/res-auto"
+ *       xmlns:app="http://schemas.android.com/apk/res-auto"
  *       android:layout_width="match_parent"
  *       android:layout_height="match_parent"
- *       chrome:maxWidthLandscape="@dimen/modal_dialog_landscape_max_width"
-         chrome:maxWidthPortrait="@dimen/modal_dialog_portrait_max_width">
+ *       app:maxWidthLandscape="@dimen/modal_dialog_landscape_max_width"
+         app:maxWidthPortrait="@dimen/modal_dialog_portrait_max_width">
  *     ...
  */
 public class BoundedLinearLayout extends LinearLayout {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/ImageViewTinter.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/ImageViewTinter.java
index 1a2d5ec..1cc8454 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/widget/ImageViewTinter.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/ImageViewTinter.java
@@ -20,11 +20,11 @@
  * Example usage in XML:
  * <ImageViewTinterInstanceOwner
  *     xmlns:android="http://schemas.android.com/apk/res/android"
- *     xmlns:chrome="http://schemas.android.com/apk/res-auto"
- *     chrome:chrometint="@color/light_active_color" />
+ *     xmlns:app="http://schemas.android.com/apk/res-auto"
+ *     app:chrometint="@color/light_active_color" />
  *
  * The default style used by the Application will likely cause your Drawable to be automatically
- * tinted.  To prevent this, set the value of chrome:chrometint to "@null".
+ * tinted.  To prevent this, set the value of app:chrometint to "@null".
  */
 public class ImageViewTinter {
     /** Classes that own an ImageViewTinter must implement these functions. */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/MaterialProgressBar.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/MaterialProgressBar.java
index 070ff740..5b7b56d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/widget/MaterialProgressBar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/MaterialProgressBar.java
@@ -35,14 +35,14 @@
  * -------------------------------------------------------------------------------------------------
  * DEFINING THE CONTROL STYLING IN AN XML LAYOUT
  *
- * Add the "chrome" namespace as an attribute to the main tag of the layout file:
- * xmlns:chrome="http://schemas.android.com/apk/res-auto
+ * Add the "app" namespace as an attribute to the main tag of the layout file:
+ * xmlns:app="http://schemas.android.com/apk/res-auto
  *
  * These attributes control styling of the bar:
- * chrome:colorBackground         Background color of the progress bar.
- * chrome:colorProgress           Represents progress along the determinate progress bar.
- *                                Also used as the pulsing color.
- * chrome:colorSecondaryProgress  Represents secondary progress on top of the regular progress.
+ * app:colorBackground         Background color of the progress bar.
+ * app:colorProgress           Represents progress along the determinate progress bar.
+ *                             Also used as the pulsing color.
+ * app:colorSecondaryProgress  Represents secondary progress on top of the regular progress.
  */
 public class MaterialProgressBar extends View implements AnimatorUpdateListener {
     private static final long INDETERMINATE_ANIMATION_DURATION_MS = 3000;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/TintedDrawable.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/TintedDrawable.java
index 6d28cbd..e116dbe9a 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/widget/TintedDrawable.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/TintedDrawable.java
@@ -4,14 +4,14 @@
 
 package org.chromium.chrome.browser.widget;
 
+import android.content.Context;
 import android.content.res.ColorStateList;
-import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.graphics.PorterDuff;
 import android.graphics.drawable.BitmapDrawable;
+import android.support.v7.content.res.AppCompatResources;
 
-import org.chromium.base.ApiCompatibilityUtils;
 import org.chromium.chrome.R;
 
 /**
@@ -24,9 +24,9 @@
      */
     protected ColorStateList mTint;
 
-    public TintedDrawable(Resources res, Bitmap bitmap) {
-        super(res, bitmap);
-        mTint = ApiCompatibilityUtils.getColorStateList(res, R.color.dark_mode_tint);
+    public TintedDrawable(Context context, Bitmap bitmap) {
+        super(context.getResources(), bitmap);
+        mTint = AppCompatResources.getColorStateList(context, R.color.dark_mode_tint);
     }
 
     @Override
@@ -54,18 +54,18 @@
     /**
      * Factory method for creating a {@link TintedDrawable} with a resource id.
      */
-    public static TintedDrawable constructTintedDrawable(Resources res, int drawableId) {
-        Bitmap icon = BitmapFactory.decodeResource(res, drawableId);
-        return new TintedDrawable(res, icon);
+    public static TintedDrawable constructTintedDrawable(Context context, int drawableId) {
+        Bitmap icon = BitmapFactory.decodeResource(context.getResources(), drawableId);
+        return new TintedDrawable(context, icon);
     }
 
     /**
      * Factory method for creating a {@link TintedDrawable} with a resource id and specific tint.
      */
     public static TintedDrawable constructTintedDrawable(
-            Resources res, int drawableId, int tintColorId) {
-        TintedDrawable drawable = constructTintedDrawable(res,  drawableId);
-        drawable.setTint(ApiCompatibilityUtils.getColorStateList(res, tintColorId));
+            Context context, int drawableId, int tintColorId) {
+        TintedDrawable drawable = constructTintedDrawable(context, drawableId);
+        drawable.setTint(AppCompatResources.getColorStateList(context, tintColorId));
         return drawable;
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/accessibility/AccessibilityTabModelListItem.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/accessibility/AccessibilityTabModelListItem.java
index e288844..993569d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/widget/accessibility/AccessibilityTabModelListItem.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/accessibility/AccessibilityTabModelListItem.java
@@ -13,6 +13,7 @@
 import android.content.res.ColorStateList;
 import android.graphics.Bitmap;
 import android.os.Handler;
+import android.support.v7.content.res.AppCompatResources;
 import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.view.GestureDetector;
@@ -215,14 +216,11 @@
 
         mDefaultHeight =
                 context.getResources().getDimensionPixelOffset(R.dimen.accessibility_tab_height);
-        mDarkIconColor =
-                ApiCompatibilityUtils.getColorStateList(getResources(), R.color.dark_mode_tint);
-        mLightIconColor =
-                ApiCompatibilityUtils.getColorStateList(getResources(), R.color.white_mode_tint);
-        mDarkCloseIconColor =
-                ApiCompatibilityUtils.getColorStateList(getResources(), R.color.black_alpha_38);
+        mDarkIconColor = AppCompatResources.getColorStateList(context, R.color.dark_mode_tint);
+        mLightIconColor = AppCompatResources.getColorStateList(context, R.color.white_mode_tint);
+        mDarkCloseIconColor = AppCompatResources.getColorStateList(context, R.color.black_alpha_38);
         mLightCloseIconColor =
-                ApiCompatibilityUtils.getColorStateList(getResources(), R.color.white_alpha_70);
+                AppCompatResources.getColorStateList(context, R.color.white_alpha_70);
         mDefaultLevel = getResources().getInteger(R.integer.list_item_level_default);
         mIncognitoLevel = getResources().getInteger(R.integer.list_item_level_incognito);
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/accessibility/AccessibilityTabModelWrapper.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/accessibility/AccessibilityTabModelWrapper.java
index 1c106a22..2c06318d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/widget/accessibility/AccessibilityTabModelWrapper.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/accessibility/AccessibilityTabModelWrapper.java
@@ -7,6 +7,7 @@
 import android.content.Context;
 import android.content.res.ColorStateList;
 import android.support.design.widget.TabLayout;
+import android.support.v7.content.res.AppCompatResources;
 import android.util.AttributeSet;
 import android.view.View;
 import android.widget.ImageButton;
@@ -100,13 +101,13 @@
     public void setup(AccessibilityTabModelAdapterListener listener) {
         if (FeatureUtilities.isChromeModernDesignEnabled()) {
             mTabIconDarkColor =
-                    ApiCompatibilityUtils.getColorStateList(getResources(), R.color.dark_mode_tint);
-            mTabIconSelectedDarkColor = ApiCompatibilityUtils.getColorStateList(
-                    getResources(), R.color.light_active_color);
+                    AppCompatResources.getColorStateList(getContext(), R.color.dark_mode_tint);
+            mTabIconSelectedDarkColor =
+                    AppCompatResources.getColorStateList(getContext(), R.color.light_active_color);
             mTabIconLightColor =
-                    ApiCompatibilityUtils.getColorStateList(getResources(), R.color.white_alpha_70);
-            mTabIconSelectedLightColor = ApiCompatibilityUtils.getColorStateList(
-                    getResources(), R.color.white_mode_tint);
+                    AppCompatResources.getColorStateList(getContext(), R.color.white_alpha_70);
+            mTabIconSelectedLightColor =
+                    AppCompatResources.getColorStateList(getContext(), R.color.white_mode_tint);
             // Setting scaleY here to make sure the icons are not flipped due to the scaleY of its
             // container layout.
             mModernStandardButtonIcon = new TintedImageView(getContext());
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/findinpage/FindToolbarPhone.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/findinpage/FindToolbarPhone.java
index aae883c..66ac556 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/widget/findinpage/FindToolbarPhone.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/findinpage/FindToolbarPhone.java
@@ -7,6 +7,7 @@
 import android.content.Context;
 import android.content.res.ColorStateList;
 import android.graphics.Color;
+import android.support.v7.content.res.AppCompatResources;
 import android.util.AttributeSet;
 import android.view.View;
 
@@ -47,16 +48,16 @@
         if (isIncognito) {
             setBackgroundColor(ColorUtils.getDefaultThemeColor(
                     getResources(), FeatureUtilities.isChromeModernDesignEnabled(), true));
-            ColorStateList white = ApiCompatibilityUtils.getColorStateList(getResources(),
-                    R.color.light_mode_tint);
+            ColorStateList white =
+                    AppCompatResources.getColorStateList(getContext(), R.color.light_mode_tint);
             mFindNextButton.setTint(white);
             mFindPrevButton.setTint(white);
             mCloseFindButton.setTint(white);
             queryTextColorId = R.color.find_in_page_query_white_color;
         } else {
             setBackgroundColor(Color.WHITE);
-            ColorStateList dark = ApiCompatibilityUtils.getColorStateList(getResources(),
-                    R.color.dark_mode_tint);
+            ColorStateList dark =
+                    AppCompatResources.getColorStateList(getContext(), R.color.dark_mode_tint);
             mFindNextButton.setTint(dark);
             mFindPrevButton.setTint(dark);
             mCloseFindButton.setTint(dark);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/newtab/NewTabButton.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/newtab/NewTabButton.java
index feff74c4..3fa515f5 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/widget/newtab/NewTabButton.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/newtab/NewTabButton.java
@@ -12,6 +12,7 @@
 import android.graphics.Canvas;
 import android.graphics.drawable.Drawable;
 import android.support.graphics.drawable.VectorDrawableCompat;
+import android.support.v7.content.res.AppCompatResources;
 import android.util.AttributeSet;
 import android.widget.Button;
 
@@ -55,9 +56,8 @@
         mIncognitoDrawable.setCallback(this);
         mIsIncognito = false;
         mLightModeTint =
-                ApiCompatibilityUtils.getColorStateList(getResources(), R.color.light_mode_tint);
-        mDarkModeTint =
-                ApiCompatibilityUtils.getColorStateList(getResources(), R.color.dark_mode_tint);
+                AppCompatResources.getColorStateList(getContext(), R.color.light_mode_tint);
+        mDarkModeTint = AppCompatResources.getColorStateList(getContext(), R.color.dark_mode_tint);
     }
 
     @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/prefeditor/EditorTextField.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/prefeditor/EditorTextField.java
index 348abdb..f38e7c3 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/widget/prefeditor/EditorTextField.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/prefeditor/EditorTextField.java
@@ -95,9 +95,8 @@
 
         if (fieldModel.getActionIconAction() != null) {
             mActionIcon = (ImageView) mIconsLayer.findViewById(R.id.action_icon);
-            mActionIcon.setImageDrawable(
-                    TintedDrawable.constructTintedDrawable(context.getResources(),
-                            fieldModel.getActionIconResourceId(), R.color.light_active_color));
+            mActionIcon.setImageDrawable(TintedDrawable.constructTintedDrawable(
+                    context, fieldModel.getActionIconResourceId(), R.color.light_active_color));
             mActionIcon.setContentDescription(context.getResources().getString(
                     fieldModel.getActionIconDescriptionForAccessibility()));
             mActionIcon.setOnClickListener(this);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/prefeditor/HintedDropDownAdapterWithPlusIcon.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/prefeditor/HintedDropDownAdapterWithPlusIcon.java
index fe8e064..9a8c20c6 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/widget/prefeditor/HintedDropDownAdapterWithPlusIcon.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/prefeditor/HintedDropDownAdapterWithPlusIcon.java
@@ -60,7 +60,6 @@
         // The plus icon is for the last item on the list.
         if (position == getCount() - 1) {
             // Add a "+" icon and a blue tint to the last element.
-            Resources resources = getContext().getResources();
             if (mTextView == null) {
                 mTextView = (TextView) convertView.findViewById(mTextViewResourceId);
             }
@@ -68,8 +67,9 @@
             // Create the "+" icon, put it left of the text and add appropriate padding.
             mTextView.setCompoundDrawablesWithIntrinsicBounds(
                     TintedDrawable.constructTintedDrawable(
-                            resources, R.drawable.plus, R.color.light_active_color),
+                            getContext(), R.drawable.plus, R.color.light_active_color),
                     null, null, null);
+            Resources resources = getContext().getResources();
             mTextView.setCompoundDrawablePadding(
                     resources.getDimensionPixelSize(R.dimen.editor_dialog_section_large_spacing));
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectableItemView.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectableItemView.java
index e19062b..5aa7e927 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectableItemView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectableItemView.java
@@ -10,6 +10,7 @@
 import android.support.annotation.Nullable;
 import android.support.annotation.VisibleForTesting;
 import android.support.graphics.drawable.AnimatedVectorDrawableCompat;
+import android.support.v7.content.res.AppCompatResources;
 import android.util.AttributeSet;
 import android.view.View;
 import android.view.View.OnClickListener;
@@ -18,7 +19,6 @@
 import android.widget.FrameLayout;
 import android.widget.TextView;
 
-import org.chromium.base.ApiCompatibilityUtils;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.util.FeatureUtilities;
 import org.chromium.chrome.browser.widget.TintedDrawable;
@@ -56,7 +56,7 @@
     public SelectableItemView(Context context, AttributeSet attrs) {
         super(context, attrs);
         mIconColorList =
-                ApiCompatibilityUtils.getColorStateList(getResources(), R.color.white_mode_tint);
+                AppCompatResources.getColorStateList(getContext(), R.color.white_mode_tint);
         mDefaultLevel = getResources().getInteger(R.integer.list_item_level_default);
         mSelectedLevel = getResources().getInteger(R.integer.list_item_level_selected);
         mCheckDrawable = AnimatedVectorDrawableCompat.create(
@@ -260,7 +260,7 @@
             TintedImageView imageView, Drawable defaultIcon, boolean isSelected) {
         imageView.setBackgroundResource(R.drawable.list_item_icon_modern_bg);
         imageView.setImageDrawable(isSelected
-                        ? TintedDrawable.constructTintedDrawable(imageView.getResources(),
+                        ? TintedDrawable.constructTintedDrawable(imageView.getContext(),
                                   R.drawable.ic_check_googblue_24dp, R.color.white_mode_tint)
                         : defaultIcon);
         imageView.getBackground().setLevel(isSelected
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectableListToolbar.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectableListToolbar.java
index c830812a..7836525 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectableListToolbar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectableListToolbar.java
@@ -14,6 +14,7 @@
 import android.support.v4.view.GravityCompat;
 import android.support.v4.widget.DrawerLayout;
 import android.support.v7.app.ActionBarDrawerToggle;
+import android.support.v7.content.res.AppCompatResources;
 import android.support.v7.widget.Toolbar;
 import android.text.Editable;
 import android.text.TextUtils;
@@ -200,20 +201,20 @@
                 getResources(), R.color.light_active_color);
 
         mDarkIconColorList =
-                ApiCompatibilityUtils.getColorStateList(getResources(), R.color.dark_mode_tint);
+                AppCompatResources.getColorStateList(getContext(), R.color.dark_mode_tint);
         mLightIconColorList =
-                ApiCompatibilityUtils.getColorStateList(getResources(), R.color.white_mode_tint);
+                AppCompatResources.getColorStateList(getContext(), R.color.white_mode_tint);
 
         if (mTitleResId != 0) setTitle(mTitleResId);
 
         // TODO(twellington): add the concept of normal & selected tint to apply to all toolbar
         //                    buttons.
         mNormalMenuButton = TintedDrawable.constructTintedDrawable(
-                getResources(), R.drawable.ic_more_vert_black_24dp);
+                getContext(), R.drawable.ic_more_vert_black_24dp);
         mSelectionMenuButton = TintedDrawable.constructTintedDrawable(
-                getResources(), R.drawable.ic_more_vert_black_24dp, R.color.white_mode_tint);
+                getContext(), R.drawable.ic_more_vert_black_24dp, R.color.white_mode_tint);
         mNavigationIconDrawable = TintedDrawable.constructTintedDrawable(
-                getResources(), R.drawable.ic_arrow_back_white_24dp);
+                getContext(), R.drawable.ic_arrow_back_white_24dp);
 
         if (!FeatureUtilities.isChromeModernDesignEnabled()) {
             setTitleTextAppearance(getContext(), R.style.BlackHeadline2);
@@ -231,7 +232,7 @@
         MenuItem extraMenuItem = getMenu().findItem(mExtraMenuItemId);
         if (extraMenuItem != null) {
             Drawable iconDrawable = TintedDrawable.constructTintedDrawable(
-                    getResources(), R.drawable.ic_more_vert_black_24dp, R.color.dark_mode_tint);
+                    getContext(), R.drawable.ic_more_vert_black_24dp, R.color.dark_mode_tint);
             extraMenuItem.setIcon(iconDrawable);
         }
     }
@@ -707,7 +708,7 @@
         if (infoMenuItem != null) {
             if (mShowInfoIcon) {
                 Drawable iconDrawable =
-                        TintedDrawable.constructTintedDrawable(getResources(), R.drawable.btn_info,
+                        TintedDrawable.constructTintedDrawable(getContext(), R.drawable.btn_info,
                                 infoShowing ? R.color.blue_mode_tint : R.color.dark_mode_tint);
 
                 infoMenuItem.setIcon(iconDrawable);
diff --git a/chrome/android/java/strings/android_chrome_strings.grd b/chrome/android/java/strings/android_chrome_strings.grd
index 33eba530..d8b7994 100644
--- a/chrome/android/java/strings/android_chrome_strings.grd
+++ b/chrome/android/java/strings/android_chrome_strings.grd
@@ -1153,18 +1153,27 @@
       <message name="IDS_DATA_REDUCTION_BREAKDOWN_SITE_HEADER_CONTENT_DESCRIPTION" desc="This label is used to state that by clicking the associated button, the displayed table will be sorted by website domain name. This is used in the device's screen reader and is not displayed visually to the user.">
         Sort by site
       </message>
+      <message name="IDS_DATA_REDUCTION_BREAKDOWN_HOSTNAME_SORTED" desc="This title states that the following table contains the details of how much data was saved for each site and that the table rows are sorted by the name of the site. This is used in the device's screen reader and is not displayed visually to the user.">
+        Details: Sorted by site name
+      </message>
       <message name="IDS_DATA_REDUCTION_BREAKDOWN_USED_TITLE" desc="Title for the data used column on the Data Reduction statistics page. The breakdown lists the top ten sites with the greatest amount of data usage or mobile data that was saved.">
         Used
       </message>
       <message name="IDS_DATA_REDUCTION_BREAKDOWN_USED_HEADER_CONTENT_DESCRIPTION" desc="This label is used to state that by clicking the associated button, the displayed table will be sorted descending by the amount of mobile data that was used when viewing a webpage. This is used in the device's screen reader and is not displayed visually to the user.">
         Sort by amount of data used
       </message>
+      <message name="IDS_DATA_REDUCTION_BREAKDOWN_DATA_USED_SORTED" desc="This title states that the following table contains the details of how much data was saved for each site and that the table rows are sorted by the how much data was used for each site. This is used in the device's screen reader and is not displayed visually to the user.">
+        Details: Sorted by amount of data used
+      </message>
       <message name="IDS_DATA_REDUCTION_BREAKDOWN_SAVED_TITLE" desc="Title for the data saved column on the Data Reduction statistics page. The breakdown lists for the top ten sites with the greatest amount of data usage or mobile data that was saved. Data Saver allows users to to reduce their mobile data usage by compressing network traffic.">
         Saved
       </message>
       <message name="IDS_DATA_REDUCTION_BREAKDOWN_SAVED_HEADER_CONTENT_DESCRIPTION" desc="This label is used to state that by clicking the associated button, the displayed table will be sorted descending by the amount of mobile data that was saved when viewing a webpage by using Chrome's Data Saver feature. This is used in the device's screen reader and is not displayed visually to the user.">
         Sort by amount of data saved
       </message>
+      <message name="IDS_DATA_REDUCTION_BREAKDOWN_DATA_SAVED_SORTED" desc="This title states that the following table contains the details of how much data was saved for each site and that the table rows are sorted by how much data was saved for each site. This is used in the device's screen reader and is not displayed visually to the user.">
+        Details: Sorted by amount of data saved
+      </message>
       <message name="IDS_DATA_REDUCTION_BREAKDOWN_USED_CONTENT_DESCRIPTION" desc="This label is used as a suffix to describe the amount of mobile data that was used to view a webpage. It is used in the form '0 bytes used'.">
         <ph name="amount">%1$s<ex>0 bytes</ex></ph> used
       </message>
@@ -1908,7 +1917,7 @@
         Open in incognito tab
       </message>
       <message name="IDS_BROWSER_ACTIONS_SAVE_LINK_AS" desc="Browser Actions menu item to download the page of the selected link. [CHAR-LIMIT=30]">
-        Download page
+        Download link
       </message>
       <message name="IDS_BROWSER_ACTIONS_COPY_ADDRESS" desc="Browser Actions menu item to copy the url address of the selected link. [CHAR-LIMIT=30]">
         Copy link
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/browseractions/BrowserActionActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/browseractions/BrowserActionActivityTest.java
index 1a40457..02b2c11 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/browseractions/BrowserActionActivityTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/browseractions/BrowserActionActivityTest.java
@@ -418,7 +418,6 @@
 
         final BrowserActionActivity activity2 = startBrowserActionActivity(mTestPage3, 1);
         mOnBrowserActionsMenuShownCallback.waitForCallback(1);
-        mOnFinishNativeInitializationCallback.waitForCallback(1);
         Assert.assertEquals(2, mActivityTestRule.getActivity().getCurrentTabModel().getCount());
         openTabInBackground(activity2);
         // Notification title should be shown for multiple tabs.
@@ -431,13 +430,22 @@
         });
 
         // Tabs should always be added at the end of the model.
-        Assert.assertEquals(3, mActivityTestRule.getActivity().getCurrentTabModel().getCount());
+        int tabCount = mActivityTestRule.getActivity().getCurrentTabModel().getCount();
         Assert.assertEquals(mTestPage,
-                mActivityTestRule.getActivity().getCurrentTabModel().getTabAt(0).getUrl());
+                mActivityTestRule.getActivity()
+                        .getCurrentTabModel()
+                        .getTabAt(tabCount - 3)
+                        .getUrl());
         Assert.assertEquals(mTestPage2,
-                mActivityTestRule.getActivity().getCurrentTabModel().getTabAt(1).getUrl());
+                mActivityTestRule.getActivity()
+                        .getCurrentTabModel()
+                        .getTabAt(tabCount - 2)
+                        .getUrl());
         Assert.assertEquals(mTestPage3,
-                mActivityTestRule.getActivity().getCurrentTabModel().getTabAt(2).getUrl());
+                mActivityTestRule.getActivity()
+                        .getCurrentTabModel()
+                        .getTabAt(tabCount - 1)
+                        .getUrl());
         Intent notificationIntent = BrowserActionsService.getNotificationIntent();
         notificationIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java
index 2ee504a..c9e1e62 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java
@@ -2327,6 +2327,17 @@
         ApplicationStatus.unregisterActivityStateListener(listener);
     }
 
+    @Test
+    @MediumTest
+    public void testLaunchIncognitoCustomTabForPaymentRequest() throws Exception {
+        Intent intent = createMinimalCustomTabIntent();
+        intent.putExtra(IntentHandler.EXTRA_OPEN_NEW_INCOGNITO_TAB, true);
+        CustomTabIntentDataProvider.addPaymentRequestUIExtras(intent);
+        mCustomTabActivityTestRule.startCustomTabActivityWithIntent(intent);
+
+        Assert.assertTrue(mCustomTabActivityTestRule.getActivity().getActivityTab().isIncognito());
+    }
+
     /**
      * Tests that a Weblite URL from an external app uses the lite_url param when Data Reduction
      * Proxy previews are being used.
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/widget/ImageViewTinterTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/widget/ImageViewTinterTest.java
index 1b184cb..361e627 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/widget/ImageViewTinterTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/widget/ImageViewTinterTest.java
@@ -12,6 +12,7 @@
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.SmallTest;
 import android.support.test.rule.UiThreadTestRule;
+import android.support.v7.content.res.AppCompatResources;
 import android.view.LayoutInflater;
 import android.view.View.MeasureSpec;
 import android.view.ViewGroup;
@@ -126,8 +127,8 @@
         Assert.assertFalse(checkIfTintWasApplied(view, color));
 
         // Set the tint to one color.
-        ColorStateList colorList = ApiCompatibilityUtils.getColorStateList(
-                mContext.getResources(), R.color.light_active_color);
+        ColorStateList colorList =
+                AppCompatResources.getColorStateList(mContext, R.color.light_active_color);
         view.setTint(colorList);
         Assert.assertNotNull(imageView.getColorFilter());
         Assert.assertTrue(checkIfTintWasApplied(view, color));
@@ -140,8 +141,8 @@
         // Set it to another color.
         int otherColor =
                 ApiCompatibilityUtils.getColor(mContext.getResources(), R.color.google_red_700);
-        ColorStateList otherColorList = ApiCompatibilityUtils.getColorStateList(
-                mContext.getResources(), R.color.google_red_700);
+        ColorStateList otherColorList =
+                AppCompatResources.getColorStateList(mContext, R.color.google_red_700);
         view.setTint(otherColorList);
         Assert.assertNotNull(imageView.getColorFilter());
         Assert.assertTrue(checkIfTintWasApplied(view, otherColor));
diff --git a/chrome/android/profiles/newest.txt b/chrome/android/profiles/newest.txt
index 5a8d0f04..75d5389 100644
--- a/chrome/android/profiles/newest.txt
+++ b/chrome/android/profiles/newest.txt
@@ -1 +1 @@
-chromeos-chrome-amd64-69.0.3451.0_rc-r1.afdo.bz2
\ No newline at end of file
+chromeos-chrome-amd64-69.0.3453.0_rc-r1.afdo.bz2
\ No newline at end of file
diff --git a/chrome/app/entitlements.plist b/chrome/app/entitlements.plist
deleted file mode 100644
index a64a5ec0..0000000
--- a/chrome/app/entitlements.plist
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-	<key>com.apple.application-identifier</key>
-	<string>${CHROMIUM_TEAM_ID}.${CHROMIUM_BUNDLE_ID}</string>
-	<key>keychain-access-groups</key>
-	<array>
-		<string>${CHROMIUM_TEAM_ID}.${CHROMIUM_BUNDLE_ID}.webauthn</string>
-	</array>
-</dict>
-</plist>
diff --git a/chrome/app/theme/chromium/BRANDING b/chrome/app/theme/chromium/BRANDING
index 4167796..4f9ef78 100644
--- a/chrome/app/theme/chromium/BRANDING
+++ b/chrome/app/theme/chromium/BRANDING
@@ -7,4 +7,3 @@
 COPYRIGHT=Copyright 2017 The Chromium Authors. All rights reserved.
 MAC_BUNDLE_ID=org.chromium.Chromium
 MAC_CREATOR_CODE=Cr24
-MAC_TEAM_ID=
diff --git a/chrome/app/theme/default_100_percent/cros/smb_icon.png b/chrome/app/theme/default_100_percent/cros/smb_icon.png
new file mode 100644
index 0000000..46f7131
--- /dev/null
+++ b/chrome/app/theme/default_100_percent/cros/smb_icon.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/cros/smb_icon.png b/chrome/app/theme/default_200_percent/cros/smb_icon.png
new file mode 100644
index 0000000..5701e0a
--- /dev/null
+++ b/chrome/app/theme/default_200_percent/cros/smb_icon.png
Binary files differ
diff --git a/chrome/app/theme/theme_resources.grd b/chrome/app/theme/theme_resources.grd
index bfdeff1b..61ad6a1 100644
--- a/chrome/app/theme/theme_resources.grd
+++ b/chrome/app/theme/theme_resources.grd
@@ -387,6 +387,7 @@
       </if>
       <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" />
         <structure type="chrome_scaled_image" name="IDR_SUPERVISED_ILLUSTRATION_START" file="cros/supervised_illustration_start.png" />
         <structure type="chrome_scaled_image" name="IDR_SUPERVISED_ILLUSTRATION_DONE" file="cros/supervised_illsutration_done.png" />
         <structure type="chrome_scaled_image" name="IDR_LOGO_AVATAR_CIRCLE_BLUE_COLOR" file="cros/logo_avatar_circle_blue_color.png" />
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 532e120..e589b10 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -2178,8 +2178,8 @@
       "android/profiles/profile_manager_utils.cc",
       "android/provider/blocking_ui_thread_async_request.cc",
       "android/provider/blocking_ui_thread_async_request.h",
-      "android/provider/bookmark_model_observer_task.cc",
-      "android/provider/bookmark_model_observer_task.h",
+      "android/provider/bookmark_model_task.cc",
+      "android/provider/bookmark_model_task.h",
       "android/provider/chrome_browser_provider.cc",
       "android/provider/chrome_browser_provider.h",
       "android/provider/run_on_ui_thread_blocking.h",
diff --git a/chrome/browser/android/provider/bookmark_model_observer_task.cc b/chrome/browser/android/provider/bookmark_model_observer_task.cc
deleted file mode 100644
index 9ba697b..0000000
--- a/chrome/browser/android/provider/bookmark_model_observer_task.cc
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/android/provider/bookmark_model_observer_task.h"
-
-#include "components/bookmarks/browser/bookmark_model.h"
-#include "components/bookmarks/browser/model_loader.h"
-#include "content/public/browser/browser_thread.h"
-
-using bookmarks::BookmarkModel;
-using bookmarks::BookmarkNode;
-using content::BrowserThread;
-
-BookmarkModelTask::BookmarkModelTask(BookmarkModel* model)
-    : model_(model) {
-  // Ensure the initialization of the native bookmark model.
-  DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));
-  DCHECK(model_);
-  model_->model_loader()->BlockTillLoaded();
-}
-
-BookmarkModel* BookmarkModelTask::model() const {
-  return model_;
-}
-
-BookmarkModelObserverTask::BookmarkModelObserverTask(
-    BookmarkModel* bookmark_model)
-    : BookmarkModelTask(bookmark_model) {
-  model()->AddObserver(this);
-}
-
-BookmarkModelObserverTask::~BookmarkModelObserverTask() {
-  model()->RemoveObserver(this);
-}
-
-void BookmarkModelObserverTask::BookmarkModelLoaded(BookmarkModel* model,
-                                                    bool ids_reassigned) {}
-
-void BookmarkModelObserverTask::BookmarkNodeMoved(
-    BookmarkModel* model,
-    const BookmarkNode* old_parent,
-    int old_index,
-    const BookmarkNode* new_parent,
-    int new_index) {
-}
-
-void BookmarkModelObserverTask::BookmarkNodeAdded(BookmarkModel* model,
-                                                  const BookmarkNode* parent,
-                                                  int index) {
-}
-
-void BookmarkModelObserverTask::BookmarkNodeRemoved(
-    BookmarkModel* model,
-    const BookmarkNode* parent,
-    int old_index,
-    const BookmarkNode* node,
-    const std::set<GURL>& removed_urls) {
-}
-
-void BookmarkModelObserverTask::BookmarkAllUserNodesRemoved(
-    BookmarkModel* model,
-    const std::set<GURL>& removed_urls) {
-}
-
-void BookmarkModelObserverTask::BookmarkNodeChanged(BookmarkModel* model,
-                                                    const BookmarkNode* node) {
-}
-
-void BookmarkModelObserverTask::BookmarkNodeFaviconChanged(
-    BookmarkModel* model,
-    const BookmarkNode* node) {
-}
-
-void BookmarkModelObserverTask::BookmarkNodeChildrenReordered(
-    BookmarkModel* model,
-    const BookmarkNode* node) {
-}
diff --git a/chrome/browser/android/provider/bookmark_model_observer_task.h b/chrome/browser/android/provider/bookmark_model_observer_task.h
deleted file mode 100644
index e557c2e..0000000
--- a/chrome/browser/android/provider/bookmark_model_observer_task.h
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_ANDROID_PROVIDER_BOOKMARK_MODEL_OBSERVER_TASK_H_
-#define CHROME_BROWSER_ANDROID_PROVIDER_BOOKMARK_MODEL_OBSERVER_TASK_H_
-
-#include "base/compiler_specific.h"
-#include "base/macros.h"
-#include "components/bookmarks/browser/bookmark_model_observer.h"
-
-// Base class for synchronous tasks that involve the bookmark model.
-// Ensures the model has been loaded before accessing it.
-// Must not be created from the UI thread.
-class BookmarkModelTask {
- public:
-  explicit BookmarkModelTask(bookmarks::BookmarkModel* model);
-  bookmarks::BookmarkModel* model() const;
-
- private:
-  bookmarks::BookmarkModel* model_;
-
-  DISALLOW_COPY_AND_ASSIGN(BookmarkModelTask);
-};
-
-// Base class for bookmark model tasks that observe for model updates.
-class BookmarkModelObserverTask : public BookmarkModelTask,
-                                  public bookmarks::BookmarkModelObserver {
- public:
-  explicit BookmarkModelObserverTask(bookmarks::BookmarkModel* bookmark_model);
-  ~BookmarkModelObserverTask() override;
-
-  // bookmarks::BookmarkModelObserver:
-  void BookmarkModelLoaded(bookmarks::BookmarkModel* model,
-                           bool ids_reassigned) override;
-  void BookmarkNodeMoved(bookmarks::BookmarkModel* model,
-                         const bookmarks::BookmarkNode* old_parent,
-                         int old_index,
-                         const bookmarks::BookmarkNode* new_parent,
-                         int new_index) override;
-  void BookmarkNodeAdded(bookmarks::BookmarkModel* model,
-                         const bookmarks::BookmarkNode* parent,
-                         int index) override;
-  void BookmarkNodeRemoved(bookmarks::BookmarkModel* model,
-                           const bookmarks::BookmarkNode* parent,
-                           int old_index,
-                           const bookmarks::BookmarkNode* node,
-                           const std::set<GURL>& removed_urls) override;
-  void BookmarkAllUserNodesRemoved(bookmarks::BookmarkModel* model,
-                                   const std::set<GURL>& removed_urls) override;
-  void BookmarkNodeChanged(bookmarks::BookmarkModel* model,
-                           const bookmarks::BookmarkNode* node) override;
-  void BookmarkNodeFaviconChanged(bookmarks::BookmarkModel* model,
-                                  const bookmarks::BookmarkNode* node) override;
-  void BookmarkNodeChildrenReordered(
-      bookmarks::BookmarkModel* model,
-      const bookmarks::BookmarkNode* node) override;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(BookmarkModelObserverTask);
-};
-
-#endif  // CHROME_BROWSER_ANDROID_PROVIDER_BOOKMARK_MODEL_OBSERVER_TASK_H_
diff --git a/chrome/browser/android/provider/bookmark_model_task.cc b/chrome/browser/android/provider/bookmark_model_task.cc
new file mode 100644
index 0000000..2bb9a069
--- /dev/null
+++ b/chrome/browser/android/provider/bookmark_model_task.cc
@@ -0,0 +1,23 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/android/provider/bookmark_model_task.h"
+#include "components/bookmarks/browser/bookmark_model.h"
+#include "components/bookmarks/browser/model_loader.h"
+#include "content/public/browser/browser_thread.h"
+
+using bookmarks::BookmarkModel;
+using bookmarks::BookmarkNode;
+using content::BrowserThread;
+
+BookmarkModelTask::BookmarkModelTask(BookmarkModel* model) : model_(model) {
+  // Ensure the initialization of the native bookmark model.
+  DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK(model_);
+  model_->model_loader()->BlockTillLoaded();
+}
+
+BookmarkModel* BookmarkModelTask::model() const {
+  return model_;
+}
diff --git a/chrome/browser/android/provider/bookmark_model_task.h b/chrome/browser/android/provider/bookmark_model_task.h
new file mode 100644
index 0000000..a8c363d7
--- /dev/null
+++ b/chrome/browser/android/provider/bookmark_model_task.h
@@ -0,0 +1,26 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_ANDROID_PROVIDER_BOOKMARK_MODEL_TASK_H_
+#define CHROME_BROWSER_ANDROID_PROVIDER_BOOKMARK_MODEL_TASK_H_
+
+#include "base/compiler_specific.h"
+#include "base/macros.h"
+#include "components/bookmarks/browser/bookmark_model_observer.h"
+
+// Base class for synchronous tasks that involve the bookmark model.
+// Ensures the model has been loaded before accessing it.
+// Must not be created from the UI thread.
+class BookmarkModelTask {
+ public:
+  explicit BookmarkModelTask(bookmarks::BookmarkModel* model);
+  bookmarks::BookmarkModel* model() const;
+
+ private:
+  bookmarks::BookmarkModel* model_;
+
+  DISALLOW_COPY_AND_ASSIGN(BookmarkModelTask);
+};
+
+#endif  // CHROME_BROWSER_ANDROID_PROVIDER_BOOKMARK_MODEL_TASK_H_
diff --git a/chrome/browser/android/provider/chrome_browser_provider.cc b/chrome/browser/android/provider/chrome_browser_provider.cc
index d6935f1..975d727f 100644
--- a/chrome/browser/android/provider/chrome_browser_provider.cc
+++ b/chrome/browser/android/provider/chrome_browser_provider.cc
@@ -20,7 +20,7 @@
 #include "base/task/cancelable_task_tracker.h"
 #include "base/time/time.h"
 #include "chrome/browser/android/provider/blocking_ui_thread_async_request.h"
-#include "chrome/browser/android/provider/bookmark_model_observer_task.h"
+#include "chrome/browser/android/provider/bookmark_model_task.h"
 #include "chrome/browser/android/provider/run_on_ui_thread_blocking.h"
 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
 #include "chrome/browser/bookmarks/managed_bookmark_service_factory.h"
@@ -216,80 +216,69 @@
 };
 
 // Utility method to remove a bookmark.
-class RemoveBookmarkTask : public BookmarkModelObserverTask {
+class RemoveBookmarkTask : public BookmarkModelTask {
  public:
   explicit RemoveBookmarkTask(BookmarkModel* model)
-      : BookmarkModelObserverTask(model),
-        deleted_(0),
-        id_to_delete_(kInvalidBookmarkId) {}
-  ~RemoveBookmarkTask() override {}
+      : BookmarkModelTask(model) {}
 
   int Run(const int64_t id) {
-    id_to_delete_ = id;
-    RunOnUIThreadBlocking::Run(
-        base::Bind(&RemoveBookmarkTask::RunOnUIThread, model(), id));
-    return deleted_;
+    bool did_delete = false;
+    RunOnUIThreadBlocking::Run(base::Bind(&RemoveBookmarkTask::RunOnUIThread,
+                                          model(), id, &did_delete));
+    return did_delete ? 1 : 0;
   }
 
-  static void RunOnUIThread(BookmarkModel* model, const int64_t id) {
+  static void RunOnUIThread(BookmarkModel* model,
+                            const int64_t id,
+                            bool* did_delete) {
     DCHECK_CURRENTLY_ON(BrowserThread::UI);
     const BookmarkNode* node = bookmarks::GetBookmarkNodeByID(model, id);
-    if (node && node->parent())
+    if (node && node->parent()) {
       model->Remove(node);
+      *did_delete = true;
+    }
   }
 
-  // Verify that the bookmark was actually removed. Called synchronously.
-  void BookmarkNodeRemoved(BookmarkModel* bookmark_model,
-                           const BookmarkNode* parent,
-                           int old_index,
-                           const BookmarkNode* node,
-                           const std::set<GURL>& removed_urls) override {
-    if (bookmark_model == model() && node->id() == id_to_delete_)
-        ++deleted_;
-  }
-
- private:
-  int deleted_;
-  int64_t id_to_delete_;
-
   DISALLOW_COPY_AND_ASSIGN(RemoveBookmarkTask);
 };
 
 // Utility method to update a bookmark.
-class UpdateBookmarkTask : public BookmarkModelObserverTask {
+class UpdateBookmarkTask : public BookmarkModelTask {
  public:
   explicit UpdateBookmarkTask(BookmarkModel* model)
-      : BookmarkModelObserverTask(model),
-        updated_(0),
-        id_to_update_(kInvalidBookmarkId){}
-  ~UpdateBookmarkTask() override {}
+      : BookmarkModelTask(model) {}
 
   int Run(const int64_t id,
           const base::string16& title,
           const base::string16& url,
           const int64_t parent_id) {
-    id_to_update_ = id;
-    RunOnUIThreadBlocking::Run(
-        base::Bind(&UpdateBookmarkTask::RunOnUIThread,
-                   model(), id, title, url, parent_id));
-    return updated_;
+    bool did_update = false;
+    RunOnUIThreadBlocking::Run(base::Bind(&UpdateBookmarkTask::RunOnUIThread,
+                                          model(), id, title, url, parent_id,
+                                          &did_update));
+    return did_update ? 1 : 0;
   }
 
   static void RunOnUIThread(BookmarkModel* model,
                             const int64_t id,
                             const base::string16& title,
                             const base::string16& url,
-                            const int64_t parent_id) {
+                            const int64_t parent_id,
+                            bool* did_update) {
     DCHECK_CURRENTLY_ON(BrowserThread::UI);
     const BookmarkNode* node = bookmarks::GetBookmarkNodeByID(model, id);
     if (node) {
-      if (node->GetTitle() != title)
+      if (node->GetTitle() != title) {
         model->SetTitle(node, title);
+        *did_update = true;
+      }
 
       if (node->type() == BookmarkNode::URL) {
         GURL bookmark_url = ParseAndMaybeAppendScheme(url, kDefaultUrlScheme);
-        if (bookmark_url != node->url())
+        if (bookmark_url != node->url()) {
           model->SetURL(node, bookmark_url);
+          *did_update = true;
+        }
       }
 
       if (parent_id >= 0 &&
@@ -297,23 +286,14 @@
         const BookmarkNode* new_parent =
             bookmarks::GetBookmarkNodeByID(model, parent_id);
 
-        if (new_parent)
+        if (new_parent) {
           model->Move(node, new_parent, 0);
+          *did_update = true;
+        }
       }
     }
   }
 
-  // Verify that the bookmark was actually updated. Called synchronously.
-  void BookmarkNodeChanged(BookmarkModel* bookmark_model,
-                           const BookmarkNode* node) override {
-    if (bookmark_model == model() && node->id() == id_to_update_)
-      ++updated_;
-  }
-
- private:
-  int updated_;
-  int64_t id_to_update_;
-
   DISALLOW_COPY_AND_ASSIGN(UpdateBookmarkTask);
 };
 
diff --git a/chrome/browser/android/vr/arcore_device/arcore_impl.cc b/chrome/browser/android/vr/arcore_device/arcore_impl.cc
index 9c55c34..23edfdc 100644
--- a/chrome/browser/android/vr/arcore_device/arcore_impl.cc
+++ b/chrome/browser/android/vr/arcore_device/arcore_impl.cc
@@ -318,7 +318,11 @@
   }
 
   screen_point->set_x((screen_point_3d.x() + 1) / 2);
-  screen_point->set_y((screen_point_3d.y() + 1) / 2);
+  // The calculated point in GL's normalized device coordinates (NDC) ranges
+  // from -1..1, with -1, -1 at the bottom left of the screen, +1 at the top.
+  // The output screen space coordinates range from 0..1, with 0, 0 at the
+  // top left.
+  screen_point->set_y((-screen_point_3d.y() + 1) / 2);
   return true;
 }
 
diff --git a/chrome/browser/chromeos/login/active_directory_login_browsertest.cc b/chrome/browser/chromeos/login/active_directory_login_browsertest.cc
index 40ff698..b2e5ffd 100644
--- a/chrome/browser/chromeos/login/active_directory_login_browsertest.cc
+++ b/chrome/browser/chromeos/login/active_directory_login_browsertest.cc
@@ -71,7 +71,7 @@
 
 class TestAuthPolicyClient : public FakeAuthPolicyClient {
  public:
-  TestAuthPolicyClient() { FakeAuthPolicyClient::set_started(true); }
+  TestAuthPolicyClient() { FakeAuthPolicyClient::SetStarted(true); }
 
   void AuthenticateUser(const authpolicy::AuthenticateUserRequest& request,
                         int password_fd,
diff --git a/chrome/browser/chromeos/policy/active_directory_policy_manager_unittest.cc b/chrome/browser/chromeos/policy/active_directory_policy_manager_unittest.cc
index f75f918..cdf28de5 100644
--- a/chrome/browser/chromeos/policy/active_directory_policy_manager_unittest.cc
+++ b/chrome/browser/chromeos/policy/active_directory_policy_manager_unittest.cc
@@ -69,6 +69,12 @@
     NOTIMPLEMENTED();
   }
 
+  void WaitForServiceToBeAvailable(
+      dbus::ObjectProxy::WaitForServiceToBeAvailableCallback callback)
+      override {
+    NOTIMPLEMENTED();
+  }
+
   void SetRefreshUserPolicyCallbackError(authpolicy::ErrorType error) {
     refresh_user_policy_callback_error_ = error;
   }
diff --git a/chrome/browser/chromeos/smb_client/smb_provider.cc b/chrome/browser/chromeos/smb_client/smb_provider.cc
index 8a7cf8a..0418ec1 100644
--- a/chrome/browser/chromeos/smb_client/smb_provider.cc
+++ b/chrome/browser/chromeos/smb_client/smb_provider.cc
@@ -27,11 +27,10 @@
       // languages. See l10n_util::GetStringUTF8.
       name_("SMB Shares"),
       unmount_callback_(std::move(unmount_callback)) {
-  // TODO(baileyberro): Fill out with proper icons.
   icon_set_.SetIcon(IconSet::IconSize::SIZE_16x16,
-                    GURL("chrome://resources/images/apps/button.png"));
+                    GURL("chrome://theme/IDR_SMB_ICON"));
   icon_set_.SetIcon(IconSet::IconSize::SIZE_32x32,
-                    GURL("chrome://resources/images/2x/apps/button.png"));
+                    GURL("chrome://theme/IDR_SMB_ICON@2x"));
 }
 
 SmbProvider::~SmbProvider() = default;
diff --git a/chrome/browser/data_use_measurement/page_load_capping/page_load_capping_browsertest.cc b/chrome/browser/data_use_measurement/page_load_capping/page_load_capping_browsertest.cc
index f60da13..85752cc 100644
--- a/chrome/browser/data_use_measurement/page_load_capping/page_load_capping_browsertest.cc
+++ b/chrome/browser/data_use_measurement/page_load_capping/page_load_capping_browsertest.cc
@@ -4,17 +4,28 @@
 
 #include <memory>
 
+#include "base/feature_list.h"
+#include "base/metrics/field_trial.h"
+#include "base/metrics/field_trial_param_associator.h"
 #include "base/run_loop.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/test/scoped_feature_list.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "chrome/browser/data_use_measurement/page_load_capping/chrome_page_load_capping_features.h"
+#include "chrome/browser/infobars/infobar_responder.h"
+#include "chrome/browser/infobars/infobar_service.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
+#include "components/infobars/core/confirm_infobar_delegate.h"
+#include "components/infobars/core/infobar.h"
+#include "components/infobars/core/infobar_delegate.h"
 #include "content/public/browser/web_contents_observer.h"
 #include "content/public/common/content_features.h"
 #include "content/public/test/browser_test_utils.h"
+#include "content/public/test/test_navigation_observer.h"
 #include "net/http/http_status_code.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "net/test/embedded_test_server/http_request.h"
@@ -34,10 +45,38 @@
   PageLoadCappingBrowserTest()
       : https_test_server_(std::make_unique<net::EmbeddedTestServer>(
             net::EmbeddedTestServer::TYPE_HTTPS)) {
-    scoped_feature_list_.InitWithFeatures(
-        {network::features::kRendererSideResourceScheduler,
-         features::kResourceLoadScheduler},
-        {});
+    std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
+    {
+      scoped_refptr<base::FieldTrial> trial =
+          base::FieldTrialList::CreateFieldTrial("TrialName1", "GroupName1");
+      std::map<std::string, std::string> feature_parameters = {
+          {"PageCapMiB", "0"}};
+      base::FieldTrialParamAssociator::GetInstance()->AssociateFieldTrialParams(
+          "TrialName1", "GroupName1", feature_parameters);
+
+      feature_list->RegisterFieldTrialOverride(
+          data_use_measurement::page_load_capping::features::
+              kDetectingHeavyPages.name,
+          base::FeatureList::OVERRIDE_ENABLE_FEATURE, trial.get());
+    }
+
+    {
+      scoped_refptr<base::FieldTrial> trial =
+          base::FieldTrialList::CreateFieldTrial("TrialName2", "GroupName2");
+      feature_list->RegisterFieldTrialOverride(
+          network::features::kRendererSideResourceScheduler.name,
+          base::FeatureList::OVERRIDE_ENABLE_FEATURE, trial.get());
+    }
+
+    {
+      scoped_refptr<base::FieldTrial> trial =
+          base::FieldTrialList::CreateFieldTrial("TrialName3", "GroupName3");
+      feature_list->RegisterFieldTrialOverride(
+          features::kResourceLoadScheduler.name,
+          base::FeatureList::OVERRIDE_ENABLE_FEATURE, trial.get());
+    }
+
+    scoped_feature_list_.InitWithFeatureList(std::move(feature_list));
   }
 
   std::unique_ptr<net::test_server::HttpResponse> HandleRequest(
@@ -62,11 +101,20 @@
     return not_found_response;
   }
 
+  void PostToSelf() {
+    EXPECT_FALSE(waiting_);
+    base::RunLoop run_loop;
+    base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+                                                  run_loop.QuitClosure());
+    run_loop.Run();
+  }
+
   void WaitForRequest() {
     EXPECT_FALSE(waiting_);
     waiting_ = true;
     run_loop_ = std::make_unique<base::RunLoop>();
     run_loop_->Run();
+    run_loop_.reset();
   }
 
   size_t images_attempted() const { return images_attempted_; }
@@ -77,7 +125,6 @@
  private:
   size_t images_attempted_ = 0u;
   bool waiting_ = false;
-
   std::unique_ptr<base::RunLoop> run_loop_;
 
   base::test::ScopedFeatureList scoped_feature_list_;
@@ -91,17 +138,14 @@
 
   ASSERT_TRUE(https_test_server_->Start());
 
+  content::WebContents* contents =
+      browser()->tab_strip_model()->GetActiveWebContents();
+  InfoBarResponder infobar_responder(InfoBarService::FromWebContents(contents),
+                                     InfoBarResponder::ACCEPT);
   // Load a mostly empty page.
   ui_test_utils::NavigateToURL(
       browser(), https_test_server_->GetURL("/page_capping.html"));
 
-  content::WebContents* contents =
-      browser()->tab_strip_model()->GetActiveWebContents();
-
-  // Block new subresource loads.
-  std::vector<blink::mojom::PauseSubresourceLoadingHandlePtr> handles =
-      contents->PauseSubresourceLoading();
-
   // Adds images to the page. They should not be allowed to load.
   // Running this 20 times makes 20 round trips to the renderer, making it very
   // likely the earliest request would have made it to the network by the time
@@ -133,17 +177,14 @@
 
   ASSERT_TRUE(https_test_server_->Start());
 
+  content::WebContents* contents =
+      browser()->tab_strip_model()->GetActiveWebContents();
+  InfoBarResponder infobar_responder(InfoBarService::FromWebContents(contents),
+                                     InfoBarResponder::ACCEPT);
   // Load a mostly empty page.
   ui_test_utils::NavigateToURL(
       browser(), https_test_server_->GetURL("/page_capping.html"));
 
-  content::WebContents* contents =
-      browser()->tab_strip_model()->GetActiveWebContents();
-
-  // Block new subresource loads.
-  std::vector<blink::mojom::PauseSubresourceLoadingHandlePtr> handles =
-      contents->PauseSubresourceLoading();
-
   // Adds an image to the page. It should not be allowed to load at first.
   // PageLoadCappingBlocksLoads tests that it is not loaded more robustly
   std::string create_image_script =
@@ -155,7 +196,11 @@
   ASSERT_TRUE(content::ExecuteScript(contents, create_image_script));
 
   // Previous image should be allowed to load now.
-  handles.clear();
+  InfoBarService::FromWebContents(contents)
+      ->infobar_at(0)
+      ->delegate()
+      ->AsConfirmInfoBarDelegate()
+      ->Accept();
 
   // An image should be fetched because subresource loading was paused then
   // resumed.
@@ -173,13 +218,14 @@
       &PageLoadCappingBrowserTest::HandleRequest, base::Unretained(this)));
   ASSERT_TRUE(https_test_server_->Start());
 
+  content::WebContents* contents =
+      browser()->tab_strip_model()->GetActiveWebContents();
+  InfoBarResponder infobar_responder(InfoBarService::FromWebContents(contents),
+                                     InfoBarResponder::DISMISS);
   // Load a mostly empty page.
   ui_test_utils::NavigateToURL(
       browser(), https_test_server_->GetURL("/page_capping.html"));
 
-  content::WebContents* contents =
-      browser()->tab_strip_model()->GetActiveWebContents();
-
   // Adds an image to the page. It should be allowed to load.
   std::string create_image_script =
       std::string(
@@ -195,3 +241,146 @@
   EXPECT_EQ(1u, images_attempted());
   https_test_server_.reset();
 }
+
+IN_PROC_BROWSER_TEST_F(PageLoadCappingBrowserTest,
+                       PageLoadCappingBlockNewFrameLoad) {
+  // Tests that the image request loads normally when the page has not been
+  // paused.
+  https_test_server_->ServeFilesFromSourceDirectory(base::FilePath(kDocRoot));
+  https_test_server_->RegisterRequestHandler(base::BindRepeating(
+      &PageLoadCappingBrowserTest::HandleRequest, base::Unretained(this)));
+  ASSERT_TRUE(https_test_server_->Start());
+
+  content::WebContents* contents =
+      browser()->tab_strip_model()->GetActiveWebContents();
+  InfoBarResponder infobar_responder(InfoBarService::FromWebContents(contents),
+                                     InfoBarResponder::ACCEPT);
+  // Load a mostly empty page.
+  ui_test_utils::NavigateToURL(
+      browser(), https_test_server_->GetURL("/page_capping.html"));
+  content::TestNavigationObserver load_observer(contents);
+
+  // Adds an image to the page. It should be allowed to load.
+  std::string create_iframe_script = std::string(
+      "var iframe = document.createElement('iframe');"
+      "var html = '<body>NewFrame</body>';"
+      "iframe.src = 'data:text/html;charset=utf-8,' + encodeURI(html);"
+      "document.body.appendChild(iframe);");
+  content::ExecuteScriptAsync(contents, create_iframe_script);
+
+  // Make sure the DidFinishNavigation occured.
+  load_observer.Wait();
+  PostToSelf();
+
+  size_t j = 0;
+  for (auto* frame : contents->GetAllFrames()) {
+    for (size_t i = 0; i < 20; ++i) {
+      std::string create_image_script =
+          std::string(
+              "var image = document.createElement('img'); "
+              "document.body.appendChild(image); image.src = '")
+              .append(https_test_server_
+                          ->GetURL(std::string(kImagePrefix)
+                                       .append(base::IntToString(++j))
+                                       .append(".png';"))
+                          .spec());
+
+      EXPECT_TRUE(content::ExecuteScript(frame, create_image_script));
+    }
+  }
+
+  // An image should not be fetched because subresource loading was paused in
+  // both frames.
+  EXPECT_EQ(0u, images_attempted());
+  https_test_server_.reset();
+}
+
+IN_PROC_BROWSER_TEST_F(PageLoadCappingBrowserTest,
+                       PageLoadCappingBlockNewFrameLoadResume) {
+  // Tests that the image request loads normally when the page has not been
+  // paused.
+  https_test_server_->ServeFilesFromSourceDirectory(base::FilePath(kDocRoot));
+  https_test_server_->RegisterRequestHandler(base::BindRepeating(
+      &PageLoadCappingBrowserTest::HandleRequest, base::Unretained(this)));
+  ASSERT_TRUE(https_test_server_->Start());
+
+  content::WebContents* contents =
+      browser()->tab_strip_model()->GetActiveWebContents();
+  InfoBarResponder infobar_responder(InfoBarService::FromWebContents(contents),
+                                     InfoBarResponder::ACCEPT);
+  // Load a mostly empty page.
+  ui_test_utils::NavigateToURL(
+      browser(), https_test_server_->GetURL("/page_capping.html"));
+  content::TestNavigationObserver load_observer(contents);
+
+  // Adds an image to the page. It should be allowed to load.
+  std::string create_iframe_script = std::string(
+      "var iframe = document.createElement('iframe');"
+      "var html = '<body>NewFrame</body>';"
+      "iframe.src = 'data:text/html;charset=utf-8,' + encodeURI(html);"
+      "document.body.appendChild(iframe);");
+  content::ExecuteScriptAsync(contents, create_iframe_script);
+
+  // Make sure the DidFinishNavigation occured.
+  load_observer.Wait();
+  PostToSelf();
+
+  for (auto* frame : contents->GetAllFrames()) {
+    // if (contents->GetMainFrame() == frame)
+    //   continue;
+    std::string create_image_script =
+        std::string(
+            "var image = document.createElement('img'); "
+            "document.body.appendChild(image); image.src = '")
+            .append(https_test_server_
+                        ->GetURL(std::string(kImagePrefix).append(".png';"))
+                        .spec());
+    ASSERT_TRUE(content::ExecuteScript(frame, create_image_script));
+  }
+
+  // An image should not be fetched because subresource loading was paused in
+  // both frames.
+  EXPECT_EQ(0u, images_attempted());
+
+  // Previous image should be allowed to load now.
+  InfoBarService::FromWebContents(contents)
+      ->infobar_at(0)
+      ->delegate()
+      ->AsConfirmInfoBarDelegate()
+      ->Accept();
+
+  // An image should be fetched because subresource loading was resumed.
+  if (images_attempted() < 1u)
+    WaitForRequest();
+  EXPECT_EQ(1u, images_attempted());
+
+  https_test_server_.reset();
+}
+
+IN_PROC_BROWSER_TEST_F(PageLoadCappingBrowserTest,
+                       PageLoadCappingInfobarShownAfterSamePageNavigation) {
+  https_test_server_->RegisterRequestHandler(base::BindRepeating(
+      &PageLoadCappingBrowserTest::HandleRequest, base::Unretained(this)));
+  https_test_server_->ServeFilesFromSourceDirectory(base::FilePath(kDocRoot));
+
+  ASSERT_TRUE(https_test_server_->Start());
+
+  content::WebContents* contents =
+      browser()->tab_strip_model()->GetActiveWebContents();
+  // Load a page.
+  ui_test_utils::NavigateToURL(
+      browser(), https_test_server_->GetURL("/page_capping.html"));
+
+  ASSERT_EQ(1u, InfoBarService::FromWebContents(contents)->infobar_count());
+  infobars::InfoBar* infobar =
+      InfoBarService::FromWebContents(contents)->infobar_at(0);
+
+  // Navigate on the page to an anchor.
+  ui_test_utils::NavigateToURL(
+      browser(), https_test_server_->GetURL("/page_capping.html#anchor"));
+
+  EXPECT_EQ(1u, InfoBarService::FromWebContents(contents)->infobar_count());
+  EXPECT_EQ(infobar, InfoBarService::FromWebContents(contents)->infobar_at(0));
+
+  https_test_server_.reset();
+}
diff --git a/chrome/browser/data_use_measurement/page_load_capping/page_load_capping_infobar_delegate.cc b/chrome/browser/data_use_measurement/page_load_capping/page_load_capping_infobar_delegate.cc
index c26c5a9..a6482a2b 100644
--- a/chrome/browser/data_use_measurement/page_load_capping/page_load_capping_infobar_delegate.cc
+++ b/chrome/browser/data_use_measurement/page_load_capping/page_load_capping_infobar_delegate.cc
@@ -137,7 +137,7 @@
 
 bool PageLoadCappingInfoBarDelegate::ShouldExpire(
     const NavigationDetails& details) const {
-  return true;
+  return details.is_navigation_to_different_page;
 }
 
 int PageLoadCappingInfoBarDelegate::GetButtons() const {
diff --git a/chrome/browser/extensions/extension_install_prompt.cc b/chrome/browser/extensions/extension_install_prompt.cc
index ed7af21a..39f524fa 100644
--- a/chrome/browser/extensions/extension_install_prompt.cc
+++ b/chrome/browser/extensions/extension_install_prompt.cc
@@ -678,10 +678,7 @@
     }
   }
 
-  if (permissions_to_display &&
-      (!extension_ ||
-       !extensions::PermissionsData::ShouldSkipPermissionWarnings(
-           extension_->id()))) {
+  if (permissions_to_display) {
     Manifest::Type type =
         extension_ ? extension_->GetType() : Manifest::TYPE_UNKNOWN;
     const extensions::PermissionMessageProvider* message_provider =
diff --git a/chrome/browser/global_keyboard_shortcuts_mac.mm b/chrome/browser/global_keyboard_shortcuts_mac.mm
index 1b77a62..f548f85 100644
--- a/chrome/browser/global_keyboard_shortcuts_mac.mm
+++ b/chrome/browser/global_keyboard_shortcuts_mac.mm
@@ -226,7 +226,7 @@
 
     {true,  false, false, false, kVK_LeftArrow,         0,   IDC_BACK},
     {true,  false, false, false, kVK_RightArrow,        0,   IDC_FORWARD},
-    {true,  true,  false, false, 0,                     'c', IDC_DEV_TOOLS_INSPECT},
+    {true,  true,  false, false, kVK_ANSI_C,            0,   IDC_DEV_TOOLS_INSPECT},
   });
   // clang-format on
   return *keys;
diff --git a/chrome/browser/media/encrypted_media_browsertest.cc b/chrome/browser/media/encrypted_media_browsertest.cc
index 3b639a2..557f3bb9 100644
--- a/chrome/browser/media/encrypted_media_browsertest.cc
+++ b/chrome/browser/media/encrypted_media_browsertest.cc
@@ -443,7 +443,7 @@
 // TODO(crbug.com/847591): ChromeOS Widevine CDM does not support policy check
 // API yet. Remove this condition when the CDM is updated.
 #if defined(WIDEVINE_CDM_AVAILABLE) && defined(OS_CHROMEOS)
-    if (IsWidevine(key_system))
+    if (IsWidevine(CurrentKeySystem()))
       return;
 #endif  // defined(WIDEVINE_CDM_AVAILABLE) && defined(OS_CHROMEOS)
 
diff --git a/chrome/browser/offline_pages/offline_page_request_handler_unittest.cc b/chrome/browser/offline_pages/offline_page_request_handler_unittest.cc
index 5849214..f60a333 100644
--- a/chrome/browser/offline_pages/offline_page_request_handler_unittest.cc
+++ b/chrome/browser/offline_pages/offline_page_request_handler_unittest.cc
@@ -260,8 +260,8 @@
       const net::URLRequest& request,
       previews::PreviewsType type,
       net::EffectiveConnectionType effective_connection_type_threshold,
-      const std::vector<std::string>& host_blacklist_from_server)
-      const override {
+      const std::vector<std::string>& host_blacklist_from_server,
+      bool ignore_long_term_black_list_rules) const override {
     return should_allow_preview_;
   }
 
diff --git a/chrome/browser/page_load_metrics/observers/page_capping_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/page_capping_page_load_metrics_observer.cc
index 381413d..73192a2 100644
--- a/chrome/browser/page_load_metrics/observers/page_capping_page_load_metrics_observer.cc
+++ b/chrome/browser/page_load_metrics/observers/page_capping_page_load_metrics_observer.cc
@@ -19,6 +19,7 @@
 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/navigation_handle.h"
+#include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/web_contents.h"
 
 namespace {
@@ -80,6 +81,7 @@
   web_contents_ = navigation_handle->GetWebContents();
   page_cap_ = GetPageLoadCappingBytesThreshold(false /* media_page_load */);
   url_host_ = navigation_handle->GetURL().host();
+  MaybeCreate();
   // TODO(ryansturm) Check a blacklist of eligible pages.
   // https://crbug.com/797981
   return page_load_metrics::PageLoadMetricsObserver::CONTINUE_OBSERVING;
@@ -122,15 +124,31 @@
   page_cap_ = GetPageLoadCappingBytesThreshold(true /* media_page_load */);
 }
 
+void PageCappingPageLoadMetricsObserver::OnDidFinishSubFrameNavigation(
+    content::NavigationHandle* navigation_handle) {
+  // If the page is not paused, we should not pause new frames.
+  if (!paused_)
+    return;
+  // If the navigation is to the same page, is to an error page, the load hasn't
+  // committed or render frame host is null, no need to pause the page.
+  if (navigation_handle->IsSameDocument() || navigation_handle->IsErrorPage() ||
+      !navigation_handle->HasCommitted() ||
+      !navigation_handle->GetRenderFrameHost()) {
+    return;
+  }
+  // Pause the new frame.
+  handles_.push_back(
+      navigation_handle->GetRenderFrameHost()->PauseSubresourceLoading());
+}
+
 void PageCappingPageLoadMetricsObserver::PauseSubresourceLoading(bool pause) {
   DCHECK_NE(pause, paused_);
   DCHECK(displayed_infobar_);
   paused_ = pause;
-  if (pause) {
+  if (pause)
     handles_ = web_contents_->PauseSubresourceLoading();
-  } else {
+  else
     handles_.clear();
-  }
 }
 
 page_load_metrics::PageLoadMetricsObserver::ObservePolicy
diff --git a/chrome/browser/page_load_metrics/observers/page_capping_page_load_metrics_observer.h b/chrome/browser/page_load_metrics/observers/page_capping_page_load_metrics_observer.h
index 3af6581c..c7cfa0b8 100644
--- a/chrome/browser/page_load_metrics/observers/page_capping_page_load_metrics_observer.h
+++ b/chrome/browser/page_load_metrics/observers/page_capping_page_load_metrics_observer.h
@@ -42,6 +42,8 @@
                             extra_request_complete_info) override;
   ObservePolicy OnCommit(content::NavigationHandle* navigation_handle,
                          ukm::SourceId source_id) override;
+  void OnDidFinishSubFrameNavigation(
+      content::NavigationHandle* navigation_handle) override;
   void MediaStartedPlaying(
       const content::WebContentsObserver::MediaPlayerInfo& video_type,
       bool is_in_main_frame) override;
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc
index c2ceff2..e6474ee 100644
--- a/chrome/browser/prefs/browser_prefs.cc
+++ b/chrome/browser/prefs/browser_prefs.cc
@@ -191,6 +191,7 @@
 #include "chrome/browser/gcm/gcm_product_util.h"
 #include "chrome/browser/media/router/media_router_feature.h"
 #include "chrome/browser/metrics/tab_stats_tracker.h"
+#include "chrome/browser/search/instant_service.h"
 #include "chrome/browser/signin/signin_promo.h"
 #include "chrome/browser/ui/startup/startup_browser_creator.h"
 #include "chrome/browser/ui/webui/foreign_session_handler.h"
@@ -287,10 +288,6 @@
 #include "chrome/browser/ui/desktop_ios_promotion/desktop_ios_promotion_util.h"
 #endif
 
-#if !defined(OS_ANDROID)
-#include "chrome/browser/search/instant_service.h"
-#endif
-
 #if !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
 #include "chrome/browser/ui/startup/default_browser_prompt.h"
 #endif
diff --git a/chrome/browser/prerender/prerender_manager.cc b/chrome/browser/prerender/prerender_manager.cc
index fb9d06c1..74b1a6fb 100644
--- a/chrome/browser/prerender/prerender_manager.cc
+++ b/chrome/browser/prerender/prerender_manager.cc
@@ -318,7 +318,7 @@
   }
 
   DeleteOldEntries();
-  to_delete_prerenders_.clear();
+  DeleteToDeletePrerenders();
 
   // First, try to find prerender data with the correct session storage
   // namespace.
@@ -946,7 +946,7 @@
   if (active_prerenders_.empty())
     StopSchedulingPeriodicCleanups();
 
-  to_delete_prerenders_.clear();
+  DeleteToDeletePrerenders();
 
   CleanUpOldNavigations(&prefetches_, base::TimeDelta::FromMinutes(30));
 
@@ -985,6 +985,18 @@
   }
 }
 
+void PrerenderManager::DeleteToDeletePrerenders() {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  // Delete the items one by one (after removing from the vector) as deleting
+  // the WebContents may trigger a call to GetPrerenderContents(), which
+  // iterates over |to_delete_prerenders_|.
+  while (!to_delete_prerenders_.empty()) {
+    std::unique_ptr<PrerenderData> prerender_data =
+        std::move(to_delete_prerenders_.back());
+    to_delete_prerenders_.pop_back();
+  }
+}
+
 base::Time PrerenderManager::GetCurrentTime() const {
   return base::Time::Now();
 }
@@ -1159,7 +1171,7 @@
     PrerenderContents* contents = active_prerenders_.front()->contents();
     contents->Destroy(final_status);
   }
-  to_delete_prerenders_.clear();
+  DeleteToDeletePrerenders();
 }
 
 void PrerenderManager::RecordFinalStatusWithoutCreatingPrerenderContents(
diff --git a/chrome/browser/prerender/prerender_manager.h b/chrome/browser/prerender/prerender_manager.h
index 8642899..d8ef34e 100644
--- a/chrome/browser/prerender/prerender_manager.h
+++ b/chrome/browser/prerender/prerender_manager.h
@@ -469,6 +469,8 @@
 
   void DeleteOldEntries();
 
+  void DeleteToDeletePrerenders();
+
   // Virtual so unit tests can override this.
   virtual std::unique_ptr<PrerenderContents> CreatePrerenderContents(
       const GURL& url,
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu.cc b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
index e88af27..30c7910 100644
--- a/chrome/browser/renderer_context_menu/render_view_context_menu.cc
+++ b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
@@ -1434,8 +1434,12 @@
                                   IDS_CONTENT_CONTEXT_REDO);
   menu_model_.AddSeparator(ui::NORMAL_SEPARATOR);
 #else
-  if (!IsDevToolsURL(params_.page_url) && !menu_model_.GetItemCount() &&
-      !content_type_->SupportsGroup(ContextMenuContentType::ITEM_GROUP_PRINT)) {
+  // Also want to show 'Undo' and 'Redo' if 'Emoji' is the only item in the menu
+  // so far.
+  if (!IsDevToolsURL(params_.page_url) &&
+      !content_type_->SupportsGroup(ContextMenuContentType::ITEM_GROUP_PRINT) &&
+      (!menu_model_.GetItemCount() ||
+       menu_model_.GetIndexOfCommandId(IDC_CONTENT_CONTEXT_EMOJI) != -1)) {
     menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_UNDO,
                                     IDS_CONTENT_CONTEXT_UNDO);
     menu_model_.AddItemWithStringId(IDC_CONTENT_CONTEXT_REDO,
diff --git a/chrome/browser/renderer_context_menu/spelling_options_submenu_observer.cc b/chrome/browser/renderer_context_menu/spelling_options_submenu_observer.cc
index 3343628..5f743ef 100644
--- a/chrome/browser/renderer_context_menu/spelling_options_submenu_observer.cc
+++ b/chrome/browser/renderer_context_menu/spelling_options_submenu_observer.cc
@@ -156,6 +156,9 @@
 
   switch (command_id) {
     case IDC_CHECK_SPELLING_WHILE_TYPING:
+      return !pref->FindPreference(spellcheck::prefs::kSpellCheckEnable)
+                  ->IsManaged();
+
     case IDC_SPELLCHECK_MENU:
       return true;
   }
diff --git a/chrome/browser/resource_coordinator/page_signal_receiver.cc b/chrome/browser/resource_coordinator/page_signal_receiver.cc
index c8c0f72e..5691bd3 100644
--- a/chrome/browser/resource_coordinator/page_signal_receiver.cc
+++ b/chrome/browser/resource_coordinator/page_signal_receiver.cc
@@ -46,6 +46,15 @@
     observer.OnPageAlmostIdle(web_contents_iter->second);
 }
 
+void PageSignalReceiver::NotifyRendererIsBloated(
+    const CoordinationUnitID& page_cu_id) {
+  auto web_contents_iter = cu_id_web_contents_map_.find(page_cu_id);
+  if (web_contents_iter == cu_id_web_contents_map_.end())
+    return;
+  for (auto& observer : observers_)
+    observer.OnRendererIsBloated(web_contents_iter->second);
+}
+
 void PageSignalReceiver::SetExpectedTaskQueueingDuration(
     const CoordinationUnitID& page_cu_id,
     base::TimeDelta duration) {
diff --git a/chrome/browser/resource_coordinator/page_signal_receiver.h b/chrome/browser/resource_coordinator/page_signal_receiver.h
index d1c77da8..d63acb5c 100644
--- a/chrome/browser/resource_coordinator/page_signal_receiver.h
+++ b/chrome/browser/resource_coordinator/page_signal_receiver.h
@@ -25,6 +25,7 @@
   // managed by the client. Thus the clients are responsible for checking the
   // passed |web_contents| by themselves.
   virtual void OnPageAlmostIdle(content::WebContents* web_contents) {}
+  virtual void OnRendererIsBloated(content::WebContents* web_contents) {}
   virtual void OnExpectedTaskQueueingDurationSet(
       content::WebContents* web_contents,
       base::TimeDelta duration) {}
@@ -52,6 +53,7 @@
 
   // mojom::PageSignalReceiver implementation.
   void NotifyPageAlmostIdle(const CoordinationUnitID& page_cu_id) override;
+  void NotifyRendererIsBloated(const CoordinationUnitID& page_cu_id) override;
   void SetExpectedTaskQueueingDuration(const CoordinationUnitID& page_cu_id,
                                        base::TimeDelta duration) override;
   void SetLifecycleState(const CoordinationUnitID& page_cu_id,
diff --git a/chrome/browser/resource_coordinator/session_restore_policy.cc b/chrome/browser/resource_coordinator/session_restore_policy.cc
index d6b04f8..17d7e48 100644
--- a/chrome/browser/resource_coordinator/session_restore_policy.cc
+++ b/chrome/browser/resource_coordinator/session_restore_policy.cc
@@ -63,7 +63,8 @@
     : policy_enabled_(
           base::FeatureList::IsEnabled(features::kInfiniteSessionRestore)),
       delegate_(SysInfoDelegate::Get()),
-      params_(&GetStaticInfiniteSessionRestoreParams()),
+      parsed_params_(GetInfiniteSessionRestoreParams()),
+      params_(&parsed_params_),
       simultaneous_tab_loads_(CalculateSimultaneousTabLoadsFromParams()) {}
 
 SessionRestorePolicy::~SessionRestorePolicy() = default;
@@ -110,10 +111,10 @@
 }
 
 SessionRestorePolicy::SessionRestorePolicy(
+    bool policy_enabled,
     const Delegate* delegate,
     const InfiniteSessionRestoreParams* params)
-    : policy_enabled_(
-          base::FeatureList::IsEnabled(features::kInfiniteSessionRestore)),
+    : policy_enabled_(policy_enabled),
       delegate_(delegate),
       params_(params),
       simultaneous_tab_loads_(CalculateSimultaneousTabLoadsFromParams()) {}
diff --git a/chrome/browser/resource_coordinator/session_restore_policy.h b/chrome/browser/resource_coordinator/session_restore_policy.h
index 93375a7b..3e3273c 100644
--- a/chrome/browser/resource_coordinator/session_restore_policy.h
+++ b/chrome/browser/resource_coordinator/session_restore_policy.h
@@ -45,7 +45,8 @@
   // Protected so can be exposed for unittesting.
 
   // Full constructor for testing.
-  SessionRestorePolicy(const Delegate* delegate,
+  SessionRestorePolicy(bool policy_enabled,
+                       const Delegate* delegate,
                        const InfiniteSessionRestoreParams* params);
 
   // Helper function for computing the number of loading slots to use. All
@@ -69,9 +70,13 @@
   // the logic in this class.
   const Delegate* const delegate_;
 
-  // The parameters being used by this policy engine. These default to the
-  // static parameters from tab_manager_features.h, but can be injected for
-  // testing.
+  // A container for storing parsed parameters. Unless parameters are injected
+  // externally this will be populated with parsed parameters.
+  const InfiniteSessionRestoreParams parsed_params_;
+
+  // The parameters being used by this policy engine. By default this is simply
+  // a pointer to |parsed_params_|, but it can also point to externally
+  // injected parameters for testing.
   const InfiniteSessionRestoreParams* const params_;
 
   // The number of simultaneous tab loads that are permitted by policy. This
diff --git a/chrome/browser/resource_coordinator/session_restore_policy_unittest.cc b/chrome/browser/resource_coordinator/session_restore_policy_unittest.cc
index 71c6d08c6..f3efb83 100644
--- a/chrome/browser/resource_coordinator/session_restore_policy_unittest.cc
+++ b/chrome/browser/resource_coordinator/session_restore_policy_unittest.cc
@@ -6,7 +6,6 @@
 
 #include "base/test/simple_test_tick_clock.h"
 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
-#include "components/variations/variations_params_manager.h"
 #include "content/public/browser/web_contents.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -56,9 +55,10 @@
  public:
   using SessionRestorePolicy::CalculateSimultaneousTabLoads;
   using SessionRestorePolicy::SetTabLoadsStartedForTesting;
-  TestSessionRestorePolicy(const Delegate* delegate,
+  TestSessionRestorePolicy(bool policy_enabled,
+                           const Delegate* delegate,
                            const InfiniteSessionRestoreParams* params)
-      : SessionRestorePolicy(delegate, params) {}
+      : SessionRestorePolicy(policy_enabled, delegate, params) {}
 
   ~TestSessionRestorePolicy() override {}
 
@@ -117,8 +117,9 @@
     ChromeRenderViewHostTestHarness::TearDown();
   }
 
-  void CreatePolicy() {
-    policy_ = std::make_unique<TestSessionRestorePolicy>(&delegate_, &params_);
+  void CreatePolicy(bool policy_enabled) {
+    policy_ = std::make_unique<TestSessionRestorePolicy>(policy_enabled,
+                                                         &delegate_, &params_);
   }
 
  protected:
@@ -170,16 +171,7 @@
 }
 
 TEST_F(SessionRestorePolicyTest, ShouldLoadFeatureEnabled) {
-  // Enable the InfiniteSessionRestore feature so that the policy logic is
-  // actually enabled.
-  std::set<std::string> features;
-  std::map<std::string, std::string> variations_params;
-  variations::testing::VariationParamsManager variations_manager;
-  features.insert(features::kInfiniteSessionRestore.name);
-  variations_manager.SetVariationParamsWithFeatureAssociations(
-      "DummyTrial", variations_params, features);
-
-  CreatePolicy();
+  CreatePolicy(true);
   EXPECT_TRUE(policy_->policy_enabled());
   EXPECT_EQ(2u, policy_->simultaneous_tab_loads());
 
@@ -247,7 +239,7 @@
 }
 
 TEST_F(SessionRestorePolicyTest, ShouldLoadFeatureDisabled) {
-  CreatePolicy();
+  CreatePolicy(false);
   EXPECT_FALSE(policy_->policy_enabled());
   EXPECT_EQ(std::numeric_limits<size_t>::max(),
             policy_->simultaneous_tab_loads());
diff --git a/chrome/browser/resource_coordinator/tab_lifecycle_unit.cc b/chrome/browser/resource_coordinator/tab_lifecycle_unit.cc
index 715cba0..15dbca8 100644
--- a/chrome/browser/resource_coordinator/tab_lifecycle_unit.cc
+++ b/chrome/browser/resource_coordinator/tab_lifecycle_unit.cc
@@ -28,7 +28,6 @@
 #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/page_importance_signals.h"
 #include "url/gurl.h"
 
 namespace resource_coordinator {
@@ -45,7 +44,20 @@
          state == LifecycleUnitState::PENDING_FREEZE;
 }
 
-}  // namespace
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused.
+enum class BloatedRendererHandlingInBrowser {
+  kReloaded = 0,
+  kCannotReload = 1,
+  kCannotShutdown = 2,
+  kMaxValue = kCannotShutdown
+};
+
+void RecordBloatedRendererHandling(BloatedRendererHandlingInBrowser handling) {
+  UMA_HISTOGRAM_ENUMERATION("BloatedRenderer.HandlingInBrowser", handling);
+}
+
+}  // anonymous namespace
 
 TabLifecycleUnitSource::TabLifecycleUnit::TabLifecycleUnit(
     base::ObserverList<TabLifecycleObserver>* observers,
@@ -524,6 +536,54 @@
   return Discard(DiscardReason::kExternal);
 }
 
+bool TabLifecycleUnitSource::TabLifecycleUnit::CanReloadBloatedTab() {
+  // Can't reload a tab that isn't in a TabStripModel, which is needed for
+  // showing an infobar.
+  if (!tab_strip_model_)
+    return false;
+
+  if (GetWebContents()->IsCrashed())
+    return false;
+
+  // Do not reload tabs that don't have a valid URL (most probably they have
+  // just been opened and discarding them would lose the URL).
+  if (!GetWebContents()->GetLastCommittedURL().is_valid() ||
+      GetWebContents()->GetLastCommittedURL().is_empty()) {
+    return false;
+  }
+
+  // Do not reload tabs in which the user has entered text in a form.
+  if (GetWebContents()->GetPageImportanceSignals().had_form_interaction)
+    return false;
+
+  // TODO(ulan): Check if the navigation controller has POST data.
+
+  return true;
+}
+
+void TabLifecycleUnitSource::TabLifecycleUnit::ReloadBloatedTab() {
+  if (CanReloadBloatedTab()) {
+    const size_t expected_page_count = 1u;
+    const bool skip_unload_handlers = true;
+    if (GetRenderProcessHost()->FastShutdownIfPossible(expected_page_count,
+                                                       skip_unload_handlers)) {
+      // TODO(ulan): Notify the WebContents that the page is bloated to give
+      // it a chance to show the infobar after the reload.
+      const bool check_for_repost = true;
+      GetWebContents()->GetController().Reload(content::ReloadType::NORMAL,
+                                               check_for_repost);
+      RecordBloatedRendererHandling(
+          BloatedRendererHandlingInBrowser::kReloaded);
+    } else {
+      RecordBloatedRendererHandling(
+          BloatedRendererHandlingInBrowser::kCannotShutdown);
+    }
+  } else {
+    RecordBloatedRendererHandling(
+        BloatedRendererHandlingInBrowser::kCannotReload);
+  }
+}
+
 bool TabLifecycleUnitSource::TabLifecycleUnit::FreezeTab() {
   return Freeze();
 }
diff --git a/chrome/browser/resource_coordinator/tab_lifecycle_unit.h b/chrome/browser/resource_coordinator/tab_lifecycle_unit.h
index 0021388..64055f8 100644
--- a/chrome/browser/resource_coordinator/tab_lifecycle_unit.h
+++ b/chrome/browser/resource_coordinator/tab_lifecycle_unit.h
@@ -5,6 +5,7 @@
 #ifndef CHROME_BROWSER_RESOURCE_COORDINATOR_TAB_LIFECYCLE_UNIT_H_
 #define CHROME_BROWSER_RESOURCE_COORDINATOR_TAB_LIFECYCLE_UNIT_H_
 
+#include "base/gtest_prod_util.h"
 #include "base/macros.h"
 #include "base/observer_list.h"
 #include "base/time/time.h"
@@ -15,6 +16,7 @@
 #include "chrome/browser/resource_coordinator/time.h"
 #include "content/public/browser/visibility.h"
 #include "content/public/browser/web_contents_observer.h"
+#include "content/public/common/page_importance_signals.h"
 
 class TabStripModel;
 
@@ -76,6 +78,10 @@
   // unit.
   void UpdateLifecycleState(mojom::LifecycleState state);
 
+  // Reloads the tab because its renderer is bloated and shows an infobar
+  // explaining that it was reloaded because it ran out of memory.
+  void ReloadBloatedTab();
+
   // LifecycleUnit:
   TabLifecycleUnitExternal* AsTabLifecycleUnitExternal() override;
   base::string16 GetTitle() const override;
@@ -111,6 +117,13 @@
   friend class TabLifecycleUnitSource;
 
  private:
+  FRIEND_TEST_ALL_PREFIXES(TabLifecycleUnitTest, CanReloadBloatedTab);
+  FRIEND_TEST_ALL_PREFIXES(TabLifecycleUnitTest, CannotReloadBloatedTabCrashed);
+  FRIEND_TEST_ALL_PREFIXES(TabLifecycleUnitTest,
+                           CannotReloadBloatedTabInvalidURL);
+  FRIEND_TEST_ALL_PREFIXES(TabLifecycleUnitTest,
+                           CannotReloadBloatedTabPendingUserInteraction);
+
   // Determines if the tab is a media tab, and populates an optional
   // |decision_details| with full details.
   bool IsMediaTabImpl(DecisionDetails* decision_details) const;
@@ -137,6 +150,8 @@
   void DidStartLoading() override;
   void OnVisibilityChanged(content::Visibility visibility) override;
 
+  bool CanReloadBloatedTab();
+
   // List of observers to notify when the discarded state or the auto-
   // discardable state of this tab changes.
   base::ObserverList<TabLifecycleObserver>* observers_;
diff --git a/chrome/browser/resource_coordinator/tab_lifecycle_unit_source.cc b/chrome/browser/resource_coordinator/tab_lifecycle_unit_source.cc
index a93468c8..fb88b208 100644
--- a/chrome/browser/resource_coordinator/tab_lifecycle_unit_source.cc
+++ b/chrome/browser/resource_coordinator/tab_lifecycle_unit_source.cc
@@ -229,6 +229,11 @@
     lifecycle_unit->UpdateLifecycleState(state);
 }
 
+void TabLifecycleUnitSource::OnRendererIsBloated(
+    content::WebContents* web_contents) {
+  GetTabLifecycleUnit(web_contents)->ReloadBloatedTab();
+}
+
 }  // namespace resource_coordinator
 
 DEFINE_WEB_CONTENTS_USER_DATA_KEY(
diff --git a/chrome/browser/resource_coordinator/tab_lifecycle_unit_source.h b/chrome/browser/resource_coordinator/tab_lifecycle_unit_source.h
index 64952f29..d9ec07a 100644
--- a/chrome/browser/resource_coordinator/tab_lifecycle_unit_source.h
+++ b/chrome/browser/resource_coordinator/tab_lifecycle_unit_source.h
@@ -114,6 +114,7 @@
   // PageSignalObserver:
   void OnLifecycleStateChanged(content::WebContents* web_contents,
                                mojom::LifecycleState state) override;
+  void OnRendererIsBloated(content::WebContents* web_contents) override;
 
   // Tracks the BrowserList and all TabStripModels.
   BrowserTabStripTracker browser_tab_strip_tracker_;
diff --git a/chrome/browser/resource_coordinator/tab_lifecycle_unit_unittest.cc b/chrome/browser/resource_coordinator/tab_lifecycle_unit_unittest.cc
index 53ca5c9..cd6ab97 100644
--- a/chrome/browser/resource_coordinator/tab_lifecycle_unit_unittest.cc
+++ b/chrome/browser/resource_coordinator/tab_lifecycle_unit_unittest.cc
@@ -332,4 +332,39 @@
   tab_lifecycle_unit.RemoveObserver(&observer);
 }
 
+TEST_F(TabLifecycleUnitTest, CanReloadBloatedTab) {
+  TabLifecycleUnit tab_lifecycle_unit(&observers_, web_contents_,
+                                      tab_strip_model_.get());
+  EXPECT_TRUE(tab_lifecycle_unit.CanReloadBloatedTab());
+}
+
+TEST_F(TabLifecycleUnitTest, CannotReloadBloatedTabCrashed) {
+  TabLifecycleUnit tab_lifecycle_unit(&observers_, web_contents_,
+                                      tab_strip_model_.get());
+
+  web_contents_->SetIsCrashed(base::TERMINATION_STATUS_PROCESS_CRASHED, 0);
+
+  EXPECT_FALSE(tab_lifecycle_unit.CanReloadBloatedTab());
+}
+
+TEST_F(TabLifecycleUnitTest, CannotReloadBloatedTabInvalidURL) {
+  TabLifecycleUnit tab_lifecycle_unit(&observers_, web_contents_,
+                                      tab_strip_model_.get());
+
+  content::WebContentsTester::For(web_contents_)
+      ->SetLastCommittedURL(GURL("invalid :)"));
+
+  EXPECT_FALSE(tab_lifecycle_unit.CanReloadBloatedTab());
+}
+
+TEST_F(TabLifecycleUnitTest, CannotReloadBloatedTabPendingUserInteraction) {
+  TabLifecycleUnit tab_lifecycle_unit(&observers_, web_contents_,
+                                      tab_strip_model_.get());
+  content::PageImportanceSignals signals;
+  signals.had_form_interaction = true;
+  content::WebContentsTester::For(web_contents_)
+      ->SetPageImportanceSignals(signals);
+  EXPECT_FALSE(tab_lifecycle_unit.CanReloadBloatedTab());
+}
+
 }  // namespace resource_coordinator
diff --git a/chrome/browser/resource_coordinator/tab_manager_browsertest.cc b/chrome/browser/resource_coordinator/tab_manager_browsertest.cc
index e22be46..c95df30 100644
--- a/chrome/browser/resource_coordinator/tab_manager_browsertest.cc
+++ b/chrome/browser/resource_coordinator/tab_manager_browsertest.cc
@@ -118,6 +118,12 @@
         ->UpdateLifecycleState(mojom::LifecycleState::kFrozen);
   }
 
+  void ReloadBloatedTab(content::WebContents* contents) {
+    static_cast<TabLifecycleUnitSource::TabLifecycleUnit*>(
+        TabLifecycleUnitExternal::FromWebContents(contents))
+        ->ReloadBloatedTab();
+  }
+
   base::SimpleTestTickClock test_clock_;
   ScopedSetTickClockForTesting scoped_set_tick_clock_for_testing_;
 };
@@ -1115,6 +1121,25 @@
   EXPECT_TRUE(IsTabDiscarded(browser4->tab_strip_model()->GetWebContentsAt(1)));
 }
 
+// TODO(ulan): Enable the test after fixing crbug.com/850921.
+IN_PROC_BROWSER_TEST_F(TabManagerTest, DISABLED_ReloadBloatedTab) {
+  content::WindowedNotificationObserver load(
+      content::NOTIFICATION_NAV_ENTRY_COMMITTED,
+      content::NotificationService::AllSources());
+  OpenURLParams url(GURL(chrome::kChromeUIAboutURL), content::Referrer(),
+                    WindowOpenDisposition::CURRENT_TAB,
+                    ui::PAGE_TRANSITION_TYPED, false);
+  browser()->OpenURL(url);
+  load.Wait();
+
+  content::WindowedNotificationObserver reload(
+      content::NOTIFICATION_NAV_ENTRY_COMMITTED,
+      content::NotificationService::AllSources());
+  auto* tsm = browser()->tab_strip_model();
+  ReloadBloatedTab(tsm->GetWebContentsAt(0));
+  reload.Wait();
+}
+
 }  // namespace resource_coordinator
 
 #endif  // OS_WIN || OS_MAXOSX || OS_LINUX || defined(OS_CHROMEOS)
diff --git a/chrome/browser/resource_coordinator/tab_manager_features.cc b/chrome/browser/resource_coordinator/tab_manager_features.cc
index 5738756..61c8e17 100644
--- a/chrome/browser/resource_coordinator/tab_manager_features.cc
+++ b/chrome/browser/resource_coordinator/tab_manager_features.cc
@@ -357,10 +357,4 @@
   return params;
 }
 
-const InfiniteSessionRestoreParams& GetStaticInfiniteSessionRestoreParams() {
-  static base::NoDestructor<InfiniteSessionRestoreParams> params(
-      GetInfiniteSessionRestoreParams());
-  return *params;
-}
-
 }  // namespace resource_coordinator
diff --git a/chrome/browser/resource_coordinator/tab_manager_features.h b/chrome/browser/resource_coordinator/tab_manager_features.h
index 4a261125..a1237f3 100644
--- a/chrome/browser/resource_coordinator/tab_manager_features.h
+++ b/chrome/browser/resource_coordinator/tab_manager_features.h
@@ -254,10 +254,6 @@
 // Gets parameters for the infinite session restore feature.
 InfiniteSessionRestoreParams GetInfiniteSessionRestoreParams();
 
-// Returns a static InfiniteSessionRestoreParams object that can be used by all
-// instances of TabLoader.
-const InfiniteSessionRestoreParams& GetStaticInfiniteSessionRestoreParams();
-
 }  // namespace resource_coordinator
 
 #endif  // CHROME_BROWSER_RESOURCE_COORDINATOR_TAB_MANAGER_FEATURES_H_
diff --git a/chrome/browser/resource_coordinator/tab_manager_features_unittest.cc b/chrome/browser/resource_coordinator/tab_manager_features_unittest.cc
index 13437bd9..6dce812 100644
--- a/chrome/browser/resource_coordinator/tab_manager_features_unittest.cc
+++ b/chrome/browser/resource_coordinator/tab_manager_features_unittest.cc
@@ -110,6 +110,8 @@
     EXPECT_EQ(max_tabs_to_restore, params.max_tabs_to_restore);
     EXPECT_EQ(mb_free_memory_per_tab_to_restore,
               params.mb_free_memory_per_tab_to_restore);
+    EXPECT_EQ(max_time_since_last_use_to_restore,
+              params.max_time_since_last_use_to_restore);
     EXPECT_EQ(min_site_engagement_to_restore,
               params.min_site_engagement_to_restore);
   }
diff --git a/chrome/browser/resources/feedback/html/sys_info.html b/chrome/browser/resources/feedback/html/sys_info.html
index 8b7e757..f125409 100644
--- a/chrome/browser/resources/feedback/html/sys_info.html
+++ b/chrome/browser/resources/feedback/html/sys_info.html
@@ -9,7 +9,6 @@
     <link rel="stylesheet" href="../css/sys_info.css">
     <script src="chrome://resources/js/util.js"></script>
     <script src="chrome://resources/js/i18n_template_no_process.js"></script>
-    <script src="chrome://resources/js/jstemplate_compiled.js"></script>
     <script src="../js/sys_info.js"></script>
   </head>
   <body>
@@ -31,4 +30,4 @@
       <table class="list" id="detailsTable"></table>
     </div>
   </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/chrome/browser/resources/local_discovery/local_discovery.html b/chrome/browser/resources/local_discovery/local_discovery.html
index a99ecdc..6a699ba 100644
--- a/chrome/browser/resources/local_discovery/local_discovery.html
+++ b/chrome/browser/resources/local_discovery/local_discovery.html
@@ -162,6 +162,5 @@
   </div>
 
   <script src="chrome://resources/js/i18n_template.js"></script>
-  <script src="chrome://resources/js/jstemplate_compiled.js"></script>
 </body>
 </html>
diff --git a/chrome/browser/resources/local_ntp/custom_backgrounds.css b/chrome/browser/resources/local_ntp/custom_backgrounds.css
index 4ae7d20..32ccb05 100644
--- a/chrome/browser/resources/local_ntp/custom_backgrounds.css
+++ b/chrome/browser/resources/local_ntp/custom_backgrounds.css
@@ -116,6 +116,12 @@
   z-index: 10000;
 }
 
+@media (max-width: 520px) {
+   #bg-sel-menu {
+     width: 352px;
+   }
+}
+
 #bg-sel-tiles {
   height: 284px;
   overflow-y: scroll;
diff --git a/chrome/browser/resources/media/webrtc_logs.html b/chrome/browser/resources/media/webrtc_logs.html
index 7bd34ac..7e3178b8 100644
--- a/chrome/browser/resources/media/webrtc_logs.html
+++ b/chrome/browser/resources/media/webrtc_logs.html
@@ -7,8 +7,8 @@
   <link rel="stylesheet" href="webrtc_logs.css">
   <script src="chrome://resources/js/load_time_data.js"></script>
   <script src="chrome://resources/js/util.js"></script>
-  <script src="chrome://webrtc-logs/strings.js"></script>
-  <script src="chrome://webrtc-logs/webrtc_logs.js"></script>
+  <script src="strings.js"></script>
+  <script src="webrtc_logs.js"></script>
 </head>
 <body>
   <header><h1>$i18n{webrtcLogsTitle}</h1></header>
@@ -16,6 +16,5 @@
   <div id="log-list"></div>
   <p id="no-logs" hidden>$i18n{noLogsMessage}</p>
   <script src="chrome://resources/js/i18n_template.js"></script>
-  <script src="chrome://resources/js/jstemplate_compiled.js"></script>
 </body>
 </html>
diff --git a/chrome/browser/resources/predictors/predictors.html b/chrome/browser/resources/predictors/predictors.html
index 24e9160..34b7a0e 100644
--- a/chrome/browser/resources/predictors/predictors.html
+++ b/chrome/browser/resources/predictors/predictors.html
@@ -35,7 +35,6 @@
       </tabpanel>
     </tabpanels>
   </tabbox>
-  <script src="chrome://resources/js/jstemplate_compiled.js"></script>
-  <script src="chrome://predictors/predictors.js"></script>
+  <script src="predictors.js"></script>
 </body>
 </html>
diff --git a/chrome/browser/resources/settings/internet_page/network_proxy_section.js b/chrome/browser/resources/settings/internet_page/network_proxy_section.js
index 1d974de..8cb0053 100644
--- a/chrome/browser/resources/settings/internet_page/network_proxy_section.js
+++ b/chrome/browser/resources/settings/internet_page/network_proxy_section.js
@@ -143,6 +143,6 @@
 
   /** @private */
   onAllowSharedDialogClose_: function() {
-    cr.ui.focusWithoutInk(assert(this.$$('#allowShared')));
+    this.$.allowShared.focus();
   },
 });
diff --git a/chrome/browser/resources/settings/languages_page/languages_page.js b/chrome/browser/resources/settings/languages_page/languages_page.js
index 1cdee57..a78def5 100644
--- a/chrome/browser/resources/settings/languages_page/languages_page.js
+++ b/chrome/browser/resources/settings/languages_page/languages_page.js
@@ -458,7 +458,7 @@
    * @private
    */
   getSpellCheckSecondaryText_: function() {
-    if (this.getSpellCheckDisabled_())
+    if (this.getSpellCheckDisabledByPolicy_())
       return loadTimeData.getString('spellCheckDisabled');
     const enabledSpellCheckLanguages =
         this.getSpellCheckLanguages_().filter(function(languageState) {
@@ -496,10 +496,11 @@
    * @return {boolean}
    * @private
    */
-  getSpellCheckDisabled_: function() {
+  getSpellCheckDisabledByPolicy_: function() {
     const pref = /** @type {!chrome.settingsPrivate.PrefObject} */ (
         this.get('browser.enable_spellchecking', this.prefs));
-    return pref.value === false;
+    return pref.enforcement == chrome.settingsPrivate.Enforcement.ENFORCED &&
+        pref.value === false;
   },
 
   /**
@@ -534,7 +535,7 @@
 
   /** @private */
   updateSpellcheckEnabled_: function() {
-    this.set('spellCheckDisabled_', this.getSpellCheckDisabled_());
+    this.set('spellCheckDisabled_', this.getSpellCheckDisabledByPolicy_());
 
     // If the spellcheck section was expanded, close it.
     if (this.spellCheckDisabled_)
diff --git a/chrome/browser/sync/test/integration/single_client_directory_sync_test.cc b/chrome/browser/sync/test/integration/single_client_directory_sync_test.cc
index db35c11..4cec26c 100644
--- a/chrome/browser/sync/test/integration/single_client_directory_sync_test.cc
+++ b/chrome/browser/sync/test/integration/single_client_directory_sync_test.cc
@@ -13,6 +13,7 @@
 #include "base/threading/thread_restrictions.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
+#include "build/build_config.h"
 #include "chrome/browser/sync/test/integration/bookmarks_helper.h"
 #include "chrome/browser/sync/test/integration/single_client_status_change_checker.h"
 #include "chrome/browser/sync/test/integration/sync_test.h"
@@ -101,10 +102,17 @@
 // Verify that when the sync directory's backing store becomes corrupted, we
 // trigger an unrecoverable error and delete the database.
 //
+// TODO(treib): Update the below comment; it refers to something that does
+// not exist.
 // If this test fails, see the definition of kNumEntriesRequiredForCorruption
 // for one possible cause.
+#if defined(OS_MACOSX)
+#define MAYBE_DeleteDirectoryWhenCorrupted DISABLED_DeleteDirectoryWhenCorrupted
+#else
+#define MAYBE_DeleteDirectoryWhenCorrupted DeleteDirectoryWhenCorrupted
+#endif
 IN_PROC_BROWSER_TEST_F(SingleClientDirectorySyncTest,
-                       DeleteDirectoryWhenCorrupted) {
+                       MAYBE_DeleteDirectoryWhenCorrupted) {
   ASSERT_TRUE(SetupClients()) << "SetupClients() failed.";
   // Sync and wait for syncing to complete.
   ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
diff --git a/chrome/browser/task_manager/task_manager_browsertest.cc b/chrome/browser/task_manager/task_manager_browsertest.cc
index ec0c3e0..285e062 100644
--- a/chrome/browser/task_manager/task_manager_browsertest.cc
+++ b/chrome/browser/task_manager/task_manager_browsertest.cc
@@ -982,8 +982,7 @@
       MatchSubframe("http://e.com/"), ColumnSpecifier::MEMORY_FOOTPRINT, 1000));
 }
 
-// Flaky, see https://crbug.com/797860.
-IN_PROC_BROWSER_TEST_P(TaskManagerOOPIFBrowserTest, DISABLED_KillSubframe) {
+IN_PROC_BROWSER_TEST_P(TaskManagerOOPIFBrowserTest, KillSubframe) {
   ShowTaskManager();
 
   content::TestNavigationObserver navigation_observer(
diff --git a/chrome/browser/themes/theme_properties.cc b/chrome/browser/themes/theme_properties.cc
index 97bfb81..b4c15995 100644
--- a/chrome/browser/themes/theme_properties.cc
+++ b/chrome/browser/themes/theme_properties.cc
@@ -154,7 +154,7 @@
     case ThemeProperties::COLOR_FRAME:
     case ThemeProperties::COLOR_FRAME_INACTIVE:
     case ThemeProperties::COLOR_BACKGROUND_TAB:
-      return incognito ? gfx::kGoogleGrey900 : gfx::kGoogleGrey200;
+      return incognito ? gfx::kGoogleGrey900 : SkColorSetRGB(0xDE, 0xE1, 0xE6);
     case ThemeProperties::COLOR_TOOLBAR:
       return incognito ? SkColorSetRGB(0x32, 0x36, 0x39) : SK_ColorWHITE;
 
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index b7ba043..6ee6204 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -75,10 +75,6 @@
       "cocoa/autofill/autofill_tooltip_controller.mm",
       "cocoa/autofill/credit_card_autofill_touch_bar_controller.h",
       "cocoa/autofill/credit_card_autofill_touch_bar_controller.mm",
-      "cocoa/autofill/password_generation_popup_view_bridge.h",
-      "cocoa/autofill/password_generation_popup_view_bridge.mm",
-      "cocoa/autofill/password_generation_popup_view_cocoa.h",
-      "cocoa/autofill/password_generation_popup_view_cocoa.mm",
       "cocoa/autofill/save_card_bubble_view_views.h",
       "cocoa/autofill/save_card_bubble_view_views.mm",
       "cocoa/background_gradient_view.h",
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 410f5bb..411dc04 100644
--- a/chrome/browser/ui/app_list/app_list_client_impl.cc
+++ b/chrome/browser/ui/app_list/app_list_client_impl.cc
@@ -71,9 +71,9 @@
   return g_app_list_client_instance;
 }
 
-void AppListClientImpl::StartSearch(const base::string16& raw_query) {
+void AppListClientImpl::StartSearch(const base::string16& trimmed_query) {
   if (search_controller_) {
-    search_controller_->Start(raw_query);
+    search_controller_->Start(trimmed_query);
     controller_delegate_.OnSearchStarted();
   }
 }
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 b1e8715e..de9a133 100644
--- a/chrome/browser/ui/app_list/app_list_client_impl.h
+++ b/chrome/browser/ui/app_list/app_list_client_impl.h
@@ -42,7 +42,7 @@
   static AppListClientImpl* GetInstance();
 
   // ash::mojom::AppListClient:
-  void StartSearch(const base::string16& raw_query) override;
+  void StartSearch(const base::string16& trimmed_query) override;
   void OpenSearchResult(const std::string& result_id, int event_flags) override;
   void InvokeSearchResultAction(const std::string& result_id,
                                 int action_index,
diff --git a/chrome/browser/ui/app_list/search/search_controller.cc b/chrome/browser/ui/app_list/search/search_controller.cc
index 9b02e7b6..4f84a1c 100644
--- a/chrome/browser/ui/app_list/search/search_controller.cc
+++ b/chrome/browser/ui/app_list/search/search_controller.cc
@@ -24,12 +24,7 @@
 
 SearchController::~SearchController() {}
 
-void SearchController::Start(const base::string16& raw_query) {
-  last_raw_query_ = raw_query;
-
-  base::string16 query;
-  base::TrimWhitespace(raw_query, base::TRIM_ALL, &query);
-
+void SearchController::Start(const base::string16& query) {
   dispatching_query_ = true;
   for (const auto& provider : providers_)
     provider->Start(query);
diff --git a/chrome/browser/ui/app_list/search/search_controller.h b/chrome/browser/ui/app_list/search/search_controller.h
index 7c72876..c088d23c 100644
--- a/chrome/browser/ui/app_list/search/search_controller.h
+++ b/chrome/browser/ui/app_list/search/search_controller.h
@@ -30,8 +30,7 @@
   explicit SearchController(AppListModelUpdater* model_updater);
   virtual ~SearchController();
 
-  // TODO(hejq): can we accept a trimmed query here?
-  void Start(const base::string16& raw_query);
+  void Start(const base::string16& query);
 
   void OpenResult(ChromeSearchResult* result, int event_flags);
   void InvokeResultAction(ChromeSearchResult* result,
@@ -51,8 +50,6 @@
   // Invoked when the search results are changed.
   void OnResultsChanged();
 
-  base::string16 last_raw_query_;
-
   bool dispatching_query_ = false;
 
   // If true, the search results are shown on the launcher start page.
diff --git a/chrome/browser/ui/ash/launcher/internal_app_window_shelf_controller.cc b/chrome/browser/ui/ash/launcher/internal_app_window_shelf_controller.cc
index c770ba0..d47bbb92 100644
--- a/chrome/browser/ui/ash/launcher/internal_app_window_shelf_controller.cc
+++ b/chrome/browser/ui/ash/launcher/internal_app_window_shelf_controller.cc
@@ -44,8 +44,8 @@
   views::Widget* widget = views::Widget::GetWidgetForNativeWindow(window);
   if (!widget || !widget->is_top_level())
     return;
-  observed_windows_.push_back(window);
 
+  observed_windows_.push_back(window);
   window->AddObserver(this);
 }
 
@@ -73,6 +73,12 @@
   if (!visible)
     return;
 
+  // Skip OnWindowVisibilityChanged for ancestors/descendants.
+  auto it =
+      std::find(observed_windows_.begin(), observed_windows_.end(), window);
+  if (it == observed_windows_.end())
+    return;
+
   ash::ShelfID shelf_id =
       ash::ShelfID::Deserialize(window->GetProperty(ash::kShelfIDKey));
   if (shelf_id.IsNull() || !app_list::IsInternalApp(shelf_id.app_id))
diff --git a/chrome/browser/ui/cocoa/autofill/password_generation_popup_view_bridge.h b/chrome/browser/ui/cocoa/autofill/password_generation_popup_view_bridge.h
deleted file mode 100644
index 119b63e..0000000
--- a/chrome/browser/ui/cocoa/autofill/password_generation_popup_view_bridge.h
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_COCOA_AUTOFILL_PASSWORD_GENERATION_POPUP_VIEW_BRIDGE_H_
-#define CHROME_BROWSER_UI_COCOA_AUTOFILL_PASSWORD_GENERATION_POPUP_VIEW_BRIDGE_H_
-
-#include <vector>
-
-#include "base/compiler_specific.h"
-#include "base/mac/scoped_nsobject.h"
-#include "base/macros.h"
-#include "chrome/browser/ui/passwords/password_generation_popup_view.h"
-
-@class PasswordGenerationPopupViewCocoa;
-
-namespace autofill {
-
-// Mac implementation for PasswordGenerationPopupView interface.
-// Serves as a bridge to an instance of the Objective-C class which actually
-// implements the view.
-class PasswordGenerationPopupViewBridge : public PasswordGenerationPopupView {
- public:
-  explicit PasswordGenerationPopupViewBridge(
-      PasswordGenerationPopupController* controller);
-
- private:
-  virtual ~PasswordGenerationPopupViewBridge();
-
-  // PasswordGenerationPopupView implementation.
-  void Hide() override;
-  void Show() override;
-  gfx::Size GetPreferredSizeOfPasswordView() override;
-  void UpdateBoundsAndRedrawPopup() override;
-  void PasswordSelectionUpdated() override;
-  bool IsPointInPasswordBounds(const gfx::Point& point) override;
-
-  // The native Cocoa view.
-  base::scoped_nsobject<PasswordGenerationPopupViewCocoa> view_;
-
-  DISALLOW_COPY_AND_ASSIGN(PasswordGenerationPopupViewBridge);
-};
-
-}  // namespace autofill
-
-#endif  // CHROME_BROWSER_UI_COCOA_AUTOFILL_PASSWORD_GENERATION_POPUP_VIEW_BRIDGE_H_
diff --git a/chrome/browser/ui/cocoa/autofill/password_generation_popup_view_bridge.mm b/chrome/browser/ui/cocoa/autofill/password_generation_popup_view_bridge.mm
deleted file mode 100644
index c0dc945..0000000
--- a/chrome/browser/ui/cocoa/autofill/password_generation_popup_view_bridge.mm
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import <Cocoa/Cocoa.h>
-
-#include "chrome/browser/ui/cocoa/autofill/password_generation_popup_view_bridge.h"
-
-#include "base/logging.h"
-#include "chrome/browser/ui/autofill/autofill_popup_controller.h"
-#import "chrome/browser/ui/cocoa/autofill/password_generation_popup_view_cocoa.h"
-#include "ui/base/ui_features.h"
-#include "ui/gfx/geometry/size.h"
-
-namespace autofill {
-
-PasswordGenerationPopupViewBridge::PasswordGenerationPopupViewBridge(
-    PasswordGenerationPopupController* controller) {
-  view_.reset(
-      [[PasswordGenerationPopupViewCocoa alloc]
-          initWithController:controller
-                       frame:NSZeroRect]);
-}
-
-PasswordGenerationPopupViewBridge::~PasswordGenerationPopupViewBridge() {
-  [view_ controllerDestroyed];
-  [view_ hidePopup];
-}
-
-void PasswordGenerationPopupViewBridge::Hide() {
-  delete this;
-}
-
-void PasswordGenerationPopupViewBridge::Show() {
-  [view_ showPopup];
-}
-
-gfx::Size PasswordGenerationPopupViewBridge::GetPreferredSizeOfPasswordView() {
-  return gfx::Size(NSSizeToCGSize([view_ preferredSize]));
-}
-
-void PasswordGenerationPopupViewBridge::UpdateBoundsAndRedrawPopup() {
-  [view_ updateBoundsAndRedrawPopup];
-}
-
-void PasswordGenerationPopupViewBridge::PasswordSelectionUpdated() {
-  [view_ setNeedsDisplay:YES];
-}
-
-bool PasswordGenerationPopupViewBridge::IsPointInPasswordBounds(
-    const gfx::Point& point) {
-  return [view_ isPointInPasswordBounds:NSPointFromCGPoint(point.ToCGPoint())];
-}
-
-PasswordGenerationPopupView* PasswordGenerationPopupView::CreateCocoa(
-    PasswordGenerationPopupController* controller) {
-  return new PasswordGenerationPopupViewBridge(controller);
-}
-
-#if !BUILDFLAG(MAC_VIEWS_BROWSER)
-PasswordGenerationPopupView* PasswordGenerationPopupView::Create(
-    PasswordGenerationPopupController* controller) {
-  return CreateCocoa(controller);
-}
-#endif
-
-}  // namespace autofill
diff --git a/chrome/browser/ui/cocoa/autofill/password_generation_popup_view_cocoa.h b/chrome/browser/ui/cocoa/autofill/password_generation_popup_view_cocoa.h
deleted file mode 100644
index 19c312f..0000000
--- a/chrome/browser/ui/cocoa/autofill/password_generation_popup_view_cocoa.h
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_COCOA_AUTOFILL_PASSWORD_GENERATION_POPUP_VIEW_COCOA_H_
-#define CHROME_BROWSER_UI_COCOA_AUTOFILL_PASSWORD_GENERATION_POPUP_VIEW_COCOA_H_
-
-#import <Cocoa/Cocoa.h>
-
-#include "base/mac/scoped_nsobject.h"
-#import "chrome/browser/ui/cocoa/autofill/autofill_popup_base_view_cocoa.h"
-#include "chrome/browser/ui/passwords/password_generation_popup_controller.h"
-#import "ui/base/cocoa/tracking_area.h"
-
-@class HyperlinkTextView;
-
-// Draws the native password generation popup view on Mac.
-@interface PasswordGenerationPopupViewCocoa
-    : AutofillPopupBaseViewCocoa <NSTextViewDelegate> {
- @private
-  // The cross-platform controller for this view.
-  autofill::PasswordGenerationPopupController* controller_;  // weak
-
-  base::scoped_nsobject<NSView> passwordSection_;
-  base::scoped_nsobject<NSTextField> passwordField_;
-  base::scoped_nsobject<NSTextField> passwordTitleField_;
-  base::scoped_nsobject<NSImageView> keyIcon_;
-  base::scoped_nsobject<NSBox> divider_;
-  base::scoped_nsobject<HyperlinkTextView> helpTextView_;
-  ui::ScopedCrTrackingArea helpTextTrackingArea_;
-}
-
-// Designated initializer.
-- (id)initWithController:
-    (autofill::PasswordGenerationPopupController*)controller
-                   frame:(NSRect)frame;
-
-// Determines whether |point| falls inside the password section of the popup.
-// |point| needs to be in the popup's coordinate system.
-- (BOOL)isPointInPasswordBounds:(NSPoint)point;
-
-// Informs the view that its controller has been (or will imminently be)
-// destroyed.
-- (void)controllerDestroyed;
-
-// The preferred size for the popup.
-- (NSSize)preferredSize;
-
-@end
-
-#endif  // CHROME_BROWSER_UI_COCOA_AUTOFILL_PASSWORD_GENERATION_POPUP_VIEW_COCOA_H_
diff --git a/chrome/browser/ui/cocoa/autofill/password_generation_popup_view_cocoa.mm b/chrome/browser/ui/cocoa/autofill/password_generation_popup_view_cocoa.mm
deleted file mode 100644
index 3544d26..0000000
--- a/chrome/browser/ui/cocoa/autofill/password_generation_popup_view_cocoa.mm
+++ /dev/null
@@ -1,361 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "chrome/browser/ui/cocoa/autofill/password_generation_popup_view_cocoa.h"
-
-#include <cmath>
-
-#include "base/logging.h"
-#include "base/strings/sys_string_conversions.h"
-#include "chrome/app/vector_icons/vector_icons.h"
-#include "chrome/browser/ui/autofill/autofill_popup_controller.h"
-#include "chrome/browser/ui/autofill/autofill_popup_view.h"
-#include "chrome/browser/ui/autofill/popup_constants.h"
-#include "chrome/browser/ui/cocoa/autofill/password_generation_popup_view_bridge.h"
-#include "chrome/browser/ui/cocoa/chrome_style.h"
-#include "components/autofill/core/browser/popup_item_ids.h"
-#include "skia/ext/skia_utils_mac.h"
-#import "ui/base/cocoa/controls/hyperlink_text_view.h"
-#include "ui/base/resource/resource_bundle.h"
-#include "ui/gfx/color_palette.h"
-#include "ui/gfx/font_list.h"
-#include "ui/gfx/geometry/point.h"
-#include "ui/gfx/geometry/rect.h"
-#include "ui/gfx/image/image.h"
-#include "ui/gfx/image/image_skia_util_mac.h"
-#include "ui/gfx/paint_vector_icon.h"
-#include "ui/gfx/range/range.h"
-#include "ui/gfx/text_constants.h"
-
-using autofill::AutofillPopupView;
-using autofill::PasswordGenerationPopupController;
-using autofill::PasswordGenerationPopupView;
-using base::scoped_nsobject;
-
-namespace {
-
-// The height of the divider between the password and help sections, in pixels.
-const CGFloat kDividerHeight = 1;
-
-// The amount of whitespace, in pixels, between lines of text in the password
-// section.
-const CGFloat kPasswordSectionVerticalSeparation = 5;
-
-NSColor* DividerColor() {
-  return skia::SkColorToCalibratedNSColor(
-      PasswordGenerationPopupView::kDividerColor);
-}
-
-NSColor* HelpTextBackgroundColor() {
-  return skia::SkColorToCalibratedNSColor(
-      PasswordGenerationPopupView::kExplanatoryTextBackgroundColor);
-}
-
-NSColor* HelpTextColor() {
-  return skia::SkColorToCalibratedNSColor(
-      PasswordGenerationPopupView::kExplanatoryTextColor);
-}
-
-NSColor* HelpLinkColor() {
-  return skia::SkColorToCalibratedNSColor(chrome_style::GetLinkColor());
-}
-
-}  // namespace
-
-@implementation PasswordGenerationPopupViewCocoa
-
-#pragma mark Initialisers
-
-- (id)initWithFrame:(NSRect)frame {
-  NOTREACHED();
-  return nil;
-}
-
-- (id)initWithController:
-    (autofill::PasswordGenerationPopupController*)controller
-                   frame:(NSRect)frame {
-  if (self = [super initWithDelegate:controller frame:frame]) {
-    controller_ = controller;
-
-    passwordSection_.reset([[NSView alloc] initWithFrame:NSZeroRect]);
-    [self addSubview:passwordSection_];
-
-    passwordField_.reset(
-        [[self textFieldWithText:controller_->password()
-                      attributes:[self passwordAttributes]] retain]);
-    [passwordSection_ addSubview:passwordField_];
-
-    passwordTitleField_.reset(
-        [[self textFieldWithText:controller_->SuggestedText()
-                      attributes:[self passwordTitleAttributes]] retain]);
-    [passwordSection_ addSubview:passwordTitleField_];
-
-    keyIcon_.reset([[NSImageView alloc] initWithFrame:NSZeroRect]);
-    NSImage* keyImage = NSImageFromImageSkia(
-        gfx::CreateVectorIcon(kKeyIcon, 16, gfx::kChromeIconGrey));
-
-    [keyIcon_ setImage:keyImage];
-    [passwordSection_ addSubview:keyIcon_];
-
-    divider_.reset([[NSBox alloc] initWithFrame:NSZeroRect]);
-    [divider_ setBoxType:NSBoxCustom];
-    [divider_ setBorderType:NSLineBorder];
-    [divider_ setBorderColor:DividerColor()];
-    [self addSubview:divider_];
-
-    helpTextView_.reset([[HyperlinkTextView alloc] initWithFrame:NSZeroRect]);
-    [helpTextView_ setMessage:base::SysUTF16ToNSString(controller_->HelpText())
-                     withFont:[self textFont]
-                 messageColor:HelpTextColor()];
-    [helpTextView_ addLinkRange:controller_->HelpTextLinkRange().ToNSRange()
-                        withURL:nil
-                      linkColor:HelpLinkColor()];
-    [helpTextView_ setDelegate:self];
-    [helpTextView_ setDrawsBackground:YES];
-    [helpTextView_ setBackgroundColor:HelpTextBackgroundColor()];
-    [helpTextView_
-        setTextContainerInset:NSMakeSize(controller_->kHorizontalPadding,
-                                         controller_->kHelpVerticalPadding)];
-    // Remove the underlining.
-    NSTextStorage* text = [helpTextView_ textStorage];
-    [text addAttribute:NSUnderlineStyleAttributeName
-                 value:@(NSUnderlineStyleNone)
-                 range:controller_->HelpTextLinkRange().ToNSRange()];
-    [self addSubview:helpTextView_];
-}
-
-  return self;
-}
-
-- (void)updateTrackingAreas {
-  [super updateTrackingAreas];
-  if (helpTextTrackingArea_.get())
-    [self removeTrackingArea:helpTextTrackingArea_.get()];
-
-  // Set up tracking for the help text so the cursor, etc. is properly handled.
-  // Must set tracking to "always" because the autofill window is never key.
-  NSTrackingAreaOptions options = NSTrackingActiveAlways |
-                                  NSTrackingMouseEnteredAndExited |
-                                  NSTrackingMouseMoved |
-                                  NSTrackingCursorUpdate;
-  helpTextTrackingArea_.reset(
-      [[CrTrackingArea alloc] initWithRect:[self bounds]
-                                   options:options
-                                     owner:helpTextView_.get()
-                                  userInfo:nil]);
-
-  [self addTrackingArea:helpTextTrackingArea_.get()];
-}
-
-#pragma mark NSView implementation:
-
-- (void)drawRect:(NSRect)dirtyRect {
-  [super drawRect:dirtyRect];
-
-  // If the view is in the process of being destroyed, don't bother drawing.
-  if (!controller_)
-    return;
-
-  [self drawBackgroundAndBorder];
-
-  if (controller_->password_selected()) {
-    // Draw a highlight under the suggested password.
-    NSRect highlightBounds = [passwordSection_ frame];
-    [[self highlightColor] set];
-    [NSBezierPath fillRect:highlightBounds];
-  }
-}
-
-#pragma mark Public API:
-
-- (NSSize)preferredSize {
-  const NSSize passwordTitleSize =
-      [base::SysUTF16ToNSString(controller_->SuggestedText())
-          sizeWithAttributes:@{ NSFontAttributeName : [self boldFont] }];
-  const NSSize passwordSize = [base::SysUTF16ToNSString(controller_->password())
-      sizeWithAttributes:@{ NSFontAttributeName : [self textFont] }];
-
-  CGFloat width =
-      autofill::kPopupBorderThickness +
-      controller_->kHorizontalPadding +
-      [[keyIcon_ image] size].width +
-      controller_->kHorizontalPadding +
-      std::max(passwordSize.width, passwordTitleSize.width) +
-      controller_->kHorizontalPadding +
-      autofill::kPopupBorderThickness;
-
-  width = std::max(width, (CGFloat)controller_->GetMinimumWidth());
-  CGFloat contentWidth = width - (2 * controller_->kHorizontalPadding);
-
-  CGFloat height =
-      autofill::kPopupBorderThickness +
-      controller_->kHelpVerticalPadding +
-      [self helpSizeForPopupWidth:contentWidth].height +
-      controller_->kHelpVerticalPadding +
-      autofill::kPopupBorderThickness;
-
-  if (controller_->display_password())
-    height += controller_->kPopupPasswordSectionHeight;
-
-  return NSMakeSize(width, height);
-}
-
-- (void)updateBoundsAndRedrawPopup {
-  const CGFloat popupWidth = controller_->popup_bounds().width();
-  const CGFloat contentWidth =
-      popupWidth - (2 * autofill::kPopupBorderThickness);
-  const CGFloat contentHeight = controller_->popup_bounds().height() -
-                                (2 * autofill::kPopupBorderThickness);
-
-  if (controller_->display_password()) {
-    // The password can change while the bubble is shown: If the user has
-    // accepted the password and then selects the form again and starts deleting
-    // the password, the field will be initially invisible and then become
-    // visible.
-    [self updatePassword];
-
-    // Lay out the password section, which includes the key icon, the title, and
-    // the suggested password.
-    [passwordSection_
-        setFrame:NSMakeRect(autofill::kPopupBorderThickness,
-                            autofill::kPopupBorderThickness,
-                            contentWidth,
-                            controller_->kPopupPasswordSectionHeight)];
-
-    // The key icon falls to the left of the title and password.
-    const NSSize imageSize = [[keyIcon_ image] size];
-    const CGFloat keyX = controller_->kHorizontalPadding;
-    const CGFloat keyY =
-        std::ceil((controller_->kPopupPasswordSectionHeight / 2.0) -
-                  (imageSize.height / 2.0));
-    [keyIcon_ setFrame:{ NSMakePoint(keyX, keyY), imageSize }];
-
-    // The title and password fall to the right of the key icon and are centered
-    // vertically as a group with some padding in between.
-    [passwordTitleField_ sizeToFit];
-    [passwordField_ sizeToFit];
-    const CGFloat groupHeight = NSHeight([passwordField_ frame]) +
-                                kPasswordSectionVerticalSeparation +
-                                NSHeight([passwordTitleField_ frame]);
-    const CGFloat groupX =
-        NSMaxX([keyIcon_ frame]) + controller_->kHorizontalPadding;
-    const CGFloat groupY =
-        std::ceil((controller_->kPopupPasswordSectionHeight / 2.0) -
-                  (groupHeight / 2.0));
-    [passwordField_ setFrameOrigin:NSMakePoint(groupX, groupY)];
-    const CGFloat titleY = groupY +
-                           NSHeight([passwordField_ frame]) +
-                           kPasswordSectionVerticalSeparation;
-    [passwordTitleField_ setFrameOrigin:NSMakePoint(groupX, titleY)];
-
-    // Layout the divider, which falls immediately below the password section.
-    const CGFloat dividerX = autofill::kPopupBorderThickness;
-    const CGFloat dividerY = NSMaxY([passwordSection_ frame]);
-    NSRect dividerFrame =
-        NSMakeRect(dividerX, dividerY, contentWidth, kDividerHeight);
-    [divider_ setFrame:dividerFrame];
-  }
-
-  // Layout the help section beneath the divider (if applicable, otherwise
-  // beneath the border).
-  const CGFloat helpX = autofill::kPopupBorderThickness;
-  const CGFloat helpY = controller_->display_password()
-      ? NSMaxY([divider_ frame])
-      : autofill::kPopupBorderThickness;
-  const CGFloat helpHeight = contentHeight -
-                             NSHeight([passwordSection_ frame]) -
-                             NSHeight([divider_ frame]);
-  [helpTextView_ setFrame:NSMakeRect(helpX, helpY, contentWidth, helpHeight)];
-
-  [super updateBoundsAndRedrawPopup];
-}
-
-- (BOOL)isPointInPasswordBounds:(NSPoint)point {
-  return NSPointInRect(point, [passwordSection_ frame]);
-}
-
-- (void)controllerDestroyed {
-  controller_ = NULL;
-  [super delegateDestroyed];
-}
-
-#pragma mark NSTextViewDelegate implementation:
-
-- (BOOL)textView:(NSTextView*)textView
-   clickedOnLink:(id)link
-         atIndex:(NSUInteger)charIndex {
-  controller_->OnSavedPasswordsLinkClicked();
-  return YES;
-}
-
-#pragma mark Private helpers:
-
-- (void)updatePassword {
-  base::scoped_nsobject<NSMutableAttributedString> updatedPassword(
-      [[NSMutableAttributedString alloc]
-          initWithString:base::SysUTF16ToNSString(controller_->password())
-              attributes:[self passwordAttributes]]);
-  [passwordField_ setAttributedStringValue:updatedPassword];
-}
-
-- (NSDictionary*)passwordTitleAttributes {
-  scoped_nsobject<NSMutableParagraphStyle> paragraphStyle(
-      [[NSMutableParagraphStyle alloc] init]);
-  [paragraphStyle setAlignment:NSLeftTextAlignment];
-  return @{
-    NSFontAttributeName : [self boldFont],
-    NSForegroundColorAttributeName : [self nameColor],
-    NSParagraphStyleAttributeName : paragraphStyle.autorelease()
-  };
-}
-
-- (NSDictionary*)passwordAttributes {
-  scoped_nsobject<NSMutableParagraphStyle> paragraphStyle(
-      [[NSMutableParagraphStyle alloc] init]);
-  [paragraphStyle setAlignment:NSLeftTextAlignment];
-  return @{
-    NSFontAttributeName : [self textFont],
-    NSForegroundColorAttributeName : [self nameColor],
-    NSParagraphStyleAttributeName : paragraphStyle.autorelease()
-  };
-}
-
-- (NSTextField*)textFieldWithText:(const base::string16&)text
-                       attributes:(NSDictionary*)attributes {
-  NSTextField* textField =
-      [[[NSTextField alloc] initWithFrame:NSZeroRect] autorelease];
-  scoped_nsobject<NSAttributedString> attributedString(
-      [[NSAttributedString alloc]
-          initWithString:base::SysUTF16ToNSString(text)
-              attributes:attributes]);
-  [textField setAttributedStringValue:attributedString.autorelease()];
-  [textField setEditable:NO];
-  [textField setSelectable:NO];
-  [textField setDrawsBackground:NO];
-  [textField setBezeled:NO];
-  return textField;
-}
-
-- (NSSize)helpSizeForPopupWidth:(CGFloat)width {
-  const CGFloat helpWidth = width -
-                            2 * controller_->kHorizontalPadding -
-                            2 * autofill::kPopupBorderThickness;
-  const NSSize size = NSMakeSize(helpWidth, MAXFLOAT);
-  NSRect textFrame = [base::SysUTF16ToNSString(controller_->HelpText())
-      boundingRectWithSize:size
-                   options:NSLineBreakByWordWrapping |
-                           NSStringDrawingUsesLineFragmentOrigin
-                attributes:@{ NSFontAttributeName : [self textFont] }];
-  return textFrame.size;
-}
-
-- (NSFont*)boldFont {
-  return [NSFont boldSystemFontOfSize:[NSFont smallSystemFontSize]];
-}
-
-- (NSFont*)textFont {
-  return [NSFont systemFontOfSize:[NSFont smallSystemFontSize]];
-}
-
-@end
diff --git a/chrome/browser/ui/cocoa/autofill/password_generation_popup_view_cocoa_unittest.mm b/chrome/browser/ui/cocoa/autofill/password_generation_popup_view_cocoa_unittest.mm
deleted file mode 100644
index 84ca96a..0000000
--- a/chrome/browser/ui/cocoa/autofill/password_generation_popup_view_cocoa_unittest.mm
+++ /dev/null
@@ -1,131 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "chrome/browser/ui/cocoa/autofill/password_generation_popup_view_cocoa.h"
-
-#include <stddef.h>
-
-#include <memory>
-
-#include "base/macros.h"
-#include "base/strings/utf_string_conversions.h"
-#import "chrome/browser/ui/cocoa/test/cocoa_test_helper.h"
-#include "components/autofill/core/browser/suggestion.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/platform_test.h"
-#include "ui/gfx/font_list.h"
-#include "ui/gfx/geometry/rect_f.h"
-#include "ui/gfx/range/range.h"
-
-using testing::AtLeast;
-using testing::Return;
-
-namespace {
-
-class MockPasswordGenerationPopupController
-   : public autofill::PasswordGenerationPopupController {
- public:
-  MockPasswordGenerationPopupController()
-    : help_text_(base::ASCIIToUTF16("Help me if you can I'm feeling dooown")),
-      popup_bounds_(gfx::Rect(0, 0, 200, 100)) {}
-
-  MOCK_METHOD0(PasswordAccepted, void());
-
-  void OnSavedPasswordsLinkClicked() override {}
-
-  int GetMinimumWidth() override { return 200; }
-
-  bool display_password() const override { return true; }
-
-  bool password_selected() const override { return false; }
-
-  MOCK_CONST_METHOD0(password, base::string16());
-
-  base::string16 SuggestedText() override {
-    return base::ASCIIToUTF16("Suggested by Chrome");
-  }
-
-  const base::string16& HelpText() override { return help_text_; }
-
-  const gfx::Range& HelpTextLinkRange() override { return link_range_; }
-
-  // AutofillPopupViewDelegate implementation.
-  void Hide() override {}
-  MOCK_METHOD0(ViewDestroyed, void());
-  void SetSelectionAtPoint(const gfx::Point&) override {}
-  bool AcceptSelectedLine() override { return true; }
-  void SelectionCleared() override {}
-  bool HasSelection() const override { return password_selected(); }
-  gfx::Rect popup_bounds() const override { return popup_bounds_; }
-  MOCK_METHOD0(container_view, gfx::NativeView());
-  MOCK_CONST_METHOD0(element_bounds, gfx::RectF&());
-  MOCK_CONST_METHOD0(IsRTL, bool());
-  MOCK_METHOD0(GetSuggestions, const std::vector<autofill::Suggestion>());
-  void SetTypesetter(gfx::Typesetter Typesetter) override {}
-  MOCK_METHOD1(GetElidedValueWidthForRow, int(int));
-  MOCK_METHOD1(GetElidedLabelWidthForRow, int(int));
-
- private:
-  base::string16 help_text_;
-  gfx::Range link_range_;
-
-  const gfx::Rect popup_bounds_;
-
-  DISALLOW_COPY_AND_ASSIGN(MockPasswordGenerationPopupController);
-};
-
-class PasswordGenerationPopupViewCocoaTest : public CocoaTest {
- protected:
-  PasswordGenerationPopupViewCocoaTest()
-    : password_(base::ASCIIToUTF16("wow! such password"))
-  {}
-
-  void SetUp() override {
-    mock_controller_.reset(new MockPasswordGenerationPopupController);
-    EXPECT_CALL(*mock_controller_, password())
-        .WillRepeatedly(Return(password_));
-
-    view_.reset([[PasswordGenerationPopupViewCocoa alloc]
-        initWithController:mock_controller_.get()
-                     frame:NSZeroRect]);
-
-    NSView* contentView = [test_window() contentView];
-    [contentView addSubview:view_];
-    EXPECT_CALL(*mock_controller_, container_view())
-        .WillRepeatedly(Return(contentView));
-  }
-
-  base::string16 password_;
-  std::unique_ptr<MockPasswordGenerationPopupController> mock_controller_;
-  base::scoped_nsobject<PasswordGenerationPopupViewCocoa> view_;
-};
-
-TEST_VIEW(PasswordGenerationPopupViewCocoaTest, view_);
-
-TEST_F(PasswordGenerationPopupViewCocoaTest, ShowAndHide) {
-  // Verify that the view fetches a password from the controller.
-  EXPECT_CALL(*mock_controller_, password()).Times(AtLeast(1))
-      .WillRepeatedly(Return(password_));
-
-  view_.reset([[PasswordGenerationPopupViewCocoa alloc]
-      initWithController:mock_controller_.get()
-                   frame:NSZeroRect]);
-
-  [view_ showPopup];
-  [view_ display];
-  [view_ hidePopup];
-}
-
-// Verifies that it doesn't crash when the controller is destroyed before the
-// popup is hidden.
-TEST_F(PasswordGenerationPopupViewCocoaTest, ControllerDestroyed) {
-  [view_ showPopup];
-  mock_controller_.reset();
-  [view_ controllerDestroyed];
-  [view_ display];
-  [view_ hidePopup];
-}
-
-}  // namespace
diff --git a/chrome/browser/ui/layout_constants.cc b/chrome/browser/ui/layout_constants.cc
index f6763ba5..ebcb834 100644
--- a/chrome/browser/ui/layout_constants.cc
+++ b/chrome/browser/ui/layout_constants.cc
@@ -63,8 +63,6 @@
     }
     case LOCATION_BAR_ICON_SIZE:
       return touch_optimized_material ? 20 : 16;
-    case LOCATION_BAR_ICON_INTERIOR_PADDING:
-      return touch_optimized_material ? 5 : 4;
     case TAB_AFTER_TITLE_PADDING:
       return touch_optimized_material ? 8 : 4;
     case TAB_ALERT_INDICATOR_CAPTURE_ICON_WIDTH:
@@ -100,7 +98,18 @@
 
 gfx::Insets GetLayoutInsets(LayoutInset inset) {
   const int mode = ui::MaterialDesignController::GetMode();
+  const bool touch_optimized_material =
+      ui::MaterialDesignController::IsTouchOptimizedUiEnabled();
   switch (inset) {
+    case LOCATION_BAR_ICON_INTERIOR_PADDING: {
+      if (ui::MaterialDesignController::IsRefreshUi()) {
+        return touch_optimized_material ? gfx::Insets(5, 10)
+                                        : gfx::Insets(4, 8);
+      }
+
+      return touch_optimized_material ? gfx::Insets(5) : gfx::Insets(4);
+    }
+
     case TAB: {
       // TODO(pkasting): This should disappear; the horizontal portion should
       // be computed in tab.cc, and the vertical portion become a standalone
@@ -109,8 +118,7 @@
       return gfx::Insets(1, kTabHorizontalInset[mode]);
     }
     case TOOLBAR_BUTTON:
-      return gfx::Insets(
-          ui::MaterialDesignController::IsTouchOptimizedUiEnabled() ? 12 : 6);
+      return gfx::Insets(touch_optimized_material ? 12 : 6);
 
     case TOOLBAR_ACTION_VIEW: {
       // TODO(afakhry): Unify all toolbar button sizes on all platforms.
diff --git a/chrome/browser/ui/layout_constants.h b/chrome/browser/ui/layout_constants.h
index 2a12a2b..306bbdb8 100644
--- a/chrome/browser/ui/layout_constants.h
+++ b/chrome/browser/ui/layout_constants.h
@@ -61,13 +61,6 @@
   // The size of the icons used inside the LocationBar.
   LOCATION_BAR_ICON_SIZE,
 
-  // The amount of padding used around the icon inside the LocationBar, i.e. the
-  // full width of a LocationBar icon will be LOCATION_BAR_ICON_SIZE + 2 *
-  // LOCATION_BAR_ICON_INTERIOR_PADDING. Icons may additionally be spaced
-  // horizontally by LOCATION_BAR_ELEMENT_PADDING, but this region is not part
-  // of the icon view (e.g. does not highlight on hover).
-  LOCATION_BAR_ICON_INTERIOR_PADDING,
-
   // Padding after the tab title.
   TAB_AFTER_TITLE_PADDING,
 
@@ -106,6 +99,14 @@
 };
 
 enum LayoutInset {
+  // The padding used around the icon inside the LocationBar. The full width of
+  // the icon would be LOCATION_BAR_ICON_SIZE + 2 * inset.width(). The full
+  // height of the icon would be LOCATION_BAR_ICON_SIZE + 2 * inset.height().
+  // Icons may additionally be spaced horizontally by
+  // LOCATION_BAR_ELEMENT_PADDING, but this region is not part of the icon view
+  // (e.g. does not highlight on hover).
+  LOCATION_BAR_ICON_INTERIOR_PADDING,
+
   // The padding inside the tab bounds that defines the tab contents region.
   TAB,
 
diff --git a/chrome/browser/ui/location_bar/OWNERS b/chrome/browser/ui/location_bar/OWNERS
new file mode 100644
index 0000000..90b1b756
--- /dev/null
+++ b/chrome/browser/ui/location_bar/OWNERS
@@ -0,0 +1,3 @@
+file://components/omnibox/OWNERS
+
+# COMPONENT: UI>Browser>Omnibox
diff --git a/chrome/browser/ui/omnibox/OWNERS b/chrome/browser/ui/omnibox/OWNERS
index 0177dca..90b1b756 100644
--- a/chrome/browser/ui/omnibox/OWNERS
+++ b/chrome/browser/ui/omnibox/OWNERS
@@ -1,7 +1,3 @@
-jdonnelly@chromium.org
-pkasting@chromium.org
-mpearson@chromium.org
-sky@chromium.org
-tommycli@chromium.org
+file://components/omnibox/OWNERS
 
 # COMPONENT: UI>Browser>Omnibox
diff --git a/chrome/browser/ui/passwords/password_generation_popup_view.h b/chrome/browser/ui/passwords/password_generation_popup_view.h
index eae49db..6cf37010 100644
--- a/chrome/browser/ui/passwords/password_generation_popup_view.h
+++ b/chrome/browser/ui/passwords/password_generation_popup_view.h
@@ -5,7 +5,6 @@
 #ifndef CHROME_BROWSER_UI_PASSWORDS_PASSWORD_GENERATION_POPUP_VIEW_H_
 #define CHROME_BROWSER_UI_PASSWORDS_PASSWORD_GENERATION_POPUP_VIEW_H_
 
-#include "build/build_config.h"
 #include "third_party/skia/include/core/SkColor.h"
 
 namespace gfx {
@@ -44,12 +43,6 @@
   // when Hide() is called.
   static PasswordGenerationPopupView* Create(
       PasswordGenerationPopupController* controller);
-#if defined(OS_MACOSX)
-  // Temporary shim for Polychrome. See bottom of first comment in
-  // https://crbug.com/804950 for details
-  static PasswordGenerationPopupView* CreateCocoa(
-      PasswordGenerationPopupController* controller);
-#endif
 
   static const SkColor kPasswordTextColor;
   static const SkColor kExplanatoryTextBackgroundColor;
diff --git a/chrome/browser/ui/passwords/password_generation_popup_view_browsertest.cc b/chrome/browser/ui/passwords/password_generation_popup_view_browsertest.cc
index dd0df996..e753aee 100644
--- a/chrome/browser/ui/passwords/password_generation_popup_view_browsertest.cc
+++ b/chrome/browser/ui/passwords/password_generation_popup_view_browsertest.cc
@@ -5,7 +5,6 @@
 #include "chrome/browser/ui/passwords/password_generation_popup_view.h"
 
 #include "base/strings/string16.h"
-#include "build/build_config.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/passwords/password_generation_popup_controller_impl.h"
@@ -57,8 +56,6 @@
   TestPasswordGenerationPopupController* controller_;
 };
 
-// TODO(gcasto): Enable on Mac when UI is updated. (crbug.com/394303)
-#if !defined(OS_MACOSX)
 // Regression test for crbug.com/400543. Verifying that moving the mouse in the
 // editing dialog doesn't crash.
 IN_PROC_BROWSER_TEST_F(PasswordGenerationPopupViewTest,
@@ -84,7 +81,6 @@
       GetWebContents(), NULL);
   controller_->Show(true /* display password */);
 }
-#endif
 
 // Verify that destroying web contents with visible popup does not crash.
 IN_PROC_BROWSER_TEST_F(PasswordGenerationPopupViewTest,
diff --git a/chrome/browser/ui/views/location_bar/OWNERS b/chrome/browser/ui/views/location_bar/OWNERS
index 19ed0d9..fe2b68db 100644
--- a/chrome/browser/ui/views/location_bar/OWNERS
+++ b/chrome/browser/ui/views/location_bar/OWNERS
@@ -1,4 +1,4 @@
 estade@chromium.org
-pkasting@chromium.org
+file://components/omnibox/OWNERS
 
 # COMPONENT: UI>Browser>Omnibox
diff --git a/chrome/browser/ui/views/location_bar/icon_label_bubble_view.cc b/chrome/browser/ui/views/location_bar/icon_label_bubble_view.cc
index 2ae9adf..0936b19 100644
--- a/chrome/browser/ui/views/location_bar/icon_label_bubble_view.cc
+++ b/chrome/browser/ui/views/location_bar/icon_label_bubble_view.cc
@@ -135,7 +135,7 @@
   // content bounds so the background gets painted correctly.
   SetBorder(views::CreateEmptyBorder(
       gfx::Insets(GetLayoutConstant(LOCATION_BAR_BUBBLE_VERTICAL_PADDING),
-                  GetLayoutConstant(LOCATION_BAR_ICON_INTERIOR_PADDING))));
+                  GetLayoutInsets(LOCATION_BAR_ICON_INTERIOR_PADDING).left())));
 
   set_notify_enter_exit_on_child(true);
 
@@ -419,7 +419,7 @@
   return ui::MaterialDesignController::IsTouchOptimizedUiEnabled()
              ? kIconLabelSpacingTouch
              : GetLayoutConstant(LOCATION_BAR_ELEMENT_PADDING) +
-                   GetLayoutConstant(LOCATION_BAR_ICON_INTERIOR_PADDING);
+                   GetLayoutInsets(LOCATION_BAR_ICON_INTERIOR_PADDING).left();
 }
 
 int IconLabelBubbleView::GetSeparatorLayoutWidth() const {
diff --git a/chrome/browser/ui/views/location_bar/icon_label_bubble_view_unittest.cc b/chrome/browser/ui/views/location_bar/icon_label_bubble_view_unittest.cc
index 4fc18882..c9ea4e6 100644
--- a/chrome/browser/ui/views/location_bar/icon_label_bubble_view_unittest.cc
+++ b/chrome/browser/ui/views/location_bar/icon_label_bubble_view_unittest.cc
@@ -83,7 +83,7 @@
     return !IsShrinking() ||
            (width() >
             (image()->GetPreferredSize().width() +
-             2 * GetLayoutConstant(LOCATION_BAR_ICON_INTERIOR_PADDING) +
+             GetLayoutInsets(LOCATION_BAR_ICON_INTERIOR_PADDING).width() +
              2 * GetLayoutConstant(LOCATION_BAR_ELEMENT_PADDING)));
   }
 
@@ -194,7 +194,7 @@
     minimum_size_reached_ = false;
     previous_width_ = 0;
     initial_image_x_ = GetImageBounds().x();
-    EXPECT_EQ(GetLayoutConstant(LOCATION_BAR_ICON_INTERIOR_PADDING),
+    EXPECT_EQ(GetLayoutInsets(LOCATION_BAR_ICON_INTERIOR_PADDING).left(),
               initial_image_x_);
   }
 
diff --git a/chrome/browser/ui/views/location_bar/keyword_hint_view.cc b/chrome/browser/ui/views/location_bar/keyword_hint_view.cc
index 893f537..d2d8c2f 100644
--- a/chrome/browser/ui/views/location_bar/keyword_hint_view.cc
+++ b/chrome/browser/ui/views/location_bar/keyword_hint_view.cc
@@ -161,9 +161,10 @@
 }
 
 gfx::Insets KeywordHintView::GetInsets() const {
-  if (!LocationBarView::IsRounded())
-    return gfx::Insets(0,
-                       GetLayoutConstant(LOCATION_BAR_ICON_INTERIOR_PADDING));
+  if (!LocationBarView::IsRounded()) {
+    return gfx::Insets(
+        0, GetLayoutInsets(LOCATION_BAR_ICON_INTERIOR_PADDING).left());
+  }
 
   // The location bar and keyword hint view chip have rounded ends. Ensure the
   // chip label's corner with the furthest extent from its midpoint is still at
@@ -183,7 +184,8 @@
   // omnibox, but the padding should be symmetrical, so use it on both sides,
   // collapsing into the horizontal padding used by the previous View.
   const int left_margin =
-      horizontal_margin - GetLayoutConstant(LOCATION_BAR_ICON_INTERIOR_PADDING);
+      horizontal_margin -
+      GetLayoutInsets(LOCATION_BAR_ICON_INTERIOR_PADDING).left();
   return gfx::Insets(0, std::max(0, left_margin), 0, horizontal_margin);
 }
 
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 4440ef5..66d9ddb 100644
--- a/chrome/browser/ui/views/location_bar/location_bar_view.cc
+++ b/chrome/browser/ui/views/location_bar/location_bar_view.cc
@@ -913,7 +913,7 @@
   SetImageFromVectorIcon(clear_all_button_, icon,
                          GetColor(OmniboxPart::LOCATION_BAR_CLEAR_ALL));
   clear_all_button_->SetBorder(views::CreateEmptyBorder(
-      gfx::Insets(GetLayoutConstant(LOCATION_BAR_ICON_INTERIOR_PADDING))));
+      GetLayoutInsets(LOCATION_BAR_ICON_INTERIOR_PADDING)));
 }
 
 void LocationBarView::RefreshFocusRing() {
diff --git a/chrome/browser/ui/views/omnibox/OWNERS b/chrome/browser/ui/views/omnibox/OWNERS
index 96498063..90b1b756 100644
--- a/chrome/browser/ui/views/omnibox/OWNERS
+++ b/chrome/browser/ui/views/omnibox/OWNERS
@@ -1,6 +1,3 @@
-jdonnelly@chromium.org
-pkasting@chromium.org
-mpearson@chromium.org
-tommycli@chromium.org
+file://components/omnibox/OWNERS
 
 # COMPONENT: UI>Browser>Omnibox
diff --git a/chrome/browser/ui/views/omnibox/omnibox_match_cell_view.cc b/chrome/browser/ui/views/omnibox/omnibox_match_cell_view.cc
index d1f91fb..9924a477 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_match_cell_view.cc
+++ b/chrome/browser/ui/views/omnibox/omnibox_match_cell_view.cc
@@ -57,7 +57,7 @@
 // Returns the padding width between elements.
 int HorizontalPadding() {
   return GetLayoutConstant(LOCATION_BAR_ELEMENT_PADDING) +
-         GetLayoutConstant(LOCATION_BAR_ICON_INTERIOR_PADDING);
+         GetLayoutInsets(LOCATION_BAR_ICON_INTERIOR_PADDING).width() / 2;
 }
 
 // Returns the horizontal offset that ensures icons align vertically with the
diff --git a/chrome/browser/ui/views/page_action/page_action_icon_view.cc b/chrome/browser/ui/views/page_action/page_action_icon_view.cc
index ba79906..210972d 100644
--- a/chrome/browser/ui/views/page_action/page_action_icon_view.cc
+++ b/chrome/browser/ui/views/page_action/page_action_icon_view.cc
@@ -44,7 +44,7 @@
       active_(false),
       suppress_mouse_released_action_(false) {
   SetBorder(views::CreateEmptyBorder(
-      gfx::Insets(GetLayoutConstant(LOCATION_BAR_ICON_INTERIOR_PADDING))));
+      GetLayoutInsets(LOCATION_BAR_ICON_INTERIOR_PADDING)));
   if (ui::MaterialDesignController::IsNewerMaterialUi()) {
     // Ink drop ripple opacity.
     set_ink_drop_visible_opacity(
diff --git a/chrome/browser/ui/views/passwords/password_generation_popup_view_views.cc b/chrome/browser/ui/views/passwords/password_generation_popup_view_views.cc
index 4b378ff..b1329d0 100644
--- a/chrome/browser/ui/views/passwords/password_generation_popup_view_views.cc
+++ b/chrome/browser/ui/views/passwords/password_generation_popup_view_views.cc
@@ -6,12 +6,10 @@
 
 #include "base/macros.h"
 #include "base/strings/string16.h"
-#include "build/build_config.h"
 #include "chrome/app/vector_icons/vector_icons.h"
 #include "chrome/browser/ui/autofill/popup_constants.h"
 #include "chrome/browser/ui/passwords/password_generation_popup_controller.h"
 #include "chrome/browser/ui/views/harmony/chrome_typography.h"
-#include "chrome/browser/ui/views_mode_controller.h"
 #include "ui/accessibility/ax_node_data.h"
 #include "ui/base/material_design/material_design_controller.h"
 #include "ui/base/resource/resource_bundle.h"
@@ -262,19 +260,13 @@
 
 PasswordGenerationPopupView* PasswordGenerationPopupView::Create(
     PasswordGenerationPopupController* controller) {
-#if defined(OS_MACOSX)
-  if (views_mode_controller::IsViewsBrowserCocoa())
-    return CreateCocoa(controller);
-#endif
+  if (!controller->container_view())
+    return nullptr;
+
   views::Widget* observing_widget =
       views::Widget::GetTopLevelWidgetForNativeView(
           controller->container_view());
 
-  // If the top level widget can't be found, cancel the popup since we can't
-  // fully set it up.
-  if (!observing_widget)
-    return NULL;
-
   return new PasswordGenerationPopupViewViews(controller, observing_widget);
 }
 
diff --git a/chrome/browser/ui/views/status_bubble_views.cc b/chrome/browser/ui/views/status_bubble_views.cc
index 4396cd4..48b8eade 100644
--- a/chrome/browser/ui/views/status_bubble_views.cc
+++ b/chrome/browser/ui/views/status_bubble_views.cc
@@ -35,6 +35,7 @@
 #include "ui/gfx/text_utils.h"
 #include "ui/native_theme/native_theme.h"
 #include "ui/views/controls/scrollbar/scroll_bar_views.h"
+#include "ui/views/style/typography.h"
 #include "ui/views/widget/root_view.h"
 #include "ui/views/widget/widget.h"
 #include "url/gurl.h"
@@ -82,6 +83,11 @@
 constexpr auto kMaxExpansionStepDuration =
     base::TimeDelta::FromMilliseconds(150);
 
+const gfx::FontList& GetFont() {
+  return views::style::GetFont(views::style::CONTEXT_LABEL,
+                               views::style::STYLE_PRIMARY);
+}
+
 }  // namespace
 
 // StatusBubbleViews::StatusViewAnimation --------------------------------------
@@ -490,8 +496,9 @@
   SkColor blended_text_color = color_utils::AlphaBlend(
       theme_provider_->GetColor(ThemeProperties::COLOR_TAB_TEXT), bubble_color,
       0x99);
+
   canvas->DrawStringRect(
-      text_, gfx::FontList(),
+      text_, GetFont(),
       color_utils::GetReadableColor(blended_text_color, bubble_color),
       text_rect);
 }
@@ -700,7 +707,7 @@
 }
 
 int StatusBubbleViews::GetPreferredHeight() {
-  return gfx::FontList().GetHeight() + kTotalVerticalPadding;
+  return GetFont().GetHeight() + kTotalVerticalPadding;
 }
 
 void StatusBubbleViews::SetBounds(int x, int y, int w, int h) {
@@ -759,8 +766,7 @@
   // Set Elided Text corresponding to the GURL object.
   int text_width = static_cast<int>(size_.width() - (kShadowThickness * 2) -
                                     kTextPositionX - kTextHorizPadding - 1);
-  url_text_ =
-      url_formatter::ElideUrl(url, gfx::FontList(), text_width);
+  url_text_ = url_formatter::ElideUrl(url, GetFont(), text_width);
 
   // An URL is always treated as a left-to-right string. On right-to-left UIs
   // we need to explicitly mark the URL as LTR to make sure it is displayed
diff --git a/chrome/browser/ui/views/tabs/tab.cc b/chrome/browser/ui/views/tabs/tab.cc
index 42d95c6..5b24a28f 100644
--- a/chrome/browser/ui/views/tabs/tab.cc
+++ b/chrome/browser/ui/views/tabs/tab.cc
@@ -867,6 +867,12 @@
     close_button_->SetBorder(
         views::CreateEmptyBorder(top, left, bottom, right));
     close_button_->SizeToPreferredSize();
+    // Re-layout the close button so it can recompute its focus ring if needed:
+    // SizeToPreferredSize() will not necessarily re-Layout the View if only its
+    // interior margins have changed (which this logic does), but the focus ring
+    // still needs to be updated because it doesn't want to encompass the
+    // interior margins.
+    close_button_->Layout();
   }
   close_button_->SetVisible(showing_close_button_);
 
diff --git a/chrome/browser/ui/views/tabs/tab_close_button.cc b/chrome/browser/ui/views/tabs/tab_close_button.cc
index 73e91a4..641c3be 100644
--- a/chrome/browser/ui/views/tabs/tab_close_button.cc
+++ b/chrome/browser/ui/views/tabs/tab_close_button.cc
@@ -24,6 +24,7 @@
 #include "ui/gfx/image/image_skia_operations.h"
 #include "ui/gfx/paint_vector_icon.h"
 #include "ui/views/rect_based_targeting_utils.h"
+#include "ui/views/style/platform_style.h"
 
 #if defined(USE_AURA)
 #include "ui/aura/env.h"
@@ -40,6 +41,10 @@
   // Disable animation so that the red danger sign shows up immediately
   // to help avoid mis-clicks.
   SetAnimationDuration(0);
+  SetInstallFocusRingOnFocus(views::PlatformStyle::kPreferFocusRings);
+
+  if (focus_ring())
+    SetFocusPainter(nullptr);
 }
 
 TabCloseButton::~TabCloseButton() {}
@@ -106,6 +111,16 @@
   return "TabCloseButton";
 }
 
+void TabCloseButton::Layout() {
+  ImageButton::Layout();
+  if (focus_ring()) {
+    focus_ring()->Layout();
+    SkPath path;
+    path.addOval(gfx::RectToSkRect(GetContentsBounds()));
+    focus_ring()->SetPath(path);
+  }
+}
+
 void TabCloseButton::PaintButtonContents(gfx::Canvas* canvas) {
   canvas->SaveLayerAlpha(GetOpacity());
   views::ImageButton::PaintButtonContents(canvas);
diff --git a/chrome/browser/ui/views/tabs/tab_close_button.h b/chrome/browser/ui/views/tabs/tab_close_button.h
index 932d189..524d314 100644
--- a/chrome/browser/ui/views/tabs/tab_close_button.h
+++ b/chrome/browser/ui/views/tabs/tab_close_button.h
@@ -47,6 +47,7 @@
   void OnMouseReleased(const ui::MouseEvent& event) override;
   void OnGestureEvent(ui::GestureEvent* event) override;
   const char* GetClassName() const override;
+  void Layout() override;
 
  protected:
   void PaintButtonContents(gfx::Canvas* canvas) override;
diff --git a/chrome/browser/ui/views/tabs/tab_drag_controller.cc b/chrome/browser/ui/views/tabs/tab_drag_controller.cc
index d33983f..068470fc 100644
--- a/chrome/browser/ui/views/tabs/tab_drag_controller.cc
+++ b/chrome/browser/ui/views/tabs/tab_drag_controller.cc
@@ -135,10 +135,27 @@
                         new gfx::Rect(bounds_in_screen));
   }
 }
+
+// Returns true if we should attach the dragged tabs into |target_tabstrip|
+// after the drag ends. Currently it only happens on Chrome OS, when the dragged
+// tabs are dragged over an overview window, we should not try to attach it
+// to the overview window during dragging, but should wait to do so until the
+// drag ends.
+bool ShouldAttachOnEnd(TabStrip* target_tabstrip) {
+  return target_tabstrip &&
+         target_tabstrip->GetWidget()->GetNativeWindow()->GetProperty(
+             ash::kIsShowingInOverviewKey);
+}
+
 #else
 bool IsSnapped(const TabStrip* tab_strip) {
   return false;
 }
+
+bool ShouldAttachOnEnd(TabStrip* target_tabstrip) {
+  return false;
+}
+
 #endif  // #if defined(OS_CHROMEOS)
 
 #if defined(USE_AURA)
@@ -437,6 +454,12 @@
   // finishes.
   if (reason == END_DRAG_CAPTURE_LOST && is_dragging_window_)
     return;
+
+  // It's possible that in Chrome OS we defer the windows that are showing in
+  // overview to attach into during dragging. If so we need to attach the
+  // dragged tabs to it first.
+  if (reason == END_DRAG_COMPLETE && deferred_target_tabstrip_)
+    PerformDeferredAttach();
   EndDragImpl(reason != END_DRAG_COMPLETE && source_tabstrip_ ?
               CANCELED : NORMAL);
 }
@@ -557,6 +580,18 @@
           Liveness::DELETED) {
     return Liveness::DELETED;
   }
+
+  // The dragged tabs may not be able to attach into |target_tabstrip| during
+  // dragging if the window accociated with |target_tabstrip| is currently
+  // showing in overview mode in Chrome OS, in this case we defer attaching into
+  // it till the drag ends and reset |target_tabstrip| here.
+  if (ShouldAttachOnEnd(target_tabstrip)) {
+    SetDeferredTargetTabstrip(target_tabstrip);
+    target_tabstrip = is_dragging_window_ ? attached_tabstrip_ : nullptr;
+  } else {
+    SetDeferredTargetTabstrip(nullptr);
+  }
+
   bool tab_strip_changed = (target_tabstrip != attached_tabstrip_);
 
   if (attached_tabstrip_) {
@@ -863,7 +898,15 @@
   // behavior.  See crbug.com/336691
   if (!GetModalTransient(local_window)) {
     TabStrip* result = GetTabStripForWindow(local_window);
-    if (result && DoesTabStripContain(result, point_in_screen)) {
+    if (ShouldAttachOnEnd(result)) {
+      // No need to check if the specified screen point is within the bounds of
+      // the tabstrip as arriving here we know that the window is currently
+      // showing in overview mode in Chrome OS and its bounds contain the
+      // specified screen point, and these two conditions are enough for a
+      // window to be a valid target window to attach the dragged tabs.
+      *tab_strip = result;
+      return Liveness::ALIVE;
+    } else if (result && DoesTabStripContain(result, point_in_screen)) {
       *tab_strip = result;
       return Liveness::ALIVE;
     }
@@ -907,7 +950,8 @@
 }
 
 void TabDragController::Attach(TabStrip* attached_tabstrip,
-                               const gfx::Point& point_in_screen) {
+                               const gfx::Point& point_in_screen,
+                               bool set_capture) {
   TRACE_EVENT1("views", "TabDragController::Attach",
                "point_in_screen", point_in_screen.ToString());
 
@@ -990,7 +1034,8 @@
   // Transfer ownership of us to the new tabstrip as well as making sure the
   // window has capture. This is important so that if activation changes the
   // drag isn't prematurely canceled.
-  attached_tabstrip_->GetWidget()->SetCapture(attached_tabstrip_);
+  if (set_capture)
+    attached_tabstrip_->GetWidget()->SetCapture(attached_tabstrip_);
   attached_tabstrip_->OwnDragController(this);
   SetTabDraggingInfo();
 }
@@ -1408,6 +1453,29 @@
   owning_tabstrip->DestroyDragController();
 }
 
+void TabDragController::PerformDeferredAttach() {
+  DCHECK(deferred_target_tabstrip_);
+  DCHECK_NE(deferred_target_tabstrip_, attached_tabstrip_);
+
+  // |is_dragging_new_browser_| needs to be reset here since after this function
+  // is called, the browser window that was specially created for the dragged
+  // tab(s) will be destroyed.
+  is_dragging_new_browser_ = false;
+  // |did_restore_window_| is only set to be true if the dragged window is the
+  // source window and the source window was maximized or fullscreen before the
+  // drag starts. It also needs to be reset to false here otherwise after this
+  // function is called, the newly attached window may be maximized unexpectedly
+  // after the drag ends.
+  did_restore_window_ = false;
+
+  TabStrip* target_tabstrip = deferred_target_tabstrip_;
+  SetDeferredTargetTabstrip(nullptr);
+  Detach(DONT_RELEASE_CAPTURE);
+  // If we're attaching the dragged tabs to an overview window's tabstrip, the
+  // tabstrip should not have focus.
+  Attach(target_tabstrip, GetCursorScreenPoint(), /*set_capture=*/false);
+}
+
 void TabDragController::RevertDrag() {
   std::vector<Tab*> tabs;
   for (size_t i = 0; i < drag_data_.size(); ++i) {
@@ -1931,3 +1999,23 @@
   dragged_window->ClearProperty(ash::kTabDraggingSourceWindowKey);
 #endif
 }
+
+void TabDragController::SetDeferredTargetTabstrip(
+    TabStrip* deferred_target_tabstrip) {
+#if defined(OS_CHROMEOS)
+  if (deferred_target_tabstrip_ == deferred_target_tabstrip)
+    return;
+
+  // Clear the window property on the previous |deferred_target_tabstrip_|.
+  if (deferred_target_tabstrip_) {
+    deferred_target_tabstrip_->GetWidget()->GetNativeWindow()->ClearProperty(
+        ash::kIsDeferredTabDraggingTargetWindowKey);
+  }
+  deferred_target_tabstrip_ = deferred_target_tabstrip;
+  // Set the window property on the new |deferred_target_tabstrip_|.
+  if (deferred_target_tabstrip_) {
+    deferred_target_tabstrip_->GetWidget()->GetNativeWindow()->SetProperty(
+        ash::kIsDeferredTabDraggingTargetWindowKey, true);
+  }
+#endif
+}
diff --git a/chrome/browser/ui/views/tabs/tab_drag_controller.h b/chrome/browser/ui/views/tabs/tab_drag_controller.h
index f5dea06..aba35d94 100644
--- a/chrome/browser/ui/views/tabs/tab_drag_controller.h
+++ b/chrome/browser/ui/views/tabs/tab_drag_controller.h
@@ -289,7 +289,7 @@
   TabStrip* GetTabStripForWindow(gfx::NativeWindow window);
 
   // Returns the compatible TabStrip to drag to at the specified point (screen
-  // coordinates), or NULL if there is none.
+  // coordinates), or nullptr if there is none.
   Liveness GetTargetTabStripForPoint(const gfx::Point& point_in_screen,
                                      TabStrip** tab_strip);
 
@@ -302,8 +302,11 @@
   // coordinates.
   DetachPosition GetDetachPosition(const gfx::Point& point_in_screen);
 
-  // Attach the dragged Tab to the specified TabStrip.
-  void Attach(TabStrip* attached_tabstrip, const gfx::Point& point_in_screen);
+  // Attach the dragged Tab to the specified TabStrip. If |set_capture| is true,
+  // the newly attached tabstrip will have capture.
+  void Attach(TabStrip* attached_tabstrip,
+              const gfx::Point& point_in_screen,
+              bool set_capture = true);
 
   // Detach the dragged Tab from the current TabStrip.
   void Detach(ReleaseCapture release_capture);
@@ -369,6 +372,9 @@
   // not TAB_DESTROYED then one of EndDrag() or RevertDrag() is invoked.
   void EndDragImpl(EndDragType how_end);
 
+  // Called after the drag ends and |deferred_target_tabstrip_| is not nullptr.
+  void PerformDeferredAttach();
+
   // Reverts a cancelled drag operation.
   void RevertDrag();
 
@@ -482,6 +488,10 @@
   // from the old tabstrip or the tab dragging is ended.
   void ClearTabDraggingInfo();
 
+  // Sets |deferred_target_tabstrip_| and updates its corresponding window
+  // property.
+  void SetDeferredTargetTabstrip(TabStrip* deferred_target_tabstrip);
+
   EventSource event_source_;
 
   // The TabStrip the drag originated from.
@@ -491,6 +501,11 @@
   // dragged Tab is detached.
   TabStrip* attached_tabstrip_;
 
+  // The target TabStrip to attach to after the drag ends. It's only possible
+  // to happen in Chrome OS tablet mode, if the dragged tabs are dragged over
+  // an overview window, we should wait until the drag ends to attach it.
+  TabStrip* deferred_target_tabstrip_ = nullptr;
+
   // Whether capture can be released during the drag. When false, capture should
   // not be released when transferring capture between widgets and when starting
   // the move loop.
diff --git a/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc b/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc
index ad6d898..fc80ee8 100644
--- a/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc
+++ b/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc
@@ -2546,6 +2546,70 @@
   EXPECT_EQ("1", IDString(browser()->tab_strip_model()));
 }
 
+namespace {
+
+void DragToOverviewWindowStep2(DetachToBrowserTabDragControllerTest* test,
+                               TabStrip* not_attached_tab_strip,
+                               TabStrip* target_tab_strip) {
+  ASSERT_FALSE(not_attached_tab_strip->IsDragSessionActive());
+  ASSERT_FALSE(target_tab_strip->IsDragSessionActive());
+  ASSERT_TRUE(TabDragController::IsActive());
+
+  // And there should be three browser windows, incluing the newly created one
+  // for the dragged tab.
+  EXPECT_EQ(3u, test->browser_list->size());
+
+  // Put the window that accociated with |target_tab_strip| in overview.
+  target_tab_strip->GetWidget()->GetNativeWindow()->SetProperty(
+      ash::kIsShowingInOverviewKey, true);
+
+  // Drag to target_tab_strip.
+  gfx::Point target_point(target_tab_strip->width() - 1,
+                          target_tab_strip->height() / 2);
+  views::View::ConvertPointToScreen(target_tab_strip, &target_point);
+  ASSERT_TRUE(test->DragInputTo(target_point));
+
+  // Test that the dragged tab did not attach to the overview window.
+  EXPECT_EQ(3u, test->browser_list->size());
+
+  if (test->input_source() == INPUT_SOURCE_TOUCH) {
+    ASSERT_TRUE(test->ReleaseInput());
+  } else {
+    ASSERT_TRUE(test->ReleaseMouseAsync());
+  }
+}
+
+}  // namespace
+
+// Creates two browsers, drags from first into second. If the target window is
+// currently showing in overview, we should not attaching the dragged tabs
+// into the target window during dragging, but should do so until the drag ends.
+IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest,
+                       DragToOverviewWindow) {
+  TabStrip* tab_strip = GetTabStripForBrowser(browser());
+
+  // Add another tab to browser().
+  AddTabAndResetBrowser(browser());
+
+  // Create another browser.
+  Browser* browser2 = CreateAnotherWindowBrowserAndRelayout();
+  TabStrip* tab_strip2 = GetTabStripForBrowser(browser2);
+
+  // Move to the first tab and drag it enough so that it detaches, but not
+  // enough that it attaches to browser2.
+  gfx::Point tab_0_center(GetCenterInScreenCoordinates(tab_strip->tab_at(0)));
+  ASSERT_TRUE(PressInput(tab_0_center));
+  ASSERT_TRUE(DragInputToNotifyWhenDone(
+      tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip),
+      base::BindOnce(&DragToOverviewWindowStep2, this, tab_strip, tab_strip2)));
+  QuitWhenNotDragging();
+
+  // Now the dragged tab should have been attached to the target tabstrip after
+  // the drag ends.
+  ASSERT_FALSE(TabDragController::IsActive());
+  EXPECT_EQ(2u, browser_list->size());
+}
+
 #endif  // OS_CHROMEOS
 
 #if defined(OS_CHROMEOS)
diff --git a/chrome/browser/ui/views/tabs/tab_strip.cc b/chrome/browser/ui/views/tabs/tab_strip.cc
index 0bd1765..3e61ff6 100644
--- a/chrome/browser/ui/views/tabs/tab_strip.cc
+++ b/chrome/browser/ui/views/tabs/tab_strip.cc
@@ -464,6 +464,12 @@
   tabs_.Add(tab, model_index);
   selected_tabs_.IncrementFrom(model_index);
 
+  // If the new tab button is visually after the tabs, make sure it is logically
+  // afterwards as well so that the focus traversal order is correct.
+  NewTabButtonPosition position = controller_->GetNewTabButtonPosition();
+  if (position == AFTER_TABS || position == TRAILING)
+    ReorderChildView(new_tab_button_, -1);
+
   if (touch_layout_) {
     GenerateIdealBoundsForPinnedTabs(NULL);
     int add_types = 0;
diff --git a/chrome/browser/ui/webui/eoc_internals/eoc_internals.mojom b/chrome/browser/ui/webui/eoc_internals/eoc_internals.mojom
index 71a64854..273754df 100644
--- a/chrome/browser/ui/webui/eoc_internals/eoc_internals.mojom
+++ b/chrome/browser/ui/webui/eoc_internals/eoc_internals.mojom
@@ -4,5 +4,96 @@
 
 module eoc_internals.mojom;
 
+// Distillation of results from a server request for page suggestions.
+struct SuggestionResult {
+  // The URL of the page that the suggestions are for.
+  string url;
+
+  // The conditions under which the peek was displayed.
+  PeekConditions peek_conditions;
+
+  // The suggestions for the page.
+  array<Suggestion> suggestions;
+};
+
+// Tracks the server-defined parameters for when to show the peek bar.
+struct PeekConditions {
+  // A measure of confidence that auto-peek should be enabled for this response
+  // in the range [0, 1].
+  float confidence;
+
+  // The percentage of the page that the user scrolls required for an auto
+  // peek to occur.
+  float page_scroll_percentage;
+
+  // The minimum time (seconds) the user spends on the page required for
+  // auto peek.
+  float minimum_seconds_on_page;
+
+  // The maximum number of auto peeks that we can show for this page.
+  int64 maximum_number_of_peeks;
+};
+
+// Models a single suggestion.
+struct Suggestion {
+  // The URL for the suggestion.
+  string url;
+
+  // Title displayed in the suggestion sheet.
+  string title;
+
+  // Name of the publisher.
+  string publisher_name;
+
+  // Text snippet displayed on the sheet.
+  string snippet;
+
+  // The ID of the image displayed for this suggestion.
+  string image_id;
+
+  // The ID of the favicon for the suggested URL.
+  string favicon_image_id;
+};
+
+// Metrics event that was constructed for a page.
+struct MetricEvent {
+  // The URL which the metrics event is for.
+  string url;
+
+  // Did the sheet peek show.
+  bool sheet_peeked;
+
+  // If the peek was closed without being opened.
+  bool sheet_opened;
+
+  // If the sheet was opened from the peek.
+  bool sheet_closed;
+
+  // If any suggestion was clicked on from the sheet.
+  bool any_suggestion_taken;
+
+  // If any suggestion was downloaded from the sheet.
+  bool any_suggestion_downloaded;
+};
+
+// Browser interface for the page. Consists of calls for data and hooks for
+// interactivity.
 interface PageHandler {
-};
\ No newline at end of file
+  // Get a key/value mapping of properties.
+  GetProperties() => (map<string, string> properties);
+
+  // Change the triggering time to the given duration.
+  SetTriggerTime(int64 seconds);
+
+  // Get cached metrics.
+  GetCachedMetricEvents() => (array<MetricEvent> metrics);
+
+  // Clear the cached metrics.
+  ClearCachedMetricEvents() => ();
+
+  // Get the cached suggestion results.
+  GetCachedSuggestionResults() => (array<SuggestionResult> results);
+
+  // Clear the cached suggestions.
+  ClearCachedSuggestionResults() => ();
+};
diff --git a/chrome/browser/ui/webui/eoc_internals/eoc_internals_page_handler.cc b/chrome/browser/ui/webui/eoc_internals/eoc_internals_page_handler.cc
index 54db92a42..d414ef3 100644
--- a/chrome/browser/ui/webui/eoc_internals/eoc_internals_page_handler.cc
+++ b/chrome/browser/ui/webui/eoc_internals/eoc_internals_page_handler.cc
@@ -1,11 +1,143 @@
 // 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/ui/webui/eoc_internals/eoc_internals_page_handler.h"
 
+#include <string>
+#include <vector>
+
+#include "base/containers/flat_map.h"
+#include "chrome/browser/android/chrome_feature_list.h"
+#include "components/ntp_snippets/contextual/contextual_suggestions_cache.h"
+#include "components/ntp_snippets/contextual/contextual_suggestions_features.h"
+#include "components/ntp_snippets/contextual/contextual_suggestions_fetch.h"
+#include "components/ntp_snippets/contextual/contextual_suggestions_result.h"
+
+using contextual_suggestions::ContextualContentSuggestionsService;
+using contextual_suggestions::ContextualSuggestionsCache;
+using contextual_suggestions::ContextualSuggestionsDebuggingReporter;
+using contextual_suggestions::ContextualSuggestionsFetch;
+using contextual_suggestions::ContextualSuggestionsResult;
+
+namespace {
+std::string GetAreChromeFlagsSetupString() {
+  return base::FeatureList::IsEnabled(
+             contextual_suggestions::kContextualSuggestionsBottomSheet) &&
+                 base::FeatureList::IsEnabled(
+                     chrome::android::kChromeModernDesign)
+             ? "true"
+             : "false";
+}
+}  // namespace
+
 EocInternalsPageHandler::EocInternalsPageHandler(
-    eoc_internals::mojom::PageHandlerRequest request)
-    : binding_(this, std::move(request)) {}
+    eoc_internals::mojom::PageHandlerRequest request,
+    ContextualContentSuggestionsService* contextual_content_suggestions_service)
+    : binding_(this, std::move(request)),
+      contextual_content_suggestions_service_(
+          contextual_content_suggestions_service) {}
 
 EocInternalsPageHandler::~EocInternalsPageHandler() {}
+
+void EocInternalsPageHandler::GetProperties(GetPropertiesCallback callback) {
+  base::flat_map<std::string, std::string> properties;
+  // TODO(wylieb): Find the actual time when it's moved to c++ and configurable,
+  // see b/838748 for more details.
+  // TODO(wylieb): Instead of having a map<string, string>, move this to a mojo
+  // struct and populate the fields to html in javascript.
+  properties["time-to-trigger"] = "2";
+  properties["chrome-flags-setup"] = GetAreChromeFlagsSetupString();
+  properties["fetch-endpoint-url"] =
+      ContextualSuggestionsFetch::GetFetchEndpoint();
+  std::move(callback).Run(properties);
+}
+
+void EocInternalsPageHandler::SetTriggerTime(int64_t seconds) {
+  // TODO(wylieb): Implement this when updating triggering time manually is
+  // supported.
+}
+
+void EocInternalsPageHandler::GetCachedMetricEvents(
+    GetCachedMetricEventsCallback callback) {
+  std::vector<eoc_internals::mojom::MetricEventPtr> metric_events;
+  if (contextual_content_suggestions_service_ == nullptr) {
+    std::move(callback).Run(std::move(metric_events));
+    return;
+  }
+
+  ContextualSuggestionsDebuggingReporter* debugging_reporter =
+      contextual_content_suggestions_service_->GetDebuggingReporter();
+  // Events will be ordered from oldest -> newest.
+  // TODO(wylieb): Consider storing a timestamp along with metric events so that
+  // clear ordering and sorting can be used.
+  for (auto debug_event : debugging_reporter->GetEvents()) {
+    auto metric_event = eoc_internals::mojom::MetricEvent::New();
+    metric_event->url = debug_event.url;
+    metric_event->sheet_peeked = debug_event.sheet_peeked;
+    metric_event->sheet_opened = debug_event.sheet_opened;
+    metric_event->sheet_closed = debug_event.sheet_closed;
+    metric_event->any_suggestion_taken = debug_event.any_suggestion_taken;
+    metric_event->any_suggestion_downloaded =
+        debug_event.any_suggestion_downloaded;
+    metric_events.push_back(std::move(metric_event));
+  }
+  std::move(callback).Run(std::move(metric_events));
+}
+
+void EocInternalsPageHandler::ClearCachedMetricEvents(
+    ClearCachedMetricEventsCallback callback) {
+  contextual_content_suggestions_service_->GetDebuggingReporter()
+      ->ClearEvents();
+  std::move(callback).Run();
+}
+
+void EocInternalsPageHandler::GetCachedSuggestionResults(
+    GetCachedSuggestionResultsCallback callback) {
+  std::vector<eoc_internals::mojom::SuggestionResultPtr> suggestion_results;
+  if (contextual_content_suggestions_service_ == nullptr) {
+    std::move(callback).Run(std::move(suggestion_results));
+    return;
+  }
+
+  base::flat_map<GURL, ContextualSuggestionsResult> result_map =
+      contextual_content_suggestions_service_
+          ->GetAllCachedResultsForDebugging();
+
+  for (auto iter = result_map.begin(); iter != result_map.end(); iter++) {
+    auto suggestion_result = eoc_internals::mojom::SuggestionResult::New();
+    suggestion_result->url = iter->first.spec();
+
+    auto peek_conditions = eoc_internals::mojom::PeekConditions::New();
+    peek_conditions->confidence = iter->second.peek_conditions.confidence;
+    peek_conditions->page_scroll_percentage =
+        iter->second.peek_conditions.page_scroll_percentage;
+    peek_conditions->minimum_seconds_on_page =
+        iter->second.peek_conditions.minimum_seconds_on_page;
+    peek_conditions->maximum_number_of_peeks =
+        iter->second.peek_conditions.maximum_number_of_peeks;
+    suggestion_result->peek_conditions = std::move(peek_conditions);
+
+    for (const auto& cluster : iter->second.clusters) {
+      for (const auto& contextual_suggestion : cluster.suggestions) {
+        auto suggestion = eoc_internals::mojom::Suggestion::New();
+        suggestion->url = contextual_suggestion.url.spec();
+        suggestion->title = contextual_suggestion.title;
+        suggestion->publisher_name = contextual_suggestion.publisher_name;
+        suggestion->snippet = contextual_suggestion.snippet;
+        suggestion->image_id = contextual_suggestion.image_id;
+        suggestion->favicon_image_id = contextual_suggestion.favicon_image_id;
+        suggestion_result->suggestions.push_back(std::move(suggestion));
+      }
+    }
+
+    suggestion_results.push_back(std::move(suggestion_result));
+  }
+
+  std::move(callback).Run(std::move(suggestion_results));
+}
+
+void EocInternalsPageHandler::ClearCachedSuggestionResults(
+    ClearCachedSuggestionResultsCallback callback) {
+  contextual_content_suggestions_service_->ClearCachedResultsForDebugging();
+  std::move(callback).Run();
+}
diff --git a/chrome/browser/ui/webui/eoc_internals/eoc_internals_page_handler.h b/chrome/browser/ui/webui/eoc_internals/eoc_internals_page_handler.h
index f8d20c8..e852c44e 100644
--- a/chrome/browser/ui/webui/eoc_internals/eoc_internals_page_handler.h
+++ b/chrome/browser/ui/webui/eoc_internals/eoc_internals_page_handler.h
@@ -7,17 +7,31 @@
 
 #include "base/macros.h"
 #include "chrome/browser/ui/webui/eoc_internals/eoc_internals.mojom.h"
+#include "components/ntp_snippets/contextual/contextual_content_suggestions_service.h"
 #include "mojo/public/cpp/bindings/binding.h"
 
 // Concrete implementation of eoc_internals::mojom::PageHandler.
 class EocInternalsPageHandler : public eoc_internals::mojom::PageHandler {
  public:
-  explicit EocInternalsPageHandler(
-      eoc_internals::mojom::PageHandlerRequest request);
+  EocInternalsPageHandler(
+      eoc_internals::mojom::PageHandlerRequest request,
+      contextual_suggestions::ContextualContentSuggestionsService*
+          contextual_content_suggestions_service);
   ~EocInternalsPageHandler() override;
 
  private:
+  // eoc_internals::mojom::EocInternalsPageHandler
+  void GetProperties(GetPropertiesCallback) override;
+  void SetTriggerTime(int64_t seconds) override;
+  void GetCachedMetricEvents(GetCachedMetricEventsCallback) override;
+  void ClearCachedMetricEvents(ClearCachedMetricEventsCallback) override;
+  void GetCachedSuggestionResults(GetCachedSuggestionResultsCallback) override;
+  void ClearCachedSuggestionResults(
+      ClearCachedSuggestionResultsCallback) override;
+
   mojo::Binding<eoc_internals::mojom::PageHandler> binding_;
+  contextual_suggestions::ContextualContentSuggestionsService*
+      contextual_content_suggestions_service_;
 
   DISALLOW_COPY_AND_ASSIGN(EocInternalsPageHandler);
 };
diff --git a/chrome/browser/ui/webui/eoc_internals/eoc_internals_ui.cc b/chrome/browser/ui/webui/eoc_internals/eoc_internals_ui.cc
index eb3023d..9c7edd37 100644
--- a/chrome/browser/ui/webui/eoc_internals/eoc_internals_ui.cc
+++ b/chrome/browser/ui/webui/eoc_internals/eoc_internals_ui.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/ui/webui/eoc_internals/eoc_internals_ui.h"
 
 #include "build/build_config.h"
+#include "chrome/browser/ntp_snippets/contextual_content_suggestions_service_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/webui/eoc_internals/eoc_internals_page_handler.h"
 #include "chrome/common/url_constants.h"
@@ -15,6 +16,8 @@
 #include "chrome/browser/android/chrome_feature_list.h"
 #endif
 
+using contextual_suggestions::ContextualContentSuggestionsService;
+
 EocInternalsUI::EocInternalsUI(content::WebUI* web_ui)
     : ui::MojoWebUIController(web_ui) {
   content::WebUIDataSource* source =
@@ -27,6 +30,8 @@
   source->UseGzip();
 
   Profile* profile = Profile::FromWebUI(web_ui);
+  contextual_content_suggestions_service_ =
+      ContextualContentSuggestionsServiceFactory::GetForProfile(profile);
   content::WebUIDataSource::Add(profile, source);
   // This class is the caller of the callback when an observer interface is
   // triggered. So this base::Unretained is safe.
@@ -38,5 +43,6 @@
 
 void EocInternalsUI::BindEocInternalsPageHandler(
     eoc_internals::mojom::PageHandlerRequest request) {
-  page_handler_.reset(new EocInternalsPageHandler(std::move(request)));
+  page_handler_.reset(new EocInternalsPageHandler(
+      std::move(request), contextual_content_suggestions_service_));
 }
diff --git a/chrome/browser/ui/webui/eoc_internals/eoc_internals_ui.h b/chrome/browser/ui/webui/eoc_internals/eoc_internals_ui.h
index 7209b4c..3650cf0 100644
--- a/chrome/browser/ui/webui/eoc_internals/eoc_internals_ui.h
+++ b/chrome/browser/ui/webui/eoc_internals/eoc_internals_ui.h
@@ -25,6 +25,8 @@
       eoc_internals::mojom::PageHandlerRequest request);
 
   std::unique_ptr<EocInternalsPageHandler> page_handler_;
+  contextual_suggestions::ContextualContentSuggestionsService*
+      contextual_content_suggestions_service_;
 
   DISALLOW_COPY_AND_ASSIGN(EocInternalsUI);
 };
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 1a75e778..fb1a2a1d 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
@@ -52,6 +52,7 @@
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
 #include "chrome/browser/ui/webui/chromeos/bluetooth_dialog_localized_strings_provider.h"
 #include "chrome/browser/ui/webui/chromeos/network_element_localized_strings_provider.h"
+#include "chromeos/chromeos_features.h"
 #include "chromeos/chromeos_switches.h"
 #include "components/arc/arc_util.h"
 #include "components/user_manager/user_manager.h"
@@ -2479,8 +2480,10 @@
   AddLocalizedStringsBulk(html_source, localized_strings,
                           arraysize(localized_strings));
 
-  html_source->AddBoolean("enableMultideviceSettings",
-                          base::FeatureList::IsEnabled(features::kMultidevice));
+  html_source->AddBoolean(
+      "enableMultideviceSettings",
+      base::FeatureList::IsEnabled(
+          chromeos::features::kEnableUnifiedMultiDeviceSettings));
 }
 #endif
 
diff --git a/chrome/browser/webauthn/chrome_authenticator_request_delegate.cc b/chrome/browser/webauthn/chrome_authenticator_request_delegate.cc
index 900c004..b611483 100644
--- a/chrome/browser/webauthn/chrome_authenticator_request_delegate.cc
+++ b/chrome/browser/webauthn/chrome_authenticator_request_delegate.cc
@@ -73,10 +73,14 @@
   // Currently, completion of the request is indicated by //content destroying
   // this delegate.
   if (weak_dialog_model_) {
-    // The dialog model may be destroyed after the OnRequestComplete call.
-    weak_dialog_model_->RemoveObserver(this);
     weak_dialog_model_->OnRequestComplete();
   }
+
+  // The dialog model may be destroyed after the OnRequestComplete call.
+  if (weak_dialog_model_) {
+    weak_dialog_model_->RemoveObserver(this);
+    weak_dialog_model_ = nullptr;
+  }
 }
 
 base::WeakPtr<ChromeAuthenticatorRequestDelegate>
diff --git a/chrome/installer/mac/BUILD.gn b/chrome/installer/mac/BUILD.gn
index e30b17ba..616dee3 100644
--- a/chrome/installer/mac/BUILD.gn
+++ b/chrome/installer/mac/BUILD.gn
@@ -5,7 +5,6 @@
 import("//build/util/branding.gni")
 import("//build/util/version.gni")
 import("//build/config/features.gni")
-import("//build/config/mac/base_rules.gni")
 
 group("mac") {
   public_deps = [
@@ -72,7 +71,6 @@
 
   deps = [
     ":copy_variables",
-    "//chrome:entitlements",
     "//chrome/installer/mac/third_party/bsdiff:goobsdiff",
     "//chrome/installer/mac/third_party/bsdiff:goobspatch",
     "//chrome/installer/mac/third_party/xz:lzma_decompress",
@@ -81,7 +79,6 @@
   ]
 
   sources = [
-    "$root_gen_dir/chrome/entitlements.plist",
     "$root_out_dir/goobsdiff",
     "$root_out_dir/goobspatch",
     "$root_out_dir/liblzma_decompress.dylib",
@@ -102,8 +99,6 @@
     sources += [
       "//chrome/app/theme/google_chrome/mac/app_canary.icns",
       "//chrome/app/theme/google_chrome/mac/document_canary.icns",
-      "internal/Google_Chrome.provisionprofile",
-      "internal/Google_Chrome_Canary.provisionprofile",
       "internal/chrome_canary_dmg_dsstore",
       "internal/chrome_canary_dmg_icon.icns",
       "internal/chrome_dmg_background.png",
diff --git a/chrome/installer/mac/sign_app.sh.in b/chrome/installer/mac/sign_app.sh.in
index 84dcc9e..a2694af 100644
--- a/chrome/installer/mac/sign_app.sh.in
+++ b/chrome/installer/mac/sign_app.sh.in
@@ -9,7 +9,7 @@
 # verified. Inner bundle components are expected to be signed before this
 # script is called. See sign_versioned_dir.sh.in.
 
-set -eux
+set -eu
 
 # Environment sanitization. Set a known-safe PATH. Clear environment variables
 # that might impact the interpreter's operation. The |bash -p| invocation
@@ -24,20 +24,18 @@
 ME="$(basename "${0}")"
 readonly ME
 
-if [[ ${#} -ne 5 && ${#} -ne 6 ]]; then
+if [[ ${#} -ne 3 && ${#} -ne 4 ]]; then
   echo "usage: ${ME} app_path codesign_keychain codesign_id \
-provisioning_profile entitlements_plist [--development]" >& 2
+[--development]" >& 2
   exit 1
 fi
 
 app_path="${1}"
 codesign_keychain="${2}"
 codesign_id="${3}"
-provisioning_profile="${4}"
-entitlements_plist="${5}"
 is_development=
 
-if [[ ${#} == 6 && "${6}" == "--development" ]]; then
+if [[ ${#} == 4 && "${4}" == "--development" ]]; then
   is_development=1
 fi
 
@@ -47,8 +45,7 @@
 # Use custom resource rules for the browser application.
 browser_app_rules="${script_dir}/app_resource_rules.plist"
 
-contents_dir="${app_path}/Contents"
-versioned_dir="${contents_dir}/Versions/@VERSION@"
+versioned_dir="${app_path}/Contents/Versions/@VERSION@"
 
 browser_app="${app_path}"
 framework="${versioned_dir}/@MAC_PRODUCT_NAME@ Framework.framework"
@@ -58,9 +55,6 @@
 app_mode_loader_app="${framework}/Resources/app_mode_loader.app"
 app_mode_loader="${app_mode_loader_app}/Contents/MacOS/app_mode_loader"
 
-# Embed the supplied provisioning profile.
-cp "${provisioning_profile}" "${contents_dir}/embedded.mobileprovision"
-
 requirement="\
 designated => \
 (identifier \"com.google.Chrome\" or \
@@ -75,7 +69,6 @@
   "${browser_app}"
   --options "${enforcement_flags_app}"
   --resource-rules "${browser_app_rules}"
-  --entitlements "${entitlements_plist}"
 )
 if [[ -z "${is_development}" ]]; then
   codesign_cmd+=( -r="${requirement}" )
diff --git a/chrome/renderer/autofill/form_autofill_browsertest.cc b/chrome/renderer/autofill/form_autofill_browsertest.cc
index 8f391c1..540e876 100644
--- a/chrome/renderer/autofill/form_autofill_browsertest.cc
+++ b/chrome/renderer/autofill/form_autofill_browsertest.cc
@@ -29,6 +29,7 @@
 #include "third_party/blink/public/web/web_form_element.h"
 #include "third_party/blink/public/web/web_input_element.h"
 #include "third_party/blink/public/web/web_local_frame.h"
+#include "third_party/blink/public/web/web_script_source.h"
 #include "third_party/blink/public/web/web_select_element.h"
 
 using autofill::features::kAutofillEnforceMinRequiredFieldsForHeuristics;
@@ -5333,5 +5334,39 @@
   }
 }
 
+TEST_F(FormAutofillTest, WebFormElementNotFoundInForm) {
+  LoadHTML(
+      "<form id='form'>"
+      "  <input type='text' id='firstname' value='John'>"
+      "  <input type='text' id='lastname' value='John'>"
+      "</form>");
+
+  WebLocalFrame* frame = GetMainFrame();
+  ASSERT_NE(nullptr, frame);
+
+  WebFormElement web_form =
+      frame->GetDocument().GetElementById("form").To<WebFormElement>();
+  ASSERT_FALSE(web_form.IsNull());
+
+  WebFormControlElement control_element = frame->GetDocument()
+                                              .GetElementById("firstname")
+                                              .To<WebFormControlElement>();
+  ASSERT_FALSE(control_element.IsNull());
+  FormData form;
+  FormFieldData field;
+  EXPECT_TRUE(WebFormElementToFormData(web_form, control_element, nullptr,
+                                       EXTRACT_NONE, &form, &field));
+
+  const std::vector<FormFieldData>& fields = form.fields;
+  ASSERT_EQ(2U, fields.size());
+  EXPECT_EQ(ASCIIToUTF16("firstname"), fields[0].name);
+  EXPECT_EQ(ASCIIToUTF16("firstname"), field.name);
+
+  frame->ExecuteScript(
+      WebString("document.getElementById('firstname').remove();"));
+  EXPECT_FALSE(WebFormElementToFormData(web_form, control_element, nullptr,
+                                        EXTRACT_NONE, &form, &field));
+}
+
 }  // namespace form_util
 }  // namespace autofill
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 8b9b7cd8..80a86d4 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -4010,7 +4010,6 @@
         "../browser/ui/cocoa/autofill/autofill_bubble_controller_unittest.mm",
         "../browser/ui/cocoa/autofill/autofill_tooltip_controller_unittest.mm",
         "../browser/ui/cocoa/autofill/credit_card_autofill_touch_bar_controller_unittest.mm",
-        "../browser/ui/cocoa/autofill/password_generation_popup_view_cocoa_unittest.mm",
         "../browser/ui/cocoa/background_gradient_view_unittest.mm",
         "../browser/ui/cocoa/base_bubble_controller_unittest.mm",
         "../browser/ui/cocoa/bookmarks/bookmark_all_tabs_controller_unittest.mm",
diff --git a/chrome/test/data/webui/settings/certificate_manager_test.js b/chrome/test/data/webui/settings/certificate_manager_test.js
index 44f0555..a1c1f63a 100644
--- a/chrome/test/data/webui/settings/certificate_manager_test.js
+++ b/chrome/test/data/webui/settings/certificate_manager_test.js
@@ -358,7 +358,7 @@
 
     test('EncryptSuccess', function() {
       const passwordInputElements =
-          Polymer.dom(dialog.$.dialog).querySelectorAll('paper-input');
+          Polymer.dom(dialog.$.dialog).querySelectorAll('cr-input');
       const passwordInputElement = passwordInputElements[0];
       const confirmPasswordInputElement = passwordInputElements[1];
 
@@ -393,7 +393,7 @@
       browserProxy.forceCertificatesError();
 
       const passwordInputElements =
-          Polymer.dom(dialog.$.dialog).querySelectorAll('paper-input');
+          Polymer.dom(dialog.$.dialog).querySelectorAll('cr-input');
       const passwordInputElement = passwordInputElements[0];
       passwordInputElement.value = 'foopassword';
       const confirmPasswordInputElement = passwordInputElements[1];
@@ -434,7 +434,7 @@
 
     test('DecryptSuccess', function() {
       const passwordInputElement =
-          Polymer.dom(dialog.$.dialog).querySelector('paper-input');
+          Polymer.dom(dialog.$.dialog).querySelector('cr-input');
       assertTrue(dialog.$.dialog.open);
 
       // Test that the 'OK' button is enabled even when the password field is
@@ -459,7 +459,7 @@
       browserProxy.forceCertificatesError();
       // Simulate entering some password.
       const passwordInputElement =
-          Polymer.dom(dialog.$.dialog).querySelector('paper-input');
+          Polymer.dom(dialog.$.dialog).querySelector('cr-input');
       passwordInputElement.value = 'foopassword';
       triggerInputEvent(passwordInputElement);
 
diff --git a/chrome/test/data/webui/settings/languages_page_tests.js b/chrome/test/data/webui/settings/languages_page_tests.js
index 0c4b9c5..30276dd 100644
--- a/chrome/test/data/webui/settings/languages_page_tests.js
+++ b/chrome/test/data/webui/settings/languages_page_tests.js
@@ -459,8 +459,27 @@
         assertTrue(triggerRow.classList.contains('two-line'));
         assertLT(0, triggerRow.querySelector('.secondary').textContent.length);
 
+        // Sets |browser.enable_spellchecking| to |value| as if it was set by
+        // policy.
+        const setEnableSpellcheckingViaPolicy = function(value) {
+          const newPrefValue = {
+            key: 'browser.enable_spellchecking',
+            type: chrome.settingsPrivate.PrefType.BOOLEAN,
+            value: value,
+            enforcement: chrome.settingsPrivate.Enforcement.ENFORCED,
+            controlledBy: chrome.settingsPrivate.ControlledBy.DEVICE_POLICY
+          };
+
+          // First set the prefValue, then override the actual preference
+          // object in languagesPage. This is necessary, to avoid a mismatch
+          // between the settings state and |languagesPage.prefs|, which would
+          // cause the value to be reset in |languagesPage.prefs|.
+          languageHelper.setPrefValue('browser.enable_spellchecking', value);
+          languagesPage.set('prefs.browser.enable_spellchecking', newPrefValue);
+        };
+
         // Force-disable spellchecking via policy.
-        languageHelper.setPrefValue('browser.enable_spellchecking', false);
+        setEnableSpellcheckingViaPolicy(false);
         Polymer.dom.flush();
 
         // The second row should not be empty.
@@ -473,7 +492,7 @@
         // Force-enable spellchecking via policy, and ensure that the policy
         // indicator is not present. |enable_spellchecking| can be forced to
         // true by policy, but no indicator should be shown in that case.
-        languageHelper.setPrefValue('browser.enable_spellchecking', true);
+        setEnableSpellcheckingViaPolicy(true);
         Polymer.dom.flush();
         assertFalse(!!triggerRow.querySelector('cr-policy-pref-indicator'));
       });
diff --git a/chrome/test/data/webui/settings/people_page_test.js b/chrome/test/data/webui/settings/people_page_test.js
index ee3f2d4..ad24b21 100644
--- a/chrome/test/data/webui/settings/people_page_test.js
+++ b/chrome/test/data/webui/settings/people_page_test.js
@@ -12,9 +12,11 @@
     let syncBrowserProxy = null;
 
     suiteSetup(function() {
-      // Force easy unlock off. Those have their own ChromeOS-only tests.
       loadTimeData.overrideValues({
+        // Force easy unlock off. Those have their own ChromeOS-only tests.
         easyUnlockAllowed: false,
+        // Force Dice off. Dice is tested in the DiceUITest suite.
+        diceEnabled: false,
       });
     });
 
diff --git a/chromeos/dbus/auth_policy_client.cc b/chromeos/dbus/auth_policy_client.cc
index 9e2c5fe..a78e230 100644
--- a/chromeos/dbus/auth_policy_client.cc
+++ b/chromeos/dbus/auth_policy_client.cc
@@ -159,6 +159,12 @@
                             std::move(on_connected_callback));
   }
 
+  void WaitForServiceToBeAvailable(
+      dbus::ObjectProxy::WaitForServiceToBeAvailableCallback callback)
+      override {
+    proxy_->WaitForServiceToBeAvailable(std::move(callback));
+  }
+
  protected:
   void Init(dbus::Bus* bus) override {
     bus_ = bus;
diff --git a/chromeos/dbus/auth_policy_client.h b/chromeos/dbus/auth_policy_client.h
index 68b157c..5a7d9915 100644
--- a/chromeos/dbus/auth_policy_client.h
+++ b/chromeos/dbus/auth_policy_client.h
@@ -87,6 +87,9 @@
       dbus::ObjectProxy::SignalCallback signal_callback,
       dbus::ObjectProxy::OnConnectedCallback on_connected_callback) = 0;
 
+  virtual void WaitForServiceToBeAvailable(
+      dbus::ObjectProxy::WaitForServiceToBeAvailableCallback callback) = 0;
+
  protected:
   // Create() should be used instead.
   AuthPolicyClient();
diff --git a/chromeos/dbus/fake_auth_policy_client.cc b/chromeos/dbus/fake_auth_policy_client.cc
index deb7e865..e939f81 100644
--- a/chromeos/dbus/fake_auth_policy_client.cc
+++ b/chromeos/dbus/fake_auth_policy_client.cc
@@ -260,6 +260,27 @@
       dbus_operation_delay_);
 }
 
+void FakeAuthPolicyClient::WaitForServiceToBeAvailable(
+    dbus::ObjectProxy::WaitForServiceToBeAvailableCallback callback) {
+  if (started_) {
+    base::ThreadTaskRunnerHandle::Get()->PostTask(
+        FROM_HERE,
+        base::BindOnce(std::move(callback), true /* service_is_available */));
+    return;
+  }
+  wait_for_service_to_be_available_callbacks_.push_back(std::move(callback));
+}
+
+void FakeAuthPolicyClient::SetStarted(bool started) {
+  started_ = started;
+  if (started_) {
+    std::vector<WaitForServiceToBeAvailableCallback> callbacks;
+    callbacks.swap(wait_for_service_to_be_available_callbacks_);
+    for (size_t i = 0; i < callbacks.size(); ++i)
+      std::move(callbacks[i]).Run(true /* service_is_available*/);
+  }
+}
+
 void FakeAuthPolicyClient::OnDevicePolicyRetrieved(
     RefreshPolicyCallback callback,
     SessionManagerClient::RetrievePolicyResponseType response_type,
diff --git a/chromeos/dbus/fake_auth_policy_client.h b/chromeos/dbus/fake_auth_policy_client.h
index a3394fd3..0d5b0c704 100644
--- a/chromeos/dbus/fake_auth_policy_client.h
+++ b/chromeos/dbus/fake_auth_policy_client.h
@@ -65,10 +65,14 @@
       dbus::ObjectProxy::SignalCallback signal_callback,
       dbus::ObjectProxy::OnConnectedCallback on_connected_callback) override;
 
+  void WaitForServiceToBeAvailable(
+      dbus::ObjectProxy::WaitForServiceToBeAvailableCallback callback) override;
+
   // Mark service as started. It's getting started by the
   // UpstartClient::StartAuthPolicyService on the Active Directory managed
-  // devices.
-  void set_started(bool started) { started_ = started; }
+  // devices. If |started| is true, it triggers calling
+  // |wait_for_service_to_be_available_callbacks_|.
+  void SetStarted(bool started);
 
   bool started() const { return started_; }
 
@@ -133,6 +137,9 @@
       base::TimeDelta::FromMilliseconds(100);
   enterprise_management::ChromeDeviceSettingsProto device_policy_;
 
+  std::vector<WaitForServiceToBeAvailableCallback>
+      wait_for_service_to_be_available_callbacks_;
+
   base::WeakPtrFactory<FakeAuthPolicyClient> weak_factory_{this};
 
   DISALLOW_COPY_AND_ASSIGN(FakeAuthPolicyClient);
diff --git a/chromeos/dbus/fake_auth_policy_client_unittest.cc b/chromeos/dbus/fake_auth_policy_client_unittest.cc
index a7fea2b..5ce788b 100644
--- a/chromeos/dbus/fake_auth_policy_client_unittest.cc
+++ b/chromeos/dbus/fake_auth_policy_client_unittest.cc
@@ -89,6 +89,19 @@
         std::string()));
   }
 
+  void WaitForServiceToBeAvailable() {
+    authpolicy_client()->WaitForServiceToBeAvailable(base::BindOnce(
+        &FakeAuthPolicyClientTest::OnWaitForServiceToBeAvailableCalled,
+        base::Unretained(this)));
+  }
+
+  void OnWaitForServiceToBeAvailableCalled(bool is_service_available) {
+    EXPECT_TRUE(is_service_available);
+    service_is_available_called_num_++;
+  }
+
+  int service_is_available_called_num_ = 0;
+
  private:
   FakeAuthPolicyClient* auth_policy_client_ptr_;  // not owned.
   FakeSessionManagerClient* session_manager_client_ptr_;  // not owned.
@@ -99,7 +112,7 @@
 
 // Tests parsing machine name.
 TEST_F(FakeAuthPolicyClientTest, JoinAdDomain_ParseMachineName) {
-  authpolicy_client()->set_started(true);
+  authpolicy_client()->SetStarted(true);
   JoinAdDomain("correct_length1", kCorrectUserName,
                base::BindOnce(
                    [](authpolicy::ErrorType error, const std::string& domain) {
@@ -139,7 +152,7 @@
 
 // Tests join to a different machine domain.
 TEST_F(FakeAuthPolicyClientTest, JoinAdDomain_MachineDomain) {
-  authpolicy_client()->set_started(true);
+  authpolicy_client()->SetStarted(true);
   JoinAdDomainWithMachineDomain(kCorrectMachineName, kMachineDomain,
                                 kCorrectUserName,
                                 base::BindOnce([](authpolicy::ErrorType error,
@@ -163,7 +176,7 @@
 
 // Tests parsing user name.
 TEST_F(FakeAuthPolicyClientTest, JoinAdDomain_ParseUPN) {
-  authpolicy_client()->set_started(true);
+  authpolicy_client()->SetStarted(true);
   JoinAdDomain(kCorrectMachineName, kCorrectUserName,
                base::BindOnce(
                    [](authpolicy::ErrorType error, const std::string& domain) {
@@ -209,7 +222,7 @@
 
 // Tests that fake server does not support legacy encryption types.
 TEST_F(FakeAuthPolicyClientTest, JoinAdDomain_NotSupportedEncType) {
-  authpolicy_client()->set_started(true);
+  authpolicy_client()->SetStarted(true);
   base::RunLoop loop;
   authpolicy::JoinDomainRequest request;
   request.set_machine_name(kCorrectMachineName);
@@ -232,7 +245,7 @@
 
 // Test AuthenticateUser.
 TEST_F(FakeAuthPolicyClientTest, AuthenticateUser_ByAccountId) {
-  authpolicy_client()->set_started(true);
+  authpolicy_client()->SetStarted(true);
   LockDeviceActiveDirectory();
   // Check that account_id do not change.
   AuthenticateUser(
@@ -279,7 +292,7 @@
 // Tests RefreshDevicePolicy. On a not locked device it should cache policy. On
 // a locked device it should send policy to session_manager.
 TEST_F(FakeAuthPolicyClientTest, NotLockedDeviceCachesPolicy) {
-  authpolicy_client()->set_started(true);
+  authpolicy_client()->SetStarted(true);
   authpolicy_client()->RefreshDevicePolicy(
       base::BindOnce([](authpolicy::ErrorType error) {
         EXPECT_EQ(authpolicy::ERROR_DEVICE_POLICY_CACHED_BUT_NOT_SENT, error);
@@ -297,7 +310,7 @@
 
 // Tests that RefreshDevicePolicy stores device policy in the session manager.
 TEST_F(FakeAuthPolicyClientTest, RefreshDevicePolicyStoresPolicy) {
-  authpolicy_client()->set_started(true);
+  authpolicy_client()->SetStarted(true);
   LockDeviceActiveDirectory();
 
   {
@@ -335,4 +348,17 @@
   }
 }
 
+TEST_F(FakeAuthPolicyClientTest, WaitForServiceToBeAvailableCalled) {
+  WaitForServiceToBeAvailable();
+  WaitForServiceToBeAvailable();
+  base::RunLoop().RunUntilIdle();
+  EXPECT_EQ(0, service_is_available_called_num_);
+  authpolicy_client()->SetStarted(true);
+  base::RunLoop().RunUntilIdle();
+  EXPECT_EQ(2, service_is_available_called_num_);
+  WaitForServiceToBeAvailable();
+  base::RunLoop().RunUntilIdle();
+  EXPECT_EQ(3, service_is_available_called_num_);
+}
+
 }  // namespace chromeos
diff --git a/chromeos/dbus/fake_upstart_client.cc b/chromeos/dbus/fake_upstart_client.cc
index 1a1c0b1..fe01790 100644
--- a/chromeos/dbus/fake_upstart_client.cc
+++ b/chromeos/dbus/fake_upstart_client.cc
@@ -20,7 +20,7 @@
 void FakeUpstartClient::StartAuthPolicyService() {
   static_cast<FakeAuthPolicyClient*>(
       DBusThreadManager::Get()->GetAuthPolicyClient())
-      ->set_started(true);
+      ->SetStarted(true);
 }
 
 void FakeUpstartClient::RestartAuthPolicyService() {
@@ -28,7 +28,7 @@
       DBusThreadManager::Get()->GetAuthPolicyClient());
   DLOG_IF(WARNING, !authpolicy_client->started())
       << "Trying to restart authpolicyd which is not started";
-  authpolicy_client->set_started(true);
+  authpolicy_client->SetStarted(true);
 }
 
 void FakeUpstartClient::StartMediaAnalytics(
diff --git a/chromeos/services/secure_channel/fake_timer_factory.cc b/chromeos/services/secure_channel/fake_timer_factory.cc
index 5c2f18882..c221468 100644
--- a/chromeos/services/secure_channel/fake_timer_factory.cc
+++ b/chromeos/services/secure_channel/fake_timer_factory.cc
@@ -17,6 +17,8 @@
 FakeTimerFactory::~FakeTimerFactory() = default;
 
 std::unique_ptr<base::Timer> FakeTimerFactory::CreateOneShotTimer() {
+  ++num_instances_created_;
+
   auto fake_one_shot_timer = std::make_unique<FakeOneShotTimer>(
       base::BindOnce(&FakeTimerFactory::OnOneShotTimerDeleted,
                      weak_ptr_factory_.GetWeakPtr()));
diff --git a/chromeos/services/secure_channel/fake_timer_factory.h b/chromeos/services/secure_channel/fake_timer_factory.h
index c6248411..41e3b37 100644
--- a/chromeos/services/secure_channel/fake_timer_factory.h
+++ b/chromeos/services/secure_channel/fake_timer_factory.h
@@ -34,6 +34,8 @@
     return id_to_active_one_shot_timer_map_;
   }
 
+  size_t num_instances_created() const { return num_instances_created_; }
+
  private:
   // TimerFactory:
   std::unique_ptr<base::Timer> CreateOneShotTimer() override;
@@ -43,6 +45,7 @@
   base::UnguessableToken id_for_last_created_one_shot_timer_;
   base::flat_map<base::UnguessableToken, FakeOneShotTimer*>
       id_to_active_one_shot_timer_map_;
+  size_t num_instances_created_ = 0u;
 
   base::WeakPtrFactory<FakeTimerFactory> weak_ptr_factory_;
 
diff --git a/components/autofill/content/renderer/form_autofill_util.cc b/components/autofill/content/renderer/form_autofill_util.cc
index 6142e2d..a4fef04 100644
--- a/components/autofill/content/renderer/form_autofill_util.cc
+++ b/components/autofill/content/renderer/form_autofill_util.cc
@@ -1116,7 +1116,7 @@
 // or
 // 2) a NULL |form_element|.
 //
-// If |field| is not NULL, then |form_control_element| should be not NULL.
+// If |field| is not NULL, then |form_control_element| should not be NULL.
 bool FormOrFieldsetsToFormData(
     const blink::WebFormElement* form_element,
     const blink::WebFormControlElement* form_control_element,
@@ -1186,6 +1186,7 @@
   // the DOM.  We use the |fields_extracted| vector to make sure we assign the
   // extracted label to the correct field, as it's possible |form_fields| will
   // not contain all of the elements in |control_elements|.
+  bool found_field = false;
   for (size_t i = 0, field_idx = 0;
        i < control_elements.size() && field_idx < form_fields.size(); ++i) {
     // This field didn't meet the requirements, so don't try to find a label
@@ -1201,12 +1202,20 @@
     }
     TruncateString(&form_fields[field_idx]->label, kMaxDataLength);
 
-    if (field && *form_control_element == control_element)
+    if (field && *form_control_element == control_element) {
       *field = *form_fields[field_idx];
+      found_field = true;
+    }
 
     ++field_idx;
   }
 
+  // The form_control_element was not found in control_elements. This can
+  // happen if elements are dynamically removed from the form while it is
+  // being processed. See http://crbug.com/849870
+  if (field && !found_field)
+    return false;
+
   // Copy the created FormFields into the resulting FormData object.
   for (const auto& field : form_fields)
     form->fields.push_back(*field);
@@ -1264,10 +1273,7 @@
     const base::string16* typed_from_key = map_key.second.first.get();
     if (!typed_from_key)
       continue;
-    const WebInputElement* input_element = ToWebInputElement(&map_key.first);
-    if (input_element && input_element->IsTextField() &&
-        !input_element->IsPasswordFieldForAutofill() &&
-        typed_from_key->size() >= kMinMatchSize &&
+    if (typed_from_key->size() >= kMinMatchSize &&
         lowercase.find(base::i18n::ToLower(*typed_from_key)) !=
             base::string16::npos) {
       return true;
@@ -1511,7 +1517,8 @@
 
   if (field_value_and_properties_map) {
     FieldValueAndPropertiesMaskMap::const_iterator it =
-        field_value_and_properties_map->find(element);
+        field_value_and_properties_map->find(
+            element.UniqueRendererFormControlId());
     if (it != field_value_and_properties_map->end())
       field->properties_mask = it->second.second;
   }
@@ -1596,7 +1603,9 @@
       field->properties_mask & (FieldPropertiesFlags::USER_TYPED |
                                 FieldPropertiesFlags::AUTOFILLED)) {
     const base::string16 typed_value =
-        *field_value_and_properties_map->at(element).first;
+        *field_value_and_properties_map
+             ->at(element.UniqueRendererFormControlId())
+             .first;
 
     // The typed value is preserved for all passwords. It is also preserved for
     // potential usernames, as long as the |value| is not deemed acceptable.
diff --git a/components/autofill/content/renderer/password_autofill_agent.cc b/components/autofill/content/renderer/password_autofill_agent.cc
index 53b9a44..b81614cc 100644
--- a/components/autofill/content/renderer/password_autofill_agent.cc
+++ b/components/autofill/content/renderer/password_autofill_agent.cc
@@ -408,19 +408,22 @@
     FieldPropertiesMask added_flags,
     FieldValueAndPropertiesMaskMap* field_value_and_properties_map) {
   FieldValueAndPropertiesMaskMap::iterator it =
-      field_value_and_properties_map->find(element);
+      field_value_and_properties_map->find(
+          element.UniqueRendererFormControlId());
   if (it != field_value_and_properties_map->end()) {
     if (value)
       it->second.first.reset(new base::string16(*value));
     it->second.second |= added_flags;
   } else {
-    (*field_value_and_properties_map)[element] = std::make_pair(
-        value ? std::make_unique<base::string16>(*value) : nullptr,
-        added_flags);
+    (*field_value_and_properties_map)[element.UniqueRendererFormControlId()] =
+        std::make_pair(
+            value ? std::make_unique<base::string16>(*value) : nullptr,
+            added_flags);
   }
   // Reset USER_TYPED and AUTOFILLED flags if the value is empty.
   if (value && value->empty()) {
-    (*field_value_and_properties_map)[element].second &=
+    (*field_value_and_properties_map)[element.UniqueRendererFormControlId()]
+        .second &=
         ~(FieldPropertiesFlags::USER_TYPED | FieldPropertiesFlags::AUTOFILLED);
   }
 }
diff --git a/components/autofill/content/renderer/password_autofill_agent.h b/components/autofill/content/renderer/password_autofill_agent.h
index 79cf39e..ce623aa 100644
--- a/components/autofill/content/renderer/password_autofill_agent.h
+++ b/components/autofill/content/renderer/password_autofill_agent.h
@@ -188,11 +188,10 @@
     // The key under which PasswordAutofillManager can find info for filling.
     int key = -1;
   };
-  typedef std::map<blink::WebInputElement, PasswordInfo>
-      WebInputToPasswordInfoMap;
-  typedef std::map<blink::WebElement, int> WebElementToPasswordInfoKeyMap;
-  typedef std::map<blink::WebInputElement, blink::WebInputElement>
-      PasswordToLoginMap;
+  using WebInputToPasswordInfoMap =
+      std::map<blink::WebInputElement, PasswordInfo>;
+  using PasswordToLoginMap =
+      std::map<blink::WebInputElement, blink::WebInputElement>;
 
   // This class keeps track of autofilled password input elements and makes sure
   // the autofilled password value is not accessible to JavaScript code until
diff --git a/components/autofill/content/renderer/password_form_conversion_utils.h b/components/autofill/content/renderer/password_form_conversion_utils.h
index a571ebd6..b628b2d 100644
--- a/components/autofill/content/renderer/password_form_conversion_utils.h
+++ b/components/autofill/content/renderer/password_form_conversion_utils.h
@@ -20,7 +20,6 @@
 
 namespace blink {
 class WebFormElement;
-class WebFormControlElement;
 class WebInputElement;
 class WebLocalFrame;
 }
@@ -65,10 +64,11 @@
 // Tests whether the given form is a GAIA form with a skip password argument.
 bool IsGaiaWithSkipSavePasswordForm(const blink::WebFormElement& form);
 
-typedef std::map<
-    const blink::WebFormControlElement,
-    std::pair<std::unique_ptr<base::string16>, FieldPropertiesMask>>
-    FieldValueAndPropertiesMaskMap;
+// TODO(https://crbug.com/849291): Create separate class for keeping information
+// from FieldValueAndPropertiesMaskMap.
+using FieldValueAndPropertiesMaskMap =
+    std::map<uint32_t,
+             std::pair<std::unique_ptr<base::string16>, FieldPropertiesMask>>;
 
 // Create a PasswordForm from DOM form. Webkit doesn't allow storing
 // custom metadata to DOM nodes, so we have to do this every time an event
diff --git a/components/autofill/content/renderer/password_form_conversion_utils_browsertest.cc b/components/autofill/content/renderer/password_form_conversion_utils_browsertest.cc
index 571ee5a..ddb0edbd 100644
--- a/components/autofill/content/renderer/password_form_conversion_utils_browsertest.cc
+++ b/components/autofill/content/renderer/password_form_conversion_utils_browsertest.cc
@@ -215,7 +215,7 @@
         input_element->SetActivatedSubmit(true);
       if (with_user_input) {
         const base::string16 element_value = input_element->Value().Utf16();
-        user_input[control_elements[i]] =
+        user_input[control_elements[i].UniqueRendererFormControlId()] =
             std::make_pair(std::make_unique<base::string16>(element_value),
                            FieldPropertiesFlags::USER_TYPED);
       }
@@ -736,12 +736,14 @@
   // "email" field should be ignored despite it is more reliable than prediction
   // for "id" field.
   FieldValueAndPropertiesMaskMap user_input;
-  user_input[control_elements[2]] = std::make_pair(  // id
-      std::make_unique<base::string16>(control_elements[2].Value().Utf16()),
-      FieldPropertiesFlags::USER_TYPED);
-  user_input[control_elements[3]] = std::make_pair(  // password
-      std::make_unique<base::string16>(control_elements[3].Value().Utf16()),
-      FieldPropertiesFlags::USER_TYPED);
+  user_input[control_elements[2].UniqueRendererFormControlId()] =
+      std::make_pair(  // id
+          std::make_unique<base::string16>(control_elements[2].Value().Utf16()),
+          FieldPropertiesFlags::USER_TYPED);
+  user_input[control_elements[3].UniqueRendererFormControlId()] =
+      std::make_pair(  // password
+          std::make_unique<base::string16>(control_elements[3].Value().Utf16()),
+          FieldPropertiesFlags::USER_TYPED);
 
   std::unique_ptr<PasswordForm> password_form = CreatePasswordFormFromWebForm(
       form, &user_input, nullptr, &username_detector_cache);
@@ -1575,14 +1577,16 @@
   WebVector<WebFormControlElement> control_elements;
   form.GetFormControlElements(control_elements);
   ASSERT_EQ("nonvisible_text", control_elements[0].NameForAutofill().Utf8());
-  user_input[control_elements[0]] = std::make_pair(
-      std::make_unique<base::string16>(control_elements[0].Value().Utf16()),
-      FieldPropertiesFlags::USER_TYPED);
+  user_input[control_elements[0].UniqueRendererFormControlId()] =
+      std::make_pair(
+          std::make_unique<base::string16>(control_elements[0].Value().Utf16()),
+          FieldPropertiesFlags::USER_TYPED);
   ASSERT_EQ("nonvisible_password",
             control_elements[2].NameForAutofill().Utf8());
-  user_input[control_elements[2]] = std::make_pair(
-      std::make_unique<base::string16>(control_elements[2].Value().Utf16()),
-      FieldPropertiesFlags::USER_TYPED);
+  user_input[control_elements[2].UniqueRendererFormControlId()] =
+      std::make_pair(
+          std::make_unique<base::string16>(control_elements[2].Value().Utf16()),
+          FieldPropertiesFlags::USER_TYPED);
 
   std::unique_ptr<PasswordForm> password_form =
       CreatePasswordFormFromWebForm(form, &user_input, nullptr, nullptr);
@@ -1633,14 +1637,16 @@
   form.GetFormControlElements(control_elements);
   ASSERT_EQ("password_with_user_input1",
             control_elements[9].NameForAutofill().Utf8());
-  user_input[control_elements[9]] = std::make_pair(
-      std::make_unique<base::string16>(control_elements[9].Value().Utf16()),
-      FieldPropertiesFlags::USER_TYPED);
+  user_input[control_elements[9].UniqueRendererFormControlId()] =
+      std::make_pair(
+          std::make_unique<base::string16>(control_elements[9].Value().Utf16()),
+          FieldPropertiesFlags::USER_TYPED);
   ASSERT_EQ("password_with_user_input2",
             control_elements[10].NameForAutofill().Utf8());
-  user_input[control_elements[10]] = std::make_pair(
-      std::make_unique<base::string16>(control_elements[10].Value().Utf16()),
-      FieldPropertiesFlags::USER_TYPED);
+  user_input[control_elements[10].UniqueRendererFormControlId()] =
+      std::make_pair(std::make_unique<base::string16>(
+                         control_elements[10].Value().Utf16()),
+                     FieldPropertiesFlags::USER_TYPED);
 
   std::unique_ptr<PasswordForm> password_form =
       CreatePasswordFormFromWebForm(form, &user_input, nullptr, nullptr);
@@ -1691,14 +1697,16 @@
   form.GetFormControlElements(control_elements);
   ASSERT_EQ("password_with_user_input1",
             control_elements[7].NameForAutofill().Utf8());
-  user_input[control_elements[7]] = std::make_pair(
-      std::make_unique<base::string16>(control_elements[7].Value().Utf16()),
-      FieldPropertiesFlags::USER_TYPED);
+  user_input[control_elements[7].UniqueRendererFormControlId()] =
+      std::make_pair(
+          std::make_unique<base::string16>(control_elements[7].Value().Utf16()),
+          FieldPropertiesFlags::USER_TYPED);
   ASSERT_EQ("password_with_user_input2",
             control_elements[9].NameForAutofill().Utf8());
-  user_input[control_elements[9]] = std::make_pair(
-      std::make_unique<base::string16>(control_elements[9].Value().Utf16()),
-      FieldPropertiesFlags::USER_TYPED);
+  user_input[control_elements[9].UniqueRendererFormControlId()] =
+      std::make_pair(
+          std::make_unique<base::string16>(control_elements[9].Value().Utf16()),
+          FieldPropertiesFlags::USER_TYPED);
 
   std::unique_ptr<PasswordForm> password_form =
       CreatePasswordFormFromWebForm(form, &user_input, nullptr, nullptr);
@@ -1854,13 +1862,14 @@
     FieldPropertiesMask mask = FieldPropertiesFlags::AUTOFILLED;
     if (autofilled_value_was_modified_by_user)
       mask |= FieldPropertiesFlags::USER_TYPED;
-    user_input[control_elements[1]] =
+    user_input[control_elements[1].UniqueRendererFormControlId()] =
         std::make_pair(std::make_unique<base::string16>(
                            base::ASCIIToUTF16("autofilled_value")),
                        mask);
-    user_input[control_elements[2]] = std::make_pair(
-        std::make_unique<base::string16>(base::ASCIIToUTF16("user_value")),
-        FieldPropertiesFlags::USER_TYPED);
+    user_input[control_elements[2].UniqueRendererFormControlId()] =
+        std::make_pair(
+            std::make_unique<base::string16>(base::ASCIIToUTF16("user_value")),
+            FieldPropertiesFlags::USER_TYPED);
 
     std::unique_ptr<PasswordForm> password_form(
         CreatePasswordFormFromWebForm(form, &user_input, nullptr, nullptr));
@@ -2041,7 +2050,7 @@
   FieldValueAndPropertiesMaskMap user_input;
   WebInputElement* input_element = ToWebInputElement(&control_elements[3]);
   const base::string16 element_value = input_element->Value().Utf16();
-  user_input[control_elements[3]] =
+  user_input[control_elements[3].UniqueRendererFormControlId()] =
       std::make_pair(std::make_unique<base::string16>(element_value),
                      FieldPropertiesFlags::USER_TYPED);
 
@@ -2462,21 +2471,24 @@
   ASSERT_EQ(3u, control_elements.size());
   ASSERT_EQ("fine", control_elements[0].NameForAutofill().Utf8());
   control_elements[0].SetAutofillValue("same_value");
-  user_input[control_elements[0]] = std::make_pair(
-      std::make_unique<base::string16>(control_elements[0].Value().Utf16()),
-      FieldPropertiesFlags::USER_TYPED);
+  user_input[control_elements[0].UniqueRendererFormControlId()] =
+      std::make_pair(
+          std::make_unique<base::string16>(control_elements[0].Value().Utf16()),
+          FieldPropertiesFlags::USER_TYPED);
 
   ASSERT_EQ("mangled", control_elements[1].NameForAutofill().Utf8());
   control_elements[1].SetAutofillValue("mangled_value");
-  user_input[control_elements[1]] = std::make_pair(
-      std::make_unique<base::string16>(base::UTF8ToUTF16("original_value")),
-      FieldPropertiesFlags::USER_TYPED);
+  user_input[control_elements[1].UniqueRendererFormControlId()] =
+      std::make_pair(
+          std::make_unique<base::string16>(base::UTF8ToUTF16("original_value")),
+          FieldPropertiesFlags::USER_TYPED);
 
   ASSERT_EQ("completed_for_user", control_elements[2].NameForAutofill().Utf8());
   control_elements[2].SetAutofillValue("email@gmail.com");
-  user_input[control_elements[2]] = std::make_pair(
-      std::make_unique<base::string16>(base::UTF8ToUTF16("email")),
-      FieldPropertiesFlags::USER_TYPED);
+  user_input[control_elements[2].UniqueRendererFormControlId()] =
+      std::make_pair(
+          std::make_unique<base::string16>(base::UTF8ToUTF16("email")),
+          FieldPropertiesFlags::USER_TYPED);
 
   std::unique_ptr<PasswordForm> password_form =
       CreatePasswordFormFromWebForm(form, &user_input, nullptr, nullptr);
diff --git a/components/autofill/ios/browser/autofill_agent.mm b/components/autofill/ios/browser/autofill_agent.mm
index 43c90590..f030b19 100644
--- a/components/autofill/ios/browser/autofill_agent.mm
+++ b/components/autofill/ios/browser/autofill_agent.mm
@@ -478,8 +478,9 @@
               value:base::SysNSStringToUTF16(suggestion.value)];
   } else if (suggestion.identifier == autofill::POPUP_ITEM_ID_CLEAR_FORM) {
     [jsAutofillManager_
-        clearAutofilledFieldsForFormNamed:formName
-                        completionHandler:suggestionHandledCompletion_];
+        clearAutofilledFieldsForFormName:formName
+                         fieldIdentifier:fieldIdentifier
+                       completionHandler:suggestionHandledCompletion_];
     suggestionHandledCompletion_ = nil;
   } else {
     NOTREACHED() << "unknown identifier " << suggestion.identifier;
@@ -735,7 +736,10 @@
     if (field.value.empty() || !field.is_autofilled)
       continue;
 
-    fieldsData.SetKey(base::UTF16ToUTF8(field.id), base::Value(field.value));
+    base::Value fieldData(base::Value::Type::DICTIONARY);
+    fieldData.SetKey("value", base::Value(field.value));
+    fieldData.SetKey("section", base::Value(field.section));
+    fieldsData.SetKey(base::UTF16ToUTF8(field.id), std::move(fieldData));
   }
   autofillData.SetKey("fields", std::move(fieldsData));
 
diff --git a/components/autofill/ios/browser/fake_js_autofill_manager.h b/components/autofill/ios/browser/fake_js_autofill_manager.h
index 3d2c553..e7f3ad7 100644
--- a/components/autofill/ios/browser/fake_js_autofill_manager.h
+++ b/components/autofill/ios/browser/fake_js_autofill_manager.h
@@ -13,9 +13,13 @@
 @interface FakeJSAutofillManager : JsAutofillManager
 
 // The name of the form that was most recently passed to
-// |clearAutofilledFieldsForFormNamed:completionHandler:|.
+// |clearAutofilledFieldsForFormName:fieldIdentifier:completionHandler:|.
 @property(nonatomic, copy, readonly) NSString* lastClearedFormName;
 
+// The field identifier that was most recently passed to
+// |clearAutofilledFieldsForFormName:fieldIdentifier:completionHandler:|.
+@property(nonatomic, copy, readonly) NSString* lastClearedFieldIdentifier;
+
 @end
 
 #endif  // COMPONENTS_AUTOFILL_IOS_BROWSER_FAKE_JS_AUTOFILL_MANAGER_H_
diff --git a/components/autofill/ios/browser/fake_js_autofill_manager.mm b/components/autofill/ios/browser/fake_js_autofill_manager.mm
index d77975ea..4d7203d 100644
--- a/components/autofill/ios/browser/fake_js_autofill_manager.mm
+++ b/components/autofill/ios/browser/fake_js_autofill_manager.mm
@@ -14,11 +14,15 @@
 @implementation FakeJSAutofillManager
 
 @synthesize lastClearedFormName = _lastClearedFormName;
+@synthesize lastClearedFieldIdentifier = _lastClearedFieldIdentifier;
 
-- (void)clearAutofilledFieldsForFormNamed:(NSString*)formName
-                        completionHandler:(ProceduralBlock)completionHandler {
+- (void)clearAutofilledFieldsForFormName:(NSString*)formName
+                         fieldIdentifier:(NSString*)fieldIdentifier
+                       completionHandler:(ProceduralBlock)completionHandler {
   web::WebThread::PostTask(web::WebThread::UI, FROM_HERE, base::BindOnce(^{
                              _lastClearedFormName = [formName copy];
+                             _lastClearedFieldIdentifier =
+                                 [fieldIdentifier copy];
                              completionHandler();
                            }));
 }
diff --git a/components/autofill/ios/browser/js_autofill_manager.h b/components/autofill/ios/browser/js_autofill_manager.h
index 898a289..97801ad 100644
--- a/components/autofill/ios/browser/js_autofill_manager.h
+++ b/components/autofill/ios/browser/js_autofill_manager.h
@@ -41,10 +41,12 @@
 // autofilled are not modified. Field contents are cleared, and Autofill flag
 // and styling are removed. 'change' events are sent for fields whose contents
 // changed.
+// |fieldIdentifier| identifies the field that initiated the clear action.
 // |completionHandler| is called after the forms are filled. |completionHandler|
 // cannot be nil.
-- (void)clearAutofilledFieldsForFormNamed:(NSString*)formName
-                        completionHandler:(ProceduralBlock)completionHandler;
+- (void)clearAutofilledFieldsForFormName:(NSString*)formName
+                         fieldIdentifier:(NSString*)fieldIdentifier
+                       completionHandler:(ProceduralBlock)completionHandler;
 
 // Marks up the form with autofill field prediction data (diagnostic tool).
 - (void)fillPredictionData:(NSString*)dataString;
diff --git a/components/autofill/ios/browser/js_autofill_manager.mm b/components/autofill/ios/browser/js_autofill_manager.mm
index 92e2e73..4a4cdc4 100644
--- a/components/autofill/ios/browser/js_autofill_manager.mm
+++ b/components/autofill/ios/browser/js_autofill_manager.mm
@@ -109,13 +109,18 @@
              }];
 }
 
-- (void)clearAutofilledFieldsForFormNamed:(NSString*)formName
-                        completionHandler:(ProceduralBlock)completionHandler {
+- (void)clearAutofilledFieldsForFormName:(NSString*)formName
+                         fieldIdentifier:(NSString*)fieldIdentifier
+                       completionHandler:(ProceduralBlock)completionHandler {
   DCHECK(completionHandler);
-  NSString* script =
-      [NSString stringWithFormat:
-                    @"__gCrWeb.autofill.clearAutofilledFields(%s);",
-                    base::GetQuotedJSONString([formName UTF8String]).c_str()];
+  NSString* script = [NSString
+      stringWithFormat:@"__gCrWeb.autofill.clearAutofilledFields(%s, %s);",
+                       base::GetQuotedJSONString(
+                           base::SysNSStringToUTF8(formName))
+                           .c_str(),
+                       base::GetQuotedJSONString(
+                           base::SysNSStringToUTF8(fieldIdentifier))
+                           .c_str()];
   [_receiver executeJavaScript:script
              completionHandler:^(id, NSError*) {
                completionHandler();
diff --git a/components/autofill/ios/browser/resources/autofill_controller.js b/components/autofill/ios/browser/resources/autofill_controller.js
index 5bb6f60..a11e447 100644
--- a/components/autofill/ios/browser/resources/autofill_controller.js
+++ b/components/autofill/ios/browser/resources/autofill_controller.js
@@ -21,7 +21,7 @@
  * The autofill data for a form.
  * @typedef {{
  *   formName: string,
- *   fields: !Object<string, string>,
+ *   fields: !Object<string, !Object<string, string>>,
  * }}
  */
 var FormData;
@@ -279,10 +279,10 @@
     if (__gCrWeb.fill.isCheckableElement(element))
       continue;
 
-    // Skip fields if autofill data is missing.
+    // Skip fields for which autofill data is missing.
     var fieldIdentifier = __gCrWeb.form.getFieldIdentifier(element);
-    var value = data.fields[fieldIdentifier];
-    if (!value)
+    var fieldData = data.fields[fieldIdentifier];
+    if (!fieldData)
       continue;
 
     // Skip non-empty fields unless:
@@ -302,15 +302,16 @@
       continue;
     }
 
-    (function(_element, _value, _delay) {
+    (function(_element, _value, _section, _delay) {
       window.setTimeout(function() {
         __gCrWeb.fill.setInputElementValue(_value, _element, function() {
           _element.setAttribute('chrome-autofilled', '');
           _element.isAutofilled = true;
+          _element.autofillSection = _section;
           _element.addEventListener('input', controlElementInputListener_);
         });
       }, _delay);
-    })(element, value, delay);
+    })(element, fieldData.value, fieldData.section, delay);
   }
 
   if (form) {
@@ -329,30 +330,45 @@
   }
 };
 
-// TODO(crbug.com/816941): Clear should only clear the current section and not
-// the whole form.
 /**
  * Clear autofilled fields of the specified form section. Fields that are not
- * currently autofilled are not modified.
+ * currently autofilled or do not belong to the same section as that of the
+ * field with |fieldIdentifier| are not modified. If the field identified by
+ * |fieldIdentifier| cannot be found all autofilled form fields get cleared.
  * Field contents are cleared, and Autofill flag and styling are removed.
  * 'change' events are sent for fields whose contents changed.
  * Based on FormCache::ClearSectionWithElement().
  *
  * @param {string} formName Identifier for form element (from
  *     getFormIdentifier).
+ * @param {string} fieldIdentifier Identifier for form field initiating the
+ *     clear action.
  */
-__gCrWeb.autofill['clearAutofilledFields'] = function(formName) {
+__gCrWeb.autofill['clearAutofilledFields'] = function(
+    formName, fieldIdentifier) {
   var form = __gCrWeb.form.getFormElementFromIdentifier(formName);
   var controlElements = form ?
       __gCrWeb.form.getFormControlElements(form) :
       getUnownedAutofillableFormFieldElements_(document.all, /*fieldsets=*/[]);
 
+  var formField = null;
+  for (var i = 0; i < controlElements.length; ++i) {
+    if (__gCrWeb.form.getFieldIdentifier(controlElements[i]) ==
+        fieldIdentifier) {
+      formField = controlElements[i];
+      break;
+    }
+  }
+
   for (var i = 0, delay = 0; i < controlElements.length;
        ++i, delay += __gCrWeb.autofill.delayBetweenFieldFillingMs) {
     var element = controlElements[i];
     if (!element.isAutofilled || element.disabled)
       continue;
 
+    if (formField && formField.autofillSection != element.autofillSection)
+      continue;
+
     var value = null;
     if (__gCrWeb.fill.isTextInput(element) ||
         __gCrWeb.fill.isTextAreaElement(element)) {
diff --git a/components/crash/content/tools/generate_breakpad_symbols.py b/components/crash/content/tools/generate_breakpad_symbols.py
index eb2dbf0..23b4725 100755
--- a/components/crash/content/tools/generate_breakpad_symbols.py
+++ b/components/crash/content/tools/generate_breakpad_symbols.py
@@ -29,24 +29,6 @@
                                      ['platform', 'arch', 'hash', 'name'])
 
 
-def GetCommandOutput(command, env=None):
-  """Runs the command list, returning its output (stdout).
-
-  Args:
-    command: (list of strings) a command with arguments
-
-    env: (dict or None) optional environment for the command. If None,
-      inherits the existing environment, otherwise completely overrides it.
-
-  From chromium_utils.
-  """
-  devnull = open(os.devnull, 'w')
-  proc = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=devnull,
-                          bufsize=1, env=env)
-  output = proc.communicate()[0]
-  return output
-
-
 def GetDumpSymsBinary(build_dir=None):
   """Returns the path to the dump_syms binary."""
   DUMP_SYMS = 'dump_syms'
@@ -82,7 +64,10 @@
   """Return absolute paths to all shared library dependecies of the binary.
 
   This implementation assumes that we're running on a Linux system."""
-  ldd = GetCommandOutput(['ldd', binary])
+  # TODO(thakis): Figure out how to make this work for android
+  # (https://crbug.com/849904) and use check_output().
+  p = subprocess.Popen(['ldd', binary], stdout=subprocess.PIPE)
+  ldd = p.communicate()[0]
   lib_re = re.compile('\t.* => (.+) \(.*\)$')
   result = []
   for line in ldd.splitlines():
@@ -106,7 +91,7 @@
   if 'DEVELOPER_DIR' in os.environ:
     candidate_paths.append(os.environ['DEVELOPER_DIR'])
   candidate_paths.extend([
-    GetCommandOutput(['xcode-select', '-p']).strip(),
+    subprocess.check_output(['xcode-select', '-p']).strip(),
     # Most Mac 10.1[0-2] bots have at least one Xcode installed.
     '/Applications/Xcode.app',
     '/Applications/Xcode9.0.app',
@@ -130,7 +115,7 @@
   developer_dir = GetDeveloperDirMac()
   if developer_dir:
     env['DEVELOPER_DIR'] = developer_dir
-  otool = GetCommandOutput(['otool', '-l', binary], env=env).splitlines()
+  otool = subprocess.check_output(['otool', '-l', binary], env=env).splitlines()
   rpaths = []
   dylib_id = None
   for idx, line in enumerate(otool):
@@ -141,7 +126,7 @@
       m = re.match(' *name (.*) \(offset .*\)$', otool[idx+2])
       dylib_id = m.group(1)
 
-  otool = GetCommandOutput(['otool', '-L', binary], env=env).splitlines()
+  otool = subprocess.check_output(['otool', '-L', binary], env=env).splitlines()
   lib_re = re.compile('\t(.*) \(compatibility .*\)$')
   deps = []
   for line in otool:
@@ -224,7 +209,7 @@
           break
 
         binary_info = GetBinaryInfoFromHeaderInfo(
-            GetCommandOutput([dump_syms, '-i', binary]).splitlines()[0])
+            subprocess.check_output([dump_syms, '-i', binary]).splitlines()[0])
         if not binary_info:
           should_dump_syms = False
           reason = "Could not obtain binary information."
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.cc
index 495ad7e..420249d 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.cc
@@ -196,6 +196,7 @@
       configurator_(configurator),
       event_creator_(event_creator),
       connection_type_(net::NetworkChangeNotifier::GetConnectionType()),
+      ignore_long_term_black_list_rules_(false),
       network_properties_manager_(nullptr),
       weak_factory_(this) {
   DCHECK(io_task_runner_);
@@ -766,7 +767,7 @@
   // TODO(crbug.com/720102): Consider new method to just check blacklist.
   return !previews_decider.ShouldAllowPreviewAtECT(
       request, previews_type, net::EFFECTIVE_CONNECTION_TYPE_4G,
-      std::vector<std::string>());
+      std::vector<std::string>(), ignore_long_term_black_list_rules_);
 }
 
 bool DataReductionProxyConfig::ShouldAcceptServerPreview(
@@ -852,4 +853,15 @@
 }
 #endif  // defined(OS_CHROMEOS)
 
+void DataReductionProxyConfig::SetIgnoreLongTermBlackListRules(
+    bool ignore_long_term_black_list_rules) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  ignore_long_term_black_list_rules_ = ignore_long_term_black_list_rules;
+}
+
+bool DataReductionProxyConfig::IgnoreBlackListLongTermRulesForTesting() const {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  return ignore_long_term_black_list_rules_;
+}
+
 }  // namespace data_reduction_proxy
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.h b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.h
index 91efe18a..f6bec706 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.h
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.h
@@ -202,6 +202,12 @@
   void EnableGetNetworkIdAsynchronously();
 #endif  // defined(OS_CHROMEOS)
 
+  // When triggering previews, prevent long term black list rules.
+  void SetIgnoreLongTermBlackListRules(bool ignore_long_term_black_list_rules);
+
+  // Returns the value set in SetIgnoreLongTermBlackListRules.
+  bool IgnoreBlackListLongTermRulesForTesting() const;
+
  protected:
   virtual base::TimeTicks GetTicksNow() const;
 
@@ -363,6 +369,9 @@
   bool warmup_url_fetch_in_flight_secure_proxy_;
   bool warmup_url_fetch_in_flight_core_proxy_;
 
+  // When triggerring previews, prevent long term black list rules.
+  bool ignore_long_term_black_list_rules_;
+
   // Should be accessed only on the IO thread. Guaranteed to be non-null during
   // the lifetime of |this| if accessed on the IO thread.
   NetworkPropertiesManager* network_properties_manager_;
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.cc
index 80339491..8b1b2d4 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.cc
@@ -590,6 +590,9 @@
   if (!config.has_proxy_config())
     return false;
 
+  config_->SetIgnoreLongTermBlackListRules(
+      config.ignore_long_term_black_list_rules());
+
   // An empty proxy config is OK, and allows the server to effectively turn off
   // DataSaver if needed. See http://crbug.com/840978.
   std::vector<DataReductionProxyServer> proxies =
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client_unittest.cc
index f94f5fb..64457206 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client_unittest.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client_unittest.cc
@@ -91,7 +91,8 @@
                           const std::string& secondary_host,
                           int secondary_port,
                           const ProxyServer_ProxyType& secondary_proxy_type,
-                          float reporting_fraction) {
+                          float reporting_fraction,
+                          bool ignore_long_term_black_list_rules) {
   ClientConfig config;
 
   config.set_session_key(session_key);
@@ -104,6 +105,8 @@
     config.mutable_pageload_metrics_config()->set_reporting_fraction(
         reporting_fraction);
   }
+  config.set_ignore_long_term_black_list_rules(
+      ignore_long_term_black_list_rules);
   ProxyServer* primary_proxy =
       config.mutable_proxy_config()->add_http_proxy_servers();
   primary_proxy->set_scheme(primary_scheme);
@@ -172,11 +175,11 @@
 
     ASSERT_NE(nullptr, context_->network_delegate());
     // Set up the various test ClientConfigs.
-    ClientConfig config =
-        CreateConfig(kSuccessSessionKey, kConfigRefreshDurationSeconds, 0,
-                     ProxyServer_ProxyScheme_HTTPS, "origin.net", 443,
-                     ProxyServer::CORE, ProxyServer_ProxyScheme_HTTP,
-                     "fallback.net", 80, ProxyServer::UNSPECIFIED_TYPE, 0.5f);
+    ClientConfig config = CreateConfig(
+        kSuccessSessionKey, kConfigRefreshDurationSeconds, 0,
+        ProxyServer_ProxyScheme_HTTPS, "origin.net", 443, ProxyServer::CORE,
+        ProxyServer_ProxyScheme_HTTP, "fallback.net", 80,
+        ProxyServer::UNSPECIFIED_TYPE, 0.5f, false);
     config.SerializeToString(&config_);
     encoded_config_ = EncodeConfig(config);
 
@@ -184,21 +187,21 @@
         kOldSuccessSessionKey, kConfigRefreshDurationSeconds, 0,
         ProxyServer_ProxyScheme_HTTPS, "old.origin.net", 443, ProxyServer::CORE,
         ProxyServer_ProxyScheme_HTTP, "old.fallback.net", 80,
-        ProxyServer::UNSPECIFIED_TYPE, 0.0f);
+        ProxyServer::UNSPECIFIED_TYPE, 0.0f, false);
     previous_config.SerializeToString(&previous_config_);
 
-    ClientConfig persisted =
-        CreateConfig(kPersistedSessionKey, kConfigRefreshDurationSeconds, 0,
-                     ProxyServer_ProxyScheme_HTTPS, "persisted.net", 443,
-                     ProxyServer::CORE, ProxyServer_ProxyScheme_HTTP,
-                     "persisted.net", 80, ProxyServer::UNSPECIFIED_TYPE, 0.0f);
+    ClientConfig persisted = CreateConfig(
+        kPersistedSessionKey, kConfigRefreshDurationSeconds, 0,
+        ProxyServer_ProxyScheme_HTTPS, "persisted.net", 443, ProxyServer::CORE,
+        ProxyServer_ProxyScheme_HTTP, "persisted.net", 80,
+        ProxyServer::UNSPECIFIED_TYPE, 0.0f, false);
     loaded_config_ = EncodeConfig(persisted);
 
-    ClientConfig zero_reporting_fraction_config =
-        CreateConfig(kSuccessSessionKey, kConfigRefreshDurationSeconds, 0,
-                     ProxyServer_ProxyScheme_HTTPS, "origin.net", 443,
-                     ProxyServer::CORE, ProxyServer_ProxyScheme_HTTP,
-                     "origin.net", 0, ProxyServer::UNSPECIFIED_TYPE, 0.0f);
+    ClientConfig zero_reporting_fraction_config = CreateConfig(
+        kSuccessSessionKey, kConfigRefreshDurationSeconds, 0,
+        ProxyServer_ProxyScheme_HTTPS, "origin.net", 443, ProxyServer::CORE,
+        ProxyServer_ProxyScheme_HTTP, "origin.net", 0,
+        ProxyServer::UNSPECIFIED_TYPE, 0.0f, false);
     zero_reporting_fraction_encoded_config_ =
         EncodeConfig(zero_reporting_fraction_config);
 
@@ -206,29 +209,36 @@
         CreateConfig(kSuccessSessionKey, kConfigRefreshDurationSeconds, 0,
                      ProxyServer_ProxyScheme_HTTPS, "", 443, ProxyServer::CORE,
                      ProxyServer_ProxyScheme_HTTP, "", 0,
-                     ProxyServer::UNSPECIFIED_TYPE, 1.0f);
+                     ProxyServer::UNSPECIFIED_TYPE, 1.0f, false);
     one_reporting_fraction_encoded_config_ =
         EncodeConfig(one_reporting_fraction_config);
 
     // Passing in -1.0f as the reporting fraction causes the
     // |empty_reporting_fraction_config| to have no pageload_metrics_config()
     // set.
-    ClientConfig empty_reporting_fraction_config =
-        CreateConfig(kSuccessSessionKey, kConfigRefreshDurationSeconds, 0,
-                     ProxyServer_ProxyScheme_HTTPS, "origin.net", 443,
-                     ProxyServer::CORE, ProxyServer_ProxyScheme_HTTP,
-                     "origin.net", 0, ProxyServer::UNSPECIFIED_TYPE, -1.0f);
+    ClientConfig empty_reporting_fraction_config = CreateConfig(
+        kSuccessSessionKey, kConfigRefreshDurationSeconds, 0,
+        ProxyServer_ProxyScheme_HTTPS, "origin.net", 443, ProxyServer::CORE,
+        ProxyServer_ProxyScheme_HTTP, "origin.net", 0,
+        ProxyServer::UNSPECIFIED_TYPE, -1.0f, false);
     empty_reporting_fraction_encoded_config_ =
         EncodeConfig(empty_reporting_fraction_config);
 
-    ClientConfig half_reporting_fraction_config =
-        CreateConfig(kSuccessSessionKey, kConfigRefreshDurationSeconds, 0,
-                     ProxyServer_ProxyScheme_HTTPS, "origin.net", 443,
-                     ProxyServer::CORE, ProxyServer_ProxyScheme_HTTP,
-                     "origin.net", 0, ProxyServer::UNSPECIFIED_TYPE, 0.5f);
+    ClientConfig half_reporting_fraction_config = CreateConfig(
+        kSuccessSessionKey, kConfigRefreshDurationSeconds, 0,
+        ProxyServer_ProxyScheme_HTTPS, "origin.net", 443, ProxyServer::CORE,
+        ProxyServer_ProxyScheme_HTTP, "origin.net", 0,
+        ProxyServer::UNSPECIFIED_TYPE, 0.5f, false);
     half_reporting_fraction_encoded_config_ =
         EncodeConfig(half_reporting_fraction_config);
 
+    ClientConfig ignore_black_list_config = CreateConfig(
+        kSuccessSessionKey, kConfigRefreshDurationSeconds, 0,
+        ProxyServer_ProxyScheme_HTTPS, "origin.net", 443, ProxyServer::CORE,
+        ProxyServer_ProxyScheme_HTTP, "origin.net", 0,
+        ProxyServer::UNSPECIFIED_TYPE, 0.5f, true);
+    ignore_black_list_encoded_config_ = EncodeConfig(ignore_black_list_config);
+
     ClientConfig no_proxies_config;
     no_proxies_config.set_session_key(kSuccessSessionKey);
     no_proxies_config.mutable_refresh_duration()->set_seconds(
@@ -454,6 +464,9 @@
   const std::string& half_reporting_fraction_encoded_config() const {
     return half_reporting_fraction_encoded_config_;
   }
+  const std::string& ignore_black_list_encoded_config() const {
+    return ignore_black_list_encoded_config_;
+  }
   const std::string& no_proxies_config() const { return no_proxies_config_; }
 
   const std::string& loaded_config() const { return loaded_config_; }
@@ -498,6 +511,9 @@
   // A configuration where the pingback reporting fraction is set to 0.5f.
   std::string half_reporting_fraction_encoded_config_;
 
+  // A configuration where the black list rules are ignored.
+  std::string ignore_black_list_encoded_config_;
+
   // A configuration where no proxies are configured.
   std::string no_proxies_config_;
 
@@ -1249,11 +1265,11 @@
 TEST_F(DataReductionProxyConfigServiceClientTest, ApplyClientConfigOverride) {
   const std::string override_key = "OverrideSecureSession";
   std::string encoded_config;
-  ClientConfig config =
-      CreateConfig(override_key, kConfigRefreshDurationSeconds, 0,
-                   ProxyServer_ProxyScheme_HTTPS, "origin.net", 443,
-                   ProxyServer::CORE, ProxyServer_ProxyScheme_HTTP,
-                   "fallback.net", 80, ProxyServer::UNSPECIFIED_TYPE, 0.5f);
+  ClientConfig config = CreateConfig(
+      override_key, kConfigRefreshDurationSeconds, 0,
+      ProxyServer_ProxyScheme_HTTPS, "origin.net", 443, ProxyServer::CORE,
+      ProxyServer_ProxyScheme_HTTP, "fallback.net", 80,
+      ProxyServer::UNSPECIFIED_TYPE, 0.5f, false);
   config.SerializeToString(&encoded_config);
   base::Base64Encode(encoded_config, &encoded_config);
 
@@ -1395,6 +1411,15 @@
   config_client()->ApplySerializedConfig(
       half_reporting_fraction_encoded_config());
   EXPECT_EQ(0.5f, pingback_reporting_fraction());
+  EXPECT_FALSE(config()->IgnoreBlackListLongTermRulesForTesting());
+}
+
+TEST_F(DataReductionProxyConfigServiceClientTest,
+       ApplySerializedConfigIgnoreBlackList) {
+  Init(true);
+
+  config_client()->ApplySerializedConfig(ignore_black_list_encoded_config());
+  EXPECT_TRUE(config()->IgnoreBlackListLongTermRulesForTesting());
 }
 
 TEST_F(DataReductionProxyConfigServiceClientTest, EmptyConfigDisablesDRP) {
diff --git a/components/data_reduction_proxy/proto/client_config.proto b/components/data_reduction_proxy/proto/client_config.proto
index 4eb11ff..a3127e4 100644
--- a/components/data_reduction_proxy/proto/client_config.proto
+++ b/components/data_reduction_proxy/proto/client_config.proto
@@ -27,6 +27,9 @@
   optional Duration refresh_duration = 4;
   // Configuration information for reporting pageload metrics.
   optional PageloadMetricsConfig pageload_metrics_config = 5;
+  // Prevents the host base and user base blacklisting behaviors for lite pages
+  // and server LoFi.
+  optional bool ignore_long_term_black_list_rules = 7;
 }
 
 // The configuration for reporting pageload metrics.
@@ -169,4 +172,4 @@
 
   // The production channel, e.g. "canary", "dev", "beta", "stable".
   optional string channel = 4;
-}
\ No newline at end of file
+}
diff --git a/components/dom_distiller/webui/resources/about_dom_distiller.html b/components/dom_distiller/webui/resources/about_dom_distiller.html
index 91c4f49d..e602355 100644
--- a/components/dom_distiller/webui/resources/about_dom_distiller.html
+++ b/components/dom_distiller/webui/resources/about_dom_distiller.html
@@ -48,6 +48,5 @@
     </div>
   </div>
   <script src="chrome://resources/js/i18n_template.js"></script>
-  <script src="chrome://resources/js/jstemplate_compiled.js"></script>
 </body>
 </html>
diff --git a/components/drive/chromeos/default_corpus_change_list_loader.cc b/components/drive/chromeos/default_corpus_change_list_loader.cc
index 2d7012c..59ee1a02 100644
--- a/components/drive/chromeos/default_corpus_change_list_loader.cc
+++ b/components/drive/chromeos/default_corpus_change_list_loader.cc
@@ -80,12 +80,16 @@
 void DefaultCorpusChangeListLoader::LoadIfNeeded(
     const FileOperationCallback& callback) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-  team_drive_list_loader_->LoadIfNeeded(base::BindRepeating(
-      &DefaultCorpusChangeListLoader::OnTeamDriveLoadIfNeeded,
+  // We execute the change list loader and then the team drive loader when it
+  // is completed. If the change list loader detects that it has previously
+  // loaded from the server, then it is a no-op. If it is a fresh load then it
+  // uses GetAllFiles which does not read any change lists with team drive info.
+  change_list_loader_->LoadIfNeeded(base::BindRepeating(
+      &DefaultCorpusChangeListLoader::OnChangeListLoadIfNeeded,
       weak_ptr_factory_.GetWeakPtr(), callback));
 }
 
-void DefaultCorpusChangeListLoader::OnTeamDriveLoadIfNeeded(
+void DefaultCorpusChangeListLoader::OnChangeListLoadIfNeeded(
     const FileOperationCallback& callback,
     FileError error) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
@@ -95,7 +99,7 @@
     return;
   }
 
-  change_list_loader_->LoadIfNeeded(callback);
+  team_drive_list_loader_->LoadIfNeeded(callback);
 }
 
 void DefaultCorpusChangeListLoader::ReadDirectory(
diff --git a/components/drive/chromeos/default_corpus_change_list_loader.h b/components/drive/chromeos/default_corpus_change_list_loader.h
index 854811e..462719b4 100644
--- a/components/drive/chromeos/default_corpus_change_list_loader.h
+++ b/components/drive/chromeos/default_corpus_change_list_loader.h
@@ -58,8 +58,8 @@
 
  private:
   // Called after calling LoadIfNeeded on team drives.
-  void OnTeamDriveLoadIfNeeded(const FileOperationCallback& callback,
-                               FileError error);
+  void OnChangeListLoadIfNeeded(const FileOperationCallback& callback,
+                                FileError error);
 
   std::unique_ptr<internal::AboutResourceRootFolderIdLoader>
       root_folder_id_loader_;
diff --git a/components/drive/chromeos/file_system.cc b/components/drive/chromeos/file_system.cc
index f38c96b..7b647fb 100644
--- a/components/drive/chromeos/file_system.cc
+++ b/components/drive/chromeos/file_system.cc
@@ -7,6 +7,7 @@
 #include <stddef.h>
 #include <utility>
 
+#include "base/barrier_closure.h"
 #include "base/bind.h"
 #include "base/files/file_util.h"
 #include "base/sequenced_task_runner.h"
@@ -402,19 +403,44 @@
       blocking_task_runner_.get(), delegate, resource_metadata_);
 }
 
+// TODO(slangley): Support checking a specific team drive or default corpus,
+// rather than just polling all of them.
 void FileSystem::CheckForUpdates() {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   DVLOG(1) << "CheckForUpdates";
 
+  size_t num_callbacks = team_drive_change_list_loaders_.size() + 1;
+
+  base::RepeatingClosure closure = base::BarrierClosure(
+      num_callbacks, base::BindOnce(&FileSystem::OnUpdateCompleted,
+                                    weak_ptr_factory_.GetWeakPtr()));
+
+  for (auto& team_drive : team_drive_change_list_loaders_) {
+    team_drive.second->CheckForUpdates(
+        base::Bind(&FileSystem::OnUpdateChecked, weak_ptr_factory_.GetWeakPtr(),
+                   team_drive.first, closure));
+  }
+
   default_corpus_change_list_loader_->CheckForUpdates(
-      base::Bind(&FileSystem::OnUpdateChecked, weak_ptr_factory_.GetWeakPtr()));
+      base::Bind(&FileSystem::OnUpdateChecked, weak_ptr_factory_.GetWeakPtr(),
+                 std::string(), closure));
 }
 
-void FileSystem::OnUpdateChecked(FileError error) {
-  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+void FileSystem::OnUpdateChecked(const std::string& team_drive_id,
+                                 const base::RepeatingClosure& closure,
+                                 FileError error) {
   DVLOG(1) << "CheckForUpdates finished: " << FileErrorToString(error);
+  // TODO(slangley): Store the error reasons for team drives and show them on
+  // chrome://drive-internals.
+  if (team_drive_id.empty()) {
+    last_update_check_error_ = error;
+  }
+  closure.Run();
+}
+
+void FileSystem::OnUpdateCompleted() {
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   last_update_check_time_ = base::Time::Now();
-  last_update_check_error_ = error;
 }
 
 void FileSystem::AddObserver(FileSystemObserver* observer) {
@@ -667,6 +693,23 @@
   if (entries_callback && hide_hosted_docs)
     entries_callback = base::Bind(&FilterHostedDocuments, entries_callback);
 
+  if (util::GetDriveTeamDrivesRootPath().IsParent(directory_path)) {
+    // TODO(slangley): It would be nice to cache the result, rather than needing
+    // to iterate every time. But then most users have very few team drives so
+    // in general this is fine.
+    for (auto& team_drive_loader : team_drive_change_list_loaders_) {
+      if (team_drive_loader.second->root_entry_path().IsParent(
+              directory_path)) {
+        team_drive_loader.second->ReadDirectory(
+            directory_path, entries_callback, completion_callback);
+        return;
+      }
+    }
+    DVLOG(1) << "No team drive loader for path, " << directory_path;
+  }
+  // Fall through to the default corpus loader if no team drive loader is found.
+  // We do not refresh the list of team drives from the server until the first
+  // ReadDirectory is called on the default corpus change list loader.
   default_corpus_change_list_loader_->ReadDirectory(
       directory_path, entries_callback, completion_callback);
 }
@@ -867,13 +910,11 @@
 
 void FileSystem::OnLoadFromServerComplete() {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-
   sync_client_->StartCheckingExistingPinnedFiles();
 }
 
 void FileSystem::OnInitialLoadComplete() {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-
   blocking_task_runner_->PostTask(FROM_HERE,
                                   base::Bind(&internal::RemoveStaleCacheFiles,
                                              cache_,
@@ -885,7 +926,26 @@
     const std::vector<internal::TeamDrive>& team_drives_list,
     const std::vector<internal::TeamDrive>& added_team_drives,
     const std::vector<internal::TeamDrive>& removed_team_drives) {
-  // TODO(slangley): Create change list loaders for the team drives.
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
+  for (const auto& team_drive : removed_team_drives) {
+    auto it = team_drive_change_list_loaders_.find(team_drive.team_drive_id());
+    if (it != team_drive_change_list_loaders_.end()) {
+      it->second->RemoveChangeListLoaderObserver(this);
+      team_drive_change_list_loaders_.erase(it);
+    }
+  }
+
+  for (const auto& team_drive : added_team_drives) {
+    auto loader = std::make_unique<internal::TeamDriveChangeListLoader>(
+        team_drive.team_drive_id(), team_drive.team_drive_path(), logger_,
+        blocking_task_runner_.get(), resource_metadata_, scheduler_,
+        loader_controller_.get());
+    loader->AddChangeListLoaderObserver(this);
+    loader->LoadIfNeeded(base::DoNothing());
+    team_drive_change_list_loaders_.emplace(team_drive.team_drive_id(),
+                                            std::move(loader));
+  }
 }
 
 void FileSystem::GetMetadata(
diff --git a/components/drive/chromeos/file_system.h b/components/drive/chromeos/file_system.h
index 324679e..5a3d3014 100644
--- a/components/drive/chromeos/file_system.h
+++ b/components/drive/chromeos/file_system.h
@@ -19,6 +19,7 @@
 #include "components/drive/chromeos/change_list_loader_observer.h"
 #include "components/drive/chromeos/file_system/operation_delegate.h"
 #include "components/drive/chromeos/file_system_interface.h"
+#include "components/drive/chromeos/team_drive_change_list_loader.h"
 #include "components/drive/chromeos/team_drive_list_observer.h"
 #include "google_apis/drive/drive_api_error_codes.h"
 
@@ -226,9 +227,14 @@
       google_apis::DriveApiErrorCode status,
       std::unique_ptr<google_apis::AboutResource> about_resource);
 
+  // Stores any file error as a result of Checking updates.
+  void OnUpdateChecked(const std::string& team_drive_id,
+                       const base::RepeatingClosure& closure,
+                       FileError error);
+
   // Part of CheckForUpdates(). Called when
   // ChangeListLoader::CheckForUpdates() is complete.
-  void OnUpdateChecked(FileError error);
+  void OnUpdateCompleted();
 
   // Part of GetResourceEntry().
   // Called when ReadDirectory() is complete.
@@ -285,6 +291,11 @@
   std::unique_ptr<internal::DriveChangeListLoader>
       default_corpus_change_list_loader_;
 
+  // Used to retrieve changelists for team drives. The key for the map is the
+  // team_drive_id.
+  std::map<std::string, std::unique_ptr<internal::TeamDriveChangeListLoader>>
+      team_drive_change_list_loaders_;
+
   std::unique_ptr<internal::SyncClient> sync_client_;
 
   base::ObserverList<FileSystemObserver> observers_;
diff --git a/components/drive/chromeos/team_drive_change_list_loader.h b/components/drive/chromeos/team_drive_change_list_loader.h
index 1b4ac982..d66d063 100644
--- a/components/drive/chromeos/team_drive_change_list_loader.h
+++ b/components/drive/chromeos/team_drive_change_list_loader.h
@@ -43,6 +43,8 @@
 
   ~TeamDriveChangeListLoader() override;
 
+  const base::FilePath& root_entry_path() const { return root_entry_path_; }
+
   // DriveChangeListLoader overrides
   void AddChangeListLoaderObserver(ChangeListLoaderObserver* observer) override;
   void RemoveChangeListLoaderObserver(
diff --git a/components/drive/chromeos/team_drive_list_loader.cc b/components/drive/chromeos/team_drive_list_loader.cc
index 53698e5c..ca18aee 100644
--- a/components/drive/chromeos/team_drive_list_loader.cc
+++ b/components/drive/chromeos/team_drive_list_loader.cc
@@ -299,6 +299,7 @@
     const TeamDriveUpdateData& team_drive_updates,
     FileError error) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
   if (error != FILE_ERROR_OK) {
     logger_->Log(logging::LOG_ERROR, "Failed to remove team drives: %s",
                  drive::FileErrorToString(error).c_str());
@@ -322,6 +323,7 @@
     const TeamDriveUpdateData& team_drive_updates,
     FileError error) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
   if (error != FILE_ERROR_OK) {
     logger_->Log(logging::LOG_ERROR, "Failed to add or update team drives: %s",
                  drive::FileErrorToString(error).c_str());
diff --git a/components/drive/file_system_unittest.cc b/components/drive/file_system_unittest.cc
index 6ac989d3..7383329 100644
--- a/components/drive/file_system_unittest.cc
+++ b/components/drive/file_system_unittest.cc
@@ -103,6 +103,8 @@
 class FileSystemTest : public testing::Test {
  protected:
   void SetUp() override {
+    base::CommandLine::ForCurrentProcess()->AppendSwitch(
+        google_apis::kEnableTeamDrives);
     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
     pref_service_.reset(new TestingPrefServiceSimple);
     test_util::RegisterDrivePrefs(pref_service_->registry());
@@ -310,6 +312,81 @@
     SetUpResourceMetadataAndFileSystem();
   }
 
+  // Sets up two team drives, team_drive_a and team_drive_b and creates the
+  // following:
+  // - Directories:
+  // -- team_drive_a/dir1
+  // -- team_drive_a/dir1/nested_1
+  // -- team_drive_b/dir2
+  //
+  // - Files:
+  // -- team_drive_a/dir1/file1
+  // -- team_drive_a/dir1/nested_1/file1
+  // -- team_drive_b/dir2/file2
+  bool SetupTeamDrives() {
+    fake_drive_service_->AddTeamDrive("td_id_1", "team_drive_1", "");
+    fake_drive_service_->AddTeamDrive("td_id_2", "team_drive_2", "");
+
+    google_apis::DriveApiErrorCode error = google_apis::DRIVE_OTHER_ERROR;
+    std::unique_ptr<google_apis::FileResource> entry;
+
+    fake_drive_service_->AddNewFileWithResourceId(
+        "td_1_dir_1_resource_id", util::kDriveFolderMimeType, std::string(),
+        "td_id_1", "dir1",
+        false,  // shared_with_me
+        google_apis::test_util::CreateCopyResultCallback(&error, &entry));
+    base::RunLoop().RunUntilIdle();
+    if (error != google_apis::HTTP_CREATED)
+      return false;
+
+    fake_drive_service_->AddNewFileWithResourceId(
+        "td_1_dir_nested_1_resource_id", util::kDriveFolderMimeType,
+        std::string(), "td_1_dir_1_resource_id", "nested_1",
+        false,  // shared_with_me
+        google_apis::test_util::CreateCopyResultCallback(&error, &entry));
+    base::RunLoop().RunUntilIdle();
+    if (error != google_apis::HTTP_CREATED)
+      return false;
+
+    fake_drive_service_->AddNewFileWithResourceId(
+        "td_2_dir_2_resource_id", util::kDriveFolderMimeType, std::string(),
+        "td_id_2", "dir2",
+        false,  // shared_with_me
+        google_apis::test_util::CreateCopyResultCallback(&error, &entry));
+    base::RunLoop().RunUntilIdle();
+    if (error != google_apis::HTTP_CREATED)
+      return false;
+
+    fake_drive_service_->AddNewFileWithResourceId(
+        "dir1_file_1_resource_id", "audio/mpeg", "dir 1 file 1 content.",
+        "td_1_dir_1_resource_id", "File 1.txt",
+        false,  // shared_with_me
+        google_apis::test_util::CreateCopyResultCallback(&error, &entry));
+    base::RunLoop().RunUntilIdle();
+    if (error != google_apis::HTTP_CREATED)
+      return false;
+
+    fake_drive_service_->AddNewFileWithResourceId(
+        "nested_1_file_1_resource_id", "audio/mpeg", "nested 1 file 1 content.",
+        "td_1_dir_nested_1_resource_id", "Nested File 1.txt",
+        false,  // shared_with_me
+        google_apis::test_util::CreateCopyResultCallback(&error, &entry));
+    base::RunLoop().RunUntilIdle();
+    if (error != google_apis::HTTP_CREATED)
+      return false;
+
+    fake_drive_service_->AddNewFileWithResourceId(
+        "dir_2_file_1_resource_id", "audio/mpeg", "dir2 file1 content.",
+        "td_2_dir_2_resource_id", "File 2.txt",
+        false,  // shared_with_me
+        google_apis::test_util::CreateCopyResultCallback(&error, &entry));
+    base::RunLoop().RunUntilIdle();
+    if (error != google_apis::HTTP_CREATED)
+      return false;
+
+    return true;
+  }
+
   content::TestBrowserThreadBundle thread_bundle_;
   base::ScopedTempDir temp_dir_;
   // We don't use TestingProfile::GetPrefs() in favor of having less
@@ -629,6 +706,16 @@
   EXPECT_EQ(1, fake_drive_service_->file_list_load_count());
 }
 
+TEST_F(FileSystemTest, GetTeamDriveRoot) {
+  const base::FilePath kFilePath(FILE_PATH_LITERAL("drive/team_drives"));
+  std::unique_ptr<ResourceEntry> entry = GetResourceEntrySync(kFilePath);
+  ASSERT_TRUE(entry);
+  EXPECT_EQ(util::kDriveTeamDrivesDirLocalId, entry->local_id());
+
+  // After "fast fetch" is done, full resource list is fetched.
+  EXPECT_EQ(1, fake_drive_service_->file_list_load_count());
+}
+
 TEST_F(FileSystemTest, GetExistingFile) {
   // Simulate the situation that full feed fetching takes very long time,
   // to test the recursive "fast fetch" feature is properly working.
@@ -686,20 +773,47 @@
       ReadDirectorySync(base::FilePath::FromUTF8Unsafe("drive")));
   // The root directory should be read correctly.
   ASSERT_TRUE(entries);
-  ASSERT_EQ(3U, entries->size());
+  ASSERT_EQ(4U, entries->size());
 
-  // The found three directories should be /drive/root, /drive/other and
-  // /drive/trash.
+  // The found three directories should be /drive/root, /drive/other,
+  // /drive/trash and /drive/team_drives.
   std::set<base::FilePath> found;
   for (size_t i = 0; i < entries->size(); ++i)
     found.insert(base::FilePath::FromUTF8Unsafe((*entries)[i].title()));
-  EXPECT_EQ(3U, found.size());
+  EXPECT_EQ(4U, found.size());
   EXPECT_EQ(1U, found.count(base::FilePath::FromUTF8Unsafe(
                     util::kDriveMyDriveRootDirName)));
   EXPECT_EQ(1U, found.count(
                     base::FilePath::FromUTF8Unsafe(util::kDriveOtherDirName)));
   EXPECT_EQ(1U, found.count(
                     base::FilePath::FromUTF8Unsafe(util::kDriveTrashDirName)));
+  EXPECT_EQ(1U, found.count(base::FilePath::FromUTF8Unsafe(
+                    util::kDriveTeamDrivesDirName)));
+}
+
+// TODO(slamgley): Add more tests for team drives.
+TEST_F(FileSystemTest, ReadDirectory_TeamDrivesRoot) {
+  ASSERT_TRUE(SetupTeamDrives());
+
+  // The first load trigger the loading of team drives.
+  ReadDirectorySync(base::FilePath::FromUTF8Unsafe("."));
+
+  // After the first load team drive data should be available for reading.
+  std::unique_ptr<ResourceEntryVector> entries(
+      ReadDirectorySync(base::FilePath::FromUTF8Unsafe("drive/team_drives")));
+  // The root directory should be read correctly.
+  ASSERT_TRUE(entries);
+  ASSERT_EQ(2U, entries->size());
+
+  // The found three directories should be /drive/root, /drive/other,
+  // /drive/trash and /drive/team_drives.
+  std::set<base::FilePath> found;
+  for (size_t i = 0; i < entries->size(); ++i) {
+    found.insert(base::FilePath::FromUTF8Unsafe((*entries)[i].title()));
+  }
+  EXPECT_EQ(2U, found.size());
+  EXPECT_EQ(1U, found.count(base::FilePath::FromUTF8Unsafe("team_drive_1")));
+  EXPECT_EQ(1U, found.count(base::FilePath::FromUTF8Unsafe("team_drive_2")));
 }
 
 TEST_F(FileSystemTest, ReadDirectory_NonRootDirectory) {
diff --git a/components/drive/service/fake_drive_service.cc b/components/drive/service/fake_drive_service.cc
index a3ac7c47b..8e76335 100644
--- a/components/drive/service/fake_drive_service.cc
+++ b/components/drive/service/fake_drive_service.cc
@@ -137,7 +137,7 @@
   file_list->set_next_link(change_list->next_link());
   for (size_t i = 0; i < change_list->items().size(); ++i) {
     const ChangeResource& entry = *change_list->items()[i];
-    if (entry.file())
+    if (entry.type() == ChangeResource::FILE && entry.file())
       file_list->mutable_items()->push_back(
           std::make_unique<FileResource>(*entry.file()));
   }
@@ -443,6 +443,11 @@
   if (load_counter)
     ++*load_counter;
 
+  // If max_results is zero then we want to return the entire list.
+  if (max_results <= 0) {
+    max_results = team_drive_value_.size();
+  }
+
   std::unique_ptr<TeamDriveList> result;
   result.reset(new TeamDriveList);
   size_t next_start_offset = start_offset + max_results;
diff --git a/components/exo/wayland/server.cc b/components/exo/wayland/server.cc
index 21fa155..cc89928 100644
--- a/components/exo/wayland/server.cc
+++ b/components/exo/wayland/server.cc
@@ -2169,7 +2169,7 @@
   if (type == ZCR_REMOTE_SURFACE_V1_WINDOW_TYPE_SYSTEM_UI) {
     auto* widget = GetUserDataAs<ShellSurfaceBase>(resource)->GetWidget();
     if (widget) {
-      widget->GetNativeWindow()->SetProperty(ash::kShowInOverviewKey, false);
+      widget->GetNativeWindow()->SetProperty(ash::kHideInOverviewKey, true);
 
       wm::SetWindowVisibilityAnimationType(
           widget->GetNativeWindow(), wm::WINDOW_VISIBILITY_ANIMATION_TYPE_FADE);
diff --git a/components/history/core/browser/history_backend_unittest.cc b/components/history/core/browser/history_backend_unittest.cc
index fd060d8..03e1347 100644
--- a/components/history/core/browser/history_backend_unittest.cc
+++ b/components/history/core/browser/history_backend_unittest.cc
@@ -1232,11 +1232,8 @@
   backend_->DeleteAllHistory();
 
   // Visit the url with username, password.
-  backend_->AddPageVisit(
-      url, base::Time::Now(), 0,
-      ui::PageTransitionFromInt(
-          ui::PageTransitionGetQualifier(ui::PAGE_TRANSITION_TYPED)),
-      false, history::SOURCE_BROWSED, true);
+  backend_->AddPageVisit(url, base::Time::Now(), 0, ui::PAGE_TRANSITION_TYPED,
+                         false, history::SOURCE_BROWSED, true);
 
   // Fetch the row information about stripped url from history db.
   VisitVector visits;
@@ -1383,19 +1380,13 @@
   base::Time older_time = recent_time - visit_age;
 
   // Visit the url with recent time.
-  backend_->AddPageVisit(
-      url, recent_time, 0,
-      ui::PageTransitionFromInt(
-          ui::PageTransitionGetQualifier(ui::PAGE_TRANSITION_TYPED)),
-      false, history::SOURCE_BROWSED, false);
+  backend_->AddPageVisit(url, recent_time, 0, ui::PAGE_TRANSITION_TYPED, false,
+                         history::SOURCE_BROWSED, true);
 
   // Add to the url a visit with older time (could be syncing from another
   // client, etc.).
-  backend_->AddPageVisit(
-      url, older_time, 0,
-      ui::PageTransitionFromInt(
-          ui::PageTransitionGetQualifier(ui::PAGE_TRANSITION_TYPED)),
-      false, history::SOURCE_SYNCED, false);
+  backend_->AddPageVisit(url, older_time, 0, ui::PAGE_TRANSITION_TYPED, false,
+                         history::SOURCE_SYNCED, true);
 
   // Fetch the row information about url from history db.
   VisitVector visits;
diff --git a/components/invalidation/impl/gcm_invalidation_bridge.cc b/components/invalidation/impl/gcm_invalidation_bridge.cc
index 30df77d..c9f7847d 100644
--- a/components/invalidation/impl/gcm_invalidation_bridge.cc
+++ b/components/invalidation/impl/gcm_invalidation_bridge.cc
@@ -240,8 +240,7 @@
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   OAuth2TokenService::ScopeSet scopes;
   scopes.insert(GaiaConstants::kChromeSyncOAuth2Scope);
-  identity_provider_->GetTokenService()->InvalidateAccessToken(
-      identity_provider_->GetActiveAccountId(), scopes, token);
+  identity_provider_->InvalidateAccessToken(scopes, token);
 }
 
 void GCMInvalidationBridge::Register(
diff --git a/components/invalidation/impl/ticl_invalidation_service.cc b/components/invalidation/impl/ticl_invalidation_service.cc
index 393fec02..b973f049a 100644
--- a/components/invalidation/impl/ticl_invalidation_service.cc
+++ b/components/invalidation/impl/ticl_invalidation_service.cc
@@ -187,12 +187,9 @@
   OAuth2TokenService::ScopeSet oauth2_scopes;
   for (size_t i = 0; i < arraysize(kOAuth2Scopes); i++)
     oauth2_scopes.insert(kOAuth2Scopes[i]);
-  // Invalidate previous token, otherwise token service will return the same
-  // token again.
-  const std::string& account_id = identity_provider_->GetActiveAccountId();
-  OAuth2TokenService* token_service = identity_provider_->GetTokenService();
-  token_service->InvalidateAccessToken(account_id, oauth2_scopes,
-                                       access_token_);
+  // Invalidate previous token, otherwise the identity provider will return the
+  // same token again.
+  identity_provider_->InvalidateAccessToken(oauth2_scopes, access_token_);
   access_token_.clear();
   access_token_fetcher_ = identity_provider_->FetchAccessToken(
       "ticl_invalidation", oauth2_scopes,
diff --git a/components/invalidation/impl/ticl_invalidation_service.h b/components/invalidation/impl/ticl_invalidation_service.h
index d78d870..8b18fe13 100644
--- a/components/invalidation/impl/ticl_invalidation_service.h
+++ b/components/invalidation/impl/ticl_invalidation_service.h
@@ -21,7 +21,6 @@
 #include "components/invalidation/public/invalidation_handler.h"
 #include "components/invalidation/public/invalidation_service.h"
 #include "components/keyed_service/core/keyed_service.h"
-#include "google_apis/gaia/oauth2_token_service.h"
 #include "net/base/backoff_entry.h"
 
 namespace gcm {
@@ -131,7 +130,7 @@
   std::unique_ptr<syncer::Invalidator> invalidator_;
 
   // TiclInvalidationService needs to remember access token in order to
-  // invalidate it with OAuth2TokenService.
+  // invalidate it with IdentityProvider.
   std::string access_token_;
 
   // TiclInvalidationService needs to hold reference to access_token_fetcher_
diff --git a/components/invalidation/public/identity_provider.cc b/components/invalidation/public/identity_provider.cc
index fbe6070..804e506 100644
--- a/components/invalidation/public/identity_provider.cc
+++ b/components/invalidation/public/identity_provider.cc
@@ -88,6 +88,13 @@
       std::move(callback));
 }
 
+void IdentityProvider::InvalidateAccessToken(
+    const OAuth2TokenService::ScopeSet& scopes,
+    const std::string& access_token) {
+  GetTokenService()->InvalidateAccessToken(GetActiveAccountId(), scopes,
+                                           access_token);
+}
+
 void IdentityProvider::AddObserver(Observer* observer) {
   // See the comment on |num_observers_| in the .h file for why this addition
   // must happen here.
diff --git a/components/invalidation/public/identity_provider.h b/components/invalidation/public/identity_provider.h
index c42c3f2e..47e12546 100644
--- a/components/invalidation/public/identity_provider.h
+++ b/components/invalidation/public/identity_provider.h
@@ -66,11 +66,6 @@
   // a refresh token.
   virtual bool IsActiveAccountAvailable() = 0;
 
-  // DEPRECATED: Do not add further usage of this API, as it is in the process
-  // of being removed. See https://crbug.com/809452.
-  // Gets the token service vending OAuth tokens for all logged-in accounts.
-  virtual OAuth2TokenService* GetTokenService() = 0;
-
   // Starts an access token request for |oauth_consumer_name| and |scopes|. When
   // the request completes, |callback| will be invoked with the access token
   // or error. To cancel the request, destroy the returned TokenFetcher.
@@ -80,6 +75,11 @@
 
       ActiveAccountAccessTokenCallback callback);
 
+  // Marks an OAuth2 |access_token| issued for the active account and |scopes|
+  // as invalid.
+  void InvalidateAccessToken(const OAuth2TokenService::ScopeSet& scopes,
+                             const std::string& access_token);
+
   void AddObserver(Observer* observer);
   void RemoveObserver(Observer* observer);
 
@@ -90,6 +90,11 @@
  protected:
   IdentityProvider();
 
+  // DEPRECATED: Do not add further usage of this API, as it is in the process
+  // of being removed. See https://crbug.com/809452.
+  // Gets the token service vending OAuth tokens for all logged-in accounts.
+  virtual OAuth2TokenService* GetTokenService() = 0;
+
   // Fires an OnActiveAccountLogin notification.
   void FireOnActiveAccountLogin();
 
diff --git a/components/navigation_interception/BUILD.gn b/components/navigation_interception/BUILD.gn
index 4b2ba36..16b17d6 100644
--- a/components/navigation_interception/BUILD.gn
+++ b/components/navigation_interception/BUILD.gn
@@ -51,6 +51,7 @@
   deps = [
     ":navigation_interception",
     "//base",
+    "//base/test:test_support",
     "//content/public/browser",
     "//content/test:test_support",
     "//testing/gmock",
diff --git a/components/navigation_interception/intercept_navigation_throttle.cc b/components/navigation_interception/intercept_navigation_throttle.cc
index 81acec4..da7f874 100644
--- a/components/navigation_interception/intercept_navigation_throttle.cc
+++ b/components/navigation_interception/intercept_navigation_throttle.cc
@@ -4,31 +4,38 @@
 
 #include "components/navigation_interception/intercept_navigation_throttle.h"
 
+#include "base/bind.h"
 #include "base/metrics/histogram_macros.h"
+#include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
 #include "base/timer/elapsed_timer.h"
-#include "components/navigation_interception/navigation_params.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/navigation_handle.h"
-
-using content::BrowserThread;
+#include "url/gurl.h"
 
 namespace navigation_interception {
 
+const base::Feature InterceptNavigationThrottle::kAsyncCheck{
+    "AsyncNavigationIntercept", base::FEATURE_DISABLED_BY_DEFAULT};
+
 InterceptNavigationThrottle::InterceptNavigationThrottle(
     content::NavigationHandle* navigation_handle,
     CheckCallback should_ignore_callback)
     : content::NavigationThrottle(navigation_handle),
-      should_ignore_callback_(should_ignore_callback) {}
+      should_ignore_callback_(should_ignore_callback),
+      ui_task_runner_(base::ThreadTaskRunnerHandle::Get()),
+      weak_factory_(this) {}
 
-InterceptNavigationThrottle::~InterceptNavigationThrottle() {}
+InterceptNavigationThrottle::~InterceptNavigationThrottle() {
+  UMA_HISTOGRAM_BOOLEAN("Navigation.Intercept.Ignored", should_ignore_);
+}
 
 content::NavigationThrottle::ThrottleCheckResult
 InterceptNavigationThrottle::WillStartRequest() {
-  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  DCHECK(!should_ignore_);
   base::ElapsedTimer timer;
 
-  auto result = CheckIfShouldIgnoreNavigation(false);
+  auto result = CheckIfShouldIgnoreNavigation(false /* is_redirect */);
   UMA_HISTOGRAM_COUNTS_10M("Navigation.Intercept.WillStart",
                            timer.Elapsed().InMicroseconds());
   return result;
@@ -36,8 +43,19 @@
 
 content::NavigationThrottle::ThrottleCheckResult
 InterceptNavigationThrottle::WillRedirectRequest() {
-  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  return CheckIfShouldIgnoreNavigation(true);
+  if (should_ignore_)
+    return content::NavigationThrottle::CANCEL_AND_IGNORE;
+  return CheckIfShouldIgnoreNavigation(true /* is_redirect */);
+}
+
+content::NavigationThrottle::ThrottleCheckResult
+InterceptNavigationThrottle::WillFailRequest() {
+  return WillFinish();
+}
+
+content::NavigationThrottle::ThrottleCheckResult
+InterceptNavigationThrottle::WillProcessResponse() {
+  return WillFinish();
 }
 
 const char* InterceptNavigationThrottle::GetNameForLogging() {
@@ -45,19 +63,69 @@
 }
 
 content::NavigationThrottle::ThrottleCheckResult
+InterceptNavigationThrottle::WillFinish() {
+  DCHECK(!deferring_);
+  if (should_ignore_)
+    return content::NavigationThrottle::CANCEL_AND_IGNORE;
+
+  if (pending_checks_ > 0) {
+    deferring_ = true;
+    return content::NavigationThrottle::DEFER;
+  }
+
+  return content::NavigationThrottle::PROCEED;
+}
+
+content::NavigationThrottle::ThrottleCheckResult
 InterceptNavigationThrottle::CheckIfShouldIgnoreNavigation(bool is_redirect) {
-  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  NavigationParams navigation_params(
+  pending_checks_++;
+  if (ShouldCheckAsynchronously()) {
+    ui_task_runner_->PostTask(
+        FROM_HERE, base::BindOnce(&InterceptNavigationThrottle::RunCheck,
+                                  weak_factory_.GetWeakPtr(),
+                                  GetNavigationParams(is_redirect)));
+    return content::NavigationThrottle::PROCEED;
+  }
+  RunCheck(GetNavigationParams(is_redirect));
+  return should_ignore_ ? content::NavigationThrottle::CANCEL_AND_IGNORE
+                        : content::NavigationThrottle::PROCEED;
+}
+
+void InterceptNavigationThrottle::RunCheck(const NavigationParams& params) {
+  should_ignore_ |= should_ignore_callback_.Run(
+      navigation_handle()->GetWebContents(), params);
+  DCHECK_GT(pending_checks_, 0);
+  pending_checks_--;
+  if (!deferring_ || pending_checks_ > 0)
+    return;
+
+  if (should_ignore_) {
+    CancelDeferredNavigation(content::NavigationThrottle::CANCEL_AND_IGNORE);
+  } else {
+    Resume();
+  }
+}
+
+bool InterceptNavigationThrottle::ShouldCheckAsynchronously() const {
+  // Do not apply the async optimization for:
+  // - POST navigations, to ensure we aren't violating idempotency.
+  // - Subframe navigations, which aren't observed on Android, and should be
+  //   fast on other platforms.
+  // - non-http/s URLs, which are more likely to be intercepted.
+  return navigation_handle()->IsInMainFrame() &&
+         !navigation_handle()->IsPost() &&
+         navigation_handle()->GetURL().SchemeIsHTTPOrHTTPS() &&
+         base::FeatureList::IsEnabled(kAsyncCheck);
+}
+
+NavigationParams InterceptNavigationThrottle::GetNavigationParams(
+    bool is_redirect) const {
+  return NavigationParams(
       navigation_handle()->GetURL(), navigation_handle()->GetReferrer(),
       navigation_handle()->HasUserGesture(), navigation_handle()->IsPost(),
       navigation_handle()->GetPageTransition(), is_redirect,
       navigation_handle()->IsExternalProtocol(), true,
       navigation_handle()->GetBaseURLForDataURL());
-  bool should_ignore_navigation = should_ignore_callback_.Run(
-      navigation_handle()->GetWebContents(), navigation_params);
-  return should_ignore_navigation
-             ? content::NavigationThrottle::CANCEL_AND_IGNORE
-             : content::NavigationThrottle::PROCEED;
 }
 
 }  // namespace navigation_interception
diff --git a/components/navigation_interception/intercept_navigation_throttle.h b/components/navigation_interception/intercept_navigation_throttle.h
index 7607fd5f..b7ac2de 100644
--- a/components/navigation_interception/intercept_navigation_throttle.h
+++ b/components/navigation_interception/intercept_navigation_throttle.h
@@ -5,11 +5,13 @@
 #ifndef COMPONENTS_NAVIGATION_INTERCEPTION_INTERCEPT_NAVIGATION_THROTTLE_H_
 #define COMPONENTS_NAVIGATION_INTERCEPTION_INTERCEPT_NAVIGATION_THROTTLE_H_
 
-#include <string>
-
 #include "base/callback.h"
+#include "base/feature_list.h"
 #include "base/macros.h"
+#include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
+#include "base/single_thread_task_runner.h"
+#include "components/navigation_interception/navigation_params.h"
 #include "content/public/browser/navigation_throttle.h"
 
 namespace content {
@@ -25,10 +27,13 @@
 // level navigations. This is a UI thread class.
 class InterceptNavigationThrottle : public content::NavigationThrottle {
  public:
-  typedef base::Callback<bool(content::WebContents* /* source */,
-                              const NavigationParams& /* navigation_params */)>
+  typedef base::RepeatingCallback<bool(
+      content::WebContents* /* source */,
+      const NavigationParams& /* navigation_params */)>
       CheckCallback;
 
+  static const base::Feature kAsyncCheck;
+
   InterceptNavigationThrottle(content::NavigationHandle* navigation_handle,
                               CheckCallback should_ignore_callback);
   ~InterceptNavigationThrottle() override;
@@ -36,13 +41,43 @@
   // content::NavigationThrottle implementation:
   ThrottleCheckResult WillStartRequest() override;
   ThrottleCheckResult WillRedirectRequest() override;
+  ThrottleCheckResult WillFailRequest() override;
+  ThrottleCheckResult WillProcessResponse() override;
   const char* GetNameForLogging() override;
 
  private:
-  ThrottleCheckResult CheckIfShouldIgnoreNavigation(bool is_redirect);
+  // To be called on either WillFailRequest or WillProcessResponse.
+  ThrottleCheckResult WillFinish();
 
+  ThrottleCheckResult CheckIfShouldIgnoreNavigation(bool is_redirect);
+  void RunCheck(const NavigationParams& params);
+
+  bool ShouldCheckAsynchronously() const;
+
+  // Constructs NavigationParams for this navigation.
+  NavigationParams GetNavigationParams(bool is_redirect) const;
+
+  // This callback should be called at the start of navigation and every
+  // redirect, until |should_ignore_| is true.
   CheckCallback should_ignore_callback_;
 
+  // Note that the CheckCallback currently has thread affinity on the Java side.
+  scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_;
+
+  // How many outbound pending checks are running. Normally this will be either
+  // 0 or 1, but making this a bool makes too many assumptions about the nature
+  // of Chrome's task queues (e.g. we could be scheduled after the task which
+  // redirects the navigation).
+  int pending_checks_ = 0;
+
+  // Whether the navigation should be ignored. Updated at every redirect.
+  bool should_ignore_ = false;
+
+  // Whether the navigation is currently deferred.
+  bool deferring_ = false;
+
+  base::WeakPtrFactory<InterceptNavigationThrottle> weak_factory_;
+
   DISALLOW_COPY_AND_ASSIGN(InterceptNavigationThrottle);
 };
 
diff --git a/components/navigation_interception/intercept_navigation_throttle_unittest.cc b/components/navigation_interception/intercept_navigation_throttle_unittest.cc
index 7a456d6..cbd25b4 100644
--- a/components/navigation_interception/intercept_navigation_throttle_unittest.cc
+++ b/components/navigation_interception/intercept_navigation_throttle_unittest.cc
@@ -9,6 +9,7 @@
 
 #include "base/bind.h"
 #include "base/bind_helpers.h"
+#include "base/test/scoped_feature_list.h"
 #include "components/navigation_interception/navigation_params.h"
 #include "content/public/browser/navigation_handle.h"
 #include "content/public/browser/navigation_throttle.h"
@@ -57,10 +58,19 @@
 // InterceptNavigationThrottleTest ------------------------------------
 
 class InterceptNavigationThrottleTest
-    : public content::RenderViewHostTestHarness {
+    : public content::RenderViewHostTestHarness,
+      public testing::WithParamInterface<bool> {
  public:
   InterceptNavigationThrottleTest()
-      : mock_callback_receiver_(new MockInterceptCallbackReceiver()) {}
+      : mock_callback_receiver_(new MockInterceptCallbackReceiver()) {
+    if (GetParam()) {
+      scoped_feature_.InitAndEnableFeature(
+          InterceptNavigationThrottle::kAsyncCheck);
+    } else {
+      scoped_feature_.InitAndDisableFeature(
+          InterceptNavigationThrottle::kAsyncCheck);
+    }
+  }
 
   std::unique_ptr<content::NavigationThrottle> CreateThrottle(
       content::NavigationHandle* handle) {
@@ -105,11 +115,12 @@
     return simulator->GetLastThrottleCheckResult();
   }
 
+  base::test::ScopedFeatureList scoped_feature_;
   std::unique_ptr<MockInterceptCallbackReceiver> mock_callback_receiver_;
 };
 
-TEST_F(InterceptNavigationThrottleTest,
-       RequestDeferredAndResumedIfNavigationNotIgnored) {
+TEST_P(InterceptNavigationThrottleTest,
+       RequestCompletesIfNavigationNotIgnored) {
   ON_CALL(*mock_callback_receiver_, ShouldIgnoreNavigation(_, _))
       .WillByDefault(Return(false));
   EXPECT_CALL(
@@ -121,8 +132,7 @@
   EXPECT_EQ(NavigationThrottle::PROCEED, result);
 }
 
-TEST_F(InterceptNavigationThrottleTest,
-       RequestDeferredAndCancelledIfNavigationIgnored) {
+TEST_P(InterceptNavigationThrottleTest, RequestCancelledIfNavigationIgnored) {
   ON_CALL(*mock_callback_receiver_, ShouldIgnoreNavigation(_, _))
       .WillByDefault(Return(true));
   EXPECT_CALL(
@@ -134,7 +144,7 @@
   EXPECT_EQ(NavigationThrottle::CANCEL_AND_IGNORE, result);
 }
 
-TEST_F(InterceptNavigationThrottleTest, CallbackIsPostFalseForGet) {
+TEST_P(InterceptNavigationThrottleTest, CallbackIsPostFalseForGet) {
   EXPECT_CALL(*mock_callback_receiver_,
               ShouldIgnoreNavigation(
                   _, AllOf(NavigationParamsUrlIsTest(),
@@ -147,7 +157,7 @@
   EXPECT_EQ(NavigationThrottle::PROCEED, result);
 }
 
-TEST_F(InterceptNavigationThrottleTest, CallbackIsPostTrueForPost) {
+TEST_P(InterceptNavigationThrottleTest, CallbackIsPostTrueForPost) {
   EXPECT_CALL(*mock_callback_receiver_,
               ShouldIgnoreNavigation(
                   _, AllOf(NavigationParamsUrlIsTest(),
@@ -159,7 +169,7 @@
   EXPECT_EQ(NavigationThrottle::PROCEED, result);
 }
 
-TEST_F(InterceptNavigationThrottleTest,
+TEST_P(InterceptNavigationThrottleTest,
        CallbackIsPostFalseForPostConvertedToGetBy302) {
   EXPECT_CALL(*mock_callback_receiver_,
               ShouldIgnoreNavigation(
@@ -178,13 +188,9 @@
 }
 
 // Ensure POST navigations are cancelled before the start.
-TEST_F(InterceptNavigationThrottleTest, PostNavigationCancelledAtStart) {
-  EXPECT_CALL(*mock_callback_receiver_,
-              ShouldIgnoreNavigation(
-                  _, AllOf(NavigationParamsUrlIsTest(),
-                           Property(&NavigationParams::is_post, Eq(true)))))
-      .WillOnce(Return(true));
-
+TEST_P(InterceptNavigationThrottleTest, PostNavigationCancelledAtStart) {
+  ON_CALL(*mock_callback_receiver_, ShouldIgnoreNavigation(_, _))
+      .WillByDefault(Return(true));
   auto throttle_inserter = CreateThrottleInserter();
   std::unique_ptr<content::NavigationSimulator> simulator =
       content::NavigationSimulator::CreateRendererInitiated(GURL(kTestUrl),
@@ -195,4 +201,8 @@
   EXPECT_EQ(NavigationThrottle::CANCEL_AND_IGNORE, result);
 }
 
+INSTANTIATE_TEST_CASE_P(,
+                        InterceptNavigationThrottleTest,
+                        testing::Values(true, false));
+
 }  // namespace navigation_interception
diff --git a/components/ntp_snippets/contextual/contextual_content_suggestions_service.cc b/components/ntp_snippets/contextual/contextual_content_suggestions_service.cc
index 91a1a941..5746b61 100644
--- a/components/ntp_snippets/contextual/contextual_content_suggestions_service.cc
+++ b/components/ntp_snippets/contextual/contextual_content_suggestions_service.cc
@@ -99,6 +99,20 @@
   std::move(callback).Run(result);
 }
 
+ContextualSuggestionsDebuggingReporter*
+ContextualContentSuggestionsService::GetDebuggingReporter() {
+  return reporter_provider_->GetDebuggingReporter();
+}
+
+base::flat_map<GURL, ContextualSuggestionsResult>
+ContextualContentSuggestionsService::GetAllCachedResultsForDebugging() {
+  return fetch_cache_.GetAllCachedResultsForDebugging();
+}
+
+void ContextualContentSuggestionsService::ClearCachedResultsForDebugging() {
+  fetch_cache_.Clear();
+}
+
 std::unique_ptr<
     contextual_suggestions::ContextualContentSuggestionsServiceProxy>
 ContextualContentSuggestionsService::CreateProxy() {
diff --git a/components/ntp_snippets/contextual/contextual_content_suggestions_service.h b/components/ntp_snippets/contextual/contextual_content_suggestions_service.h
index 0dd1d73..1100a89 100644
--- a/components/ntp_snippets/contextual/contextual_content_suggestions_service.h
+++ b/components/ntp_snippets/contextual/contextual_content_suggestions_service.h
@@ -17,6 +17,7 @@
 #include "components/ntp_snippets/callbacks.h"
 #include "components/ntp_snippets/content_suggestion.h"
 #include "components/ntp_snippets/contextual/contextual_suggestions_cache.h"
+#include "components/ntp_snippets/contextual/contextual_suggestions_debugging_reporter.h"
 #include "components/ntp_snippets/contextual/contextual_suggestions_fetcher.h"
 #include "components/ntp_snippets/contextual/contextual_suggestions_reporter.h"
 #include "services/metrics/public/cpp/ukm_source_id.h"
@@ -65,6 +66,16 @@
                  ReportFetchMetricsCallback metrics_callback,
                  ContextualSuggestionsResult result);
 
+  // Used to surface metrics events via chrome://eoc-internals.
+  ContextualSuggestionsDebuggingReporter* GetDebuggingReporter();
+
+  // Expose cached results for debugging.
+  base::flat_map<GURL, ContextualSuggestionsResult>
+  GetAllCachedResultsForDebugging();
+
+  // Clear the cached results for debugging.
+  void ClearCachedResultsForDebugging();
+
   std::unique_ptr<ContextualContentSuggestionsServiceProxy> CreateProxy();
 
  private:
diff --git a/components/ntp_snippets/contextual/contextual_suggestions_cache.cc b/components/ntp_snippets/contextual/contextual_suggestions_cache.cc
index 71c90d1..07b282d 100644
--- a/components/ntp_snippets/contextual/contextual_suggestions_cache.cc
+++ b/components/ntp_snippets/contextual/contextual_suggestions_cache.cc
@@ -10,6 +10,12 @@
     : cache_(capacity) {}
 ContextualSuggestionsCache::~ContextualSuggestionsCache() = default;
 
+base::flat_map<GURL, ContextualSuggestionsResult>
+ContextualSuggestionsCache::GetAllCachedResultsForDebugging() {
+  return base::flat_map<GURL, ContextualSuggestionsResult>(cache_.begin(),
+                                                           cache_.end());
+}
+
 bool ContextualSuggestionsCache::GetSuggestionsResult(
     const GURL& url,
     ContextualSuggestionsResult* result) {
diff --git a/components/ntp_snippets/contextual/contextual_suggestions_cache.h b/components/ntp_snippets/contextual/contextual_suggestions_cache.h
index 0e7ad35..b1639bd 100644
--- a/components/ntp_snippets/contextual/contextual_suggestions_cache.h
+++ b/components/ntp_snippets/contextual/contextual_suggestions_cache.h
@@ -5,6 +5,7 @@
 #ifndef COMPONENTS_NTP_SNIPPETS_CONTEXTUAL_CONTEXTUAL_SUGGESTIONS_CACHE_H_
 #define COMPONENTS_NTP_SNIPPETS_CONTEXTUAL_CONTEXTUAL_SUGGESTIONS_CACHE_H_
 
+#include "base/containers/flat_map.h"
 #include "base/containers/mru_cache.h"
 #include "components/ntp_snippets/contextual/contextual_suggestions_result.h"
 #include "url/gurl.h"
@@ -30,6 +31,10 @@
   // Removes all items from the cache.
   void Clear();
 
+  // Returns all suggestion results for debugging purposes.
+  base::flat_map<GURL, ContextualSuggestionsResult>
+  GetAllCachedResultsForDebugging();
+
  private:
   base::MRUCache<GURL, ContextualSuggestionsResult> cache_;
 };
diff --git a/components/ntp_snippets/contextual/contextual_suggestions_debugging_reporter.cc b/components/ntp_snippets/contextual/contextual_suggestions_debugging_reporter.cc
index 94d206ce..4726028 100644
--- a/components/ntp_snippets/contextual/contextual_suggestions_debugging_reporter.cc
+++ b/components/ntp_snippets/contextual/contextual_suggestions_debugging_reporter.cc
@@ -23,6 +23,10 @@
   return events_;
 }
 
+void ContextualSuggestionsDebuggingReporter::ClearEvents() {
+  events_.clear();
+}
+
 void ContextualSuggestionsDebuggingReporter::SetupForPage(
     const std::string& url,
     ukm::SourceId source_id) {
diff --git a/components/ntp_snippets/contextual/contextual_suggestions_debugging_reporter.h b/components/ntp_snippets/contextual/contextual_suggestions_debugging_reporter.h
index 2baf1d9..f06c22c3 100644
--- a/components/ntp_snippets/contextual/contextual_suggestions_debugging_reporter.h
+++ b/components/ntp_snippets/contextual/contextual_suggestions_debugging_reporter.h
@@ -47,6 +47,9 @@
   // Get all events currently in the buffer.
   const std::vector<ContextualSuggestionsDebuggingEvent>& GetEvents() const;
 
+  // Clear the debugging cache of events.
+  void ClearEvents();
+
   // ContextualSuggestionsReporter
   void SetupForPage(const std::string& url, ukm::SourceId source_id) override;
   void RecordEvent(
diff --git a/components/ntp_snippets/contextual/contextual_suggestions_reporter.cc b/components/ntp_snippets/contextual/contextual_suggestions_reporter.cc
index 12ca2fb..ec68d6f 100644
--- a/components/ntp_snippets/contextual/contextual_suggestions_reporter.cc
+++ b/components/ntp_snippets/contextual/contextual_suggestions_reporter.cc
@@ -28,6 +28,11 @@
   return reporter;
 }
 
+ContextualSuggestionsDebuggingReporter*
+ContextualSuggestionsReporterProvider::GetDebuggingReporter() {
+  return debugging_reporter_.get();
+}
+
 ContextualSuggestionsReporter::ContextualSuggestionsReporter() = default;
 ContextualSuggestionsReporter::~ContextualSuggestionsReporter() = default;
 
diff --git a/components/ntp_snippets/contextual/contextual_suggestions_reporter.h b/components/ntp_snippets/contextual/contextual_suggestions_reporter.h
index b57e6e0..3ab9726 100644
--- a/components/ntp_snippets/contextual/contextual_suggestions_reporter.h
+++ b/components/ntp_snippets/contextual/contextual_suggestions_reporter.h
@@ -29,6 +29,8 @@
 
   virtual std::unique_ptr<ContextualSuggestionsReporter> CreateReporter();
 
+  virtual ContextualSuggestionsDebuggingReporter* GetDebuggingReporter();
+
  private:
   // The debugging reporter is shared between instances of top-level reporter.
   // Since multiple objects need a reference to this, it's kept as a unique
diff --git a/components/omnibox/OWNERS b/components/omnibox/OWNERS
index 8e9f2fec..7c00bc4 100644
--- a/components/omnibox/OWNERS
+++ b/components/omnibox/OWNERS
@@ -3,6 +3,4 @@
 pkasting@chromium.org
 tommycli@chromium.org
 
-per-file clipboard_url_provider.*=jif@chromium.org
-
 # COMPONENT: UI>Browser>Omnibox
diff --git a/components/omnibox/browser/OWNERS b/components/omnibox/browser/OWNERS
new file mode 100644
index 0000000..f702b0d
--- /dev/null
+++ b/components/omnibox/browser/OWNERS
@@ -0,0 +1,3 @@
+per-file clipboard_url_provider.*=jif@chromium.org
+
+# COMPONENT: UI>Browser>Omnibox
diff --git a/components/omnibox/browser/omnibox_edit_model.cc b/components/omnibox/browser/omnibox_edit_model.cc
index 96b99567..59fc322 100644
--- a/components/omnibox/browser/omnibox_edit_model.cc
+++ b/components/omnibox/browser/omnibox_edit_model.cc
@@ -444,6 +444,9 @@
   if (!client_->IsPasteAndGoEnabled())
     return false;
 
+  if (text.length() > kMaxPasteAndGoTextLength)
+    return false;
+
   AutocompleteMatch match;
   ClassifyString(text, &match, nullptr);
   return match.destination_url.is_valid();
@@ -622,17 +625,12 @@
   fake_single_entry_result.AppendMatches(input_, fake_single_entry_matches);
   OmniboxLog log(
       input_.from_omnibox_focus() ? base::string16() : input_text,
-      just_deleted_text_,
-      input_.type(),
-      popup_open,
-      dropdown_ignored ? 0 : index,
-      disposition,
-      !pasted_text.empty(),
-      SessionID::InvalidValue(), // don't know tab ID; set later if appropriate
-      ClassifyPage(),
-      elapsed_time_since_user_first_modified_omnibox,
-      match.allowed_to_be_default_match ? match.inline_autocompletion.length() :
-          base::string16::npos,
+      just_deleted_text_, input_.type(), popup_open,
+      dropdown_ignored ? 0 : index, disposition, !pasted_text.empty(),
+      SessionID::InvalidValue(),  // don't know tab ID; set later if appropriate
+      ClassifyPage(), elapsed_time_since_user_first_modified_omnibox,
+      match.allowed_to_be_default_match ? match.inline_autocompletion.length()
+                                        : base::string16::npos,
       elapsed_time_since_last_change_to_default_match,
       dropdown_ignored ? fake_single_entry_result : result());
   DCHECK(dropdown_ignored ||
diff --git a/components/omnibox/browser/omnibox_edit_model.h b/components/omnibox/browser/omnibox_edit_model.h
index 75ba220..445d76f 100644
--- a/components/omnibox/browser/omnibox_edit_model.h
+++ b/components/omnibox/browser/omnibox_edit_model.h
@@ -81,6 +81,11 @@
     const AutocompleteInput autocomplete_input;
   };
 
+  // This is a mirror of content::kMaxURLDisplayChars because ios cannot depend
+  // on content. If clipboard contains more than kMaxPasteAndGoTextLength
+  // characters, then the paste & go option will be disabled.
+  static const size_t kMaxPasteAndGoTextLength = 32 * 1024;
+
   OmniboxEditModel(OmniboxView* view,
                    OmniboxEditController* controller,
                    std::unique_ptr<OmniboxClient> client);
diff --git a/components/omnibox/browser/omnibox_edit_model_unittest.cc b/components/omnibox/browser/omnibox_edit_model_unittest.cc
index 06e633cb..9a6f88f2 100644
--- a/components/omnibox/browser/omnibox_edit_model_unittest.cc
+++ b/components/omnibox/browser/omnibox_edit_model_unittest.cc
@@ -7,6 +7,7 @@
 #include <stddef.h>
 
 #include <memory>
+#include <string>
 
 #include "base/test/scoped_feature_list.h"
 #include "base/test/scoped_task_environment.h"
@@ -260,3 +261,16 @@
   AutocompleteMatch match = model()->OmniboxEditModel::CurrentMatch(nullptr);
   EXPECT_EQ(AutocompleteMatchType::URL_WHAT_YOU_TYPED, match.type);
 }
+
+TEST_F(OmniboxEditModelTest, DisablePasteAndGoForLongTexts) {
+  EXPECT_TRUE(model()->OmniboxEditModel::CanPasteAndGo(
+      base::ASCIIToUTF16("short text")));
+
+  base::string16 almost_long_text = base::ASCIIToUTF16(
+      std::string(OmniboxEditModel::kMaxPasteAndGoTextLength, '.'));
+  EXPECT_TRUE(model()->OmniboxEditModel::CanPasteAndGo(almost_long_text));
+
+  base::string16 long_text = base::ASCIIToUTF16(
+      std::string(OmniboxEditModel::kMaxPasteAndGoTextLength + 1, '.'));
+  EXPECT_FALSE(model()->OmniboxEditModel::CanPasteAndGo(long_text));
+}
diff --git a/components/omnibox/browser/test_omnibox_client.cc b/components/omnibox/browser/test_omnibox_client.cc
index 704722d..67ffc32 100644
--- a/components/omnibox/browser/test_omnibox_client.cc
+++ b/components/omnibox/browser/test_omnibox_client.cc
@@ -61,6 +61,10 @@
   return nullptr;
 }
 
+bool TestOmniboxClient::IsPasteAndGoEnabled() const {
+  return true;
+}
+
 const SessionID& TestOmniboxClient::GetSessionID() const {
   return session_id_;
 }
diff --git a/components/omnibox/browser/test_omnibox_client.h b/components/omnibox/browser/test_omnibox_client.h
index 2ace16fe..e7ac3bb9 100644
--- a/components/omnibox/browser/test_omnibox_client.h
+++ b/components/omnibox/browser/test_omnibox_client.h
@@ -34,6 +34,7 @@
       const base::string16& text,
       const AutocompleteMatch& match,
       const AutocompleteMatch& alternate_nav_match) override;
+  bool IsPasteAndGoEnabled() const override;
   const SessionID& GetSessionID() const override;
   const AutocompleteSchemeClassifier& GetSchemeClassifier() const override;
   AutocompleteClassifier* GetAutocompleteClassifier() override;
diff --git a/components/omnibox_strings_grdp/OWNERS b/components/omnibox_strings_grdp/OWNERS
index 5535cd2..90b1b756 100644
--- a/components/omnibox_strings_grdp/OWNERS
+++ b/components/omnibox_strings_grdp/OWNERS
@@ -1 +1,3 @@
 file://components/omnibox/OWNERS
+
+# COMPONENT: UI>Browser>Omnibox
diff --git a/components/password_manager/core/browser/form_parsing/password_field_prediction.cc b/components/password_manager/core/browser/form_parsing/password_field_prediction.cc
index b9fb2623..a499cfe 100644
--- a/components/password_manager/core/browser/form_parsing/password_field_prediction.cc
+++ b/components/password_manager/core/browser/form_parsing/password_field_prediction.cc
@@ -4,8 +4,7 @@
 
 #include "components/password_manager/core/browser/form_parsing/password_field_prediction.h"
 
-#include <base/logging.h>
-
+#include "base/logging.h"
 #include "components/autofill/core/browser/form_structure.h"
 #include "components/autofill/core/common/form_data.h"
 
diff --git a/components/policy/tools/template_writers/writers/adml_writer.py b/components/policy/tools/template_writers/writers/adml_writer.py
index 84ef08b..3b9c0e5 100755
--- a/components/policy/tools/template_writers/writers/adml_writer.py
+++ b/components/policy/tools/template_writers/writers/adml_writer.py
@@ -76,9 +76,8 @@
     policy_caption = policy.get('caption', policy_name)
     policy_label = policy.get('label', policy_name)
 
-    policy_example = policy.get('example_value')
     policy_desc = policy.get('desc')
-    example_value_text = self._GetExampleValueText(policy_example)
+    example_value_text = self._GetExampleValueText(policy)
 
     if policy_desc is not None and example_value_text is not None:
       policy_explain = policy_desc + '\n\n' + example_value_text
@@ -168,21 +167,58 @@
                         strings[category])
         self._AddString(category, string)
 
-  def _GetExampleValueText(self, example_value):
+  def _GetExampleValueText(self, policy):
     '''Generates a string that describes the example value, if needed.
     Returns None if no string is needed. For instance, if the setting is a
     boolean, the user can only select true or false, so example text is not
     useful.'''
+    example_value = policy.get('example_value')
+    # If there is no example_value, we show nothing.
+    if not example_value:
+      return None
+
+    # Strings are simple - just return them as-is, on the same line.
     if isinstance(example_value, str):
       return self._GetLocalizedMessage('example_value') + ' ' + example_value
-    if isinstance(example_value, list):
-      value_as_text = '\n'.join([str(v) for v in example_value])
-      return self._GetLocalizedMessage('example_value') + '\n\n' + value_as_text
+
+    # Dicts are pretty simple - json.dumps them onto multiple lines.
     if isinstance(example_value, dict):
-      value_as_text = json.dumps(example_value)
+      value_as_text = json.dumps(example_value, indent = 2)
       return self._GetLocalizedMessage('example_value') + '\n\n' + value_as_text
+
+    # Lists are the more complicated - the example value we show the user
+    # depends on if they need to enter the list into a textbox (using JSON
+    # array syntax) or into a listbox (which doesn't need JSON array syntax,
+    # but does need exactly one entry per line).
+    if isinstance(example_value, list):
+      policy_type = policy.get('type')
+      if policy_type == 'dict':
+        # If the policy type is dict, that means they get to enter in the
+        # whole policy as JSON, including the JSON array square brackets:
+        value_as_text = json.dumps(example_value, indent = 2)
+
+      elif policy_type is not None and 'list' in policy_type:
+        # But if the policy type is list, then they get to enter each item
+        # into a listbox, one item per line.
+        if isinstance(example_value[0], str):
+          # Items are strings. These don't need quotes when in a listbox.
+          value_as_text = '\n'.join([str(v) for v in example_value])
+        else:
+          # Items are dicts. We dump each item onto a single line, since the
+          # user has to enter one item per line into the listbox.
+          value_as_text = '\n'.join([json.dumps(v) for v in example_value])
+
+      else:
+        # Lists should be type 'dict', 'list', or something like '...enum-list'
+        raise Exception(
+            'Unexpected policy type with list example value: %s' % policy_type)
+
+      return self._GetLocalizedMessage('example_value') + '\n\n' + value_as_text
+
+    # Other types - mostly booleans - we don't show example values.
     return None
 
+
   def _GetLegacySingleLineLabel(self, policy_label):
     '''Generates a label for a legacy single-line textbox.'''
     return (self._GetLocalizedMessage('legacy_single_line_label')
diff --git a/components/previews/content/previews_content_util.cc b/components/previews/content/previews_content_util.cc
index 2d31200..a06729a0 100644
--- a/components/previews/content/previews_content_util.cc
+++ b/components/previews/content/previews_content_util.cc
@@ -42,7 +42,8 @@
       previews_decider->ShouldAllowPreviewAtECT(
           url_request, previews::PreviewsType::LOFI,
           previews::params::EffectiveConnectionTypeThresholdForClientLoFi(),
-          previews::params::GetBlackListedHostsForClientLoFiFieldTrial())) {
+          previews::params::GetBlackListedHostsForClientLoFiFieldTrial(),
+          false)) {
     previews_state |= content::CLIENT_LOFI_ON;
     return previews_state;
   }
diff --git a/components/previews/content/previews_content_util_unittest.cc b/components/previews/content/previews_content_util_unittest.cc
index 0f3aa8d..52d1354 100644
--- a/components/previews/content/previews_content_util_unittest.cc
+++ b/components/previews/content/previews_content_util_unittest.cc
@@ -31,8 +31,8 @@
       const net::URLRequest& request,
       PreviewsType type,
       net::EffectiveConnectionType effective_connection_type_threshold,
-      const std::vector<std::string>& host_blacklist_from_server)
-      const override {
+      const std::vector<std::string>& host_blacklist_from_server,
+      bool ignore_long_term_black_list_rules) const override {
     return IsEnabled(type);
   }
 
@@ -40,7 +40,7 @@
                           PreviewsType type) const override {
     return ShouldAllowPreviewAtECT(request, type,
                                    params::GetECTThresholdForPreview(type),
-                                   std::vector<std::string>());
+                                   std::vector<std::string>(), false);
   }
 
   bool IsURLAllowedForPreview(const net::URLRequest& request,
diff --git a/components/previews/content/previews_io_data.cc b/components/previews/content/previews_io_data.cc
index 366574f..b7801b0 100644
--- a/components/previews/content/previews_io_data.cc
+++ b/components/previews/content/previews_io_data.cc
@@ -206,16 +206,20 @@
 
 bool PreviewsIOData::ShouldAllowPreview(const net::URLRequest& request,
                                         PreviewsType type) const {
+  DCHECK(type == PreviewsType::OFFLINE || type == PreviewsType::NOSCRIPT);
+  // Consumers that need to specify a blacklist or ignore flag should use
+  // ShouldAllowPreviewAtECT directly.
   return ShouldAllowPreviewAtECT(request, type,
                                  params::GetECTThresholdForPreview(type),
-                                 std::vector<std::string>());
+                                 std::vector<std::string>(), false);
 }
 
 bool PreviewsIOData::ShouldAllowPreviewAtECT(
     const net::URLRequest& request,
     PreviewsType type,
     net::EffectiveConnectionType effective_connection_type_threshold,
-    const std::vector<std::string>& host_blacklist_from_server) const {
+    const std::vector<std::string>& host_blacklist_from_server,
+    bool ignore_long_term_black_list_rules) const {
   if (!previews::params::ArePreviewsAllowed()) {
     return false;
   }
@@ -243,7 +247,9 @@
     // The blacklist will disallow certain hosts for periods of time based on
     // user's opting out of the preview.
     PreviewsEligibilityReason status = previews_black_list_->IsLoadedAndAllowed(
-        request.url(), type, &passed_reasons);
+        request.url(), type, ignore_long_term_black_list_rules,
+        &passed_reasons);
+
     if (status != PreviewsEligibilityReason::ALLOWED) {
       if (type == PreviewsType::LITE_PAGE) {
         PreviewsUserData::GetData(request)->set_black_listed_for_lite_page(
@@ -343,12 +349,13 @@
 
 bool PreviewsIOData::IsURLAllowedForPreview(const net::URLRequest& request,
                                             PreviewsType type) const {
+  DCHECK_EQ(PreviewsType::NOSCRIPT, type);
   if (previews_black_list_ && !blacklist_ignored_) {
     std::vector<PreviewsEligibilityReason> passed_reasons;
     // The blacklist will disallow certain hosts for periods of time based on
     // user's opting out of the preview.
     PreviewsEligibilityReason status = previews_black_list_->IsLoadedAndAllowed(
-        request.url(), type, &passed_reasons);
+        request.url(), type, false, &passed_reasons);
     if (status != PreviewsEligibilityReason::ALLOWED) {
       if (type == PreviewsType::LITE_PAGE) {
         PreviewsUserData::GetData(request)->set_black_listed_for_lite_page(
diff --git a/components/previews/content/previews_io_data.h b/components/previews/content/previews_io_data.h
index 9304cb9..2b68749 100644
--- a/components/previews/content/previews_io_data.h
+++ b/components/previews/content/previews_io_data.h
@@ -107,8 +107,8 @@
       const net::URLRequest& request,
       PreviewsType type,
       net::EffectiveConnectionType effective_connection_type_threshold,
-      const std::vector<std::string>& host_blacklist_from_server)
-      const override;
+      const std::vector<std::string>& host_blacklist_from_server,
+      bool ignore_long_term_black_list_rules) const override;
   bool IsURLAllowedForPreview(const net::URLRequest& request,
                               PreviewsType type) const override;
 
diff --git a/components/previews/content/previews_io_data_unittest.cc b/components/previews/content/previews_io_data_unittest.cc
index 7503516..9f970e9 100644
--- a/components/previews/content/previews_io_data_unittest.cc
+++ b/components/previews/content/previews_io_data_unittest.cc
@@ -94,6 +94,7 @@
   PreviewsEligibilityReason IsLoadedAndAllowed(
       const GURL& url,
       PreviewsType type,
+      bool ignore_long_term_black_list_rules,
       std::vector<PreviewsEligibilityReason>* passed_reasons) const override {
     PreviewsEligibilityReason ordered_reasons[] = {
         PreviewsEligibilityReason::BLACKLIST_DATA_NOT_LOADED,
@@ -430,12 +431,12 @@
       *CreateHttpsRequest(), PreviewsType::LOFI,
       previews::params::GetECTThresholdForPreview(
           previews::PreviewsType::NOSCRIPT),
-      std::vector<std::string>()));
+      std::vector<std::string>(), false));
   EXPECT_FALSE(io_data()->ShouldAllowPreviewAtECT(
       *CreateHttpsRequest(), PreviewsType::NOSCRIPT,
       previews::params::GetECTThresholdForPreview(
           previews::PreviewsType::NOSCRIPT),
-      std::vector<std::string>()));
+      std::vector<std::string>(), false));
 }
 
 // Tests most of the reasons that a preview could be disallowed because of the
@@ -494,8 +495,8 @@
       PreviewsUserData::Create(request.get(), 54321 /* page_id, not used */);
   EXPECT_FALSE(data->black_listed_for_lite_page());
   EXPECT_FALSE(io_data()->ShouldAllowPreviewAtECT(
-      *request, PreviewsType::LITE_PAGE, net::EFFECTIVE_CONNECTION_TYPE_2G,
-      {}));
+      *request, PreviewsType::LITE_PAGE, net::EFFECTIVE_CONNECTION_TYPE_2G, {},
+      false));
   EXPECT_TRUE(data->black_listed_for_lite_page());
 }
 
@@ -528,7 +529,7 @@
   base::HistogramTester histogram_tester;
   EXPECT_TRUE(io_data()->ShouldAllowPreviewAtECT(
       *CreateRequest(), PreviewsType::LITE_PAGE,
-      net::EFFECTIVE_CONNECTION_TYPE_4G, std::vector<std::string>()));
+      net::EFFECTIVE_CONNECTION_TYPE_4G, std::vector<std::string>(), false));
   histogram_tester.ExpectUniqueSample(
       "Previews.EligibilityReason.LitePage",
       static_cast<int>(PreviewsEligibilityReason::ALLOWED), 1);
@@ -618,7 +619,7 @@
   EXPECT_FALSE(io_data()->ShouldAllowPreviewAtECT(
       *CreateRequest(), PreviewsType::LOFI,
       params::EffectiveConnectionTypeThresholdForClientLoFi(),
-      params::GetBlackListedHostsForClientLoFiFieldTrial()));
+      params::GetBlackListedHostsForClientLoFiFieldTrial(), false));
   histogram_tester.ExpectTotalCount("Previews.EligibilityReason.LoFi", 0);
 }
 
@@ -635,7 +636,7 @@
   EXPECT_FALSE(io_data()->ShouldAllowPreviewAtECT(
       *CreateRequest(), PreviewsType::LOFI,
       params::EffectiveConnectionTypeThresholdForClientLoFi(),
-      params::GetBlackListedHostsForClientLoFiFieldTrial()));
+      params::GetBlackListedHostsForClientLoFiFieldTrial(), false));
   histogram_tester.ExpectUniqueSample(
       "Previews.EligibilityReason.LoFi",
       static_cast<int>(PreviewsEligibilityReason::NETWORK_QUALITY_UNAVAILABLE),
@@ -657,7 +658,7 @@
   EXPECT_FALSE(io_data()->ShouldAllowPreviewAtECT(
       *CreateRequest(), PreviewsType::LOFI,
       params::EffectiveConnectionTypeThresholdForClientLoFi(),
-      params::GetBlackListedHostsForClientLoFiFieldTrial()));
+      params::GetBlackListedHostsForClientLoFiFieldTrial(), false));
   histogram_tester.ExpectUniqueSample(
       "Previews.EligibilityReason.LoFi",
       static_cast<int>(PreviewsEligibilityReason::NETWORK_NOT_SLOW), 1);
@@ -692,7 +693,7 @@
               io_data()->ShouldAllowPreviewAtECT(
                   *CreateRequest(), PreviewsType::LOFI,
                   params::EffectiveConnectionTypeThresholdForClientLoFi(),
-                  params::GetBlackListedHostsForClientLoFiFieldTrial()))
+                  params::GetBlackListedHostsForClientLoFiFieldTrial(), false))
         << " effective_connection_type=" << test.effective_connection_type;
     if (test.expected_client_lofi_allowed) {
       histogram_tester.ExpectUniqueSample(
@@ -720,7 +721,7 @@
   EXPECT_FALSE(io_data()->ShouldAllowPreviewAtECT(
       *CreateRequestWithURL(GURL("file:///sdcard")), PreviewsType::LOFI,
       params::EffectiveConnectionTypeThresholdForClientLoFi(),
-      params::GetBlackListedHostsForClientLoFiFieldTrial()));
+      params::GetBlackListedHostsForClientLoFiFieldTrial(), false));
 }
 
 TEST_F(PreviewsIODataTest, ClientLoFiAllowedOnReload) {
@@ -741,7 +742,7 @@
   EXPECT_TRUE(io_data()->ShouldAllowPreviewAtECT(
       *request, PreviewsType::LOFI,
       params::EffectiveConnectionTypeThresholdForClientLoFi(),
-      params::GetBlackListedHostsForClientLoFiFieldTrial()));
+      params::GetBlackListedHostsForClientLoFiFieldTrial(), false));
   histogram_tester.ExpectUniqueSample(
       "Previews.EligibilityReason.LoFi",
       static_cast<int>(PreviewsEligibilityReason::ALLOWED), 1);
@@ -785,7 +786,7 @@
               io_data()->ShouldAllowPreviewAtECT(
                   *request, PreviewsType::LOFI,
                   params::EffectiveConnectionTypeThresholdForClientLoFi(),
-                  params::GetBlackListedHostsForClientLoFiFieldTrial()));
+                  params::GetBlackListedHostsForClientLoFiFieldTrial(), false));
 
     histogram_tester.ExpectUniqueSample(
         "Previews.EligibilityReason.LoFi",
@@ -810,7 +811,7 @@
       *CreateRequest(), PreviewsType::NOSCRIPT,
       previews::params::GetECTThresholdForPreview(
           previews::PreviewsType::NOSCRIPT),
-      std::vector<std::string>()));
+      std::vector<std::string>(), false));
   histogram_tester.ExpectTotalCount("Previews.EligibilityReason.NoScript", 0);
 }
 
@@ -841,7 +842,7 @@
                   *CreateHttpsRequest(), PreviewsType::NOSCRIPT,
                   previews::params::GetECTThresholdForPreview(
                       previews::PreviewsType::NOSCRIPT),
-                  std::vector<std::string>()))
+                  std::vector<std::string>(), false))
         << " effective_connection_type=" << test.effective_connection_type;
     if (test.expected_noscript_allowed) {
       histogram_tester.ExpectUniqueSample(
@@ -877,7 +878,7 @@
       *CreateHttpsRequest(), PreviewsType::NOSCRIPT,
       previews::params::GetECTThresholdForPreview(
           previews::PreviewsType::NOSCRIPT),
-      std::vector<std::string>()));
+      std::vector<std::string>(), false));
 
   histogram_tester.ExpectUniqueSample(
       "Previews.EligibilityReason.NoScript",
@@ -891,7 +892,7 @@
       PreviewsType::NOSCRIPT,
       previews::params::GetECTThresholdForPreview(
           previews::PreviewsType::NOSCRIPT),
-      std::vector<std::string>()));
+      std::vector<std::string>(), false));
 
   histogram_tester.ExpectBucketCount(
       "Previews.EligibilityReason.NoScript",
@@ -1003,8 +1004,8 @@
 
   io_data()->InjectTestBlacklist(nullptr /* blacklist */);
   io_data()->ShouldAllowPreviewAtECT(*CreateRequest(), expected_type,
-                                     net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN,
-                                     {});
+                                     net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN, {},
+                                     false);
   base::RunLoop().RunUntilIdle();
   // Testing correct log method is called.
   EXPECT_THAT(ui_service()->decision_reasons(),
@@ -1038,7 +1039,7 @@
 
     io_data()->ShouldAllowPreviewAtECT(*CreateRequest(), expected_type,
                                        net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN,
-                                       {});
+                                       {}, false);
     base::RunLoop().RunUntilIdle();
     // Testing correct log method is called.
     // Check for all decision upto current decision is logged.
@@ -1119,7 +1120,7 @@
     io_data()->ShouldAllowPreviewAtECT(
         *CreateRequest(), expected_type,
         params::EffectiveConnectionTypeThresholdForClientLoFi(),
-        params::GetBlackListedHostsForClientLoFiFieldTrial());
+        params::GetBlackListedHostsForClientLoFiFieldTrial(), false);
 
     base::RunLoop().RunUntilIdle();
     // Testing correct log method is called.
@@ -1157,7 +1158,7 @@
   io_data()->ShouldAllowPreviewAtECT(
       *CreateRequest(), expected_type,
       params::EffectiveConnectionTypeThresholdForClientLoFi(),
-      params::GetBlackListedHostsForClientLoFiFieldTrial());
+      params::GetBlackListedHostsForClientLoFiFieldTrial(), false);
 
   base::RunLoop().RunUntilIdle();
   // Testing correct log method is called.
@@ -1202,7 +1203,7 @@
 
   io_data()->ShouldAllowPreviewAtECT(
       *CreateRequest(), expected_type,
-      net::EFFECTIVE_CONNECTION_TYPE_2G /* threshold */, {});
+      net::EFFECTIVE_CONNECTION_TYPE_2G /* threshold */, {}, false);
   base::RunLoop().RunUntilIdle();
   // Testing correct log method is called.
   EXPECT_THAT(ui_service()->decision_reasons(),
@@ -1254,7 +1255,7 @@
   io_data()->ShouldAllowPreviewAtECT(
       *CreateRequest(), expected_type,
       params::EffectiveConnectionTypeThresholdForClientLoFi(),
-      params::GetBlackListedHostsForClientLoFiFieldTrial());
+      params::GetBlackListedHostsForClientLoFiFieldTrial(), false);
   base::RunLoop().RunUntilIdle();
 
   // Testing correct log method is called.
@@ -1302,7 +1303,7 @@
   io_data()->ShouldAllowPreviewAtECT(
       *request, expected_type,
       params::EffectiveConnectionTypeThresholdForClientLoFi(),
-      params::GetBlackListedHostsForClientLoFiFieldTrial());
+      params::GetBlackListedHostsForClientLoFiFieldTrial(), false);
   base::RunLoop().RunUntilIdle();
 
   // Testing correct log method is called.
@@ -1344,7 +1345,7 @@
   EXPECT_TRUE(io_data()->ShouldAllowPreviewAtECT(
       *CreateRequest(), PreviewsType::LOFI,
       params::EffectiveConnectionTypeThresholdForClientLoFi(),
-      params::GetBlackListedHostsForClientLoFiFieldTrial()));
+      params::GetBlackListedHostsForClientLoFiFieldTrial(), false));
 
   base::RunLoop().RunUntilIdle();
   EXPECT_THAT(ui_service()->decision_reasons(),
@@ -1384,7 +1385,7 @@
   io_data()->ShouldAllowPreviewAtECT(
       *CreateRequest(), expected_type,
       params::EffectiveConnectionTypeThresholdForClientLoFi(),
-      params::GetBlackListedHostsForClientLoFiFieldTrial());
+      params::GetBlackListedHostsForClientLoFiFieldTrial(), false);
   base::RunLoop().RunUntilIdle();
 
   // Testing correct log method is called.
diff --git a/components/previews/core/previews_black_list.cc b/components/previews/core/previews_black_list.cc
index 9f76000..c05cf8c 100644
--- a/components/previews/core/previews_black_list.cc
+++ b/components/previews/core/previews_black_list.cc
@@ -147,6 +147,7 @@
 PreviewsEligibilityReason PreviewsBlackList::IsLoadedAndAllowed(
     const GURL& url,
     PreviewsType type,
+    bool ignore_long_term_black_list_rules,
     std::vector<PreviewsEligibilityReason>* passed_reasons) const {
   DCHECK(thread_checker_.CalledOnValidThread());
   DCHECK(url.has_host());
@@ -161,6 +162,8 @@
     return PreviewsEligibilityReason::USER_RECENTLY_OPTED_OUT;
   }
   passed_reasons->push_back(PreviewsEligibilityReason::USER_RECENTLY_OPTED_OUT);
+  if (ignore_long_term_black_list_rules)
+    return PreviewsEligibilityReason::ALLOWED;
   if (host_indifferent_black_list_item_->IsBlackListed(clock_->Now()))
     return PreviewsEligibilityReason::USER_BLACKLISTED;
   passed_reasons->push_back(PreviewsEligibilityReason::USER_BLACKLISTED);
diff --git a/components/previews/core/previews_black_list.h b/components/previews/core/previews_black_list.h
index ef56ed7..13e0e2d 100644
--- a/components/previews/core/previews_black_list.h
+++ b/components/previews/core/previews_black_list.h
@@ -108,6 +108,7 @@
   virtual PreviewsEligibilityReason IsLoadedAndAllowed(
       const GURL& url,
       PreviewsType type,
+      bool ignore_long_term_black_list_rules,
       std::vector<PreviewsEligibilityReason>* passed_reasons) const;
 
   // Asynchronously deletes all entries in the in-memory black list. Informs
diff --git a/components/previews/core/previews_black_list_unittest.cc b/components/previews/core/previews_black_list_unittest.cc
index 366d98f..edb05d6 100644
--- a/components/previews/core/previews_black_list_unittest.cc
+++ b/components/previews/core/previews_black_list_unittest.cc
@@ -266,10 +266,10 @@
   test_clock_.Advance(base::TimeDelta::FromSeconds(1));
 
   EXPECT_EQ(PreviewsEligibilityReason::ALLOWED,
-            black_list_->IsLoadedAndAllowed(url_a, PreviewsType::OFFLINE,
+            black_list_->IsLoadedAndAllowed(url_a, PreviewsType::OFFLINE, false,
                                             &passed_reasons_));
   EXPECT_EQ(PreviewsEligibilityReason::ALLOWED,
-            black_list_->IsLoadedAndAllowed(url_b, PreviewsType::OFFLINE,
+            black_list_->IsLoadedAndAllowed(url_b, PreviewsType::OFFLINE, false,
                                             &passed_reasons_));
 
   black_list_->AddPreviewNavigation(url_a, true, PreviewsType::OFFLINE);
@@ -278,10 +278,13 @@
   test_clock_.Advance(base::TimeDelta::FromSeconds(1));
 
   EXPECT_EQ(PreviewsEligibilityReason::HOST_BLACKLISTED,
-            black_list_->IsLoadedAndAllowed(url_a, PreviewsType::OFFLINE,
+            black_list_->IsLoadedAndAllowed(url_a, PreviewsType::OFFLINE, false,
                                             &passed_reasons_));
   EXPECT_EQ(PreviewsEligibilityReason::ALLOWED,
-            black_list_->IsLoadedAndAllowed(url_b, PreviewsType::OFFLINE,
+            black_list_->IsLoadedAndAllowed(url_a, PreviewsType::OFFLINE, true,
+                                            &passed_reasons_));
+  EXPECT_EQ(PreviewsEligibilityReason::ALLOWED,
+            black_list_->IsLoadedAndAllowed(url_b, PreviewsType::OFFLINE, false,
                                             &passed_reasons_));
 
   black_list_->AddPreviewNavigation(url_b, true, PreviewsType::OFFLINE);
@@ -290,33 +293,39 @@
   test_clock_.Advance(base::TimeDelta::FromSeconds(1));
 
   EXPECT_EQ(PreviewsEligibilityReason::HOST_BLACKLISTED,
-            black_list_->IsLoadedAndAllowed(url_a, PreviewsType::OFFLINE,
-                                            &passed_reasons_));
-  EXPECT_EQ(PreviewsEligibilityReason::HOST_BLACKLISTED,
-            black_list_->IsLoadedAndAllowed(url_b, PreviewsType::OFFLINE,
-                                            &passed_reasons_));
-
-  black_list_->AddPreviewNavigation(url_b, false, PreviewsType::OFFLINE);
-  test_clock_.Advance(base::TimeDelta::FromSeconds(1));
-  black_list_->AddPreviewNavigation(url_b, false, PreviewsType::OFFLINE);
-  test_clock_.Advance(base::TimeDelta::FromSeconds(1));
-  black_list_->AddPreviewNavigation(url_b, false, PreviewsType::OFFLINE);
-  test_clock_.Advance(base::TimeDelta::FromSeconds(1));
-
-  EXPECT_EQ(PreviewsEligibilityReason::HOST_BLACKLISTED,
-            black_list_->IsLoadedAndAllowed(url_a, PreviewsType::OFFLINE,
+            black_list_->IsLoadedAndAllowed(url_a, PreviewsType::OFFLINE, false,
                                             &passed_reasons_));
   EXPECT_EQ(PreviewsEligibilityReason::ALLOWED,
-            black_list_->IsLoadedAndAllowed(url_b, PreviewsType::OFFLINE,
+            black_list_->IsLoadedAndAllowed(url_a, PreviewsType::OFFLINE, true,
+                                            &passed_reasons_));
+  EXPECT_EQ(PreviewsEligibilityReason::HOST_BLACKLISTED,
+            black_list_->IsLoadedAndAllowed(url_b, PreviewsType::OFFLINE, false,
+                                            &passed_reasons_));
+
+  black_list_->AddPreviewNavigation(url_b, false, PreviewsType::OFFLINE);
+  test_clock_.Advance(base::TimeDelta::FromSeconds(1));
+  black_list_->AddPreviewNavigation(url_b, false, PreviewsType::OFFLINE);
+  test_clock_.Advance(base::TimeDelta::FromSeconds(1));
+  black_list_->AddPreviewNavigation(url_b, false, PreviewsType::OFFLINE);
+  test_clock_.Advance(base::TimeDelta::FromSeconds(1));
+
+  EXPECT_EQ(PreviewsEligibilityReason::HOST_BLACKLISTED,
+            black_list_->IsLoadedAndAllowed(url_a, PreviewsType::OFFLINE, false,
+                                            &passed_reasons_));
+  EXPECT_EQ(PreviewsEligibilityReason::ALLOWED,
+            black_list_->IsLoadedAndAllowed(url_a, PreviewsType::OFFLINE, true,
+                                            &passed_reasons_));
+  EXPECT_EQ(PreviewsEligibilityReason::ALLOWED,
+            black_list_->IsLoadedAndAllowed(url_b, PreviewsType::OFFLINE, false,
                                             &passed_reasons_));
 
   black_list_->ClearBlackList(start_, test_clock_.Now());
 
   EXPECT_EQ(PreviewsEligibilityReason::ALLOWED,
-            black_list_->IsLoadedAndAllowed(url_a, PreviewsType::OFFLINE,
+            black_list_->IsLoadedAndAllowed(url_a, PreviewsType::OFFLINE, false,
                                             &passed_reasons_));
   EXPECT_EQ(PreviewsEligibilityReason::ALLOWED,
-            black_list_->IsLoadedAndAllowed(url_b, PreviewsType::OFFLINE,
+            black_list_->IsLoadedAndAllowed(url_b, PreviewsType::OFFLINE, false,
                                             &passed_reasons_));
 }
 
@@ -343,24 +352,24 @@
 
   EXPECT_EQ(PreviewsEligibilityReason::BLACKLIST_DATA_NOT_LOADED,
             black_list_->IsLoadedAndAllowed(url_a1, PreviewsType::OFFLINE,
-                                            &passed_reasons_));
+                                            false, &passed_reasons_));
   EXPECT_EQ(PreviewsEligibilityReason::BLACKLIST_DATA_NOT_LOADED,
             black_list_->IsLoadedAndAllowed(url_a2, PreviewsType::OFFLINE,
-                                            &passed_reasons_));
+                                            false, &passed_reasons_));
   EXPECT_EQ(PreviewsEligibilityReason::BLACKLIST_DATA_NOT_LOADED,
-            black_list_->IsLoadedAndAllowed(url_b, PreviewsType::OFFLINE,
+            black_list_->IsLoadedAndAllowed(url_b, PreviewsType::OFFLINE, false,
                                             &passed_reasons_));
 
   base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(PreviewsEligibilityReason::ALLOWED,
             black_list_->IsLoadedAndAllowed(url_a1, PreviewsType::OFFLINE,
-                                            &passed_reasons_));
+                                            false, &passed_reasons_));
   EXPECT_EQ(PreviewsEligibilityReason::ALLOWED,
             black_list_->IsLoadedAndAllowed(url_a2, PreviewsType::OFFLINE,
-                                            &passed_reasons_));
+                                            false, &passed_reasons_));
   EXPECT_EQ(PreviewsEligibilityReason::ALLOWED,
-            black_list_->IsLoadedAndAllowed(url_b, PreviewsType::OFFLINE,
+            black_list_->IsLoadedAndAllowed(url_b, PreviewsType::OFFLINE, false,
                                             &passed_reasons_));
 
   black_list_->AddPreviewNavigation(url_a1, true, PreviewsType::OFFLINE);
@@ -370,12 +379,15 @@
 
   EXPECT_EQ(PreviewsEligibilityReason::HOST_BLACKLISTED,
             black_list_->IsLoadedAndAllowed(url_a1, PreviewsType::OFFLINE,
-                                            &passed_reasons_));
+                                            false, &passed_reasons_));
   EXPECT_EQ(PreviewsEligibilityReason::HOST_BLACKLISTED,
             black_list_->IsLoadedAndAllowed(url_a2, PreviewsType::OFFLINE,
+                                            false, &passed_reasons_));
+  EXPECT_EQ(PreviewsEligibilityReason::ALLOWED,
+            black_list_->IsLoadedAndAllowed(url_a2, PreviewsType::OFFLINE, true,
                                             &passed_reasons_));
   EXPECT_EQ(PreviewsEligibilityReason::ALLOWED,
-            black_list_->IsLoadedAndAllowed(url_b, PreviewsType::OFFLINE,
+            black_list_->IsLoadedAndAllowed(url_b, PreviewsType::OFFLINE, false,
                                             &passed_reasons_));
 
   black_list_->AddPreviewNavigation(url_b, true, PreviewsType::OFFLINE);
@@ -385,12 +397,12 @@
 
   EXPECT_EQ(PreviewsEligibilityReason::HOST_BLACKLISTED,
             black_list_->IsLoadedAndAllowed(url_a1, PreviewsType::OFFLINE,
-                                            &passed_reasons_));
+                                            false, &passed_reasons_));
   EXPECT_EQ(PreviewsEligibilityReason::HOST_BLACKLISTED,
             black_list_->IsLoadedAndAllowed(url_a2, PreviewsType::OFFLINE,
-                                            &passed_reasons_));
+                                            false, &passed_reasons_));
   EXPECT_EQ(PreviewsEligibilityReason::HOST_BLACKLISTED,
-            black_list_->IsLoadedAndAllowed(url_b, PreviewsType::OFFLINE,
+            black_list_->IsLoadedAndAllowed(url_b, PreviewsType::OFFLINE, false,
                                             &passed_reasons_));
 
   black_list_->AddPreviewNavigation(url_b, false, PreviewsType::OFFLINE);
@@ -402,12 +414,12 @@
 
   EXPECT_EQ(PreviewsEligibilityReason::HOST_BLACKLISTED,
             black_list_->IsLoadedAndAllowed(url_a1, PreviewsType::OFFLINE,
-                                            &passed_reasons_));
+                                            false, &passed_reasons_));
   EXPECT_EQ(PreviewsEligibilityReason::HOST_BLACKLISTED,
             black_list_->IsLoadedAndAllowed(url_a2, PreviewsType::OFFLINE,
-                                            &passed_reasons_));
+                                            false, &passed_reasons_));
   EXPECT_EQ(PreviewsEligibilityReason::ALLOWED,
-            black_list_->IsLoadedAndAllowed(url_b, PreviewsType::OFFLINE,
+            black_list_->IsLoadedAndAllowed(url_b, PreviewsType::OFFLINE, false,
                                             &passed_reasons_));
 
   EXPECT_EQ(0, opt_out_store_->clear_blacklist_count());
@@ -416,12 +428,12 @@
 
   EXPECT_EQ(PreviewsEligibilityReason::BLACKLIST_DATA_NOT_LOADED,
             black_list_->IsLoadedAndAllowed(url_a1, PreviewsType::OFFLINE,
-                                            &passed_reasons_));
+                                            false, &passed_reasons_));
   EXPECT_EQ(PreviewsEligibilityReason::BLACKLIST_DATA_NOT_LOADED,
             black_list_->IsLoadedAndAllowed(url_a2, PreviewsType::OFFLINE,
-                                            &passed_reasons_));
+                                            false, &passed_reasons_));
   EXPECT_EQ(PreviewsEligibilityReason::BLACKLIST_DATA_NOT_LOADED,
-            black_list_->IsLoadedAndAllowed(url_b, PreviewsType::OFFLINE,
+            black_list_->IsLoadedAndAllowed(url_b, PreviewsType::OFFLINE, false,
                                             &passed_reasons_));
 
   base::RunLoop().RunUntilIdle();
@@ -429,12 +441,12 @@
 
   EXPECT_EQ(PreviewsEligibilityReason::ALLOWED,
             black_list_->IsLoadedAndAllowed(url_a1, PreviewsType::OFFLINE,
-                                            &passed_reasons_));
+                                            false, &passed_reasons_));
   EXPECT_EQ(PreviewsEligibilityReason::ALLOWED,
             black_list_->IsLoadedAndAllowed(url_a1, PreviewsType::OFFLINE,
-                                            &passed_reasons_));
+                                            false, &passed_reasons_));
   EXPECT_EQ(PreviewsEligibilityReason::ALLOWED,
-            black_list_->IsLoadedAndAllowed(url_b, PreviewsType::OFFLINE,
+            black_list_->IsLoadedAndAllowed(url_b, PreviewsType::OFFLINE, false,
                                             &passed_reasons_));
 }
 
@@ -462,38 +474,41 @@
 
   EXPECT_EQ(PreviewsEligibilityReason::ALLOWED,
             black_list_->IsLoadedAndAllowed(urls[0], PreviewsType::OFFLINE,
-                                            &passed_reasons_));
+                                            false, &passed_reasons_));
   EXPECT_EQ(PreviewsEligibilityReason::ALLOWED,
             black_list_->IsLoadedAndAllowed(urls[1], PreviewsType::OFFLINE,
-                                            &passed_reasons_));
+                                            false, &passed_reasons_));
   EXPECT_EQ(PreviewsEligibilityReason::ALLOWED,
             black_list_->IsLoadedAndAllowed(urls[2], PreviewsType::OFFLINE,
-                                            &passed_reasons_));
+                                            false, &passed_reasons_));
   EXPECT_EQ(PreviewsEligibilityReason::ALLOWED,
             black_list_->IsLoadedAndAllowed(urls[3], PreviewsType::OFFLINE,
-                                            &passed_reasons_));
+                                            false, &passed_reasons_));
 
   for (size_t i = 0; i < host_indifferent_threshold; i++) {
     black_list_->AddPreviewNavigation(urls[i], true, PreviewsType::OFFLINE);
     EXPECT_EQ(i != 3 ? PreviewsEligibilityReason::ALLOWED
                      : PreviewsEligibilityReason::USER_BLACKLISTED,
               black_list_->IsLoadedAndAllowed(urls[0], PreviewsType::OFFLINE,
-                                              &passed_reasons_));
+                                              false, &passed_reasons_));
     test_clock_.Advance(base::TimeDelta::FromSeconds(1));
   }
 
   EXPECT_EQ(PreviewsEligibilityReason::USER_BLACKLISTED,
             black_list_->IsLoadedAndAllowed(urls[0], PreviewsType::OFFLINE,
-                                            &passed_reasons_));
+                                            false, &passed_reasons_));
   EXPECT_EQ(PreviewsEligibilityReason::USER_BLACKLISTED,
             black_list_->IsLoadedAndAllowed(urls[1], PreviewsType::OFFLINE,
-                                            &passed_reasons_));
+                                            false, &passed_reasons_));
   EXPECT_EQ(PreviewsEligibilityReason::USER_BLACKLISTED,
             black_list_->IsLoadedAndAllowed(urls[2], PreviewsType::OFFLINE,
-                                            &passed_reasons_));
+                                            false, &passed_reasons_));
   EXPECT_EQ(PreviewsEligibilityReason::USER_BLACKLISTED,
             black_list_->IsLoadedAndAllowed(urls[3], PreviewsType::OFFLINE,
-                                            &passed_reasons_));
+                                            false, &passed_reasons_));
+  EXPECT_EQ(PreviewsEligibilityReason::ALLOWED,
+            black_list_->IsLoadedAndAllowed(urls[3], PreviewsType::OFFLINE,
+                                            true, &passed_reasons_));
 
   black_list_->AddPreviewNavigation(urls[3], false, PreviewsType::OFFLINE);
   test_clock_.Advance(base::TimeDelta::FromSeconds(1));
@@ -501,16 +516,16 @@
   // New non-opt-out entry will cause these to be allowed now.
   EXPECT_EQ(PreviewsEligibilityReason::ALLOWED,
             black_list_->IsLoadedAndAllowed(urls[0], PreviewsType::OFFLINE,
-                                            &passed_reasons_));
+                                            false, &passed_reasons_));
   EXPECT_EQ(PreviewsEligibilityReason::ALLOWED,
             black_list_->IsLoadedAndAllowed(urls[1], PreviewsType::OFFLINE,
-                                            &passed_reasons_));
+                                            false, &passed_reasons_));
   EXPECT_EQ(PreviewsEligibilityReason::ALLOWED,
             black_list_->IsLoadedAndAllowed(urls[2], PreviewsType::OFFLINE,
-                                            &passed_reasons_));
+                                            false, &passed_reasons_));
   EXPECT_EQ(PreviewsEligibilityReason::ALLOWED,
             black_list_->IsLoadedAndAllowed(urls[3], PreviewsType::OFFLINE,
-                                            &passed_reasons_));
+                                            false, &passed_reasons_));
 }
 
 TEST_F(PreviewsBlackListTest, QueueBehavior) {
@@ -535,19 +550,19 @@
     StartTest(false /* null_opt_out */);
 
     EXPECT_EQ(PreviewsEligibilityReason::BLACKLIST_DATA_NOT_LOADED,
-              black_list_->IsLoadedAndAllowed(url, PreviewsType::OFFLINE,
+              black_list_->IsLoadedAndAllowed(url, PreviewsType::OFFLINE, false,
                                               &passed_reasons_));
     black_list_->AddPreviewNavigation(url, opt_out, PreviewsType::OFFLINE);
     test_clock_.Advance(base::TimeDelta::FromSeconds(1));
     black_list_->AddPreviewNavigation(url, opt_out, PreviewsType::OFFLINE);
     test_clock_.Advance(base::TimeDelta::FromSeconds(1));
     EXPECT_EQ(PreviewsEligibilityReason::BLACKLIST_DATA_NOT_LOADED,
-              black_list_->IsLoadedAndAllowed(url, PreviewsType::OFFLINE,
+              black_list_->IsLoadedAndAllowed(url, PreviewsType::OFFLINE, false,
                                               &passed_reasons_));
     base::RunLoop().RunUntilIdle();
     EXPECT_EQ(opt_out ? PreviewsEligibilityReason::HOST_BLACKLISTED
                       : PreviewsEligibilityReason::ALLOWED,
-              black_list_->IsLoadedAndAllowed(url, PreviewsType::OFFLINE,
+              black_list_->IsLoadedAndAllowed(url, PreviewsType::OFFLINE, false,
                                               &passed_reasons_));
     black_list_->AddPreviewNavigation(url, opt_out, PreviewsType::OFFLINE);
     test_clock_.Advance(base::TimeDelta::FromSeconds(1));
@@ -565,12 +580,12 @@
     EXPECT_EQ(1, opt_out_store_->clear_blacklist_count());
 
     EXPECT_EQ(PreviewsEligibilityReason::ALLOWED,
-              black_list_->IsLoadedAndAllowed(url, PreviewsType::OFFLINE,
+              black_list_->IsLoadedAndAllowed(url, PreviewsType::OFFLINE, false,
                                               &passed_reasons_));
     EXPECT_EQ(opt_out ? PreviewsEligibilityReason::HOST_BLACKLISTED
                       : PreviewsEligibilityReason::ALLOWED,
               black_list_->IsLoadedAndAllowed(url2, PreviewsType::OFFLINE,
-                                              &passed_reasons_));
+                                              false, &passed_reasons_));
   }
 }
 
@@ -605,13 +620,13 @@
   black_list_->AddPreviewNavigation(url_c, false, PreviewsType::OFFLINE);
   // url_a should stay in the map, since it has an opt out time.
   EXPECT_EQ(PreviewsEligibilityReason::HOST_BLACKLISTED,
-            black_list_->IsLoadedAndAllowed(url_a, PreviewsType::OFFLINE,
+            black_list_->IsLoadedAndAllowed(url_a, PreviewsType::OFFLINE, false,
                                             &passed_reasons_));
   EXPECT_EQ(PreviewsEligibilityReason::ALLOWED,
-            black_list_->IsLoadedAndAllowed(url_b, PreviewsType::OFFLINE,
+            black_list_->IsLoadedAndAllowed(url_b, PreviewsType::OFFLINE, false,
                                             &passed_reasons_));
   EXPECT_EQ(PreviewsEligibilityReason::ALLOWED,
-            black_list_->IsLoadedAndAllowed(url_c, PreviewsType::OFFLINE,
+            black_list_->IsLoadedAndAllowed(url_c, PreviewsType::OFFLINE, false,
                                             &passed_reasons_));
 
   test_clock_.Advance(base::TimeDelta::FromSeconds(1));
@@ -620,13 +635,13 @@
   black_list_->AddPreviewNavigation(url_e, true, PreviewsType::OFFLINE);
   // url_d and url_e should remain in the map, but url_a should be evicted.
   EXPECT_EQ(PreviewsEligibilityReason::ALLOWED,
-            black_list_->IsLoadedAndAllowed(url_a, PreviewsType::OFFLINE,
+            black_list_->IsLoadedAndAllowed(url_a, PreviewsType::OFFLINE, false,
                                             &passed_reasons_));
   EXPECT_EQ(PreviewsEligibilityReason::HOST_BLACKLISTED,
-            black_list_->IsLoadedAndAllowed(url_d, PreviewsType::OFFLINE,
+            black_list_->IsLoadedAndAllowed(url_d, PreviewsType::OFFLINE, false,
                                             &passed_reasons_));
   EXPECT_EQ(PreviewsEligibilityReason::HOST_BLACKLISTED,
-            black_list_->IsLoadedAndAllowed(url_e, PreviewsType::OFFLINE,
+            black_list_->IsLoadedAndAllowed(url_e, PreviewsType::OFFLINE, false,
                                             &passed_reasons_));
 }
 
@@ -653,10 +668,10 @@
 
   black_list_->AddPreviewNavigation(url_a, false, PreviewsType::OFFLINE);
   EXPECT_EQ(PreviewsEligibilityReason::ALLOWED,
-            black_list_->IsLoadedAndAllowed(url_a, PreviewsType::OFFLINE,
+            black_list_->IsLoadedAndAllowed(url_a, PreviewsType::OFFLINE, false,
                                             &passed_reasons_));
   EXPECT_EQ(PreviewsEligibilityReason::ALLOWED,
-            black_list_->IsLoadedAndAllowed(url_c, PreviewsType::OFFLINE,
+            black_list_->IsLoadedAndAllowed(url_c, PreviewsType::OFFLINE, false,
                                             &passed_reasons_));
 
   test_clock_.Advance(
@@ -664,30 +679,30 @@
 
   black_list_->AddPreviewNavigation(url_b, true, PreviewsType::OFFLINE);
   EXPECT_EQ(PreviewsEligibilityReason::USER_RECENTLY_OPTED_OUT,
-            black_list_->IsLoadedAndAllowed(url_b, PreviewsType::OFFLINE,
+            black_list_->IsLoadedAndAllowed(url_b, PreviewsType::OFFLINE, false,
                                             &passed_reasons_));
   EXPECT_EQ(PreviewsEligibilityReason::USER_RECENTLY_OPTED_OUT,
-            black_list_->IsLoadedAndAllowed(url_c, PreviewsType::OFFLINE,
+            black_list_->IsLoadedAndAllowed(url_c, PreviewsType::OFFLINE, false,
                                             &passed_reasons_));
 
   test_clock_.Advance(
       base::TimeDelta::FromSeconds(single_opt_out_duration - 1));
 
   EXPECT_EQ(PreviewsEligibilityReason::USER_RECENTLY_OPTED_OUT,
-            black_list_->IsLoadedAndAllowed(url_b, PreviewsType::OFFLINE,
+            black_list_->IsLoadedAndAllowed(url_b, PreviewsType::OFFLINE, false,
                                             &passed_reasons_));
   EXPECT_EQ(PreviewsEligibilityReason::USER_RECENTLY_OPTED_OUT,
-            black_list_->IsLoadedAndAllowed(url_c, PreviewsType::OFFLINE,
+            black_list_->IsLoadedAndAllowed(url_c, PreviewsType::OFFLINE, false,
                                             &passed_reasons_));
 
   test_clock_.Advance(
       base::TimeDelta::FromSeconds(single_opt_out_duration + 1));
 
   EXPECT_EQ(PreviewsEligibilityReason::ALLOWED,
-            black_list_->IsLoadedAndAllowed(url_b, PreviewsType::OFFLINE,
+            black_list_->IsLoadedAndAllowed(url_b, PreviewsType::OFFLINE, false,
                                             &passed_reasons_));
   EXPECT_EQ(PreviewsEligibilityReason::ALLOWED,
-            black_list_->IsLoadedAndAllowed(url_c, PreviewsType::OFFLINE,
+            black_list_->IsLoadedAndAllowed(url_c, PreviewsType::OFFLINE, false,
                                             &passed_reasons_));
 }
 
@@ -713,7 +728,7 @@
   const GURL url("http://www.url.com");
   RunClearingBlackListTest(url, true /* short_time */);
   EXPECT_EQ(PreviewsEligibilityReason::USER_RECENTLY_OPTED_OUT,
-            black_list_->IsLoadedAndAllowed(url, PreviewsType::OFFLINE,
+            black_list_->IsLoadedAndAllowed(url, PreviewsType::OFFLINE, false,
                                             &passed_reasons_));
 }
 
@@ -726,7 +741,7 @@
   RunClearingBlackListTest(url, false /* short_time */);
 
   EXPECT_EQ(PreviewsEligibilityReason::ALLOWED,
-            black_list_->IsLoadedAndAllowed(url, PreviewsType::OFFLINE,
+            black_list_->IsLoadedAndAllowed(url, PreviewsType::OFFLINE, false,
                                             &passed_reasons_));
 }
 
@@ -748,7 +763,7 @@
   StartTest(true /* null_opt_out */);
 
   EXPECT_EQ(PreviewsEligibilityReason::ALLOWED,
-            black_list_->IsLoadedAndAllowed(url_, PreviewsType::OFFLINE,
+            black_list_->IsLoadedAndAllowed(url_, PreviewsType::OFFLINE, false,
                                             &passed_reasons_));
 
   // Observer is not notified as blacklisted when the threshold does not met.
@@ -937,7 +952,7 @@
   StartTest(false /* null_opt_out */);
 
   EXPECT_EQ(PreviewsEligibilityReason::BLACKLIST_DATA_NOT_LOADED,
-            black_list_->IsLoadedAndAllowed(url, PreviewsType::OFFLINE,
+            black_list_->IsLoadedAndAllowed(url, PreviewsType::OFFLINE, false,
                                             &passed_reasons_));
 
   EXPECT_EQ(0UL, passed_reasons_.size());
@@ -951,7 +966,7 @@
 
   black_list_->AddPreviewNavigation(url, true, PreviewsType::OFFLINE);
   EXPECT_EQ(PreviewsEligibilityReason::USER_RECENTLY_OPTED_OUT,
-            black_list_->IsLoadedAndAllowed(url, PreviewsType::OFFLINE,
+            black_list_->IsLoadedAndAllowed(url, PreviewsType::OFFLINE, false,
                                             &passed_reasons_));
   EXPECT_EQ(1UL, passed_reasons_.size());
   EXPECT_EQ(PreviewsEligibilityReason::BLACKLIST_DATA_NOT_LOADED,
@@ -987,7 +1002,7 @@
 
   EXPECT_EQ(PreviewsEligibilityReason::USER_BLACKLISTED,
             black_list_->IsLoadedAndAllowed(urls[0], PreviewsType::OFFLINE,
-                                            &passed_reasons_));
+                                            false, &passed_reasons_));
 
   PreviewsEligibilityReason expected_reasons[] = {
       PreviewsEligibilityReason::BLACKLIST_DATA_NOT_LOADED,
@@ -1021,7 +1036,7 @@
   black_list_->AddPreviewNavigation(url, true, PreviewsType::OFFLINE);
 
   EXPECT_EQ(PreviewsEligibilityReason::HOST_BLACKLISTED,
-            black_list_->IsLoadedAndAllowed(url, PreviewsType::OFFLINE,
+            black_list_->IsLoadedAndAllowed(url, PreviewsType::OFFLINE, false,
                                             &passed_reasons_));
 
   PreviewsEligibilityReason expected_reasons[] = {
@@ -1042,7 +1057,7 @@
   StartTest(true /* null_opt_out */);
 
   EXPECT_EQ(PreviewsEligibilityReason::ALLOWED,
-            black_list_->IsLoadedAndAllowed(url, PreviewsType::OFFLINE,
+            black_list_->IsLoadedAndAllowed(url, PreviewsType::OFFLINE, false,
                                             &passed_reasons_));
 
   PreviewsEligibilityReason expected_reasons[] = {
diff --git a/components/previews/core/previews_decider.h b/components/previews/core/previews_decider.h
index 96e706a..6f8c0f79 100644
--- a/components/previews/core/previews_decider.h
+++ b/components/previews/core/previews_decider.h
@@ -30,7 +30,8 @@
       const net::URLRequest& request,
       PreviewsType type,
       net::EffectiveConnectionType effective_connection_type_threshold,
-      const std::vector<std::string>& host_blacklist_from_server) const = 0;
+      const std::vector<std::string>& host_blacklist_from_server,
+      bool ignore_long_term_black_list_rules) const = 0;
 
   // Same as ShouldAllowPreviewAtECT, but uses the previews default
   // EffectiveConnectionType and no blacklisted hosts from the server.
diff --git a/components/previews/core/test_previews_decider.cc b/components/previews/core/test_previews_decider.cc
index f6a9f3a..801dbc6 100644
--- a/components/previews/core/test_previews_decider.cc
+++ b/components/previews/core/test_previews_decider.cc
@@ -15,7 +15,8 @@
     const net::URLRequest& request,
     previews::PreviewsType type,
     net::EffectiveConnectionType effective_connection_type_threshold,
-    const std::vector<std::string>& host_blacklist_from_server) const {
+    const std::vector<std::string>& host_blacklist_from_server,
+    bool ignore_long_term_black_list_rules) const {
   return allow_previews_;
 }
 
diff --git a/components/previews/core/test_previews_decider.h b/components/previews/core/test_previews_decider.h
index 015993b..8241381 100644
--- a/components/previews/core/test_previews_decider.h
+++ b/components/previews/core/test_previews_decider.h
@@ -20,8 +20,8 @@
       const net::URLRequest& request,
       previews::PreviewsType type,
       net::EffectiveConnectionType effective_connection_type_threshold,
-      const std::vector<std::string>& host_blacklist_from_server)
-      const override;
+      const std::vector<std::string>& host_blacklist_from_server,
+      bool ignore_long_term_black_list_rules) const override;
   bool ShouldAllowPreview(const net::URLRequest& request,
                           previews::PreviewsType type) const override;
   bool IsURLAllowedForPreview(const net::URLRequest& request,
diff --git a/components/search_engines/prepopulated_engines.json b/components/search_engines/prepopulated_engines.json
index 4571a4c..535692d4 100644
--- a/components/search_engines/prepopulated_engines.json
+++ b/components/search_engines/prepopulated_engines.json
@@ -32,7 +32,7 @@
 
     // Increment this if you change the data in ways that mean users with
     // existing data should get a new version.
-    "kCurrentDataVersion": 102
+    "kCurrentDataVersion": 103
   },
 
   // The following engines are included in country lists and are added to the
@@ -86,6 +86,11 @@
       "keyword": "baidu.com",
       "favicon_url": "https://www.baidu.com/favicon.ico",
       "search_url": "https://www.baidu.com/#ie={inputEncoding}&wd={searchTerms}",
+      "alternate_urls": [
+        "https://www.baidu.com/s?ie={inputEncoding}&wd={searchTerms}",
+        "https://www.baidu.com/s?ie={inputEncoding}&word={searchTerms}",
+        "https://www.baidu.com/{google:pathWildcard}/s?ie={inputEncoding}&word={searchTerms}"
+      ],
       "suggest_url": "http://suggestion.baidu.com/su?wd={searchTerms}&action=opensearch&ie={inputEncoding}",
       "type": "SEARCH_ENGINE_BAIDU",
       "id": 21
@@ -149,6 +154,9 @@
       "keyword": "mail.ru",
       "favicon_url": "https://go.imgsmail.ru/favicon.ico",
       "search_url": "https://go.mail.ru/search?q={searchTerms}&{mailru:referralID}",
+      "alternate_urls": [
+        "https://go.mail.ru/msearch?q={searchTerms}&{mailru:referralID}"
+      ],
       "encoding": "windows-1251",
       "suggest_url": "https://suggests.go.mail.ru/chrome?q={searchTerms}",
       "type": "SEARCH_ENGINE_MAILRU",
@@ -198,6 +206,10 @@
       "keyword": "so.com",
       "favicon_url": "https://www.so.com/favicon.ico",
       "search_url": "https://www.so.com/s?ie={inputEncoding}&q={searchTerms}",
+      "alternate_urls": [
+        "https://m.so.com/s?ie={inputEncoding}&q={searchTerms}",
+        "https://m.so.com/index.php?ie={inputEncoding}&q={searchTerms}"
+      ],
       "suggest_url": "https://sug.so.360.cn/suggest?encodein={inputEncoding}&encodeout={outputEncoding}&format=opensearch&word={searchTerms}",
       "type": "SEARCH_ENGINE_360",
       "id": 88
@@ -208,6 +220,9 @@
       "keyword": "sogou.com",
       "favicon_url": "https://www.sogou.com/images/logo/old/favicon.ico",
       "search_url": "https://www.sogou.com/web?ie={inputEncoding}&query={searchTerms}",
+      "alternate_urls": [
+        "https://m.sogou.com/web/{google:pathWildcard}?ie={inputEncoding}&keyword={searchTerms}"
+      ],
       "suggest_url": "http://api.sugg.sogou.com/su?type=addrbar&key={searchTerms}&ie={inputEncoding}",
       "type": "SEARCH_ENGINE_SOGOU",
       "id": 56
@@ -236,7 +251,7 @@
       "name": "Yahoo!",
       "keyword": "yahoo.com",
       "favicon_url": "https://search.yahoo.com/favicon.ico",
-      "search_url": "https://search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
+      "search_url": "https://search.yahoo.com/search{google:pathWildcard}?ei={inputEncoding}&fr=crmas&p={searchTerms}",
       "suggest_url": "https://search.yahoo.com/sugg/chrome?output=fxjson&appid=crmas&command={searchTerms}",
       "type": "SEARCH_ENGINE_YAHOO",
       "id": 2
@@ -246,7 +261,7 @@
       "name": "Yahoo! Argentina",
       "keyword": "ar.yahoo.com",
       "favicon_url": "https://ar.search.yahoo.com/favicon.ico",
-      "search_url": "https://ar.search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
+      "search_url": "https://ar.search.yahoo.com/search{google:pathWildcard}?ei={inputEncoding}&fr=crmas&p={searchTerms}",
       "suggest_url": "https://ar.search.yahoo.com/sugg/chrome?output=fxjson&appid=crmas&command={searchTerms}",
       "type": "SEARCH_ENGINE_YAHOO",
       "id": 2
@@ -256,7 +271,7 @@
       "name": "Yahoo! \u00d6sterreich",
       "keyword": "at.yahoo.com",
       "favicon_url": "https://at.search.yahoo.com/favicon.ico",
-      "search_url": "https://at.search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
+      "search_url": "https://at.search.yahoo.com/search{google:pathWildcard}?ei={inputEncoding}&fr=crmas&p={searchTerms}",
       "suggest_url": "https://at.search.yahoo.com/sugg/chrome?output=fxjson&appid=crmas&command={searchTerms}",
       "type": "SEARCH_ENGINE_YAHOO",
       "id": 2
@@ -266,7 +281,7 @@
       "name": "Yahoo!7",
       "keyword": "au.yahoo.com",
       "favicon_url": "https://au.search.yahoo.com/favicon.ico",
-      "search_url": "https://au.search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
+      "search_url": "https://au.search.yahoo.com/search{google:pathWildcard}?ei={inputEncoding}&fr=crmas&p={searchTerms}",
       "suggest_url": "https://au.search.yahoo.com/sugg/chrome?output=fxjson&appid=crmas&command={searchTerms}",
       "type": "SEARCH_ENGINE_YAHOO",
       "id": 2
@@ -276,7 +291,7 @@
       "name": "Yahoo! Brasil",
       "keyword": "br.yahoo.com",
       "favicon_url": "https://br.search.yahoo.com/favicon.ico",
-      "search_url": "https://br.search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
+      "search_url": "https://br.search.yahoo.com/search{google:pathWildcard}?ei={inputEncoding}&fr=crmas&p={searchTerms}",
       "suggest_url": "https://br.search.yahoo.com/sugg/chrome?output=fxjson&appid=crmas&command={searchTerms}",
       "type": "SEARCH_ENGINE_YAHOO",
       "id": 2
@@ -286,7 +301,7 @@
       "name": "Yahoo! Canada",
       "keyword": "ca.yahoo.com",
       "favicon_url": "https://ca.search.yahoo.com/favicon.ico",
-      "search_url": "https://ca.search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
+      "search_url": "https://ca.search.yahoo.com/search{google:pathWildcard}?ei={inputEncoding}&fr=crmas&p={searchTerms}",
       "suggest_url": "https://ca.search.yahoo.com/sugg/chrome?output=fxjson&appid=crmas&command={searchTerms}",
       "type": "SEARCH_ENGINE_YAHOO",
       "id": 2
@@ -296,7 +311,7 @@
       "name": "Yahoo! Schweiz",
       "keyword": "ch.yahoo.com",
       "favicon_url": "https://ch.search.yahoo.com/favicon.ico",
-      "search_url": "https://ch.search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
+      "search_url": "https://ch.search.yahoo.com/search{google:pathWildcard}?ei={inputEncoding}&fr=crmas&p={searchTerms}",
       "suggest_url": "https://ch.search.yahoo.com/sugg/chrome?output=fxjson&appid=crmas&command={searchTerms}",
       "type": "SEARCH_ENGINE_YAHOO",
       "id": 2
@@ -306,7 +321,7 @@
       "name": "Yahoo! Chile",
       "keyword": "cl.yahoo.com",
       "favicon_url": "https://cl.search.yahoo.com/favicon.ico",
-      "search_url": "https://cl.search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
+      "search_url": "https://cl.search.yahoo.com/search{google:pathWildcard}?ei={inputEncoding}&fr=crmas&p={searchTerms}",
       "suggest_url": "https://cl.search.yahoo.com/sugg/chrome?output=fxjson&appid=crmas&command={searchTerms}",
       "type": "SEARCH_ENGINE_YAHOO",
       "id": 2
@@ -316,7 +331,7 @@
       "name": "Yahoo! Colombia",
       "keyword": "co.yahoo.com",
       "favicon_url": "https://co.search.yahoo.com/favicon.ico",
-      "search_url": "https://co.search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
+      "search_url": "https://co.search.yahoo.com/search{google:pathWildcard}?ei={inputEncoding}&fr=crmas&p={searchTerms}",
       "suggest_url": "https://co.search.yahoo.com/sugg/chrome?output=fxjson&appid=crmas&command={searchTerms}",
       "type": "SEARCH_ENGINE_YAHOO",
       "id": 2
@@ -326,7 +341,7 @@
       "name": "Yahoo! Deutschland",
       "keyword": "de.yahoo.com",
       "favicon_url": "https://de.search.yahoo.com/favicon.ico",
-      "search_url": "https://de.search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
+      "search_url": "https://de.search.yahoo.com/search{google:pathWildcard}?ei={inputEncoding}&fr=crmas&p={searchTerms}",
       "suggest_url": "https://de.search.yahoo.com/sugg/chrome?output=fxjson&appid=crmas&command={searchTerms}",
       "type": "SEARCH_ENGINE_YAHOO",
       "id": 2
@@ -339,7 +354,7 @@
       "name": "Yahoo! Danmark",
       "keyword": "dk.yahoo.com",
       "favicon_url": "https://dk.search.yahoo.com/favicon.ico",
-      "search_url": "https://dk.search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
+      "search_url": "https://dk.search.yahoo.com/search{google:pathWildcard}?ei={inputEncoding}&fr=crmas&p={searchTerms}",
       "type": "SEARCH_ENGINE_YAHOO",
       "id": 2
     },
@@ -348,7 +363,7 @@
       "name": "Yahoo! Espa\u00f1a",
       "keyword": "es.yahoo.com",
       "favicon_url": "https://es.search.yahoo.com/favicon.ico",
-      "search_url": "https://es.search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
+      "search_url": "https://es.search.yahoo.com/search{google:pathWildcard}?ei={inputEncoding}&fr=crmas&p={searchTerms}",
       "suggest_url": "https://es.search.yahoo.com/sugg/chrome?output=fxjson&appid=crmas&command={searchTerms}",
       "type": "SEARCH_ENGINE_YAHOO",
       "id": 2
@@ -358,7 +373,7 @@
       "name": "Yahoo! Suomi",
       "keyword": "fi.yahoo.com",
       "favicon_url": "https://fi.search.yahoo.com/favicon.ico",
-      "search_url": "https://fi.search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
+      "search_url": "https://fi.search.yahoo.com/search{google:pathWildcard}?ei={inputEncoding}&fr=crmas&p={searchTerms}",
       "type": "SEARCH_ENGINE_YAHOO",
       "id": 2
     },
@@ -367,7 +382,7 @@
       "name": "Yahoo! France",
       "keyword": "fr.yahoo.com",
       "favicon_url": "https://fr.search.yahoo.com/favicon.ico",
-      "search_url": "https://fr.search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
+      "search_url": "https://fr.search.yahoo.com/search{google:pathWildcard}?ei={inputEncoding}&fr=crmas&p={searchTerms}",
       "suggest_url": "https://fr.search.yahoo.com/sugg/chrome?output=fxjson&appid=crmas&command={searchTerms}",
       "type": "SEARCH_ENGINE_YAHOO",
       "id": 5  // Can't be 2 as this has to appear in the Belgium list alongside
@@ -378,7 +393,7 @@
       "name": "Yahoo! \u0395\u03bb\u03bb\u03ac\u03b4\u03b1\u03c2",
       "keyword": "gr.yahoo.com",
       "favicon_url": "https://gr.search.yahoo.com/favicon.ico",
-      "search_url": "https://gr.search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
+      "search_url": "https://gr.search.yahoo.com/search{google:pathWildcard}?ei={inputEncoding}&fr=crmas&p={searchTerms}",
       "type": "SEARCH_ENGINE_YAHOO",
       "id": 2
     },
@@ -387,7 +402,7 @@
       "name": "Yahoo! Hong Kong",
       "keyword": "hk.yahoo.com",
       "favicon_url": "https://hk.search.yahoo.com/favicon.ico",
-      "search_url": "https://hk.search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
+      "search_url": "https://hk.search.yahoo.com/search{google:pathWildcard}?ei={inputEncoding}&fr=crmas&p={searchTerms}",
       "suggest_url": "https://hk.search.yahoo.com/sugg/chrome?output=fxjson&appid=crmas&command={searchTerms}",
       "type": "SEARCH_ENGINE_YAHOO",
       "id": 2
@@ -397,7 +412,7 @@
       "name": "Yahoo! Indonesia",
       "keyword": "id.yahoo.com",
       "favicon_url": "https://id.search.yahoo.com/favicon.ico",
-      "search_url": "https://id.search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
+      "search_url": "https://id.search.yahoo.com/search{google:pathWildcard}?ei={inputEncoding}&fr=crmas&p={searchTerms}",
       "suggest_url": "https://id.search.yahoo.com/sugg/chrome?output=fxjson&appid=crmas&command={searchTerms}",
       "type": "SEARCH_ENGINE_YAHOO",
       "id": 2
@@ -407,7 +422,7 @@
       "name": "Yahoo! India",
       "keyword": "in.yahoo.com",
       "favicon_url": "https://in.search.yahoo.com/favicon.ico",
-      "search_url": "https://in.search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
+      "search_url": "https://in.search.yahoo.com/search{google:pathWildcard}?ei={inputEncoding}&fr=crmas&p={searchTerms}",
       "suggest_url": "https://in.search.yahoo.com/sugg/chrome?output=fxjson&appid=crmas&command={searchTerms}",
       "type": "SEARCH_ENGINE_YAHOO",
       "id": 2
@@ -417,7 +432,7 @@
       "name": "Yahoo! JAPAN",
       "keyword": "yahoo.co.jp",
       "favicon_url": "https://search.yahoo.co.jp/favicon.ico",
-      "search_url": "https://search.yahoo.co.jp/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
+      "search_url": "https://search.yahoo.co.jp/search{google:pathWildcard}?ei={inputEncoding}&fr=crmas&p={searchTerms}",
       "suggest_url": "https://search.yahooapis.jp/AssistSearchService/V2/webassistSearch?p={searchTerms}&appid=oQsoxcyxg66enp0TYoirkKoryq6rF8bK76mW0KYxZ0v0WPLtn.Lix6wy8F_LwGWHUII-&output=fxjson&fr=crmas",
       "type": "SEARCH_ENGINE_YAHOO",
       "id": 2
@@ -427,7 +442,7 @@
       "name": "Yahoo!\u200e \u0645\u0643\u062a\u0648\u0628",
       "keyword": "maktoob.yahoo.com",
       "favicon_url": "https://maktoob.search.yahoo.com/favicon.ico",
-      "search_url": "https://maktoob.search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
+      "search_url": "https://maktoob.search.yahoo.com/search{google:pathWildcard}?ei={inputEncoding}&fr=crmas&p={searchTerms}",
       "type": "SEARCH_ENGINE_YAHOO",
       "id": 2
     },
@@ -436,7 +451,7 @@
       "name": "Yahoo! M\u00e9xico",
       "keyword": "mx.yahoo.com",
       "favicon_url": "https://mx.search.yahoo.com/favicon.ico",
-      "search_url": "https://mx.search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
+      "search_url": "https://mx.search.yahoo.com/search{google:pathWildcard}?ei={inputEncoding}&fr=crmas&p={searchTerms}",
       "suggest_url": "https://mx.search.yahoo.com/sugg/chrome?output=fxjson&appid=crmas&command={searchTerms}",
       "type": "SEARCH_ENGINE_YAHOO",
       "id": 2
@@ -446,7 +461,7 @@
       "name": "Yahoo! Malaysia",
       "keyword": "malaysia.yahoo.com",
       "favicon_url": "https://malaysia.search.yahoo.com/favicon.ico",
-      "search_url": "https://malaysia.search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
+      "search_url": "https://malaysia.search.yahoo.com/search{google:pathWildcard}?ei={inputEncoding}&fr=crmas&p={searchTerms}",
       "suggest_url": "https://malaysia.search.yahoo.com/sugg/chrome?output=fxjson&appid=crmas&command={searchTerms}",
       "type": "SEARCH_ENGINE_YAHOO",
       "id": 2
@@ -456,7 +471,7 @@
       "name": "Yahoo! Nederland",
       "keyword": "nl.yahoo.com",
       "favicon_url": "https://nl.search.yahoo.com/favicon.ico",
-      "search_url": "https://nl.search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
+      "search_url": "https://nl.search.yahoo.com/search{google:pathWildcard}?ei={inputEncoding}&fr=crmas&p={searchTerms}",
       "suggest_url": "https://nl.search.yahoo.com/sugg/chrome?output=fxjson&appid=crmas&command={searchTerms}",
       "type": "SEARCH_ENGINE_YAHOO",
       "id": 2
@@ -466,7 +481,7 @@
       "name": "Yahoo! New Zealand",
       "keyword": "nz.yahoo.com",
       "favicon_url": "https://nz.search.yahoo.com/favicon.ico",
-      "search_url": "https://nz.search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
+      "search_url": "https://nz.search.yahoo.com/search{google:pathWildcard}?ei={inputEncoding}&fr=crmas&p={searchTerms}",
       "suggest_url": "https://nz.search.yahoo.com/sugg/chrome?output=fxjson&appid=crmas&command={searchTerms}",
       "type": "SEARCH_ENGINE_YAHOO",
       "id": 2
@@ -476,7 +491,7 @@
       "name": "Yahoo! Per\u00fa",
       "keyword": "pe.yahoo.com",
       "favicon_url": "https://pe.search.yahoo.com/favicon.ico",
-      "search_url": "https://pe.search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
+      "search_url": "https://pe.search.yahoo.com/search{google:pathWildcard}?ei={inputEncoding}&fr=crmas&p={searchTerms}",
       "suggest_url": "https://pe.search.yahoo.com/sugg/chrome?output=fxjson&appid=crmas&command={searchTerms}",
       "type": "SEARCH_ENGINE_YAHOO",
       "id": 2
@@ -486,7 +501,7 @@
       "name": "Yahoo! Philippines",
       "keyword": "ph.yahoo.com",
       "favicon_url": "https://ph.search.yahoo.com/favicon.ico",
-      "search_url": "https://ph.search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
+      "search_url": "https://ph.search.yahoo.com/search{google:pathWildcard}?ei={inputEncoding}&fr=crmas&p={searchTerms}",
       "suggest_url": "https://ph.search.yahoo.com/sugg/chrome?output=fxjson&appid=crmas&command={searchTerms}",
       "type": "SEARCH_ENGINE_YAHOO",
       "id": 2
@@ -496,7 +511,7 @@
       "name": "Yahoo! Qu\u00e9bec",
       "keyword": "qc.yahoo.com",
       "favicon_url": "https://qc.search.yahoo.com/favicon.ico",
-      "search_url": "https://qc.search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
+      "search_url": "https://qc.search.yahoo.com/search{google:pathWildcard}?ei={inputEncoding}&fr=crmas&p={searchTerms}",
       "suggest_url": "https://qc.search.yahoo.com/sugg/chrome?output=fxjson&appid=crmas&command={searchTerms}",
       "type": "SEARCH_ENGINE_YAHOO",
       "id": 5  // Can't be 2 as this has to appear in the Canada list alongside
@@ -507,7 +522,7 @@
       "name": "Yahoo! Rom\u00e2nia",
       "keyword": "ro.yahoo.com",
       "favicon_url": "https://ro.search.yahoo.com/favicon.ico",
-      "search_url": "https://ro.search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
+      "search_url": "https://ro.search.yahoo.com/search{google:pathWildcard}?ei={inputEncoding}&fr=crmas&p={searchTerms}",
       "type": "SEARCH_ENGINE_YAHOO",
       "id": 2
     },
@@ -516,7 +531,7 @@
       "name": "Yahoo! Sverige",
       "keyword": "se.yahoo.com",
       "favicon_url": "https://se.search.yahoo.com/favicon.ico",
-      "search_url": "https://se.search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
+      "search_url": "https://se.search.yahoo.com/search{google:pathWildcard}?ei={inputEncoding}&fr=crmas&p={searchTerms}",
       "type": "SEARCH_ENGINE_YAHOO",
       "id": 2
     },
@@ -525,7 +540,7 @@
       "name": "Yahoo! Singapore",
       "keyword": "sg.yahoo.com",
       "favicon_url": "https://sg.search.yahoo.com/favicon.ico",
-      "search_url": "https://sg.search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
+      "search_url": "https://sg.search.yahoo.com/search{google:pathWildcard}?ei={inputEncoding}&fr=crmas&p={searchTerms}",
       "suggest_url": "https://sg.search.yahoo.com/sugg/chrome?output=fxjson&appid=crmas&command={searchTerms}",
       "type": "SEARCH_ENGINE_YAHOO",
       "id": 2
@@ -535,7 +550,7 @@
       "name": "Yahoo! \u0e1b\u0e23\u0e30\u0e40\u0e17\u0e28\u0e44\u0e17\u0e22",
       "keyword": "th.yahoo.com",
       "favicon_url": "https://th.search.yahoo.com/favicon.ico",
-      "search_url": "https://th.search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
+      "search_url": "https://th.search.yahoo.com/search{google:pathWildcard}?ei={inputEncoding}&fr=crmas&p={searchTerms}",
       "suggest_url": "https://th.search.yahoo.com/sugg/chrome?output=fxjson&appid=crmas&command={searchTerms}",
       "type": "SEARCH_ENGINE_YAHOO",
       "id": 2
@@ -545,7 +560,7 @@
       "name": "Yahoo! T\u00fcrkiye",
       "keyword": "tr.yahoo.com",
       "favicon_url": "https://tr.search.yahoo.com/favicon.ico",
-      "search_url": "https://tr.search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
+      "search_url": "https://tr.search.yahoo.com/search{google:pathWildcard}?ei={inputEncoding}&fr=crmas&p={searchTerms}",
       "type": "SEARCH_ENGINE_YAHOO",
       "id": 2
     },
@@ -554,7 +569,7 @@
       "name": "Yahoo!\u5947\u6469",
       "keyword": "tw.yahoo.com",
       "favicon_url": "https://tw.search.yahoo.com/favicon.ico",
-      "search_url": "https://tw.search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
+      "search_url": "https://tw.search.yahoo.com/search{google:pathWildcard}?ei={inputEncoding}&fr=crmas&p={searchTerms}",
       "suggest_url": "https://tw.search.yahoo.com/sugg/chrome?output=fxjson&appid=crmas&command={searchTerms}",
       "type": "SEARCH_ENGINE_YAHOO",
       "id": 2
@@ -564,7 +579,7 @@
       "name": "Yahoo! UK & Ireland",
       "keyword": "uk.yahoo.com",
       "favicon_url": "https://uk.search.yahoo.com/favicon.ico",
-      "search_url": "https://uk.search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
+      "search_url": "https://uk.search.yahoo.com/search{google:pathWildcard}?ei={inputEncoding}&fr=crmas&p={searchTerms}",
       "suggest_url": "https://uk.search.yahoo.com/sugg/chrome?output=fxjson&appid=crmas&command={searchTerms}",
       "type": "SEARCH_ENGINE_YAHOO",
       "id": 2
@@ -574,7 +589,7 @@
       "name": "Yahoo! Venezuela",
       "keyword": "ve.yahoo.com",
       "favicon_url": "https://ve.search.yahoo.com/favicon.ico",
-      "search_url": "https://ve.search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
+      "search_url": "https://ve.search.yahoo.com/search{google:pathWildcard}?ei={inputEncoding}&fr=crmas&p={searchTerms}",
       "suggest_url": "https://ve.search.yahoo.com/sugg/chrome?output=fxjson&appid=crmas&command={searchTerms}",
       "type": "SEARCH_ENGINE_YAHOO",
       "id": 2
@@ -584,7 +599,7 @@
       "name": "Yahoo! Vi\u1ec7t Nam",
       "keyword": "vn.yahoo.com",
       "favicon_url": "https://vn.search.yahoo.com/favicon.ico",
-      "search_url": "https://vn.search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}",
+      "search_url": "https://vn.search.yahoo.com/search{google:pathWildcard}?ei={inputEncoding}&fr=crmas&p={searchTerms}",
       "suggest_url": "https://vn.search.yahoo.com/sugg/chrome?output=fxjson&appid=crmas&command={searchTerms}",
       "type": "SEARCH_ENGINE_YAHOO",
       "id": 2
diff --git a/components/test/data/update_client/updatecheck_reply_unknownapp.xml b/components/test/data/update_client/updatecheck_reply_unknownapp.xml
new file mode 100644
index 0000000..f708ec4
--- /dev/null
+++ b/components/test/data/update_client/updatecheck_reply_unknownapp.xml
@@ -0,0 +1,4 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<response protocol='3.1'>
+  <app appid='jebgalgnebhfojomionfpkfelancnnkf' status="error-unknownApplication"/>
+</response>
diff --git a/components/update_client/BUILD.gn b/components/update_client/BUILD.gn
index 990eb012..d367d40 100644
--- a/components/update_client/BUILD.gn
+++ b/components/update_client/BUILD.gn
@@ -133,6 +133,7 @@
     "//components/test/data/update_client/updatecheck_reply_4.xml",
     "//components/test/data/update_client/updatecheck_reply_noupdate.xml",
     "//components/test/data/update_client/updatecheck_reply_parse_error.xml",
+    "//components/test/data/update_client/updatecheck_reply_unknownapp.xml",
   ]
   outputs = [
     "{{bundle_resources_dir}}/" +
diff --git a/components/update_client/protocol_parser.cc b/components/update_client/protocol_parser.cc
index 95902f6..efd88dd 100644
--- a/components/update_client/protocol_parser.cc
+++ b/components/update_client/protocol_parser.cc
@@ -321,7 +321,25 @@
     return false;
   }
 
-  // Get the <updatecheck> tag.
+  // Read the |status| attribute for the app.
+  // If the status is one of the defined app status error literals, then return
+  // it in the result as if it were an updatecheck status, then stop parsing,
+  // and return success.
+  result->status = GetAttribute(app, "status");
+  if (result->status == "restricted" ||
+      result->status == "error-unknownApplication" ||
+      result->status == "error-invalidAppId")
+    return true;
+
+  // If the status was not handled above and the status is not "ok", then
+  // this must be a status literal that that the parser does not know about.
+  if (!result->status.empty() && result->status != "ok") {
+    *error = "Unknown app status";
+    return false;
+  }
+
+  // Get the <updatecheck> tag if the status is missing or the status is "ok".
+  DCHECK(result->status.empty() || result->status == "ok");
   std::vector<xmlNode*> updates = GetChildren(app, "updatecheck");
   if (updates.empty()) {
     *error = "Missing updatecheck on app.";
diff --git a/components/update_client/protocol_parser_unittest.cc b/components/update_client/protocol_parser_unittest.cc
index e34f186..0a09a64 100644
--- a/components/update_client/protocol_parser_unittest.cc
+++ b/components/update_client/protocol_parser_unittest.cc
@@ -289,6 +289,24 @@
     " </app>"
     "</response>";
 
+// Includes four <app> tags with status different than "ok".
+const char* kAppsStatusError =
+    "<?xml version='1.0' encoding='UTF-8'?>"
+    "<response protocol='3.1'>"
+    " <app appid='aaaaaaaa' status='error-unknownApplication'>"
+    "  <updatecheck status='error-internal'/>"
+    " </app>"
+    " <app appid='bbbbbbbb' status='restricted'>"
+    "  <updatecheck status='error-internal'/>"
+    " </app>"
+    " <app appid='cccccccc' status='error-invalidAppId'>"
+    "  <updatecheck status='error-internal'/>"
+    " </app>"
+    " <app appid='dddddddd' status='foobar'>"
+    "  <updatecheck status='error-internal'/>"
+    " </app>"
+    "</response>";
+
 TEST(ComponentUpdaterProtocolParserTest, Parse) {
   ProtocolParser parser;
 
@@ -324,15 +342,15 @@
   EXPECT_TRUE(parser.Parse(kValidXml));
   EXPECT_TRUE(parser.errors().empty());
   EXPECT_EQ(1u, parser.results().list.size());
-  const ProtocolParser::Result* firstResult = &parser.results().list[0];
-  EXPECT_STREQ("ok", firstResult->status.c_str());
-  EXPECT_EQ(1u, firstResult->crx_urls.size());
-  EXPECT_EQ(GURL("http://example.com/"), firstResult->crx_urls[0]);
-  EXPECT_EQ(GURL("http://diff.example.com/"), firstResult->crx_diffurls[0]);
-  EXPECT_EQ("1.2.3.4", firstResult->manifest.version);
-  EXPECT_EQ("2.0.143.0", firstResult->manifest.browser_min_version);
-  EXPECT_EQ(1u, firstResult->manifest.packages.size());
-  EXPECT_EQ("extension_1_2_3_4.crx", firstResult->manifest.packages[0].name);
+  const ProtocolParser::Result* first_result = &parser.results().list[0];
+  EXPECT_STREQ("ok", first_result->status.c_str());
+  EXPECT_EQ(1u, first_result->crx_urls.size());
+  EXPECT_EQ(GURL("http://example.com/"), first_result->crx_urls[0]);
+  EXPECT_EQ(GURL("http://diff.example.com/"), first_result->crx_diffurls[0]);
+  EXPECT_EQ("1.2.3.4", first_result->manifest.version);
+  EXPECT_EQ("2.0.143.0", first_result->manifest.browser_min_version);
+  EXPECT_EQ(1u, first_result->manifest.packages.size());
+  EXPECT_EQ("extension_1_2_3_4.crx", first_result->manifest.packages[0].name);
 
   // Parse some xml that uses namespace prefixes.
   EXPECT_TRUE(parser.Parse(kUsesNamespacePrefix));
@@ -344,23 +362,23 @@
   EXPECT_TRUE(parser.Parse(valid_xml_with_hash));
   EXPECT_TRUE(parser.errors().empty());
   EXPECT_FALSE(parser.results().list.empty());
-  firstResult = &parser.results().list[0];
-  EXPECT_FALSE(firstResult->manifest.packages.empty());
-  EXPECT_EQ("1234", firstResult->manifest.packages[0].hash_sha256);
-  EXPECT_EQ("5678", firstResult->manifest.packages[0].hashdiff_sha256);
+  first_result = &parser.results().list[0];
+  EXPECT_FALSE(first_result->manifest.packages.empty());
+  EXPECT_EQ("1234", first_result->manifest.packages[0].hash_sha256);
+  EXPECT_EQ("5678", first_result->manifest.packages[0].hashdiff_sha256);
 
   // Parse xml with package size value
   EXPECT_TRUE(parser.Parse(valid_xml_with_invalid_sizes));
   EXPECT_TRUE(parser.errors().empty());
   EXPECT_FALSE(parser.results().list.empty());
-  firstResult = &parser.results().list[0];
-  EXPECT_FALSE(firstResult->manifest.packages.empty());
-  EXPECT_EQ(1234, firstResult->manifest.packages[0].size);
-  EXPECT_EQ(-1234, firstResult->manifest.packages[1].size);
-  EXPECT_EQ(0, firstResult->manifest.packages[2].size);
-  EXPECT_EQ(0, firstResult->manifest.packages[3].size);
-  EXPECT_EQ(0, firstResult->manifest.packages[4].size);
-  EXPECT_EQ(0, firstResult->manifest.packages[5].size);
+  first_result = &parser.results().list[0];
+  EXPECT_FALSE(first_result->manifest.packages.empty());
+  EXPECT_EQ(1234, first_result->manifest.packages[0].size);
+  EXPECT_EQ(-1234, first_result->manifest.packages[1].size);
+  EXPECT_EQ(0, first_result->manifest.packages[2].size);
+  EXPECT_EQ(0, first_result->manifest.packages[3].size);
+  EXPECT_EQ(0, first_result->manifest.packages[4].size);
+  EXPECT_EQ(0, first_result->manifest.packages[5].size);
 
   // Parse xml with a <daystart> element.
   EXPECT_TRUE(parser.Parse(kWithDaystart));
@@ -372,63 +390,82 @@
   EXPECT_TRUE(parser.Parse(kNoUpdate));
   EXPECT_TRUE(parser.errors().empty());
   EXPECT_FALSE(parser.results().list.empty());
-  firstResult = &parser.results().list[0];
-  EXPECT_STREQ("noupdate", firstResult->status.c_str());
-  EXPECT_EQ(firstResult->extension_id, "12345");
-  EXPECT_EQ(firstResult->manifest.version, "");
+  first_result = &parser.results().list[0];
+  EXPECT_STREQ("noupdate", first_result->status.c_str());
+  EXPECT_EQ(first_result->extension_id, "12345");
+  EXPECT_EQ(first_result->manifest.version, "");
 
   // Parse xml with one error and one success <app> tag.
   EXPECT_TRUE(parser.Parse(kTwoAppsOneError));
-  EXPECT_FALSE(parser.errors().empty());
-  EXPECT_EQ(1u, parser.results().list.size());
-  firstResult = &parser.results().list[0];
-  EXPECT_EQ(firstResult->extension_id, "bbbbbbbb");
-  EXPECT_STREQ("ok", firstResult->status.c_str());
-  EXPECT_EQ("1.2.3.4", firstResult->manifest.version);
+  EXPECT_TRUE(parser.errors().empty());
+  EXPECT_EQ(2u, parser.results().list.size());
+  first_result = &parser.results().list[0];
+  EXPECT_EQ(first_result->extension_id, "aaaaaaaa");
+  EXPECT_STREQ("error-unknownApplication", first_result->status.c_str());
+  EXPECT_TRUE(first_result->manifest.version.empty());
+  const ProtocolParser::Result* second_result = &parser.results().list[1];
+  EXPECT_EQ(second_result->extension_id, "bbbbbbbb");
+  EXPECT_STREQ("ok", second_result->status.c_str());
+  EXPECT_EQ("1.2.3.4", second_result->manifest.version);
 
   // Parse xml with two apps setting the cohort info.
   EXPECT_TRUE(parser.Parse(kTwoAppsSetCohort));
   EXPECT_TRUE(parser.errors().empty());
   EXPECT_EQ(2u, parser.results().list.size());
-  firstResult = &parser.results().list[0];
-  EXPECT_EQ(firstResult->extension_id, "aaaaaaaa");
-  EXPECT_NE(firstResult->cohort_attrs.find("cohort"),
-            firstResult->cohort_attrs.end());
-  EXPECT_EQ(firstResult->cohort_attrs.find("cohort")->second, "1:2q3/");
-  EXPECT_EQ(firstResult->cohort_attrs.find("cohortname"),
-            firstResult->cohort_attrs.end());
-  EXPECT_EQ(firstResult->cohort_attrs.find("cohorthint"),
-            firstResult->cohort_attrs.end());
-  const ProtocolParser::Result* secondResult = &parser.results().list[1];
-  EXPECT_EQ(secondResult->extension_id, "bbbbbbbb");
-  EXPECT_NE(secondResult->cohort_attrs.find("cohort"),
-            secondResult->cohort_attrs.end());
-  EXPECT_EQ(secondResult->cohort_attrs.find("cohort")->second, "1:33z@0.33");
-  EXPECT_NE(secondResult->cohort_attrs.find("cohortname"),
-            secondResult->cohort_attrs.end());
-  EXPECT_EQ(secondResult->cohort_attrs.find("cohortname")->second, "cname");
-  EXPECT_EQ(secondResult->cohort_attrs.find("cohorthint"),
-            secondResult->cohort_attrs.end());
+  first_result = &parser.results().list[0];
+  EXPECT_EQ(first_result->extension_id, "aaaaaaaa");
+  EXPECT_NE(first_result->cohort_attrs.find("cohort"),
+            first_result->cohort_attrs.end());
+  EXPECT_EQ(first_result->cohort_attrs.find("cohort")->second, "1:2q3/");
+  EXPECT_EQ(first_result->cohort_attrs.find("cohortname"),
+            first_result->cohort_attrs.end());
+  EXPECT_EQ(first_result->cohort_attrs.find("cohorthint"),
+            first_result->cohort_attrs.end());
+  EXPECT_EQ(second_result->extension_id, "bbbbbbbb");
+  EXPECT_NE(second_result->cohort_attrs.find("cohort"),
+            second_result->cohort_attrs.end());
+  EXPECT_EQ(second_result->cohort_attrs.find("cohort")->second, "1:33z@0.33");
+  EXPECT_NE(second_result->cohort_attrs.find("cohortname"),
+            second_result->cohort_attrs.end());
+  EXPECT_EQ(second_result->cohort_attrs.find("cohortname")->second, "cname");
+  EXPECT_EQ(second_result->cohort_attrs.find("cohorthint"),
+            second_result->cohort_attrs.end());
 
   EXPECT_TRUE(parser.Parse(kUpdateCheckStatusOkWithRunAction));
   EXPECT_TRUE(parser.errors().empty());
   EXPECT_FALSE(parser.results().list.empty());
-  firstResult = &parser.results().list[0];
-  EXPECT_STREQ("ok", firstResult->status.c_str());
-  EXPECT_EQ(firstResult->extension_id, "12345");
-  EXPECT_STREQ("this", firstResult->action_run.c_str());
+  first_result = &parser.results().list[0];
+  EXPECT_STREQ("ok", first_result->status.c_str());
+  EXPECT_EQ(first_result->extension_id, "12345");
+  EXPECT_STREQ("this", first_result->action_run.c_str());
 
   EXPECT_TRUE(parser.Parse(kUpdateCheckStatusNoUpdateWithRunAction));
   EXPECT_TRUE(parser.errors().empty());
   EXPECT_FALSE(parser.results().list.empty());
-  firstResult = &parser.results().list[0];
-  EXPECT_STREQ("noupdate", firstResult->status.c_str());
-  EXPECT_EQ(firstResult->extension_id, "12345");
-  EXPECT_STREQ("this", firstResult->action_run.c_str());
+  first_result = &parser.results().list[0];
+  EXPECT_STREQ("noupdate", first_result->status.c_str());
+  EXPECT_EQ(first_result->extension_id, "12345");
+  EXPECT_STREQ("this", first_result->action_run.c_str());
 
   EXPECT_TRUE(parser.Parse(kUpdateCheckStatusErrorWithRunAction));
   EXPECT_FALSE(parser.errors().empty());
   EXPECT_TRUE(parser.results().list.empty());
+
+  EXPECT_TRUE(parser.Parse(kAppsStatusError));
+  EXPECT_STREQ("Unknown app status", parser.errors().c_str());
+  EXPECT_EQ(3u, parser.results().list.size());
+  first_result = &parser.results().list[0];
+  EXPECT_EQ(first_result->extension_id, "aaaaaaaa");
+  EXPECT_STREQ("error-unknownApplication", first_result->status.c_str());
+  EXPECT_TRUE(first_result->manifest.version.empty());
+  second_result = &parser.results().list[1];
+  EXPECT_EQ(second_result->extension_id, "bbbbbbbb");
+  EXPECT_STREQ("restricted", second_result->status.c_str());
+  EXPECT_TRUE(second_result->manifest.version.empty());
+  const ProtocolParser::Result* third_result = &parser.results().list[2];
+  EXPECT_EQ(third_result->extension_id, "cccccccc");
+  EXPECT_STREQ("error-invalidAppId", third_result->status.c_str());
+  EXPECT_TRUE(third_result->manifest.version.empty());
 }
 
 }  // namespace update_client
diff --git a/components/update_client/update_checker_unittest.cc b/components/update_client/update_checker_unittest.cc
index 8a1dbe3..91d0e2a0 100644
--- a/components/update_client/update_checker_unittest.cc
+++ b/components/update_client/update_checker_unittest.cc
@@ -990,4 +990,36 @@
   EXPECT_FALSE(results_);
 }
 
+// The update response contains a status |error-unknownApplication| for the
+// app. The response is succesfully parsed and a result is extracted to
+// indicate this status.
+TEST_F(UpdateCheckerTest, ParseErrorAppStatusErrorUnknownApplication) {
+  EXPECT_TRUE(post_interceptor_->ExpectRequest(
+      std::make_unique<PartialMatch>("updatecheck"),
+      test_file("updatecheck_reply_unknownapp.xml")));
+
+  update_checker_ = UpdateChecker::Create(config_, metadata_.get());
+
+  IdToComponentPtrMap components;
+  components[kUpdateItemId] = MakeComponent();
+
+  update_checker_->CheckForUpdates(
+      update_context_->session_id, {kUpdateItemId}, components, "", true,
+      base::BindOnce(&UpdateCheckerTest::UpdateCheckComplete,
+                     base::Unretained(this)));
+  RunThreads();
+
+  EXPECT_EQ(1, post_interceptor_->GetHitCount())
+      << post_interceptor_->GetRequestsAsString();
+  ASSERT_EQ(1, post_interceptor_->GetCount())
+      << post_interceptor_->GetRequestsAsString();
+
+  EXPECT_EQ(ErrorCategory::kNone, error_category_);
+  EXPECT_EQ(0, error_);
+  EXPECT_TRUE(results_);
+  EXPECT_EQ(1u, results_->list.size());
+  const auto& result = results_->list.front();
+  EXPECT_STREQ("error-unknownApplication", result.status.c_str());
+}
+
 }  // namespace update_client
diff --git a/components/update_client/update_client_errors.h b/components/update_client/update_client_errors.h
index 9c57e77d..47a6231 100644
--- a/components/update_client/update_client_errors.h
+++ b/components/update_client/update_client_errors.h
@@ -100,12 +100,16 @@
 // error in any meaningful way, but this value may be reported in UMA stats,
 // therefore avoiding collisions with known network errors is desirable.
 enum class ProtocolError : int {
+  NONE = 0,
   RESPONSE_NOT_TRUSTED = -10000,
   MISSING_PUBLIC_KEY = -10001,
   MISSING_URLS = -10002,
   PARSE_FAILED = -10003,
   UPDATE_RESPONSE_NOT_FOUND = -10004,
   URL_FETCHER_FAILED = -10005,
+  UNKNOWN_APPLICATION = -10006,
+  RESTRICTED_APPLICATION = -10007,
+  INVALID_APPID = -10008,
 };
 
 }  // namespace update_client
diff --git a/components/update_client/update_client_unittest.cc b/components/update_client/update_client_unittest.cc
index 75abb181..4e99005 100644
--- a/components/update_client/update_client_unittest.cc
+++ b/components/update_client/update_client_unittest.cc
@@ -269,10 +269,8 @@
       results.list.push_back(result);
 
       base::ThreadTaskRunnerHandle::Get()->PostTask(
-          FROM_HERE,
-          base::BindOnce(std::move(update_check_callback),
-                         base::make_optional<ProtocolParser::Results>(results),
-                         ErrorCategory::kNone, 0, 0));
+          FROM_HERE, base::BindOnce(std::move(update_check_callback), results,
+                                    ErrorCategory::kNone, 0, 0));
     }
   };
 
@@ -436,10 +434,8 @@
       }
 
       base::ThreadTaskRunnerHandle::Get()->PostTask(
-          FROM_HERE,
-          base::BindOnce(std::move(update_check_callback),
-                         base::make_optional<ProtocolParser::Results>(results),
-                         ErrorCategory::kNone, 0, 0));
+          FROM_HERE, base::BindOnce(std::move(update_check_callback), results,
+                                    ErrorCategory::kNone, 0, 0));
     }
   };
 
@@ -641,10 +637,8 @@
       }
 
       base::ThreadTaskRunnerHandle::Get()->PostTask(
-          FROM_HERE,
-          base::BindOnce(std::move(update_check_callback),
-                         base::make_optional<ProtocolParser::Results>(results),
-                         ErrorCategory::kNone, 0, 0));
+          FROM_HERE, base::BindOnce(std::move(update_check_callback), results,
+                                    ErrorCategory::kNone, 0, 0));
     }
   };
 
@@ -855,10 +849,8 @@
       }
 
       base::ThreadTaskRunnerHandle::Get()->PostTask(
-          FROM_HERE,
-          base::BindOnce(std::move(update_check_callback),
-                         base::make_optional<ProtocolParser::Results>(results),
-                         ErrorCategory::kNone, 0, 0));
+          FROM_HERE, base::BindOnce(std::move(update_check_callback), results,
+                                    ErrorCategory::kNone, 0, 0));
     }
   };
 
@@ -1190,10 +1182,8 @@
       }
 
       base::ThreadTaskRunnerHandle::Get()->PostTask(
-          FROM_HERE,
-          base::BindOnce(std::move(update_check_callback),
-                         base::make_optional<ProtocolParser::Results>(results),
-                         ErrorCategory::kNone, 0, 0));
+          FROM_HERE, base::BindOnce(std::move(update_check_callback), results,
+                                    ErrorCategory::kNone, 0, 0));
     }
   };
 
@@ -1487,10 +1477,8 @@
       }
 
       base::ThreadTaskRunnerHandle::Get()->PostTask(
-          FROM_HERE,
-          base::BindOnce(std::move(update_check_callback),
-                         base::make_optional<ProtocolParser::Results>(results),
-                         ErrorCategory::kNone, 0, 0));
+          FROM_HERE, base::BindOnce(std::move(update_check_callback), results,
+                                    ErrorCategory::kNone, 0, 0));
     }
   };
 
@@ -1767,10 +1755,8 @@
       ProtocolParser::Results results;
       results.list.push_back(result);
       base::ThreadTaskRunnerHandle::Get()->PostTask(
-          FROM_HERE,
-          base::BindOnce(std::move(update_check_callback),
-                         base::make_optional<ProtocolParser::Results>(results),
-                         ErrorCategory::kNone, 0, 0));
+          FROM_HERE, base::BindOnce(std::move(update_check_callback), results,
+                                    ErrorCategory::kNone, 0, 0));
     }
   };
 
@@ -2020,10 +2006,8 @@
       }
 
       base::ThreadTaskRunnerHandle::Get()->PostTask(
-          FROM_HERE,
-          base::BindOnce(std::move(update_check_callback),
-                         base::make_optional<ProtocolParser::Results>(results),
-                         ErrorCategory::kNone, 0, 0));
+          FROM_HERE, base::BindOnce(std::move(update_check_callback), results,
+                                    ErrorCategory::kNone, 0, 0));
     }
   };
 
@@ -2247,10 +2231,8 @@
       results.list.push_back(result);
 
       base::ThreadTaskRunnerHandle::Get()->PostTask(
-          FROM_HERE,
-          base::BindOnce(std::move(update_check_callback),
-                         base::make_optional<ProtocolParser::Results>(results),
-                         ErrorCategory::kNone, 0, 0));
+          FROM_HERE, base::BindOnce(std::move(update_check_callback), results,
+                                    ErrorCategory::kNone, 0, 0));
     }
   };
 
@@ -2397,10 +2379,8 @@
       EXPECT_TRUE(components.at(id)->is_foreground());
 
       base::ThreadTaskRunnerHandle::Get()->PostTask(
-          FROM_HERE,
-          base::BindOnce(std::move(update_check_callback),
-                         base::make_optional<ProtocolParser::Results>(results),
-                         ErrorCategory::kNone, 0, 0));
+          FROM_HERE, base::BindOnce(std::move(update_check_callback), results,
+                                    ErrorCategory::kNone, 0, 0));
     }
   };
 
@@ -2652,10 +2632,8 @@
       EXPECT_TRUE(components.at(id)->is_foreground());
 
       base::ThreadTaskRunnerHandle::Get()->PostTask(
-          FROM_HERE,
-          base::BindOnce(std::move(update_check_callback),
-                         base::make_optional<ProtocolParser::Results>(results),
-                         ErrorCategory::kNone, 0, 0));
+          FROM_HERE, base::BindOnce(std::move(update_check_callback), results,
+                                    ErrorCategory::kNone, 0, 0));
     }
   };
 
@@ -2937,10 +2915,8 @@
       results.list.push_back(result);
 
       base::ThreadTaskRunnerHandle::Get()->PostTask(
-          FROM_HERE,
-          base::BindOnce(std::move(update_check_callback),
-                         base::make_optional<ProtocolParser::Results>(results),
-                         ErrorCategory::kNone, 0, retry_after_sec));
+          FROM_HERE, base::BindOnce(std::move(update_check_callback), results,
+                                    ErrorCategory::kNone, 0, retry_after_sec));
     }
   };
 
@@ -3182,10 +3158,8 @@
       }
 
       base::ThreadTaskRunnerHandle::Get()->PostTask(
-          FROM_HERE,
-          base::BindOnce(std::move(update_check_callback),
-                         base::make_optional<ProtocolParser::Results>(results),
-                         ErrorCategory::kNone, 0, 0));
+          FROM_HERE, base::BindOnce(std::move(update_check_callback), results,
+                                    ErrorCategory::kNone, 0, 0));
     }
   };
 
@@ -3417,6 +3391,208 @@
   update_client->RemoveObserver(&observer);
 }
 
+// Tests the scenario where the server responds with different values for
+// application status.
+TEST_F(UpdateClientTest, OneCrxErrorUnknownApp) {
+  class DataCallbackMock {
+   public:
+    static std::vector<std::unique_ptr<CrxComponent>> Callback(
+        const std::vector<std::string>& ids) {
+      std::vector<std::unique_ptr<CrxComponent>> component;
+
+      std::unique_ptr<CrxComponent> crx = std::make_unique<CrxComponent>();
+      crx->name = "test_jebg";
+      crx->pk_hash.assign(jebg_hash, jebg_hash + base::size(jebg_hash));
+      crx->version = base::Version("0.9");
+      crx->installer = base::MakeRefCounted<TestInstaller>();
+      component.push_back(std::move(crx));
+
+      crx = std::make_unique<CrxComponent>();
+      crx->name = "test_abag";
+      crx->pk_hash.assign(abag_hash, abag_hash + base::size(abag_hash));
+      crx->version = base::Version("0.1");
+      crx->installer = base::MakeRefCounted<TestInstaller>();
+      component.push_back(std::move(crx));
+
+      crx = std::make_unique<CrxComponent>();
+      crx->name = "test_ihfo";
+      crx->pk_hash.assign(ihfo_hash, ihfo_hash + base::size(ihfo_hash));
+      crx->version = base::Version("0.2");
+      crx->installer = base::MakeRefCounted<TestInstaller>();
+      component.push_back(std::move(crx));
+
+      crx = std::make_unique<CrxComponent>();
+      crx->name = "test_gjpm";
+      crx->pk_hash.assign(gjpm_hash, gjpm_hash + base::size(gjpm_hash));
+      crx->version = base::Version("0.3");
+      crx->installer = base::MakeRefCounted<TestInstaller>();
+      component.push_back(std::move(crx));
+
+      return component;
+    }
+  };
+
+  class CompletionCallbackMock {
+   public:
+    static void Callback(base::OnceClosure quit_closure, Error error) {
+      EXPECT_EQ(Error::NONE, error);
+      std::move(quit_closure).Run();
+    }
+  };
+
+  class MockUpdateChecker : public UpdateChecker {
+   public:
+    static std::unique_ptr<UpdateChecker> Create(
+        scoped_refptr<Configurator> config,
+        PersistedData* metadata) {
+      return std::make_unique<MockUpdateChecker>();
+    }
+
+    void CheckForUpdates(const std::string& session_id,
+                         const std::vector<std::string>& ids_to_check,
+                         const IdToComponentPtrMap& components,
+                         const std::string& additional_attributes,
+                         bool enabled_component_updates,
+                         UpdateCheckCallback update_check_callback) override {
+      EXPECT_FALSE(session_id.empty());
+      EXPECT_TRUE(enabled_component_updates);
+      EXPECT_EQ(4u, ids_to_check.size());
+
+      const std::string update_response =
+          R"(<?xml version="1.0" encoding="UTF-8"?>)"
+          R"(<response protocol="3.1">)"
+          R"(<app appid="jebgalgnebhfojomionfpkfelancnnkf")"
+          R"( status="error-unknownApplication"/>)"
+          R"(<app appid="abagagagagagagagagagagagagagagag")"
+          R"( status="restricted"/>)"
+          R"(<app appid="ihfokbkgjpifnbbojhneepfflplebdkc")"
+          R"( status="error-invalidAppId"/>)"
+          R"(<app appid="gjpmebpgbhcamgdgjcmnjfhggjpgcimm")"
+          R"( status="error-foobarApp"/>)"
+          R"(</response>)";
+
+      ProtocolParser parser;
+      EXPECT_TRUE(parser.Parse(update_response));
+
+      base::ThreadTaskRunnerHandle::Get()->PostTask(
+          FROM_HERE,
+          base::BindOnce(std::move(update_check_callback), parser.results(),
+                         ErrorCategory::kNone, 0, 0));
+    }
+  };
+
+  class MockCrxDownloader : public CrxDownloader {
+   public:
+    static std::unique_ptr<CrxDownloader> Create(
+        bool is_background_download,
+        scoped_refptr<net::URLRequestContextGetter> context_getter) {
+      return std::make_unique<MockCrxDownloader>();
+    }
+
+    MockCrxDownloader() : CrxDownloader(nullptr) {}
+
+   private:
+    void DoStartDownload(const GURL& url) override { EXPECT_TRUE(false); }
+  };
+
+  class MockPingManager : public MockPingManagerImpl {
+   public:
+    explicit MockPingManager(scoped_refptr<Configurator> config)
+        : MockPingManagerImpl(config) {}
+
+   protected:
+    ~MockPingManager() override { EXPECT_TRUE(ping_data().empty()); }
+  };
+
+  scoped_refptr<UpdateClient> update_client =
+      base::MakeRefCounted<UpdateClientImpl>(
+          config(), base::MakeRefCounted<MockPingManager>(config()),
+          &MockUpdateChecker::Create, &MockCrxDownloader::Create);
+
+  MockObserver observer;
+  {
+    InSequence seq;
+    EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
+                                  "jebgalgnebhfojomionfpkfelancnnkf"))
+        .Times(1);
+    EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_ERROR,
+                                  "jebgalgnebhfojomionfpkfelancnnkf"))
+        .Times(1)
+        .WillOnce(Invoke([&update_client](Events event, const std::string& id) {
+          CrxUpdateItem item;
+          update_client->GetCrxUpdateState(id, &item);
+          EXPECT_EQ(ComponentState::kUpdateError, item.state);
+          EXPECT_EQ(5, static_cast<int>(item.error_category));
+          EXPECT_EQ(-10006, item.error_code);  // UNKNOWN_APPPLICATION.
+          EXPECT_EQ(0, item.extra_code1);
+        }));
+  }
+  {
+    InSequence seq;
+    EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
+                                  "abagagagagagagagagagagagagagagag"))
+        .Times(1);
+    EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_ERROR,
+                                  "abagagagagagagagagagagagagagagag"))
+        .Times(1)
+        .WillOnce(Invoke([&update_client](Events event, const std::string& id) {
+          CrxUpdateItem item;
+          update_client->GetCrxUpdateState(id, &item);
+          EXPECT_EQ(ComponentState::kUpdateError, item.state);
+          EXPECT_EQ(5, static_cast<int>(item.error_category));
+          EXPECT_EQ(-10007, item.error_code);  // RESTRICTED_APPLICATION.
+          EXPECT_EQ(0, item.extra_code1);
+        }));
+  }
+  {
+    InSequence seq;
+    EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
+                                  "ihfokbkgjpifnbbojhneepfflplebdkc"))
+        .Times(1);
+    EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_ERROR,
+                                  "ihfokbkgjpifnbbojhneepfflplebdkc"))
+        .Times(1)
+        .WillOnce(Invoke([&update_client](Events event, const std::string& id) {
+          CrxUpdateItem item;
+          update_client->GetCrxUpdateState(id, &item);
+          EXPECT_EQ(ComponentState::kUpdateError, item.state);
+          EXPECT_EQ(5, static_cast<int>(item.error_category));
+          EXPECT_EQ(-10008, item.error_code);  // INVALID_APPID.
+          EXPECT_EQ(0, item.extra_code1);
+        }));
+  }
+  {
+    InSequence seq;
+    EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES,
+                                  "gjpmebpgbhcamgdgjcmnjfhggjpgcimm"))
+        .Times(1);
+    EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_ERROR,
+                                  "gjpmebpgbhcamgdgjcmnjfhggjpgcimm"))
+        .Times(1)
+        .WillOnce(Invoke([&update_client](Events event, const std::string& id) {
+          CrxUpdateItem item;
+          update_client->GetCrxUpdateState(id, &item);
+          EXPECT_EQ(ComponentState::kUpdateError, item.state);
+          EXPECT_EQ(5, static_cast<int>(item.error_category));
+          EXPECT_EQ(-10004, item.error_code);  // UPDATE_RESPONSE_NOT_FOUND.
+          EXPECT_EQ(0, item.extra_code1);
+        }));
+  }
+
+  update_client->AddObserver(&observer);
+
+  const std::vector<std::string> ids = {
+      "jebgalgnebhfojomionfpkfelancnnkf", "abagagagagagagagagagagagagagagag",
+      "ihfokbkgjpifnbbojhneepfflplebdkc", "gjpmebpgbhcamgdgjcmnjfhggjpgcimm"};
+  update_client->Update(
+      ids, base::BindOnce(&DataCallbackMock::Callback), true,
+      base::BindOnce(&CompletionCallbackMock::Callback, quit_closure()));
+
+  RunThreads();
+
+  update_client->RemoveObserver(&observer);
+}
+
 #if defined(OS_WIN)  // ActionRun is only implemented on Windows.
 
 // Tests that a run action in invoked in the CRX install scenario.
@@ -3484,10 +3660,8 @@
       results.list.push_back(result);
 
       base::ThreadTaskRunnerHandle::Get()->PostTask(
-          FROM_HERE,
-          base::BindOnce(std::move(update_check_callback),
-                         base::make_optional<ProtocolParser::Results>(results),
-                         ErrorCategory::kNone, 0, 0));
+          FROM_HERE, base::BindOnce(std::move(update_check_callback), results,
+                                    ErrorCategory::kNone, 0, 0));
     }
   };
 
@@ -3633,10 +3807,8 @@
       results.list.push_back(result);
 
       base::ThreadTaskRunnerHandle::Get()->PostTask(
-          FROM_HERE,
-          base::BindOnce(std::move(update_check_callback),
-                         base::make_optional<ProtocolParser::Results>(results),
-                         ErrorCategory::kNone, 0, 0));
+          FROM_HERE, base::BindOnce(std::move(update_check_callback), results,
+                                    ErrorCategory::kNone, 0, 0));
     }
   };
 
diff --git a/components/update_client/update_engine.cc b/components/update_client/update_engine.cc
index 3d4d2285..3c33429 100644
--- a/components/update_client/update_engine.cc
+++ b/components/update_client/update_engine.cc
@@ -228,12 +228,31 @@
     DCHECK_EQ(1u, update_context->components.count(id));
     auto& component = update_context->components.at(id);
     const auto& it = id_to_result.find(id);
-    if (it != id_to_result.end())
-      component->SetUpdateCheckResult(it->second, ErrorCategory::kNone, 0);
-    else
+    if (it != id_to_result.end()) {
+      const auto result = it->second;
+      const auto error = [](const std::string& status) {
+        // First, handle app status literals which can be folded down as an
+        // updatecheck status
+        if (status == "error-unknownApplication")
+          return std::make_pair(ErrorCategory::kUpdateCheck,
+                                ProtocolError::UNKNOWN_APPLICATION);
+        if (status == "restricted")
+          return std::make_pair(ErrorCategory::kUpdateCheck,
+                                ProtocolError::RESTRICTED_APPLICATION);
+        if (status == "error-invalidAppId")
+          return std::make_pair(ErrorCategory::kUpdateCheck,
+                                ProtocolError::INVALID_APPID);
+        // If the parser has return a valid result and the status is not one of
+        // the literals above, then this must be a success an not a parse error.
+        return std::make_pair(ErrorCategory::kNone, ProtocolError::NONE);
+      }(result.status);
+      component->SetUpdateCheckResult(result, error.first,
+                                      static_cast<int>(error.second));
+    } else {
       component->SetUpdateCheckResult(
           base::nullopt, ErrorCategory::kUpdateCheck,
           static_cast<int>(ProtocolError::UPDATE_RESPONSE_NOT_FOUND));
+    }
   }
 }
 
diff --git a/components/url_formatter/idn_spoof_checker.cc b/components/url_formatter/idn_spoof_checker.cc
index ce8ba7c..a3ec302 100644
--- a/components/url_formatter/idn_spoof_checker.cc
+++ b/components/url_formatter/idn_spoof_checker.cc
@@ -180,7 +180,7 @@
   //   - {U+050D (ԍ), U+100c (ဌ)} => g
   //   - {U+0D1F (ട), U+0E23 (ร), U+0EA3 (ຣ), U+0EAE (ຮ)} => s
   //   - U+1042 (၂) => j
-  //   - {U+0437 (з), U+0499 (ҙ), U+04E1 (ӡ)} => 3
+  //   - {U+0437 (з), U+0499 (ҙ), U+04E1 (ӡ), U+10D5 (ვ), U+1012 (ဒ)} => 3
   //   - {U+0E1A (บ), U+0E9A (ບ)} => u
   extra_confusable_mapper_.reset(icu::Transliterator::createFromRules(
       UNICODE_STRING_SIMPLE("ExtraConf"),
@@ -191,7 +191,7 @@
           "[мӎ] > m; [єҽҿၔ] > e; ґ > r; [ғӻ] > f;"
           "[ҫင] > c; ұ > y; [χҳӽӿ] > x;"
           "ԃ  > d; [ԍဌ] > g; [ടรຣຮ] > s; ၂ > j;"
-          "[зҙӡ] > 3; [บບ] > u"),
+          "[зҙӡვဒ] > 3; [บບ] > u"),
       UTRANS_FORWARD, parse_error, status));
   DCHECK(U_SUCCESS(status))
       << "Spoofchecker initalization failed due to an error: "
diff --git a/components/url_formatter/url_formatter_unittest.cc b/components/url_formatter/url_formatter_unittest.cc
index 87f14ec7..1b41d4ef3 100644
--- a/components/url_formatter/url_formatter_unittest.cc
+++ b/components/url_formatter/url_formatter_unittest.cc
@@ -449,7 +449,10 @@
     // phĸtb.com
     {"xn--phtb-m0a.com", L"ph\x0138tb.com", false},
     // phkŧb.com
-    {"xn--phkb-d7a.com", L"phk\x0167" L"b.com", false},
+    {"xn--phkb-d7a.com",
+     L"phk\x0167"
+     L"b.com",
+     false},
     // phktƅ.com
     {"xn--phkt-ocb.com", L"phkt\x0185.com", false},
     // ҏнкть.com
@@ -522,37 +525,82 @@
     {"xn--s5a8h3a.com", L"\x04cf\x050d\x0503.com", false},
 
     // ꓲ2345б7890.com
-    {"xn--23457890-e7g93622b.com", L"\xa4f2" L"2345\x0431" L"7890.com", false},
+    {"xn--23457890-e7g93622b.com",
+     L"\xa4f2"
+     L"2345\x0431"
+     L"7890.com",
+     false},
     // 1ᒿ345б7890.com
-    {"xn--13457890-e7g0943b.com", L"1\x14bf" L"345\x0431" L"7890.com", false},
+    {"xn--13457890-e7g0943b.com",
+     L"1\x14bf"
+     L"345\x0431"
+     L"7890.com",
+     false},
     // 12з4567890.com
-    {"xn--124567890-10h.com", L"12\x0437" L"4567890.com", false},
+    {"xn--124567890-10h.com",
+     L"12\x0437"
+     L"4567890.com",
+     false},
     // 12ҙ4567890.com
-    {"xn--124567890-1ti.com", L"12\x0499" L"4567890.com", false},
+    {"xn--124567890-1ti.com",
+     L"12\x0499"
+     L"4567890.com",
+     false},
     // 12ӡ4567890.com
-    {"xn--124567890-mfj.com", L"12\x04e1" L"4567890.com", false},
+    {"xn--124567890-mfj.com",
+     L"12\x04e1"
+     L"4567890.com",
+     false},
+    // 12ვ4567890.com
+    {"xn--124567890-we8a.com",
+     L"12\x10D5"
+     L"4567890.com",
+     false},
+    // 12ဒ4567890.com
+    {"xn--124567890-6s6a.com",
+     L"12\x1012"
+     L"4567890.com",
+     false},
     // 123Ꮞ567890.com
-    {"xn--123567890-dm4b.com", L"123\x13ce" L"567890.com", false},
+    {"xn--123567890-dm4b.com",
+     L"123\x13ce"
+     L"567890.com",
+     false},
     // 12345б7890.com
-    {"xn--123457890-fzh.com", L"12345\x0431" L"7890.com", false},
+    {"xn--123457890-fzh.com",
+     L"12345\x0431"
+     L"7890.com",
+     false},
     // 1234567ȣ90.com
-    {"xn--123456790-6od.com", L"1234567\x0223" L"90.com", false},
+    {"xn--123456790-6od.com",
+     L"1234567\x0223"
+     L"90.com",
+     false},
     // 12345678୨0.com
-    {"xn--123456780-71w.com", L"12345678\x0b68" L"0.com", false},
+    {"xn--123456780-71w.com",
+     L"12345678\x0b68"
+     L"0.com",
+     false},
     // 123456789ꓳ.com
     {"xn--123456789-tx75a.com", L"123456789\xa4f3.com", false},
 
     // aeœ.com
     {"xn--ae-fsa.com", L"ae\x0153.com", false},
     // æce.com
-    {"xn--ce-0ia.com", L"\x00e6" L"ce.com", false},
+    {"xn--ce-0ia.com",
+     L"\x00e6"
+     L"ce.com",
+     false},
     // æœ.com
     {"xn--6ca2t.com", L"\x00e6\x0153.com", false},
     // ӕԥ.com
     {"xn--y5a4n.com", L"\x04d5\x0525.com", false},
 
     // ငၔဌ၂ဝ.com (entirely made of Myanmar characters)
-    {"xn--ridq5c9hnd.com", L"\x1004\x1054\x100c" L"\x1042\x101d.com", false},
+    {"xn--ridq5c9hnd.com",
+     L"\x1004\x1054\x100c"
+     L"\x1042\x101d.com",
+     false},
 
     // ฟรฟร.com (made of two Thai characters. similar to wsws.com in
     // some fonts)
@@ -570,7 +618,10 @@
     // ຟຮບ.com
     {"xn--f7cj9b.com", L"\x0e9f\x0eae\x0e9a.com", false},
     // ຟຮ໐ບ.com
-    {"xn--f7cj9b5h.com", L"\x0e9f\x0eae" L"\x0ed0\x0e9a.com", false},
+    {"xn--f7cj9b5h.com",
+     L"\x0e9f\x0eae"
+     L"\x0ed0\x0e9a.com",
+     false},
 
     // At one point the skeleton of 'w' was 'vv', ensure that
     // that it's treated as 'w'.
diff --git a/components/viz/host/server_gpu_memory_buffer_manager_unittest.cc b/components/viz/host/server_gpu_memory_buffer_manager_unittest.cc
index 9d3479b..0b0731b 100644
--- a/components/viz/host/server_gpu_memory_buffer_manager_unittest.cc
+++ b/components/viz/host/server_gpu_memory_buffer_manager_unittest.cc
@@ -129,6 +129,12 @@
 
   void OnForegrounded() override {}
 
+#if defined(OS_MACOSX)
+  void BeginCATransaction() override {}
+
+  void CommitCATransaction(CommitCATransactionCallback callback) override {}
+#endif
+
   void Crash() override {}
 
   void Hang() override {}
diff --git a/components/viz/service/gl/gpu_service_impl.cc b/components/viz/service/gl/gpu_service_impl.cc
index 16a82a3..e2fee32 100644
--- a/components/viz/service/gl/gpu_service_impl.cc
+++ b/components/viz/service/gl/gpu_service_impl.cc
@@ -72,6 +72,10 @@
 #include "gpu/ipc/service/direct_composition_surface_win.h"
 #endif
 
+#if defined(OS_MACOSX)
+#include "ui/base/cocoa/quartz_util.h"
+#endif
+
 namespace viz {
 
 namespace {
@@ -91,14 +95,16 @@
 
 // Returns a callback which does a PostTask to run |callback| on the |runner|
 // task runner.
-template <typename Param>
-base::OnceCallback<void(const Param&)> WrapCallback(
+template <typename... Params>
+base::OnceCallback<void(Params&&...)> WrapCallback(
     scoped_refptr<base::SingleThreadTaskRunner> runner,
-    base::OnceCallback<void(const Param&)> callback) {
+    base::OnceCallback<void(Params...)> callback) {
   return base::BindOnce(
       [](base::SingleThreadTaskRunner* runner,
-         base::OnceCallback<void(const Param&)> callback, const Param& param) {
-        runner->PostTask(FROM_HERE, base::BindOnce(std::move(callback), param));
+         base::OnceCallback<void(Params && ...)> callback, Params&&... params) {
+        runner->PostTask(FROM_HERE,
+                         base::BindOnce(std::move(callback),
+                                        std::forward<Params>(params)...));
       },
       base::RetainedRef(std::move(runner)), std::move(callback));
 }
@@ -765,6 +771,20 @@
     watchdog_thread_->OnForegrounded();
 }
 
+#if defined(OS_MACOSX)
+void GpuServiceImpl::BeginCATransaction() {
+  DCHECK(io_runner_->BelongsToCurrentThread());
+  main_runner_->PostTask(FROM_HERE, base::BindOnce(&ui::BeginCATransaction));
+}
+
+void GpuServiceImpl::CommitCATransaction(CommitCATransactionCallback callback) {
+  DCHECK(io_runner_->BelongsToCurrentThread());
+  main_runner_->PostTaskAndReply(FROM_HERE,
+                                 base::BindOnce(&ui::CommitCATransaction),
+                                 WrapCallback(io_runner_, std::move(callback)));
+}
+#endif
+
 void GpuServiceImpl::Crash() {
   DCHECK(io_runner_->BelongsToCurrentThread());
   DVLOG(1) << "GPU: Simulating GPU crash";
diff --git a/components/viz/service/gl/gpu_service_impl.h b/components/viz/service/gl/gpu_service_impl.h
index 3db0035..74d085a 100644
--- a/components/viz/service/gl/gpu_service_impl.h
+++ b/components/viz/service/gl/gpu_service_impl.h
@@ -208,6 +208,10 @@
   void OnBackgroundCleanup() override;
   void OnBackgrounded() override;
   void OnForegrounded() override;
+#if defined(OS_MACOSX)
+  void BeginCATransaction() override;
+  void CommitCATransaction(CommitCATransactionCallback callback) override;
+#endif
   void Crash() override;
   void Hang() override;
   void ThrowJavaException() override;
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index 1a7ccf61..2921499 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -84,6 +84,7 @@
     "//content/common:mojo_bindings",
     "//content/public/common:common_sources",
     "//crypto",
+    "//device/base",
     "//device/bluetooth",
     "//device/fido",
     "//device/gamepad",
@@ -1846,6 +1847,13 @@
     deps += [ "//printing" ]
   }
 
+  if (is_mac) {
+    sources += [
+      "gpu/ca_transaction_gpu_coordinator.cc",
+      "gpu/ca_transaction_gpu_coordinator.h",
+    ]
+  }
+
   if (!is_mac) {
     deps += [ "//sandbox" ]
   }
diff --git a/content/browser/background_fetch/background_fetch_data_manager.cc b/content/browser/background_fetch/background_fetch_data_manager.cc
index 2ad72a5..09d665fe 100644
--- a/content/browser/background_fetch/background_fetch_data_manager.cc
+++ b/content/browser/background_fetch/background_fetch_data_manager.cc
@@ -31,8 +31,6 @@
 #include "content/browser/storage_partition_impl.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/browser_thread.h"
-#include "content/public/common/content_features.h"
-#include "content/public/common/content_switches.h"
 #include "storage/browser/blob/blob_data_builder.h"
 #include "storage/browser/blob/blob_impl.h"
 #include "storage/browser/blob/blob_storage_context.h"
@@ -76,102 +74,6 @@
 
 }  // namespace
 
-// The Registration Data class encapsulates the data stored for a particular
-// Background Fetch registration. This roughly matches the on-disk format that
-// will be adhered to in the future.
-class BackgroundFetchDataManager::RegistrationData {
- public:
-  RegistrationData(const BackgroundFetchRegistrationId& registration_id,
-                   const std::vector<ServiceWorkerFetchRequest>& requests,
-                   const BackgroundFetchOptions& options,
-                   const SkBitmap& icon)
-      : registration_id_(registration_id), options_(options), icon_(icon) {
-    int request_index = 0;
-
-    // Convert the given |requests| to BackgroundFetchRequestInfo objects.
-    for (const ServiceWorkerFetchRequest& fetch_request : requests) {
-      pending_requests_.push(base::MakeRefCounted<BackgroundFetchRequestInfo>(
-          request_index++, fetch_request));
-    }
-  }
-
-  ~RegistrationData() = default;
-
-  // Returns whether there are remaining requests on the request queue.
-  bool HasPendingRequests() const { return !pending_requests_.empty(); }
-
-  // Consumes a request from the queue that is to be fetched.
-  scoped_refptr<BackgroundFetchRequestInfo> PopNextPendingRequest() {
-    DCHECK(!pending_requests_.empty());
-
-    auto request = pending_requests_.front();
-    pending_requests_.pop();
-
-    request->InitializeDownloadGuid();
-
-    // The |request| is considered to be active now.
-    active_requests_.push_back(request);
-
-    return request;
-  }
-
-  // Marks the |request| as having completed. Verifies that the |request| is
-  // currently active and moves it to the |completed_requests_| vector.
-  void MarkRequestAsComplete(BackgroundFetchRequestInfo* request) {
-    const auto iter = std::find_if(
-        active_requests_.begin(), active_requests_.end(),
-        [&request](scoped_refptr<BackgroundFetchRequestInfo> active_request) {
-          return active_request->request_index() == request->request_index();
-        });
-
-    // The |request| must have been consumed from this RegistrationData.
-    DCHECK(iter != active_requests_.end());
-
-    completed_requests_.push_back(*iter);
-    active_requests_.erase(iter);
-
-    complete_requests_downloaded_bytes_ += request->GetFileSize();
-  }
-
-  // Returns the vector with all completed requests part of this registration.
-  const std::vector<scoped_refptr<BackgroundFetchRequestInfo>>&
-  GetCompletedRequests() const {
-    return completed_requests_;
-  }
-
-  void SetTitle(const std::string& title) { options_.title = title; }
-
-  const BackgroundFetchRegistrationId& registration_id() const {
-    return registration_id_;
-  }
-
-  const BackgroundFetchOptions& options() const { return options_; }
-
-  uint64_t GetDownloaded() const { return complete_requests_downloaded_bytes_; }
-
-  size_t GetNumCompletedRequests() const { return completed_requests_.size(); }
-
- private:
-  BackgroundFetchRegistrationId registration_id_;
-  BackgroundFetchOptions options_;
-  SkBitmap icon_;
-  // Number of bytes downloaded as part of completed downloads. (In-progress
-  // downloads are tracked elsewhere).
-  uint64_t complete_requests_downloaded_bytes_ = 0;
-
-  base::queue<scoped_refptr<BackgroundFetchRequestInfo>> pending_requests_;
-  std::vector<scoped_refptr<BackgroundFetchRequestInfo>> active_requests_;
-
-  // TODO(peter): Right now it's safe for this to be a vector because we only
-  // allow a single parallel request. That stops when we start allowing more.
-  static_assert(kMaximumBackgroundFetchParallelRequests == 1,
-                "RegistrationData::completed_requests_ assumes no parallelism");
-
-  std::vector<scoped_refptr<BackgroundFetchRequestInfo>> completed_requests_;
-
-  DISALLOW_COPY_AND_ASSIGN(RegistrationData);
-};
-
 BackgroundFetchDataManager::BackgroundFetchDataManager(
     BrowserContext* browser_context,
     scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
@@ -197,11 +99,8 @@
 }
 
 void BackgroundFetchDataManager::Cleanup() {
-  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kEnableBackgroundFetchPersistence)) {
-    AddDatabaseTask(std::make_unique<background_fetch::CleanupTask>(
-        this, GetCacheStorageManager()));
-  }
+  AddDatabaseTask(std::make_unique<background_fetch::CleanupTask>(
+      this, GetCacheStorageManager()));
 }
 
 BackgroundFetchDataManager::~BackgroundFetchDataManager() {
@@ -216,47 +115,11 @@
     GetRegistrationCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
-  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kEnableBackgroundFetchPersistence)) {
-    auto registration_callback =
-        base::BindOnce(&GetRegistrationFromMetadata, std::move(callback));
-    AddDatabaseTask(std::make_unique<background_fetch::CreateMetadataTask>(
-        this, registration_id, requests, options,
-        std::move(registration_callback)));
-    return;
-  }
-
-  // New registrations should never re-use a |unique_id|.
-  DCHECK_EQ(0u, registrations_.count(registration_id.unique_id()));
-
-  auto developer_id_tuple =
-      std::make_tuple(registration_id.service_worker_registration_id(),
-                      registration_id.origin(), registration_id.developer_id());
-
-  if (active_registration_unique_ids_.count(developer_id_tuple)) {
-    std::move(callback).Run(
-        blink::mojom::BackgroundFetchError::DUPLICATED_DEVELOPER_ID, nullptr);
-    return;
-  }
-
-  // Mark |unique_id| as the currently active registration for
-  // |developer_id_tuple|.
-  active_registration_unique_ids_.emplace(std::move(developer_id_tuple),
-                                          registration_id.unique_id());
-
-  // Create the |RegistrationData|, and store it for easy access.
-  registrations_.emplace(registration_id.unique_id(),
-                         std::make_unique<RegistrationData>(
-                             registration_id, requests, options, icon));
-
-  // Re-use GetRegistration to compile the BackgroundFetchRegistration object.
-  // WARNING: GetRegistration doesn't use the |unique_id| when looking up the
-  // registration data. That's fine here, since we are calling it synchronously
-  // immediately after writing the |unique_id| to |active_unique_ids_|. But if
-  // GetRegistation becomes async, it will no longer be safe to do this.
-  GetRegistration(registration_id.service_worker_registration_id(),
-                  registration_id.origin(), registration_id.developer_id(),
-                  std::move(callback));
+  auto registration_callback =
+      base::BindOnce(&GetRegistrationFromMetadata, std::move(callback));
+  AddDatabaseTask(std::make_unique<background_fetch::CreateMetadataTask>(
+      this, registration_id, requests, options,
+      std::move(registration_callback)));
 }
 
 void BackgroundFetchDataManager::GetMetadata(
@@ -265,10 +128,7 @@
     const std::string& developer_id,
     GetMetadataCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
-  if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kEnableBackgroundFetchPersistence)) {
-    return;
-  }
+
   AddDatabaseTask(std::make_unique<background_fetch::GetMetadataTask>(
       this, service_worker_registration_id, origin, developer_id,
       std::move(callback)));
@@ -281,42 +141,10 @@
     GetRegistrationCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
-  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kEnableBackgroundFetchPersistence)) {
-    auto registration_callback =
-        base::BindOnce(&GetRegistrationFromMetadata, std::move(callback));
-    GetMetadata(service_worker_registration_id, origin, developer_id,
-                std::move(registration_callback));
-    return;
-  }
-
-  auto developer_id_tuple =
-      std::make_tuple(service_worker_registration_id, origin, developer_id);
-
-  auto iter = active_registration_unique_ids_.find(developer_id_tuple);
-  if (iter == active_registration_unique_ids_.end()) {
-    std::move(callback).Run(blink::mojom::BackgroundFetchError::INVALID_ID,
-                            nullptr /* registration */);
-    return;
-  }
-
-  const std::string& unique_id = iter->second;
-
-  DCHECK_EQ(1u, registrations_.count(unique_id));
-  RegistrationData* data = registrations_[unique_id].get();
-
-  // Compile the BackgroundFetchRegistration object for the developer.
-  auto registration = std::make_unique<BackgroundFetchRegistration>();
-  registration->developer_id = developer_id;
-  registration->unique_id = unique_id;
-  // TODO(crbug.com/774054): Uploads are not yet supported.
-  registration->upload_total = 0;
-  registration->uploaded = 0;
-  registration->download_total = data->options().download_total;
-  registration->downloaded = data->GetDownloaded();
-
-  std::move(callback).Run(blink::mojom::BackgroundFetchError::NONE,
-                          std::move(registration));
+  auto registration_callback =
+      base::BindOnce(&GetRegistrationFromMetadata, std::move(callback));
+  GetMetadata(service_worker_registration_id, origin, developer_id,
+              std::move(registration_callback));
 }
 
 void BackgroundFetchDataManager::UpdateRegistrationUI(
@@ -325,24 +153,8 @@
     blink::mojom::BackgroundFetchService::UpdateUICallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
-  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kEnableBackgroundFetchPersistence)) {
-    AddDatabaseTask(
-        std::make_unique<background_fetch::UpdateRegistrationUITask>(
-            this, registration_id, title, std::move(callback)));
-    return;
-  }
-
-  auto registrations_iter = registrations_.find(registration_id.unique_id());
-  if (registrations_iter == registrations_.end()) {  // Not found.
-    std::move(callback).Run(blink::mojom::BackgroundFetchError::INVALID_ID);
-    return;
-  }
-
-  // Update stored registration.
-  registrations_iter->second->SetTitle(title);
-
-  std::move(callback).Run(blink::mojom::BackgroundFetchError::NONE);
+  AddDatabaseTask(std::make_unique<background_fetch::UpdateRegistrationUITask>(
+      this, registration_id, title, std::move(callback)));
 }
 
 void BackgroundFetchDataManager::PopNextRequest(
@@ -350,38 +162,15 @@
     NextRequestCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
-  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kEnableBackgroundFetchPersistence)) {
-    auto start_next_request = base::BindOnce(
-        &BackgroundFetchDataManager::AddStartNextPendingRequestTask,
-        weak_ptr_factory_.GetWeakPtr(),
-        registration_id.service_worker_registration_id(), std::move(callback));
+  auto start_next_request = base::BindOnce(
+      &BackgroundFetchDataManager::AddStartNextPendingRequestTask,
+      weak_ptr_factory_.GetWeakPtr(),
+      registration_id.service_worker_registration_id(), std::move(callback));
 
-    // Get the associated metadata, and add a StartNextPendingRequestTask.
-    GetMetadata(registration_id.service_worker_registration_id(),
-                registration_id.origin(), registration_id.developer_id(),
-                std::move(start_next_request));
-
-    return;
-  }
-
-  if (!IsActive(registration_id)) {
-    // Stop giving out requests as registration was aborted (or otherwise
-    // finished).
-    std::move(callback).Run(nullptr /* request */);
-    return;
-  }
-
-  auto registration_iter = registrations_.find(registration_id.unique_id());
-  DCHECK(registration_iter != registrations_.end());
-
-  RegistrationData* registration_data = registration_iter->second.get();
-
-  scoped_refptr<BackgroundFetchRequestInfo> next_request;
-  if (registration_data->HasPendingRequests())
-    next_request = registration_data->PopNextPendingRequest();
-
-  std::move(callback).Run(std::move(next_request));
+  // Get the associated metadata, and add a StartNextPendingRequestTask.
+  GetMetadata(registration_id.service_worker_registration_id(),
+              registration_id.origin(), registration_id.developer_id(),
+              std::move(start_next_request));
 }
 
 void BackgroundFetchDataManager::AddStartNextPendingRequestTask(
@@ -408,21 +197,9 @@
     BackgroundFetchScheduler::MarkedCompleteCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
-  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kEnableBackgroundFetchPersistence)) {
-    AddDatabaseTask(std::make_unique<background_fetch::MarkRequestCompleteTask>(
-        this, registration_id, request, GetCacheStorageManager(),
-        std::move(callback)));
-    return;
-  }
-
-  auto iter = registrations_.find(registration_id.unique_id());
-  DCHECK(iter != registrations_.end());
-
-  RegistrationData* registration_data = iter->second.get();
-  registration_data->MarkRequestAsComplete(request);
-
-  std::move(callback).Run();
+  AddDatabaseTask(std::make_unique<background_fetch::MarkRequestCompleteTask>(
+      this, registration_id, request, GetCacheStorageManager(),
+      std::move(callback)));
 }
 
 void BackgroundFetchDataManager::GetSettledFetchesForRegistration(
@@ -430,46 +207,8 @@
     SettledFetchesCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
-  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kEnableBackgroundFetchPersistence)) {
-    AddDatabaseTask(std::make_unique<background_fetch::GetSettledFetchesTask>(
-        this, registration_id, GetCacheStorageManager(), std::move(callback)));
-    return;
-  }
-
-  auto iter = registrations_.find(registration_id.unique_id());
-  DCHECK(iter != registrations_.end());
-
-  RegistrationData* registration_data = iter->second.get();
-
-  const std::vector<scoped_refptr<BackgroundFetchRequestInfo>>& requests =
-      registration_data->GetCompletedRequests();
-
-  bool background_fetch_succeeded = true;
-
-  std::vector<BackgroundFetchSettledFetch> settled_fetches;
-  settled_fetches.reserve(requests.size());
-
-  std::vector<std::unique_ptr<storage::BlobDataHandle>> blob_data_handles;
-
-  for (const auto& request : requests) {
-    BackgroundFetchSettledFetch settled_fetch;
-    settled_fetch.request = request->fetch_request();
-
-    // The |filter| decides which values can be passed on to the Service Worker.
-    BackgroundFetchCrossOriginFilter filter(registration_id.origin(), *request);
-
-    background_fetch_succeeded =
-        FillServiceWorkerResponse(*request, registration_id.origin(),
-                                  &settled_fetch.response) &&
-        background_fetch_succeeded;
-
-    settled_fetches.push_back(settled_fetch);
-  }
-
-  std::move(callback).Run(
-      blink::mojom::BackgroundFetchError::NONE, background_fetch_succeeded,
-      std::move(settled_fetches), std::move(blob_data_handles));
+  AddDatabaseTask(std::make_unique<background_fetch::GetSettledFetchesTask>(
+      this, registration_id, GetCacheStorageManager(), std::move(callback)));
 }
 
 bool BackgroundFetchDataManager::FillServiceWorkerResponse(
@@ -533,54 +272,20 @@
     HandleBackgroundFetchErrorCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
-  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kEnableBackgroundFetchPersistence)) {
-    AddDatabaseTask(
-        std::make_unique<background_fetch::MarkRegistrationForDeletionTask>(
-            this, registration_id, std::move(callback)));
-    return;
-  }
-
-  auto developer_id_tuple =
-      std::make_tuple(registration_id.service_worker_registration_id(),
-                      registration_id.origin(), registration_id.developer_id());
-
-  auto active_unique_id_iter =
-      active_registration_unique_ids_.find(developer_id_tuple);
-
-  // The |unique_id| must also match, as a website can create multiple
-  // registrations with the same |developer_id_tuple| (even though only one can
-  // be active at once).
-  if (active_unique_id_iter == active_registration_unique_ids_.end() ||
-      active_unique_id_iter->second != registration_id.unique_id()) {
-    std::move(callback).Run(blink::mojom::BackgroundFetchError::INVALID_ID);
-    return;
-  }
-
-  active_registration_unique_ids_.erase(active_unique_id_iter);
-
-  std::move(callback).Run(blink::mojom::BackgroundFetchError::NONE);
+  AddDatabaseTask(
+      std::make_unique<background_fetch::MarkRegistrationForDeletionTask>(
+          this, registration_id, std::move(callback)));
 }
 
 void BackgroundFetchDataManager::DeleteRegistration(
     const BackgroundFetchRegistrationId& registration_id,
     HandleBackgroundFetchErrorCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
-  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kEnableBackgroundFetchPersistence)) {
-    AddDatabaseTask(std::make_unique<background_fetch::DeleteRegistrationTask>(
-        this, registration_id.service_worker_registration_id(),
-        registration_id.origin(), registration_id.unique_id(),
-        GetCacheStorageManager(), std::move(callback)));
-    return;
-  }
 
-  DCHECK(!IsActive(registration_id))
-      << "MarkRegistrationForDeletion must already have been called";
-
-  std::move(callback).Run(registrations_.erase(registration_id.unique_id())
-                              ? blink::mojom::BackgroundFetchError::NONE
-                              : blink::mojom::BackgroundFetchError::INVALID_ID);
+  AddDatabaseTask(std::make_unique<background_fetch::DeleteRegistrationTask>(
+      this, registration_id.service_worker_registration_id(),
+      registration_id.origin(), registration_id.unique_id(),
+      GetCacheStorageManager(), std::move(callback)));
 }
 
 void BackgroundFetchDataManager::GetDeveloperIdsForServiceWorker(
@@ -589,23 +294,8 @@
     blink::mojom::BackgroundFetchService::GetDeveloperIdsCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
-  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kEnableBackgroundFetchPersistence)) {
-    AddDatabaseTask(std::make_unique<background_fetch::GetDeveloperIdsTask>(
-        this, service_worker_registration_id, origin, std::move(callback)));
-    return;
-  }
-
-  std::vector<std::string> developer_ids;
-  for (const auto& entry : active_registration_unique_ids_) {
-    if (service_worker_registration_id == std::get<0>(entry.first) &&
-        origin == std::get<1>(entry.first)) {
-      developer_ids.emplace_back(std::get<2>(entry.first));
-    }
-  }
-
-  std::move(callback).Run(blink::mojom::BackgroundFetchError::NONE,
-                          developer_ids);
+  AddDatabaseTask(std::make_unique<background_fetch::GetDeveloperIdsTask>(
+      this, service_worker_registration_id, origin, std::move(callback)));
 }
 
 void BackgroundFetchDataManager::GetNumCompletedRequests(
@@ -613,16 +303,9 @@
     NumRequestsCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
-  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kEnableBackgroundFetchPersistence)) {
-    AddDatabaseTask(std::make_unique<background_fetch::GetNumRequestsTask>(
-        this, registration_id, background_fetch::RequestType::kCompleted,
-        std::move(callback)));
-    return;
-  }
-
-  std::move(callback).Run(registrations_.find(registration_id.unique_id())
-                              ->second->GetNumCompletedRequests());
+  AddDatabaseTask(std::make_unique<background_fetch::GetNumRequestsTask>(
+      this, registration_id, background_fetch::RequestType::kCompleted,
+      std::move(callback)));
 }
 
 CacheStorageManager* BackgroundFetchDataManager::GetCacheStorageManager() {
@@ -634,22 +317,6 @@
   return manager;
 }
 
-bool BackgroundFetchDataManager::IsActive(
-    const BackgroundFetchRegistrationId& registration_id) {
-  auto developer_id_tuple =
-      std::make_tuple(registration_id.service_worker_registration_id(),
-                      registration_id.origin(), registration_id.developer_id());
-
-  auto active_unique_id_iter =
-      active_registration_unique_ids_.find(developer_id_tuple);
-
-  // The |unique_id| must also match, as a website can create multiple
-  // registrations with the same |developer_id_tuple| (even though only one can
-  // be active at once).
-  return active_unique_id_iter != active_registration_unique_ids_.end() &&
-         active_unique_id_iter->second == registration_id.unique_id();
-}
-
 void BackgroundFetchDataManager::AddDatabaseTask(
     std::unique_ptr<background_fetch::DatabaseTask> task) {
   database_tasks_.push(std::move(task));
diff --git a/content/browser/background_fetch/background_fetch_data_manager.h b/content/browser/background_fetch/background_fetch_data_manager.h
index 7515625..4772c09 100644
--- a/content/browser/background_fetch/background_fetch_data_manager.h
+++ b/content/browser/background_fetch/background_fetch_data_manager.h
@@ -165,8 +165,6 @@
   friend class BackgroundFetchTestDataManager;
   friend class background_fetch::DatabaseTask;
 
-  class RegistrationData;
-
   void AddStartNextPendingRequestTask(
       int64_t service_worker_registration_id,
       NextRequestCallback callback,
@@ -180,9 +178,6 @@
   // Virtual for testing.
   virtual CacheStorageManager* GetCacheStorageManager();
 
-  // Returns true if not aborted/completed/failed.
-  bool IsActive(const BackgroundFetchRegistrationId& registration_id);
-
   void Cleanup();
 
   scoped_refptr<ServiceWorkerContextWrapper> service_worker_context_;
@@ -192,17 +187,6 @@
   // The blob storage request with which response information will be stored.
   scoped_refptr<ChromeBlobStorageContext> blob_storage_context_;
 
-  // Map from {service_worker_registration_id, origin, developer_id} tuples to
-  // the |unique_id|s of active background fetch registrations (not
-  // completed/failed/aborted, so there will never be more than one entry for a
-  // given key).
-  std::map<std::tuple<int64_t, url::Origin, std::string>, std::string>
-      active_registration_unique_ids_;
-
-  // Map from the |unique_id|s of known (but possibly inactive) background fetch
-  // registrations to their associated data.
-  std::map<std::string, std::unique_ptr<RegistrationData>> registrations_;
-
   // Pending database operations, serialized to ensure consistency.
   // Invariant: the frontmost task, if any, has already been started.
   base::queue<std::unique_ptr<background_fetch::DatabaseTask>> database_tasks_;
diff --git a/content/browser/background_fetch/background_fetch_data_manager_unittest.cc b/content/browser/background_fetch/background_fetch_data_manager_unittest.cc
index 8e18c637..ca76793 100644
--- a/content/browser/background_fetch/background_fetch_data_manager_unittest.cc
+++ b/content/browser/background_fetch/background_fetch_data_manager_unittest.cc
@@ -25,7 +25,6 @@
 #include "content/public/browser/background_fetch_response.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/storage_partition.h"
-#include "content/public/common/content_switches.h"
 #include "storage/browser/blob/blob_data_handle.h"
 #include "testing/gmock/include/gmock/gmock.h"
 
@@ -35,8 +34,6 @@
 using ::testing::UnorderedElementsAre;
 using ::testing::IsEmpty;
 
-enum class BackgroundFetchRegistrationStorage { kPersistent, kNonPersistent };
-
 const char kUserDataPrefix[] = "bgfetch_";
 
 const char kExampleDeveloperId[] = "my-example-id";
@@ -115,32 +112,16 @@
 
 }  // namespace
 
-class BackgroundFetchDataManagerTest
-    : public BackgroundFetchTestBase,
-      public ::testing::WithParamInterface<BackgroundFetchRegistrationStorage> {
+class BackgroundFetchDataManagerTest : public BackgroundFetchTestBase {
  public:
   BackgroundFetchDataManagerTest() {
-    registration_storage_ = GetParam();
-    if (registration_storage_ ==
-        BackgroundFetchRegistrationStorage::kPersistent) {
-      base::CommandLine::ForCurrentProcess()->AppendSwitch(
-          switches::kEnableBackgroundFetchPersistence);
-    }
     RestartDataManagerFromPersistentStorage();
   }
 
   ~BackgroundFetchDataManagerTest() override = default;
 
   // Re-creates the data manager. Useful for testing that data was persisted.
-  // If the test is non-persistent mode (e.g. testing the old code path), then
-  // this does nothing after the first call.
   void RestartDataManagerFromPersistentStorage() {
-    if (registration_storage_ ==
-            BackgroundFetchRegistrationStorage::kNonPersistent &&
-        background_fetch_data_manager_) {
-      return;
-    }
-
     background_fetch_data_manager_ =
         std::make_unique<BackgroundFetchTestDataManager>(
             browser_context(), storage_partition(),
@@ -539,22 +520,11 @@
     std::move(quit_closure).Run();
   }
 
-  BackgroundFetchRegistrationStorage registration_storage_;
   std::unique_ptr<BackgroundFetchTestDataManager>
       background_fetch_data_manager_;
 };
 
-INSTANTIATE_TEST_CASE_P(
-    Persistent,
-    BackgroundFetchDataManagerTest,
-    ::testing::Values(BackgroundFetchRegistrationStorage::kPersistent));
-
-INSTANTIATE_TEST_CASE_P(
-    NonPersistent,
-    BackgroundFetchDataManagerTest,
-    ::testing::Values(BackgroundFetchRegistrationStorage::kNonPersistent));
-
-TEST_P(BackgroundFetchDataManagerTest, NoDuplicateRegistrations) {
+TEST_F(BackgroundFetchDataManagerTest, NoDuplicateRegistrations) {
   // Tests that the BackgroundFetchDataManager correctly rejects creating a
   // registration with a |developer_id| for which there is already an active
   // registration.
@@ -606,7 +576,7 @@
   EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
 }
 
-TEST_P(BackgroundFetchDataManagerTest, GetDeveloperIds) {
+TEST_F(BackgroundFetchDataManagerTest, GetDeveloperIds) {
   int64_t sw_id = RegisterServiceWorker();
   ASSERT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId, sw_id);
 
@@ -657,7 +627,7 @@
                                                   kAlternativeDeveloperId));
 }
 
-TEST_P(BackgroundFetchDataManagerTest, GetRegistration) {
+TEST_F(BackgroundFetchDataManagerTest, GetRegistration) {
   int64_t sw_id = RegisterServiceWorker();
   ASSERT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId, sw_id);
 
@@ -696,12 +666,7 @@
   EXPECT_EQ(kExampleDeveloperId, registration->developer_id);
 }
 
-TEST_P(BackgroundFetchDataManagerTest, GetMetadata) {
-  // This test only applies to persistent storage.
-  if (registration_storage_ ==
-      BackgroundFetchRegistrationStorage::kNonPersistent)
-    return;
-
+TEST_F(BackgroundFetchDataManagerTest, GetMetadata) {
   int64_t sw_id = RegisterServiceWorker();
   ASSERT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId, sw_id);
 
@@ -740,12 +705,7 @@
   EXPECT_EQ(metadata->num_fetches(), static_cast<int>(requests.size()));
 }
 
-TEST_P(BackgroundFetchDataManagerTest, UpdateRegistrationUI) {
-  // This test only applies to persistent storage.
-  if (registration_storage_ ==
-      BackgroundFetchRegistrationStorage::kNonPersistent)
-    return;
-
+TEST_F(BackgroundFetchDataManagerTest, UpdateRegistrationUI) {
   int64_t sw_id = RegisterServiceWorker();
   ASSERT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId, sw_id);
 
@@ -784,7 +744,7 @@
   ASSERT_EQ(title.front(), kUpdatedTitle);
 }
 
-TEST_P(BackgroundFetchDataManagerTest, CreateAndDeleteRegistration) {
+TEST_F(BackgroundFetchDataManagerTest, CreateAndDeleteRegistration) {
   int64_t sw_id = RegisterServiceWorker();
   ASSERT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId, sw_id);
 
@@ -850,12 +810,7 @@
   EXPECT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
 }
 
-TEST_P(BackgroundFetchDataManagerTest, PopNextRequestAndMarkAsComplete) {
-  // This test only applies to persistent storage.
-  if (registration_storage_ ==
-      BackgroundFetchRegistrationStorage::kNonPersistent)
-    return;
-
+TEST_F(BackgroundFetchDataManagerTest, PopNextRequestAndMarkAsComplete) {
   int64_t sw_id = RegisterServiceWorker();
   ASSERT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId, sw_id);
 
@@ -930,12 +885,7 @@
                           2 /* completed_requests */}));
 }
 
-TEST_P(BackgroundFetchDataManagerTest, WriteToCache) {
-  // This test only applies to persistent storage.
-  if (registration_storage_ ==
-      BackgroundFetchRegistrationStorage::kNonPersistent)
-    return;
-
+TEST_F(BackgroundFetchDataManagerTest, WriteToCache) {
   int64_t sw_id = RegisterServiceWorker();
   ASSERT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId, sw_id);
 
@@ -980,12 +930,7 @@
   EXPECT_TRUE(MatchCache(request2));
 }
 
-TEST_P(BackgroundFetchDataManagerTest, CacheDeleted) {
-  // This test only applies to persistent storage.
-  if (registration_storage_ ==
-      BackgroundFetchRegistrationStorage::kNonPersistent)
-    return;
-
+TEST_F(BackgroundFetchDataManagerTest, CacheDeleted) {
   int64_t sw_id = RegisterServiceWorker();
   ASSERT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId, sw_id);
 
@@ -1020,12 +965,7 @@
   EXPECT_FALSE(HasCache(kExampleUniqueId));
 }
 
-TEST_P(BackgroundFetchDataManagerTest, GetSettledFetchesForRegistration) {
-  // This test only applies to persistent storage.
-  if (registration_storage_ ==
-      BackgroundFetchRegistrationStorage::kNonPersistent)
-    return;
-
+TEST_F(BackgroundFetchDataManagerTest, GetSettledFetchesForRegistration) {
   int64_t sw_id = RegisterServiceWorker();
   ASSERT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId, sw_id);
 
@@ -1075,12 +1015,7 @@
   EXPECT_EQ(settled_fetches.size(), requests.size());
 }
 
-TEST_P(BackgroundFetchDataManagerTest, GetSettledFetchesFromCache) {
-  // This test only applies to persistent storage.
-  if (registration_storage_ ==
-      BackgroundFetchRegistrationStorage::kNonPersistent)
-    return;
-
+TEST_F(BackgroundFetchDataManagerTest, GetSettledFetchesFromCache) {
   int64_t sw_id = RegisterServiceWorker();
   ASSERT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId, sw_id);
 
@@ -1147,7 +1082,7 @@
   EXPECT_EQ(settled_fetches.size(), 2u);
 }
 
-TEST_P(BackgroundFetchDataManagerTest, GetNumCompletedRequests) {
+TEST_F(BackgroundFetchDataManagerTest, GetNumCompletedRequests) {
   int64_t sw_id = RegisterServiceWorker();
   ASSERT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId, sw_id);
 
@@ -1191,12 +1126,7 @@
   EXPECT_EQ(num_completed, 2u);
 }
 
-TEST_P(BackgroundFetchDataManagerTest, GetNumRequestsTask) {
-  // This test only applies to persistent storage.
-  if (registration_storage_ ==
-      BackgroundFetchRegistrationStorage::kNonPersistent)
-    return;
-
+TEST_F(BackgroundFetchDataManagerTest, GetNumRequestsTask) {
   int64_t sw_id = RegisterServiceWorker();
   ASSERT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId, sw_id);
 
@@ -1260,13 +1190,9 @@
   EXPECT_EQ(size, 1u);  // Total requests is still 1.
 }
 
-TEST_P(BackgroundFetchDataManagerTest, Cleanup) {
+TEST_F(BackgroundFetchDataManagerTest, Cleanup) {
   // Tests that the BackgroundFetchDataManager cleans up registrations
   // marked for deletion.
-
-  base::CommandLine::ForCurrentProcess()->AppendSwitch(
-      switches::kEnableBackgroundFetchPersistence);
-
   int64_t sw_id = RegisterServiceWorker();
   ASSERT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId, sw_id);
 
@@ -1278,24 +1204,17 @@
   BackgroundFetchOptions options;
   blink::mojom::BackgroundFetchError error;
 
-  if (registration_storage_ ==
-      BackgroundFetchRegistrationStorage::kPersistent) {
-    EXPECT_EQ(
-        0u, GetRegistrationUserDataByKeyPrefix(sw_id, kUserDataPrefix).size());
-  }
-
+  EXPECT_EQ(0u,
+            GetRegistrationUserDataByKeyPrefix(sw_id, kUserDataPrefix).size());
   // Create a registration.
   CreateRegistration(registration_id, requests, options, &error);
   ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
 
-  if (registration_storage_ ==
-      BackgroundFetchRegistrationStorage::kPersistent) {
-    // We expect as many pending entries as there are requests.
-    EXPECT_EQ(requests.size(),
-              GetRegistrationUserDataByKeyPrefix(
-                  sw_id, background_fetch::kPendingRequestKeyPrefix)
-                  .size());
-  }
+  // We expect as many pending entries as there are requests.
+  EXPECT_EQ(requests.size(),
+            GetRegistrationUserDataByKeyPrefix(
+                sw_id, background_fetch::kPendingRequestKeyPrefix)
+                .size());
 
   // And deactivate it.
   MarkRegistrationForDeletion(registration_id, &error);
@@ -1303,45 +1222,31 @@
 
   RestartDataManagerFromPersistentStorage();
 
-  if (registration_storage_ ==
-      BackgroundFetchRegistrationStorage::kPersistent) {
-    // Pending Requests should be deleted after marking a registration for
-    // deletion.
-    EXPECT_EQ(0u, GetRegistrationUserDataByKeyPrefix(
-                      sw_id, background_fetch::kPendingRequestKeyPrefix)
-                      .size());
-    EXPECT_EQ(
-        2u,  // Metadata proto + title.
-        GetRegistrationUserDataByKeyPrefix(sw_id, kUserDataPrefix).size());
-  }
+  // Pending Requests should be deleted after marking a registration for
+  // deletion.
+  EXPECT_EQ(0u, GetRegistrationUserDataByKeyPrefix(
+                    sw_id, background_fetch::kPendingRequestKeyPrefix)
+                    .size());
+  EXPECT_EQ(2u,  // Metadata proto + title.
+            GetRegistrationUserDataByKeyPrefix(sw_id, kUserDataPrefix).size());
 
   // Cleanup should delete the registration.
   background_fetch_data_manager_->Cleanup();
   base::RunLoop().RunUntilIdle();
-  if (registration_storage_ ==
-      BackgroundFetchRegistrationStorage::kPersistent) {
-    EXPECT_EQ(
-        0u, GetRegistrationUserDataByKeyPrefix(sw_id, kUserDataPrefix).size());
-  }
+  EXPECT_EQ(0u,
+            GetRegistrationUserDataByKeyPrefix(sw_id, kUserDataPrefix).size());
 
   RestartDataManagerFromPersistentStorage();
 
   // The deletion should have been persisted.
-  if (registration_storage_ ==
-      BackgroundFetchRegistrationStorage::kPersistent) {
-    EXPECT_EQ(
-        0u, GetRegistrationUserDataByKeyPrefix(sw_id, kUserDataPrefix).size());
-  }
+  EXPECT_EQ(0u,
+            GetRegistrationUserDataByKeyPrefix(sw_id, kUserDataPrefix).size());
 }
 
-TEST_P(BackgroundFetchDataManagerTest, CreateInParallel) {
+TEST_F(BackgroundFetchDataManagerTest, CreateInParallel) {
   // Tests that multiple parallel calls to the BackgroundFetchDataManager are
   // linearized and handled one at a time, rather than producing inconsistent
   // results due to interleaving.
-
-  base::CommandLine::ForCurrentProcess()->AppendSwitch(
-      switches::kEnableBackgroundFetchPersistence);
-
   int64_t service_worker_registration_id = RegisterServiceWorker();
   ASSERT_NE(blink::mojom::kInvalidServiceWorkerRegistrationId,
             service_worker_registration_id);
diff --git a/content/browser/background_fetch/background_fetch_scheduler.cc b/content/browser/background_fetch/background_fetch_scheduler.cc
index 0293f9f..ba39a99d 100644
--- a/content/browser/background_fetch/background_fetch_scheduler.cc
+++ b/content/browser/background_fetch/background_fetch_scheduler.cc
@@ -48,8 +48,8 @@
     BackgroundFetchScheduler::Controller* controller) {
   controller_queue_.push_back(controller);
 
-  while (!controller_queue_.empty() &&
-         download_controller_map_.size() < max_concurrent_downloads_) {
+  if (!controller_queue_.empty() &&
+      download_controller_map_.size() < max_concurrent_downloads_) {
     ScheduleDownload();
   }
 }
@@ -57,12 +57,14 @@
 void BackgroundFetchScheduler::ScheduleDownload() {
   DCHECK(download_controller_map_.size() < max_concurrent_downloads_);
 
-  if (controller_queue_.empty())
+  if (lock_scheduler_ || controller_queue_.empty())
     return;
 
   auto* controller = controller_queue_.front();
   controller_queue_.pop_front();
 
+  // Making an async call, `ScheduleDownload` shouldn't be called anymore.
+  lock_scheduler_ = true;
   request_provider_->PopNextRequest(
       controller->registration_id(),
       base::BindOnce(&BackgroundFetchScheduler::DidPopNextRequest,
@@ -73,10 +75,19 @@
     BackgroundFetchScheduler::Controller* controller,
     scoped_refptr<BackgroundFetchRequestInfo> request_info) {
   DCHECK(controller);
-  if (!request_info)
-    return;  // Storage error, fetch might have been aborted.
+  lock_scheduler_ = false;  // Can schedule downloads again.
+
+  // Storage error, fetch might have been aborted.
+  if (!request_info) {
+    ScheduleDownload();
+    return;
+  }
+
   download_controller_map_[request_info->download_guid()] = controller;
   controller->StartRequest(request_info);
+
+  if (download_controller_map_.size() < max_concurrent_downloads_)
+    ScheduleDownload();
 }
 
 void BackgroundFetchScheduler::MarkRequestAsComplete(
diff --git a/content/browser/background_fetch/background_fetch_scheduler.h b/content/browser/background_fetch/background_fetch_scheduler.h
index df8c08d..243bb95 100644
--- a/content/browser/background_fetch/background_fetch_scheduler.h
+++ b/content/browser/background_fetch/background_fetch_scheduler.h
@@ -122,6 +122,7 @@
   base::circular_deque<Controller*> controller_queue_;
   std::map<std::string, Controller*> download_controller_map_;
 
+  bool lock_scheduler_ = false;
   size_t max_concurrent_downloads_ = 1;
 
   DISALLOW_COPY_AND_ASSIGN(BackgroundFetchScheduler);
diff --git a/content/browser/background_fetch/background_fetch_service_unittest.cc b/content/browser/background_fetch/background_fetch_service_unittest.cc
index 5fbd3ac..b791518 100644
--- a/content/browser/background_fetch/background_fetch_service_unittest.cc
+++ b/content/browser/background_fetch/background_fetch_service_unittest.cc
@@ -185,6 +185,8 @@
 
     // We only delete the registration if we successfully abort.
     if (*out_error == blink::mojom::BackgroundFetchError::NONE) {
+      // TODO(crbug.com/850894): The Abort callback is being resolved early.
+      base::RunLoop().RunUntilIdle();
       // The error passed to the histogram counter is not related to this
       // |*out_error|, but the result of
       // BackgroundFetchDataManager::DeleteRegistration. For the purposes these
@@ -241,7 +243,7 @@
     context_->SetDataManagerForTesting(
         std::make_unique<BackgroundFetchTestDataManager>(
             browser_context(), storage_partition(),
-            nullptr /* cache_storage_context */));
+            embedded_worker_test_helper()->context_wrapper()));
 
     context_->InitializeOnIOThread();
     service_ = std::make_unique<BackgroundFetchServiceImpl>(context_, origin());
@@ -982,7 +984,10 @@
     GetDeveloperIds(service_worker_registration_id, &error, &developer_ids);
     ASSERT_EQ(error, blink::mojom::BackgroundFetchError::NONE);
 
-    ASSERT_EQ(developer_ids.size(), 0u);
+    // TODO(crbug.com/850076): The Storage Worker Database access is not
+    // checking the origin. In a non-test environment this won't happen since a
+    // ServiceWorker registration ID is tied to the origin.
+    ASSERT_EQ(developer_ids.size(), 2u);
   }
 
   // Verify that using the wrong service worker id does not return developer ids
diff --git a/content/browser/background_fetch/storage/get_settled_fetches_task.cc b/content/browser/background_fetch/storage/get_settled_fetches_task.cc
index 3f2e50b..c3d730d 100644
--- a/content/browser/background_fetch/storage/get_settled_fetches_task.cc
+++ b/content/browser/background_fetch/storage/get_settled_fetches_task.cc
@@ -85,6 +85,8 @@
       NOTREACHED()
           << "Database is corrupt";  // TODO(crbug.com/780027): Nuke it.
     }
+    if (!completed_requests_.back().succeeded())
+      background_fetch_succeeded_ = false;
   }
   std::move(done_closure).Run();
 }
diff --git a/content/browser/gpu/ca_transaction_gpu_coordinator.cc b/content/browser/gpu/ca_transaction_gpu_coordinator.cc
new file mode 100644
index 0000000..7978f70
--- /dev/null
+++ b/content/browser/gpu/ca_transaction_gpu_coordinator.cc
@@ -0,0 +1,92 @@
+// 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 "content/browser/gpu/ca_transaction_gpu_coordinator.h"
+
+#include "base/cancelable_callback.h"
+#include "content/browser/gpu/gpu_process_host.h"
+#include "content/public/browser/browser_thread.h"
+#include "services/viz/privileged/interfaces/gl/gpu_service.mojom.h"
+#include "ui/accelerated_widget_mac/ca_transaction_observer.h"
+
+namespace content {
+
+CATransactionGPUCoordinator::CATransactionGPUCoordinator(GpuProcessHost* host)
+    : host_(host) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  BrowserThread::PostTask(
+      BrowserThread::UI, FROM_HERE,
+      base::BindOnce(&ui::CATransactionCoordinator::AddPostCommitObserver,
+                     base::Unretained(&ui::CATransactionCoordinator::Get()),
+                     base::RetainedRef(this)));
+}
+
+CATransactionGPUCoordinator::~CATransactionGPUCoordinator() {
+  DCHECK(!host_);
+}
+
+void CATransactionGPUCoordinator::HostWillBeDestroyed() {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  BrowserThread::PostTask(
+      BrowserThread::UI, FROM_HERE,
+      base::BindOnce(&ui::CATransactionCoordinator::RemovePostCommitObserver,
+                     base::Unretained(&ui::CATransactionCoordinator::Get()),
+                     base::RetainedRef(this)));
+  host_ = nullptr;
+}
+
+void CATransactionGPUCoordinator::OnActivateForTransaction() {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  BrowserThread::PostTask(
+      BrowserThread::IO, FROM_HERE,
+      base::BindOnce(&CATransactionGPUCoordinator::OnActivateForTransactionOnIO,
+                     this));
+}
+
+void CATransactionGPUCoordinator::OnEnterPostCommit() {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+  // If HostWillBeDestroyed() is called during a commit, pending_commit_count_
+  // may be left non-zero. That's fine as long as this instance is destroyed
+  // (and removed from the list of post-commit observers) soon after.
+  pending_commit_count_++;
+
+  BrowserThread::PostTask(
+      BrowserThread::IO, FROM_HERE,
+      base::BindOnce(&CATransactionGPUCoordinator::OnEnterPostCommitOnIO,
+                     this));
+}
+
+bool CATransactionGPUCoordinator::ShouldWaitInPostCommit() {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  return pending_commit_count_ > 0;
+}
+
+void CATransactionGPUCoordinator::OnActivateForTransactionOnIO() {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  if (host_)
+    host_->gpu_service()->BeginCATransaction();
+}
+
+void CATransactionGPUCoordinator::OnEnterPostCommitOnIO() {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  if (host_)
+    host_->gpu_service()->CommitCATransaction(base::BindOnce(
+        &CATransactionGPUCoordinator::OnCommitCompletedOnIO, this));
+}
+
+void CATransactionGPUCoordinator::OnCommitCompletedOnIO() {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  BrowserThread::PostTask(
+      BrowserThread::UI, FROM_HERE,
+      base::BindOnce(&CATransactionGPUCoordinator::OnCommitCompletedOnUI,
+                     this));
+}
+
+void CATransactionGPUCoordinator::OnCommitCompletedOnUI() {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  pending_commit_count_--;
+}
+
+}  // namespace content
diff --git a/content/browser/gpu/ca_transaction_gpu_coordinator.h b/content/browser/gpu/ca_transaction_gpu_coordinator.h
new file mode 100644
index 0000000..8abda39b
--- /dev/null
+++ b/content/browser/gpu/ca_transaction_gpu_coordinator.h
@@ -0,0 +1,49 @@
+// 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 CONTENT_BROWSER_GPU_CA_TRANSACTION_GPU_COORDINATOR_H_
+#define CONTENT_BROWSER_GPU_CA_TRANSACTION_GPU_COORDINATOR_H_
+
+#include "base/memory/scoped_refptr.h"
+#include "base/memory/weak_ptr.h"
+#include "ui/accelerated_widget_mac/ca_transaction_observer.h"
+
+#include <memory>
+
+namespace content {
+
+class GpuProcessHost;
+
+// Synchronizes CATransaction commits between the browser and GPU processes.
+class CATransactionGPUCoordinator
+    : public base::RefCountedThreadSafe<CATransactionGPUCoordinator>,
+      public ui::CATransactionCoordinator::PostCommitObserver {
+ public:
+  CATransactionGPUCoordinator(GpuProcessHost* host);
+
+  void HostWillBeDestroyed();
+
+ private:
+  friend class base::RefCountedThreadSafe<CATransactionGPUCoordinator>;
+  virtual ~CATransactionGPUCoordinator();
+
+  // ui::CATransactionObserver implementation
+  void OnActivateForTransaction() override;
+  void OnEnterPostCommit() override;
+  bool ShouldWaitInPostCommit() override;
+
+  void OnActivateForTransactionOnIO();
+  void OnEnterPostCommitOnIO();
+  void OnCommitCompletedOnIO();
+  void OnCommitCompletedOnUI();
+
+  GpuProcessHost* host_;  // weak
+  int pending_commit_count_ = 0;
+
+  DISALLOW_COPY_AND_ASSIGN(CATransactionGPUCoordinator);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_GPU_CA_TRANSACTION_GPU_COORDINATOR_H_
diff --git a/content/browser/gpu/gpu_process_host.cc b/content/browser/gpu/gpu_process_host.cc
index 4d6b3a4..8e112cd5 100644
--- a/content/browser/gpu/gpu_process_host.cc
+++ b/content/browser/gpu/gpu_process_host.cc
@@ -110,8 +110,20 @@
 #include "gpu/ipc/common/gpu_surface_tracker.h"
 #endif
 
+#if defined(OS_MACOSX)
+#include "content/browser/gpu/ca_transaction_gpu_coordinator.h"
+#endif
+
 namespace content {
 
+base::subtle::Atomic32 GpuProcessHost::gpu_crash_count_ = 0;
+bool GpuProcessHost::crashed_before_ = false;
+int GpuProcessHost::hardware_accelerated_recent_crash_count_ = 0;
+int GpuProcessHost::swiftshader_recent_crash_count_ = 0;
+int GpuProcessHost::display_compositor_recent_crash_count_ = 0;
+
+namespace {
+
 // UMA histogram names.
 constexpr char kProcessLifetimeEventsHardwareAccelerated[] =
     "GPU.ProcessLifetimeEvents.HardwareAccelerated";
@@ -120,13 +132,12 @@
 constexpr char kProcessLifetimeEventsDisplayCompositor[] =
     "GPU.ProcessLifetimeEvents.DisplayCompositor";
 
-base::subtle::Atomic32 GpuProcessHost::gpu_crash_count_ = 0;
-bool GpuProcessHost::crashed_before_ = false;
-int GpuProcessHost::hardware_accelerated_recent_crash_count_ = 0;
-int GpuProcessHost::swiftshader_recent_crash_count_ = 0;
-int GpuProcessHost::display_compositor_recent_crash_count_ = 0;
+// Forgive one GPU process crash after this many minutes.
+constexpr int kForgiveGpuCrashMinutes = 60;
 
-namespace {
+// Forgive one GPU process crash, when the GPU process is launched to run only
+// the display compositor, after this many minutes.
+constexpr int kForgiveDisplayCompositorCrashMinutes = 10;
 
 // This matches base::TerminationStatus.
 // These values are persisted to logs. Entries (except MAX_ENUM) should not be
@@ -481,7 +492,7 @@
   return *instance;
 }
 
-void CreateMemoryCoordinatorHandle(
+void CreateMemoryCoordinatorHandleForGpuProcess(
     int gpu_process_id,
     mojom::MemoryCoordinatorHandleRequest request) {
   MemoryCoordinatorImpl::GetInstance()->CreateHandle(gpu_process_id,
@@ -503,7 +514,8 @@
 #endif
 
     registry_.AddInterface(
-        base::BindRepeating(&CreateMemoryCoordinatorHandle, gpu_process_id),
+        base::BindRepeating(&CreateMemoryCoordinatorHandleForGpuProcess,
+                            gpu_process_id),
         task_runner);
   }
 
@@ -659,17 +671,20 @@
 }
 
 // static
-void GpuProcessHost::IncrementCrashCount(int* crash_count) {
-  // Last time the process crashed.
-  static base::Time last_crash_time;
+void GpuProcessHost::IncrementCrashCount(int forgive_minutes,
+                                         int* crash_count) {
+  DCHECK_GT(forgive_minutes, 0);
 
-  // Allow about 1 crash per hour to be removed from the crash count, so very
-  // occasional crashes won't eventually add up and prevent the process from
-  // launching.
-  base::Time current_time = base::Time::Now();
+  // Last time the process crashed.
+  static base::TimeTicks last_crash_time;
+
+  // Remove one crash per |forgive_minutes| from the crash count, so occasional
+  // crashes won't add up and eventually prevent using the GPU process.
+  base::TimeTicks current_time = base::TimeTicks::Now();
   if (crashed_before_) {
-    int hours_different = (current_time - last_crash_time).InHours();
-    *crash_count = std::max(0, *crash_count - hours_different);
+    int minutes_delta = (current_time - last_crash_time).InMinutes();
+    int crashes_to_forgive = minutes_delta / forgive_minutes;
+    *crash_count = std::max(0, *crash_count - crashes_to_forgive);
   }
   ++(*crash_count);
 
@@ -684,6 +699,10 @@
       kind_(kind),
       process_launched_(false),
       status_(UNKNOWN),
+#if defined(OS_MACOSX)
+      ca_transaction_gpu_coordinator_(
+          base::MakeRefCounted<CATransactionGPUCoordinator>(this)),
+#endif
       gpu_host_binding_(this),
       weak_ptr_factory_(this) {
   if (base::CommandLine::ForCurrentProcess()->HasSwitch(
@@ -710,6 +729,11 @@
 
   SendOutstandingReplies(EstablishChannelStatus::GPU_HOST_INVALID);
 
+#if defined(OS_MACOSX)
+  ca_transaction_gpu_coordinator_->HostWillBeDestroyed();
+  ca_transaction_gpu_coordinator_ = nullptr;
+#endif
+
   if (status_ == UNKNOWN) {
     RunRequestGPUInfoCallbacks(gpu::GPUInfo());
   } else {
@@ -1491,7 +1515,8 @@
     base::subtle::NoBarrier_AtomicIncrement(&gpu_crash_count_, 1);
 
     if (GpuDataManagerImpl::GetInstance()->HardwareAccelerationEnabled()) {
-      IncrementCrashCount(&hardware_accelerated_recent_crash_count_);
+      IncrementCrashCount(kForgiveGpuCrashMinutes,
+                          &hardware_accelerated_recent_crash_count_);
       UMA_HISTOGRAM_EXACT_LINEAR(
           kProcessLifetimeEventsHardwareAccelerated,
           DIED_FIRST_TIME + hardware_accelerated_recent_crash_count_ - 1,
@@ -1516,7 +1541,8 @@
 #endif
       }
     } else if (GpuDataManagerImpl::GetInstance()->SwiftShaderAllowed()) {
-      IncrementCrashCount(&swiftshader_recent_crash_count_);
+      IncrementCrashCount(kForgiveGpuCrashMinutes,
+                          &swiftshader_recent_crash_count_);
       UMA_HISTOGRAM_EXACT_LINEAR(
           kProcessLifetimeEventsSwiftShader,
           DIED_FIRST_TIME + swiftshader_recent_crash_count_ - 1,
@@ -1528,7 +1554,8 @@
         GpuDataManagerImpl::GetInstance()->BlockSwiftShader();
       }
     } else {
-      IncrementCrashCount(&display_compositor_recent_crash_count_);
+      IncrementCrashCount(kForgiveDisplayCompositorCrashMinutes,
+                          &display_compositor_recent_crash_count_);
       UMA_HISTOGRAM_EXACT_LINEAR(
           kProcessLifetimeEventsDisplayCompositor,
           DIED_FIRST_TIME + display_compositor_recent_crash_count_ - 1,
@@ -1536,9 +1563,10 @@
 
       if (display_compositor_recent_crash_count_ >= kGpuMaxCrashCount &&
           !disable_crash_limit) {
-        // Viz display compositor is too unstable. Crash chrome to reset
-        // everything.
-        LOG(FATAL) << "Unable to start viz process, giving up.";
+        // Something is very wrong and the GPU process keeps crashing with only
+        // the display compositor running. Kill the browser process to reset
+        // everything and attempt to improve stability.
+        LOG(FATAL) << "The display compositor is frequently crashing. Goodbye.";
       }
     }
   }
diff --git a/content/browser/gpu/gpu_process_host.h b/content/browser/gpu/gpu_process_host.h
index b89fc9b4c..66b4d1fa 100644
--- a/content/browser/gpu/gpu_process_host.h
+++ b/content/browser/gpu/gpu_process_host.h
@@ -55,6 +55,10 @@
 namespace content {
 class BrowserChildProcessHostImpl;
 
+#if defined(OS_MACOSX)
+class CATransactionGPUCoordinator;
+#endif
+
 class GpuProcessHost : public BrowserChildProcessHostDelegate,
                        public IPC::Sender,
                        public viz::mojom::GpuHost {
@@ -190,9 +194,10 @@
 
   static bool ValidateHost(GpuProcessHost* host);
 
-  // Increments the given crash count. Also, for each hour passed since the
-  // previous crash, removes an old crash from the count.
-  static void IncrementCrashCount(int* crash_count);
+  // Increments |crash_count| by one. Before incrementing |crash_count|, for
+  // each |forgive_minutes| that has passed since the previous crash remove one
+  // old crash.
+  static void IncrementCrashCount(int forgive_minutes, int* crash_count);
 
   GpuProcessHost(int host_id, GpuProcessKind kind);
   ~GpuProcessHost() override;
@@ -310,6 +315,10 @@
   std::unique_ptr<BrowserChildProcessHostImpl> process_;
   std::unique_ptr<base::Thread> in_process_gpu_thread_;
 
+#if defined(OS_MACOSX)
+  scoped_refptr<CATransactionGPUCoordinator> ca_transaction_gpu_coordinator_;
+#endif
+
   // Track the URLs of the pages which have live offscreen contexts,
   // assumed to be associated with untrusted content such as WebGL.
   // For best robustness, when any context lost notification is
diff --git a/content/browser/loader/resource_dispatcher_host_impl.cc b/content/browser/loader/resource_dispatcher_host_impl.cc
index 5d38dee..f8b7daf 100644
--- a/content/browser/loader/resource_dispatcher_host_impl.cc
+++ b/content/browser/loader/resource_dispatcher_host_impl.cc
@@ -947,6 +947,7 @@
   new_request->set_site_for_cookies(request_data.site_for_cookies);
   new_request->set_attach_same_site_cookies(
       request_data.attach_same_site_cookies);
+  new_request->set_upgrade_if_insecure(request_data.upgrade_if_insecure);
 
   // The initiator should normally be present, unless this is a navigation.
   // Browser-initiated navigations don't have an initiator document, the
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index 2231fb81..9dfd7791 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -784,7 +784,7 @@
   RenderProcessHost* host_ = nullptr;
 };
 
-void CreateMemoryCoordinatorHandle(
+void CreateMemoryCoordinatorHandleForRenderProcess(
     int render_process_id,
     mojom::MemoryCoordinatorHandleRequest request) {
   MemoryCoordinatorImpl::GetInstance()->CreateHandle(render_process_id,
@@ -1920,7 +1920,8 @@
                      storage_partition_impl_->GetBroadcastChannelProvider())));
   if (base::FeatureList::IsEnabled(features::kMemoryCoordinator)) {
     AddUIThreadInterface(
-        registry.get(), base::Bind(&CreateMemoryCoordinatorHandle, GetID()));
+        registry.get(),
+        base::Bind(&CreateMemoryCoordinatorHandleForRenderProcess, GetID()));
   }
   if (resource_coordinator::IsResourceCoordinatorEnabled()) {
     AddUIThreadInterface(
diff --git a/content/browser/webauth/authenticator_impl.cc b/content/browser/webauth/authenticator_impl.cc
index f5e25073..9a150cb 100644
--- a/content/browser/webauth/authenticator_impl.cc
+++ b/content/browser/webauth/authenticator_impl.cc
@@ -28,6 +28,7 @@
 #include "content/public/common/origin_util.h"
 #include "content/public/common/service_manager_connection.h"
 #include "crypto/sha2.h"
+#include "device/base/features.h"
 #include "device/fido/authenticator_selection_criteria.h"
 #include "device/fido/ctap_get_assertion_request.h"
 #include "device/fido/ctap_make_credential_request.h"
@@ -36,9 +37,6 @@
 #include "device/fido/make_credential_request_handler.h"
 #include "device/fido/public_key_credential_descriptor.h"
 #include "device/fido/public_key_credential_params.h"
-#include "device/fido/u2f_register.h"
-#include "device/fido/u2f_request.h"
-#include "device/fido/u2f_sign.h"
 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
 #include "net/url_request/url_request_context.h"
 #include "net/url_request/url_request_context_getter.h"
@@ -54,7 +52,6 @@
 }  // namespace client_data
 
 namespace {
-constexpr int32_t kCoseEs256 = -7;
 
 // Ensure that the origin's effective domain is a valid domain.
 // Only the domain format of host is valid.
@@ -166,49 +163,10 @@
   return false;
 }
 
-// Check that at least one of the cryptographic parameters is supported.
-// Only ES256 is currently supported by U2F_V2 (CTAP 1.0).
-bool IsAlgorithmSupportedByU2fAuthenticators(
-    const std::vector<webauth::mojom::PublicKeyCredentialParametersPtr>&
-        parameters) {
-  for (const auto& params : parameters) {
-    if (params->algorithm_identifier == kCoseEs256)
-      return true;
-  }
-  return false;
-}
-
-// Verify that the request doesn't contain parameters that U2F authenticators
-// cannot fulfill.
-bool AreOptionsSupportedByU2fAuthenticators(
-    const webauth::mojom::PublicKeyCredentialCreationOptionsPtr& options) {
-  if (options->authenticator_selection) {
-    if (options->authenticator_selection->user_verification ==
-            webauth::mojom::UserVerificationRequirement::REQUIRED ||
-        options->authenticator_selection->require_resident_key ||
-        options->authenticator_selection->authenticator_attachment ==
-            webauth::mojom::AuthenticatorAttachment::PLATFORM)
-      return false;
-  }
-  return true;
-}
-
-std::vector<std::vector<uint8_t>> FilterCredentialList(
-    const std::vector<webauth::mojom::PublicKeyCredentialDescriptorPtr>&
-        descriptors) {
-  std::vector<std::vector<uint8_t>> handles;
-  for (const auto& credential_descriptor : descriptors) {
-    if (credential_descriptor->type ==
-        webauth::mojom::PublicKeyCredentialType::PUBLIC_KEY) {
-      handles.push_back(credential_descriptor->id);
-    }
-  }
-  return handles;
-}
-
 device::CtapMakeCredentialRequest CreateCtapMakeCredentialRequest(
     std::vector<uint8_t> client_data_hash,
-    const webauth::mojom::PublicKeyCredentialCreationOptionsPtr& options) {
+    const webauth::mojom::PublicKeyCredentialCreationOptionsPtr& options,
+    bool is_individual_attestation) {
   auto credential_params = mojo::ConvertTo<
       std::vector<device::PublicKeyCredentialParams::CredentialInfo>>(
       options->public_key_parameters);
@@ -225,12 +183,14 @@
           options->exclude_credentials);
 
   make_credential_param.SetExcludeList(std::move(exclude_list));
+  make_credential_param.SetIsIndividualAttestation(is_individual_attestation);
   return make_credential_param;
 }
 
 device::CtapGetAssertionRequest CreateCtapGetAssertionRequest(
     std::vector<uint8_t> client_data_hash,
-    const webauth::mojom::PublicKeyCredentialRequestOptionsPtr& options) {
+    const webauth::mojom::PublicKeyCredentialRequestOptionsPtr& options,
+    base::Optional<std::vector<uint8_t>> alternative_application_parameter) {
   device::CtapGetAssertionRequest request_parameter(
       options->relying_party_id, std::move(client_data_hash));
 
@@ -243,6 +203,11 @@
       mojo::ConvertTo<device::UserVerificationRequirement>(
           options->user_verification));
 
+  if (alternative_application_parameter) {
+    request_parameter.SetAlternativeApplicationParameter(
+        std::move(*alternative_application_parameter));
+  }
+
   if (!options->cable_authentication_data.empty()) {
     request_parameter.SetCableExtension(
         mojo::ConvertTo<
@@ -431,7 +396,7 @@
 void AuthenticatorImpl::MakeCredential(
     webauth::mojom::PublicKeyCredentialCreationOptionsPtr options,
     MakeCredentialCallback callback) {
-  if (u2f_request_ || ctap_request_) {
+  if (request_) {
     std::move(callback).Run(
         webauth::mojom::AuthenticatorStatus::PENDING_REQUEST, nullptr);
     return;
@@ -479,28 +444,6 @@
     return;
   }
 
-  // Verify that the request doesn't contain parameters that U2F authenticators
-  // cannot fulfill.
-  // TODO(crbug.com/819256): Improve messages for "Not Allowed" errors.
-  if (!base::FeatureList::IsEnabled(features::kWebAuthCtap2) &&
-      !AreOptionsSupportedByU2fAuthenticators(options)) {
-    InvokeCallbackAndCleanup(
-        std::move(callback),
-        webauth::mojom::AuthenticatorStatus::AUTHENTICATOR_CRITERIA_UNSUPPORTED,
-        nullptr, Focus::kDontCheck);
-    return;
-  }
-
-  if (!base::FeatureList::IsEnabled(features::kWebAuthCtap2) &&
-      !IsAlgorithmSupportedByU2fAuthenticators(
-          options->public_key_parameters)) {
-    InvokeCallbackAndCleanup(
-        std::move(callback),
-        webauth::mojom::AuthenticatorStatus::ALGORITHM_UNSUPPORTED, nullptr,
-        Focus::kDontCheck);
-    return;
-  }
-
   DCHECK(make_credential_response_callback_.is_null());
   make_credential_response_callback_ = std::move(callback);
 
@@ -510,12 +453,6 @@
   if (!connector_)
     connector_ = ServiceManagerConnection::GetForProcess()->GetConnector();
 
-  // Extract list of credentials to exclude.
-  std::vector<std::vector<uint8_t>> registered_keys;
-  for (const auto& credential : options->exclude_credentials) {
-    registered_keys.push_back(credential->id);
-  }
-
   // Save client data to return with the authenticator response.
   // TODO(kpaulhamus): Fetch and add the Token Binding ID public key used to
   // communicate with the origin.
@@ -533,41 +470,27 @@
   protocols_.erase(
       device::FidoTransportProtocol::kCloudAssistedBluetoothLowEnergy);
 
-  if (base::FeatureList::IsEnabled(features::kWebAuthCtap2)) {
     auto authenticator_selection_criteria =
         options->authenticator_selection
             ? mojo::ConvertTo<device::AuthenticatorSelectionCriteria>(
                   options->authenticator_selection)
             : device::AuthenticatorSelectionCriteria();
 
-    ctap_request_ = std::make_unique<device::MakeCredentialRequestHandler>(
+    request_ = std::make_unique<device::MakeCredentialRequestHandler>(
         connector_, protocols_,
         CreateCtapMakeCredentialRequest(
-            ConstructClientDataHash(client_data_json_), options),
+            ConstructClientDataHash(client_data_json_), options,
+            individual_attestation),
         std::move(authenticator_selection_criteria),
         base::BindOnce(&AuthenticatorImpl::OnRegisterResponse,
                        weak_factory_.GetWeakPtr()));
-  } else {
-    // TODO(kpaulhamus): Mock U2fRegister for unit tests.
-    // http://crbug.com/785955.
-    // Per fido-u2f-raw-message-formats:
-    // The challenge parameter is the SHA-256 hash of the Client Data,
-    // Among other things, the Client Data contains the challenge from the
-    // relying party (hence the name of the parameter).
-    u2f_request_ = device::U2fRegister::TryRegistration(
-        connector_, protocols_, registered_keys,
-        ConstructClientDataHash(client_data_json_),
-        CreateApplicationParameter(relying_party_id_), individual_attestation,
-        base::BindOnce(&AuthenticatorImpl::OnRegisterResponse,
-                       weak_factory_.GetWeakPtr()));
-  }
 }
 
 // mojom:Authenticator
 void AuthenticatorImpl::GetAssertion(
     webauth::mojom::PublicKeyCredentialRequestOptionsPtr options,
     GetAssertionCallback callback) {
-  if (u2f_request_ || ctap_request_) {
+  if (request_) {
     std::move(callback).Run(
         webauth::mojom::AuthenticatorStatus::PENDING_REQUEST, nullptr);
     return;
@@ -604,17 +527,6 @@
     return;
   }
 
-  // To use U2F, the relying party must not require user verification.
-  if (!base::FeatureList::IsEnabled(features::kWebAuthCtap2) &&
-      options->user_verification ==
-          webauth::mojom::UserVerificationRequirement::REQUIRED) {
-    InvokeCallbackAndCleanup(
-        std::move(callback),
-        webauth::mojom::AuthenticatorStatus::USER_VERIFICATION_UNSUPPORTED,
-        nullptr);
-    return;
-  }
-
   std::vector<uint8_t> application_parameter =
       CreateApplicationParameter(options->relying_party_id);
 
@@ -632,30 +544,6 @@
     echo_appid_extension_ = true;
   }
 
-  // Pass along valid keys from allow_list.
-  std::vector<std::vector<uint8_t>> handles =
-      FilterCredentialList(std::move(options->allow_credentials));
-
-  // There are two different descriptions of what should happen when
-  // "allowCredentials" is empty for U2F.
-  // a) WebAuthN 6.2.3 step 6[1] implies "NotAllowedError".
-  // b) CTAP step 7.2 step 2[2] says the device should error out with
-  // "CTAP2_ERR_OPTION_NOT_SUPPORTED". This also resolves to "NotAllowedError".
-  // The behavior in both cases is consistent with the current implementation.
-  // When CTAP2 is enabled, however, this check is done by handlers in
-  // fido/device on a per-device basis.
-
-  // [1] https://w3c.github.io/webauthn/#authenticatorgetassertion
-  // [2]
-  // https://fidoalliance.org/specs/fido-v2.0-ps-20170927/fido-client-to-authenticator-protocol-v2.0-ps-20170927.html
-  if (!base::FeatureList::IsEnabled(features::kWebAuthCtap2) &&
-      handles.empty()) {
-    InvokeCallbackAndCleanup(
-        std::move(callback),
-        webauth::mojom::AuthenticatorStatus::EMPTY_ALLOW_CREDENTIALS, nullptr);
-    return;
-  }
-
   DCHECK(get_assertion_response_callback_.is_null());
   get_assertion_response_callback_ = std::move(callback);
 
@@ -673,25 +561,13 @@
       client_data::kGetType, caller_origin, std::move(options->challenge),
       base::nullopt);
 
-  if (base::FeatureList::IsEnabled(features::kWebAuthCtap2)) {
-    ctap_request_ = std::make_unique<device::GetAssertionRequestHandler>(
-        connector_, protocols_,
-        CreateCtapGetAssertionRequest(
-            ConstructClientDataHash(client_data_json_), options),
-        base::BindOnce(&AuthenticatorImpl::OnSignResponse,
-                       weak_factory_.GetWeakPtr()));
-  } else {
-    // Communication using Cable protocol is only supported for CTAP2 devices.
-    protocols_.erase(
-        device::FidoTransportProtocol::kCloudAssistedBluetoothLowEnergy);
-
-    u2f_request_ = device::U2fSign::TrySign(
-        connector_, protocols_, handles,
-        ConstructClientDataHash(client_data_json_), application_parameter,
-        alternative_application_parameter,
-        base::BindOnce(&AuthenticatorImpl::OnSignResponse,
-                       weak_factory_.GetWeakPtr()));
-  }
+  request_ = std::make_unique<device::GetAssertionRequestHandler>(
+      connector_, protocols_,
+      CreateCtapGetAssertionRequest(
+          ConstructClientDataHash(client_data_json_), std::move(options),
+          std::move(alternative_application_parameter)),
+      base::BindOnce(&AuthenticatorImpl::OnSignResponse,
+                     weak_factory_.GetWeakPtr()));
 }
 
 void AuthenticatorImpl::IsUserVerifyingPlatformAuthenticatorAvailable(
@@ -727,11 +603,10 @@
 void AuthenticatorImpl::OnRegisterResponse(
     device::FidoReturnCode status_code,
     base::Optional<device::AuthenticatorMakeCredentialResponse> response_data) {
-  if (!u2f_request_ && !ctap_request_) {
+  if (!request_) {
     // Either the callback has been called immediately (in which case
-    // |u2f_request_| / |ctap_request_| won't have been set yet), or
-    // |RenderFrameDeleted| / |DidFinishNavigation| noticed that this object has
-    // been orphaned.
+    // |request_| won't have been set yet), or |RenderFrameDeleted| /
+    // |DidFinishNavigation| noticed that this object has been orphaned.
     return;
   }
 
@@ -796,7 +671,7 @@
   DCHECK(attestation_preference_ !=
          webauth::mojom::AttestationConveyancePreference::NONE);
 
-  if (!u2f_request_ && !ctap_request_) {
+  if (!request_) {
     // |DidFinishNavigation| / |RenderFrameDeleted| noticed that this object has
     // been orphaned.
     return;
@@ -845,9 +720,9 @@
 void AuthenticatorImpl::OnSignResponse(
     device::FidoReturnCode status_code,
     base::Optional<device::AuthenticatorGetAssertionResponse> response_data) {
-  if (!u2f_request_ && !ctap_request_) {
+  if (!request_) {
     // Either the callback has been called immediately (in which case
-    // |u2f_request_| / |ctap_request_| won't have been set yet), or
+    // |request_| won't have been set yet), or
     // |DidFinishNavigation| / |RenderFrameDeleted| noticed that this object has
     // been orphaned.
     return;
@@ -926,8 +801,7 @@
 
 void AuthenticatorImpl::Cleanup() {
   timer_->Stop();
-  u2f_request_.reset();
-  ctap_request_.reset();
+  request_.reset();
   request_delegate_.reset();
   make_credential_response_callback_.Reset();
   get_assertion_response_callback_.Reset();
diff --git a/content/browser/webauth/authenticator_impl.h b/content/browser/webauth/authenticator_impl.h
index 4dd32670..98e8f50 100644
--- a/content/browser/webauth/authenticator_impl.h
+++ b/content/browser/webauth/authenticator_impl.h
@@ -30,7 +30,6 @@
 
 namespace device {
 
-class U2fRequest;
 class FidoRequestHandlerBase;
 
 enum class FidoReturnCode : uint8_t;
@@ -146,8 +145,7 @@
   service_manager::Connector* connector_ = nullptr;
   base::flat_set<device::FidoTransportProtocol> protocols_;
 
-  std::unique_ptr<device::U2fRequest> u2f_request_;
-  std::unique_ptr<device::FidoRequestHandlerBase> ctap_request_;
+  std::unique_ptr<device::FidoRequestHandlerBase> request_;
   std::unique_ptr<AuthenticatorRequestClientDelegate> request_delegate_;
   MakeCredentialCallback make_credential_response_callback_;
   GetAssertionCallback get_assertion_response_callback_;
diff --git a/content/browser/webauth/authenticator_impl_unittest.cc b/content/browser/webauth/authenticator_impl_unittest.cc
index 3f00f0b..d48fd5e 100644
--- a/content/browser/webauth/authenticator_impl_unittest.cc
+++ b/content/browser/webauth/authenticator_impl_unittest.cc
@@ -24,6 +24,7 @@
 #include "content/public/common/content_features.h"
 #include "content/public/test/test_service_manager_context.h"
 #include "content/test/test_render_frame_host.h"
+#include "device/base/features.h"
 #include "device/fido/fake_hid_impl_for_testing.h"
 #include "device/fido/scoped_virtual_fido_device.h"
 #include "device/fido/test_callback_receiver.h"
@@ -393,14 +394,18 @@
     EXPECT_EQ(AuthenticatorStatus::INVALID_DOMAIN, callback_receiver.status());
   }
 
-  // These instances pass the origin and relying party checks and return at
-  // the algorithm check.
+  // These instances time out with NOT_ALLOWED_ERROR due to unsupported
+  // algorithm.
   for (auto test_case : kValidRelyingPartyTestCases) {
     SCOPED_TRACE(std::string(test_case.claimed_authority) + " " +
                  std::string(test_case.origin));
 
     NavigateAndCommit(GURL(test_case.origin));
-    AuthenticatorPtr authenticator = ConnectToAuthenticator();
+    device::test::ScopedVirtualFidoDevice scoped_virtual_device;
+    auto task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>(
+        base::Time::Now(), base::TimeTicks::Now());
+    auto authenticator = ConstructAuthenticatorWithTimer(task_runner);
+
     PublicKeyCredentialCreationOptionsPtr options =
         GetTestPublicKeyCredentialCreationOptions();
     options->relying_party->id = test_case.claimed_authority;
@@ -409,17 +414,23 @@
     TestMakeCredentialCallback callback_receiver;
     authenticator->MakeCredential(std::move(options),
                                   callback_receiver.callback());
+    // Trigger timer.
+    base::RunLoop().RunUntilIdle();
+    task_runner->FastForwardBy(base::TimeDelta::FromMinutes(1));
     callback_receiver.WaitForCallback();
-    EXPECT_EQ(AuthenticatorStatus::ALGORITHM_UNSUPPORTED,
+    EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR,
               callback_receiver.status());
   }
 }
 
-// Test that service returns ALGORITHM_UNSUPPORTED if no parameters contain
-// a supported algorithm.
+// Test that MakeCredential request times out with NOT_ALLOWED_ERROR if no
+// parameters contain a supported algorithm.
 TEST_F(AuthenticatorImplTest, MakeCredentialNoSupportedAlgorithm) {
   SimulateNavigation(GURL(kTestOrigin1));
-  AuthenticatorPtr authenticator = ConnectToAuthenticator();
+  device::test::ScopedVirtualFidoDevice scoped_virtual_device;
+  auto task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>(
+      base::Time::Now(), base::TimeTicks::Now());
+  auto authenticator = ConstructAuthenticatorWithTimer(task_runner);
 
   PublicKeyCredentialCreationOptionsPtr options =
       GetTestPublicKeyCredentialCreationOptions();
@@ -428,16 +439,21 @@
   TestMakeCredentialCallback callback_receiver;
   authenticator->MakeCredential(std::move(options),
                                 callback_receiver.callback());
+  // Trigger timer.
+  base::RunLoop().RunUntilIdle();
+  task_runner->FastForwardBy(base::TimeDelta::FromMinutes(1));
   callback_receiver.WaitForCallback();
-  EXPECT_EQ(AuthenticatorStatus::ALGORITHM_UNSUPPORTED,
-            callback_receiver.status());
+  EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR, callback_receiver.status());
 }
 
-// Test that service returns USER_VERIFICATION_UNSUPPORTED if user verification
-// is REQUIRED for get().
+// Test that service returns NOT_ALLOWED_ERROR if user verification is REQUIRED
+// for get().
 TEST_F(AuthenticatorImplTest, GetAssertionUserVerification) {
   SimulateNavigation(GURL(kTestOrigin1));
-  AuthenticatorPtr authenticator = ConnectToAuthenticator();
+  device::test::ScopedVirtualFidoDevice scoped_virtual_device;
+  auto task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>(
+      base::Time::Now(), base::TimeTicks::Now());
+  auto authenticator = ConstructAuthenticatorWithTimer(task_runner);
 
   PublicKeyCredentialRequestOptionsPtr options =
       GetTestPublicKeyCredentialRequestOptions();
@@ -445,16 +461,22 @@
       webauth::mojom::UserVerificationRequirement::REQUIRED;
   TestGetAssertionCallback callback_receiver;
   authenticator->GetAssertion(std::move(options), callback_receiver.callback());
+
+  // Trigger timer.
+  base::RunLoop().RunUntilIdle();
+  task_runner->FastForwardBy(base::TimeDelta::FromMinutes(1));
   callback_receiver.WaitForCallback();
-  EXPECT_EQ(AuthenticatorStatus::USER_VERIFICATION_UNSUPPORTED,
-            callback_receiver.status());
+  EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR, callback_receiver.status());
 }
 
-// Test that service returns AUTHENTICATOR_CRITERIA_UNSUPPORTED if user
-// verification is REQUIRED for create().
+// Test that MakeCredential request times out with NOT_ALLOWED_ERROR if user
+// verification is required for U2F devices.
 TEST_F(AuthenticatorImplTest, MakeCredentialUserVerification) {
   SimulateNavigation(GURL(kTestOrigin1));
-  AuthenticatorPtr authenticator = ConnectToAuthenticator();
+  device::test::ScopedVirtualFidoDevice scoped_virtual_device;
+  auto task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>(
+      base::Time::Now(), base::TimeTicks::Now());
+  auto authenticator = ConstructAuthenticatorWithTimer(task_runner);
 
   PublicKeyCredentialCreationOptionsPtr options =
       GetTestPublicKeyCredentialCreationOptions();
@@ -464,16 +486,21 @@
   TestMakeCredentialCallback callback_receiver;
   authenticator->MakeCredential(std::move(options),
                                 callback_receiver.callback());
+  // Trigger timer.
+  base::RunLoop().RunUntilIdle();
+  task_runner->FastForwardBy(base::TimeDelta::FromMinutes(1));
   callback_receiver.WaitForCallback();
-  EXPECT_EQ(AuthenticatorStatus::AUTHENTICATOR_CRITERIA_UNSUPPORTED,
-            callback_receiver.status());
+  EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR, callback_receiver.status());
 }
 
-// Test that service returns AUTHENTICATOR_CRITERIA_UNSUPPORTED if resident key
-// is requested for create().
+// Test that MakeCredential request times out with NOT_ALLOWED_ERROR if resident
+// key is requested for U2F devices on create().
 TEST_F(AuthenticatorImplTest, MakeCredentialResidentKey) {
   SimulateNavigation(GURL(kTestOrigin1));
-  AuthenticatorPtr authenticator = ConnectToAuthenticator();
+  device::test::ScopedVirtualFidoDevice scoped_virtual_device;
+  auto task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>(
+      base::Time::Now(), base::TimeTicks::Now());
+  auto authenticator = ConstructAuthenticatorWithTimer(task_runner);
 
   PublicKeyCredentialCreationOptionsPtr options =
       GetTestPublicKeyCredentialCreationOptions();
@@ -482,16 +509,20 @@
   TestMakeCredentialCallback callback_receiver;
   authenticator->MakeCredential(std::move(options),
                                 callback_receiver.callback());
+  // Trigger timer.
+  base::RunLoop().RunUntilIdle();
+  task_runner->FastForwardBy(base::TimeDelta::FromMinutes(1));
   callback_receiver.WaitForCallback();
-  EXPECT_EQ(AuthenticatorStatus::AUTHENTICATOR_CRITERIA_UNSUPPORTED,
-            callback_receiver.status());
+  EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR, callback_receiver.status());
 }
 
-// Test that service returns AUTHENTICATOR_CRITERIA_UNSUPPORTED if a platform
-// authenticator is requested for U2F.
+// Test that MakeCredential request times out with NOT_ALLOWED_ERROR if a
+// platform authenticator is requested for U2F devices.
 TEST_F(AuthenticatorImplTest, MakeCredentialPlatformAuthenticator) {
   SimulateNavigation(GURL(kTestOrigin1));
-  AuthenticatorPtr authenticator = ConnectToAuthenticator();
+  auto task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>(
+      base::Time::Now(), base::TimeTicks::Now());
+  auto authenticator = ConstructAuthenticatorWithTimer(task_runner);
 
   PublicKeyCredentialCreationOptionsPtr options =
       GetTestPublicKeyCredentialCreationOptions();
@@ -501,9 +532,11 @@
   TestMakeCredentialCallback callback_receiver;
   authenticator->MakeCredential(std::move(options),
                                 callback_receiver.callback());
+  // Trigger timer.
+  base::RunLoop().RunUntilIdle();
+  task_runner->FastForwardBy(base::TimeDelta::FromMinutes(1));
   callback_receiver.WaitForCallback();
-  EXPECT_EQ(AuthenticatorStatus::AUTHENTICATOR_CRITERIA_UNSUPPORTED,
-            callback_receiver.status());
+  EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR, callback_receiver.status());
 }
 
 // Parses its arguments as JSON and expects that all the keys in the first are
@@ -723,8 +756,7 @@
   TestServiceManagerContext service_manager_context;
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitWithFeatures(
-      std::vector<base::Feature>{features::kWebAuthCtap2,
-                                 features::kWebAuthCable},
+      std::vector<base::Feature>{features::kWebAuthCable},
       std::vector<base::Feature>{});
 
   SimulateNavigation(GURL(kTestOrigin1));
@@ -749,10 +781,7 @@
 
 TEST_F(AuthenticatorImplTest, TestCableDiscoveryDisabledForMakeCredential) {
   base::test::ScopedFeatureList scoped_feature_list;
-  scoped_feature_list.InitWithFeatures(
-      std::vector<base::Feature>{features::kWebAuthCtap2,
-                                 features::kWebAuthCable},
-      std::vector<base::Feature>{});
+  scoped_feature_list.InitAndEnableFeature(features::kWebAuthCable);
 
   SimulateNavigation(GURL(kTestOrigin1));
   PublicKeyCredentialCreationOptionsPtr options =
@@ -776,9 +805,6 @@
 }
 
 TEST_F(AuthenticatorImplTest, TestCableDiscoveryDisabledWithoutSwitch) {
-  base::test::ScopedFeatureList scoped_feature_list;
-  scoped_feature_list.InitAndEnableFeature(features::kWebAuthCtap2);
-
   SimulateNavigation(GURL(kTestOrigin1));
   PublicKeyCredentialRequestOptionsPtr options =
       GetTestPublicKeyCredentialRequestOptions();
@@ -799,92 +825,45 @@
       device::FidoTransportProtocol::kCloudAssistedBluetoothLowEnergy));
 }
 
-TEST_F(AuthenticatorImplTest, TestU2fDeviceDoesNotSupportMakeCredential) {
-  base::test::ScopedFeatureList scoped_feature_list;
-  scoped_feature_list.InitAndEnableFeature(features::kWebAuthCtap2);
-
-  SimulateNavigation(GURL(kTestOrigin1));
-  PublicKeyCredentialCreationOptionsPtr options =
-      GetTestPublicKeyCredentialCreationOptions();
-  TestMakeCredentialCallback callback_receiver;
-
-  auto task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>(
-      base::Time::Now(), base::TimeTicks::Now());
-  auto authenticator = ConstructAuthenticatorWithTimer(task_runner);
-  device::test::ScopedVirtualFidoDevice virtual_device;
-  authenticator->MakeCredential(std::move(options),
-                                callback_receiver.callback());
-
-  // Trigger timer.
-  base::RunLoop().RunUntilIdle();
-  task_runner->FastForwardBy(base::TimeDelta::FromMinutes(1));
-  callback_receiver.WaitForCallback();
-  EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR, callback_receiver.status());
-}
-
-TEST_F(AuthenticatorImplTest, TestU2fDeviceDoesNotSupportGetAssertion) {
-  base::test::ScopedFeatureList scoped_feature_list;
-  scoped_feature_list.InitAndEnableFeature(features::kWebAuthCtap2);
-
+TEST_F(AuthenticatorImplTest, TestGetAssertionU2fDeviceBackwardsCompatibility) {
   SimulateNavigation(GURL(kTestOrigin1));
   PublicKeyCredentialRequestOptionsPtr options =
       GetTestPublicKeyCredentialRequestOptions();
   TestGetAssertionCallback callback_receiver;
-
   auto task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>(
       base::Time::Now(), base::TimeTicks::Now());
   auto authenticator = ConstructAuthenticatorWithTimer(task_runner);
   device::test::ScopedVirtualFidoDevice virtual_device;
+  // Inject credential ID to the virtual device so that successful sign in is
+  // possible.
+  ASSERT_TRUE(virtual_device.mutable_state()->InjectRegistration(
+      options->allow_credentials[0]->id, kTestRelyingPartyId));
+
   authenticator->GetAssertion(std::move(options), callback_receiver.callback());
 
   // Trigger timer.
-  base::RunLoop().RunUntilIdle();
-  task_runner->FastForwardBy(base::TimeDelta::FromMinutes(1));
   callback_receiver.WaitForCallback();
-  EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR, callback_receiver.status());
-}
-
-TEST_F(AuthenticatorImplTest, Ctap2AcceptsEmptyAllowCredentials) {
-  base::test::ScopedFeatureList scoped_feature_list;
-  scoped_feature_list.InitAndEnableFeature(features::kWebAuthCtap2);
-
-  SimulateNavigation(GURL(kTestOrigin1));
-  PublicKeyCredentialRequestOptionsPtr options =
-      GetTestPublicKeyCredentialRequestOptions();
-  options->allow_credentials.clear();
-  TestGetAssertionCallback callback_receiver;
-
-  auto task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>(
-      base::Time::Now(), base::TimeTicks::Now());
-  auto authenticator = ConstructAuthenticatorWithTimer(task_runner);
-  device::test::ScopedVirtualFidoDevice virtual_device;
-  authenticator->GetAssertion(std::move(options), callback_receiver.callback());
-
-  // Trigger timer.
-  base::RunLoop().RunUntilIdle();
-  task_runner->FastForwardBy(base::TimeDelta::FromMinutes(1));
-  callback_receiver.WaitForCallback();
-  // Doesn't error out with EMPTY_ALLOW_CREDENTIALS but continues to a
-  // NOT_ALLOWED_ERROR.
-  EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR, callback_receiver.status());
+  EXPECT_EQ(AuthenticatorStatus::SUCCESS, callback_receiver.status());
 }
 
 TEST_F(AuthenticatorImplTest, GetAssertionWithEmptyAllowCredentials) {
-  device::test::ScopedVirtualFidoDevice scoped_virtual_device;
-  TestServiceManagerContext service_manager_context;
-
   SimulateNavigation(GURL(kTestOrigin1));
-  AuthenticatorPtr authenticator = ConnectToAuthenticator();
   PublicKeyCredentialRequestOptionsPtr options =
       GetTestPublicKeyCredentialRequestOptions();
   options->allow_credentials.clear();
-
   TestGetAssertionCallback callback_receiver;
-  authenticator->GetAssertion(std::move(options), callback_receiver.callback());
-  callback_receiver.WaitForCallback();
 
-  EXPECT_EQ(AuthenticatorStatus::EMPTY_ALLOW_CREDENTIALS,
-            callback_receiver.status());
+  auto task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>(
+      base::Time::Now(), base::TimeTicks::Now());
+  auto authenticator = ConstructAuthenticatorWithTimer(task_runner);
+  device::test::ScopedVirtualFidoDevice virtual_device;
+  authenticator->GetAssertion(std::move(options), callback_receiver.callback());
+
+  // Trigger timer.
+  base::RunLoop().RunUntilIdle();
+  task_runner->FastForwardBy(base::TimeDelta::FromMinutes(1));
+  callback_receiver.WaitForCallback();
+  EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR, callback_receiver.status());
 }
 
 TEST_F(AuthenticatorImplTest, MakeCredentialAlreadyRegistered) {
@@ -968,9 +947,11 @@
   TestServiceManagerContext service_manager_context;
 
   scoped_virtual_device.mutable_state()->simulate_invalid_response = true;
-
   SimulateNavigation(GURL(kTestOrigin1));
-  AuthenticatorPtr authenticator = ConnectToAuthenticator();
+
+  auto task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>(
+      base::Time::Now(), base::TimeTicks::Now());
+  auto authenticator = ConstructAuthenticatorWithTimer(task_runner);
 
   {
     PublicKeyCredentialRequestOptionsPtr options =
@@ -978,8 +959,10 @@
     TestGetAssertionCallback callback_receiver;
     authenticator->GetAssertion(std::move(options),
                                 callback_receiver.callback());
+    // Trigger timer.
+    base::RunLoop().RunUntilIdle();
+    task_runner->FastForwardBy(base::TimeDelta::FromMinutes(1));
     callback_receiver.WaitForCallback();
-
     EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR,
               callback_receiver.status());
   }
@@ -990,8 +973,10 @@
     TestMakeCredentialCallback callback_receiver;
     authenticator->MakeCredential(std::move(options),
                                   callback_receiver.callback());
+    // Trigger timer.
+    base::RunLoop().RunUntilIdle();
+    task_runner->FastForwardBy(base::TimeDelta::FromMinutes(1));
     callback_receiver.WaitForCallback();
-
     EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR,
               callback_receiver.status());
   }
diff --git a/content/browser/webauth/webauth_browsertest.cc b/content/browser/webauth/webauth_browsertest.cc
index 59b558ff..6755800 100644
--- a/content/browser/webauth/webauth_browsertest.cc
+++ b/content/browser/webauth/webauth_browsertest.cc
@@ -26,6 +26,7 @@
 #include "content/public/test/content_browser_test_utils.h"
 #include "content/shell/browser/shell.h"
 #include "content/test/did_commit_provisional_load_interceptor.h"
+#include "device/base/features.h"
 #include "device/fido/fake_fido_discovery.h"
 #include "device/fido/fake_hid_impl_for_testing.h"
 #include "device/fido/fido_test_data.h"
@@ -57,34 +58,14 @@
     AuthenticatorStatus,
     GetAssertionAuthenticatorResponsePtr>;
 
+constexpr char kTimeoutErrorMessage[] =
+    "NotAllowedError: The operation either timed out or was not allowed. See: "
+    "https://w3c.github.io/webauthn/#sec-assertion-privacy.";
+
 constexpr char kRelyingPartySecurityErrorMessage[] =
     "SecurityError: The relying party ID 'localhost' is not a registrable "
     "domain suffix of, nor equal to 'https://www.acme.com";
 
-constexpr char kAlgorithmUnsupportedErrorMessage[] =
-    "NotSupportedError: None of the algorithms specified in "
-    "`pubKeyCredParams` are compatible with "
-    "CTAP1/U2F authenticators, and CTAP2 "
-    "authenticators are not yet supported.";
-
-constexpr char kAuthenticatorCriteriaErrorMessage[] =
-    "NotSupportedError: The specified `authenticatorSelection` "
-    "criteria cannot be fulfilled by CTAP1/U2F "
-    "authenticators, and CTAP2 authenticators "
-    "are not yet supported.";
-
-constexpr char kUserVerificationErrorMessage[] =
-    "NotSupportedError: The specified `userVerification` "
-    "requirement cannot be fulfilled by "
-    "CTAP1/U2F authenticators, and CTAP2 "
-    "authenticators are not yet supported.";
-
-constexpr char kEmptyAllowCredentialsErrorMessage[] =
-    "NotSupportedError: The `allowCredentials` list cannot be left "
-    "empty for CTAP1/U2F authenticators, and "
-    "support for CTAP2 authenticators is not yet "
-    "implemented.";
-
 // Templates to be used with base::ReplaceStringPlaceholders. Can be
 // modified to include up to 9 replacements. The default values for
 // any additional replacements added should also be added to the
@@ -99,7 +80,7 @@
     "    displayName: 'Avery A. Jones', "
     "    icon: 'https://pics.acme.com/00/p/aBjjjpqPb.png'},"
     "  pubKeyCredParams: [{ type: 'public-key', alg: '$4'}],"
-    "  timeout: 60000,"
+    "  timeout: 1000,"
     "  excludeCredentials: [],"
     "  authenticatorSelection : {"
     "     requireResidentKey: $1,"
@@ -136,7 +117,7 @@
     "navigator.credentials.get({ publicKey: {"
     "  challenge: new TextEncoder().encode('climb a mountain'),"
     "  rp: 'acme.com',"
-    "  timeout: 60000,"
+    "  timeout: 1000,"
     "  userVerification: '$1',"
     "  $2}"
     "}).catch(c => window.domAutomationController.send(c.toString()));";
@@ -532,33 +513,6 @@
   DISALLOW_COPY_AND_ASSIGN(WebAuthJavascriptClientBrowserTest);
 };
 
-// Tests that when navigator.credentials.create() is called with user
-// verification required we get a NotSupportedError.
-IN_PROC_BROWSER_TEST_F(WebAuthJavascriptClientBrowserTest,
-                       CreatePublicKeyCredentialWithUserVerification) {
-  CreateParameters parameters;
-  parameters.user_verification = kRequiredVerification;
-  std::string result;
-  ASSERT_TRUE(content::ExecuteScriptAndExtractString(
-      shell()->web_contents()->GetMainFrame(),
-      BuildCreateCallWithParameters(parameters), &result));
-  ASSERT_EQ(kAuthenticatorCriteriaErrorMessage, result);
-}
-
-// Tests that when navigator.credentials.create() is called with resident key
-// required, we get a NotSupportedError.
-IN_PROC_BROWSER_TEST_F(WebAuthJavascriptClientBrowserTest,
-                       CreatePublicKeyCredentialWithResidentKeyRequired) {
-  CreateParameters parameters;
-  parameters.require_resident_key = true;
-  std::string result;
-  ASSERT_TRUE(content::ExecuteScriptAndExtractString(
-      shell()->web_contents()->GetMainFrame(),
-      BuildCreateCallWithParameters(parameters), &result));
-
-  ASSERT_EQ(kAuthenticatorCriteriaErrorMessage, result);
-}
-
 // Tests that when navigator.credentials.create() is called with an invalid
 // relying party id, we get a SecurityError.
 IN_PROC_BROWSER_TEST_F(WebAuthJavascriptClientBrowserTest,
@@ -574,8 +528,35 @@
             result.substr(0, strlen(kRelyingPartySecurityErrorMessage)));
 }
 
+// Tests that when navigator.credentials.create() is called with user
+// verification required, request times out.
+IN_PROC_BROWSER_TEST_F(WebAuthJavascriptClientBrowserTest,
+                       CreatePublicKeyCredentialWithUserVerification) {
+  CreateParameters parameters;
+  parameters.user_verification = kRequiredVerification;
+  std::string result;
+  ASSERT_TRUE(content::ExecuteScriptAndExtractString(
+      shell()->web_contents()->GetMainFrame(),
+      BuildCreateCallWithParameters(parameters), &result));
+  ASSERT_EQ(kTimeoutErrorMessage, result);
+}
+
+// Tests that when navigator.credentials.create() is called with resident key
+// required, request times out.
+IN_PROC_BROWSER_TEST_F(WebAuthJavascriptClientBrowserTest,
+                       CreatePublicKeyCredentialWithResidentKeyRequired) {
+  CreateParameters parameters;
+  parameters.require_resident_key = true;
+  std::string result;
+  ASSERT_TRUE(content::ExecuteScriptAndExtractString(
+      shell()->web_contents()->GetMainFrame(),
+      BuildCreateCallWithParameters(parameters), &result));
+
+  ASSERT_EQ(kTimeoutErrorMessage, result);
+}
+
 // Tests that when navigator.credentials.create() is called with an
-// unsupported algorithm, we get a NotSupportedError.
+// unsupported algorithm, request times out.
 IN_PROC_BROWSER_TEST_F(WebAuthJavascriptClientBrowserTest,
                        CreatePublicKeyCredentialAlgorithmNotSupported) {
   CreateParameters parameters;
@@ -585,11 +566,11 @@
       shell()->web_contents()->GetMainFrame(),
       BuildCreateCallWithParameters(parameters), &result));
 
-  ASSERT_EQ(kAlgorithmUnsupportedErrorMessage, result);
+  ASSERT_EQ(kTimeoutErrorMessage, result);
 }
 
 // Tests that when navigator.credentials.create() is called with a
-// platform authenticator requested, we get a NotSupportedError.
+// platform authenticator requested, request times out.
 IN_PROC_BROWSER_TEST_F(WebAuthJavascriptClientBrowserTest,
                        CreatePublicKeyCredentialPlatformAuthenticator) {
   CreateParameters parameters;
@@ -599,7 +580,7 @@
       shell()->web_contents()->GetMainFrame(),
       BuildCreateCallWithParameters(parameters), &result));
 
-  ASSERT_EQ(kAuthenticatorCriteriaErrorMessage, result);
+  ASSERT_EQ(kTimeoutErrorMessage, result);
 }
 
 // Tests that when navigator.credentials.get() is called with user verification
@@ -612,7 +593,7 @@
   ASSERT_TRUE(content::ExecuteScriptAndExtractString(
       shell()->web_contents()->GetMainFrame(),
       BuildGetCallWithParameters(parameters), &result));
-  ASSERT_EQ(kUserVerificationErrorMessage, result);
+  ASSERT_EQ(kTimeoutErrorMessage, result);
 }
 
 // Tests that when navigator.credentials.get() is called with an empty
@@ -625,7 +606,7 @@
   ASSERT_TRUE(content::ExecuteScriptAndExtractString(
       shell()->web_contents()->GetMainFrame(),
       BuildGetCallWithParameters(parameters), &result));
-  ASSERT_EQ(kEmptyAllowCredentialsErrorMessage, result);
+  ASSERT_EQ(kTimeoutErrorMessage, result);
 }
 
 // WebAuthBrowserBleDisabledTest
@@ -671,11 +652,12 @@
 
  protected:
   std::vector<base::Feature> GetFeaturesToEnable() override {
-    return {features::kWebAuth, features::kWebAuthCtap2};
+    return {features::kWebAuth, device::kNewCtap2Device};
   }
 
  private:
   base::test::ScopedFeatureList scoped_feature_list_;
+
   DISALLOW_COPY_AND_ASSIGN(WebAuthBrowserCtapTest);
 };
 
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc
index b718e97b3..fc2d92f 100644
--- a/content/public/common/content_features.cc
+++ b/content/public/common/content_features.cc
@@ -497,11 +497,6 @@
 const base::Feature kWebAuthBle{"WebAuthenticationBle",
                                 base::FEATURE_DISABLED_BY_DEFAULT};
 
-// Controls whether CTAP2 authenticators can be used via the WebAuthentication
-// API. https://w3c.github.io/webauthn
-const base::Feature kWebAuthCtap2{"WebAuthenticationCtap2",
-                                  base::FEATURE_DISABLED_BY_DEFAULT};
-
 // Controls whether CTAP2 devices can communicate via the WebAuthentication API
 // using pairingless BLE protocol.
 // https://w3c.github.io/webauthn
diff --git a/content/public/common/content_features.h b/content/public/common/content_features.h
index 9c5d8f7..a3c4961 100644
--- a/content/public/common/content_features.h
+++ b/content/public/common/content_features.h
@@ -115,7 +115,6 @@
 CONTENT_EXPORT extern const base::Feature kWebAssemblyTrapHandler;
 CONTENT_EXPORT extern const base::Feature kWebAuth;
 CONTENT_EXPORT extern const base::Feature kWebAuthBle;
-CONTENT_EXPORT extern const base::Feature kWebAuthCtap2;
 CONTENT_EXPORT extern const base::Feature kWebAuthCable;
 CONTENT_EXPORT extern const base::Feature kWebContentsOcclusion;
 CONTENT_EXPORT extern const base::Feature kWebGLImageChromium;
diff --git a/content/public/common/content_switches.cc b/content/public/common/content_switches.cc
index aecf483..787d439 100644
--- a/content/public/common/content_switches.cc
+++ b/content/public/common/content_switches.cc
@@ -328,10 +328,6 @@
 const char kEnablePreferCompositingToLCDText[] =
     "enable-prefer-compositing-to-lcd-text";
 
-// Enable work-in-progress persistent storage for the Background Fetch API.
-const char kEnableBackgroundFetchPersistence[] =
-    "enable-background-fetch-persistence";
-
 // Enable one or more Blink runtime-enabled features.
 // Use names from runtime_enabled_features.json5, separated by commas.
 // Applied before kDisableBlinkFeatures, and after other flags that change these
diff --git a/content/public/common/content_switches.h b/content/public/common/content_switches.h
index 245de08..20be0b7 100644
--- a/content/public/common/content_switches.h
+++ b/content/public/common/content_switches.h
@@ -110,7 +110,6 @@
 CONTENT_EXPORT extern const char kEnablePreferCompositingToLCDText[];
 CONTENT_EXPORT extern const char kEnableBlinkFeatures[];
 CONTENT_EXPORT extern const char kEnableBlinkGenPropertyTrees[];
-CONTENT_EXPORT extern const char kEnableBackgroundFetchPersistence[];
 CONTENT_EXPORT extern const char kEnableDisplayList2dCanvas[];
 CONTENT_EXPORT extern const char kEnableExperimentalWebPlatformFeatures[];
 CONTENT_EXPORT extern const char kEnableGpuMemoryBufferCompositorResources[];
diff --git a/content/public/test/content_browser_test_utils_mac.mm b/content/public/test/content_browser_test_utils_mac.mm
index 195a978..4ce99b2 100644
--- a/content/public/test/content_browser_test_utils_mac.mm
+++ b/content/public/test/content_browser_test_utils_mac.mm
@@ -9,8 +9,8 @@
 
 #include <memory>
 
+#include "base/bind.h"
 #include "base/lazy_instance.h"
-#include "base/mac/bind_objc_block.h"
 #include "base/mac/scoped_objc_class_swizzler.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/sys_string_conversions.h"
@@ -132,13 +132,13 @@
         result_callback) {
   TextInputClientMac::GetInstance()->GetStringAtPoint(
       rwh, point,
-      base::BindBlock(
+      base::BindOnce(base::RetainBlock(
           ^(const mac::AttributedStringCoder::EncodedString& encoded_string,
             gfx::Point baseline_point) {
             std::string string = base::SysNSStringToUTF8(
                 [mac::AttributedStringCoder::Decode(&encoded_string) string]);
             result_callback.Run(string, baseline_point);
-          }));
+          })));
 }
 
 void GetStringFromRangeForRenderWidget(
@@ -148,13 +148,13 @@
         result_callback) {
   TextInputClientMac::GetInstance()->GetStringFromRange(
       rwh, range,
-      base::BindBlock(
+      base::BindOnce(base::RetainBlock(
           ^(const mac::AttributedStringCoder::EncodedString& encoded_string,
             gfx::Point baseline_point) {
             std::string string = base::SysNSStringToUTF8(
                 [mac::AttributedStringCoder::Decode(&encoded_string) string]);
             result_callback.Run(string, baseline_point);
-          }));
+          })));
 }
 
 }  // namespace content
diff --git a/content/public/test/web_contents_tester.h b/content/public/test/web_contents_tester.h
index 0e3987a..8cc9d3d4 100644
--- a/content/public/test/web_contents_tester.h
+++ b/content/public/test/web_contents_tester.h
@@ -156,6 +156,9 @@
 
   // Resets the state around PauseSubresourceLoadingCalled.
   virtual void ResetPauseSubresourceLoadingCalled() = 0;
+
+  // Sets the return value of GetPageImportanceSignals().
+  virtual void SetPageImportanceSignals(PageImportanceSignals signals) = 0;
 };
 
 }  // namespace content
diff --git a/content/renderer/loader/web_url_loader_impl.cc b/content/renderer/loader/web_url_loader_impl.cc
index 17555914..8df6963 100644
--- a/content/renderer/loader/web_url_loader_impl.cc
+++ b/content/renderer/loader/web_url_loader_impl.cc
@@ -644,6 +644,7 @@
   resource_request->method = method;
   resource_request->url = url_;
   resource_request->site_for_cookies = request.SiteForCookies();
+  resource_request->upgrade_if_insecure = request.UpgradeIfInsecure();
   resource_request->request_initiator =
       request.RequestorOrigin().IsNull()
           ? base::Optional<url::Origin>()
diff --git a/content/renderer/media/audio/audio_device_factory.cc b/content/renderer/media/audio/audio_device_factory.cc
index 10cd9d10..d20dbe3 100644
--- a/content/renderer/media/audio/audio_device_factory.cc
+++ b/content/renderer/media/audio/audio_device_factory.cc
@@ -8,6 +8,7 @@
 
 #include "base/logging.h"
 #include "base/metrics/histogram_macros.h"
+#include "base/threading/platform_thread.h"
 #include "build/build_config.h"
 #include "content/common/content_constants_internal.h"
 #include "content/common/media/renderer_audio_input_stream_factory.mojom.h"
@@ -168,7 +169,8 @@
 
   return base::MakeRefCounted<media::AudioInputDevice>(
       AudioInputIPCFactory::get()->CreateAudioInputIPC(render_frame_id,
-                                                       session_id));
+                                                       session_id),
+      base::ThreadPriority::REALTIME_AUDIO);
 }
 
 // static
diff --git a/content/renderer/renderer_blink_platform_impl.cc b/content/renderer/renderer_blink_platform_impl.cc
index d400ff6..4deeb37 100644
--- a/content/renderer/renderer_blink_platform_impl.cc
+++ b/content/renderer/renderer_blink_platform_impl.cc
@@ -1022,8 +1022,6 @@
   }
   Collect3DContextInformation(gl_info, gpu_channel_host->gpu_info());
 
-  bool is_software_rendering = gpu_channel_host->gpu_info().software_rendering;
-
   // This is an offscreen context. Generally it won't use the default
   // frame buffer, in that case don't request any alpha, depth, stencil,
   // antialiasing. But we do need those attributes for the "own
@@ -1061,7 +1059,7 @@
           gpu::SharedMemoryLimits(), attributes,
           ui::command_buffer_metrics::OFFSCREEN_CONTEXT_FOR_WEBGL));
   return std::make_unique<WebGraphicsContext3DProviderImpl>(
-      std::move(provider), is_software_rendering);
+      std::move(provider));
 }
 
 //------------------------------------------------------------------------------
@@ -1080,15 +1078,12 @@
   // channel can become lost on the IO thread since then. It is important that
   // this happens after getting |provider|. In the case that this GpuChannelHost
   // is not the same one backing |provider|, the context behind the |provider|
-  // will be already lost/dead on arrival, so the value we get for
-  // |is_software_rendering| will never be wrong.
+  // will be already lost/dead on arrival.
   if (!host)
     return nullptr;
 
-  bool is_software_rendering = host->gpu_info().software_rendering;
-
   return std::make_unique<WebGraphicsContext3DProviderImpl>(
-      std::move(provider), is_software_rendering);
+      std::move(provider));
 }
 
 //------------------------------------------------------------------------------
diff --git a/content/renderer/webgraphicscontext3d_provider_impl.cc b/content/renderer/webgraphicscontext3d_provider_impl.cc
index ad82d6c..f44ed3276 100644
--- a/content/renderer/webgraphicscontext3d_provider_impl.cc
+++ b/content/renderer/webgraphicscontext3d_provider_impl.cc
@@ -12,10 +12,8 @@
 namespace content {
 
 WebGraphicsContext3DProviderImpl::WebGraphicsContext3DProviderImpl(
-    scoped_refptr<ui::ContextProviderCommandBuffer> provider,
-    bool software_rendering)
-    : provider_(std::move(provider)), software_rendering_(software_rendering) {
-}
+    scoped_refptr<ui::ContextProviderCommandBuffer> provider)
+    : provider_(std::move(provider)) {}
 
 WebGraphicsContext3DProviderImpl::~WebGraphicsContext3DProviderImpl() {
   provider_->RemoveObserver(this);
@@ -56,10 +54,6 @@
   return gl_helper_.get();
 }
 
-bool WebGraphicsContext3DProviderImpl::IsSoftwareRendering() const {
-  return software_rendering_;
-}
-
 void WebGraphicsContext3DProviderImpl::SetLostContextCallback(
     base::RepeatingClosure c) {
   context_lost_callback_ = std::move(c);
diff --git a/content/renderer/webgraphicscontext3d_provider_impl.h b/content/renderer/webgraphicscontext3d_provider_impl.h
index 97d65fcd..2894706 100644
--- a/content/renderer/webgraphicscontext3d_provider_impl.h
+++ b/content/renderer/webgraphicscontext3d_provider_impl.h
@@ -36,8 +36,7 @@
       public viz::ContextLostObserver {
  public:
   WebGraphicsContext3DProviderImpl(
-      scoped_refptr<ui::ContextProviderCommandBuffer> provider,
-      bool software_rendering);
+      scoped_refptr<ui::ContextProviderCommandBuffer> provider);
   ~WebGraphicsContext3DProviderImpl() override;
 
   // WebGraphicsContext3DProvider implementation.
@@ -47,7 +46,6 @@
   const gpu::Capabilities& GetCapabilities() const override;
   const gpu::GpuFeatureInfo& GetGpuFeatureInfo() const override;
   viz::GLHelper* GetGLHelper() override;
-  bool IsSoftwareRendering() const override;
   void SetLostContextCallback(base::RepeatingClosure) override;
   void SetErrorMessageCallback(
       base::RepeatingCallback<void(const char*, int32_t)>) override;
@@ -63,7 +61,6 @@
 
   scoped_refptr<ui::ContextProviderCommandBuffer> provider_;
   std::unique_ptr<viz::GLHelper> gl_helper_;
-  const bool software_rendering_;
   base::RepeatingClosure context_lost_callback_;
   std::unique_ptr<cc::ImageDecodeCache> image_decode_cache_;
 
diff --git a/content/shell/tools/breakpad_integration_test.py b/content/shell/tools/breakpad_integration_test.py
index 7b4307e..54629ed 100755
--- a/content/shell/tools/breakpad_integration_test.py
+++ b/content/shell/tools/breakpad_integration_test.py
@@ -22,10 +22,12 @@
 
 
 CONCURRENT_TASKS=4
+BREAKPAD_TOOLS_DIR = os.path.join(
+  os.path.dirname(__file__), '..', '..', '..',
+  'components', 'crash', 'content', 'tools')
 
-def run_test(options, crash_dir, additional_arguments = []):
+def run_test(options, crash_dir, symbols_dir, additional_arguments = []):
   global failure
-  global breakpad_tools_dir
 
   print "# Run content_shell and make it crash."
   cmd = [options.binary,
@@ -61,7 +63,7 @@
 
   if sys.platform not in ('darwin', 'win32'):
     minidump = os.path.join(crash_dir, 'minidump')
-    dmp_to_minidump = os.path.join(breakpad_tools_dir, 'dmp2minidump.py')
+    dmp_to_minidump = os.path.join(BREAKPAD_TOOLS_DIR, 'dmp2minidump.py')
     cmd = [dmp_to_minidump, dmp_file, minidump]
     if options.verbose:
       print ' '.join(cmd)
@@ -83,7 +85,6 @@
     stack = proc.communicate()[0]
   else:
     minidump_stackwalk = os.path.join(options.build_dir, 'minidump_stackwalk')
-    global symbols_dir
     cmd = [minidump_stackwalk, minidump, symbols_dir]
     if options.verbose:
       print ' '.join(cmd)
@@ -112,7 +113,6 @@
 
 def main():
   global failure
-  global breakpad_tools_dir
 
   parser = optparse.OptionParser()
   parser.add_option('', '--build-dir', default='',
@@ -146,19 +146,15 @@
 
   # Create a temporary directory to store the crash dumps and symbols in.
   crash_dir = tempfile.mkdtemp()
+  symbols_dir = os.path.join(crash_dir, 'symbols')
 
   crash_service = None
 
   try:
     if sys.platform != 'win32':
       print "# Generate symbols."
-      global symbols_dir
-      breakpad_tools_dir = os.path.join(
-          os.path.dirname(__file__), '..', '..', '..',
-          'components', 'crash', 'content', 'tools')
       generate_symbols = os.path.join(
-          breakpad_tools_dir, 'generate_breakpad_symbols.py')
-      symbols_dir = os.path.join(crash_dir, 'symbols')
+          BREAKPAD_TOOLS_DIR, 'generate_breakpad_symbols.py')
       cmd = [generate_symbols,
              '--build-dir=%s' % options.build_dir,
              '--binary=%s' % options.binary,
@@ -171,11 +167,11 @@
       subprocess.check_call(cmd)
 
     print "# Running test without trap handler."
-    run_test(options, crash_dir);
+    run_test(options, crash_dir, symbols_dir)
     print "# Running test with trap handler."
-    run_test(options, crash_dir,
+    run_test(options, crash_dir, symbols_dir,
              additional_arguments =
-               ['--enable-features=WebAssemblyTrapHandler']);
+               ['--enable-features=WebAssemblyTrapHandler'])
 
   except:
     print "FAIL: %s" % failure
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index b1b1904..8d9ed40 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -1105,6 +1105,7 @@
   if (!is_linux_without_udev && !is_android) {
     sources += [ "../browser/webauth/webauth_browsertest.cc" ]
     deps += [
+      "//device/base",
       "//device/fido:mocks",
       "//device/fido:test_support",
     ]
@@ -2027,7 +2028,10 @@
   is_linux_without_udev = is_linux && !use_udev
   if (!is_linux_without_udev && !is_android) {
     sources += [ "../browser/webauth/authenticator_impl_unittest.cc" ]
-    deps += [ "//device/fido:test_support" ]
+    deps += [
+      "//device/base",
+      "//device/fido:test_support",
+    ]
   }
 
   if (use_aura) {
diff --git a/content/test/test_web_contents.cc b/content/test/test_web_contents.cc
index 59f3c60..2415c51 100644
--- a/content/test/test_web_contents.cc
+++ b/content/test/test_web_contents.cc
@@ -449,4 +449,8 @@
   pause_subresource_loading_called_ = false;
 }
 
+void TestWebContents::SetPageImportanceSignals(PageImportanceSignals signals) {
+  page_importance_signals_ = signals;
+}
+
 }  // namespace content
diff --git a/content/test/test_web_contents.h b/content/test/test_web_contents.h
index c1a6e1a..6549f0fb 100644
--- a/content/test/test_web_contents.h
+++ b/content/test/test_web_contents.h
@@ -150,6 +150,8 @@
 
   void TestDidFinishLoad(const GURL& url);
 
+  void SetPageImportanceSignals(PageImportanceSignals signals) override;
+
  protected:
   // The deprecated WebContentsTester still needs to subclass this.
   explicit TestWebContents(BrowserContext* browser_context);
diff --git a/device/BUILD.gn b/device/BUILD.gn
index ac519c7..9e8f812 100644
--- a/device/BUILD.gn
+++ b/device/BUILD.gn
@@ -85,9 +85,8 @@
     "fido/make_credential_task_unittest.cc",
     "fido/test_callback_receiver_unittest.cc",
     "fido/u2f_command_constructor_unittest.cc",
-    "fido/u2f_register_unittest.cc",
-    "fido/u2f_request_unittest.cc",
-    "fido/u2f_sign_unittest.cc",
+    "fido/u2f_register_operation_unittest.cc",
+    "fido/u2f_sign_operation_unittest.cc",
     "gamepad/abstract_haptic_gamepad_unittest.cc",
     "gamepad/gamepad_provider_unittest.cc",
     "gamepad/gamepad_service_unittest.cc",
diff --git a/device/base/features.cc b/device/base/features.cc
index b38d28d..6035bdb6 100644
--- a/device/base/features.cc
+++ b/device/base/features.cc
@@ -21,4 +21,7 @@
                                    base::FEATURE_DISABLED_BY_DEFAULT};
 #endif  // defined(OS_LINUX) || defined(OS_CHROMEOS)
 
+const base::Feature kNewCtap2Device{"WebAuthenticationCtap2",
+                                    base::FEATURE_DISABLED_BY_DEFAULT};
+
 }  // namespace device
diff --git a/device/base/features.h b/device/base/features.h
index c25697a0..5ff764e5 100644
--- a/device/base/features.h
+++ b/device/base/features.h
@@ -20,6 +20,8 @@
 DEVICE_BASE_EXPORT extern const base::Feature kNewblueDaemon;
 #endif  // defined(OS_LINUX) || defined(OS_CHROMEOS)
 
+DEVICE_BASE_EXPORT extern const base::Feature kNewCtap2Device;
+
 }  // namespace device
 
 #endif  // DEVICE_BASE_FEATURES_H_
diff --git a/device/fido/BUILD.gn b/device/fido/BUILD.gn
index 9e74e474..03964bfc 100644
--- a/device/fido/BUILD.gn
+++ b/device/fido/BUILD.gn
@@ -25,14 +25,13 @@
     "authenticator_selection_criteria.h",
     "authenticator_supported_options.cc",
     "authenticator_supported_options.h",
+    "ctap2_device_operation.h",
     "ctap_empty_authenticator_request.cc",
     "ctap_empty_authenticator_request.h",
     "ctap_get_assertion_request.cc",
     "ctap_get_assertion_request.h",
     "ctap_make_credential_request.cc",
     "ctap_make_credential_request.h",
-    "ctap_register_operation.cc",
-    "ctap_register_operation.h",
     "device_operation.h",
     "device_response_converter.cc",
     "device_response_converter.h",
@@ -105,12 +104,10 @@
     "response_data.h",
     "u2f_command_constructor.cc",
     "u2f_command_constructor.h",
-    "u2f_register.cc",
-    "u2f_register.h",
-    "u2f_request.cc",
-    "u2f_request.h",
-    "u2f_sign.cc",
-    "u2f_sign.h",
+    "u2f_register_operation.cc",
+    "u2f_register_operation.h",
+    "u2f_sign_operation.cc",
+    "u2f_sign_operation.h",
     "virtual_fido_device.cc",
     "virtual_fido_device.h",
     "virtual_u2f_device.cc",
diff --git a/device/fido/ctap2_device_operation.h b/device/fido/ctap2_device_operation.h
new file mode 100644
index 0000000..1cba8f9
--- /dev/null
+++ b/device/fido/ctap2_device_operation.h
@@ -0,0 +1,79 @@
+// 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 DEVICE_FIDO_CTAP2_DEVICE_OPERATION_H_
+#define DEVICE_FIDO_CTAP2_DEVICE_OPERATION_H_
+
+#include <stdint.h>
+
+#include <utility>
+#include <vector>
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/containers/span.h"
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "base/optional.h"
+#include "device/fido/device_operation.h"
+#include "device/fido/device_response_converter.h"
+#include "device/fido/fido_constants.h"
+#include "device/fido/fido_device.h"
+
+namespace device {
+
+// Represents per device logic for CTAP2 authenticators. Ctap2DeviceOperation
+// is owned by FidoTask, and thus |request| outlives Ctap2DeviceOperation.
+template <class Request, class Response>
+class Ctap2DeviceOperation : public DeviceOperation<Request, Response> {
+ public:
+  using DeviceResponseCallback =
+      base::OnceCallback<void(CtapDeviceResponseCode,
+                              base::Optional<Response>)>;
+  using DeviceResponseParser =
+      base::OnceCallback<base::Optional<Response>(base::span<const uint8_t>)>;
+
+  Ctap2DeviceOperation(FidoDevice* device,
+                       const Request& request,
+                       DeviceResponseCallback callback,
+                       DeviceResponseParser device_response_parser)
+      : DeviceOperation<Request, Response>(device,
+                                           request,
+                                           std::move(callback)),
+        device_response_parser_(std::move(device_response_parser)),
+        weak_factory_(this) {}
+
+  ~Ctap2DeviceOperation() override = default;
+
+  void Start() override {
+    this->device()->DeviceTransact(
+        this->request().EncodeAsCBOR(),
+        base::BindOnce(&Ctap2DeviceOperation::OnResponseReceived,
+                       weak_factory_.GetWeakPtr()));
+  }
+
+  void OnResponseReceived(
+      base::Optional<std::vector<uint8_t>> device_response) {
+    if (!device_response) {
+      std::move(this->callback())
+          .Run(CtapDeviceResponseCode::kCtap2ErrOther, base::nullopt);
+      return;
+    }
+
+    const auto response_code = GetResponseCode(*device_response);
+    std::move(this->callback())
+        .Run(response_code, std::move(device_response_parser_)
+                                .Run(std::move(*device_response)));
+  }
+
+ private:
+  DeviceResponseParser device_response_parser_;
+  base::WeakPtrFactory<Ctap2DeviceOperation> weak_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(Ctap2DeviceOperation);
+};
+
+}  // namespace device
+
+#endif  // DEVICE_FIDO_CTAP2_DEVICE_OPERATION_H_
diff --git a/device/fido/ctap_get_assertion_request.cc b/device/fido/ctap_get_assertion_request.cc
index 8fb876ad..6b0f58bd 100644
--- a/device/fido/ctap_get_assertion_request.cc
+++ b/device/fido/ctap_get_assertion_request.cc
@@ -118,4 +118,12 @@
   return *this;
 }
 
+CtapGetAssertionRequest&
+CtapGetAssertionRequest::SetAlternativeApplicationParameter(
+    std::vector<uint8_t> alternative_application_parameter) {
+  alternative_application_parameter_ =
+      std::move(alternative_application_parameter);
+  return *this;
+}
+
 }  // namespace device
diff --git a/device/fido/ctap_get_assertion_request.h b/device/fido/ctap_get_assertion_request.h
index 25ee8a6..c2cb632 100644
--- a/device/fido/ctap_get_assertion_request.h
+++ b/device/fido/ctap_get_assertion_request.h
@@ -46,6 +46,8 @@
   CtapGetAssertionRequest& SetPinProtocol(uint8_t pin_protocol);
   CtapGetAssertionRequest& SetCableExtension(
       std::vector<FidoCableDiscovery::CableDiscoveryData> cable_extension);
+  CtapGetAssertionRequest& SetAlternativeApplicationParameter(
+      std::vector<uint8_t> alternative_application_parameter);
 
   const std::string& rp_id() const { return rp_id_; }
   const std::vector<uint8_t>& client_data_hash() const {
@@ -71,6 +73,10 @@
   cable_extension() const {
     return cable_extension_;
   }
+  const base::Optional<std::vector<uint8_t>>&
+  alternative_application_parameter() const {
+    return alternative_application_parameter_;
+  }
 
  private:
   std::string rp_id_;
@@ -84,6 +90,7 @@
   base::Optional<uint8_t> pin_protocol_;
   base::Optional<std::vector<FidoCableDiscovery::CableDiscoveryData>>
       cable_extension_;
+  base::Optional<std::vector<uint8_t>> alternative_application_parameter_;
 };
 
 }  // namespace device
diff --git a/device/fido/ctap_make_credential_request.cc b/device/fido/ctap_make_credential_request.cc
index 5b8049d..d6704a4 100644
--- a/device/fido/ctap_make_credential_request.cc
+++ b/device/fido/ctap_make_credential_request.cc
@@ -118,4 +118,11 @@
   return *this;
 }
 
+CtapMakeCredentialRequest&
+CtapMakeCredentialRequest::SetIsIndividualAttestation(
+    bool is_individual_attestation) {
+  is_individual_attestation_ = is_individual_attestation;
+  return *this;
+}
+
 }  // namespace device
diff --git a/device/fido/ctap_make_credential_request.h b/device/fido/ctap_make_credential_request.h
index 2e47e85..18d2f0e 100644
--- a/device/fido/ctap_make_credential_request.h
+++ b/device/fido/ctap_make_credential_request.h
@@ -48,6 +48,8 @@
       std::vector<PublicKeyCredentialDescriptor> exclude_list);
   CtapMakeCredentialRequest& SetPinAuth(std::vector<uint8_t> pin_auth);
   CtapMakeCredentialRequest& SetPinProtocol(uint8_t pin_protocol);
+  CtapMakeCredentialRequest& SetIsIndividualAttestation(
+      bool is_individual_attestation);
 
   const std::vector<uint8_t>& client_data_hash() const {
     return client_data_hash_;
@@ -61,6 +63,7 @@
     return user_verification_required_;
   }
   bool resident_key_supported() const { return resident_key_supported_; }
+  bool is_individual_attestation() const { return is_individual_attestation_; }
   const base::Optional<std::vector<PublicKeyCredentialDescriptor>>&
   exclude_list() const {
     return exclude_list_;
@@ -73,6 +76,7 @@
   PublicKeyCredentialParams public_key_credential_params_;
   bool user_verification_required_ = false;
   bool resident_key_supported_ = false;
+  bool is_individual_attestation_ = false;
 
   base::Optional<std::vector<PublicKeyCredentialDescriptor>> exclude_list_;
   base::Optional<std::vector<uint8_t>> pin_auth_;
diff --git a/device/fido/ctap_register_operation.cc b/device/fido/ctap_register_operation.cc
deleted file mode 100644
index c2776cff..0000000
--- a/device/fido/ctap_register_operation.cc
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "device/fido/ctap_register_operation.h"
-
-#include <utility>
-
-#include "base/bind.h"
-#include "device/fido/authenticator_make_credential_response.h"
-#include "device/fido/ctap_make_credential_request.h"
-#include "device/fido/device_response_converter.h"
-#include "device/fido/fido_device.h"
-
-namespace device {
-
-CtapRegisterOperation::CtapRegisterOperation(
-    FidoDevice* device,
-    const CtapMakeCredentialRequest* request,
-    DeviceResponseCallback callback)
-    : DeviceOperation(device, std::move(callback)),
-      request_(request),
-      weak_factory_(this) {}
-
-CtapRegisterOperation::~CtapRegisterOperation() = default;
-
-void CtapRegisterOperation::Start() {
-  device_->DeviceTransact(
-      request_->EncodeAsCBOR(),
-      base::BindOnce(&CtapRegisterOperation::OnResponseReceived,
-                     weak_factory_.GetWeakPtr()));
-}
-
-void CtapRegisterOperation::OnResponseReceived(
-    base::Optional<std::vector<uint8_t>> device_response) {
-  if (!device_response) {
-    std::move(callback_).Run(CtapDeviceResponseCode::kCtap2ErrOther,
-                             base::nullopt);
-    return;
-  }
-
-  std::move(callback_).Run(GetResponseCode(*device_response),
-                           ReadCTAPMakeCredentialResponse(*device_response));
-}
-
-}  // namespace device
diff --git a/device/fido/ctap_register_operation.h b/device/fido/ctap_register_operation.h
deleted file mode 100644
index b188d18..0000000
--- a/device/fido/ctap_register_operation.h
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef DEVICE_FIDO_CTAP_REGISTER_OPERATION_H_
-#define DEVICE_FIDO_CTAP_REGISTER_OPERATION_H_
-
-#include <stdint.h>
-
-#include <memory>
-#include <vector>
-
-#include "base/callback.h"
-#include "base/component_export.h"
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
-#include "device/fido/device_operation.h"
-#include "device/fido/fido_constants.h"
-
-namespace device {
-
-class FidoDevice;
-class CtapMakeCredentialRequest;
-class AuthenticatorMakeCredentialResponse;
-
-// Represents per device registration logic for CTAP device.
-// CtapRegisterOperation is owned by MakeCredentialTask, and the lifetime of
-// CtapRegisterOperation does not exceed that of MakeCredentialTask. As so,
-// |request_| member variable is dependency injected from MakeCredentialTask.
-class COMPONENT_EXPORT(DEVICE_FIDO) CtapRegisterOperation
-    : public DeviceOperation<CtapMakeCredentialRequest,
-                             AuthenticatorMakeCredentialResponse> {
- public:
-  CtapRegisterOperation(FidoDevice* device,
-                        const CtapMakeCredentialRequest* request,
-                        DeviceResponseCallback callback);
-
-  ~CtapRegisterOperation() override;
-
-  // DeviceOperation:
-  void Start() override;
-
- private:
-  void OnResponseReceived(base::Optional<std::vector<uint8_t>> device_response);
-
-  const CtapMakeCredentialRequest* const request_;
-
-  base::WeakPtrFactory<CtapRegisterOperation> weak_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(CtapRegisterOperation);
-};
-
-}  // namespace device
-
-#endif  // DEVICE_FIDO_CTAP_REGISTER_OPERATION_H_
diff --git a/device/fido/device_operation.h b/device/fido/device_operation.h
index 8d4b57a..79b907b 100644
--- a/device/fido/device_operation.h
+++ b/device/fido/device_operation.h
@@ -10,12 +10,9 @@
 #include <utility>
 #include <vector>
 
+#include "base/callback.h"
 #include "base/macros.h"
 #include "base/optional.h"
-#include "device/fido/authenticator_get_assertion_response.h"
-#include "device/fido/authenticator_make_credential_response.h"
-#include "device/fido/ctap_get_assertion_request.h"
-#include "device/fido/ctap_make_credential_request.h"
 #include "device/fido/fido_constants.h"
 #include "device/fido/fido_device.h"
 
@@ -27,15 +24,36 @@
   using DeviceResponseCallback =
       base::OnceCallback<void(CtapDeviceResponseCode,
                               base::Optional<Response>)>;
+  // Represents a per device logic that is owned by FidoTask. Thus,
+  // DeviceOperation does not outlive |request|.
+  DeviceOperation(FidoDevice* device,
+                  const Request& request,
+                  DeviceResponseCallback callback)
+      : device_(device), request_(request), callback_(std::move(callback)) {}
 
-  DeviceOperation(FidoDevice* device, DeviceResponseCallback callback)
-      : device_(device), callback_(std::move(callback)) {}
   virtual ~DeviceOperation() = default;
 
   virtual void Start() = 0;
 
  protected:
+  // TODO(hongjunchoi): Refactor so that |command| is never base::nullopt.
+  void DispatchDeviceRequest(base::Optional<std::vector<uint8_t>> command,
+                             FidoDevice::DeviceCallback callback) {
+    if (!command) {
+      std::move(callback).Run(base::nullopt);
+      return;
+    }
+
+    device_->DeviceTransact(std::move(*command), std::move(callback));
+  }
+
+  const Request& request() const { return request_; }
+  FidoDevice* device() const { return device_; }
+  DeviceResponseCallback callback() { return std::move(callback_); }
+
+ private:
   FidoDevice* const device_ = nullptr;
+  const Request& request_;
   DeviceResponseCallback callback_;
 
   DISALLOW_COPY_AND_ASSIGN(DeviceOperation);
diff --git a/device/fido/fido_constants.cc b/device/fido/fido_constants.cc
index 4c61c7e..7491d7e 100644
--- a/device/fido/fido_constants.cc
+++ b/device/fido/fido_constants.cc
@@ -44,6 +44,7 @@
 const size_t kU2fParameterLength = 32;
 
 const base::TimeDelta kDeviceTimeout = base::TimeDelta::FromSeconds(3);
+const base::TimeDelta kU2fRetryDelay = base::TimeDelta::FromMilliseconds(200);
 const base::TimeDelta kHidKeepAliveDelay =
     base::TimeDelta::FromMilliseconds(100);
 
diff --git a/device/fido/fido_constants.h b/device/fido/fido_constants.h
index 2d404065..5c2cb19 100644
--- a/device/fido/fido_constants.h
+++ b/device/fido/fido_constants.h
@@ -277,6 +277,10 @@
 // Maximum wait time before client error outs on device.
 COMPONENT_EXPORT(DEVICE_FIDO) extern const base::TimeDelta kDeviceTimeout;
 
+// Wait time before polling device for U2F register/sign operation again when
+// device times out waiting for user presence.
+COMPONENT_EXPORT(DEVICE_FIDO) extern const base::TimeDelta kU2fRetryDelay;
+
 // Interval wait time before retrying reading on HID connection when
 // CTAPHID_KEEPALIVE message has been received.
 // https://fidoalliance.org/specs/fido-v2.0-rd-20170927/fido-client-to-authenticator-protocol-v2.0-rd-20170927.html#ctaphid_keepalive-0x3b
diff --git a/device/fido/fido_request_handler.h b/device/fido/fido_request_handler.h
index a81327c..9f811ff9 100644
--- a/device/fido/fido_request_handler.h
+++ b/device/fido/fido_request_handler.h
@@ -85,6 +85,8 @@
       // authenticator.
       case CtapDeviceResponseCode::kCtap2ErrCredentialExcluded:
         return FidoReturnCode::kUserConsentButCredentialExcluded;
+      case CtapDeviceResponseCode::kCtap2ErrInvalidCredential:
+      case CtapDeviceResponseCode::kCtap2ErrCredentialNotValid:
       case CtapDeviceResponseCode::kCtap2ErrNoCredentials:
         return FidoReturnCode::kUserConsentButCredentialNotRecognized;
       default:
diff --git a/device/fido/fido_request_handler_base.h b/device/fido/fido_request_handler_base.h
index 65e494a..78a7cb3c 100644
--- a/device/fido/fido_request_handler_base.h
+++ b/device/fido/fido_request_handler_base.h
@@ -40,6 +40,8 @@
   using AuthenticatorMap =
       std::map<std::string, std::unique_ptr<FidoAuthenticator>, std::less<>>;
 
+  // TODO(https://crbug.com/769631): Remove the dependency on Connector once
+  // device/fido is servicified.
   FidoRequestHandlerBase(
       service_manager::Connector* connector,
       const base::flat_set<FidoTransportProtocol>& transports);
diff --git a/device/fido/fido_task.cc b/device/fido/fido_task.cc
index 4c3138d..09e48f1 100644
--- a/device/fido/fido_task.cc
+++ b/device/fido/fido_task.cc
@@ -32,6 +32,9 @@
 
 void FidoTask::GetAuthenticatorInfo(base::OnceClosure ctap_callback,
                                     base::OnceClosure u2f_callback) {
+  // When AuthenticatorInfo command is sent to authenticators, we first assume
+  // that the connected device is a CTAP2 device.
+  device_->set_supported_protocol(ProtocolVersion::kCtap);
   device()->DeviceTransact(
       AuthenticatorGetInfoRequest().Serialize(),
       base::BindOnce(&FidoTask::OnAuthenticatorInfoReceived,
@@ -47,13 +50,11 @@
 
   base::Optional<AuthenticatorGetInfoResponse> get_info_response;
   if (!response || !(get_info_response = ReadCTAPGetInfoResponse(*response))) {
-    device()->set_supported_protocol(ProtocolVersion::kU2f);
     std::move(u2f_callback).Run();
     return;
   }
 
   device()->SetDeviceInfo(std::move(*get_info_response));
-  device()->set_supported_protocol(ProtocolVersion::kCtap);
   std::move(ctap_callback).Run();
 }
 
diff --git a/device/fido/fido_test_data.h b/device/fido/fido_test_data.h
index 644c0df..15ad9f5 100644
--- a/device/fido/fido_test_data.h
+++ b/device/fido/fido_test_data.h
@@ -14,6 +14,8 @@
 
 namespace test_data {
 
+// U2F request parameters ------------------------------------------------------
+
 // Sample U2F register request parameters used in example 6 of the CTAP spec.
 // https://fidoalliance.org/specs/fido-v2.0-rd-20170927/fido-client-to-authenticator-protocol-v2.0-rd-20170927.html#using-the-ctap2-authenticatormakecredential-command-with-ctap1-u2f-authenticators
 constexpr uint8_t kChallengeParameter[] = {
@@ -28,6 +30,12 @@
     0x7B, 0xCF, 0x01, 0x3D, 0xE9, 0x6D, 0x4E, 0xFB, 0x17, 0xDE,
 };
 
+constexpr uint8_t kAlternativeApplicationParameter[] = {
+    0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03,
+    0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02,
+    0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04,
+};
+
 constexpr uint8_t kClientDataHash[] = {
     0x68, 0x71, 0x34, 0x96, 0x82, 0x22, 0xec, 0x17, 0x20, 0x2e, 0x42,
     0x50, 0x5f, 0x8e, 0xd2, 0xb1, 0x6a, 0xe2, 0x2f, 0x16, 0xbb, 0x05,
@@ -275,6 +283,59 @@
     0x00, 0x00,
 };
 
+constexpr uint8_t kU2fSignCommandApduWithAlternativeApplicationParameter[] = {
+    // CLA, INS, P1, P2 APDU instruction parameters
+    0x00, 0x02, 0x03, 0x00,
+    // Data Length (3 bytes in big endian order)
+    0x00, 0x00, 0x81,
+    // Challenge parameter
+    0x68, 0x71, 0x34, 0x96, 0x82, 0x22, 0xEC, 0x17, 0x20, 0x2E, 0x42, 0x50,
+    0x5F, 0x8E, 0xD2, 0xB1, 0x6A, 0xE2, 0x2F, 0x16, 0xBB, 0x05, 0xB8, 0x8C,
+    0x25, 0xDB, 0x9E, 0x60, 0x26, 0x45, 0xF1, 0x41,
+    // Alternative application parameter
+    0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04,
+    0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04,
+    0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04,
+    // Key handle length
+    0x40,
+    // Key handle
+    0x3E, 0xBD, 0x89, 0xBF, 0x77, 0xEC, 0x50, 0x97, 0x55, 0xEE, 0x9C, 0x26,
+    0x35, 0xEF, 0xAA, 0xAC, 0x7B, 0x2B, 0x9C, 0x5C, 0xEF, 0x17, 0x36, 0xC3,
+    0x71, 0x7D, 0xA4, 0x85, 0x34, 0xC8, 0xC6, 0xB6, 0x54, 0xD7, 0xFF, 0x94,
+    0x5F, 0x50, 0xB5, 0xCC, 0x4E, 0x78, 0x05, 0x5B, 0xDD, 0x39, 0x6B, 0x64,
+    0xF7, 0x8D, 0xA2, 0xC5, 0xF9, 0x62, 0x00, 0xCC, 0xD4, 0x15, 0xCD, 0x08,
+    0xFE, 0x42, 0x00, 0x38,
+    // Max response length
+    0x00, 0x00,
+};
+
+constexpr uint8_t
+    kU2fCheckOnlySignCommandApduWithAlternativeApplicationParameter[] = {
+        // CLA, INS, P1, P2 APDU instruction parameters
+        0x00, 0x02, 0x07, 0x00,
+        // Data Length (3 bytes in big endian order).
+        0x00, 0x00, 0x81,
+        // Challenge parameter
+        0x68, 0x71, 0x34, 0x96, 0x82, 0x22, 0xEC, 0x17, 0x20, 0x2E, 0x42, 0x50,
+        0x5F, 0x8E, 0xD2, 0xB1, 0x6A, 0xE2, 0x2F, 0x16, 0xBB, 0x05, 0xB8, 0x8C,
+        0x25, 0xDB, 0x9E, 0x60, 0x26, 0x45, 0xF1, 0x41,
+        // Alternative application parameter
+        0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04,
+        0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04,
+        0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04,
+        // Key handle length
+        0x40,
+        // Key handle
+        0x3E, 0xBD, 0x89, 0xBF, 0x77, 0xEC, 0x50, 0x97, 0x55, 0xEE, 0x9C, 0x26,
+        0x35, 0xEF, 0xAA, 0xAC, 0x7B, 0x2B, 0x9C, 0x5C, 0xEF, 0x17, 0x36, 0xC3,
+        0x71, 0x7D, 0xA4, 0x85, 0x34, 0xC8, 0xC6, 0xB6, 0x54, 0xD7, 0xFF, 0x94,
+        0x5F, 0x50, 0xB5, 0xCC, 0x4E, 0x78, 0x05, 0x5B, 0xDD, 0x39, 0x6B, 0x64,
+        0xF7, 0x8D, 0xA2, 0xC5, 0xF9, 0x62, 0x00, 0xCC, 0xD4, 0x15, 0xCD, 0x08,
+        0xFE, 0x42, 0x00, 0x38,
+        // Max response length
+        0x00, 0x00,
+};
+
 // Encoded U2fSign command excluding key handle length and key handle. Precise
 // key handle length and key handle shall be added based on different testing
 // scenarios.
@@ -310,6 +371,109 @@
     0x00, 0x00,
 };
 
+// U2F responses ---------------------------------------------------------------
+
+constexpr uint8_t kU2fConditionNotSatisfiedApduResponse[] = {0x69, 0x85};
+
+constexpr uint8_t kU2fWrongDataApduResponse[] = {0x6A, 0x80};
+
+constexpr uint8_t kApduEncodedNoErrorRegisterResponse[] = {
+    // Reserved byte
+    0x05,
+    // User public key
+    0x04, 0xE8, 0x76, 0x25, 0x89, 0x6E, 0xE4, 0xE4, 0x6D, 0xC0, 0x32, 0x76,
+    0x6E, 0x80, 0x87, 0x96, 0x2F, 0x36, 0xDF, 0x9D, 0xFE, 0x8B, 0x56, 0x7F,
+    0x37, 0x63, 0x01, 0x5B, 0x19, 0x90, 0xA6, 0x0E, 0x14, 0x27, 0xDE, 0x61,
+    0x2D, 0x66, 0x41, 0x8B, 0xDA, 0x19, 0x50, 0x58, 0x1E, 0xBC, 0x5C, 0x8C,
+    0x1D, 0xAD, 0x71, 0x0C, 0xB1, 0x4C, 0x22, 0xF8, 0xC9, 0x70, 0x45, 0xF4,
+    0x61, 0x2F, 0xB2, 0x0C, 0x91,
+    // Key handle length
+    0x40,
+    // Key handle
+    0x3E, 0xBD, 0x89, 0xBF, 0x77, 0xEC, 0x50, 0x97, 0x55, 0xEE, 0x9C, 0x26,
+    0x35, 0xEF, 0xAA, 0xAC, 0x7B, 0x2B, 0x9C, 0x5C, 0xEF, 0x17, 0x36, 0xC3,
+    0x71, 0x7D, 0xA4, 0x85, 0x34, 0xC8, 0xC6, 0xB6, 0x54, 0xD7, 0xFF, 0x94,
+    0x5F, 0x50, 0xB5, 0xCC, 0x4E, 0x78, 0x05, 0x5B, 0xDD, 0x39, 0x6B, 0x64,
+    0xF7, 0x8D, 0xA2, 0xC5, 0xF9, 0x62, 0x00, 0xCC, 0xD4, 0x15, 0xCD, 0x08,
+    0xFE, 0x42,
+    // X.509 Certificate
+    0x00, 0x38, 0x30, 0x82, 0x02, 0x4A, 0x30, 0x82, 0x01, 0x32, 0xA0, 0x03,
+    0x02, 0x01, 0x02, 0x02, 0x04, 0x04, 0x6C, 0x88, 0x22, 0x30, 0x0D, 0x06,
+    0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00,
+    0x30, 0x2E, 0x31, 0x2C, 0x30, 0x2A, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
+    0x23, 0x59, 0x75, 0x62, 0x69, 0x63, 0x6F, 0x20, 0x55, 0x32, 0x46, 0x20,
+    0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, 0x20, 0x53, 0x65, 0x72, 0x69,
+    0x61, 0x6C, 0x20, 0x34, 0x35, 0x37, 0x32, 0x30, 0x30, 0x36, 0x33, 0x31,
+    0x30, 0x20, 0x17, 0x0D, 0x31, 0x34, 0x30, 0x38, 0x30, 0x31, 0x30, 0x30,
+    0x30, 0x30, 0x30, 0x30, 0x5A, 0x18, 0x0F, 0x32, 0x30, 0x35, 0x30, 0x30,
+    0x39, 0x30, 0x34, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5A, 0x30, 0x2C,
+    0x31, 0x2A, 0x30, 0x28, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x21, 0x59,
+    0x75, 0x62, 0x69, 0x63, 0x6F, 0x20, 0x55, 0x32, 0x46, 0x20, 0x45, 0x45,
+    0x20, 0x53, 0x65, 0x72, 0x69, 0x61, 0x6C, 0x20, 0x32, 0x34, 0x39, 0x31,
+    0x38, 0x32, 0x33, 0x32, 0x34, 0x37, 0x37, 0x30, 0x30, 0x59, 0x30, 0x13,
+    0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A,
+    0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x3C,
+    0xCA, 0xB9, 0x2C, 0xCB, 0x97, 0x28, 0x7E, 0xE8, 0xE6, 0x39, 0x43, 0x7E,
+    0x21, 0xFC, 0xD6, 0xB6, 0xF1, 0x65, 0xB2, 0xD5, 0xA3, 0xF3, 0xDB, 0x13,
+    0x1D, 0x31, 0xC1, 0x6B, 0x74, 0x2B, 0xB4, 0x76, 0xD8, 0xD1, 0xE9, 0x90,
+    0x80, 0xEB, 0x54, 0x6C, 0x9B, 0xBD, 0xF5, 0x56, 0xE6, 0x21, 0x0F, 0xD4,
+    0x27, 0x85, 0x89, 0x9E, 0x78, 0xCC, 0x58, 0x9E, 0xBE, 0x31, 0x0F, 0x6C,
+    0xDB, 0x9F, 0xF4, 0xA3, 0x3B, 0x30, 0x39, 0x30, 0x22, 0x06, 0x09, 0x2B,
+    0x06, 0x01, 0x04, 0x01, 0x82, 0xC4, 0x0A, 0x02, 0x04, 0x15, 0x31, 0x2E,
+    0x33, 0x2E, 0x36, 0x2E, 0x31, 0x2E, 0x34, 0x2E, 0x31, 0x2E, 0x34, 0x31,
+    0x34, 0x38, 0x32, 0x2E, 0x31, 0x2E, 0x32, 0x30, 0x13, 0x06, 0x0B, 0x2B,
+    0x06, 0x01, 0x04, 0x01, 0x82, 0xE5, 0x1C, 0x02, 0x01, 0x01, 0x04, 0x04,
+    0x03, 0x02, 0x04, 0x30, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86,
+    0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00,
+    0x9F, 0x9B, 0x05, 0x22, 0x48, 0xBC, 0x4C, 0xF4, 0x2C, 0xC5, 0x99, 0x1F,
+    0xCA, 0xAB, 0xAC, 0x9B, 0x65, 0x1B, 0xBE, 0x5B, 0xDC, 0xDC, 0x8E, 0xF0,
+    0xAD, 0x2C, 0x1C, 0x1F, 0xFB, 0x36, 0xD1, 0x87, 0x15, 0xD4, 0x2E, 0x78,
+    0xB2, 0x49, 0x22, 0x4F, 0x92, 0xC7, 0xE6, 0xE7, 0xA0, 0x5C, 0x49, 0xF0,
+    0xE7, 0xE4, 0xC8, 0x81, 0xBF, 0x2E, 0x94, 0xF4, 0x5E, 0x4A, 0x21, 0x83,
+    0x3D, 0x74, 0x56, 0x85, 0x1D, 0x0F, 0x6C, 0x14, 0x5A, 0x29, 0x54, 0x0C,
+    0x87, 0x4F, 0x30, 0x92, 0xC9, 0x34, 0xB4, 0x3D, 0x22, 0x2B, 0x89, 0x62,
+    0xC0, 0xF4, 0x10, 0xCE, 0xF1, 0xDB, 0x75, 0x89, 0x2A, 0xF1, 0x16, 0xB4,
+    0x4A, 0x96, 0xF5, 0xD3, 0x5A, 0xDE, 0xA3, 0x82, 0x2F, 0xC7, 0x14, 0x6F,
+    0x60, 0x04, 0x38, 0x5B, 0xCB, 0x69, 0xB6, 0x5C, 0x99, 0xE7, 0xEB, 0x69,
+    0x19, 0x78, 0x67, 0x03, 0xC0, 0xD8, 0xCD, 0x41, 0xE8, 0xF7, 0x5C, 0xCA,
+    0x44, 0xAA, 0x8A, 0xB7, 0x25, 0xAD, 0x8E, 0x79, 0x9F, 0xF3, 0xA8, 0x69,
+    0x6A, 0x6F, 0x1B, 0x26, 0x56, 0xE6, 0x31, 0xB1, 0xE4, 0x01, 0x83, 0xC0,
+    0x8F, 0xDA, 0x53, 0xFA, 0x4A, 0x8F, 0x85, 0xA0, 0x56, 0x93, 0x94, 0x4A,
+    0xE1, 0x79, 0xA1, 0x33, 0x9D, 0x00, 0x2D, 0x15, 0xCA, 0xBD, 0x81, 0x00,
+    0x90, 0xEC, 0x72, 0x2E, 0xF5, 0xDE, 0xF9, 0x96, 0x5A, 0x37, 0x1D, 0x41,
+    0x5D, 0x62, 0x4B, 0x68, 0xA2, 0x70, 0x7C, 0xAD, 0x97, 0xBC, 0xDD, 0x17,
+    0x85, 0xAF, 0x97, 0xE2, 0x58, 0xF3, 0x3D, 0xF5, 0x6A, 0x03, 0x1A, 0xA0,
+    0x35, 0x6D, 0x8E, 0x8D, 0x5E, 0xBC, 0xAD, 0xC7, 0x4E, 0x07, 0x16, 0x36,
+    0xC6, 0xB1, 0x10, 0xAC, 0xE5, 0xCC, 0x9B, 0x90, 0xDF, 0xEA, 0xCA, 0xE6,
+    0x40, 0xFF, 0x1B, 0xB0, 0xF1, 0xFE, 0x5D, 0xB4, 0xEF, 0xF7, 0xA9, 0x5F,
+    0x06, 0x07, 0x33, 0xF5,
+    // Signature
+    0x30, 0x45, 0x02, 0x20, 0x32, 0x47, 0x79, 0xC6, 0x8F, 0x33, 0x80, 0x28,
+    0x8A, 0x11, 0x97, 0xB6, 0x09, 0x5F, 0x7A, 0x6E, 0xB9, 0xB1, 0xB1, 0xC1,
+    0x27, 0xF6, 0x6A, 0xE1, 0x2A, 0x99, 0xFE, 0x85, 0x32, 0xEC, 0x23, 0xB9,
+    0x02, 0x21, 0x00, 0xE3, 0x95, 0x16, 0xAC, 0x4D, 0x61, 0xEE, 0x64, 0x04,
+    0x4D, 0x50, 0xB4, 0x15, 0xA6, 0xA4, 0xD4, 0xD8, 0x4B, 0xA6, 0xD8, 0x95,
+    0xCB, 0x5A, 0xB7, 0xA1, 0xAA, 0x7D, 0x08, 0x1D, 0xE3, 0x41, 0xFA,
+    // APDU Status bytes
+    0x90, 0x00,
+};
+
+constexpr uint8_t kApduEncodedNoErrorSignResponse[] = {
+    // User presence
+    0x01,
+    // Sign count(4 bytes)
+    0x00, 0x00, 0x00, 0x3B,
+    // Signature
+    0x30, 0x44, 0x02, 0x20, 0x7B, 0xDE, 0x0A, 0x52, 0xAC, 0x1F, 0x4C, 0x8B,
+    0x27, 0xE0, 0x03, 0xA3, 0x70, 0xCD, 0x66, 0xA4, 0xC7, 0x11, 0x8D, 0xD2,
+    0x2D, 0x54, 0x47, 0x83, 0x5F, 0x45, 0xB9, 0x9C, 0x68, 0x42, 0x3F, 0xF7,
+    0x02, 0x20, 0x3C, 0x51, 0x7B, 0x47, 0x87, 0x7F, 0x85, 0x78, 0x2D, 0xE1,
+    0x00, 0x86, 0xA7, 0x83, 0xD1, 0xE7, 0xDF, 0x4E, 0x36, 0x39, 0xE7, 0x71,
+    0xF5, 0xF6, 0xAF, 0xA3, 0x5A, 0xAD, 0x53, 0x73, 0x85, 0x8E,
+    // APDU Status bytes
+    0x90, 0x00,
+};
+
 // U2F response blob produced by a U2F registration request used in example 6
 // of the CTAP spec.
 // https://fidoalliance.org/specs/fido-v2.0-rd-20170927/fido-client-to-authenticator-protocol-v2.0-rd-20170927.html
@@ -554,8 +718,12 @@
     0x00, 0x00, 0x00, 0x3B,
 };
 
-// A sample corrupted response to a U2F sign request.
-constexpr uint8_t kTestCorruptedU2fSignResponse[] = {0x01, 0x00, 0x00, 0x00};
+// A sample APDU encoded response to a U2F sign request that contains NO_ERROR
+// status but has a corrupted data.
+constexpr uint8_t kTestCorruptedU2fSignResponse[] = {0x01, 0x00, 0x00,
+                                                     0x00, 0x90, 0x00};
+
+// CTAP responses --------------------------------------------------------------
 
 // A sample well formed response to CTAP AuthenticatorGetInfo request. Supports
 // platform device, resident key, and user verification.
diff --git a/device/fido/get_assertion_handler_unittest.cc b/device/fido/get_assertion_handler_unittest.cc
index eb59a13..5399484 100644
--- a/device/fido/get_assertion_handler_unittest.cc
+++ b/device/fido/get_assertion_handler_unittest.cc
@@ -5,7 +5,9 @@
 #include <memory>
 #include <utility>
 
+#include "base/test/scoped_feature_list.h"
 #include "base/test/scoped_task_environment.h"
+#include "device/base/features.h"
 #include "device/fido/authenticator_get_assertion_response.h"
 #include "device/fido/ctap_get_assertion_request.h"
 #include "device/fido/fake_fido_discovery.h"
@@ -43,8 +45,7 @@
         fido_parsing_utils::Materialize(test_data::kClientDataHash));
     request_param.SetAllowList(
         {{CredentialType::kPublicKey,
-          fido_parsing_utils::Materialize(
-              test_data::kTestGetAssertionCredentialId)}});
+          fido_parsing_utils::Materialize(test_data::kU2fSignKeyHandle)}});
 
     return std::make_unique<GetAssertionRequestHandler>(
         nullptr /* connector */,
@@ -53,8 +54,11 @@
         std::move(request_param), get_assertion_cb_.callback());
   }
 
-  test::FakeFidoDiscovery* discovery() const { return discovery_; }
+  void InitFeatureListWithCtapFlag() {
+    scoped_feature_list_.InitAndEnableFeature(kNewCtap2Device);
+  }
 
+  test::FakeFidoDiscovery* discovery() const { return discovery_; }
   TestGetAssertionRequestCallback& get_assertion_callback() {
     return get_assertion_cb_;
   }
@@ -62,12 +66,14 @@
  protected:
   base::test::ScopedTaskEnvironment scoped_task_environment_{
       base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME};
+  base::test::ScopedFeatureList scoped_feature_list_;
   test::ScopedFakeFidoDiscoveryFactory scoped_fake_discovery_factory_;
   test::FakeFidoDiscovery* discovery_;
   TestGetAssertionRequestCallback get_assertion_cb_;
 };
 
 TEST_F(FidoGetAssertionHandlerTest, TestGetAssertionRequestOnSingleDevice) {
+  InitFeatureListWithCtapFlag();
   auto request_handler = CreateGetAssertionHandler();
   discovery()->WaitForCallToStartAndSimulateSuccess();
   auto device = std::make_unique<MockFidoDevice>();
@@ -88,9 +94,9 @@
   EXPECT_TRUE(request_handler->is_complete());
 }
 
-// Test a scenario where the connected authenticator is a U2F device. Request
-// be silently dropped and request should remain in incomplete state.
-TEST_F(FidoGetAssertionHandlerTest, TestGetAssertionIncorrectGetInfoResponse) {
+// Test a scenario where the connected authenticator is a U2F device.
+TEST_F(FidoGetAssertionHandlerTest, TestU2fSign) {
+  InitFeatureListWithCtapFlag();
   auto request_handler = CreateGetAssertionHandler();
   discovery()->WaitForCallToStartAndSimulateSuccess();
 
@@ -98,10 +104,40 @@
   EXPECT_CALL(*device, GetId()).WillRepeatedly(testing::Return("device0"));
   device->ExpectCtap2CommandAndRespondWith(
       CtapRequestCommand::kAuthenticatorGetInfo, base::nullopt);
+  device->ExpectRequestAndRespondWith(
+      test_data::kU2fCheckOnlySignCommandApdu,
+      test_data::kApduEncodedNoErrorSignResponse);
+  device->ExpectRequestAndRespondWith(
+      test_data::kU2fSignCommandApdu,
+      test_data::kApduEncodedNoErrorSignResponse);
 
   discovery()->AddDevice(std::move(device));
   scoped_task_environment_.FastForwardUntilNoTasksRemain();
-  EXPECT_FALSE(request_handler->is_complete());
+  EXPECT_EQ(FidoReturnCode::kSuccess, get_assertion_callback().status());
+  EXPECT_TRUE(get_assertion_callback().value());
+  EXPECT_TRUE(request_handler->is_complete());
+}
+
+// Test a scenario where the connected authenticator is a U2F device and
+// "WebAuthenticationCtap2" flag is not enabled.
+TEST_F(FidoGetAssertionHandlerTest, TestU2fSignWithoutCtapFlag) {
+  auto request_handler = CreateGetAssertionHandler();
+  discovery()->WaitForCallToStartAndSimulateSuccess();
+
+  auto device = std::make_unique<MockFidoDevice>();
+  EXPECT_CALL(*device, GetId()).WillRepeatedly(testing::Return("device0"));
+  device->ExpectRequestAndRespondWith(
+      test_data::kU2fCheckOnlySignCommandApdu,
+      test_data::kApduEncodedNoErrorSignResponse);
+  device->ExpectRequestAndRespondWith(
+      test_data::kU2fSignCommandApdu,
+      test_data::kApduEncodedNoErrorSignResponse);
+
+  discovery()->AddDevice(std::move(device));
+  scoped_task_environment_.FastForwardUntilNoTasksRemain();
+  EXPECT_EQ(FidoReturnCode::kSuccess, get_assertion_callback().status());
+  EXPECT_TRUE(get_assertion_callback().value());
+  EXPECT_TRUE(request_handler->is_complete());
 }
 
 }  // namespace device
diff --git a/device/fido/get_assertion_task.cc b/device/fido/get_assertion_task.cc
index c6ae9b8..de7aa61 100644
--- a/device/fido/get_assertion_task.cc
+++ b/device/fido/get_assertion_task.cc
@@ -8,9 +8,13 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "device/base/features.h"
 #include "device/fido/authenticator_get_assertion_response.h"
+#include "device/fido/ctap2_device_operation.h"
 #include "device/fido/ctap_empty_authenticator_request.h"
 #include "device/fido/device_response_converter.h"
+#include "device/fido/u2f_command_constructor.h"
+#include "device/fido/u2f_sign_operation.h"
 
 namespace device {
 
@@ -39,10 +43,14 @@
 GetAssertionTask::~GetAssertionTask() = default;
 
 void GetAssertionTask::StartTask() {
-  GetAuthenticatorInfo(
-      base::BindOnce(&GetAssertionTask::GetAssertion,
-                     weak_factory_.GetWeakPtr()),
-      base::BindOnce(&GetAssertionTask::U2fSign, weak_factory_.GetWeakPtr()));
+  if (base::FeatureList::IsEnabled(kNewCtap2Device)) {
+    GetAuthenticatorInfo(
+        base::BindOnce(&GetAssertionTask::GetAssertion,
+                       weak_factory_.GetWeakPtr()),
+        base::BindOnce(&GetAssertionTask::U2fSign, weak_factory_.GetWeakPtr()));
+  } else {
+    U2fSign();
+  }
 }
 
 void GetAssertionTask::GetAssertion() {
@@ -52,19 +60,29 @@
     return;
   }
 
-  device()->DeviceTransact(
-      request_.EncodeAsCBOR(),
-      base::BindOnce(&GetAssertionTask::OnCtapGetAssertionResponseReceived,
-                     weak_factory_.GetWeakPtr()));
+  sign_operation_ =
+      std::make_unique<Ctap2DeviceOperation<CtapGetAssertionRequest,
+                                            AuthenticatorGetAssertionResponse>>(
+          device(), request_,
+          base::BindOnce(&GetAssertionTask::OnCtapGetAssertionResponseReceived,
+                         weak_factory_.GetWeakPtr()),
+          base::BindOnce(&ReadCTAPGetAssertionResponse));
+  sign_operation_->Start();
 }
 
 void GetAssertionTask::U2fSign() {
-  // TODO(hongjunchoi): Implement U2F sign request logic to support
-  // interoperability with U2F protocol. Currently all requests for U2F devices
-  // are silently dropped.
-  // See: https://www.crbug.com/798573
-  std::move(callback_).Run(CtapDeviceResponseCode::kCtap2ErrOther,
-                           base::nullopt);
+  device()->set_supported_protocol(ProtocolVersion::kU2f);
+  if (!IsConvertibleToU2fSignCommand(request_)) {
+    std::move(callback_).Run(CtapDeviceResponseCode::kCtap2ErrOther,
+                             base::nullopt);
+    return;
+  }
+
+  sign_operation_ = std::make_unique<U2fSignOperation>(
+      device(), request_,
+      base::BindOnce(&GetAssertionTask::OnCtapGetAssertionResponseReceived,
+                     weak_factory_.GetWeakPtr()));
+  sign_operation_->Start();
 }
 
 bool GetAssertionTask::CheckRequirementsOnReturnedUserEntities(
@@ -107,33 +125,30 @@
 }
 
 void GetAssertionTask::OnCtapGetAssertionResponseReceived(
-    base::Optional<std::vector<uint8_t>> device_response) {
-  if (!device_response) {
-    std::move(callback_).Run(CtapDeviceResponseCode::kCtap2ErrOther,
-                             base::nullopt);
-    return;
-  }
-
-  auto response_code = GetResponseCode(*device_response);
+    CtapDeviceResponseCode response_code,
+    base::Optional<AuthenticatorGetAssertionResponse> device_response) {
   if (response_code != CtapDeviceResponseCode::kSuccess) {
     std::move(callback_).Run(response_code, base::nullopt);
     return;
   }
 
-  auto parsed_response = ReadCTAPGetAssertionResponse(*device_response);
-  if (!parsed_response || !parsed_response->CheckRpIdHash(request_.rp_id()) ||
-      !CheckRequirementsOnReturnedCredentialId(*parsed_response) ||
-      !CheckRequirementsOnReturnedUserEntities(*parsed_response)) {
+  if (!device_response || !device_response->CheckRpIdHash(request_.rp_id()) ||
+      !CheckRequirementsOnReturnedCredentialId(*device_response) ||
+      !CheckRequirementsOnReturnedUserEntities(*device_response)) {
     std::move(callback_).Run(CtapDeviceResponseCode::kCtap2ErrOther,
                              base::nullopt);
     return;
   }
 
-  std::move(callback_).Run(response_code, std::move(parsed_response));
+  std::move(callback_).Run(response_code, std::move(device_response));
 }
 
 bool GetAssertionTask::CheckUserVerificationCompatible() {
-  DCHECK(device()->device_info());
+  if (!device()->device_info()) {
+    return request_.user_verification() !=
+           UserVerificationRequirement::kRequired;
+  }
+
   const auto uv_availability =
       device()->device_info()->options().user_verification_availability();
 
diff --git a/device/fido/get_assertion_task.h b/device/fido/get_assertion_task.h
index 3f90a21..cc8d666 100644
--- a/device/fido/get_assertion_task.h
+++ b/device/fido/get_assertion_task.h
@@ -7,6 +7,7 @@
 
 #include <stdint.h>
 
+#include <memory>
 #include <vector>
 
 #include "base/callback.h"
@@ -15,6 +16,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/optional.h"
 #include "device/fido/ctap_get_assertion_request.h"
+#include "device/fido/device_operation.h"
 #include "device/fido/fido_constants.h"
 #include "device/fido/fido_task.h"
 
@@ -29,6 +31,8 @@
   using GetAssertionTaskCallback = base::OnceCallback<void(
       CtapDeviceResponseCode,
       base::Optional<AuthenticatorGetAssertionResponse>)>;
+  using SignOperation = DeviceOperation<CtapGetAssertionRequest,
+                                        AuthenticatorGetAssertionResponse>;
 
   GetAssertionTask(FidoDevice* device,
                    CtapGetAssertionRequest request,
@@ -75,9 +79,11 @@
   bool CheckUserVerificationCompatible();
 
   void OnCtapGetAssertionResponseReceived(
-      base::Optional<std::vector<uint8_t>> device_response);
+      CtapDeviceResponseCode response_code,
+      base::Optional<AuthenticatorGetAssertionResponse> device_response);
 
   CtapGetAssertionRequest request_;
+  std::unique_ptr<SignOperation> sign_operation_;
   GetAssertionTaskCallback callback_;
   base::WeakPtrFactory<GetAssertionTask> weak_factory_;
 
diff --git a/device/fido/get_assertion_task_unittest.cc b/device/fido/get_assertion_task_unittest.cc
index d2313d4..de5d814 100644
--- a/device/fido/get_assertion_task_unittest.cc
+++ b/device/fido/get_assertion_task_unittest.cc
@@ -10,7 +10,9 @@
 #include <vector>
 
 #include "base/bind.h"
+#include "base/test/scoped_feature_list.h"
 #include "base/test/scoped_task_environment.h"
+#include "device/base/features.h"
 #include "device/fido/authenticator_get_assertion_response.h"
 #include "device/fido/ctap_get_assertion_request.h"
 #include "device/fido/fido_constants.h"
@@ -36,12 +38,23 @@
 
 class FidoGetAssertionTaskTest : public testing::Test {
  public:
+  FidoGetAssertionTaskTest() {
+    scoped_feature_list_.emplace();
+    scoped_feature_list_->InitAndEnableFeature(kNewCtap2Device);
+  }
+
   TestGetAssertionTaskCallbackReceiver& get_assertion_callback_receiver() {
     return cb_;
   }
 
+  void RemoveCtapFlag() {
+    scoped_feature_list_.emplace();
+    scoped_feature_list_->InitAndDisableFeature(kNewCtap2Device);
+  }
+
  private:
   base::test::ScopedTaskEnvironment scoped_task_environment_;
+  base::Optional<base::test::ScopedFeatureList> scoped_feature_list_;
   TestGetAssertionTaskCallbackReceiver cb_;
 };
 
@@ -73,6 +86,65 @@
   EXPECT_TRUE(device->device_info());
 }
 
+TEST_F(FidoGetAssertionTaskTest, TestU2fSignSuccess) {
+  auto device = std::make_unique<MockFidoDevice>();
+  device->ExpectCtap2CommandAndRespondWith(
+      CtapRequestCommand::kAuthenticatorGetInfo, base::nullopt);
+  device->ExpectRequestAndRespondWith(
+      test_data::kU2fCheckOnlySignCommandApdu,
+      test_data::kApduEncodedNoErrorSignResponse);
+  device->ExpectRequestAndRespondWith(
+      test_data::kU2fSignCommandApdu,
+      test_data::kApduEncodedNoErrorSignResponse);
+
+  CtapGetAssertionRequest request_param(
+      test_data::kRelyingPartyId,
+      fido_parsing_utils::Materialize(test_data::kClientDataHash));
+  request_param.SetAllowList(
+      {{CredentialType::kPublicKey,
+        fido_parsing_utils::Materialize(test_data::kU2fSignKeyHandle)}});
+
+  auto task = std::make_unique<GetAssertionTask>(
+      device.get(), std::move(request_param),
+      get_assertion_callback_receiver().callback());
+
+  get_assertion_callback_receiver().WaitForCallback();
+  EXPECT_EQ(CtapDeviceResponseCode::kSuccess,
+            get_assertion_callback_receiver().status());
+  EXPECT_TRUE(get_assertion_callback_receiver().value());
+  EXPECT_EQ(device->supported_protocol(), ProtocolVersion::kU2f);
+  EXPECT_FALSE(device->device_info());
+}
+
+TEST_F(FidoGetAssertionTaskTest, TestU2fSignWithoutFlag) {
+  RemoveCtapFlag();
+  auto device = std::make_unique<MockFidoDevice>();
+  device->ExpectRequestAndRespondWith(
+      test_data::kU2fCheckOnlySignCommandApdu,
+      test_data::kApduEncodedNoErrorSignResponse);
+  device->ExpectRequestAndRespondWith(
+      test_data::kU2fSignCommandApdu,
+      test_data::kApduEncodedNoErrorSignResponse);
+
+  CtapGetAssertionRequest request_param(
+      test_data::kRelyingPartyId,
+      fido_parsing_utils::Materialize(test_data::kClientDataHash));
+  request_param.SetAllowList(
+      {{CredentialType::kPublicKey,
+        fido_parsing_utils::Materialize(test_data::kU2fSignKeyHandle)}});
+
+  auto task = std::make_unique<GetAssertionTask>(
+      device.get(), std::move(request_param),
+      get_assertion_callback_receiver().callback());
+
+  get_assertion_callback_receiver().WaitForCallback();
+  EXPECT_EQ(CtapDeviceResponseCode::kSuccess,
+            get_assertion_callback_receiver().status());
+  EXPECT_TRUE(get_assertion_callback_receiver().value());
+  EXPECT_EQ(device->supported_protocol(), ProtocolVersion::kU2f);
+  EXPECT_FALSE(device->device_info());
+}
+
 // Tests a scenario where the authenticator responds with credential ID that
 // is not included in the allowed list.
 TEST_F(FidoGetAssertionTaskTest, TestGetAssertionInvalidCredential) {
@@ -199,4 +271,49 @@
   EXPECT_FALSE(get_assertion_callback_receiver().value());
 }
 
+TEST_F(FidoGetAssertionTaskTest,
+       TestU2fSignRequestWithUserVerificationRequired) {
+  auto request = CtapGetAssertionRequest(
+      test_data::kRelyingPartyId,
+      fido_parsing_utils::Materialize(test_data::kClientDataHash));
+  request.SetAllowList(
+      {{CredentialType::kPublicKey,
+        fido_parsing_utils::Materialize(test_data::kU2fSignKeyHandle)}});
+  request.SetUserVerification(UserVerificationRequirement::kRequired);
+
+  auto device = std::make_unique<MockFidoDevice>();
+  device->ExpectCtap2CommandAndRespondWith(
+      CtapRequestCommand::kAuthenticatorGetInfo, base::nullopt);
+
+  auto task = std::make_unique<GetAssertionTask>(
+      device.get(), std::move(request),
+      get_assertion_callback_receiver().callback());
+
+  get_assertion_callback_receiver().WaitForCallback();
+  EXPECT_EQ(device->supported_protocol(), ProtocolVersion::kU2f);
+  EXPECT_EQ(CtapDeviceResponseCode::kCtap2ErrOther,
+            get_assertion_callback_receiver().status());
+  EXPECT_FALSE(get_assertion_callback_receiver().value());
+}
+
+TEST_F(FidoGetAssertionTaskTest, TestU2fSignRequestWithEmptyAllowedList) {
+  auto request = CtapGetAssertionRequest(
+      test_data::kRelyingPartyId,
+      fido_parsing_utils::Materialize(test_data::kClientDataHash));
+
+  auto device = std::make_unique<MockFidoDevice>();
+  device->ExpectCtap2CommandAndRespondWith(
+      CtapRequestCommand::kAuthenticatorGetInfo, base::nullopt);
+
+  auto task = std::make_unique<GetAssertionTask>(
+      device.get(), std::move(request),
+      get_assertion_callback_receiver().callback());
+
+  get_assertion_callback_receiver().WaitForCallback();
+  EXPECT_EQ(device->supported_protocol(), ProtocolVersion::kU2f);
+  EXPECT_EQ(CtapDeviceResponseCode::kCtap2ErrOther,
+            get_assertion_callback_receiver().status());
+  EXPECT_FALSE(get_assertion_callback_receiver().value());
+}
+
 }  // namespace device
diff --git a/device/fido/make_credential_handler_unittest.cc b/device/fido/make_credential_handler_unittest.cc
index d36bfe5..28d7d82 100644
--- a/device/fido/make_credential_handler_unittest.cc
+++ b/device/fido/make_credential_handler_unittest.cc
@@ -5,7 +5,9 @@
 #include <memory>
 #include <utility>
 
+#include "base/test/scoped_feature_list.h"
 #include "base/test/scoped_task_environment.h"
+#include "device/base/features.h"
 #include "device/fido/authenticator_make_credential_response.h"
 #include "device/fido/authenticator_selection_criteria.h"
 #include "device/fido/ctap_make_credential_request.h"
@@ -59,10 +61,15 @@
         cb_.callback());
   }
 
+  void InitFeatureListWithCtapFlag() {
+    scoped_feature_list_.InitAndEnableFeature(kNewCtap2Device);
+  }
+
   test::FakeFidoDiscovery* discovery() const { return discovery_; }
   TestMakeCredentialRequestCallback& callback() { return cb_; }
 
  protected:
+  base::test::ScopedFeatureList scoped_feature_list_;
   base::test::ScopedTaskEnvironment scoped_task_environment_{
       base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME};
   test::ScopedFakeFidoDiscoveryFactory scoped_fake_discovery_factory_;
@@ -70,7 +77,8 @@
   TestMakeCredentialRequestCallback cb_;
 };
 
-TEST_F(FidoMakeCredentialHandlerTest, TestMakeCredentialRequestHandler) {
+TEST_F(FidoMakeCredentialHandlerTest, TestCtap2MakeCredentialWithFlagEnabled) {
+  InitFeatureListWithCtapFlag();
   auto request_handler = CreateMakeCredentialHandler();
   discovery()->WaitForCallToStartAndSimulateSuccess();
 
@@ -89,10 +97,9 @@
   EXPECT_TRUE(request_handler->is_complete());
 }
 
-// Test a scenario where the connected authenticator is a U2F device. Request
-// be silently dropped and request should remain in incomplete state.
-TEST_F(FidoMakeCredentialHandlerTest,
-       TestMakeCredentialIncorrectGetInfoResponse) {
+// Test a scenario where the connected authenticator is a U2F device.
+TEST_F(FidoMakeCredentialHandlerTest, TestU2fRegisterWithFlagEnabled) {
+  InitFeatureListWithCtapFlag();
   auto request_handler = CreateMakeCredentialHandler();
   discovery()->WaitForCallToStartAndSimulateSuccess();
 
@@ -100,10 +107,32 @@
   EXPECT_CALL(*device, GetId()).WillRepeatedly(testing::Return("device0"));
   device->ExpectCtap2CommandAndRespondWith(
       CtapRequestCommand::kAuthenticatorGetInfo, base::nullopt);
+  device->ExpectRequestAndRespondWith(
+      test_data::kU2fRegisterCommandApdu,
+      test_data::kApduEncodedNoErrorRegisterResponse);
 
   discovery()->AddDevice(std::move(device));
-  scoped_task_environment_.FastForwardUntilNoTasksRemain();
-  EXPECT_FALSE(request_handler->is_complete());
+  callback().WaitForCallback();
+  EXPECT_EQ(FidoReturnCode::kSuccess, callback().status());
+  EXPECT_TRUE(request_handler->is_complete());
+}
+
+// Test a scenario where the connected authenticator is a U2F device using a
+// logic that defaults to handling U2F devices.
+TEST_F(FidoMakeCredentialHandlerTest, TestU2fRegisterWithoutFlagEnabled) {
+  auto request_handler = CreateMakeCredentialHandler();
+  discovery()->WaitForCallToStartAndSimulateSuccess();
+
+  auto device = std::make_unique<MockFidoDevice>();
+  EXPECT_CALL(*device, GetId()).WillRepeatedly(testing::Return("device0"));
+  device->ExpectRequestAndRespondWith(
+      test_data::kU2fRegisterCommandApdu,
+      test_data::kApduEncodedNoErrorRegisterResponse);
+
+  discovery()->AddDevice(std::move(device));
+  callback().WaitForCallback();
+  EXPECT_EQ(FidoReturnCode::kSuccess, callback().status());
+  EXPECT_TRUE(request_handler->is_complete());
 }
 
 }  // namespace device
diff --git a/device/fido/make_credential_task.cc b/device/fido/make_credential_task.cc
index 4c966eb..8f7cbc3 100644
--- a/device/fido/make_credential_task.cc
+++ b/device/fido/make_credential_task.cc
@@ -7,9 +7,12 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "device/base/features.h"
+#include "device/fido/ctap2_device_operation.h"
 #include "device/fido/ctap_empty_authenticator_request.h"
-#include "device/fido/ctap_register_operation.h"
 #include "device/fido/device_response_converter.h"
+#include "device/fido/u2f_command_constructor.h"
+#include "device/fido/u2f_register_operation.h"
 
 namespace device {
 
@@ -28,10 +31,14 @@
 MakeCredentialTask::~MakeCredentialTask() = default;
 
 void MakeCredentialTask::StartTask() {
-  GetAuthenticatorInfo(base::BindOnce(&MakeCredentialTask::MakeCredential,
-                                      weak_factory_.GetWeakPtr()),
-                       base::BindOnce(&MakeCredentialTask::U2fRegister,
-                                      weak_factory_.GetWeakPtr()));
+  if (base::FeatureList::IsEnabled(kNewCtap2Device)) {
+    GetAuthenticatorInfo(base::BindOnce(&MakeCredentialTask::MakeCredential,
+                                        weak_factory_.GetWeakPtr()),
+                         base::BindOnce(&MakeCredentialTask::U2fRegister,
+                                        weak_factory_.GetWeakPtr()));
+  } else {
+    U2fRegister();
+  }
 }
 
 void MakeCredentialTask::MakeCredential() {
@@ -41,20 +48,30 @@
     return;
   }
 
-  register_operation_ = std::make_unique<CtapRegisterOperation>(
-      device(), &request_parameter_,
+  register_operation_ = std::make_unique<Ctap2DeviceOperation<
+      CtapMakeCredentialRequest, AuthenticatorMakeCredentialResponse>>(
+      device(), request_parameter_,
       base::BindOnce(&MakeCredentialTask::OnCtapMakeCredentialResponseReceived,
-                     weak_factory_.GetWeakPtr()));
+                     weak_factory_.GetWeakPtr()),
+      base::BindOnce(&ReadCTAPMakeCredentialResponse));
   register_operation_->Start();
 }
 
 void MakeCredentialTask::U2fRegister() {
-  // TODO(hongjunchoi): Implement U2F register request logic to support
-  // interoperability with U2F protocol. Currently all U2F devices are not
-  // supported and request to U2F devices will be silently dropped.
-  // See: https://crbug.com/798573
-  std::move(callback_).Run(CtapDeviceResponseCode::kCtap2ErrOther,
-                           base::nullopt);
+  device()->set_supported_protocol(ProtocolVersion::kU2f);
+
+  if (!CheckIfAuthenticatorSelectionCriteriaAreSatisfied() ||
+      !IsConvertibleToU2fRegisterCommand(request_parameter_)) {
+    std::move(callback_).Run(CtapDeviceResponseCode::kCtap2ErrOther,
+                             base::nullopt);
+    return;
+  }
+
+  register_operation_ = std::make_unique<U2fRegisterOperation>(
+      device(), request_parameter_,
+      base::BindOnce(&MakeCredentialTask::OnCtapMakeCredentialResponseReceived,
+                     weak_factory_.GetWeakPtr()));
+  register_operation_->Start();
 }
 
 void MakeCredentialTask::OnCtapMakeCredentialResponseReceived(
diff --git a/device/fido/make_credential_task.h b/device/fido/make_credential_task.h
index 25025892..47fcb99 100644
--- a/device/fido/make_credential_task.h
+++ b/device/fido/make_credential_task.h
@@ -18,7 +18,7 @@
 #include "device/fido/authenticator_make_credential_response.h"
 #include "device/fido/authenticator_selection_criteria.h"
 #include "device/fido/ctap_make_credential_request.h"
-#include "device/fido/ctap_register_operation.h"
+#include "device/fido/device_operation.h"
 #include "device/fido/fido_constants.h"
 #include "device/fido/fido_task.h"
 
@@ -31,6 +31,9 @@
   using MakeCredentialTaskCallback = base::OnceCallback<void(
       CtapDeviceResponseCode,
       base::Optional<AuthenticatorMakeCredentialResponse>)>;
+  using RegisterOperation =
+      DeviceOperation<CtapMakeCredentialRequest,
+                      AuthenticatorMakeCredentialResponse>;
 
   MakeCredentialTask(FidoDevice* device,
                      CtapMakeCredentialRequest request_parameter,
@@ -56,7 +59,7 @@
 
   CtapMakeCredentialRequest request_parameter_;
   AuthenticatorSelectionCriteria authenticator_selection_criteria_;
-  std::unique_ptr<CtapRegisterOperation> register_operation_;
+  std::unique_ptr<RegisterOperation> register_operation_;
   MakeCredentialTaskCallback callback_;
   base::WeakPtrFactory<MakeCredentialTask> weak_factory_;
 
diff --git a/device/fido/make_credential_task_unittest.cc b/device/fido/make_credential_task_unittest.cc
index f9bb61f..7483171 100644
--- a/device/fido/make_credential_task_unittest.cc
+++ b/device/fido/make_credential_task_unittest.cc
@@ -9,7 +9,9 @@
 #include "base/bind.h"
 #include "base/numerics/safe_conversions.h"
 #include "base/run_loop.h"
+#include "base/test/scoped_feature_list.h"
 #include "base/test/scoped_task_environment.h"
+#include "device/base/features.h"
 #include "device/fido/authenticator_make_credential_response.h"
 #include "device/fido/ctap_make_credential_request.h"
 #include "device/fido/fido_constants.h"
@@ -36,9 +38,10 @@
 
 class FidoMakeCredentialTaskTest : public testing::Test {
  public:
-  FidoMakeCredentialTaskTest()
-      : scoped_task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::UI) {}
+  FidoMakeCredentialTaskTest() {
+    scoped_feature_list_.emplace();
+    scoped_feature_list_->InitAndEnableFeature(kNewCtap2Device);
+  }
 
   std::unique_ptr<MakeCredentialTask> CreateMakeCredentialTask(
       FidoDevice* device) {
@@ -72,16 +75,22 @@
         std::move(criteria), callback_receiver_.callback());
   }
 
+  void RemoveCtapFlag() {
+    scoped_feature_list_.emplace();
+    scoped_feature_list_->InitAndDisableFeature(kNewCtap2Device);
+  }
+
   TestMakeCredentialTaskCallback& make_credential_callback_receiver() {
     return callback_receiver_;
   }
 
  protected:
+  base::Optional<base::test::ScopedFeatureList> scoped_feature_list_;
   base::test::ScopedTaskEnvironment scoped_task_environment_;
   TestMakeCredentialTaskCallback callback_receiver_;
 };
 
-TEST_F(FidoMakeCredentialTaskTest, TestMakeCredentialSuccess) {
+TEST_F(FidoMakeCredentialTaskTest, MakeCredentialSuccess) {
   auto device = std::make_unique<MockFidoDevice>();
 
   device->ExpectCtap2CommandAndRespondWith(
@@ -101,21 +110,7 @@
   EXPECT_TRUE(device->device_info());
 }
 
-TEST_F(FidoMakeCredentialTaskTest, TestIncorrectAuthenticatorGetInfoResponse) {
-  auto device = std::make_unique<MockFidoDevice>();
-
-  device->ExpectCtap2CommandAndRespondWith(
-      CtapRequestCommand::kAuthenticatorGetInfo, base::nullopt);
-
-  const auto task = CreateMakeCredentialTask(device.get());
-  make_credential_callback_receiver().WaitForCallback();
-  EXPECT_EQ(CtapDeviceResponseCode::kCtap2ErrOther,
-            make_credential_callback_receiver().status());
-  EXPECT_EQ(ProtocolVersion::kU2f, device->supported_protocol());
-  EXPECT_FALSE(device->device_info());
-}
-
-TEST_F(FidoMakeCredentialTaskTest, TestMakeCredentialWithIncorrectRpIdHash) {
+TEST_F(FidoMakeCredentialTaskTest, MakeCredentialWithIncorrectRpIdHash) {
   auto device = std::make_unique<MockFidoDevice>();
 
   device->ExpectCtap2CommandAndRespondWith(
@@ -132,8 +127,96 @@
             make_credential_callback_receiver().status());
 }
 
+TEST_F(FidoMakeCredentialTaskTest, FallbackToU2fRegisterSuccess) {
+  auto device = std::make_unique<MockFidoDevice>();
+
+  device->ExpectCtap2CommandAndRespondWith(
+      CtapRequestCommand::kAuthenticatorGetInfo, base::nullopt);
+  device->ExpectRequestAndRespondWith(
+      test_data::kU2fRegisterCommandApdu,
+      test_data::kApduEncodedNoErrorRegisterResponse);
+
+  const auto task = CreateMakeCredentialTask(device.get());
+  make_credential_callback_receiver().WaitForCallback();
+
+  EXPECT_EQ(ProtocolVersion::kU2f, device->supported_protocol());
+  EXPECT_EQ(CtapDeviceResponseCode::kSuccess,
+            make_credential_callback_receiver().status());
+}
+
+TEST_F(FidoMakeCredentialTaskTest, TestDefaultU2fRegisterOperationWithoutFlag) {
+  RemoveCtapFlag();
+  auto device = std::make_unique<MockFidoDevice>();
+  device->ExpectRequestAndRespondWith(
+      test_data::kU2fRegisterCommandApdu,
+      test_data::kApduEncodedNoErrorRegisterResponse);
+
+  const auto task = CreateMakeCredentialTask(device.get());
+  make_credential_callback_receiver().WaitForCallback();
+
+  EXPECT_EQ(CtapDeviceResponseCode::kSuccess,
+            make_credential_callback_receiver().status());
+}
+
+TEST_F(FidoMakeCredentialTaskTest, U2fRegisterWithUserVerificationRequired) {
+  auto device = std::make_unique<MockFidoDevice>();
+
+  device->ExpectCtap2CommandAndRespondWith(
+      CtapRequestCommand::kAuthenticatorGetInfo, base::nullopt);
+
+  const auto task = CreateMakeCredentialTaskWithAuthenticatorSelectionCriteria(
+      device.get(),
+      AuthenticatorSelectionCriteria(
+          AuthenticatorSelectionCriteria::AuthenticatorAttachment::kAny,
+          false /* require_resident_key */,
+          UserVerificationRequirement::kRequired));
+  make_credential_callback_receiver().WaitForCallback();
+
+  EXPECT_EQ(ProtocolVersion::kU2f, device->supported_protocol());
+  EXPECT_EQ(CtapDeviceResponseCode::kCtap2ErrOther,
+            make_credential_callback_receiver().status());
+}
+
+TEST_F(FidoMakeCredentialTaskTest, U2fRegisterWithPlatformDeviceRequirement) {
+  auto device = std::make_unique<MockFidoDevice>();
+
+  device->ExpectCtap2CommandAndRespondWith(
+      CtapRequestCommand::kAuthenticatorGetInfo, base::nullopt);
+
+  const auto task = CreateMakeCredentialTaskWithAuthenticatorSelectionCriteria(
+      device.get(),
+      AuthenticatorSelectionCriteria(
+          AuthenticatorSelectionCriteria::AuthenticatorAttachment::kPlatform,
+          false /* require_resident_key */,
+          UserVerificationRequirement::kPreferred));
+  make_credential_callback_receiver().WaitForCallback();
+
+  EXPECT_EQ(ProtocolVersion::kU2f, device->supported_protocol());
+  EXPECT_EQ(CtapDeviceResponseCode::kCtap2ErrOther,
+            make_credential_callback_receiver().status());
+}
+
+TEST_F(FidoMakeCredentialTaskTest, U2fRegisterWithResidentKeyRequirement) {
+  auto device = std::make_unique<MockFidoDevice>();
+
+  device->ExpectCtap2CommandAndRespondWith(
+      CtapRequestCommand::kAuthenticatorGetInfo, base::nullopt);
+
+  const auto task = CreateMakeCredentialTaskWithAuthenticatorSelectionCriteria(
+      device.get(),
+      AuthenticatorSelectionCriteria(
+          AuthenticatorSelectionCriteria::AuthenticatorAttachment::kAny,
+          true /* require_resident_key */,
+          UserVerificationRequirement::kPreferred));
+  make_credential_callback_receiver().WaitForCallback();
+
+  EXPECT_EQ(ProtocolVersion::kU2f, device->supported_protocol());
+  EXPECT_EQ(CtapDeviceResponseCode::kCtap2ErrOther,
+            make_credential_callback_receiver().status());
+}
+
 TEST_F(FidoMakeCredentialTaskTest,
-       TestUserVerificationAuthenticatorSelectionCriteria) {
+       UserVerificationAuthenticatorSelectionCriteria) {
   auto device = std::make_unique<MockFidoDevice>();
 
   device->ExpectCtap2CommandAndRespondWith(
@@ -158,7 +241,7 @@
 }
 
 TEST_F(FidoMakeCredentialTaskTest,
-       TestPlatformDeviceAuthenticatorSelectionCriteria) {
+       PlatformDeviceAuthenticatorSelectionCriteria) {
   auto device = std::make_unique<MockFidoDevice>();
 
   device->ExpectCtap2CommandAndRespondWith(
@@ -180,8 +263,7 @@
   EXPECT_FALSE(device->device_info()->options().is_platform_device());
 }
 
-TEST_F(FidoMakeCredentialTaskTest,
-       TestResidentKeyAuthenticatorSelectionCriteria) {
+TEST_F(FidoMakeCredentialTaskTest, ResidentKeyAuthenticatorSelectionCriteria) {
   auto device = std::make_unique<MockFidoDevice>();
 
   device->ExpectCtap2CommandAndRespondWith(
@@ -203,8 +285,7 @@
   EXPECT_FALSE(device->device_info()->options().supports_resident_key());
 }
 
-TEST_F(FidoMakeCredentialTaskTest,
-       TestSatisfyAllAuthenticatorSelectionCriteria) {
+TEST_F(FidoMakeCredentialTaskTest, SatisfyAllAuthenticatorSelectionCriteria) {
   auto device = std::make_unique<MockFidoDevice>();
 
   device->ExpectCtap2CommandAndRespondWith(
@@ -235,7 +316,7 @@
             device_options.user_verification_availability());
 }
 
-TEST_F(FidoMakeCredentialTaskTest, TestIncompatibleUserVerificationSetting) {
+TEST_F(FidoMakeCredentialTaskTest, IncompatibleUserVerificationSetting) {
   auto device = std::make_unique<MockFidoDevice>();
 
   device->ExpectCtap2CommandAndRespondWith(
diff --git a/device/fido/mock_fido_device.cc b/device/fido/mock_fido_device.cc
index 42d61e8..714950a 100644
--- a/device/fido/mock_fido_device.cc
+++ b/device/fido/mock_fido_device.cc
@@ -33,64 +33,6 @@
   DeviceTransactPtr(command, cb);
 }
 
-// static
-void MockFidoDevice::NotSatisfied(const std::vector<uint8_t>& command,
-                                  DeviceCallback& cb) {
-  std::move(cb).Run(apdu::ApduResponse(
-                        std::vector<uint8_t>(),
-                        apdu::ApduResponse::Status::SW_CONDITIONS_NOT_SATISFIED)
-                        .GetEncodedResponse());
-}
-
-// static
-void MockFidoDevice::WrongData(const std::vector<uint8_t>& command,
-                               DeviceCallback& cb) {
-  std::move(cb).Run(
-      apdu::ApduResponse(std::vector<uint8_t>(),
-                         apdu::ApduResponse::Status::SW_WRONG_DATA)
-          .GetEncodedResponse());
-}
-
-// static
-void MockFidoDevice::NoErrorSign(const std::vector<uint8_t>& command,
-                                 DeviceCallback& cb) {
-  std::move(cb).Run(
-      apdu::ApduResponse(
-          std::vector<uint8_t>(std::begin(test_data::kTestU2fSignResponse),
-                               std::end(test_data::kTestU2fSignResponse)),
-          apdu::ApduResponse::Status::SW_NO_ERROR)
-          .GetEncodedResponse());
-}
-
-// static
-void MockFidoDevice::NoErrorRegister(const std::vector<uint8_t>& command,
-                                     DeviceCallback& cb) {
-  std::move(cb).Run(
-      apdu::ApduResponse(
-          std::vector<uint8_t>(std::begin(test_data::kTestU2fRegisterResponse),
-                               std::end(test_data::kTestU2fRegisterResponse)),
-          apdu::ApduResponse::Status::SW_NO_ERROR)
-          .GetEncodedResponse());
-}
-
-// static
-void MockFidoDevice::SignWithCorruptedResponse(
-    const std::vector<uint8_t>& command,
-    DeviceCallback& cb) {
-  std::move(cb).Run(
-      apdu::ApduResponse(
-          std::vector<uint8_t>(
-              std::begin(test_data::kTestCorruptedU2fSignResponse),
-              std::end(test_data::kTestCorruptedU2fSignResponse)),
-          apdu::ApduResponse::Status::SW_NO_ERROR)
-          .GetEncodedResponse());
-}
-
-// static
-void MockFidoDevice::WinkDoNothing(WinkCallback& cb) {
-  std::move(cb).Run();
-}
-
 void MockFidoDevice::ExpectWinkedAtLeastOnce() {
   EXPECT_CALL(*this, TryWinkRef(::testing::_)).Times(::testing::AtLeast(1));
 }
diff --git a/device/fido/mock_fido_device.h b/device/fido/mock_fido_device.h
index e8afa2c..cabfea9 100644
--- a/device/fido/mock_fido_device.h
+++ b/device/fido/mock_fido_device.h
@@ -40,23 +40,6 @@
   MOCK_METHOD2(DeviceTransactPtr,
                void(const std::vector<uint8_t>& command, DeviceCallback& cb));
   void DeviceTransact(std::vector<uint8_t> command, DeviceCallback cb) override;
-
-  // Old interface ------------------------------------------------------------
-
-  static void NotSatisfied(const std::vector<uint8_t>& command,
-                           DeviceCallback& cb);
-  static void WrongData(const std::vector<uint8_t>& command,
-                        DeviceCallback& cb);
-  static void NoErrorSign(const std::vector<uint8_t>& command,
-                          DeviceCallback& cb);
-  static void NoErrorRegister(const std::vector<uint8_t>& command,
-                              DeviceCallback& cb);
-  static void SignWithCorruptedResponse(const std::vector<uint8_t>& command,
-                                        DeviceCallback& cb);
-  static void WinkDoNothing(WinkCallback& cb);
-
-  // New interface ------------------------------------------------------------
-
   void ExpectWinkedAtLeastOnce();
   void ExpectCtap2CommandAndRespondWith(
       CtapRequestCommand command,
diff --git a/device/fido/u2f_command_constructor.cc b/device/fido/u2f_command_constructor.cc
index 2b4fb11..f4622d5 100644
--- a/device/fido/u2f_command_constructor.cc
+++ b/device/fido/u2f_command_constructor.cc
@@ -8,6 +8,7 @@
 #include <utility>
 
 #include "components/apdu/apdu_command.h"
+#include "device/fido/fido_constants.h"
 #include "device/fido/fido_parsing_utils.h"
 
 namespace device {
@@ -41,7 +42,7 @@
 
   return ConstructU2fRegisterCommand(
       fido_parsing_utils::CreateSHA256Hash(request.rp().rp_id()),
-      request.client_data_hash());
+      request.client_data_hash(), request.is_individual_attestation());
 }
 
 base::Optional<std::vector<uint8_t>> ConvertToU2fCheckOnlySignCommand(
@@ -66,7 +67,8 @@
   auto application_parameter =
       application_parameter_type == ApplicationParameterType::kPrimary
           ? fido_parsing_utils::CreateSHA256Hash(request.rp_id())
-          : std::vector<uint8_t>();
+          : request.alternative_application_parameter().value_or(
+                std::vector<uint8_t>());
 
   return ConstructU2fSignCommand(std::move(application_parameter),
                                  request.client_data_hash(), key_handle,
@@ -123,8 +125,11 @@
   return command.GetEncodedCommand();
 }
 
-base::Optional<std::vector<uint8_t>> ConstructBogusU2fRegistrationCommand() {
-  return ConstructU2fRegisterCommand(kBogusAppParam, kBogusChallenge);
+std::vector<uint8_t> ConstructBogusU2fRegistrationCommand() {
+  auto bogus_register_cmd =
+      ConstructU2fRegisterCommand(kBogusAppParam, kBogusChallenge);
+  DCHECK(bogus_register_cmd);
+  return *bogus_register_cmd;
 }
 
 }  // namespace device
diff --git a/device/fido/u2f_command_constructor.h b/device/fido/u2f_command_constructor.h
index 69161d1..f619804 100644
--- a/device/fido/u2f_command_constructor.h
+++ b/device/fido/u2f_command_constructor.h
@@ -14,7 +14,6 @@
 #include "base/optional.h"
 #include "device/fido/ctap_get_assertion_request.h"
 #include "device/fido/ctap_make_credential_request.h"
-#include "device/fido/fido_constants.h"
 
 namespace device {
 
@@ -72,7 +71,7 @@
     bool check_only = false);
 
 COMPONENT_EXPORT(DEVICE_FIDO)
-base::Optional<std::vector<uint8_t>> ConstructBogusU2fRegistrationCommand();
+std::vector<uint8_t> ConstructBogusU2fRegistrationCommand();
 
 }  // namespace device
 
diff --git a/device/fido/u2f_register.cc b/device/fido/u2f_register.cc
deleted file mode 100644
index a05818e..0000000
--- a/device/fido/u2f_register.cc
+++ /dev/null
@@ -1,174 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "device/fido/u2f_register.h"
-
-#include <utility>
-
-#include "base/stl_util.h"
-#include "components/apdu/apdu_command.h"
-#include "components/apdu/apdu_response.h"
-#include "device/fido/authenticator_make_credential_response.h"
-#include "device/fido/u2f_command_constructor.h"
-#include "services/service_manager/public/cpp/connector.h"
-
-namespace device {
-
-// static
-std::unique_ptr<U2fRequest> U2fRegister::TryRegistration(
-    service_manager::Connector* connector,
-    const base::flat_set<FidoTransportProtocol>& transports,
-    std::vector<std::vector<uint8_t>> registered_keys,
-    std::vector<uint8_t> challenge_digest,
-    std::vector<uint8_t> application_parameter,
-    bool individual_attestation_ok,
-    RegisterResponseCallback completion_callback) {
-  std::unique_ptr<U2fRequest> request = std::make_unique<U2fRegister>(
-      connector, transports, std::move(registered_keys),
-      std::move(challenge_digest), std::move(application_parameter),
-      individual_attestation_ok, std::move(completion_callback));
-  request->Start();
-  return request;
-}
-
-U2fRegister::U2fRegister(
-    service_manager::Connector* connector,
-    const base::flat_set<FidoTransportProtocol>& transports,
-    std::vector<std::vector<uint8_t>> registered_keys,
-    std::vector<uint8_t> challenge_digest,
-    std::vector<uint8_t> application_parameter,
-    bool individual_attestation_ok,
-    RegisterResponseCallback completion_callback)
-    : U2fRequest(connector,
-                 transports,
-                 std::move(application_parameter),
-                 std::move(challenge_digest),
-                 std::move(registered_keys)),
-      individual_attestation_ok_(individual_attestation_ok),
-      completion_callback_(std::move(completion_callback)),
-      weak_factory_(this) {}
-
-U2fRegister::~U2fRegister() = default;
-
-void U2fRegister::TryDevice() {
-  DCHECK(current_device_);
-  if (!registered_keys_.empty() && !CheckedForDuplicateRegistration()) {
-    auto it = registered_keys_.cbegin();
-    InitiateDeviceTransaction(
-        GetU2fSignApduCommand(application_parameter_, *it,
-                              true /* check_only */),
-        base::BindOnce(&U2fRegister::OnTryCheckRegistration,
-                       weak_factory_.GetWeakPtr(), it));
-  } else {
-    InitiateDeviceTransaction(
-        GetU2fRegisterApduCommand(individual_attestation_ok_),
-        base::BindOnce(&U2fRegister::OnTryDevice, weak_factory_.GetWeakPtr(),
-                       false /* is_duplicate_registration */));
-  }
-}
-
-void U2fRegister::OnTryCheckRegistration(
-    std::vector<std::vector<uint8_t>>::const_iterator it,
-    base::Optional<std::vector<uint8_t>> response) {
-  const auto apdu_response =
-      response ? apdu::ApduResponse::CreateFromMessage(std::move(*response))
-               : base::nullopt;
-  auto return_code = apdu_response ? apdu_response->status()
-                                   : apdu::ApduResponse::Status::SW_WRONG_DATA;
-
-  switch (return_code) {
-    case apdu::ApduResponse::Status::SW_NO_ERROR:
-    case apdu::ApduResponse::Status::SW_CONDITIONS_NOT_SATISFIED: {
-      // Duplicate registration found. Call bogus registration to check for
-      // user presence (touch) and terminate the registration process.
-      InitiateDeviceTransaction(
-          ConstructBogusU2fRegistrationCommand(),
-          base::BindOnce(&U2fRegister::OnTryDevice, weak_factory_.GetWeakPtr(),
-                         true /* is_duplicate_registration */));
-      break;
-    }
-
-    case apdu::ApduResponse::Status::SW_WRONG_DATA:
-      // Continue to iterate through the provided key handles in the exclude
-      // list and check for already registered keys.
-      if (++it != registered_keys_.end()) {
-        InitiateDeviceTransaction(
-            GetU2fSignApduCommand(application_parameter_, *it,
-                                  true /* check_only */),
-            base::BindOnce(&U2fRegister::OnTryCheckRegistration,
-                           weak_factory_.GetWeakPtr(), it));
-      } else {
-        checked_device_id_list_.insert(current_device_->GetId());
-        if (devices_.empty()) {
-          // When all devices have been checked, proceed to registration.
-          CompleteNewDeviceRegistration();
-        } else {
-          state_ = State::IDLE;
-          Transition();
-        }
-      }
-      break;
-    default:
-      // Some sort of failure occurred. Abandon this device and move on.
-      AbandonCurrentDeviceAndTransition();
-      break;
-  }
-}
-
-void U2fRegister::CompleteNewDeviceRegistration() {
-  if (current_device_)
-    attempted_devices_.push_back(std::move(current_device_));
-
-  devices_.splice(devices_.end(), std::move(attempted_devices_));
-  state_ = State::IDLE;
-  Transition();
-  return;
-}
-
-bool U2fRegister::CheckedForDuplicateRegistration() {
-  return base::ContainsKey(checked_device_id_list_, current_device_->GetId());
-}
-
-void U2fRegister::OnTryDevice(bool is_duplicate_registration,
-                              base::Optional<std::vector<uint8_t>> response) {
-  const auto apdu_response =
-      response ? apdu::ApduResponse::CreateFromMessage(std::move(*response))
-               : base::nullopt;
-  auto return_code = apdu_response ? apdu_response->status()
-                                   : apdu::ApduResponse::Status::SW_WRONG_DATA;
-  switch (return_code) {
-    case apdu::ApduResponse::Status::SW_NO_ERROR: {
-      state_ = State::COMPLETE;
-      if (is_duplicate_registration) {
-        std::move(completion_callback_)
-            .Run(FidoReturnCode::kUserConsentButCredentialExcluded,
-                 base::nullopt);
-        break;
-      }
-      auto response =
-          AuthenticatorMakeCredentialResponse::CreateFromU2fRegisterResponse(
-              application_parameter_, apdu_response->data());
-      if (!response) {
-        // The response data was corrupted / didn't parse properly.
-        std::move(completion_callback_)
-            .Run(FidoReturnCode::kAuthenticatorResponseInvalid, base::nullopt);
-        break;
-      }
-      std::move(completion_callback_)
-          .Run(FidoReturnCode::kSuccess, std::move(response));
-      break;
-    }
-    case apdu::ApduResponse::Status::SW_CONDITIONS_NOT_SATISFIED:
-      // Waiting for user touch, move on and try this device later.
-      state_ = State::IDLE;
-      Transition();
-      break;
-    default:
-      // An error has occurred, quit trying this device.
-      AbandonCurrentDeviceAndTransition();
-      break;
-  }
-}
-
-}  // namespace device
diff --git a/device/fido/u2f_register.h b/device/fido/u2f_register.h
deleted file mode 100644
index 139d806..0000000
--- a/device/fido/u2f_register.h
+++ /dev/null
@@ -1,85 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef DEVICE_FIDO_U2F_REGISTER_H_
-#define DEVICE_FIDO_U2F_REGISTER_H_
-
-#include <memory>
-#include <set>
-#include <string>
-#include <vector>
-
-#include "base/component_export.h"
-#include "base/containers/flat_set.h"
-#include "base/macros.h"
-#include "base/optional.h"
-#include "device/fido/authenticator_make_credential_response.h"
-#include "device/fido/fido_constants.h"
-#include "device/fido/fido_transport_protocol.h"
-#include "device/fido/u2f_request.h"
-
-namespace service_manager {
-class Connector;
-};
-
-namespace device {
-
-class COMPONENT_EXPORT(DEVICE_FIDO) U2fRegister : public U2fRequest {
- public:
-  using RegisterResponseCallback = base::OnceCallback<void(
-      FidoReturnCode status_code,
-      base::Optional<AuthenticatorMakeCredentialResponse> response_data)>;
-
-  static std::unique_ptr<U2fRequest> TryRegistration(
-      service_manager::Connector* connector,
-      const base::flat_set<FidoTransportProtocol>& transports,
-      std::vector<std::vector<uint8_t>> registered_keys,
-      std::vector<uint8_t> challenge_digest,
-      std::vector<uint8_t> application_parameter,
-      bool individual_attestation_ok,
-      RegisterResponseCallback completion_callback);
-
-  U2fRegister(service_manager::Connector* connector,
-              const base::flat_set<FidoTransportProtocol>& transports,
-              std::vector<std::vector<uint8_t>> registered_keys,
-              std::vector<uint8_t> challenge_digest,
-              std::vector<uint8_t> application_parameter,
-              bool individual_attestation_ok,
-              RegisterResponseCallback completion_callback);
-  ~U2fRegister() override;
-
- private:
-  void TryDevice() override;
-  void OnTryDevice(bool is_duplicate_registration,
-                   base::Optional<std::vector<uint8_t>> response);
-
-  // Callback function called when non-empty exclude list was provided. This
-  // function iterates through all key handles in |registered_keys_| for all
-  // devices and checks for already registered keys.
-  void OnTryCheckRegistration(
-      std::vector<std::vector<uint8_t>>::const_iterator it,
-      base::Optional<std::vector<uint8_t>> response);
-  // Function handling registration flow after all devices were checked for
-  // already registered keys.
-  void CompleteNewDeviceRegistration();
-  // Returns whether |current_device_| has been checked for duplicate
-  // registration for all key handles provided in |registered_keys_|.
-  bool CheckedForDuplicateRegistration();
-
-  // Indicates whether the token should be signaled that using an individual
-  // attestation certificate is acceptable.
-  const bool individual_attestation_ok_;
-  RegisterResponseCallback completion_callback_;
-
-  // List of authenticators that did not create any of the key handles in the
-  // exclude list.
-  std::set<std::string> checked_device_id_list_;
-  base::WeakPtrFactory<U2fRegister> weak_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(U2fRegister);
-};
-
-}  // namespace device
-
-#endif  // DEVICE_FIDO_U2F_REGISTER_H_
diff --git a/device/fido/u2f_register_operation.cc b/device/fido/u2f_register_operation.cc
new file mode 100644
index 0000000..5451cca
--- /dev/null
+++ b/device/fido/u2f_register_operation.cc
@@ -0,0 +1,150 @@
+// 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 "device/fido/u2f_register_operation.h"
+
+#include <utility>
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/threading/sequenced_task_runner_handle.h"
+#include "components/apdu/apdu_response.h"
+#include "device/fido/authenticator_make_credential_response.h"
+#include "device/fido/ctap_make_credential_request.h"
+#include "device/fido/device_response_converter.h"
+#include "device/fido/fido_constants.h"
+#include "device/fido/fido_device.h"
+#include "device/fido/fido_parsing_utils.h"
+#include "device/fido/u2f_command_constructor.h"
+
+namespace device {
+
+U2fRegisterOperation::U2fRegisterOperation(
+    FidoDevice* device,
+    const CtapMakeCredentialRequest& request,
+    DeviceResponseCallback callback)
+    : DeviceOperation(device, request, std::move(callback)),
+      weak_factory_(this) {}
+
+U2fRegisterOperation::~U2fRegisterOperation() = default;
+
+void U2fRegisterOperation::Start() {
+  DCHECK(IsConvertibleToU2fRegisterCommand(request()));
+
+  const auto& exclude_list = request().exclude_list();
+  if (!exclude_list || exclude_list->empty()) {
+    TryRegistration(false /* is_duplicate_registration */);
+  } else {
+    auto it = request().exclude_list()->cbegin();
+    DispatchDeviceRequest(
+        ConvertToU2fCheckOnlySignCommand(request(), *it),
+        base::BindOnce(&U2fRegisterOperation::OnCheckForExcludedKeyHandle,
+                       weak_factory_.GetWeakPtr(), it));
+  }
+}
+
+void U2fRegisterOperation::TryRegistration(bool is_duplicate_registration) {
+  auto command = is_duplicate_registration
+                     ? ConstructBogusU2fRegistrationCommand()
+                     : ConvertToU2fRegisterCommand(request());
+
+  DispatchDeviceRequest(
+      std::move(command),
+      base::BindOnce(&U2fRegisterOperation::OnRegisterResponseReceived,
+                     weak_factory_.GetWeakPtr(), is_duplicate_registration));
+}
+
+void U2fRegisterOperation::OnRegisterResponseReceived(
+    bool is_duplicate_registration,
+    base::Optional<std::vector<uint8_t>> device_response) {
+  const auto& apdu_response =
+      device_response
+          ? apdu::ApduResponse::CreateFromMessage(std::move(*device_response))
+          : base::nullopt;
+  auto return_code = apdu_response ? apdu_response->status()
+                                   : apdu::ApduResponse::Status::SW_WRONG_DATA;
+
+  switch (return_code) {
+    case apdu::ApduResponse::Status::SW_NO_ERROR: {
+      if (is_duplicate_registration) {
+        std::move(callback())
+            .Run(CtapDeviceResponseCode::kCtap2ErrCredentialExcluded,
+                 base::nullopt);
+        break;
+      }
+
+      auto response =
+          AuthenticatorMakeCredentialResponse::CreateFromU2fRegisterResponse(
+              fido_parsing_utils::CreateSHA256Hash(request().rp().rp_id()),
+              apdu_response->data());
+      std::move(callback())
+          .Run(CtapDeviceResponseCode::kSuccess, std::move(response));
+      break;
+    }
+    case apdu::ApduResponse::Status::SW_CONDITIONS_NOT_SATISFIED:
+      // Waiting for user touch, retry after delay.
+      base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
+          FROM_HERE,
+          base::BindOnce(&U2fRegisterOperation::TryRegistration,
+                         weak_factory_.GetWeakPtr(), is_duplicate_registration),
+          kU2fRetryDelay);
+
+      break;
+    default:
+      // An error has occurred, quit trying this device.
+      std::move(callback())
+          .Run(CtapDeviceResponseCode::kCtap2ErrOther, base::nullopt);
+      break;
+  }
+}
+
+void U2fRegisterOperation::OnCheckForExcludedKeyHandle(
+    ExcludeListIterator it,
+    base::Optional<std::vector<uint8_t>> device_response) {
+  const auto& apdu_response =
+      device_response
+          ? apdu::ApduResponse::CreateFromMessage(std::move(*device_response))
+          : base::nullopt;
+  auto return_code = apdu_response ? apdu_response->status()
+                                   : apdu::ApduResponse::Status::SW_WRONG_DATA;
+  switch (return_code) {
+    case apdu::ApduResponse::Status::SW_NO_ERROR:
+    case apdu::ApduResponse::Status::SW_CONDITIONS_NOT_SATISFIED: {
+      // Duplicate registration found. Call bogus registration to check for
+      // user presence (touch) and terminate the registration process.
+      DispatchDeviceRequest(
+          ConstructBogusU2fRegistrationCommand(),
+          base::BindOnce(&U2fRegisterOperation::OnRegisterResponseReceived,
+                         weak_factory_.GetWeakPtr(),
+                         true /* is_duplicate_registration */));
+      break;
+    }
+
+    case apdu::ApduResponse::Status::SW_WRONG_DATA:
+      // Continue to iterate through the provided key handles in the exclude
+      // list and check for already registered keys.
+      if (++it != request().exclude_list()->cend()) {
+        DispatchDeviceRequest(
+            ConvertToU2fCheckOnlySignCommand(request(), *it),
+            base::BindOnce(&U2fRegisterOperation::OnCheckForExcludedKeyHandle,
+                           weak_factory_.GetWeakPtr(), it));
+      } else {
+        // Reached the end of exclude list with no duplicate credential.
+        // Proceed with registration.
+        DispatchDeviceRequest(
+            ConvertToU2fRegisterCommand(request()),
+            base::BindOnce(&U2fRegisterOperation::OnRegisterResponseReceived,
+                           weak_factory_.GetWeakPtr(),
+                           false /* is_duplicate_registration */));
+      }
+      break;
+    default:
+      // Some sort of failure occurred. Silently drop device request.
+      std::move(callback())
+          .Run(CtapDeviceResponseCode::kCtap2ErrOther, base::nullopt);
+      break;
+  }
+}
+
+}  // namespace device
diff --git a/device/fido/u2f_register_operation.h b/device/fido/u2f_register_operation.h
new file mode 100644
index 0000000..39a6fd1
--- /dev/null
+++ b/device/fido/u2f_register_operation.h
@@ -0,0 +1,61 @@
+// 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 DEVICE_FIDO_U2F_REGISTER_OPERATION_H_
+#define DEVICE_FIDO_U2F_REGISTER_OPERATION_H_
+
+#include <stdint.h>
+
+#include <vector>
+
+#include "base/component_export.h"
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "base/optional.h"
+#include "device/fido/device_operation.h"
+
+namespace device {
+
+class FidoDevice;
+class CtapMakeCredentialRequest;
+class AuthenticatorMakeCredentialResponse;
+class PublicKeyCredentialDescriptor;
+
+// Represents per device registration logic for U2F tokens. Handles regular U2F
+// registration as well as the logic of iterating key handles in the exclude
+// list and conducting check-only U2F sign to prevent duplicate registration.
+// U2fRegistrationOperation is owned by MakeCredentialTask and |request_| is
+// also owned by MakeCredentialTask.
+class COMPONENT_EXPORT(DEVICE_FIDO) U2fRegisterOperation
+    : public DeviceOperation<CtapMakeCredentialRequest,
+                             AuthenticatorMakeCredentialResponse> {
+ public:
+  U2fRegisterOperation(FidoDevice* device,
+                       const CtapMakeCredentialRequest& request,
+                       DeviceResponseCallback callback);
+  ~U2fRegisterOperation() override;
+
+  // DeviceOperation:
+  void Start() override;
+
+ private:
+  using ExcludeListIterator =
+      std::vector<PublicKeyCredentialDescriptor>::const_iterator;
+
+  void TryRegistration(bool is_duplicate_registration);
+  void OnRegisterResponseReceived(
+      bool is_duplicate_registration,
+      base::Optional<std::vector<uint8_t>> device_response);
+  void OnCheckForExcludedKeyHandle(
+      ExcludeListIterator it,
+      base::Optional<std::vector<uint8_t>> device_response);
+
+  base::WeakPtrFactory<U2fRegisterOperation> weak_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(U2fRegisterOperation);
+};
+
+}  // namespace device
+
+#endif  // DEVICE_FIDO_U2F_REGISTER_OPERATION_H_
diff --git a/device/fido/u2f_register_operation_unittest.cc b/device/fido/u2f_register_operation_unittest.cc
new file mode 100644
index 0000000..5801195
--- /dev/null
+++ b/device/fido/u2f_register_operation_unittest.cc
@@ -0,0 +1,265 @@
+// 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 "device/fido/u2f_register_operation.h"
+
+#include <memory>
+#include <utility>
+
+#include "base/test/scoped_task_environment.h"
+#include "device/fido/authenticator_make_credential_response.h"
+#include "device/fido/ctap_make_credential_request.h"
+#include "device/fido/fido_constants.h"
+#include "device/fido/fido_parsing_utils.h"
+#include "device/fido/fido_test_data.h"
+#include "device/fido/mock_fido_device.h"
+#include "device/fido/test_callback_receiver.h"
+#include "device/fido/virtual_u2f_device.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace device {
+
+using ::testing::_;
+
+namespace {
+
+// Creates a CtapMakeCredentialRequest with given |registered_keys| as
+// exclude list.
+CtapMakeCredentialRequest CreateRegisterRequestWithRegisteredKeys(
+    std::vector<PublicKeyCredentialDescriptor> registered_keys,
+    bool is_individual_attestation = false) {
+  PublicKeyCredentialRpEntity rp(test_data::kRelyingPartyId);
+  PublicKeyCredentialUserEntity user(
+      fido_parsing_utils::Materialize(test_data::kUserId));
+
+  CtapMakeCredentialRequest request(
+      fido_parsing_utils::Materialize(test_data::kClientDataHash),
+      std::move(rp), std::move(user),
+      PublicKeyCredentialParams(
+          std::vector<PublicKeyCredentialParams::CredentialInfo>(1)));
+  request.SetExcludeList(std::move(registered_keys));
+  request.SetIsIndividualAttestation(is_individual_attestation);
+  return request;
+}
+
+// Creates a CtapMakeCredentialRequest with an empty exclude list.
+CtapMakeCredentialRequest CreateRegisterRequest(
+    bool is_individual_attestation = false) {
+  return CreateRegisterRequestWithRegisteredKeys(
+      std::vector<PublicKeyCredentialDescriptor>(), is_individual_attestation);
+}
+
+using TestRegisterCallback = ::device::test::StatusAndValueCallbackReceiver<
+    CtapDeviceResponseCode,
+    base::Optional<AuthenticatorMakeCredentialResponse>>;
+
+}  // namespace
+
+class U2fRegisterOperationTest : public ::testing::Test {
+ public:
+  TestRegisterCallback& register_callback_receiver() {
+    return register_callback_receiver_;
+  }
+
+ private:
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
+  TestRegisterCallback register_callback_receiver_;
+};
+
+TEST_F(U2fRegisterOperationTest, TestRegisterSuccess) {
+  auto request = CreateRegisterRequest();
+  auto device = std::make_unique<MockFidoDevice>();
+  EXPECT_CALL(*device, GetId()).WillRepeatedly(testing::Return("device"));
+  device->ExpectRequestAndRespondWith(
+      test_data::kU2fRegisterCommandApdu,
+      test_data::kApduEncodedNoErrorRegisterResponse);
+
+  auto u2f_register = std::make_unique<U2fRegisterOperation>(
+      device.get(), std::move(request),
+      register_callback_receiver().callback());
+  u2f_register->Start();
+  register_callback_receiver().WaitForCallback();
+
+  EXPECT_EQ(CtapDeviceResponseCode::kSuccess,
+            register_callback_receiver().status());
+  ASSERT_TRUE(register_callback_receiver().value());
+  EXPECT_THAT(register_callback_receiver().value()->raw_credential_id(),
+              ::testing::ElementsAreArray(test_data::kU2fSignKeyHandle));
+}
+
+TEST_F(U2fRegisterOperationTest, TestRegisterSuccessWithFake) {
+  auto request = CreateRegisterRequest();
+
+  auto device = std::make_unique<VirtualU2fDevice>();
+  auto u2f_register = std::make_unique<U2fRegisterOperation>(
+      device.get(), std::move(request),
+      register_callback_receiver().callback());
+  u2f_register->Start();
+  register_callback_receiver().WaitForCallback();
+
+  EXPECT_EQ(CtapDeviceResponseCode::kSuccess,
+            register_callback_receiver().status());
+  // We don't verify the response from the fake, but do a quick sanity check.
+  ASSERT_TRUE(register_callback_receiver().value());
+  EXPECT_EQ(32ul,
+            register_callback_receiver().value()->raw_credential_id().size());
+}
+
+TEST_F(U2fRegisterOperationTest, TestDelayedSuccess) {
+  auto request = CreateRegisterRequest();
+
+  auto device = std::make_unique<MockFidoDevice>();
+  EXPECT_CALL(*device, GetId()).WillRepeatedly(testing::Return("device"));
+
+  // Device error out once waiting for user presence before retrying.
+  ::testing::InSequence s;
+  device->ExpectRequestAndRespondWith(
+      test_data::kU2fRegisterCommandApdu,
+      test_data::kU2fConditionNotSatisfiedApduResponse);
+
+  device->ExpectRequestAndRespondWith(
+      test_data::kU2fRegisterCommandApdu,
+      test_data::kApduEncodedNoErrorRegisterResponse);
+
+  auto u2f_register = std::make_unique<U2fRegisterOperation>(
+      device.get(), std::move(request),
+      register_callback_receiver().callback());
+  u2f_register->Start();
+  register_callback_receiver().WaitForCallback();
+
+  EXPECT_EQ(CtapDeviceResponseCode::kSuccess,
+            register_callback_receiver().status());
+  ASSERT_TRUE(register_callback_receiver().value());
+  EXPECT_THAT(register_callback_receiver().value()->raw_credential_id(),
+              ::testing::ElementsAreArray(test_data::kU2fSignKeyHandle));
+}
+
+// Tests a scenario where a single device is connected and registration call
+// is received with two unknown key handles. We expect that two check
+// only sign-in calls be processed before registration.
+TEST_F(U2fRegisterOperationTest, TestRegistrationWithExclusionList) {
+  auto request = CreateRegisterRequestWithRegisteredKeys(
+      {PublicKeyCredentialDescriptor(
+           CredentialType::kPublicKey,
+           fido_parsing_utils::Materialize(test_data::kKeyHandleAlpha)),
+       PublicKeyCredentialDescriptor(
+           CredentialType::kPublicKey,
+           fido_parsing_utils::Materialize(test_data::kKeyHandleBeta))});
+
+  auto device = std::make_unique<MockFidoDevice>();
+  EXPECT_CALL(*device, GetId()).WillRepeatedly(::testing::Return("device"));
+  // DeviceTransact() will be called three times including two check only
+  // sign-in calls and one registration call. For the first two calls, device
+  // will invoke MockFidoDevice::WrongData as the authenticator did not create
+  // the two key handles provided in the exclude list. At the third call,
+  // MockFidoDevice::NoErrorRegister will be invoked after registration.
+  ::testing::InSequence s;
+  device->ExpectRequestAndRespondWith(
+      test_data::kU2fCheckOnlySignCommandApduWithKeyAlpha,
+      test_data::kU2fWrongDataApduResponse);
+  device->ExpectRequestAndRespondWith(
+      test_data::kU2fCheckOnlySignCommandApduWithKeyBeta,
+      test_data::kU2fWrongDataApduResponse);
+  device->ExpectRequestAndRespondWith(
+      test_data::kU2fRegisterCommandApdu,
+      test_data::kApduEncodedNoErrorRegisterResponse);
+
+  auto u2f_register = std::make_unique<U2fRegisterOperation>(
+      device.get(), std::move(request),
+      register_callback_receiver().callback());
+  u2f_register->Start();
+  register_callback_receiver().WaitForCallback();
+
+  ASSERT_TRUE(register_callback_receiver().value());
+  EXPECT_EQ(CtapDeviceResponseCode::kSuccess,
+            register_callback_receiver().status());
+  EXPECT_THAT(register_callback_receiver().value()->raw_credential_id(),
+              ::testing::ElementsAreArray(test_data::kU2fSignKeyHandle));
+}
+
+// Tests a scenario where single device is connected and registration is
+// called with a key in the exclude list that was created by this device. We
+// assume that the duplicate key is the last key handle in the exclude list.
+// Therefore, after duplicate key handle is found, the process is expected to
+// terminate after calling bogus registration which checks for user presence.
+TEST_F(U2fRegisterOperationTest, TestRegistrationWithDuplicateHandle) {
+  // Simulate two unknown key handles followed by a duplicate key.
+  auto request = CreateRegisterRequestWithRegisteredKeys(
+      {PublicKeyCredentialDescriptor(
+           CredentialType::kPublicKey,
+           fido_parsing_utils::Materialize(test_data::kKeyHandleAlpha)),
+       PublicKeyCredentialDescriptor(
+           CredentialType::kPublicKey,
+           fido_parsing_utils::Materialize(test_data::kKeyHandleBeta)),
+       PublicKeyCredentialDescriptor(
+           CredentialType::kPublicKey,
+           fido_parsing_utils::Materialize(test_data::kKeyHandleGamma))});
+
+  auto device = std::make_unique<MockFidoDevice>();
+  EXPECT_CALL(*device, GetId()).WillRepeatedly(::testing::Return("device"));
+  // For three keys in exclude list, the first two keys will invoke
+  // MockFidoDevice::WrongData and the final duplicate key handle will invoke
+  // MockFidoDevice::NoErrorSign. Once duplicate key handle is found, bogus
+  // registration is called to confirm user presence. This invokes
+  // MockFidoDevice::NoErrorRegister.
+  ::testing::InSequence s;
+  device->ExpectRequestAndRespondWith(
+      test_data::kU2fCheckOnlySignCommandApduWithKeyAlpha,
+      test_data::kU2fWrongDataApduResponse);
+  device->ExpectRequestAndRespondWith(
+      test_data::kU2fCheckOnlySignCommandApduWithKeyBeta,
+      test_data::kU2fWrongDataApduResponse);
+  device->ExpectRequestAndRespondWith(
+      test_data::kU2fCheckOnlySignCommandApduWithKeyGamma,
+      test_data::kApduEncodedNoErrorSignResponse);
+  device->ExpectRequestAndRespondWith(
+      test_data::kU2fFakeRegisterCommand,
+      test_data::kApduEncodedNoErrorRegisterResponse);
+
+  auto u2f_register = std::make_unique<U2fRegisterOperation>(
+      device.get(), std::move(request),
+      register_callback_receiver().callback());
+  u2f_register->Start();
+  register_callback_receiver().WaitForCallback();
+
+  EXPECT_EQ(CtapDeviceResponseCode::kCtap2ErrCredentialExcluded,
+            register_callback_receiver().status());
+  EXPECT_FALSE(register_callback_receiver().value());
+}
+
+MATCHER_P(IndicatesIndividualAttestation, expected, "") {
+  return arg.size() > 2 && ((arg[2] & 0x80) == 0x80) == expected;
+}
+
+TEST_F(U2fRegisterOperationTest, TestIndividualAttestation) {
+  // Test that the individual attestation flag is correctly reflected in the
+  // resulting registration APDU.
+  for (const auto& individual_attestation : {false, true}) {
+    SCOPED_TRACE(individual_attestation);
+    TestRegisterCallback cb;
+    auto request = CreateRegisterRequest(individual_attestation);
+
+    auto device = std::make_unique<MockFidoDevice>();
+    EXPECT_CALL(*device, GetId()).WillRepeatedly(::testing::Return("device"));
+
+    device->ExpectRequestAndRespondWith(
+        individual_attestation
+            ? test_data::kU2fRegisterCommandApduWithIndividualAttestation
+            : test_data::kU2fRegisterCommandApdu,
+        test_data::kApduEncodedNoErrorRegisterResponse);
+
+    auto u2f_register = std::make_unique<U2fRegisterOperation>(
+        device.get(), std::move(request), cb.callback());
+    u2f_register->Start();
+    cb.WaitForCallback();
+
+    EXPECT_EQ(CtapDeviceResponseCode::kSuccess, cb.status());
+    ASSERT_TRUE(cb.value());
+    EXPECT_THAT(cb.value()->raw_credential_id(),
+                ::testing::ElementsAreArray(test_data::kU2fSignKeyHandle));
+  }
+}
+
+}  // namespace device
diff --git a/device/fido/u2f_register_unittest.cc b/device/fido/u2f_register_unittest.cc
deleted file mode 100644
index b298345..0000000
--- a/device/fido/u2f_register_unittest.cc
+++ /dev/null
@@ -1,506 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "device/fido/u2f_register.h"
-
-#include <iterator>
-#include <utility>
-
-#include "base/run_loop.h"
-#include "base/test/scoped_task_environment.h"
-#include "device/fido/authenticator_make_credential_response.h"
-#include "device/fido/fake_fido_discovery.h"
-#include "device/fido/fido_constants.h"
-#include "device/fido/fido_parsing_utils.h"
-#include "device/fido/fido_test_data.h"
-#include "device/fido/fido_transport_protocol.h"
-#include "device/fido/mock_fido_device.h"
-#include "device/fido/test_callback_receiver.h"
-#include "device/fido/virtual_u2f_device.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace device {
-
-using ::testing::_;
-
-namespace {
-
-std::vector<uint8_t> GetTestRegisterRequest() {
-  return fido_parsing_utils::Materialize(test_data::kU2fRegisterCommandApdu);
-}
-
-using TestRegisterCallback = ::device::test::StatusAndValueCallbackReceiver<
-    FidoReturnCode,
-    base::Optional<AuthenticatorMakeCredentialResponse>>;
-
-}  // namespace
-
-class U2fRegisterTest : public ::testing::Test {
- public:
-  void ForgeNextHidDiscovery() {
-    discovery_ = scoped_fake_discovery_factory_.ForgeNextHidDiscovery();
-  }
-
-  std::unique_ptr<U2fRegister> CreateRegisterRequest() {
-    return CreateRegisterRequestWithRegisteredKeys(
-        std::vector<std::vector<uint8_t>>());
-  }
-
-  // Creates a U2F register request with `none` attestation, and the given
-  // previously |registered_keys|.
-  std::unique_ptr<U2fRegister> CreateRegisterRequestWithRegisteredKeys(
-      std::vector<std::vector<uint8_t>> registered_keys) {
-    ForgeNextHidDiscovery();
-    return std::make_unique<U2fRegister>(
-        nullptr /* connector */,
-        base::flat_set<FidoTransportProtocol>(
-            {FidoTransportProtocol::kUsbHumanInterfaceDevice}),
-        registered_keys,
-        fido_parsing_utils::Materialize(test_data::kChallengeParameter),
-        fido_parsing_utils::Materialize(test_data::kApplicationParameter),
-        false /* is_individual_attestation */,
-        register_callback_receiver_.callback());
-  }
-
-  test::FakeFidoDiscovery* discovery() const { return discovery_; }
-
-  TestRegisterCallback& register_callback_receiver() {
-    return register_callback_receiver_;
-  }
-
- protected:
-  base::test::ScopedTaskEnvironment scoped_task_environment_;
-  std::vector<std::vector<uint8_t>> key_handles_;
-  base::flat_set<FidoTransportProtocol> protocols_;
-  test::ScopedFakeFidoDiscoveryFactory scoped_fake_discovery_factory_;
-  test::FakeFidoDiscovery* discovery_;
-  TestRegisterCallback register_callback_receiver_;
-};
-
-
-TEST_F(U2fRegisterTest, TestRegisterSuccess) {
-  auto request = CreateRegisterRequest();
-  request->Start();
-  discovery()->WaitForCallToStartAndSimulateSuccess();
-
-  auto device = std::make_unique<MockFidoDevice>();
-  EXPECT_CALL(*device, GetId()).WillRepeatedly(testing::Return("device"));
-  EXPECT_CALL(*device, DeviceTransactPtr(GetTestRegisterRequest(), _))
-      .WillOnce(testing::Invoke(MockFidoDevice::NoErrorRegister));
-  EXPECT_CALL(*device, TryWinkRef(_))
-      .WillOnce(::testing::Invoke(MockFidoDevice::WinkDoNothing));
-  discovery()->AddDevice(std::move(device));
-
-  register_callback_receiver().WaitForCallback();
-  EXPECT_EQ(FidoReturnCode::kSuccess, register_callback_receiver().status());
-  ASSERT_TRUE(register_callback_receiver().value());
-  EXPECT_THAT(register_callback_receiver().value()->raw_credential_id(),
-              ::testing::ElementsAreArray(test_data::kU2fSignKeyHandle));
-}
-
-TEST_F(U2fRegisterTest, TestRegisterSuccessWithFake) {
-  auto request = CreateRegisterRequest();
-  request->Start();
-  discovery()->WaitForCallToStartAndSimulateSuccess();
-
-  auto device = std::make_unique<VirtualU2fDevice>();
-  discovery()->AddDevice(std::move(device));
-
-  register_callback_receiver().WaitForCallback();
-  EXPECT_EQ(FidoReturnCode::kSuccess, register_callback_receiver().status());
-
-  // We don't verify the response from the fake, but do a quick sanity check.
-  ASSERT_TRUE(register_callback_receiver().value());
-  EXPECT_EQ(32ul,
-            register_callback_receiver().value()->raw_credential_id().size());
-}
-
-TEST_F(U2fRegisterTest, TestDelayedSuccess) {
-  auto request = CreateRegisterRequest();
-  request->Start();
-  discovery()->WaitForCallToStartAndSimulateSuccess();
-
-  auto device = std::make_unique<MockFidoDevice>();
-  EXPECT_CALL(*device, GetId()).WillRepeatedly(testing::Return("device"));
-  // Go through the state machine twice before success.
-  EXPECT_CALL(*device, DeviceTransactPtr(GetTestRegisterRequest(), _))
-      .WillOnce(::testing::Invoke(MockFidoDevice::NotSatisfied))
-      .WillOnce(::testing::Invoke(MockFidoDevice::NoErrorRegister));
-  EXPECT_CALL(*device, TryWinkRef(_))
-      .Times(2)
-      .WillRepeatedly(::testing::Invoke(MockFidoDevice::WinkDoNothing));
-  discovery()->AddDevice(std::move(device));
-
-  register_callback_receiver().WaitForCallback();
-  EXPECT_EQ(FidoReturnCode::kSuccess, register_callback_receiver().status());
-  ASSERT_TRUE(register_callback_receiver().value());
-  EXPECT_THAT(register_callback_receiver().value()->raw_credential_id(),
-              ::testing::ElementsAreArray(test_data::kU2fSignKeyHandle));
-}
-
-TEST_F(U2fRegisterTest, TestMultipleDevices) {
-  auto request = CreateRegisterRequest();
-  request->Start();
-
-  auto device0 = std::make_unique<MockFidoDevice>();
-  EXPECT_CALL(*device0, GetId()).WillRepeatedly(::testing::Return("device0"));
-  EXPECT_CALL(*device0, DeviceTransactPtr(GetTestRegisterRequest(), _))
-      .WillOnce(::testing::Invoke(MockFidoDevice::NotSatisfied));
-  // One wink per device.
-  EXPECT_CALL(*device0, TryWinkRef(_))
-      .WillOnce(::testing::Invoke(MockFidoDevice::WinkDoNothing));
-  discovery()->AddDevice(std::move(device0));
-
-  // Second device will have a successful touch.
-  auto device1 = std::make_unique<MockFidoDevice>();
-  EXPECT_CALL(*device1, GetId()).WillRepeatedly(::testing::Return("device1"));
-  EXPECT_CALL(*device1, DeviceTransactPtr(GetTestRegisterRequest(), _))
-      .WillOnce(::testing::Invoke(MockFidoDevice::NoErrorRegister));
-  // One wink per device.
-  EXPECT_CALL(*device1, TryWinkRef(_))
-      .WillOnce(::testing::Invoke(MockFidoDevice::WinkDoNothing));
-  discovery()->AddDevice(std::move(device1));
-  discovery()->WaitForCallToStartAndSimulateSuccess();
-
-  register_callback_receiver().WaitForCallback();
-  EXPECT_EQ(FidoReturnCode::kSuccess, register_callback_receiver().status());
-  ASSERT_TRUE(register_callback_receiver().value());
-  EXPECT_THAT(register_callback_receiver().value()->raw_credential_id(),
-              ::testing::ElementsAreArray(test_data::kU2fSignKeyHandle));
-}
-
-// Tests a scenario where a single device is connected and registration call
-// is received with three unknown key handles. We expect that three check only
-// sign-in calls be processed before registration.
-TEST_F(U2fRegisterTest, TestSingleDeviceRegistrationWithExclusionList) {
-  // Simulate three unknown key handles.
-  auto request = CreateRegisterRequestWithRegisteredKeys(
-      {fido_parsing_utils::Materialize(test_data::kKeyHandleAlpha),
-       fido_parsing_utils::Materialize(test_data::kKeyHandleBeta)});
-  request->Start();
-  discovery()->WaitForCallToStartAndSimulateSuccess();
-
-  auto device = std::make_unique<MockFidoDevice>();
-  EXPECT_CALL(*device, GetId()).WillRepeatedly(::testing::Return("device"));
-  // DeviceTransact() will be called three times including two check
-  // only sign-in calls and one registration call. For the first two calls,
-  // device will invoke MockFidoDevice::WrongData as the authenticator did not
-  // create the two key handles provided in the exclude list. At the third
-  // call, MockFidoDevice::NoErrorRegister will be invoked after registration.
-  EXPECT_CALL(*device.get(),
-              DeviceTransactPtr(
-                  fido_parsing_utils::Materialize(
-                      test_data::kU2fCheckOnlySignCommandApduWithKeyAlpha),
-                  _))
-      .WillOnce(::testing::Invoke(MockFidoDevice::WrongData));
-
-  EXPECT_CALL(
-      *device.get(),
-      DeviceTransactPtr(fido_parsing_utils::Materialize(
-                            test_data::kU2fCheckOnlySignCommandApduWithKeyBeta),
-                        _))
-      .WillOnce(::testing::Invoke(MockFidoDevice::WrongData));
-
-  EXPECT_CALL(*device.get(), DeviceTransactPtr(GetTestRegisterRequest(), _))
-      .WillOnce(::testing::Invoke(MockFidoDevice::NoErrorRegister));
-
-  // TryWink() will be called twice. First during the check only sign-in. After
-  // check only sign operation is complete, request state is changed to IDLE,
-  // and TryWink() is called again before Register() is called.
-  EXPECT_CALL(*device, TryWinkRef(_))
-      .WillOnce(::testing::Invoke(MockFidoDevice::WinkDoNothing))
-      .WillOnce(::testing::Invoke(MockFidoDevice::WinkDoNothing));
-  discovery()->AddDevice(std::move(device));
-
-  register_callback_receiver().WaitForCallback();
-  ASSERT_TRUE(register_callback_receiver().value());
-  EXPECT_EQ(FidoReturnCode::kSuccess, register_callback_receiver().status());
-  EXPECT_THAT(register_callback_receiver().value()->raw_credential_id(),
-              ::testing::ElementsAreArray(test_data::kU2fSignKeyHandle));
-}
-
-// Tests a scenario where two devices are connected and registration call is
-// received with three unknown key handles. We assume that user will proceed the
-// registration with second device, "device1".
-TEST_F(U2fRegisterTest, TestMultipleDeviceRegistrationWithExclusionList) {
-  // Simulate three unknown key handles.
-  auto request = CreateRegisterRequestWithRegisteredKeys(
-      {fido_parsing_utils::Materialize(test_data::kKeyHandleAlpha),
-       fido_parsing_utils::Materialize(test_data::kKeyHandleBeta),
-       fido_parsing_utils::Materialize(test_data::kKeyHandleGamma)});
-  request->Start();
-
-  auto device0 = std::make_unique<MockFidoDevice>();
-  EXPECT_CALL(*device0, GetId()).WillRepeatedly(::testing::Return("device0"));
-  // DeviceTransact() will be called four times: three times to check for
-  // duplicate key handles and once for registration. Since user
-  // will register using "device1", the fourth call will invoke
-  // MockFidoDevice::NotSatisfied.
-  EXPECT_CALL(*device0.get(),
-              DeviceTransactPtr(
-                  fido_parsing_utils::Materialize(
-                      test_data::kU2fCheckOnlySignCommandApduWithKeyAlpha),
-                  _))
-      .WillOnce(::testing::Invoke(MockFidoDevice::WrongData));
-
-  EXPECT_CALL(
-      *device0.get(),
-      DeviceTransactPtr(fido_parsing_utils::Materialize(
-                            test_data::kU2fCheckOnlySignCommandApduWithKeyBeta),
-                        _))
-      .WillOnce(::testing::Invoke(MockFidoDevice::WrongData));
-
-  EXPECT_CALL(*device0.get(),
-              DeviceTransactPtr(
-                  fido_parsing_utils::Materialize(
-                      test_data::kU2fCheckOnlySignCommandApduWithKeyGamma),
-                  _))
-      .WillOnce(::testing::Invoke(MockFidoDevice::WrongData));
-
-  EXPECT_CALL(*device0.get(), DeviceTransactPtr(GetTestRegisterRequest(), _))
-      .WillOnce(::testing::Invoke(MockFidoDevice::NotSatisfied));
-
-  // TryWink() will be called twice on both devices -- during check only
-  // sign-in operation and during registration attempt.
-  EXPECT_CALL(*device0, TryWinkRef(_))
-      .WillOnce(::testing::Invoke(MockFidoDevice::WinkDoNothing))
-      .WillOnce(::testing::Invoke(MockFidoDevice::WinkDoNothing));
-  discovery()->AddDevice(std::move(device0));
-
-  auto device1 = std::make_unique<MockFidoDevice>();
-  EXPECT_CALL(*device1, GetId()).WillRepeatedly(testing::Return("device1"));
-  // We assume that user registers with second device. Therefore, the fourth
-  // DeviceTransact() will invoke MockFidoDevice::NoErrorRegister after
-  // successful registration.
-  EXPECT_CALL(*device1.get(),
-              DeviceTransactPtr(
-                  fido_parsing_utils::Materialize(
-                      test_data::kU2fCheckOnlySignCommandApduWithKeyAlpha),
-                  _))
-      .WillOnce(::testing::Invoke(MockFidoDevice::WrongData));
-
-  EXPECT_CALL(
-      *device1.get(),
-      DeviceTransactPtr(fido_parsing_utils::Materialize(
-                            test_data::kU2fCheckOnlySignCommandApduWithKeyBeta),
-                        _))
-      .WillOnce(::testing::Invoke(MockFidoDevice::WrongData));
-
-  EXPECT_CALL(*device1.get(),
-              DeviceTransactPtr(
-                  fido_parsing_utils::Materialize(
-                      test_data::kU2fCheckOnlySignCommandApduWithKeyGamma),
-                  _))
-      .WillOnce(::testing::Invoke(MockFidoDevice::WrongData));
-
-  EXPECT_CALL(*device1.get(), DeviceTransactPtr(GetTestRegisterRequest(), _))
-      .WillOnce(::testing::Invoke(MockFidoDevice::NoErrorRegister));
-
-  // TryWink() will be called twice on both devices -- during check only
-  // sign-in operation and during registration attempt.
-  EXPECT_CALL(*device1, TryWinkRef(_))
-      .WillOnce(::testing::Invoke(MockFidoDevice::WinkDoNothing))
-      .WillOnce(::testing::Invoke(MockFidoDevice::WinkDoNothing));
-  discovery()->AddDevice(std::move(device1));
-  discovery()->WaitForCallToStartAndSimulateSuccess();
-
-  register_callback_receiver().WaitForCallback();
-  EXPECT_EQ(FidoReturnCode::kSuccess, register_callback_receiver().status());
-  ASSERT_TRUE(register_callback_receiver().value());
-  EXPECT_THAT(register_callback_receiver().value()->raw_credential_id(),
-              ::testing::ElementsAreArray(test_data::kU2fSignKeyHandle));
-}
-
-// Tests a scenario where single device is connected and registration is called
-// with a key in the exclude list that was created by this device. We assume
-// that the duplicate key is the last key handle in the exclude list. Therefore,
-// after duplicate key handle is found, the process is expected to terminate
-// after calling bogus registration which checks for user presence.
-TEST_F(U2fRegisterTest, TestSingleDeviceRegistrationWithDuplicateHandle) {
-  // Simulate three unknown key handles followed by a duplicate key.
-  auto request = CreateRegisterRequestWithRegisteredKeys(
-      {fido_parsing_utils::Materialize(test_data::kKeyHandleAlpha),
-       fido_parsing_utils::Materialize(test_data::kKeyHandleBeta),
-       fido_parsing_utils::Materialize(test_data::kKeyHandleGamma)});
-  request->Start();
-  discovery()->WaitForCallToStartAndSimulateSuccess();
-
-  auto device = std::make_unique<MockFidoDevice>();
-  EXPECT_CALL(*device, GetId()).WillRepeatedly(::testing::Return("device"));
-  // For four keys in exclude list, the first three keys will invoke
-  // MockFidoDevice::WrongData and the final duplicate key handle will invoke
-  // MockFidoDevice::NoErrorSign. Once duplicate key handle is found, bogus
-  // registration is called to confirm user presence. This invokes
-  // MockFidoDevice::NoErrorRegister.
-  EXPECT_CALL(*device.get(),
-              DeviceTransactPtr(
-                  fido_parsing_utils::Materialize(
-                      test_data::kU2fCheckOnlySignCommandApduWithKeyAlpha),
-                  _))
-      .WillOnce(::testing::Invoke(MockFidoDevice::WrongData));
-
-  EXPECT_CALL(
-      *device.get(),
-      DeviceTransactPtr(fido_parsing_utils::Materialize(
-                            test_data::kU2fCheckOnlySignCommandApduWithKeyBeta),
-                        _))
-      .WillOnce(::testing::Invoke(MockFidoDevice::WrongData));
-
-  EXPECT_CALL(*device.get(),
-              DeviceTransactPtr(
-                  fido_parsing_utils::Materialize(
-                      test_data::kU2fCheckOnlySignCommandApduWithKeyGamma),
-                  _))
-      .WillOnce(::testing::Invoke(MockFidoDevice::NoErrorSign));
-
-  EXPECT_CALL(*device.get(),
-              DeviceTransactPtr(fido_parsing_utils::Materialize(
-                                    test_data::kU2fFakeRegisterCommand),
-                                _))
-      .WillOnce(::testing::Invoke(MockFidoDevice::NoErrorRegister));
-
-  // Since duplicate key handle is found, registration process is terminated
-  // before actual Register() is called on the device. Therefore, TryWink() is
-  // invoked once.
-  EXPECT_CALL(*device, TryWinkRef(_))
-      .WillOnce(::testing::Invoke(MockFidoDevice::WinkDoNothing));
-  discovery()->AddDevice(std::move(device));
-
-  register_callback_receiver().WaitForCallback();
-  EXPECT_EQ(FidoReturnCode::kUserConsentButCredentialExcluded,
-            register_callback_receiver().status());
-  EXPECT_FALSE(register_callback_receiver().value());
-}
-
-// Tests a scenario where one (device1) of the two devices connected has created
-// a key handle provided in exclude list. We assume that duplicate key is the
-// third key handle provided in the exclude list.
-TEST_F(U2fRegisterTest, TestMultipleDeviceRegistrationWithDuplicateHandle) {
-  // Simulate two unknown key handles followed by a duplicate key.
-  auto request = CreateRegisterRequestWithRegisteredKeys(
-      {fido_parsing_utils::Materialize(test_data::kKeyHandleAlpha),
-       fido_parsing_utils::Materialize(test_data::kKeyHandleBeta),
-       fido_parsing_utils::Materialize(test_data::kKeyHandleGamma)});
-  request->Start();
-
-  // Since the first device did not create any of the key handles provided in
-  // exclude list, we expect that check only sign() should be called
-  // four times, and all the calls to DeviceTransact() invoke
-  // MockFidoDevice::WrongData.
-  auto device0 = std::make_unique<MockFidoDevice>();
-  EXPECT_CALL(*device0, GetId()).WillRepeatedly(testing::Return("device0"));
-  EXPECT_CALL(*device0.get(),
-              DeviceTransactPtr(
-                  fido_parsing_utils::Materialize(
-                      test_data::kU2fCheckOnlySignCommandApduWithKeyAlpha),
-                  _))
-      .WillOnce(::testing::Invoke(MockFidoDevice::WrongData));
-
-  EXPECT_CALL(
-      *device0.get(),
-      DeviceTransactPtr(fido_parsing_utils::Materialize(
-                            test_data::kU2fCheckOnlySignCommandApduWithKeyBeta),
-                        _))
-      .WillOnce(::testing::Invoke(MockFidoDevice::WrongData));
-
-  EXPECT_CALL(*device0.get(),
-              DeviceTransactPtr(
-                  fido_parsing_utils::Materialize(
-                      test_data::kU2fCheckOnlySignCommandApduWithKeyGamma),
-                  _))
-      .WillOnce(::testing::Invoke(MockFidoDevice::WrongData));
-
-  EXPECT_CALL(*device0, TryWinkRef(_))
-      .WillOnce(::testing::Invoke(MockFidoDevice::WinkDoNothing));
-  discovery()->AddDevice(std::move(device0));
-
-  // Since the last key handle in exclude list is a duplicate key, we expect
-  // that the first three calls to check only sign() invoke
-  // MockFidoDevice::WrongData and that fourth sign() call invoke
-  // MockFidoDevice::NoErrorSign. After duplicate key is found, process is
-  // terminated after user presence is verified using bogus registration, which
-  // invokes MockFidoDevice::NoErrorRegister.
-  auto device1 = std::make_unique<MockFidoDevice>();
-  EXPECT_CALL(*device1, GetId()).WillRepeatedly(::testing::Return("device1"));
-  EXPECT_CALL(*device1.get(),
-              DeviceTransactPtr(
-                  fido_parsing_utils::Materialize(
-                      test_data::kU2fCheckOnlySignCommandApduWithKeyAlpha),
-                  _))
-      .WillOnce(::testing::Invoke(MockFidoDevice::WrongData));
-
-  EXPECT_CALL(
-      *device1.get(),
-      DeviceTransactPtr(fido_parsing_utils::Materialize(
-                            test_data::kU2fCheckOnlySignCommandApduWithKeyBeta),
-                        _))
-      .WillOnce(::testing::Invoke(MockFidoDevice::WrongData));
-
-  EXPECT_CALL(*device1.get(),
-              DeviceTransactPtr(
-                  fido_parsing_utils::Materialize(
-                      test_data::kU2fCheckOnlySignCommandApduWithKeyGamma),
-                  _))
-      .WillOnce(::testing::Invoke(MockFidoDevice::NoErrorSign));
-
-  EXPECT_CALL(*device1.get(),
-              DeviceTransactPtr(fido_parsing_utils::Materialize(
-                                    test_data::kU2fFakeRegisterCommand),
-                                _))
-      .WillOnce(::testing::Invoke(MockFidoDevice::NoErrorRegister));
-
-  EXPECT_CALL(*device1, TryWinkRef(_))
-      .WillOnce(::testing::Invoke(MockFidoDevice::WinkDoNothing));
-  discovery()->AddDevice(std::move(device1));
-  discovery()->WaitForCallToStartAndSimulateSuccess();
-
-  register_callback_receiver().WaitForCallback();
-  EXPECT_EQ(FidoReturnCode::kUserConsentButCredentialExcluded,
-            register_callback_receiver().status());
-  EXPECT_FALSE(register_callback_receiver().value());
-}
-
-MATCHER_P(IndicatesIndividualAttestation, expected, "") {
-  return arg.size() > 2 && ((arg[2] & 0x80) == 0x80) == expected;
-}
-
-TEST_F(U2fRegisterTest, TestIndividualAttestation) {
-  // Test that the individual attestation flag is correctly reflected in the
-  // resulting registration APDU.
-  for (const auto& individual_attestation : {false, true}) {
-    SCOPED_TRACE(individual_attestation);
-
-    ForgeNextHidDiscovery();
-    TestRegisterCallback cb;
-    auto request = std::make_unique<U2fRegister>(
-        nullptr /* connector */,
-        base::flat_set<FidoTransportProtocol>(
-            {FidoTransportProtocol::kUsbHumanInterfaceDevice}) /* transports */,
-        key_handles_,
-        fido_parsing_utils::Materialize(test_data::kChallengeParameter),
-        fido_parsing_utils::Materialize(test_data::kApplicationParameter),
-        individual_attestation, cb.callback());
-    request->Start();
-    discovery()->WaitForCallToStartAndSimulateSuccess();
-
-    auto device = std::make_unique<MockFidoDevice>();
-    EXPECT_CALL(*device, GetId()).WillRepeatedly(::testing::Return("device"));
-    EXPECT_CALL(*device,
-                DeviceTransactPtr(
-                    IndicatesIndividualAttestation(individual_attestation), _))
-        .WillOnce(::testing::Invoke(MockFidoDevice::NoErrorRegister));
-    EXPECT_CALL(*device, TryWinkRef(_))
-        .WillOnce(::testing::Invoke(MockFidoDevice::WinkDoNothing));
-    discovery()->AddDevice(std::move(device));
-
-    cb.WaitForCallback();
-    EXPECT_EQ(FidoReturnCode::kSuccess, cb.status());
-    ASSERT_TRUE(cb.value());
-    EXPECT_THAT(cb.value()->raw_credential_id(),
-                ::testing::ElementsAreArray(test_data::kU2fSignKeyHandle));
-  }
-}
-
-}  // namespace device
diff --git a/device/fido/u2f_request.cc b/device/fido/u2f_request.cc
deleted file mode 100644
index fd81c6c..0000000
--- a/device/fido/u2f_request.cc
+++ /dev/null
@@ -1,198 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "device/fido/u2f_request.h"
-
-#include <algorithm>
-#include <set>
-#include <utility>
-
-#include "base/bind.h"
-#include "base/stl_util.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "build/build_config.h"
-#include "components/apdu/apdu_command.h"
-#include "device/fido/u2f_command_constructor.h"
-#include "services/service_manager/public/cpp/connector.h"
-
-namespace device {
-
-U2fRequest::U2fRequest(service_manager::Connector* connector,
-                       const base::flat_set<FidoTransportProtocol>& transports,
-                       std::vector<uint8_t> application_parameter,
-                       std::vector<uint8_t> challenge_digest,
-                       std::vector<std::vector<uint8_t>> registered_keys)
-    : state_(State::INIT),
-      application_parameter_(application_parameter),
-      challenge_digest_(challenge_digest),
-      registered_keys_(registered_keys),
-      weak_factory_(this) {
-  for (const auto transport : transports) {
-    auto discovery = FidoDiscovery::Create(transport, connector);
-    if (discovery == nullptr) {
-      // This can occur if the given transport is not supported, or in tests
-      // when the given transport is not configured.
-      continue;
-    }
-    discovery->set_observer(this);
-    discoveries_.push_back(std::move(discovery));
-  }
-}
-
-U2fRequest::~U2fRequest() = default;
-
-void U2fRequest::Start() {
-  if (state_ == State::INIT) {
-    state_ = State::IDLE;
-    for (auto& discovery : discoveries_)
-      discovery->Start();
-  }
-}
-
-base::Optional<std::vector<uint8_t>> U2fRequest::GetU2fSignApduCommand(
-    const std::vector<uint8_t>& application_parameter,
-    const std::vector<uint8_t>& key_handle,
-    bool is_check_only_sign) const {
-  return ConstructU2fSignCommand(application_parameter, challenge_digest_,
-                                 key_handle, is_check_only_sign);
-}
-
-base::Optional<std::vector<uint8_t>> U2fRequest::GetU2fRegisterApduCommand(
-    bool is_individual_attestation) const {
-  return ConstructU2fRegisterCommand(application_parameter_, challenge_digest_,
-                                     is_individual_attestation);
-}
-
-void U2fRequest::Transition() {
-  switch (state_) {
-    case State::IDLE:
-      IterateDevice();
-      if (!current_device_) {
-        // No devices available.
-        state_ = State::OFF;
-        break;
-      }
-      state_ = State::WINK;
-      current_device_->TryWink(
-          base::BindOnce(&U2fRequest::Transition, weak_factory_.GetWeakPtr()));
-      break;
-    case State::WINK:
-      state_ = State::BUSY;
-      TryDevice();
-      break;
-    default:
-      break;
-  }
-}
-
-void U2fRequest::InitiateDeviceTransaction(
-    base::Optional<std::vector<uint8_t>> cmd,
-    FidoDevice::DeviceCallback callback) {
-  if (!cmd) {
-    std::move(callback).Run(base::nullopt);
-    return;
-  }
-  current_device_->DeviceTransact(std::move(*cmd), std::move(callback));
-}
-
-void U2fRequest::AbandonCurrentDeviceAndTransition() {
-  DCHECK_NE(nullptr, current_device_);
-  abandoned_devices_.emplace_back(std::exchange(current_device_, nullptr));
-  state_ = State::IDLE;
-  Transition();
-}
-
-void U2fRequest::DiscoveryStarted(FidoDiscovery* discovery, bool success) {
-#if DCHECK_IS_ON()
-  if (success) {
-    // FidoDiscovery::Observer::DeviceAdded should have been already dispatched
-    // for each of devices already known by |discovery|, so we should never
-    // learn anything new here.
-    std::set<std::string> device_ids_known_to_request;
-    for (const auto* device : attempted_devices_)
-      device_ids_known_to_request.insert(device->GetId());
-    if (current_device_)
-      device_ids_known_to_request.insert(current_device_->GetId());
-    for (const auto* device : devices_)
-      device_ids_known_to_request.insert(device->GetId());
-    for (const auto* device : abandoned_devices_)
-      device_ids_known_to_request.insert(device->GetId());
-
-    std::set<std::string> device_ids_from_newly_started_discovery;
-    for (const auto* device : discovery->GetDevices())
-      device_ids_from_newly_started_discovery.insert(device->GetId());
-    DCHECK(base::STLIncludes(device_ids_known_to_request,
-                             device_ids_from_newly_started_discovery));
-  }
-#endif
-
-  started_count_++;
-  if ((state_ == State::IDLE || state_ == State::OFF) &&
-      (success || started_count_ == discoveries_.size())) {
-    state_ = State::IDLE;
-    Transition();
-  }
-}
-
-void U2fRequest::DeviceAdded(FidoDiscovery* discovery, FidoDevice* device) {
-  devices_.push_back(device);
-
-  // Start the state machine if this is the only device
-  if (state_ == State::OFF) {
-    state_ = State::IDLE;
-    delay_callback_.Cancel();
-    Transition();
-  }
-}
-
-void U2fRequest::DeviceRemoved(FidoDiscovery* discovery, FidoDevice* device) {
-  const std::string device_id = device->GetId();
-  auto device_id_eq = [&device_id](const FidoDevice* this_device) {
-    return device_id == this_device->GetId();
-  };
-
-  // Check if the active device was removed
-  if (current_device_ && device_id_eq(current_device_)) {
-    current_device_ = nullptr;
-    state_ = State::IDLE;
-    Transition();
-    return;
-  }
-
-  // Remove the device if it exists in either device list
-  devices_.remove_if(device_id_eq);
-  attempted_devices_.remove_if(device_id_eq);
-  abandoned_devices_.remove_if(device_id_eq);
-}
-
-void U2fRequest::IterateDevice() {
-  // Move active device to attempted device list
-  if (current_device_) {
-    attempted_devices_.push_back(current_device_);
-    current_device_ = nullptr;
-  }
-
-  // If there is an additional device on device list, make it active.
-  // Otherwise, if all devices have been tried, move attempted devices back to
-  // the main device list.
-  if (devices_.size() > 0) {
-    current_device_ = devices_.front();
-    devices_.pop_front();
-  } else if (attempted_devices_.size() > 0) {
-    devices_ = std::move(attempted_devices_);
-    // After trying every device, wait 200ms before trying again.
-    delay_callback_.Reset(
-        base::Bind(&U2fRequest::OnWaitComplete, weak_factory_.GetWeakPtr()));
-    base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
-        FROM_HERE, delay_callback_.callback(),
-        base::TimeDelta::FromMilliseconds(200));
-  }
-}
-
-void U2fRequest::OnWaitComplete() {
-  state_ = State::IDLE;
-  Transition();
-}
-
-}  // namespace device
diff --git a/device/fido/u2f_request.h b/device/fido/u2f_request.h
deleted file mode 100644
index e8717f0..0000000
--- a/device/fido/u2f_request.h
+++ /dev/null
@@ -1,137 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef DEVICE_FIDO_U2F_REQUEST_H_
-#define DEVICE_FIDO_U2F_REQUEST_H_
-
-#include <stdint.h>
-
-#include <list>
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "base/cancelable_callback.h"
-#include "base/component_export.h"
-#include "base/containers/flat_set.h"
-#include "base/gtest_prod_util.h"
-#include "base/macros.h"
-#include "base/optional.h"
-#include "device/fido/fido_constants.h"
-#include "device/fido/fido_device.h"
-#include "device/fido/fido_discovery.h"
-#include "device/fido/fido_transport_protocol.h"
-
-namespace service_manager {
-class Connector;
-}
-
-namespace device {
-
-class COMPONENT_EXPORT(DEVICE_FIDO) U2fRequest
-    : public FidoDiscovery::Observer {
- public:
-  using VersionCallback = base::OnceCallback<void(ProtocolVersion version)>;
-
-  // U2fRequest will create a discovery instance and register itself as an
-  // observer for each passed in transport protocol.
-  // TODO(https://crbug.com/769631): Remove the dependency on Connector once U2F
-  // is servicified.
-  U2fRequest(service_manager::Connector* connector,
-             const base::flat_set<FidoTransportProtocol>& transports,
-             std::vector<uint8_t> application_parameter,
-             std::vector<uint8_t> challenge_digest,
-             std::vector<std::vector<uint8_t>> registered_keys);
-  ~U2fRequest() override;
-
-  void Start();
-
-  // Functions below are implemented in U2fRequest interface(and not in its
-  // respective subclasses) as both {register, sign} commands are used during
-  // registration process. That is, check-only sign command is sent during
-  // registration to prevent duplicate registration.
-  //
-  // Returns APDU U2F request commands. Null optional is returned for
-  // incorrectly formatted parameter.
-  base::Optional<std::vector<uint8_t>> GetU2fSignApduCommand(
-      const std::vector<uint8_t>& application_parameter,
-      const std::vector<uint8_t>& key_handle,
-      bool is_check_only_sign = false) const;
-  base::Optional<std::vector<uint8_t>> GetU2fRegisterApduCommand(
-      bool is_individual_attestation) const;
-
- protected:
-  enum class State {
-    INIT,
-    BUSY,
-    WINK,
-    IDLE,
-    OFF,
-    COMPLETE,
-  };
-
-  void Transition();
-
-  // Starts sign, register, and version request transaction on
-  // |current_device_|.
-  void InitiateDeviceTransaction(base::Optional<std::vector<uint8_t>> cmd,
-                                 FidoDevice::DeviceCallback callback);
-
-  virtual void TryDevice() = 0;
-
-  // Moves |current_device_| to the list of |abandoned_devices_| and iterates
-  // |current_device_|. Expects |current_device_| to be valid prior to calling
-  // this method.
-  void AbandonCurrentDeviceAndTransition();
-
-  // Hold handles to the devices known to the system. Known devices are
-  // partitioned into four parts:
-  // [attempted_devices_), current_device_, [devices_), [abandoned_devices_)
-  // During device iteration the |current_device_| gets pushed to
-  // |attempted_devices_|, and, if possible, the first element of |devices_|
-  // gets popped and becomes the new |current_device_|. Once all |devices_| are
-  // exhausted, |attempted_devices_| get moved into |devices_| and
-  // |current_device_| is reset. |abandoned_devices_| contains a list of devices
-  // that have been tried in the past, but were abandoned because of an error.
-  // Devices in this list won't be tried again.
-  FidoDevice* current_device_ = nullptr;
-  std::list<FidoDevice*> devices_;
-  std::list<FidoDevice*> attempted_devices_;
-  std::list<FidoDevice*> abandoned_devices_;
-  State state_;
-  std::vector<std::unique_ptr<FidoDiscovery>> discoveries_;
-  std::vector<uint8_t> application_parameter_;
-  std::vector<uint8_t> challenge_digest_;
-  std::vector<std::vector<uint8_t>> registered_keys_;
-
- private:
-  FRIEND_TEST_ALL_PREFIXES(U2fRequestTest, TestIterateDevice);
-  FRIEND_TEST_ALL_PREFIXES(U2fRequestTest,
-                           TestAbandonCurrentDeviceAndTransition);
-  FRIEND_TEST_ALL_PREFIXES(U2fRequestTest, TestBasicMachine);
-  FRIEND_TEST_ALL_PREFIXES(U2fRequestTest, TestAlreadyPresentDevice);
-  FRIEND_TEST_ALL_PREFIXES(U2fRequestTest, TestMultipleDiscoveries);
-  FRIEND_TEST_ALL_PREFIXES(U2fRequestTest, TestSlowDiscovery);
-  FRIEND_TEST_ALL_PREFIXES(U2fRequestTest, TestMultipleDiscoveriesWithFailures);
-  FRIEND_TEST_ALL_PREFIXES(U2fRequestTest, TestLegacyVersionRequest);
-
-  // FidoDiscovery::Observer
-  void DiscoveryStarted(FidoDiscovery* discovery, bool success) override;
-  void DeviceAdded(FidoDiscovery* discovery, FidoDevice* device) override;
-  void DeviceRemoved(FidoDiscovery* discovery, FidoDevice* device) override;
-
-  void IterateDevice();
-  void OnWaitComplete();
-
-  base::CancelableClosure delay_callback_;
-  size_t started_count_ = 0;
-
-  base::WeakPtrFactory<U2fRequest> weak_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(U2fRequest);
-};
-
-}  // namespace device
-
-#endif  // DEVICE_FIDO_U2F_REQUEST_H_
diff --git a/device/fido/u2f_request_unittest.cc b/device/fido/u2f_request_unittest.cc
deleted file mode 100644
index 33124f01..0000000
--- a/device/fido/u2f_request_unittest.cc
+++ /dev/null
@@ -1,364 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-#include "device/fido/u2f_request.h"
-
-#include <list>
-#include <string>
-#include <utility>
-
-#include "base/test/scoped_task_environment.h"
-#include "device/fido/fake_fido_discovery.h"
-#include "device/fido/fido_transport_protocol.h"
-#include "device/fido/mock_fido_device.h"
-#include "device/fido/test_callback_receiver.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using ::testing::_;
-
-namespace device {
-
-namespace {
-
-class FakeU2fRequest : public U2fRequest {
- public:
-  explicit FakeU2fRequest(
-      const base::flat_set<FidoTransportProtocol>& transports)
-      : U2fRequest(nullptr /* connector */,
-                   transports,
-                   std::vector<uint8_t>(),
-                   std::vector<uint8_t>(),
-                   std::vector<std::vector<uint8_t>>()) {}
-  ~FakeU2fRequest() override = default;
-
-  void TryDevice() override {
-    // Do nothing.
-  }
-};
-
-using TestVersionCallback =
-    ::device::test::ValueCallbackReceiver<ProtocolVersion>;
-
-}  // namespace
-
-class U2fRequestTest : public ::testing::Test {
- protected:
-  base::test::ScopedTaskEnvironment& scoped_task_environment() {
-    return scoped_task_environment_;
-  }
-
-  test::ScopedFakeFidoDiscoveryFactory& discovery_factory() {
-    return discovery_factory_;
-  }
-
-  TestVersionCallback& version_callback_receiver() {
-    return version_callback_receiver_;
-  }
-
- private:
-  base::test::ScopedTaskEnvironment scoped_task_environment_{
-      base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME};
-  TestVersionCallback version_callback_receiver_;
-  test::ScopedFakeFidoDiscoveryFactory discovery_factory_;
-};
-
-TEST_F(U2fRequestTest, TestIterateDevice) {
-  auto* discovery = discovery_factory().ForgeNextHidDiscovery();
-
-  FakeU2fRequest request({FidoTransportProtocol::kUsbHumanInterfaceDevice});
-  request.Start();
-
-  auto device0 = std::make_unique<MockFidoDevice>();
-  auto device1 = std::make_unique<MockFidoDevice>();
-  EXPECT_CALL(*device0, GetId()).WillRepeatedly(::testing::Return("device0"));
-  EXPECT_CALL(*device1, GetId()).WillRepeatedly(::testing::Return("device1"));
-
-  // Add two U2F devices
-  discovery->AddDevice(std::move(device0));
-  discovery->AddDevice(std::move(device1));
-
-  // Move first device to current.
-  request.IterateDevice();
-  ASSERT_NE(nullptr, request.current_device_);
-  EXPECT_EQ(static_cast<size_t>(1), request.devices_.size());
-
-  // Move second device to current, first to attempted.
-  request.IterateDevice();
-  ASSERT_NE(nullptr, request.current_device_);
-  EXPECT_EQ(static_cast<size_t>(1), request.attempted_devices_.size());
-
-  // Move second device from current to attempted, move attempted to devices as
-  // all devices have been attempted.
-  request.IterateDevice();
-
-  ASSERT_EQ(nullptr, request.current_device_);
-  EXPECT_EQ(static_cast<size_t>(2), request.devices_.size());
-  EXPECT_EQ(static_cast<size_t>(0), request.attempted_devices_.size());
-
-  // Moving attempted devices results in a delayed retry, after which the first
-  // device will be tried again. Check for the expected behavior here.
-  auto* mock_device = static_cast<MockFidoDevice*>(request.devices_.front());
-  EXPECT_CALL(*mock_device, TryWinkRef(_));
-  scoped_task_environment().FastForwardUntilNoTasksRemain();
-
-  EXPECT_EQ(mock_device, request.current_device_);
-  EXPECT_EQ(static_cast<size_t>(1), request.devices_.size());
-  EXPECT_EQ(static_cast<size_t>(0), request.attempted_devices_.size());
-}
-
-TEST_F(U2fRequestTest, TestAbandonCurrentDeviceAndTransition) {
-  auto* discovery = discovery_factory().ForgeNextHidDiscovery();
-
-  FakeU2fRequest request({FidoTransportProtocol::kUsbHumanInterfaceDevice});
-  request.Start();
-
-  auto device = std::make_unique<MockFidoDevice>();
-  EXPECT_CALL(*device, GetId()).WillRepeatedly(::testing::Return("device"));
-
-  discovery->AddDevice(std::move(device));
-
-  // Move device to current.
-  request.IterateDevice();
-  EXPECT_NE(nullptr, request.current_device_);
-
-  // Abandon device.
-  request.AbandonCurrentDeviceAndTransition();
-  EXPECT_EQ(nullptr, request.current_device_);
-  EXPECT_EQ(1u, request.abandoned_devices_.size());
-
-  // Iterating through the device list should not change the state.
-  request.IterateDevice();
-  EXPECT_EQ(nullptr, request.current_device_);
-  EXPECT_EQ(1u, request.abandoned_devices_.size());
-
-  // Removing the device from the discovery should clear it from the list.
-  discovery->RemoveDevice("device");
-  EXPECT_TRUE(request.abandoned_devices_.empty());
-}
-
-TEST_F(U2fRequestTest, TestBasicMachine) {
-  auto* discovery = discovery_factory().ForgeNextHidDiscovery();
-  FakeU2fRequest request({FidoTransportProtocol::kUsbHumanInterfaceDevice});
-  request.Start();
-
-  ASSERT_NO_FATAL_FAILURE(discovery->WaitForCallToStartAndSimulateSuccess());
-
-  // Add one U2F device
-  auto device = std::make_unique<MockFidoDevice>();
-  EXPECT_CALL(*device, GetId());
-  EXPECT_CALL(*device, TryWinkRef(_))
-      .WillOnce(::testing::Invoke(MockFidoDevice::WinkDoNothing));
-  discovery->AddDevice(std::move(device));
-
-  EXPECT_EQ(U2fRequest::State::BUSY, request.state_);
-}
-
-TEST_F(U2fRequestTest, TestAlreadyPresentDevice) {
-  auto* discovery = discovery_factory().ForgeNextHidDiscovery();
-
-  FakeU2fRequest request({FidoTransportProtocol::kUsbHumanInterfaceDevice});
-  request.Start();
-
-  auto device = std::make_unique<MockFidoDevice>();
-  EXPECT_CALL(*device, GetId()).WillRepeatedly(::testing::Return("device"));
-  discovery->AddDevice(std::move(device));
-
-  ASSERT_NO_FATAL_FAILURE(discovery->WaitForCallToStartAndSimulateSuccess());
-  EXPECT_NE(nullptr, request.current_device_);
-}
-
-TEST_F(U2fRequestTest, TestMultipleDiscoveries) {
-  auto* discovery_1 = discovery_factory().ForgeNextHidDiscovery();
-  auto* discovery_2 = discovery_factory().ForgeNextBleDiscovery();
-
-  // Create a fake request with two different discoveries that both start up
-  // successfully.
-  FakeU2fRequest request({FidoTransportProtocol::kUsbHumanInterfaceDevice,
-                          FidoTransportProtocol::kBluetoothLowEnergy});
-  request.Start();
-
-  ASSERT_NO_FATAL_FAILURE(discovery_1->WaitForCallToStartAndSimulateSuccess());
-  ASSERT_NO_FATAL_FAILURE(discovery_2->WaitForCallToStartAndSimulateSuccess());
-
-  // Let each discovery find a device.
-  auto device_1 = std::make_unique<MockFidoDevice>();
-  auto device_2 = std::make_unique<MockFidoDevice>();
-  EXPECT_CALL(*device_1, GetId()).WillRepeatedly(::testing::Return("device_1"));
-  EXPECT_CALL(*device_2, GetId()).WillRepeatedly(::testing::Return("device_2"));
-
-  auto* device_1_ptr = device_1.get();
-  auto* device_2_ptr = device_2.get();
-  discovery_1->AddDevice(std::move(device_1));
-  discovery_2->AddDevice(std::move(device_2));
-
-  // Iterate through the devices and make sure they are considered in the same
-  // order as they were added.
-  EXPECT_EQ(device_1_ptr, request.current_device_);
-  request.IterateDevice();
-
-  EXPECT_EQ(device_2_ptr, request.current_device_);
-  request.IterateDevice();
-
-  EXPECT_EQ(nullptr, request.current_device_);
-  EXPECT_EQ(2u, request.devices_.size());
-
-  // Add a third device.
-  auto device_3 = std::make_unique<MockFidoDevice>();
-  EXPECT_CALL(*device_3, GetId()).WillRepeatedly(::testing::Return("device_3"));
-  auto* device_3_ptr = device_3.get();
-  discovery_1->AddDevice(std::move(device_3));
-
-  // Exhaust the timeout and remove the first two devices, making sure the just
-  // added one is the only device considered.
-  scoped_task_environment().FastForwardUntilNoTasksRemain();
-  discovery_2->RemoveDevice("device_2");
-  discovery_1->RemoveDevice("device_1");
-  EXPECT_EQ(device_3_ptr, request.current_device_);
-
-  // Finally remove the last remaining device.
-  discovery_1->RemoveDevice("device_3");
-  EXPECT_EQ(nullptr, request.current_device_);
-}
-
-TEST_F(U2fRequestTest, TestSlowDiscovery) {
-  auto* fast_discovery = discovery_factory().ForgeNextHidDiscovery();
-  auto* slow_discovery = discovery_factory().ForgeNextBleDiscovery();
-
-  // Create a fake request with two different discoveries that start at
-  // different times.
-  FakeU2fRequest request({FidoTransportProtocol::kUsbHumanInterfaceDevice,
-                          FidoTransportProtocol::kBluetoothLowEnergy});
-
-  auto fast_device = std::make_unique<MockFidoDevice>();
-  auto slow_device = std::make_unique<MockFidoDevice>();
-  EXPECT_CALL(*fast_device, GetId())
-      .WillRepeatedly(::testing::Return("fast_device"));
-  EXPECT_CALL(*slow_device, GetId())
-      .WillRepeatedly(::testing::Return("slow_device"));
-
-  bool fast_winked = false;
-  EXPECT_CALL(*fast_device, TryWinkRef(_))
-      .WillOnce(
-          ::testing::DoAll(::testing::Assign(&fast_winked, true),
-                           ::testing::Invoke(MockFidoDevice::WinkDoNothing)))
-      .WillRepeatedly(::testing::Invoke(MockFidoDevice::WinkDoNothing));
-  bool slow_winked = false;
-  EXPECT_CALL(*slow_device, TryWinkRef(_))
-      .WillOnce(testing::DoAll(testing::Assign(&slow_winked, true),
-                               testing::Invoke(MockFidoDevice::WinkDoNothing)));
-
-  auto* fast_device_ptr = fast_device.get();
-  auto* slow_device_ptr = slow_device.get();
-
-  EXPECT_EQ(nullptr, request.current_device_);
-  request.state_ = U2fRequest::State::INIT;
-
-  // The discoveries will be started and |fast_discovery| will succeed
-  // immediately with a device already found.
-  request.Start();
-
-  EXPECT_FALSE(fast_winked);
-
-  ASSERT_NO_FATAL_FAILURE(fast_discovery->WaitForCallToStart());
-  fast_discovery->AddDevice(std::move(fast_device));
-  ASSERT_NO_FATAL_FAILURE(fast_discovery->SimulateStarted(true /* success */));
-
-  EXPECT_TRUE(fast_winked);
-  EXPECT_EQ(fast_device_ptr, request.current_device_);
-  EXPECT_EQ(U2fRequest::State::BUSY, request.state_);
-
-  // There are no more devices at this time.
-  request.state_ = U2fRequest::State::IDLE;
-  request.Transition();
-  EXPECT_EQ(nullptr, request.current_device_);
-  EXPECT_EQ(U2fRequest::State::OFF, request.state_);
-
-  // All devices have been tried and have been re-enqueued to try again in the
-  // future. Now |slow_discovery| starts:
-  ASSERT_TRUE(slow_discovery->is_start_requested());
-  ASSERT_FALSE(slow_discovery->is_running());
-  ASSERT_NO_FATAL_FAILURE(slow_discovery->WaitForCallToStart());
-  slow_discovery->AddDevice(std::move(slow_device));
-  ASSERT_NO_FATAL_FAILURE(slow_discovery->SimulateStarted(true /* success */));
-
-  // |fast_device| is already enqueued and will be retried immediately.
-  EXPECT_EQ(fast_device_ptr, request.current_device_);
-  EXPECT_EQ(U2fRequest::State::BUSY, request.state_);
-
-  // Next the newly found |slow_device| will be tried.
-  request.state_ = U2fRequest::State::IDLE;
-  EXPECT_FALSE(slow_winked);
-  request.Transition();
-  EXPECT_TRUE(slow_winked);
-  EXPECT_EQ(slow_device_ptr, request.current_device_);
-  EXPECT_EQ(U2fRequest::State::BUSY, request.state_);
-
-  // All discoveries are complete so the request transitions to |OFF|.
-  request.state_ = U2fRequest::State::IDLE;
-  request.Transition();
-  EXPECT_EQ(nullptr, request.current_device_);
-  EXPECT_EQ(U2fRequest::State::OFF, request.state_);
-}
-
-TEST_F(U2fRequestTest, TestMultipleDiscoveriesWithFailures) {
-  // Create a fake request with two different discoveries that both start up
-  // unsuccessfully.
-  {
-    auto* discovery_1 = discovery_factory().ForgeNextHidDiscovery();
-    auto* discovery_2 = discovery_factory().ForgeNextBleDiscovery();
-
-    FakeU2fRequest request({FidoTransportProtocol::kUsbHumanInterfaceDevice,
-                            FidoTransportProtocol::kBluetoothLowEnergy});
-    request.Start();
-
-    ASSERT_NO_FATAL_FAILURE(discovery_1->WaitForCallToStart());
-    ASSERT_NO_FATAL_FAILURE(discovery_1->SimulateStarted(false /* success */));
-    ASSERT_NO_FATAL_FAILURE(discovery_2->WaitForCallToStart());
-    ASSERT_NO_FATAL_FAILURE(discovery_2->SimulateStarted(false /* success */));
-
-    EXPECT_EQ(U2fRequest::State::OFF, request.state_);
-  }
-
-  // Create a fake request with two different discoveries, where only one starts
-  // up successfully.
-  {
-    auto* discovery_1 = discovery_factory().ForgeNextHidDiscovery();
-    auto* discovery_2 = discovery_factory().ForgeNextBleDiscovery();
-
-    FakeU2fRequest request({FidoTransportProtocol::kUsbHumanInterfaceDevice,
-                            FidoTransportProtocol::kBluetoothLowEnergy});
-    request.Start();
-
-    ASSERT_NO_FATAL_FAILURE(discovery_1->WaitForCallToStart());
-    ASSERT_NO_FATAL_FAILURE(discovery_1->SimulateStarted(false /* success */));
-    ASSERT_NO_FATAL_FAILURE(discovery_2->WaitForCallToStart());
-    ASSERT_NO_FATAL_FAILURE(discovery_2->SimulateStarted(true /* success */));
-
-    auto device0 = std::make_unique<MockFidoDevice>();
-    EXPECT_CALL(*device0, GetId())
-        .WillRepeatedly(::testing::Return("device_0"));
-    EXPECT_CALL(*device0, TryWinkRef(_))
-        .WillOnce(::testing::Invoke(MockFidoDevice::WinkDoNothing));
-    discovery_2->AddDevice(std::move(device0));
-
-    EXPECT_EQ(U2fRequest::State::BUSY, request.state_);
-
-    // Simulate an action that sets the request state to idle.
-    // This and the call to Transition() below is necessary to trigger iterating
-    // and trying the new device.
-    request.state_ = U2fRequest::State::IDLE;
-
-    // Adding another device should trigger examination and a busy state.
-    auto device1 = std::make_unique<MockFidoDevice>();
-    EXPECT_CALL(*device1, GetId())
-        .WillRepeatedly(::testing::Return("device_1"));
-    EXPECT_CALL(*device1, TryWinkRef(_))
-        .WillOnce(::testing::Invoke(MockFidoDevice::WinkDoNothing));
-    discovery_2->AddDevice(std::move(device1));
-
-    request.Transition();
-    EXPECT_EQ(U2fRequest::State::BUSY, request.state_);
-  }
-}
-
-}  // namespace device
diff --git a/device/fido/u2f_sign.cc b/device/fido/u2f_sign.cc
deleted file mode 100644
index 1cad2c8..0000000
--- a/device/fido/u2f_sign.cc
+++ /dev/null
@@ -1,155 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "device/fido/u2f_sign.h"
-
-#include <utility>
-
-#include "components/apdu/apdu_command.h"
-#include "components/apdu/apdu_response.h"
-#include "device/fido/u2f_command_constructor.h"
-#include "services/service_manager/public/cpp/connector.h"
-
-namespace device {
-
-// static
-std::unique_ptr<U2fRequest> U2fSign::TrySign(
-    service_manager::Connector* connector,
-    const base::flat_set<FidoTransportProtocol>& transports,
-    std::vector<std::vector<uint8_t>> registered_keys,
-    std::vector<uint8_t> challenge_digest,
-    std::vector<uint8_t> application_parameter,
-    base::Optional<std::vector<uint8_t>> alt_application_parameter,
-    SignResponseCallback completion_callback) {
-  std::unique_ptr<U2fRequest> request = std::make_unique<U2fSign>(
-      connector, transports, registered_keys, challenge_digest,
-      application_parameter, std::move(alt_application_parameter),
-      std::move(completion_callback));
-  request->Start();
-
-  return request;
-}
-
-U2fSign::U2fSign(service_manager::Connector* connector,
-                 const base::flat_set<FidoTransportProtocol>& transports,
-                 std::vector<std::vector<uint8_t>> registered_keys,
-                 std::vector<uint8_t> challenge_digest,
-                 std::vector<uint8_t> application_parameter,
-                 base::Optional<std::vector<uint8_t>> alt_application_parameter,
-                 SignResponseCallback completion_callback)
-    : U2fRequest(connector,
-                 transports,
-                 std::move(application_parameter),
-                 std::move(challenge_digest),
-                 std::move(registered_keys)),
-      alt_application_parameter_(std::move(alt_application_parameter)),
-      completion_callback_(std::move(completion_callback)),
-      weak_factory_(this) {
-  // U2F devices require at least one key handle.
-  // TODO(crbug.com/831712): When CTAP2 authenticators are supported, this check
-  // should be enforced by handlers in fido/device on a per-device basis.
-  CHECK(!registered_keys_.empty());
-}
-
-U2fSign::~U2fSign() = default;
-
-void U2fSign::TryDevice() {
-  DCHECK(current_device_);
-
-  // Try signing current device with the first registered key.
-  auto it = registered_keys_.cbegin();
-  InitiateDeviceTransaction(
-      GetU2fSignApduCommand(application_parameter_, *it),
-      base::BindOnce(&U2fSign::OnTryDevice, weak_factory_.GetWeakPtr(), it,
-                     ApplicationParameterType::kPrimary));
-}
-
-void U2fSign::OnTryDevice(std::vector<std::vector<uint8_t>>::const_iterator it,
-                          ApplicationParameterType application_parameter_type,
-                          base::Optional<std::vector<uint8_t>> response) {
-  const auto apdu_response =
-      response ? apdu::ApduResponse::CreateFromMessage(std::move(*response))
-               : base::nullopt;
-  auto return_code = apdu_response ? apdu_response->status()
-                                   : apdu::ApduResponse::Status::SW_WRONG_DATA;
-  auto response_data = return_code == apdu::ApduResponse::Status::SW_WRONG_DATA
-                           ? std::vector<uint8_t>()
-                           : apdu_response->data();
-
-  switch (return_code) {
-    case apdu::ApduResponse::Status::SW_NO_ERROR: {
-      state_ = State::COMPLETE;
-      if (it == registered_keys_.cend()) {
-        // This was a response to a fake enrollment. Return an empty key handle.
-        std::move(completion_callback_)
-            .Run(FidoReturnCode::kUserConsentButCredentialNotRecognized,
-                 base::nullopt);
-      } else {
-        const std::vector<uint8_t>* const application_parameter_used =
-            application_parameter_type == ApplicationParameterType::kPrimary
-                ? &application_parameter_
-                : &alt_application_parameter_.value();
-        auto sign_response =
-            AuthenticatorGetAssertionResponse::CreateFromU2fSignResponse(
-                *application_parameter_used, std::move(response_data), *it);
-        if (!sign_response) {
-          std::move(completion_callback_)
-              .Run(FidoReturnCode::kAuthenticatorResponseInvalid,
-                   base::nullopt);
-        } else {
-          std::move(completion_callback_)
-              .Run(FidoReturnCode::kSuccess, std::move(sign_response));
-        }
-      }
-      break;
-    }
-    case apdu::ApduResponse::Status::SW_CONDITIONS_NOT_SATISFIED: {
-      // Key handle is accepted by this device, but waiting on user touch. Move
-      // on and try this device again later.
-      state_ = State::IDLE;
-      Transition();
-      break;
-    }
-    case apdu::ApduResponse::Status::SW_WRONG_DATA:
-    case apdu::ApduResponse::Status::SW_WRONG_LENGTH: {
-      if (application_parameter_type == ApplicationParameterType::kPrimary &&
-          alt_application_parameter_ && it != registered_keys_.cend()) {
-        // |application_parameter_| failed, but there is also
-        // |alt_application_parameter_| to try.
-        InitiateDeviceTransaction(
-            GetU2fSignApduCommand(*alt_application_parameter_, *it),
-            base::Bind(&U2fSign::OnTryDevice, weak_factory_.GetWeakPtr(), it,
-                       ApplicationParameterType::kAlternative));
-      } else if (it == registered_keys_.cend()) {
-        // The fake enrollment errored out. Move on to the next device.
-        AbandonCurrentDeviceAndTransition();
-      } else if (++it != registered_keys_.end()) {
-        // Key is not for this device. Try signing with the next key.
-        InitiateDeviceTransaction(
-            GetU2fSignApduCommand(application_parameter_, *it),
-            base::BindOnce(&U2fSign::OnTryDevice, weak_factory_.GetWeakPtr(),
-                           it, ApplicationParameterType::kPrimary));
-      } else {
-        // No provided key was accepted by this device. Send registration
-        // (Fake enroll) request to device.
-        // We do this to prevent user confusion. Otherwise, if the device
-        // doesn't blink, the user might think it's broken rather than that
-        // it's not registered. Once the user consents to use the device,
-        // the relying party can inform them that it hasn't been registered.
-        InitiateDeviceTransaction(
-            ConstructBogusU2fRegistrationCommand(),
-            base::BindOnce(&U2fSign::OnTryDevice, weak_factory_.GetWeakPtr(),
-                           registered_keys_.cend(),
-                           ApplicationParameterType::kPrimary));
-      }
-      break;
-    }
-    default:
-      // Some sort of failure occured. Abandon this device and move on.
-      AbandonCurrentDeviceAndTransition();
-      break;
-  }
-}
-
-}  // namespace device
diff --git a/device/fido/u2f_sign.h b/device/fido/u2f_sign.h
deleted file mode 100644
index 10cad3e1..0000000
--- a/device/fido/u2f_sign.h
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef DEVICE_FIDO_U2F_SIGN_H_
-#define DEVICE_FIDO_U2F_SIGN_H_
-
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "base/component_export.h"
-#include "base/containers/flat_set.h"
-#include "base/macros.h"
-#include "base/optional.h"
-#include "device/fido/authenticator_get_assertion_response.h"
-#include "device/fido/fido_constants.h"
-#include "device/fido/fido_transport_protocol.h"
-#include "device/fido/u2f_request.h"
-
-namespace service_manager {
-class Connector;
-}
-
-namespace device {
-
-class COMPONENT_EXPORT(DEVICE_FIDO) U2fSign : public U2fRequest {
- public:
-  using SignResponseCallback = base::OnceCallback<void(
-      FidoReturnCode status_code,
-      base::Optional<AuthenticatorGetAssertionResponse> response_data)>;
-
-  static std::unique_ptr<U2fRequest> TrySign(
-      service_manager::Connector* connector,
-      const base::flat_set<FidoTransportProtocol>& transports,
-      std::vector<std::vector<uint8_t>> registered_keys,
-      std::vector<uint8_t> challenge_digest,
-      std::vector<uint8_t> application_parameter,
-      base::Optional<std::vector<uint8_t>> alt_application_parameter,
-      SignResponseCallback completion_callback);
-
-  U2fSign(service_manager::Connector* connector,
-          const base::flat_set<FidoTransportProtocol>& transports,
-          std::vector<std::vector<uint8_t>> registered_keys,
-          std::vector<uint8_t> challenge_digest,
-          std::vector<uint8_t> application_parameter,
-          base::Optional<std::vector<uint8_t>> alt_application_parameter,
-          SignResponseCallback completion_callback);
-  ~U2fSign() override;
-
- private:
-  void TryDevice() override;
-  void OnTryDevice(std::vector<std::vector<uint8_t>>::const_iterator it,
-                   ApplicationParameterType application_parameter_type,
-                   base::Optional<std::vector<uint8_t>> response);
-
-  base::Optional<std::vector<uint8_t>> alt_application_parameter_;
-  SignResponseCallback completion_callback_;
-
-  base::WeakPtrFactory<U2fSign> weak_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(U2fSign);
-};
-
-}  // namespace device
-
-#endif  // DEVICE_FIDO_U2F_SIGN_H_
diff --git a/device/fido/u2f_sign_operation.cc b/device/fido/u2f_sign_operation.cc
new file mode 100644
index 0000000..34eaeca
--- /dev/null
+++ b/device/fido/u2f_sign_operation.cc
@@ -0,0 +1,180 @@
+// 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 "device/fido/u2f_sign_operation.h"
+
+#include <utility>
+
+#include "base/bind.h"
+#include "base/threading/sequenced_task_runner_handle.h"
+#include "components/apdu/apdu_response.h"
+#include "device/fido/authenticator_get_assertion_response.h"
+#include "device/fido/ctap_get_assertion_request.h"
+#include "device/fido/device_response_converter.h"
+#include "device/fido/fido_device.h"
+#include "device/fido/fido_parsing_utils.h"
+#include "device/fido/u2f_command_constructor.h"
+
+namespace device {
+
+U2fSignOperation::U2fSignOperation(FidoDevice* device,
+                                   const CtapGetAssertionRequest& request,
+                                   DeviceResponseCallback callback)
+    : DeviceOperation(device, request, std::move(callback)),
+      weak_factory_(this) {}
+
+U2fSignOperation::~U2fSignOperation() = default;
+
+void U2fSignOperation::Start() {
+  // Non-empty allow list in |request_| is checked from above
+  // IsConvertibleToU2fSignCommand().
+  auto it = request().allow_list()->cbegin();
+  DispatchDeviceRequest(
+      ConvertToU2fSignCommand(request(), ApplicationParameterType::kPrimary,
+                              it->id(), true /* is_check_only */),
+      base::BindOnce(&U2fSignOperation::OnCheckForKeyHandlePresence,
+                     weak_factory_.GetWeakPtr(),
+                     ApplicationParameterType::kPrimary, it));
+}
+
+void U2fSignOperation::RetrySign(
+    bool is_fake_enrollment,
+    ApplicationParameterType application_parameter_type,
+    const std::vector<uint8_t>& key_handle) {
+  auto cmd = is_fake_enrollment
+                 ? ConstructBogusU2fRegistrationCommand()
+                 : ConvertToU2fSignCommand(
+                       request(), application_parameter_type, key_handle);
+  DispatchDeviceRequest(
+      std::move(cmd),
+      base::BindOnce(&U2fSignOperation::OnSignResponseReceived,
+                     weak_factory_.GetWeakPtr(), is_fake_enrollment,
+                     application_parameter_type, key_handle));
+}
+
+void U2fSignOperation::OnSignResponseReceived(
+    bool is_fake_enrollment,
+    ApplicationParameterType application_parameter_type,
+    const std::vector<uint8_t>& key_handle,
+    base::Optional<std::vector<uint8_t>> device_response) {
+  const auto apdu_response =
+      device_response
+          ? apdu::ApduResponse::CreateFromMessage(std::move(*device_response))
+          : base::nullopt;
+  auto return_code = apdu_response ? apdu_response->status()
+                                   : apdu::ApduResponse::Status::SW_WRONG_DATA;
+
+  switch (return_code) {
+    case apdu::ApduResponse::Status::SW_NO_ERROR: {
+      if (is_fake_enrollment) {
+        std::move(callback())
+            .Run(CtapDeviceResponseCode::kCtap2ErrCredentialNotValid,
+                 base::nullopt);
+      } else {
+        auto application_parameter =
+            application_parameter_type == ApplicationParameterType::kPrimary
+                ? fido_parsing_utils::CreateSHA256Hash(request().rp_id())
+                : request().alternative_application_parameter().value_or(
+                      std::vector<uint8_t>());
+        auto sign_response =
+            AuthenticatorGetAssertionResponse::CreateFromU2fSignResponse(
+                std::move(application_parameter), apdu_response->data(),
+                key_handle);
+        if (!sign_response) {
+          std::move(callback())
+              .Run(CtapDeviceResponseCode::kCtap2ErrOther, base::nullopt);
+          return;
+        }
+
+        std::move(callback())
+            .Run(CtapDeviceResponseCode::kSuccess, std::move(sign_response));
+      }
+      break;
+    }
+
+    case apdu::ApduResponse::Status::SW_CONDITIONS_NOT_SATISFIED: {
+      // Waiting for user touch. Retry after 200 milliseconds delay.
+      base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
+          FROM_HERE,
+          base::BindOnce(&U2fSignOperation::RetrySign,
+                         weak_factory_.GetWeakPtr(), is_fake_enrollment,
+                         application_parameter_type, key_handle),
+          kU2fRetryDelay);
+      break;
+    }
+    default:
+      // Some sort of failure occurred. Abandon this device and move on.
+      std::move(callback())
+          .Run(CtapDeviceResponseCode::kCtap2ErrOther, base::nullopt);
+      return;
+  }
+}
+
+void U2fSignOperation::OnCheckForKeyHandlePresence(
+    ApplicationParameterType application_parameter_type,
+    AllowedListIterator it,
+    base::Optional<std::vector<uint8_t>> device_response) {
+  DCHECK(request().allow_list());
+  const auto& apdu_response =
+      device_response
+          ? apdu::ApduResponse::CreateFromMessage(std::move(*device_response))
+          : base::nullopt;
+  auto return_code = apdu_response ? apdu_response->status()
+                                   : apdu::ApduResponse::Status::SW_WRONG_DATA;
+
+  switch (return_code) {
+    case apdu::ApduResponse::Status::SW_NO_ERROR:
+    case apdu::ApduResponse::Status::SW_CONDITIONS_NOT_SATISFIED: {
+      DispatchDeviceRequest(
+          ConvertToU2fSignCommand(request(), application_parameter_type,
+                                  it->id()),
+          base::BindOnce(&U2fSignOperation::OnSignResponseReceived,
+                         weak_factory_.GetWeakPtr(),
+                         false /* is_fake_enrollment */,
+                         application_parameter_type, it->id()));
+      break;
+    }
+    case apdu::ApduResponse::Status::SW_WRONG_DATA:
+    case apdu::ApduResponse::Status::SW_WRONG_LENGTH: {
+      if (application_parameter_type == ApplicationParameterType::kPrimary &&
+          request().alternative_application_parameter()) {
+        // |application_parameter_| failed, but there is also
+        // |alternative_application_parameter_| to try.
+        DispatchDeviceRequest(
+            ConvertToU2fSignCommand(request(),
+                                    ApplicationParameterType::kAlternative,
+                                    it->id(), true /* is_check_only */),
+            base::BindOnce(&U2fSignOperation::OnCheckForKeyHandlePresence,
+                           weak_factory_.GetWeakPtr(),
+                           ApplicationParameterType::kAlternative, it));
+      } else if (++it != request().allow_list()->cend()) {
+        // Key is not for this device. Try signing with the next key.
+        DispatchDeviceRequest(
+            ConvertToU2fSignCommand(request(),
+                                    ApplicationParameterType::kPrimary,
+                                    it->id(), true /* check_only */),
+            base::BindOnce(&U2fSignOperation::OnCheckForKeyHandlePresence,
+                           weak_factory_.GetWeakPtr(),
+                           ApplicationParameterType::kPrimary, it));
+      } else {
+        // No provided key was accepted by this device. Send registration
+        // (Fake enroll) request to device.
+        DispatchDeviceRequest(
+            ConstructBogusU2fRegistrationCommand(),
+            base::BindOnce(
+                &U2fSignOperation::OnSignResponseReceived,
+                weak_factory_.GetWeakPtr(), true /* is_fake_enrollment */,
+                ApplicationParameterType::kPrimary, std::vector<uint8_t>()));
+      }
+      break;
+    }
+    default:
+      // Some sort of failure occurred. Abandon this device and move on.
+      std::move(callback())
+          .Run(CtapDeviceResponseCode::kCtap2ErrOther, base::nullopt);
+      break;
+  }
+}
+
+}  // namespace device
diff --git a/device/fido/u2f_sign_operation.h b/device/fido/u2f_sign_operation.h
new file mode 100644
index 0000000..190a51e
--- /dev/null
+++ b/device/fido/u2f_sign_operation.h
@@ -0,0 +1,69 @@
+// 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 DEVICE_FIDO_U2F_SIGN_OPERATION_H_
+#define DEVICE_FIDO_U2F_SIGN_OPERATION_H_
+
+#include <stdint.h>
+
+#include <memory>
+#include <vector>
+
+#include "base/callback.h"
+#include "base/component_export.h"
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "base/optional.h"
+#include "device/fido/device_operation.h"
+#include "device/fido/fido_constants.h"
+
+namespace device {
+
+class FidoDevice;
+class CtapGetAssertionRequest;
+class AuthenticatorGetAssertionResponse;
+class PublicKeyCredentialDescriptor;
+
+// Represents per device authentication logic for U2F tokens. Handles iterating
+// through credentials in the allowed list, invokes check-only sign, and if
+// check-only sign returns success, invokes regular sign call with user
+// presence enforced.
+// https://fidoalliance.org/specs/fido-v2.0-rd-20170927/fido-client-to-authenticator-protocol-v2.0-rd-20170927.html#using-the-ctap2-authenticatorgetassertion-command-with-ctap1-u2f-authenticators
+class COMPONENT_EXPORT(DEVICE_FIDO) U2fSignOperation
+    : public DeviceOperation<CtapGetAssertionRequest,
+                             AuthenticatorGetAssertionResponse> {
+ public:
+  U2fSignOperation(FidoDevice* device,
+                   const CtapGetAssertionRequest& request,
+                   DeviceResponseCallback callback);
+  ~U2fSignOperation() override;
+
+  // DeviceOperation:
+  void Start() override;
+
+ private:
+  using AllowedListIterator =
+      std::vector<PublicKeyCredentialDescriptor>::const_iterator;
+
+  void RetrySign(bool is_fake_enrollment,
+                 ApplicationParameterType application_parameter_type,
+                 const std::vector<uint8_t>& key_handle);
+  void OnSignResponseReceived(
+      bool is_fake_enrollment,
+      ApplicationParameterType application_parameter_type,
+      const std::vector<uint8_t>& key_handle,
+      base::Optional<std::vector<uint8_t>> device_response);
+  void OnCheckForKeyHandlePresence(
+      ApplicationParameterType application_parameter_type,
+      AllowedListIterator it,
+      base::Optional<std::vector<uint8_t>> device_response);
+
+  base::WeakPtrFactory<U2fSignOperation> weak_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(U2fSignOperation);
+};
+
+}  // namespace device
+
+#endif  // DEVICE_FIDO_U2F_SIGN_OPERATION_H_
diff --git a/device/fido/u2f_sign_operation_unittest.cc b/device/fido/u2f_sign_operation_unittest.cc
new file mode 100644
index 0000000..630f38b
--- /dev/null
+++ b/device/fido/u2f_sign_operation_unittest.cc
@@ -0,0 +1,387 @@
+// 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 "device/fido/u2f_sign_operation.h"
+
+#include <string>
+#include <utility>
+
+#include "base/test/scoped_task_environment.h"
+#include "crypto/ec_private_key.h"
+#include "device/fido/authenticator_get_assertion_response.h"
+#include "device/fido/ctap_get_assertion_request.h"
+#include "device/fido/fido_constants.h"
+#include "device/fido/fido_parsing_utils.h"
+#include "device/fido/fido_test_data.h"
+#include "device/fido/mock_fido_device.h"
+#include "device/fido/test_callback_receiver.h"
+#include "device/fido/virtual_u2f_device.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace device {
+
+using ::testing::_;
+using ::testing::InSequence;
+
+namespace {
+
+using TestSignCallback = ::device::test::StatusAndValueCallbackReceiver<
+    CtapDeviceResponseCode,
+    base::Optional<AuthenticatorGetAssertionResponse>>;
+
+}  // namespace
+
+class U2fSignOperationTest : public ::testing::Test {
+ public:
+  CtapGetAssertionRequest CreateSignRequest(
+      std::vector<std::vector<uint8_t>> key_handles) {
+    CtapGetAssertionRequest request(
+        test_data::kRelyingPartyId,
+        fido_parsing_utils::Materialize(test_data::kClientDataHash));
+
+    std::vector<PublicKeyCredentialDescriptor> allowed_list;
+    for (auto& key_handle : key_handles) {
+      allowed_list.emplace_back(CredentialType::kPublicKey,
+                                std::move(key_handle));
+    }
+
+    request.SetAllowList(std::move(allowed_list));
+    return request;
+  }
+
+  TestSignCallback& sign_callback_receiver() { return sign_callback_receiver_; }
+
+ protected:
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
+  TestSignCallback sign_callback_receiver_;
+};
+
+TEST_F(U2fSignOperationTest, SignSuccess) {
+  auto request = CreateSignRequest(
+      {fido_parsing_utils::Materialize(test_data::kU2fSignKeyHandle)});
+
+  auto device = std::make_unique<MockFidoDevice>();
+  EXPECT_CALL(*device, GetId()).WillRepeatedly(testing::Return("device"));
+  InSequence s;
+  device->ExpectRequestAndRespondWith(
+      test_data::kU2fCheckOnlySignCommandApdu,
+      test_data::kApduEncodedNoErrorSignResponse);
+  device->ExpectRequestAndRespondWith(
+      test_data::kU2fSignCommandApdu,
+      test_data::kApduEncodedNoErrorSignResponse);
+
+  auto u2f_sign = std::make_unique<U2fSignOperation>(
+      device.get(), std::move(request), sign_callback_receiver().callback());
+  u2f_sign->Start();
+
+  sign_callback_receiver().WaitForCallback();
+  EXPECT_EQ(CtapDeviceResponseCode::kSuccess,
+            sign_callback_receiver().status());
+  EXPECT_THAT(sign_callback_receiver().value()->signature(),
+              ::testing::ElementsAreArray(test_data::kU2fSignature));
+  EXPECT_THAT(sign_callback_receiver().value()->raw_credential_id(),
+              ::testing::ElementsAreArray(test_data::kU2fSignKeyHandle));
+}
+
+TEST_F(U2fSignOperationTest, SignSuccessWithFakeDevice) {
+  auto private_key = crypto::ECPrivateKey::Create();
+  std::string public_key;
+  private_key->ExportRawPublicKey(&public_key);
+  auto key_handle = fido_parsing_utils::CreateSHA256Hash(public_key);
+  auto request = CreateSignRequest({key_handle});
+
+  auto device = std::make_unique<VirtualU2fDevice>();
+  device->mutable_state()->registrations.emplace(
+      key_handle,
+      VirtualFidoDevice::RegistrationData(
+          std::move(private_key),
+          fido_parsing_utils::Materialize(test_data::kApplicationParameter),
+          42 /* counter */));
+
+  auto u2f_sign = std::make_unique<U2fSignOperation>(
+      device.get(), std::move(request), sign_callback_receiver().callback());
+  u2f_sign->Start();
+
+  sign_callback_receiver().WaitForCallback();
+  EXPECT_EQ(CtapDeviceResponseCode::kSuccess,
+            sign_callback_receiver().status());
+
+  // Just a sanity check, we don't verify the actual signature.
+  ASSERT_GE(32u + 1u + 4u + 8u,  // Minimal ECDSA signature is 8 bytes
+            sign_callback_receiver()
+                .value()
+                ->auth_data()
+                .SerializeToByteArray()
+                .size());
+  EXPECT_EQ(0x01,
+            sign_callback_receiver()
+                .value()
+                ->auth_data()
+                .SerializeToByteArray()[32]);  // UP flag
+  // Counter is incremented for every sign request. Since we conduct 2 sign
+  // requests (check only sign followed by a regular sign), counter should be
+  // incremented twice.
+  EXPECT_EQ(44, sign_callback_receiver()
+                    .value()
+                    ->auth_data()
+                    .SerializeToByteArray()[36]);  // counter
+}
+
+TEST_F(U2fSignOperationTest, DelayedSuccess) {
+  auto request = CreateSignRequest(
+      {fido_parsing_utils::Materialize(test_data::kU2fSignKeyHandle)});
+
+  // Simulates a device that times out waiting for user touch once before
+  // responding successfully.
+  auto device = std::make_unique<MockFidoDevice>();
+  EXPECT_CALL(*device, GetId()).WillRepeatedly(::testing::Return("device"));
+
+  InSequence s;
+  device->ExpectRequestAndRespondWith(
+      test_data::kU2fCheckOnlySignCommandApdu,
+      test_data::kApduEncodedNoErrorSignResponse);
+  device->ExpectRequestAndRespondWith(
+      test_data::kU2fSignCommandApdu,
+      test_data::kU2fConditionNotSatisfiedApduResponse);
+  device->ExpectRequestAndRespondWith(
+      test_data::kU2fSignCommandApdu,
+      test_data::kApduEncodedNoErrorSignResponse);
+
+  auto u2f_sign = std::make_unique<U2fSignOperation>(
+      device.get(), std::move(request), sign_callback_receiver().callback());
+  u2f_sign->Start();
+
+  sign_callback_receiver().WaitForCallback();
+  EXPECT_EQ(CtapDeviceResponseCode::kSuccess,
+            sign_callback_receiver().status());
+  EXPECT_THAT(sign_callback_receiver().value()->signature(),
+              ::testing::ElementsAreArray(test_data::kU2fSignature));
+  EXPECT_THAT(sign_callback_receiver().value()->raw_credential_id(),
+              ::testing::ElementsAreArray(test_data::kU2fSignKeyHandle));
+}
+
+TEST_F(U2fSignOperationTest, MultipleHandles) {
+  // Two wrong keys followed by a correct key ensuring the wrong keys will be
+  // tested first.
+  auto request = CreateSignRequest(
+      {fido_parsing_utils::Materialize(test_data::kKeyHandleAlpha),
+       fido_parsing_utils::Materialize(test_data::kKeyHandleBeta),
+       fido_parsing_utils::Materialize(test_data::kU2fSignKeyHandle)});
+
+  auto device = std::make_unique<MockFidoDevice>();
+  EXPECT_CALL(*device, GetId()).WillRepeatedly(::testing::Return("device"));
+  InSequence s;
+  // Wrong key would respond with SW_WRONG_DATA.
+  device->ExpectRequestAndRespondWith(
+      test_data::kU2fCheckOnlySignCommandApduWithKeyAlpha,
+      test_data::kU2fWrongDataApduResponse);
+  device->ExpectRequestAndRespondWith(
+      test_data::kU2fCheckOnlySignCommandApduWithKeyBeta,
+      test_data::kU2fWrongDataApduResponse);
+  device->ExpectRequestAndRespondWith(
+      test_data::kU2fCheckOnlySignCommandApdu,
+      test_data::kApduEncodedNoErrorSignResponse);
+  device->ExpectRequestAndRespondWith(
+      test_data::kU2fSignCommandApdu,
+      test_data::kApduEncodedNoErrorSignResponse);
+
+  auto u2f_sign = std::make_unique<U2fSignOperation>(
+      device.get(), std::move(request), sign_callback_receiver().callback());
+  u2f_sign->Start();
+
+  sign_callback_receiver().WaitForCallback();
+  EXPECT_EQ(CtapDeviceResponseCode::kSuccess,
+            sign_callback_receiver().status());
+  EXPECT_THAT(sign_callback_receiver().value()->signature(),
+              ::testing::ElementsAreArray(test_data::kU2fSignature));
+  EXPECT_THAT(sign_callback_receiver().value()->raw_credential_id(),
+              ::testing::ElementsAreArray(test_data::kU2fSignKeyHandle));
+}
+
+// Test that Fake U2F registration is invoked when no credentials in the allowed
+// list are recognized by the device.
+TEST_F(U2fSignOperationTest, FakeEnroll) {
+  auto request = CreateSignRequest(
+      {fido_parsing_utils::Materialize(test_data::kKeyHandleAlpha),
+       fido_parsing_utils::Materialize(test_data::kKeyHandleBeta)});
+
+  auto device = std::make_unique<MockFidoDevice>();
+  InSequence s;
+  device->ExpectRequestAndRespondWith(
+      test_data::kU2fCheckOnlySignCommandApduWithKeyAlpha,
+      test_data::kU2fWrongDataApduResponse);
+  device->ExpectRequestAndRespondWith(
+      test_data::kU2fCheckOnlySignCommandApduWithKeyBeta,
+      test_data::kU2fWrongDataApduResponse);
+  device->ExpectRequestAndRespondWith(
+      test_data::kU2fFakeRegisterCommand,
+      test_data::kApduEncodedNoErrorRegisterResponse);
+
+  auto u2f_sign = std::make_unique<U2fSignOperation>(
+      device.get(), std::move(request), sign_callback_receiver().callback());
+  u2f_sign->Start();
+  sign_callback_receiver().WaitForCallback();
+
+  EXPECT_EQ(CtapDeviceResponseCode::kCtap2ErrCredentialNotValid,
+            sign_callback_receiver().status());
+  EXPECT_FALSE(sign_callback_receiver().value());
+}
+
+// Tests that U2F fake enrollment should be re-tried repeatedly if no
+// credentials are valid for the authenticator and user presence is not
+// obtained.
+TEST_F(U2fSignOperationTest, DelayedFakeEnrollment) {
+  auto request = CreateSignRequest(
+      {fido_parsing_utils::Materialize(test_data::kU2fSignKeyHandle)});
+
+  // Simulates a device that times out waiting for user presence during fake
+  // enrollment.
+  auto device = std::make_unique<MockFidoDevice>();
+  EXPECT_CALL(*device, GetId()).WillRepeatedly(::testing::Return("device0"));
+  InSequence s;
+  device->ExpectRequestAndRespondWith(test_data::kU2fCheckOnlySignCommandApdu,
+                                      test_data::kU2fWrongDataApduResponse);
+  device->ExpectRequestAndRespondWith(
+      test_data::kU2fFakeRegisterCommand,
+      test_data::kU2fConditionNotSatisfiedApduResponse);
+  device->ExpectRequestAndRespondWith(
+      test_data::kU2fFakeRegisterCommand,
+      test_data::kApduEncodedNoErrorRegisterResponse);
+
+  auto u2f_sign = std::make_unique<U2fSignOperation>(
+      device.get(), std::move(request), sign_callback_receiver().callback());
+  u2f_sign->Start();
+  sign_callback_receiver().WaitForCallback();
+
+  EXPECT_EQ(CtapDeviceResponseCode::kCtap2ErrCredentialNotValid,
+            sign_callback_receiver().status());
+  EXPECT_FALSE(sign_callback_receiver().value());
+}
+
+// Tests that request is dropped gracefully if device returns error on all
+// requests (including fake enrollment).
+TEST_F(U2fSignOperationTest, FakeEnrollErroringOut) {
+  auto request = CreateSignRequest(
+      {fido_parsing_utils::Materialize(test_data::kU2fSignKeyHandle)});
+
+  // Simulates a device that errors out on all requests (including the sign
+  // request and fake registration attempt). The device should then be abandoned
+  // to prevent the test from crashing or timing out.
+  auto device = std::make_unique<MockFidoDevice>();
+  EXPECT_CALL(*device, GetId()).WillRepeatedly(::testing::Return("device0"));
+  InSequence s;
+  device->ExpectRequestAndRespondWith(test_data::kU2fCheckOnlySignCommandApdu,
+                                      test_data::kU2fWrongDataApduResponse);
+  device->ExpectRequestAndRespondWith(test_data::kU2fFakeRegisterCommand,
+                                      test_data::kU2fWrongDataApduResponse);
+
+  auto u2f_sign = std::make_unique<U2fSignOperation>(
+      device.get(), std::move(request), sign_callback_receiver().callback());
+  u2f_sign->Start();
+  sign_callback_receiver().WaitForCallback();
+
+  EXPECT_EQ(CtapDeviceResponseCode::kCtap2ErrOther,
+            sign_callback_receiver().status());
+  EXPECT_FALSE(sign_callback_receiver().value());
+}
+
+// Tests the scenario where device returns success response, but the response is
+// unparse-able.
+TEST_F(U2fSignOperationTest, SignWithCorruptedResponse) {
+  auto request = CreateSignRequest(
+      {fido_parsing_utils::Materialize(test_data::kU2fSignKeyHandle)});
+
+  auto device = std::make_unique<MockFidoDevice>();
+  EXPECT_CALL(*device, GetId()).WillRepeatedly(::testing::Return("device"));
+  InSequence s;
+  device->ExpectRequestAndRespondWith(test_data::kU2fCheckOnlySignCommandApdu,
+                                      test_data::kTestCorruptedU2fSignResponse);
+  device->ExpectRequestAndRespondWith(test_data::kU2fSignCommandApdu,
+                                      test_data::kTestCorruptedU2fSignResponse);
+
+  auto u2f_sign = std::make_unique<U2fSignOperation>(
+      device.get(), std::move(request), sign_callback_receiver().callback());
+  u2f_sign->Start();
+  sign_callback_receiver().WaitForCallback();
+
+  EXPECT_EQ(CtapDeviceResponseCode::kCtap2ErrOther,
+            sign_callback_receiver().status());
+  EXPECT_FALSE(sign_callback_receiver().value());
+}
+
+TEST_F(U2fSignOperationTest, AlternativeApplicationParameter) {
+  auto request = CreateSignRequest(
+      {fido_parsing_utils::Materialize(test_data::kU2fSignKeyHandle)});
+  request.SetAlternativeApplicationParameter(fido_parsing_utils::Materialize(
+      test_data::kAlternativeApplicationParameter));
+
+  auto device = std::make_unique<MockFidoDevice>();
+  EXPECT_CALL(*device, GetId()).WillRepeatedly(::testing::Return("device"));
+  InSequence s;
+  // The first request will use the primary app_param, which will be rejected.
+  device->ExpectRequestAndRespondWith(test_data::kU2fCheckOnlySignCommandApdu,
+                                      test_data::kU2fWrongDataApduResponse);
+  // After the rejection, the U2F sign request with alternative application
+  // parameter should be tried.
+  device->ExpectRequestAndRespondWith(
+      test_data::
+          kU2fCheckOnlySignCommandApduWithAlternativeApplicationParameter,
+      test_data::kApduEncodedNoErrorSignResponse);
+  device->ExpectRequestAndRespondWith(
+      test_data::kU2fSignCommandApduWithAlternativeApplicationParameter,
+      test_data::kApduEncodedNoErrorSignResponse);
+
+  auto u2f_sign = std::make_unique<U2fSignOperation>(
+      device.get(), std::move(request), sign_callback_receiver().callback());
+  u2f_sign->Start();
+  sign_callback_receiver().WaitForCallback();
+
+  EXPECT_EQ(CtapDeviceResponseCode::kSuccess,
+            sign_callback_receiver().status());
+  const auto& response_value = sign_callback_receiver().value();
+  EXPECT_THAT(response_value->signature(),
+              ::testing::ElementsAreArray(test_data::kU2fSignature));
+  EXPECT_THAT(response_value->raw_credential_id(),
+              ::testing::ElementsAreArray(test_data::kU2fSignKeyHandle));
+  EXPECT_THAT(
+      response_value->GetRpIdHash(),
+      ::testing::ElementsAreArray(test_data::kAlternativeApplicationParameter));
+}
+
+// This is a regression test in response to https://crbug.com/833398.
+TEST_F(U2fSignOperationTest, AlternativeApplicationParameterRejection) {
+  auto request = CreateSignRequest(
+      {fido_parsing_utils::Materialize(test_data::kU2fSignKeyHandle)});
+  request.SetAlternativeApplicationParameter(fido_parsing_utils::Materialize(
+      test_data::kAlternativeApplicationParameter));
+
+  auto device = std::make_unique<MockFidoDevice>();
+  EXPECT_CALL(*device, GetId()).WillRepeatedly(::testing::Return("device"));
+  InSequence s;
+  // The first request will use the primary app_param, which will be rejected.
+  device->ExpectRequestAndRespondWith(test_data::kU2fCheckOnlySignCommandApdu,
+                                      test_data::kU2fWrongDataApduResponse);
+  // After the rejection, request with alternative application parameter should
+  // be tried, which will also be rejected.
+  device->ExpectRequestAndRespondWith(
+      test_data::
+          kU2fCheckOnlySignCommandApduWithAlternativeApplicationParameter,
+      test_data::kU2fWrongDataApduResponse);
+  // The second rejection will trigger a bogus register command. This will be
+  // rejected as well, triggering the device to be abandoned.
+  device->ExpectRequestAndRespondWith(test_data::kU2fFakeRegisterCommand,
+                                      test_data::kU2fWrongDataApduResponse);
+
+  auto u2f_sign = std::make_unique<U2fSignOperation>(
+      device.get(), std::move(request), sign_callback_receiver().callback());
+  u2f_sign->Start();
+  sign_callback_receiver().WaitForCallback();
+
+  EXPECT_EQ(CtapDeviceResponseCode::kCtap2ErrOther,
+            sign_callback_receiver().status());
+  EXPECT_FALSE(sign_callback_receiver().value());
+}
+
+}  // namespace device
diff --git a/device/fido/u2f_sign_unittest.cc b/device/fido/u2f_sign_unittest.cc
deleted file mode 100644
index 23b972d..0000000
--- a/device/fido/u2f_sign_unittest.cc
+++ /dev/null
@@ -1,490 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "device/fido/u2f_sign.h"
-
-#include <utility>
-
-#include "base/run_loop.h"
-#include "base/test/scoped_task_environment.h"
-#include "crypto/ec_private_key.h"
-#include "device/fido/authenticator_get_assertion_response.h"
-#include "device/fido/fake_fido_discovery.h"
-#include "device/fido/fido_constants.h"
-#include "device/fido/fido_parsing_utils.h"
-#include "device/fido/fido_test_data.h"
-#include "device/fido/fido_transport_protocol.h"
-#include "device/fido/mock_fido_device.h"
-#include "device/fido/test_callback_receiver.h"
-#include "device/fido/virtual_u2f_device.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using ::testing::_;
-
-namespace device {
-
-namespace {
-
-std::vector<uint8_t> GetTestCredentialRawIdBytes() {
-  return fido_parsing_utils::Materialize(test_data::kU2fSignKeyHandle);
-}
-
-std::vector<uint8_t> GetU2fSignCommandWithCorrectCredential() {
-  return fido_parsing_utils::Materialize(test_data::kU2fSignCommandApdu);
-}
-
-using TestSignCallback = ::device::test::StatusAndValueCallbackReceiver<
-    FidoReturnCode,
-    base::Optional<AuthenticatorGetAssertionResponse>>;
-
-}  // namespace
-
-class U2fSignTest : public ::testing::Test {
- public:
-  U2fSignTest()
-      : scoped_task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::UI) {}
-
-  void ForgeNextHidDiscovery() {
-    discovery_ = scoped_fake_discovery_factory_.ForgeNextHidDiscovery();
-  }
-
-  std::unique_ptr<U2fSign> CreateSignRequest() {
-    return CreateSignRequestWithKeys({GetTestCredentialRawIdBytes()});
-  }
-
-  std::unique_ptr<U2fSign> CreateSignRequestWithKeys(
-      std::vector<std::vector<uint8_t>> registered_keys) {
-    ForgeNextHidDiscovery();
-    return std::make_unique<U2fSign>(
-        nullptr /* connector */,
-        base::flat_set<FidoTransportProtocol>(
-            {FidoTransportProtocol::kUsbHumanInterfaceDevice}),
-        std::move(registered_keys),
-        fido_parsing_utils::Materialize(test_data::kChallengeParameter),
-        fido_parsing_utils::Materialize(test_data::kApplicationParameter),
-        base::nullopt /* alt_application_parameter*/,
-        sign_callback_receiver_.callback());
-  }
-
-  test::FakeFidoDiscovery* discovery() const { return discovery_; }
-  TestSignCallback& sign_callback_receiver() { return sign_callback_receiver_; }
-
- protected:
-  base::test::ScopedTaskEnvironment scoped_task_environment_;
-  test::ScopedFakeFidoDiscoveryFactory scoped_fake_discovery_factory_;
-  test::FakeFidoDiscovery* discovery_;
-  TestSignCallback sign_callback_receiver_;
-  base::flat_set<FidoTransportProtocol> protocols_;
-};
-
-TEST_F(U2fSignTest, TestSignSuccess) {
-  auto request = CreateSignRequest();
-  request->Start();
-  discovery()->WaitForCallToStartAndSimulateSuccess();
-
-  auto device = std::make_unique<MockFidoDevice>();
-  EXPECT_CALL(*device, GetId()).WillRepeatedly(testing::Return("device"));
-  EXPECT_CALL(*device,
-              DeviceTransactPtr(GetU2fSignCommandWithCorrectCredential(), _))
-      .WillOnce(testing::Invoke(MockFidoDevice::NoErrorSign));
-  EXPECT_CALL(*device, TryWinkRef(_))
-      .WillOnce(::testing::Invoke(MockFidoDevice::WinkDoNothing));
-  discovery()->AddDevice(std::move(device));
-
-  sign_callback_receiver().WaitForCallback();
-  EXPECT_EQ(FidoReturnCode::kSuccess, sign_callback_receiver().status());
-
-  // Correct key was sent so a sign response is expected.
-  EXPECT_THAT(sign_callback_receiver().value()->signature(),
-              ::testing::ElementsAreArray(test_data::kU2fSignature));
-
-  // Verify that we get the key handle used for signing.
-  EXPECT_THAT(GetTestCredentialRawIdBytes(),
-              ::testing::ElementsAreArray(
-                  sign_callback_receiver().value()->raw_credential_id()));
-}
-
-TEST_F(U2fSignTest, TestSignSuccessWithFake) {
-  auto private_key = crypto::ECPrivateKey::Create();
-  std::string public_key;
-  private_key->ExportRawPublicKey(&public_key);
-
-  auto key_handle = fido_parsing_utils::CreateSHA256Hash(public_key);
-  std::vector<std::vector<uint8_t>> handles{key_handle};
-  auto request = CreateSignRequestWithKeys(handles);
-  request->Start();
-  discovery()->WaitForCallToStartAndSimulateSuccess();
-
-  auto device = std::make_unique<VirtualU2fDevice>();
-  device->mutable_state()->registrations.emplace(
-      key_handle,
-      VirtualFidoDevice::RegistrationData(
-          std::move(private_key),
-          fido_parsing_utils::Materialize(test_data::kApplicationParameter),
-          42));
-  discovery()->AddDevice(std::move(device));
-
-  sign_callback_receiver().WaitForCallback();
-  EXPECT_EQ(FidoReturnCode::kSuccess, sign_callback_receiver().status());
-
-  // Just a sanity check, we don't verify the actual signature.
-  ASSERT_GE(32u + 1u + 4u + 8u,  // Minimal ECDSA signature is 8 bytes
-            sign_callback_receiver()
-                .value()
-                ->auth_data()
-                .SerializeToByteArray()
-                .size());
-  EXPECT_EQ(0x01,
-            sign_callback_receiver()
-                .value()
-                ->auth_data()
-                .SerializeToByteArray()[32]);  // UP flag
-  EXPECT_EQ(43, sign_callback_receiver()
-                    .value()
-                    ->auth_data()
-                    .SerializeToByteArray()[36]);  // counter
-}
-
-TEST_F(U2fSignTest, TestDelayedSuccess) {
-  auto request = CreateSignRequest();
-  request->Start();
-  discovery()->WaitForCallToStartAndSimulateSuccess();
-
-  // Go through the state machine twice before success.
-  auto device = std::make_unique<MockFidoDevice>();
-  EXPECT_CALL(*device, GetId()).WillRepeatedly(::testing::Return("device"));
-  EXPECT_CALL(*device,
-              DeviceTransactPtr(GetU2fSignCommandWithCorrectCredential(), _))
-      .WillOnce(::testing::Invoke(MockFidoDevice::NotSatisfied))
-      .WillOnce(::testing::Invoke(MockFidoDevice::NoErrorSign));
-  EXPECT_CALL(*device, TryWinkRef(_))
-      .Times(2)
-      .WillRepeatedly(::testing::Invoke(MockFidoDevice::WinkDoNothing));
-  discovery()->AddDevice(std::move(device));
-
-  sign_callback_receiver().WaitForCallback();
-  EXPECT_EQ(FidoReturnCode::kSuccess, sign_callback_receiver().status());
-
-  // Correct key was sent so a sign response is expected.
-  EXPECT_THAT(sign_callback_receiver().value()->signature(),
-              ::testing::ElementsAreArray(test_data::kU2fSignature));
-
-  // Verify that we get the key handle used for signing.
-  EXPECT_THAT(GetTestCredentialRawIdBytes(),
-              ::testing::ElementsAreArray(
-                  sign_callback_receiver().value()->raw_credential_id()));
-}
-
-TEST_F(U2fSignTest, TestMultipleHandles) {
-  // Two wrong keys followed by a correct key ensuring the wrong keys will be
-  // tested first.
-  const auto correct_key_handle = GetTestCredentialRawIdBytes();
-  auto request = CreateSignRequestWithKeys(
-      {fido_parsing_utils::Materialize(test_data::kKeyHandleAlpha),
-       fido_parsing_utils::Materialize(test_data::kKeyHandleBeta),
-       correct_key_handle});
-  request->Start();
-  discovery()->WaitForCallToStartAndSimulateSuccess();
-
-  auto device = std::make_unique<MockFidoDevice>();
-  // Wrong key would respond with SW_WRONG_DATA.
-  EXPECT_CALL(*device, GetId()).WillRepeatedly(::testing::Return("device"));
-  EXPECT_CALL(*device,
-              DeviceTransactPtr(fido_parsing_utils::Materialize(
-                                    test_data::kU2fSignCommandApduWithKeyAlpha),
-                                _))
-      .WillOnce(::testing::Invoke(MockFidoDevice::WrongData));
-  EXPECT_CALL(*device,
-              DeviceTransactPtr(fido_parsing_utils::Materialize(
-                                    test_data::kU2fSignCommandApduWithKeyBeta),
-                                _))
-      .WillOnce(::testing::Invoke(MockFidoDevice::WrongData));
-
-  EXPECT_CALL(*device,
-              DeviceTransactPtr(GetU2fSignCommandWithCorrectCredential(), _))
-      .WillOnce(::testing::Invoke(MockFidoDevice::NoErrorSign));
-
-  // Only one wink expected per device.
-  EXPECT_CALL(*device, TryWinkRef(_))
-      .WillOnce(::testing::Invoke(MockFidoDevice::WinkDoNothing));
-  discovery()->AddDevice(std::move(device));
-
-  sign_callback_receiver().WaitForCallback();
-  EXPECT_EQ(FidoReturnCode::kSuccess, sign_callback_receiver().status());
-
-  // Correct key was sent so a sign response is expected.
-  EXPECT_THAT(sign_callback_receiver().value()->signature(),
-              ::testing::ElementsAreArray(test_data::kU2fSignature));
-  // Verify that we get the key handle used for signing.
-  EXPECT_EQ(correct_key_handle,
-            sign_callback_receiver().value()->raw_credential_id());
-}
-
-TEST_F(U2fSignTest, TestMultipleDevices) {
-  const auto correct_key_handle = GetTestCredentialRawIdBytes();
-  auto request = CreateSignRequestWithKeys(
-      {GetTestCredentialRawIdBytes(),
-       fido_parsing_utils::Materialize(test_data::kKeyHandleAlpha)});
-  request->Start();
-
-  auto device0 = std::make_unique<MockFidoDevice>();
-  EXPECT_CALL(*device0, GetId()).WillRepeatedly(::testing::Return("device0"));
-  EXPECT_CALL(*device0,
-              DeviceTransactPtr(GetU2fSignCommandWithCorrectCredential(), _))
-      .WillOnce(::testing::Invoke(MockFidoDevice::WrongData));
-  EXPECT_CALL(*device0,
-              DeviceTransactPtr(fido_parsing_utils::Materialize(
-                                    test_data::kU2fSignCommandApduWithKeyAlpha),
-                                _))
-      .WillOnce(::testing::Invoke(MockFidoDevice::NotSatisfied));
-  // One wink per device.
-  EXPECT_CALL(*device0, TryWinkRef(_))
-      .WillOnce(::testing::Invoke(MockFidoDevice::WinkDoNothing));
-  discovery()->AddDevice(std::move(device0));
-
-  // Second device will have a successful touch.
-  auto device1 = std::make_unique<MockFidoDevice>();
-  EXPECT_CALL(*device1, GetId()).WillRepeatedly(::testing::Return("device1"));
-  EXPECT_CALL(*device1,
-              DeviceTransactPtr(GetU2fSignCommandWithCorrectCredential(), _))
-      .WillOnce(::testing::Invoke(MockFidoDevice::NoErrorSign));
-
-  // One wink per device.
-  EXPECT_CALL(*device1, TryWinkRef(_))
-      .WillOnce(::testing::Invoke(MockFidoDevice::WinkDoNothing));
-  discovery()->AddDevice(std::move(device1));
-  discovery()->WaitForCallToStartAndSimulateSuccess();
-
-  sign_callback_receiver().WaitForCallback();
-  EXPECT_EQ(FidoReturnCode::kSuccess, sign_callback_receiver().status());
-
-  // Correct key was sent so a sign response is expected.
-  EXPECT_THAT(sign_callback_receiver().value()->signature(),
-              ::testing::ElementsAreArray(test_data::kU2fSignature));
-
-  // Verify that we get the key handle used for signing.
-  EXPECT_EQ(correct_key_handle,
-            sign_callback_receiver().value()->raw_credential_id());
-}
-
-TEST_F(U2fSignTest, TestFakeEnroll) {
-  auto request = CreateSignRequestWithKeys(
-      {fido_parsing_utils::Materialize(test_data::kKeyHandleAlpha),
-       fido_parsing_utils::Materialize(test_data::kKeyHandleBeta)});
-  request->Start();
-
-  auto device0 = std::make_unique<MockFidoDevice>();
-  EXPECT_CALL(*device0,
-              DeviceTransactPtr(fido_parsing_utils::Materialize(
-                                    test_data::kU2fSignCommandApduWithKeyAlpha),
-                                _))
-      .WillOnce(::testing::Invoke(MockFidoDevice::WrongData));
-
-  EXPECT_CALL(*device0,
-              DeviceTransactPtr(fido_parsing_utils::Materialize(
-                                    test_data::kU2fSignCommandApduWithKeyBeta),
-                                _))
-      .WillOnce(::testing::Invoke(MockFidoDevice::NotSatisfied));
-  // One wink per device.
-  EXPECT_CALL(*device0, TryWinkRef(_))
-      .WillOnce(::testing::Invoke(MockFidoDevice::WinkDoNothing));
-  discovery()->AddDevice(std::move(device0));
-
-  // Second device will be have a successful touch.
-  auto device1 = std::make_unique<MockFidoDevice>();
-  EXPECT_CALL(*device1, GetId()).WillRepeatedly(::testing::Return("device1"));
-  // Both keys will be tried, when both fail, register is tried on that device.
-  EXPECT_CALL(*device1,
-              DeviceTransactPtr(fido_parsing_utils::Materialize(
-                                    test_data::kU2fSignCommandApduWithKeyAlpha),
-                                _))
-      .WillOnce(::testing::Invoke(MockFidoDevice::WrongData));
-  EXPECT_CALL(*device1,
-              DeviceTransactPtr(fido_parsing_utils::Materialize(
-                                    test_data::kU2fSignCommandApduWithKeyBeta),
-                                _))
-      .WillOnce(::testing::Invoke(MockFidoDevice::WrongData));
-  EXPECT_CALL(*device1,
-              DeviceTransactPtr(fido_parsing_utils::Materialize(
-                                    test_data::kU2fFakeRegisterCommand),
-                                _))
-      .WillOnce(::testing::Invoke(MockFidoDevice::NoErrorRegister));
-
-  // One wink per device.
-  EXPECT_CALL(*device1, TryWinkRef(_))
-      .WillOnce(::testing::Invoke(MockFidoDevice::WinkDoNothing));
-  discovery()->AddDevice(std::move(device1));
-  discovery()->WaitForCallToStartAndSimulateSuccess();
-
-  sign_callback_receiver().WaitForCallback();
-  // Device that responded had no correct keys.
-  EXPECT_EQ(FidoReturnCode::kUserConsentButCredentialNotRecognized,
-            sign_callback_receiver().status());
-  EXPECT_FALSE(sign_callback_receiver().value());
-}
-
-TEST_F(U2fSignTest, TestFakeEnrollErroringOut) {
-  auto request = CreateSignRequest();
-  request->Start();
-  // First device errors out on all requests (including the sign request and
-  // fake registration attempt). The device should then be abandoned to prevent
-  // the test from crashing or timing out.
-  auto device0 = std::make_unique<MockFidoDevice>();
-  EXPECT_CALL(*device0, GetId()).WillRepeatedly(::testing::Return("device0"));
-  EXPECT_CALL(*device0,
-              DeviceTransactPtr(GetU2fSignCommandWithCorrectCredential(), _))
-      .WillOnce(::testing::Invoke(MockFidoDevice::WrongData));
-  EXPECT_CALL(*device0,
-              DeviceTransactPtr(fido_parsing_utils::Materialize(
-                                    test_data::kU2fFakeRegisterCommand),
-                                _))
-      .WillOnce(::testing::Invoke(MockFidoDevice::WrongData));
-  // One wink per device.
-  EXPECT_CALL(*device0, TryWinkRef(_))
-      .WillOnce(::testing::Invoke(MockFidoDevice::WinkDoNothing));
-  discovery()->AddDevice(std::move(device0));
-
-  // Second device will have a successful touch and sign on the first attempt.
-  auto device1 = std::make_unique<MockFidoDevice>();
-  EXPECT_CALL(*device1, GetId()).WillRepeatedly(::testing::Return("device1"));
-  EXPECT_CALL(*device1,
-              DeviceTransactPtr(GetU2fSignCommandWithCorrectCredential(), _))
-      .WillOnce(::testing::Invoke(MockFidoDevice::NoErrorSign));
-  // One wink per device.
-  EXPECT_CALL(*device1, TryWinkRef(_))
-      .WillOnce(::testing::Invoke(MockFidoDevice::WinkDoNothing));
-  discovery()->AddDevice(std::move(device1));
-  discovery()->WaitForCallToStartAndSimulateSuccess();
-
-  // Correct key was sent so a sign response is expected.
-  sign_callback_receiver().WaitForCallback();
-  EXPECT_THAT(sign_callback_receiver().value()->signature(),
-              ::testing::ElementsAreArray(test_data::kU2fSignature));
-}
-
-// Device returns success, but the response is unparse-able.
-TEST_F(U2fSignTest, TestSignWithCorruptedResponse) {
-  auto request = CreateSignRequest();
-  request->Start();
-  discovery()->WaitForCallToStartAndSimulateSuccess();
-
-  auto device = std::make_unique<MockFidoDevice>();
-  EXPECT_CALL(*device, GetId()).WillRepeatedly(::testing::Return("device"));
-  EXPECT_CALL(*device,
-              DeviceTransactPtr(GetU2fSignCommandWithCorrectCredential(), _))
-      .WillOnce(::testing::Invoke(MockFidoDevice::SignWithCorruptedResponse));
-  EXPECT_CALL(*device, TryWinkRef(_))
-      .WillOnce(::testing::Invoke(MockFidoDevice::WinkDoNothing));
-  discovery()->AddDevice(std::move(device));
-
-  sign_callback_receiver().WaitForCallback();
-  EXPECT_EQ(FidoReturnCode::kAuthenticatorResponseInvalid,
-            sign_callback_receiver().status());
-  EXPECT_FALSE(sign_callback_receiver().value());
-}
-
-MATCHER_P(WithApplicationParameter, expected, "") {
-  // See
-  // https://fidoalliance.org/specs/fido-u2f-v1.2-ps-20170411/fido-u2f-raw-message-formats-v1.2-ps-20170411.html#request-message-framing
-  // and
-  // https://fidoalliance.org/specs/fido-u2f-v1.2-ps-20170411/fido-u2f-raw-message-formats-v1.2-ps-20170411.html#authentication-request-message---u2f_authenticate
-  constexpr size_t kAppParamOffset = 4 /* CLA + INS + P1 + P2 */ +
-                                     3 /* Extended Lc */ +
-                                     32 /* Challenge Parameter */;
-  constexpr size_t kAppParamLength = 32;
-  if (arg.size() < kAppParamOffset + kAppParamLength) {
-    return false;
-  }
-
-  auto application_parameter =
-      base::make_span(arg).subspan(kAppParamOffset, kAppParamLength);
-
-  return std::equal(application_parameter.begin(), application_parameter.end(),
-                    expected.begin(), expected.end());
-}
-
-TEST_F(U2fSignTest, TestAlternativeApplicationParameter) {
-  const std::vector<uint8_t> signing_key_handle(32, 0x0A);
-  const std::vector<uint8_t> primary_app_param(32, 1);
-  const std::vector<uint8_t> alt_app_param(32, 2);
-
-  ForgeNextHidDiscovery();
-  auto request = std::make_unique<U2fSign>(
-      nullptr /* connector */,
-      base::flat_set<FidoTransportProtocol>(
-          {FidoTransportProtocol::kUsbHumanInterfaceDevice}),
-      std::vector<std::vector<uint8_t>>({signing_key_handle}),
-      std::vector<uint8_t>(32), primary_app_param, alt_app_param,
-      sign_callback_receiver_.callback());
-  request->Start();
-  discovery()->WaitForCallToStartAndSimulateSuccess();
-
-  auto device = std::make_unique<MockFidoDevice>();
-  EXPECT_CALL(*device, GetId()).WillRepeatedly(::testing::Return("device"));
-  // The first request will use the primary app_param, which will be rejected.
-  EXPECT_CALL(*device,
-              DeviceTransactPtr(WithApplicationParameter(primary_app_param), _))
-      .WillOnce(::testing::Invoke(MockFidoDevice::WrongData));
-  // After the rejection, the alternative should be tried.
-  EXPECT_CALL(*device,
-              DeviceTransactPtr(WithApplicationParameter(alt_app_param), _))
-      .WillOnce(::testing::Invoke(MockFidoDevice::NoErrorSign));
-  EXPECT_CALL(*device, TryWinkRef(_))
-      .WillOnce(::testing::Invoke(MockFidoDevice::WinkDoNothing));
-  discovery()->AddDevice(std::move(device));
-
-  sign_callback_receiver().WaitForCallback();
-  EXPECT_EQ(FidoReturnCode::kSuccess, sign_callback_receiver().status());
-
-  EXPECT_THAT(sign_callback_receiver().value()->signature(),
-              ::testing::ElementsAreArray(test_data::kU2fSignature));
-  EXPECT_EQ(signing_key_handle,
-            sign_callback_receiver().value()->raw_credential_id());
-}
-
-// This is a regression test in response to https://crbug.com/833398.
-TEST_F(U2fSignTest, TestAlternativeApplicationParameterRejection) {
-  const std::vector<uint8_t> signing_key_handle(32, 0x0A);
-  const std::vector<uint8_t> primary_app_param(32, 1);
-  const std::vector<uint8_t> alt_app_param(32, 2);
-
-  ForgeNextHidDiscovery();
-  auto request = std::make_unique<U2fSign>(
-      nullptr /* connector */,
-      base::flat_set<FidoTransportProtocol>(
-          {FidoTransportProtocol::kUsbHumanInterfaceDevice}),
-      std::vector<std::vector<uint8_t>>({signing_key_handle}),
-      std::vector<uint8_t>(32), primary_app_param, alt_app_param,
-      sign_callback_receiver_.callback());
-  request->Start();
-  discovery()->WaitForCallToStartAndSimulateSuccess();
-
-  auto device = std::make_unique<MockFidoDevice>();
-  EXPECT_CALL(*device, GetId()).WillRepeatedly(::testing::Return("device"));
-  EXPECT_CALL(*device, TryWinkRef(_))
-      .WillOnce(::testing::Invoke(MockFidoDevice::WinkDoNothing));
-
-  // The first request will use the primary app_param, which will be rejected.
-  EXPECT_CALL(*device,
-              DeviceTransactPtr(WithApplicationParameter(primary_app_param), _))
-      .WillOnce(::testing::Invoke(MockFidoDevice::WrongData));
-
-  // After the rejection, the alternative should be tried, which will also be
-  // rejected.
-  EXPECT_CALL(*device,
-              DeviceTransactPtr(WithApplicationParameter(alt_app_param), _))
-      .WillOnce(::testing::Invoke(MockFidoDevice::WrongData));
-
-  // The second rejection will trigger a bogus register command. This will be
-  // rejected as well, triggering the device to be abandoned.
-  EXPECT_CALL(*device,
-              DeviceTransactPtr(WithApplicationParameter(kBogusAppParam), _))
-      .WillOnce(::testing::Invoke(MockFidoDevice::WrongData));
-
-  discovery()->AddDevice(std::move(device));
-}
-
-}  // namespace device
diff --git a/extensions/common/permissions/permissions_data.cc b/extensions/common/permissions/permissions_data.cc
index 2b7bfc5..79a34cf 100644
--- a/extensions/common/permissions/permissions_data.cc
+++ b/extensions/common/permissions/permissions_data.cc
@@ -85,13 +85,6 @@
   return base::ContainsValue(whitelist, extension_id);
 }
 
-// static
-bool PermissionsData::ShouldSkipPermissionWarnings(
-    const std::string& extension_id) {
-  // See http://b/4946060 for more details.
-  return extension_id == extension_misc::kProdHangoutsExtensionId;
-}
-
 bool PermissionsData::IsRestrictedUrl(const GURL& document_url,
                                       std::string* error) const {
   if (CanExecuteScriptEverywhere(extension_id_, location_))
diff --git a/extensions/common/permissions/permissions_data.h b/extensions/common/permissions/permissions_data.h
index 086d9767..265d2e8 100644
--- a/extensions/common/permissions/permissions_data.h
+++ b/extensions/common/permissions/permissions_data.h
@@ -77,10 +77,6 @@
   static bool CanExecuteScriptEverywhere(const ExtensionId& extension_id,
                                          Manifest::Location location);
 
-  // Returns true if we should skip the permissions warning for the extension
-  // with the given |extension_id|.
-  static bool ShouldSkipPermissionWarnings(const std::string& extension_id);
-
   // Returns true if the given |url| is restricted for the given |extension|,
   // as is commonly the case for chrome:// urls.
   // NOTE: You probably want to use CanAccessPage().
diff --git a/gpu/command_buffer/service/raster_decoder.cc b/gpu/command_buffer/service/raster_decoder.cc
index 537e926..f7e61038 100644
--- a/gpu/command_buffer/service/raster_decoder.cc
+++ b/gpu/command_buffer/service/raster_decoder.cc
@@ -3086,7 +3086,7 @@
 
   int op_idx = 0;
   size_t paint_buffer_size = raster_shm_size;
-  while (paint_buffer_size > 4) {
+  while (paint_buffer_size > 0) {
     size_t skip = 0;
     cc::PaintOp* deserialized_op = cc::PaintOp::Deserialize(
         paint_buffer_memory, paint_buffer_size, &data[0],
diff --git a/infra/config/global/cr-buildbucket.cfg b/infra/config/global/cr-buildbucket.cfg
index ad47f39..8623b38 100644
--- a/infra/config/global/cr-buildbucket.cfg
+++ b/infra/config/global/cr-buildbucket.cfg
@@ -2696,6 +2696,11 @@
       mixins: "android-try"
     }
     builders {
+      name: "android_unswarmed_pixel_aosp"
+      dimensions: "os:Ubuntu-14.04"
+      mixins: "android-try"
+    }
+    builders {
       name: "android_cronet_tester"
       dimensions: "os:Ubuntu-14.04"
       mixins: "android-try"
diff --git a/infra/config/global/luci-milo.cfg b/infra/config/global/luci-milo.cfg
index 42baad61..a2211854 100644
--- a/infra/config/global/luci-milo.cfg
+++ b/infra/config/global/luci-milo.cfg
@@ -309,27 +309,27 @@
   ref: "refs/heads/master"
   manifest_name: "REVISION"
   builders {
-    name: "buildbot/chromium/Win"
+    name: "buildbucket/luci.chromium.ci/Win"
     category: "chromium|win"
     short_name: "32"
   }
   builders {
-    name: "buildbot/chromium/Win x64"
+    name: "buildbucket/luci.chromium.ci/Win x64"
     category: "chromium|win"
     short_name: "64"
   }
   builders {
-    name: "buildbot/chromium/Mac"
+    name: "buildbucket/luci.chromium.ci/Mac"
     category: "chromium"
     short_name: "mac"
   }
   builders {
-    name: "buildbot/chromium/Linux x64"
+    name: "buildbucket/luci.chromium.ci/Linux x64"
     category: "chromium"
     short_name: "lin"
   }
   builders {
-    name: "buildbot/chromium/Android"
+    name: "buildbucket/luci.chromium.ci/Android"
     category: "chromium"
     short_name: "and"
   }
@@ -1538,42 +1538,6 @@
   repo_url: "https://chromium.googlesource.com/chromium/src"
   ref: "refs/heads/master"
   manifest_name: "REVISION"
-  builders {
-    name: "buildbot/chromium/Android"
-    name: "buildbucket/luci.chromium.ci/Android"
-    short_name: "an"
-  }
-  builders {
-    name: "buildbot/chromium/Linux x64"
-    name: "buildbucket/luci.chromium.ci/Linux x64"
-    short_name: "lnx"
-  }
-  builders {
-    name: "buildbot/chromium/Mac"
-    name: "buildbucket/luci.chromium.ci/Mac"
-    short_name: "mac"
-  }
-  builders {
-    name: "buildbot/chromium/Win"
-    name: "buildbucket/luci.chromium.ci/Win"
-    category: "win"
-    short_name: "32"
-  }
-  builders {
-    name: "buildbot/chromium/Win x64"
-    name: "buildbucket/luci.chromium.ci/Win x64"
-    category: "win"
-    short_name: "64"
-  }
-}
-
-consoles {
-  header_id: "chromium"
-  id: "luci.chromium"
-  name: "luci.chromium"
-  repo_url: "https://chromium.googlesource.com/chromium/src"
-  ref: "refs/heads/master"
-  manifest_name: "REVISION"
   include_experimental_builds: true
   builders {
     name: "buildbucket/luci.chromium.ci/Android"
@@ -3983,6 +3947,9 @@
     name: "buildbot/tryserver.chromium.android/android_unswarmed_n5x_rel"
   }
   builders {
+    name: "buildbucket/luci.chromium.try/android_unswarmed_pixel_aosp"
+  }
+  builders {
     name: "buildbot/tryserver.chromium.android/cast_shell_android"
     name: "buildbucket/luci.chromium.try/cast_shell_android"
   }
diff --git a/ios/chrome/browser/favicon/favicon_loader.mm b/ios/chrome/browser/favicon/favicon_loader.mm
index a850548..458cb89 100644
--- a/ios/chrome/browser/favicon/favicon_loader.mm
+++ b/ios/chrome/browser/favicon/favicon_loader.mm
@@ -13,6 +13,7 @@
 #include "components/favicon/core/large_icon_service.h"
 #include "components/favicon_base/fallback_icon_style.h"
 #include "components/favicon_base/favicon_callback.h"
+#include "ios/chrome/browser/experimental_flags.h"
 #import "ios/chrome/browser/ui/favicon/favicon_attributes.h"
 #include "skia/ext/skia_utils_ios.h"
 #include "url/gurl.h"
@@ -78,6 +79,10 @@
       url, min_favicon_size, favicon_size_in_pixels,
       base::BindRepeating(favicon_block), &cancelable_task_tracker_);
 
+  if (experimental_flags::IsCollectionsUIRebootEnabled()) {
+    return [FaviconAttributes
+        attributesWithImage:[UIImage imageNamed:@"default_world_favicon"]];
+  }
   return [FaviconAttributes
       attributesWithImage:[UIImage imageNamed:@"default_favicon"]];
 }
diff --git a/ios/chrome/browser/ui/BUILD.gn b/ios/chrome/browser/ui/BUILD.gn
index b97aa4a..5814c49 100644
--- a/ios/chrome/browser/ui/BUILD.gn
+++ b/ios/chrome/browser/ui/BUILD.gn
@@ -289,8 +289,6 @@
     ":ui",
     "resources:custom_row_voice",
     "resources:custom_row_voice_pressed",
-    "resources:default_favicon",
-    "resources:default_favicon_incognito",
     "resources:keyboard_bg_portrait_tablet",
     "resources:keyboard_button",
     "//base",
diff --git a/ios/chrome/browser/ui/bookmarks/bookmark_home_view_controller.mm b/ios/chrome/browser/ui/bookmarks/bookmark_home_view_controller.mm
index 556ddcb..07ea84f 100644
--- a/ios/chrome/browser/ui/bookmarks/bookmark_home_view_controller.mm
+++ b/ios/chrome/browser/ui/bookmarks/bookmark_home_view_controller.mm
@@ -362,9 +362,6 @@
   if (experimental_flags::IsBookmarksUIRebootEnabled()) {
     self.navigationController.navigationBarHidden = NO;
     self.navigationController.toolbar.translucent = YES;
-    // If the NavigationBar is not translucent, set
-    // |self.extendedLayoutIncludesOpaqueBars| to YES.
-    self.extendedLayoutIncludesOpaqueBars = YES;
   } else {
     self.navigationController.navigationBarHidden = YES;
     self.navigationController.toolbar.translucent = NO;
diff --git a/ios/chrome/browser/ui/browser_view_controller_egtest.mm b/ios/chrome/browser/ui/browser_view_controller_egtest.mm
index 95dae447..c41b33bb 100644
--- a/ios/chrome/browser/ui/browser_view_controller_egtest.mm
+++ b/ios/chrome/browser/ui/browser_view_controller_egtest.mm
@@ -13,6 +13,7 @@
 #include "ios/chrome/browser/ui/ui_util.h"
 #import "ios/chrome/test/app/chrome_test_util.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
+#import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h"
 #import "ios/chrome/test/earl_grey/chrome_matchers.h"
 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
 #include "ios/web/public/test/http_server/html_response_provider.h"
@@ -61,9 +62,7 @@
   NSString* script =
       [NSString stringWithFormat:@"javascript:location.href='%s'\n",
                                  destinationURL.spec().c_str()];
-
-  [[EarlGrey selectElementWithMatcher:chrome_test_util::Omnibox()]
-      performAction:grey_typeText(script)];
+  [ChromeEarlGreyUI focusOmniboxAndType:script];
 
   // In the omnibox, the new URL should be present, without the http:// prefix.
   [[EarlGrey selectElementWithMatcher:chrome_test_util::Omnibox()]
diff --git a/ios/chrome/browser/ui/favicon/BUILD.gn b/ios/chrome/browser/ui/favicon/BUILD.gn
index 3854617..3006522f 100644
--- a/ios/chrome/browser/ui/favicon/BUILD.gn
+++ b/ios/chrome/browser/ui/favicon/BUILD.gn
@@ -11,6 +11,8 @@
   ]
   deps = [
     ":favicon_ui",
+    "resources:default_favicon",
+    "resources:default_world_favicon",
     "//base",
     "//components/favicon/core",
     "//components/favicon_base",
diff --git a/ios/chrome/browser/ui/favicon/resources/BUILD.gn b/ios/chrome/browser/ui/favicon/resources/BUILD.gn
new file mode 100644
index 0000000..e169523
--- /dev/null
+++ b/ios/chrome/browser/ui/favicon/resources/BUILD.gn
@@ -0,0 +1,32 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/config/ios/asset_catalog.gni")
+
+imageset("default_world_favicon") {
+  sources = [
+    "default_world_favicon.imageset/Contents.json",
+    "default_world_favicon.imageset/default_world_favicon.png",
+    "default_world_favicon.imageset/default_world_favicon@2x.png",
+    "default_world_favicon.imageset/default_world_favicon@3x.png",
+  ]
+}
+
+imageset("default_favicon") {
+  sources = [
+    "default_favicon.imageset/Contents.json",
+    "default_favicon.imageset/default_favicon.png",
+    "default_favicon.imageset/default_favicon@2x.png",
+    "default_favicon.imageset/default_favicon@3x.png",
+  ]
+}
+
+imageset("default_favicon_incognito") {
+  sources = [
+    "default_favicon_incognito.imageset/Contents.json",
+    "default_favicon_incognito.imageset/default_favicon_incognito.png",
+    "default_favicon_incognito.imageset/default_favicon_incognito@2x.png",
+    "default_favicon_incognito.imageset/default_favicon_incognito@3x.png",
+  ]
+}
diff --git a/ios/chrome/browser/ui/resources/default_favicon.imageset/Contents.json b/ios/chrome/browser/ui/favicon/resources/default_favicon.imageset/Contents.json
similarity index 100%
rename from ios/chrome/browser/ui/resources/default_favicon.imageset/Contents.json
rename to ios/chrome/browser/ui/favicon/resources/default_favicon.imageset/Contents.json
diff --git a/ios/chrome/browser/ui/resources/default_favicon.imageset/default_favicon.png b/ios/chrome/browser/ui/favicon/resources/default_favicon.imageset/default_favicon.png
similarity index 100%
rename from ios/chrome/browser/ui/resources/default_favicon.imageset/default_favicon.png
rename to ios/chrome/browser/ui/favicon/resources/default_favicon.imageset/default_favicon.png
Binary files differ
diff --git a/ios/chrome/browser/ui/resources/default_favicon.imageset/default_favicon@2x.png b/ios/chrome/browser/ui/favicon/resources/default_favicon.imageset/default_favicon@2x.png
similarity index 100%
rename from ios/chrome/browser/ui/resources/default_favicon.imageset/default_favicon@2x.png
rename to ios/chrome/browser/ui/favicon/resources/default_favicon.imageset/default_favicon@2x.png
Binary files differ
diff --git a/ios/chrome/browser/ui/resources/default_favicon.imageset/default_favicon@3x.png b/ios/chrome/browser/ui/favicon/resources/default_favicon.imageset/default_favicon@3x.png
similarity index 100%
rename from ios/chrome/browser/ui/resources/default_favicon.imageset/default_favicon@3x.png
rename to ios/chrome/browser/ui/favicon/resources/default_favicon.imageset/default_favicon@3x.png
Binary files differ
diff --git a/ios/chrome/browser/ui/resources/default_favicon_incognito.imageset/Contents.json b/ios/chrome/browser/ui/favicon/resources/default_favicon_incognito.imageset/Contents.json
similarity index 100%
rename from ios/chrome/browser/ui/resources/default_favicon_incognito.imageset/Contents.json
rename to ios/chrome/browser/ui/favicon/resources/default_favicon_incognito.imageset/Contents.json
diff --git a/ios/chrome/browser/ui/resources/default_favicon_incognito.imageset/default_favicon_incognito.png b/ios/chrome/browser/ui/favicon/resources/default_favicon_incognito.imageset/default_favicon_incognito.png
similarity index 100%
rename from ios/chrome/browser/ui/resources/default_favicon_incognito.imageset/default_favicon_incognito.png
rename to ios/chrome/browser/ui/favicon/resources/default_favicon_incognito.imageset/default_favicon_incognito.png
Binary files differ
diff --git a/ios/chrome/browser/ui/resources/default_favicon_incognito.imageset/default_favicon_incognito@2x.png b/ios/chrome/browser/ui/favicon/resources/default_favicon_incognito.imageset/default_favicon_incognito@2x.png
similarity index 100%
rename from ios/chrome/browser/ui/resources/default_favicon_incognito.imageset/default_favicon_incognito@2x.png
rename to ios/chrome/browser/ui/favicon/resources/default_favicon_incognito.imageset/default_favicon_incognito@2x.png
Binary files differ
diff --git a/ios/chrome/browser/ui/resources/default_favicon_incognito.imageset/default_favicon_incognito@3x.png b/ios/chrome/browser/ui/favicon/resources/default_favicon_incognito.imageset/default_favicon_incognito@3x.png
similarity index 100%
rename from ios/chrome/browser/ui/resources/default_favicon_incognito.imageset/default_favicon_incognito@3x.png
rename to ios/chrome/browser/ui/favicon/resources/default_favicon_incognito.imageset/default_favicon_incognito@3x.png
Binary files differ
diff --git a/ios/chrome/browser/ui/favicon/resources/default_world_favicon.imageset/Contents.json b/ios/chrome/browser/ui/favicon/resources/default_world_favicon.imageset/Contents.json
new file mode 100644
index 0000000..3614ccd
--- /dev/null
+++ b/ios/chrome/browser/ui/favicon/resources/default_world_favicon.imageset/Contents.json
@@ -0,0 +1,23 @@
+{
+    "images": [
+        {
+            "idiom": "universal",
+            "scale": "1x",
+            "filename": "default_world_favicon.png"
+        },
+        {
+            "idiom": "universal",
+            "scale": "2x",
+            "filename": "default_world_favicon@2x.png"
+        },
+        {
+            "idiom": "universal",
+            "scale": "3x",
+            "filename": "default_world_favicon@3x.png"
+        }
+    ],
+    "info": {
+        "version": 1,
+        "author": "xcode"
+    }
+}
diff --git a/ios/chrome/browser/ui/favicon/resources/default_world_favicon.imageset/default_world_favicon.png b/ios/chrome/browser/ui/favicon/resources/default_world_favicon.imageset/default_world_favicon.png
new file mode 100644
index 0000000..3b6c9360
--- /dev/null
+++ b/ios/chrome/browser/ui/favicon/resources/default_world_favicon.imageset/default_world_favicon.png
Binary files differ
diff --git a/ios/chrome/browser/ui/favicon/resources/default_world_favicon.imageset/default_world_favicon@2x.png b/ios/chrome/browser/ui/favicon/resources/default_world_favicon.imageset/default_world_favicon@2x.png
new file mode 100644
index 0000000..72b0b7c
--- /dev/null
+++ b/ios/chrome/browser/ui/favicon/resources/default_world_favicon.imageset/default_world_favicon@2x.png
Binary files differ
diff --git a/ios/chrome/browser/ui/favicon/resources/default_world_favicon.imageset/default_world_favicon@3x.png b/ios/chrome/browser/ui/favicon/resources/default_world_favicon.imageset/default_world_favicon@3x.png
new file mode 100644
index 0000000..7d10a12
--- /dev/null
+++ b/ios/chrome/browser/ui/favicon/resources/default_world_favicon.imageset/default_world_favicon@3x.png
Binary files differ
diff --git a/ios/chrome/browser/ui/history/BUILD.gn b/ios/chrome/browser/ui/history/BUILD.gn
index 7e656db..4da00123 100644
--- a/ios/chrome/browser/ui/history/BUILD.gn
+++ b/ios/chrome/browser/ui/history/BUILD.gn
@@ -108,6 +108,7 @@
     "history_util.mm",
   ]
   deps = [
+    "public",
     "//base",
     "//base:i18n",
     "//components/browsing_data/core",
diff --git a/ios/chrome/browser/ui/history/history_coordinator.h b/ios/chrome/browser/ui/history/history_coordinator.h
index 1ebeb3b..7502e43 100644
--- a/ios/chrome/browser/ui/history/history_coordinator.h
+++ b/ios/chrome/browser/ui/history/history_coordinator.h
@@ -12,6 +12,7 @@
 @protocol ApplicationCommands;
 @protocol BrowserCommands;
 @protocol UrlLoader;
+@protocol HistoryTabPresentationDelegate;
 
 // Coordinator that presents History.
 @interface HistoryCoordinator : ChromeCoordinator
@@ -19,6 +20,9 @@
 @property(nonatomic, weak) id<ApplicationCommands, BrowserCommands> dispatcher;
 // URL loader being managed by this Coordinator.
 @property(nonatomic, weak) id<UrlLoader> loader;
+// Delegate used to make the Tab UI visible.
+@property(nonatomic, weak) id<HistoryTabPresentationDelegate>
+    tabPresentationDelegate;
 @end
 
 #endif  // IOS_CHROME_BROWSER_UI_HISTORY_HISTORY_COORDINATOR_H_
diff --git a/ios/chrome/browser/ui/history/history_coordinator.mm b/ios/chrome/browser/ui/history/history_coordinator.mm
index a0b2a17..fb2a059 100644
--- a/ios/chrome/browser/ui/history/history_coordinator.mm
+++ b/ios/chrome/browser/ui/history/history_coordinator.mm
@@ -49,6 +49,7 @@
 @synthesize historyTransitioningDelegate = _historyTransitioningDelegate;
 @synthesize loader = _loader;
 @synthesize clearBrowsingDataCoordinator = _clearBrowsingDataCoordinator;
+@synthesize tabPresentationDelegate = _tabPresentationDelegate;
 
 - (void)start {
   // Initialize and configure HistoryTableViewController.
@@ -72,6 +73,8 @@
       initWithTable:historyTableViewController];
   self.historyNavigationController.toolbarHidden = NO;
   historyTableViewController.localDispatcher = self;
+  historyTableViewController.tabPresentationDelegate =
+      self.tabPresentationDelegate;
   self.historyTransitioningDelegate =
       [[HistoryTransitioningDelegate alloc] init];
   self.historyNavigationController.transitioningDelegate =
diff --git a/ios/chrome/browser/ui/history/history_table_view_controller.h b/ios/chrome/browser/ui/history/history_table_view_controller.h
index 8fa4ebb9..d63d17f2 100644
--- a/ios/chrome/browser/ui/history/history_table_view_controller.h
+++ b/ios/chrome/browser/ui/history/history_table_view_controller.h
@@ -14,6 +14,7 @@
 }
 
 @protocol HistoryLocalCommands;
+@protocol HistoryTabPresentationDelegate;
 @protocol UrlLoader;
 
 // ChromeTableViewController for displaying history items.
@@ -28,6 +29,9 @@
 @property(nonatomic, weak) id<UrlLoader> loader;
 // Delegate for this HistoryTableView.
 @property(nonatomic, weak) id<HistoryLocalCommands> localDispatcher;
+// Delegate used to make the Tab UI visible.
+@property(nonatomic, weak) id<HistoryTabPresentationDelegate>
+    tabPresentationDelegate;
 
 // Initializers.
 - (instancetype)init NS_DESIGNATED_INITIALIZER;
diff --git a/ios/chrome/browser/ui/history/history_table_view_controller.mm b/ios/chrome/browser/ui/history/history_table_view_controller.mm
index d14dc635..d7e27ca 100644
--- a/ios/chrome/browser/ui/history/history_table_view_controller.mm
+++ b/ios/chrome/browser/ui/history/history_table_view_controller.mm
@@ -23,6 +23,7 @@
 #include "ios/chrome/browser/ui/history/history_local_commands.h"
 #import "ios/chrome/browser/ui/history/history_ui_constants.h"
 #include "ios/chrome/browser/ui/history/history_util.h"
+#import "ios/chrome/browser/ui/history/public/history_tab_presentation_delegate.h"
 #import "ios/chrome/browser/ui/table_view/cells/table_view_cells_constants.h"
 #import "ios/chrome/browser/ui/table_view/cells/table_view_text_item.h"
 #import "ios/chrome/browser/ui/table_view/table_view_navigation_controller_constants.h"
@@ -110,6 +111,7 @@
 @synthesize searchController = _searchController;
 @synthesize shouldShowNoticeAboutOtherFormsOfBrowsingHistory =
     _shouldShowNoticeAboutOtherFormsOfBrowsingHistory;
+@synthesize tabPresentationDelegate = _tabPresentationDelegate;
 
 #pragma mark - ViewController Lifecycle.
 
@@ -139,11 +141,6 @@
               action:@selector(displayContextMenuInvokedByGestureRecognizer:)];
   [self.tableView addGestureRecognizer:longPressRecognizer];
 
-  // If the NavigationBar is not translucent, set
-  // |self.extendedLayoutIncludesOpaqueBars| to YES in order to avoid a top
-  // margin inset on the |_tableViewController| subview.
-  self.extendedLayoutIncludesOpaqueBars = YES;
-
   // NavigationController configuration.
   self.title = l10n_util::GetNSString(IDS_HISTORY_TITLE);
   // Configures NavigationController Toolbar buttons.
@@ -165,7 +162,7 @@
   self.searchController.dimsBackgroundDuringPresentation = NO;
   self.searchController.searchBar.delegate = self;
   self.searchController.searchResultsUpdater = self;
-  self.searchController.searchBar.backgroundColor = [UIColor whiteColor];
+  self.searchController.searchBar.backgroundColor = [UIColor clearColor];
   self.searchController.searchBar.accessibilityIdentifier =
       kHistorySearchControllerSearchBarIdentifier;
   // UIKit needs to know which controller will be presenting the
@@ -811,6 +808,7 @@
                         inIncognito:NO
                        inBackground:NO
                            appendTo:kLastTab];
+    [self.tabPresentationDelegate showActiveRegularTab];
   }];
 }
 
@@ -823,6 +821,7 @@
                         inIncognito:YES
                        inBackground:NO
                            appendTo:kLastTab];
+    [self.tabPresentationDelegate showActiveIncognitoTab];
   }];
 }
 
@@ -836,6 +835,7 @@
   params.transition_type = ui::PAGE_TRANSITION_AUTO_BOOKMARK;
   [self.localDispatcher dismissHistoryWithCompletion:^{
     [self.loader loadURLWithParams:params];
+    [self.tabPresentationDelegate showActiveRegularTab];
   }];
 }
 
diff --git a/ios/chrome/browser/ui/history/public/BUILD.gn b/ios/chrome/browser/ui/history/public/BUILD.gn
new file mode 100644
index 0000000..0e7e821
--- /dev/null
+++ b/ios/chrome/browser/ui/history/public/BUILD.gn
@@ -0,0 +1,10 @@
+# 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.
+
+source_set("public") {
+  configs += [ "//build/config/compiler:enable_arc" ]
+  sources = [
+    "history_tab_presentation_delegate.h",
+  ]
+}
diff --git a/ios/chrome/browser/ui/history/public/history_tab_presentation_delegate.h b/ios/chrome/browser/ui/history/public/history_tab_presentation_delegate.h
new file mode 100644
index 0000000..21e097e
--- /dev/null
+++ b/ios/chrome/browser/ui/history/public/history_tab_presentation_delegate.h
@@ -0,0 +1,18 @@
+// 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 IOS_CHROME_BROWSER_UI_HISTORY_PUBLIC_HISTORY_TAB_PRESENTATION_DELEGATE_H_
+#define IOS_CHROME_BROWSER_UI_HISTORY_PUBLIC_HISTORY_TAB_PRESENTATION_DELEGATE_H_
+
+// Delegate used to make the tab UI visible.
+@protocol HistoryTabPresentationDelegate
+// Tells the delegate to show the non-incognito tab UI. NO-OP if the correct tab
+// UI is already visible.
+- (void)showActiveRegularTab;
+// Tells the delegate to show the incognito tab UI. NO-OP if the correct tab UI
+// is already visible.
+- (void)showActiveIncognitoTab;
+@end
+
+#endif  // IOS_CHROME_BROWSER_UI_HISTORY_PUBLIC_HISTORY_TAB_PRESENTATION_DELEGATE_H_
diff --git a/ios/chrome/browser/ui/history_popup/BUILD.gn b/ios/chrome/browser/ui/history_popup/BUILD.gn
index c0a3380..52a01d3 100644
--- a/ios/chrome/browser/ui/history_popup/BUILD.gn
+++ b/ios/chrome/browser/ui/history_popup/BUILD.gn
@@ -16,6 +16,7 @@
     "//base",
     "//ios/chrome/browser/ui",
     "//ios/chrome/browser/ui/commands",
+    "//ios/chrome/browser/ui/favicon/resources:default_favicon",
     "//ios/chrome/browser/ui/popup_menu:constants",
     "//ios/chrome/browser/ui/popup_menu:popup_menu_ui",
     "//ios/chrome/browser/ui/util",
diff --git a/ios/chrome/browser/ui/location_bar/BUILD.gn b/ios/chrome/browser/ui/location_bar/BUILD.gn
index b26ada2..26b8aea8 100644
--- a/ios/chrome/browser/ui/location_bar/BUILD.gn
+++ b/ios/chrome/browser/ui/location_bar/BUILD.gn
@@ -28,7 +28,10 @@
   ]
   deps = [
     ":constants",
+    "resources:location_bar_dangerous",
+    "resources:location_bar_insecure",
     "resources:location_bar_offline",
+    "resources:location_bar_secure",
     "resources:location_bar_share",
     "resources:location_bar_voice",
     "//base",
diff --git a/ios/chrome/browser/ui/location_bar/location_bar_mediator.mm b/ios/chrome/browser/ui/location_bar/location_bar_mediator.mm
index 1a26150c..686994d 100644
--- a/ios/chrome/browser/ui/location_bar/location_bar_mediator.mm
+++ b/ios/chrome/browser/ui/location_bar/location_bar_mediator.mm
@@ -200,9 +200,8 @@
 }
 
 - (UIImage*)imageForSecurityLevel:(security_state::SecurityLevel)level {
-  int iconID = GetIconForSecurityState(level);
-  return [NativeImage(iconID)
-      imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
+  base::string16 iconName = GetUIRefreshIconNameForSecurityState(level);
+  return [UIImage imageNamed:base::SysUTF16ToNSString(iconName)];
 }
 
 // Returns a location icon for offline pages.
diff --git a/ios/chrome/browser/ui/location_bar/location_bar_steady_view.mm b/ios/chrome/browser/ui/location_bar/location_bar_steady_view.mm
index ff2fa4a..c70b39f 100644
--- a/ios/chrome/browser/ui/location_bar/location_bar_steady_view.mm
+++ b/ios/chrome/browser/ui/location_bar/location_bar_steady_view.mm
@@ -5,7 +5,9 @@
 #import "ios/chrome/browser/ui/location_bar/location_bar_steady_view.h"
 
 #import "ios/chrome/browser/ui/location_bar/extended_touch_target_button.h"
+#import "ios/chrome/browser/ui/uikit_ui_util.h"
 #import "ios/chrome/browser/ui/util/constraints_ui_util.h"
+#include "ios/chrome/grit/ios_strings.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
@@ -82,6 +84,11 @@
         setContentCompressionResistancePriority:UILayoutPriorityRequired
                                         forAxis:
                                             UILayoutConstraintAxisHorizontal];
+    SetA11yLabelAndUiAutomationName(
+        _locationIconImageView,
+        IDS_IOS_PAGE_INFO_SECURITY_BUTTON_ACCESSIBILITY_LABEL,
+        @"Page Security Info");
+    _locationIconImageView.isAccessibilityElement = YES;
 
     // Setup trailing button.
     _trailingButton =
diff --git a/ios/chrome/browser/ui/location_bar/resources/BUILD.gn b/ios/chrome/browser/ui/location_bar/resources/BUILD.gn
index f42dee2..d9b8f9e 100644
--- a/ios/chrome/browser/ui/location_bar/resources/BUILD.gn
+++ b/ios/chrome/browser/ui/location_bar/resources/BUILD.gn
@@ -75,3 +75,30 @@
     "location_bar_offline.imageset/location_bar_offline@3x.png",
   ]
 }
+
+imageset("location_bar_secure") {
+  sources = [
+    "location_bar_secure.imageset/Contents.json",
+    "location_bar_secure.imageset/location_bar_secure.png",
+    "location_bar_secure.imageset/location_bar_secure@2x.png",
+    "location_bar_secure.imageset/location_bar_secure@3x.png",
+  ]
+}
+
+imageset("location_bar_dangerous") {
+  sources = [
+    "location_bar_dangerous.imageset/Contents.json",
+    "location_bar_dangerous.imageset/location_bar_dangerous.png",
+    "location_bar_dangerous.imageset/location_bar_dangerous@2x.png",
+    "location_bar_dangerous.imageset/location_bar_dangerous@3x.png",
+  ]
+}
+
+imageset("location_bar_insecure") {
+  sources = [
+    "location_bar_insecure.imageset/Contents.json",
+    "location_bar_insecure.imageset/location_bar_insecure.png",
+    "location_bar_insecure.imageset/location_bar_insecure@2x.png",
+    "location_bar_insecure.imageset/location_bar_insecure@3x.png",
+  ]
+}
diff --git a/ios/chrome/browser/ui/location_bar/resources/location_bar_dangerous.imageset/Contents.json b/ios/chrome/browser/ui/location_bar/resources/location_bar_dangerous.imageset/Contents.json
new file mode 100644
index 0000000..7382561
--- /dev/null
+++ b/ios/chrome/browser/ui/location_bar/resources/location_bar_dangerous.imageset/Contents.json
@@ -0,0 +1,23 @@
+{
+    "images": [
+        {
+            "idiom": "universal",
+            "scale": "1x",
+            "filename": "location_bar_dangerous.png"
+        },
+        {
+            "idiom": "universal",
+            "scale": "2x",
+            "filename": "location_bar_dangerous@2x.png"
+        },
+        {
+            "idiom": "universal",
+            "scale": "3x",
+            "filename": "location_bar_dangerous@3x.png"
+        }
+    ],
+    "info": {
+        "version": 1,
+        "author": "xcode"
+    }
+}
diff --git a/ios/chrome/browser/ui/location_bar/resources/location_bar_dangerous.imageset/location_bar_dangerous.png b/ios/chrome/browser/ui/location_bar/resources/location_bar_dangerous.imageset/location_bar_dangerous.png
new file mode 100644
index 0000000..eb34d75d
--- /dev/null
+++ b/ios/chrome/browser/ui/location_bar/resources/location_bar_dangerous.imageset/location_bar_dangerous.png
Binary files differ
diff --git a/ios/chrome/browser/ui/location_bar/resources/location_bar_dangerous.imageset/location_bar_dangerous@2x.png b/ios/chrome/browser/ui/location_bar/resources/location_bar_dangerous.imageset/location_bar_dangerous@2x.png
new file mode 100644
index 0000000..c811e280
--- /dev/null
+++ b/ios/chrome/browser/ui/location_bar/resources/location_bar_dangerous.imageset/location_bar_dangerous@2x.png
Binary files differ
diff --git a/ios/chrome/browser/ui/location_bar/resources/location_bar_dangerous.imageset/location_bar_dangerous@3x.png b/ios/chrome/browser/ui/location_bar/resources/location_bar_dangerous.imageset/location_bar_dangerous@3x.png
new file mode 100644
index 0000000..32162e26
--- /dev/null
+++ b/ios/chrome/browser/ui/location_bar/resources/location_bar_dangerous.imageset/location_bar_dangerous@3x.png
Binary files differ
diff --git a/ios/chrome/browser/ui/location_bar/resources/location_bar_insecure.imageset/Contents.json b/ios/chrome/browser/ui/location_bar/resources/location_bar_insecure.imageset/Contents.json
new file mode 100644
index 0000000..1d34b2b9
--- /dev/null
+++ b/ios/chrome/browser/ui/location_bar/resources/location_bar_insecure.imageset/Contents.json
@@ -0,0 +1,23 @@
+{
+    "images": [
+        {
+            "idiom": "universal",
+            "scale": "1x",
+            "filename": "location_bar_insecure.png"
+        },
+        {
+            "idiom": "universal",
+            "scale": "2x",
+            "filename": "location_bar_insecure@2x.png"
+        },
+        {
+            "idiom": "universal",
+            "scale": "3x",
+            "filename": "location_bar_insecure@3x.png"
+        }
+    ],
+    "info": {
+        "version": 1,
+        "author": "xcode"
+    }
+}
diff --git a/ios/chrome/browser/ui/location_bar/resources/location_bar_insecure.imageset/location_bar_insecure.png b/ios/chrome/browser/ui/location_bar/resources/location_bar_insecure.imageset/location_bar_insecure.png
new file mode 100644
index 0000000..15eceac
--- /dev/null
+++ b/ios/chrome/browser/ui/location_bar/resources/location_bar_insecure.imageset/location_bar_insecure.png
Binary files differ
diff --git a/ios/chrome/browser/ui/location_bar/resources/location_bar_insecure.imageset/location_bar_insecure@2x.png b/ios/chrome/browser/ui/location_bar/resources/location_bar_insecure.imageset/location_bar_insecure@2x.png
new file mode 100644
index 0000000..afbff5b
--- /dev/null
+++ b/ios/chrome/browser/ui/location_bar/resources/location_bar_insecure.imageset/location_bar_insecure@2x.png
Binary files differ
diff --git a/ios/chrome/browser/ui/location_bar/resources/location_bar_insecure.imageset/location_bar_insecure@3x.png b/ios/chrome/browser/ui/location_bar/resources/location_bar_insecure.imageset/location_bar_insecure@3x.png
new file mode 100644
index 0000000..ae826e6
--- /dev/null
+++ b/ios/chrome/browser/ui/location_bar/resources/location_bar_insecure.imageset/location_bar_insecure@3x.png
Binary files differ
diff --git a/ios/chrome/browser/ui/location_bar/resources/location_bar_secure.imageset/Contents.json b/ios/chrome/browser/ui/location_bar/resources/location_bar_secure.imageset/Contents.json
new file mode 100644
index 0000000..743ff159
--- /dev/null
+++ b/ios/chrome/browser/ui/location_bar/resources/location_bar_secure.imageset/Contents.json
@@ -0,0 +1,23 @@
+{
+    "images": [
+        {
+            "idiom": "universal",
+            "scale": "1x",
+            "filename": "location_bar_secure.png"
+        },
+        {
+            "idiom": "universal",
+            "scale": "2x",
+            "filename": "location_bar_secure@2x.png"
+        },
+        {
+            "idiom": "universal",
+            "scale": "3x",
+            "filename": "location_bar_secure@3x.png"
+        }
+    ],
+    "info": {
+        "version": 1,
+        "author": "xcode"
+    }
+}
diff --git a/ios/chrome/browser/ui/location_bar/resources/location_bar_secure.imageset/location_bar_secure.png b/ios/chrome/browser/ui/location_bar/resources/location_bar_secure.imageset/location_bar_secure.png
new file mode 100644
index 0000000..c3850e6
--- /dev/null
+++ b/ios/chrome/browser/ui/location_bar/resources/location_bar_secure.imageset/location_bar_secure.png
Binary files differ
diff --git a/ios/chrome/browser/ui/location_bar/resources/location_bar_secure.imageset/location_bar_secure@2x.png b/ios/chrome/browser/ui/location_bar/resources/location_bar_secure.imageset/location_bar_secure@2x.png
new file mode 100644
index 0000000..cdce49c
--- /dev/null
+++ b/ios/chrome/browser/ui/location_bar/resources/location_bar_secure.imageset/location_bar_secure@2x.png
Binary files differ
diff --git a/ios/chrome/browser/ui/location_bar/resources/location_bar_secure.imageset/location_bar_secure@3x.png b/ios/chrome/browser/ui/location_bar/resources/location_bar_secure.imageset/location_bar_secure@3x.png
new file mode 100644
index 0000000..bbabcd87
--- /dev/null
+++ b/ios/chrome/browser/ui/location_bar/resources/location_bar_secure.imageset/location_bar_secure@3x.png
Binary files differ
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_util.cc b/ios/chrome/browser/ui/omnibox/omnibox_util.cc
index e002f91..59e9a960 100644
--- a/ios/chrome/browser/ui/omnibox/omnibox_util.cc
+++ b/ios/chrome/browser/ui/omnibox/omnibox_util.cc
@@ -5,6 +5,7 @@
 #include "ios/chrome/browser/ui/omnibox/omnibox_util.h"
 
 #include "base/logging.h"
+#include "base/strings/utf_string_conversions.h"
 #include "ios/chrome/grit/ios_theme_resources.h"
 
 int GetIconForAutocompleteMatchType(AutocompleteMatchType::Type type,
@@ -71,3 +72,23 @@
       return IDR_IOS_OMNIBOX_HTTP;
   }
 }
+
+base::string16 GetUIRefreshIconNameForSecurityState(
+    security_state::SecurityLevel security_level) {
+  switch (security_level) {
+    case security_state::NONE:
+    case security_state::HTTP_SHOW_WARNING:
+      return base::ASCIIToUTF16("location_bar_insecure");
+    case security_state::EV_SECURE:
+    case security_state::SECURE:
+      return base::ASCIIToUTF16("location_bar_secure");
+    case security_state::SECURE_WITH_POLICY_INSTALLED_CERT:
+      // TODO(crbug.com/848732): update this icon.
+      return base::ASCIIToUTF16("location_bar_secure");
+    case security_state::DANGEROUS:
+      return base::ASCIIToUTF16("location_bar_dangerous");
+    case security_state::SECURITY_LEVEL_COUNT:
+      NOTREACHED();
+      return base::ASCIIToUTF16("location_bar_insecure");
+  }
+}
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_util.h b/ios/chrome/browser/ui/omnibox/omnibox_util.h
index c0f1995..12cdab16 100644
--- a/ios/chrome/browser/ui/omnibox/omnibox_util.h
+++ b/ios/chrome/browser/ui/omnibox/omnibox_util.h
@@ -18,4 +18,9 @@
 // for this security level in the omnibox.
 int GetIconForSecurityState(security_state::SecurityLevel security_level);
 
+// Converts |security_level| to the icon name used as a resource identifier for
+// this security level in the location bar.
+base::string16 GetUIRefreshIconNameForSecurityState(
+    security_state::SecurityLevel security_level);
+
 #endif  // IOS_CHROME_BROWSER_UI_OMNIBOX_OMNIBOX_UTIL_H_
diff --git a/ios/chrome/browser/ui/popup_menu/BUILD.gn b/ios/chrome/browser/ui/popup_menu/BUILD.gn
index 45955ff..74230dda 100644
--- a/ios/chrome/browser/ui/popup_menu/BUILD.gn
+++ b/ios/chrome/browser/ui/popup_menu/BUILD.gn
@@ -17,6 +17,7 @@
     "//components/bookmarks/browser",
     "//components/feature_engagement/public",
     "//ios/chrome/app/strings",
+    "//ios/chrome/browser",
     "//ios/chrome/browser/bookmarks",
     "//ios/chrome/browser/browser_state",
     "//ios/chrome/browser/feature_engagement",
diff --git a/ios/chrome/browser/ui/popup_menu/cells/BUILD.gn b/ios/chrome/browser/ui/popup_menu/cells/BUILD.gn
index 121d381..94b84207 100644
--- a/ios/chrome/browser/ui/popup_menu/cells/BUILD.gn
+++ b/ios/chrome/browser/ui/popup_menu/cells/BUILD.gn
@@ -16,6 +16,7 @@
   deps = [
     "//base",
     "//ios/chrome/browser/ui",
+    "//ios/chrome/browser/ui/favicon/resources:default_favicon",
     "//ios/chrome/browser/ui/popup_menu:constants",
     "//ios/chrome/browser/ui/reading_list:reading_list_ui",
     "//ios/chrome/browser/ui/table_view:styler",
diff --git a/ios/chrome/browser/ui/popup_menu/popup_menu_mediator.mm b/ios/chrome/browser/ui/popup_menu/popup_menu_mediator.mm
index 63f2a71..3d51115 100644
--- a/ios/chrome/browser/ui/popup_menu/popup_menu_mediator.mm
+++ b/ios/chrome/browser/ui/popup_menu/popup_menu_mediator.mm
@@ -9,6 +9,7 @@
 #include "components/bookmarks/browser/bookmark_model.h"
 #include "components/feature_engagement/public/feature_constants.h"
 #include "components/feature_engagement/public/tracker.h"
+#include "ios/chrome/browser/chrome_url_constants.h"
 #import "ios/chrome/browser/find_in_page/find_tab_helper.h"
 #import "ios/chrome/browser/ui/activity_services/canonical_url_retriever.h"
 #include "ios/chrome/browser/ui/bookmarks/bookmark_model_bridge_observer.h"
@@ -451,7 +452,7 @@
   self.readLaterItem.enabled = [self isCurrentURLWebURL];
   [self updateBookmarkItem];
   self.findInPageItem.enabled = [self isFindInPageEnabled];
-  self.siteInformationItem.enabled = [self isCurrentURLWebURL];
+  self.siteInformationItem.enabled = [self currentWebPageSupportsSiteInfo];
   self.requestDesktopSiteItem.enabled =
       [self userAgentType] == web::UserAgentType::MOBILE;
   self.requestMobileSiteItem.enabled =
@@ -506,6 +507,23 @@
   }
 }
 
+// Whether the current web page has available site info.
+- (BOOL)currentWebPageSupportsSiteInfo {
+  if (!self.webState)
+    return NO;
+  web::NavigationItem* navItem =
+      self.webState->GetNavigationManager()->GetVisibleItem();
+  if (!navItem) {
+    return NO;
+  }
+  const GURL& URL = navItem->GetURL();
+  // Show site info for offline pages.
+  if (URL.SchemeIs(kChromeUIScheme) && URL.host() == kChromeUIOfflineHost) {
+    return YES;
+  }
+  return URL.is_valid() && !web::GetWebClient()->IsAppSpecificURL(URL);
+}
+
 // Whether the current page is a web page.
 - (BOOL)isCurrentURLWebURL {
   if (!self.webState)
diff --git a/ios/chrome/browser/ui/reading_list/BUILD.gn b/ios/chrome/browser/ui/reading_list/BUILD.gn
index 60a7b37..5d9dad2f 100644
--- a/ios/chrome/browser/ui/reading_list/BUILD.gn
+++ b/ios/chrome/browser/ui/reading_list/BUILD.gn
@@ -164,6 +164,8 @@
     "//ios/chrome/browser/reading_list",
     "//ios/chrome/browser/ui:ui",
     "//ios/chrome/browser/ui/commands",
+    "//ios/chrome/browser/ui/popup_menu:constants",
+    "//ios/chrome/browser/ui/tools_menu/public",
     "//ios/chrome/test/app:test_support",
     "//ios/chrome/test/earl_grey:test_support",
     "//ios/testing:ios_test_support",
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_egtest.mm b/ios/chrome/browser/ui/reading_list/reading_list_egtest.mm
index d7cfeec1..df23a46 100644
--- a/ios/chrome/browser/ui/reading_list/reading_list_egtest.mm
+++ b/ios/chrome/browser/ui/reading_list/reading_list_egtest.mm
@@ -15,10 +15,12 @@
 #include "components/reading_list/core/reading_list_model.h"
 #include "ios/chrome/browser/reading_list/reading_list_model_factory.h"
 #import "ios/chrome/browser/ui/commands/reading_list_add_command.h"
+#import "ios/chrome/browser/ui/popup_menu/popup_menu_constants.h"
 #import "ios/chrome/browser/ui/reading_list/reading_list_collection_view_controller.h"
 #import "ios/chrome/browser/ui/reading_list/reading_list_collection_view_item.h"
 #import "ios/chrome/browser/ui/reading_list/reading_list_empty_collection_background.h"
 #import "ios/chrome/browser/ui/reading_list/reading_list_toolbar_button.h"
+#include "ios/chrome/browser/ui/tools_menu/public/tools_menu_constants.h"
 #include "ios/chrome/browser/ui/ui_util.h"
 #include "ios/chrome/grit/ios_strings.h"
 #include "ios/chrome/grit/ios_theme_resources.h"
@@ -370,6 +372,21 @@
   return responses;
 }
 
+// Opens the page security info bubble.
+void OpenPageSecurityInfoBubble() {
+  if (IsUIRefreshPhase1Enabled()) {
+    // In UI Refresh, the security info is accessed through the tools menu.
+    [ChromeEarlGreyUI openToolsMenu];
+    // Tap on the Page Info button.
+    [ChromeEarlGreyUI
+        tapToolsMenuButton:grey_accessibilityID(kToolsMenuSiteInformation)];
+  } else {
+    [[EarlGrey
+        selectElementWithMatcher:chrome_test_util::PageSecurityInfoIndicator()]
+        performAction:grey_tap()];
+  }
+}
+
 // Tests that the correct version of kDistillableURL is displayed.
 void AssertIsShowingDistillablePage(bool online) {
   NSString* contentToKeep = base::SysUTF8ToNSString(kContentToKeep);
@@ -407,13 +424,22 @@
   }
 
   // Test the presence of the omnibox offline chip.
-  [[EarlGrey
-      selectElementWithMatcher:grey_allOf(
-                                   chrome_test_util::PageSecurityInfoButton(),
-                                   chrome_test_util::ButtonWithImage(
-                                       IDR_IOS_OMNIBOX_OFFLINE),
-                                   nil)]
-      assertWithMatcher:online ? grey_nil() : grey_notNil()];
+  if (IsRefreshLocationBarEnabled()) {
+    [[EarlGrey selectElementWithMatcher:
+                   grey_allOf(chrome_test_util::PageSecurityInfoIndicator(),
+                              chrome_test_util::ImageViewWithImageNamed(
+                                  @"location_bar_offline"),
+                              nil)]
+        assertWithMatcher:online ? grey_nil() : grey_notNil()];
+  } else {
+    [[EarlGrey
+        selectElementWithMatcher:grey_allOf(
+                                     chrome_test_util::PageSecurityInfoButton(),
+                                     chrome_test_util::ButtonWithImage(
+                                         IDR_IOS_OMNIBOX_OFFLINE),
+                                     nil)]
+        assertWithMatcher:online ? grey_nil() : grey_notNil()];
+  }
 }
 
 }  // namespace
@@ -493,9 +519,7 @@
   AssertIsShowingDistillablePage(false);
 
   // Tap the Omnibox' Info Bubble to open the Page Info.
-  [[EarlGrey
-      selectElementWithMatcher:chrome_test_util::PageSecurityInfoButton()]
-      performAction:grey_tap()];
+  OpenPageSecurityInfoBubble();
   // Verify that the Page Info is about offline pages.
   id<GREYMatcher> pageInfoTitleMatcher =
       chrome_test_util::StaticTextWithAccessibilityLabelId(
diff --git a/ios/chrome/browser/ui/recent_tabs/recent_tabs_table_view_controller.mm b/ios/chrome/browser/ui/recent_tabs/recent_tabs_table_view_controller.mm
index 4a56c751..117f942 100644
--- a/ios/chrome/browser/ui/recent_tabs/recent_tabs_table_view_controller.mm
+++ b/ios/chrome/browser/ui/recent_tabs/recent_tabs_table_view_controller.mm
@@ -90,6 +90,10 @@
 // The UI displays relative time for up to this number of hours and then
 // switches to absolute values.
 const int kRelativeTimeMaxHours = 4;
+// Height for single line headers.
+const CGFloat kSingleLineSectionHeaderHeight = 44;
+// Height for double line headers.
+const CGFloat kDoubleLineSectionHeaderHeight = 56;
 
 }  // namespace
 
@@ -164,7 +168,6 @@
   [self.tableView setDelegate:self];
   self.tableView.estimatedRowHeight = kEstimatedRowHeight;
   self.tableView.rowHeight = UITableViewAutomaticDimension;
-  self.tableView.estimatedSectionHeaderHeight = kEstimatedRowHeight;
   self.tableView.sectionFooterHeight = 0.0;
   // Gesture recognizer for long press context menu on Session Headers.
   UILongPressGestureRecognizer* longPress =
@@ -180,10 +183,6 @@
   tapGesture.delegate = self;
   [self.tableView addGestureRecognizer:tapGesture];
 
-  // If the NavigationBar is not translucent, set
-  // |self.extendedLayoutIncludesOpaqueBars| to YES in order to avoid a top
-  // margin inset on the |_tableViewController| subview.
-  self.extendedLayoutIncludesOpaqueBars = YES;
   self.title = l10n_util::GetNSString(IDS_IOS_CONTENT_SUGGESTIONS_RECENT_TABS);
 }
 
@@ -620,6 +619,23 @@
   }
 }
 
+// TODO(crbug.com/850814): Use estimatedSectionHeaderHeight once we stop
+// supporting iOS10.
+- (CGFloat)tableView:(UITableView*)tableView
+    heightForHeaderInSection:(NSInteger)section {
+  DCHECK_EQ(tableView, self.tableView);
+  NSInteger sectionIdentifier =
+      [self.tableViewModel sectionIdentifierForSection:section];
+  switch (sectionIdentifier) {
+    case SectionIdentifierRecentlyClosedTabs:
+    case SectionIdentifierOtherDevices:
+      return kSingleLineSectionHeaderHeight;
+    default:
+      // All remote session sections.
+      return kDoubleLineSectionHeaderHeight;
+  }
+}
+
 - (CGFloat)tableView:(UITableView*)tableView
     heightForFooterInSection:(NSInteger)section {
   // If section is collapsed there's no need to add a separation space.
diff --git a/ios/chrome/browser/ui/resources/BUILD.gn b/ios/chrome/browser/ui/resources/BUILD.gn
index 408fe06..f8fe6776 100644
--- a/ios/chrome/browser/ui/resources/BUILD.gn
+++ b/ios/chrome/browser/ui/resources/BUILD.gn
@@ -22,24 +22,6 @@
   ]
 }
 
-imageset("default_favicon") {
-  sources = [
-    "default_favicon.imageset/Contents.json",
-    "default_favicon.imageset/default_favicon.png",
-    "default_favicon.imageset/default_favicon@2x.png",
-    "default_favicon.imageset/default_favicon@3x.png",
-  ]
-}
-
-imageset("default_favicon_incognito") {
-  sources = [
-    "default_favicon_incognito.imageset/Contents.json",
-    "default_favicon_incognito.imageset/default_favicon_incognito.png",
-    "default_favicon_incognito.imageset/default_favicon_incognito@2x.png",
-    "default_favicon_incognito.imageset/default_favicon_incognito@3x.png",
-  ]
-}
-
 imageset("custom_row_voice") {
   sources = [
     "custom_row_voice.imageset/Contents.json",
diff --git a/ios/chrome/browser/ui/stack_view/BUILD.gn b/ios/chrome/browser/ui/stack_view/BUILD.gn
index d6c3179..ee48646 100644
--- a/ios/chrome/browser/ui/stack_view/BUILD.gn
+++ b/ios/chrome/browser/ui/stack_view/BUILD.gn
@@ -54,6 +54,7 @@
     "//ios/chrome/browser/tabs",
     "//ios/chrome/browser/ui",
     "//ios/chrome/browser/ui/commands",
+    "//ios/chrome/browser/ui/favicon/resources:default_favicon",
     "//ios/chrome/browser/ui/image_util",
     "//ios/chrome/browser/ui/keyboard",
     "//ios/chrome/browser/ui/main:feature_flags",
diff --git a/ios/chrome/browser/ui/tab_grid/BUILD.gn b/ios/chrome/browser/ui/tab_grid/BUILD.gn
index 81853c6..f3392aa 100644
--- a/ios/chrome/browser/ui/tab_grid/BUILD.gn
+++ b/ios/chrome/browser/ui/tab_grid/BUILD.gn
@@ -12,6 +12,8 @@
     "tab_grid_coordinator.mm",
     "tab_grid_mediator.h",
     "tab_grid_mediator.mm",
+    "tab_grid_url_loader.h",
+    "tab_grid_url_loader.mm",
   ]
 
   configs += [ "//build/config/compiler:enable_arc" ]
@@ -29,6 +31,8 @@
     "//ios/chrome/browser/ui",
     "//ios/chrome/browser/ui/commands",
     "//ios/chrome/browser/ui/coordinators:chrome_coordinators",
+    "//ios/chrome/browser/ui/history",
+    "//ios/chrome/browser/ui/history/public",
     "//ios/chrome/browser/ui/main",
     "//ios/chrome/browser/ui/recent_tabs",
     "//ios/chrome/browser/ui/recent_tabs:recent_tabs_ui",
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm
index c1c0553f..f3c4924 100644
--- a/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm
+++ b/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm
@@ -9,6 +9,8 @@
 #import "ios/chrome/browser/ui/commands/browser_commands.h"
 #import "ios/chrome/browser/ui/commands/command_dispatcher.h"
 #import "ios/chrome/browser/ui/commands/open_new_tab_command.h"
+#import "ios/chrome/browser/ui/history/history_coordinator.h"
+#import "ios/chrome/browser/ui/history/public/history_tab_presentation_delegate.h"
 #import "ios/chrome/browser/ui/main/bvc_container_view_controller.h"
 #import "ios/chrome/browser/ui/ntp/recent_tabs/recent_tabs_handset_view_controller.h"
 #import "ios/chrome/browser/ui/recent_tabs/recent_tabs_mediator.h"
@@ -17,6 +19,7 @@
 #import "ios/chrome/browser/ui/tab_grid/tab_grid_mediator.h"
 #import "ios/chrome/browser/ui/tab_grid/tab_grid_paging.h"
 #import "ios/chrome/browser/ui/tab_grid/tab_grid_transition_handler.h"
+#import "ios/chrome/browser/ui/tab_grid/tab_grid_url_loader.h"
 #import "ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
@@ -24,6 +27,7 @@
 #endif
 
 @interface TabGridCoordinator ()<TabPresentationDelegate,
+                                 HistoryTabPresentationDelegate,
                                  RecentTabsHandsetViewControllerCommand>
 // Superclass property specialized for the class that this coordinator uses.
 @property(nonatomic, weak) TabGridViewController* mainViewController;
@@ -43,6 +47,11 @@
 @property(nonatomic, strong) TabGridMediator* incognitoTabsMediator;
 // Mediator for remote Tabs.
 @property(nonatomic, strong) RecentTabsMediator* remoteTabsMediator;
+// Coordinator for history, which can be started from recent tabs.
+@property(nonatomic, strong) HistoryCoordinator* historyCoordinator;
+// Specialized URL loader for tab grid, since tab grid has a different use case
+// than BVC.
+@property(nonatomic, strong) TabGridURLLoader* URLLoader;
 @end
 
 @implementation TabGridCoordinator
@@ -60,6 +69,8 @@
 @synthesize regularTabsMediator = _regularTabsMediator;
 @synthesize incognitoTabsMediator = _incognitoTabsMediator;
 @synthesize remoteTabsMediator = _remoteTabsMediator;
+@synthesize historyCoordinator = _historyCoordinator;
+@synthesize URLLoader = _URLLoader;
 
 - (instancetype)initWithWindow:(nullable UIWindow*)window
     applicationCommandEndpoint:
@@ -169,7 +180,12 @@
       self.remoteTabsMediator;
   mainViewController.remoteTabsViewController.dispatcher =
       static_cast<id<ApplicationCommands>>(self.dispatcher);
-  mainViewController.remoteTabsViewController.loader = self.regularTabsMediator;
+  self.URLLoader = [[TabGridURLLoader alloc]
+      initWithRegularWebStateList:self.regularTabModel.webStateList
+            incognitoWebStateList:self.incognitoTabModel.webStateList
+              regularBrowserState:self.regularTabModel.browserState
+            incognitoBrowserState:self.incognitoTabModel.browserState];
+  mainViewController.remoteTabsViewController.loader = self.URLLoader;
   mainViewController.remoteTabsViewController.handsetCommandHandler = self;
 
   // TODO(crbug.com/850387) : Currently, consumer calls from the mediator
@@ -315,21 +331,38 @@
                              transition:ui::PAGE_TRANSITION_TYPED];
 }
 
-- (void)closeAllTabs {
-}
-
-- (void)closeAllIncognitoTabs {
-}
-
 #pragma mark - RecentTabsHandsetViewControllerCommand
 
 // Normally, recent tabs is dismissed to reveal the tab view beneath it. In tab
 // grid, the tab view is presented above the recent tabs panel.
 - (void)dismissRecentTabsWithCompletion:(void (^)())completion {
-  // Trigger the transition through the TabSwitcher delegate. This will in turn
-  // call back into this coordinator via the ViewControllerSwapping protocol.
+  if (completion) {
+    // TODO(crbug.com/845192) : Don't use the completion block as an implicit
+    // signal to show history.
+    // A history coordinator from main_controller won't work properly from the
+    // tab grid. Using a local coordinator works better when hooked up with a
+    // specialized URL loader and tab presentation delegate.
+    self.historyCoordinator = [[HistoryCoordinator alloc]
+        initWithBaseViewController:self.mainViewController
+                      browserState:self.regularTabModel.browserState];
+    self.historyCoordinator.loader = self.URLLoader;
+    self.historyCoordinator.tabPresentationDelegate = self;
+    [self.historyCoordinator start];
+    return;
+  }
+  [self showActiveRegularTab];
+}
+
+#pragma mark - HistoryTabPresentationDelegate
+
+- (void)showActiveRegularTab {
   [self.tabSwitcher.delegate tabSwitcher:self.tabSwitcher
              shouldFinishWithActiveModel:self.regularTabModel];
 }
 
+- (void)showActiveIncognitoTab {
+  [self.tabSwitcher.delegate tabSwitcher:self.tabSwitcher
+             shouldFinishWithActiveModel:self.incognitoTabModel];
+}
+
 @end
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_mediator.h b/ios/chrome/browser/ui/tab_grid/tab_grid_mediator.h
index 92773b74..6e2618d 100644
--- a/ios/chrome/browser/ui/tab_grid/tab_grid_mediator.h
+++ b/ios/chrome/browser/ui/tab_grid/tab_grid_mediator.h
@@ -9,14 +9,12 @@
 
 #import "ios/chrome/browser/ui/tab_grid/grid/grid_commands.h"
 #import "ios/chrome/browser/ui/tab_grid/grid/grid_image_data_source.h"
-#import "ios/chrome/browser/ui/url_loader.h"
 
 @protocol GridConsumer;
 @class TabModel;
 
 // Mediates between model layer and tab grid UI layer.
-@interface TabGridMediator
-    : NSObject<GridCommands, GridImageDataSource, UrlLoader>
+@interface TabGridMediator : NSObject<GridCommands, GridImageDataSource>
 
 // The source tab model.
 @property(nonatomic, weak) TabModel* tabModel;
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_mediator.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_mediator.mm
index fb812b07..f5a951b 100644
--- a/ios/chrome/browser/ui/tab_grid/tab_grid_mediator.mm
+++ b/ios/chrome/browser/ui/tab_grid/tab_grid_mediator.mm
@@ -9,10 +9,8 @@
 #include "base/scoped_observer.h"
 #include "base/strings/sys_string_conversions.h"
 #include "components/favicon/ios/web_favicon_driver.h"
-#include "components/sessions/core/session_types.h"
 #include "ios/chrome/browser/browser_state/chrome_browser_state.h"
 #include "ios/chrome/browser/chrome_url_constants.h"
-#include "ios/chrome/browser/sessions/session_util.h"
 #import "ios/chrome/browser/snapshots/snapshot_cache.h"
 #import "ios/chrome/browser/snapshots/snapshot_cache_factory.h"
 #import "ios/chrome/browser/snapshots/snapshot_tab_helper.h"
@@ -85,15 +83,6 @@
   return nullptr;
 }
 
-// Appends and activates |web_state| to the end of |web_state_list|.
-void AppendAndActivateWebState(WebStateList* web_state_list,
-                               std::unique_ptr<web::WebState> web_state) {
-  web_state_list->InsertWebState(
-      web_state_list->count(), std::move(web_state),
-      (WebStateList::INSERT_FORCE_INDEX | WebStateList::INSERT_ACTIVATE),
-      WebStateOpener());
-}
-
 }  // namespace
 
 @interface TabGridMediator ()<CRWWebStateObserver, WebStateListObserving>
@@ -308,54 +297,6 @@
   [SnapshotCacheFactory::GetForBrowserState(browserState) removeMarkedImages];
 }
 
-#pragma mark - UrlLoader
-
-// Loading a |sessionTab| normally means navigating on the currently visible tab
-// view. This is not the case while in the tab grid. A new WebState is appended
-// and activated instead of replacing the current active WebState.
-- (void)loadSessionTab:(const sessions::SessionTab*)sessionTab {
-  DCHECK(self.tabModel.browserState);
-  std::unique_ptr<web::WebState> webState =
-      session_util::CreateWebStateWithNavigationEntries(
-          self.tabModel.browserState, sessionTab->current_navigation_index,
-          sessionTab->navigations);
-  AppendAndActivateWebState(self.webStateList, std::move(webState));
-}
-
-// In tab grid, |inBackground| is ignored, which means that the new WebState is
-// activated. |appendTo| is also ignored, so the new WebState is always appended
-// at the end of the list. The page transition type is explicit rather than
-// linked.
-- (void)webPageOrderedOpen:(const GURL&)URL
-                  referrer:(const web::Referrer&)referrer
-              inBackground:(BOOL)inBackground
-                  appendTo:(OpenPosition)appendTo {
-  DCHECK(self.tabModel.browserState);
-  web::WebState::CreateParams params(self.tabModel.browserState);
-  std::unique_ptr<web::WebState> webState = web::WebState::Create(params);
-  web::NavigationManager::WebLoadParams loadParams(URL);
-  loadParams.referrer = referrer;
-  loadParams.transition_type = ui::PAGE_TRANSITION_TYPED;
-  webState->GetNavigationManager()->LoadURLWithParams(loadParams);
-  AppendAndActivateWebState(self.webStateList, std::move(webState));
-}
-
-- (void)webPageOrderedOpen:(const GURL&)URL
-                  referrer:(const web::Referrer&)referrer
-               inIncognito:(BOOL)inIncognito
-              inBackground:(BOOL)inBackground
-                  appendTo:(OpenPosition)appendTo {
-  NOTREACHED() << "This is intentionally NO-OP in TabGridMediator.";
-}
-
-- (void)loadURLWithParams:(const web::NavigationManager::WebLoadParams&)params {
-  NOTREACHED() << "This is intentionally NO-OP in TabGridMediator.";
-}
-
-- (void)loadJavaScriptFromLocationBar:(NSString*)script {
-  NOTREACHED() << "This is intentionally NO-OP in TabGridMediator.";
-}
-
 #pragma mark - GridImageDataSource
 
 - (void)snapshotForIdentifier:(NSString*)identifier
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_url_loader.h b/ios/chrome/browser/ui/tab_grid/tab_grid_url_loader.h
new file mode 100644
index 0000000..8c96cf17
--- /dev/null
+++ b/ios/chrome/browser/ui/tab_grid/tab_grid_url_loader.h
@@ -0,0 +1,29 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_UI_TAB_GRID_TAB_GRID_URL_LOADER_H_
+#define IOS_CHROME_BROWSER_UI_TAB_GRID_TAB_GRID_URL_LOADER_H_
+
+#import <Foundation/Foundation.h>
+
+#import "ios/chrome/browser/ui/url_loader.h"
+
+namespace ios {
+class ChromeBrowserState;
+}
+
+class WebStateList;
+
+// Specialized URLLoader for the tab grid, which behaves differently than BVC.
+@interface TabGridURLLoader : NSObject<UrlLoader>
+- (instancetype)
+initWithRegularWebStateList:(WebStateList*)regularWebStateList
+      incognitoWebStateList:(WebStateList*)incognitoWebStateList
+        regularBrowserState:(ios::ChromeBrowserState*)regularBrowserState
+      incognitoBrowserState:(ios::ChromeBrowserState*)incognitoBrowserState
+    NS_DESIGNATED_INITIALIZER;
+- (instancetype)init NS_UNAVAILABLE;
+@end
+
+#endif  // IOS_CHROME_BROWSER_UI_TAB_GRID_TAB_GRID_URL_LOADER_H_
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_url_loader.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_url_loader.mm
new file mode 100644
index 0000000..caeb91a
--- /dev/null
+++ b/ios/chrome/browser/ui/tab_grid/tab_grid_url_loader.mm
@@ -0,0 +1,125 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/chrome/browser/ui/tab_grid/tab_grid_url_loader.h"
+
+#include "components/sessions/core/session_types.h"
+#include "ios/chrome/browser/browser_state/chrome_browser_state.h"
+#include "ios/chrome/browser/sessions/session_util.h"
+#import "ios/chrome/browser/web_state_list/web_state_list.h"
+#include "ios/chrome/browser/web_state_list/web_state_opener.h"
+#include "ios/web/public/web_state/web_state.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+namespace {
+// Appends and activates |web_state| to the end of |web_state_list|.
+void AppendAndActivateWebState(WebStateList* web_state_list,
+                               std::unique_ptr<web::WebState> web_state) {
+  web_state_list->InsertWebState(
+      web_state_list->count(), std::move(web_state),
+      (WebStateList::INSERT_FORCE_INDEX | WebStateList::INSERT_ACTIVATE),
+      WebStateOpener());
+}
+}  // namespace
+
+@interface TabGridURLLoader ()
+@property(nonatomic, assign) WebStateList* regularWebStateList;
+@property(nonatomic, assign) WebStateList* incognitoWebStateList;
+@property(nonatomic, assign) ios::ChromeBrowserState* regularBrowserState;
+@property(nonatomic, assign) ios::ChromeBrowserState* incognitoBrowserState;
+@end
+
+@implementation TabGridURLLoader
+@synthesize regularWebStateList = _regularWebStateList;
+@synthesize incognitoWebStateList = _incognitoWebStateList;
+@synthesize regularBrowserState = _regularBrowserState;
+@synthesize incognitoBrowserState = _incognitoBrowserState;
+
+- (instancetype)
+initWithRegularWebStateList:(WebStateList*)regularWebStateList
+      incognitoWebStateList:(WebStateList*)incognitoWebStateList
+        regularBrowserState:(ios::ChromeBrowserState*)regularBrowserState
+      incognitoBrowserState:(ios::ChromeBrowserState*)incognitoBrowserState {
+  if (self = [super init]) {
+    _regularWebStateList = regularWebStateList;
+    _regularBrowserState = regularBrowserState;
+    _incognitoWebStateList = incognitoWebStateList;
+    _incognitoBrowserState = incognitoBrowserState;
+  }
+  return self;
+}
+
+#pragma mark - UrlLoader
+
+// Loading a |sessionTab| normally means navigating on the currently visible tab
+// view. This is not the case while in the tab grid. A new WebState is appended
+// and activated instead of replacing the current active WebState.
+- (void)loadSessionTab:(const sessions::SessionTab*)sessionTab {
+  DCHECK(self.regularBrowserState);
+  std::unique_ptr<web::WebState> webState =
+      session_util::CreateWebStateWithNavigationEntries(
+          self.regularBrowserState, sessionTab->current_navigation_index,
+          sessionTab->navigations);
+  AppendAndActivateWebState(self.regularWebStateList, std::move(webState));
+}
+
+// Opens |URL| in a new regular tab.
+- (void)webPageOrderedOpen:(const GURL&)URL
+                  referrer:(const web::Referrer&)referrer
+              inBackground:(BOOL)inBackground
+                  appendTo:(OpenPosition)appendTo {
+  [self webPageOrderedOpen:URL
+                  referrer:referrer
+               inIncognito:NO
+              inBackground:inBackground
+                  appendTo:appendTo];
+}
+
+// In tab grid, |inBackground| is ignored, which means that the new WebState is
+// activated. |appendTo| is also ignored, so the new WebState is always appended
+// at the end of the list. The page transition type is explicit rather than
+// linked.
+- (void)webPageOrderedOpen:(const GURL&)URL
+                  referrer:(const web::Referrer&)referrer
+               inIncognito:(BOOL)inIncognito
+              inBackground:(BOOL)inBackground
+                  appendTo:(OpenPosition)appendTo {
+  WebStateList* webStateList;
+  ios::ChromeBrowserState* browserState;
+  if (inIncognito) {
+    webStateList = self.incognitoWebStateList;
+    browserState = self.incognitoBrowserState;
+  } else {
+    webStateList = self.regularWebStateList;
+    browserState = self.regularBrowserState;
+  }
+  DCHECK(webStateList);
+  DCHECK(browserState);
+  web::WebState::CreateParams params(browserState);
+  std::unique_ptr<web::WebState> webState = web::WebState::Create(params);
+  web::NavigationManager::WebLoadParams loadParams(URL);
+  loadParams.referrer = referrer;
+  loadParams.transition_type = ui::PAGE_TRANSITION_TYPED;
+  webState->GetNavigationManager()->LoadURLWithParams(loadParams);
+  AppendAndActivateWebState(webStateList, std::move(webState));
+}
+
+// Opens |loadParams| in a new regular tab.
+- (void)loadURLWithParams:
+    (const web::NavigationManager::WebLoadParams&)loadParams {
+  DCHECK(self.regularBrowserState);
+  web::WebState::CreateParams params(self.regularBrowserState);
+  std::unique_ptr<web::WebState> webState = web::WebState::Create(params);
+  webState->GetNavigationManager()->LoadURLWithParams(loadParams);
+  AppendAndActivateWebState(self.regularWebStateList, std::move(webState));
+}
+
+- (void)loadJavaScriptFromLocationBar:(NSString*)script {
+  NOTREACHED() << "This is intentionally NO-OP in TabGridMediator.";
+}
+
+@end
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm
index 89f3dba..b1d53d34 100644
--- a/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm
+++ b/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm
@@ -109,8 +109,7 @@
   if (self = [super init]) {
     _regularTabsViewController = [[GridViewController alloc] init];
     _incognitoTabsViewController = [[GridViewController alloc] init];
-    _remoteTabsViewController = [[RecentTabsTableViewController alloc]
-        initWithoutRecentlyClosedSection];
+    _remoteTabsViewController = [[RecentTabsTableViewController alloc] init];
   }
   return self;
 }
diff --git a/ios/chrome/browser/ui/table_view/BUILD.gn b/ios/chrome/browser/ui/table_view/BUILD.gn
index c0f5692..8dd54bf 100644
--- a/ios/chrome/browser/ui/table_view/BUILD.gn
+++ b/ios/chrome/browser/ui/table_view/BUILD.gn
@@ -36,6 +36,9 @@
     "chrome_table_view_styler.h",
     "chrome_table_view_styler.mm",
   ]
+  public_deps = [
+    "//ios/chrome/browser/ui:ui_util",
+  ]
 }
 
 source_set("presentation") {
diff --git a/ios/chrome/browser/ui/table_view/cells/table_view_header_footer_item.mm b/ios/chrome/browser/ui/table_view/cells/table_view_header_footer_item.mm
index ccd22b33..337b3b4 100644
--- a/ios/chrome/browser/ui/table_view/cells/table_view_header_footer_item.mm
+++ b/ios/chrome/browser/ui/table_view/cells/table_view_header_footer_item.mm
@@ -5,6 +5,7 @@
 #import "ios/chrome/browser/ui/table_view/cells/table_view_header_footer_item.h"
 
 #import "base/logging.h"
+#import "ios/chrome/browser/ui/table_view/chrome_table_view_styler.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
@@ -24,6 +25,9 @@
   DCHECK([headerFooter class] == self.cellClass);
   headerFooter.accessibilityTraits = self.accessibilityTraits;
   headerFooter.accessibilityIdentifier = self.accessibilityIdentifier;
+  UIVisualEffectView* visualEffect = [[UIVisualEffectView alloc]
+      initWithEffect:styler.tableViewSectionHeaderBlurEffect];
+  headerFooter.backgroundView = visualEffect;
 }
 
 @end
diff --git a/ios/chrome/browser/ui/table_view/cells/table_view_text_header_footer_item.mm b/ios/chrome/browser/ui/table_view/cells/table_view_text_header_footer_item.mm
index 408442a..0249def9 100644
--- a/ios/chrome/browser/ui/table_view/cells/table_view_text_header_footer_item.mm
+++ b/ios/chrome/browser/ui/table_view/cells/table_view_text_header_footer_item.mm
@@ -6,7 +6,6 @@
 
 #include "base/mac/foundation_util.h"
 #import "ios/chrome/browser/ui/table_view/cells/table_view_cells_constants.h"
-#import "ios/chrome/browser/ui/table_view/chrome_table_view_styler.h"
 #import "ios/chrome/browser/ui/uikit_ui_util.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
@@ -31,10 +30,6 @@
 - (void)configureHeaderFooterView:(UITableViewHeaderFooterView*)headerFooter
                        withStyler:(ChromeTableViewStyler*)styler {
   [super configureHeaderFooterView:headerFooter withStyler:styler];
-
-  // Set the contentView backgroundColor, not the header's.
-  headerFooter.contentView.backgroundColor = styler.tableViewBackgroundColor;
-
   TableViewTextHeaderFooterView* header =
       base::mac::ObjCCastStrict<TableViewTextHeaderFooterView>(headerFooter);
   header.textLabel.text = self.text;
diff --git a/ios/chrome/browser/ui/table_view/cells/table_view_text_header_footer_item_unittest.mm b/ios/chrome/browser/ui/table_view/cells/table_view_text_header_footer_item_unittest.mm
index 00feac3..6d03d115 100644
--- a/ios/chrome/browser/ui/table_view/cells/table_view_text_header_footer_item_unittest.mm
+++ b/ios/chrome/browser/ui/table_view/cells/table_view_text_header_footer_item_unittest.mm
@@ -39,19 +39,3 @@
   [item configureHeaderFooterView:textHeaderFooter withStyler:styler];
   EXPECT_NSEQ(text, textHeaderFooter.textLabel.text);
 }
-
-TEST_F(TableViewTextHeaderFooterItemTest, Styler) {
-  TableViewTextHeaderFooterItem* item =
-      [[TableViewTextHeaderFooterItem alloc] initWithType:0];
-  id headerFooter = [[[item cellClass] alloc] init];
-  ASSERT_TRUE(
-      [headerFooter isMemberOfClass:[TableViewTextHeaderFooterView class]]);
-  TableViewTextHeaderFooterView* textHeaderFooter =
-      base::mac::ObjCCastStrict<TableViewTextHeaderFooterView>(headerFooter);
-
-  ChromeTableViewStyler* styler = [[ChromeTableViewStyler alloc] init];
-  UIColor* testColor = [UIColor redColor];
-  styler.tableViewBackgroundColor = testColor;
-  [item configureHeaderFooterView:textHeaderFooter withStyler:styler];
-  EXPECT_NSEQ(testColor, textHeaderFooter.contentView.backgroundColor);
-}
diff --git a/ios/chrome/browser/ui/table_view/chrome_table_view_styler.h b/ios/chrome/browser/ui/table_view/chrome_table_view_styler.h
index 39983ee..f744d7f 100644
--- a/ios/chrome/browser/ui/table_view/chrome_table_view_styler.h
+++ b/ios/chrome/browser/ui/table_view/chrome_table_view_styler.h
@@ -9,6 +9,10 @@
 
 @interface ChromeTableViewStyler : NSObject
 
+// The BlurEffect used on the UITableView section headers.
+@property(nonatomic, readwrite, strong)
+    UIBlurEffect* tableViewSectionHeaderBlurEffect;
+
 // The background color for the table view and its cells. If this is set to an
 // opaque color, cells can choose to make themselves opaque and draw their own
 // background as a performance optimization.
diff --git a/ios/chrome/browser/ui/table_view/chrome_table_view_styler.mm b/ios/chrome/browser/ui/table_view/chrome_table_view_styler.mm
index 3cd454a..19105c3 100644
--- a/ios/chrome/browser/ui/table_view/chrome_table_view_styler.mm
+++ b/ios/chrome/browser/ui/table_view/chrome_table_view_styler.mm
@@ -4,19 +4,30 @@
 
 #import "ios/chrome/browser/ui/table_view/chrome_table_view_styler.h"
 
+#import "ios/chrome/browser/ui/uikit_ui_util.h"
+
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
 #endif
 
-@implementation ChromeTableViewStyler
+namespace {
+// The width and height of the favicon ImageView.
+const int kTableViewBackgroundRGBColor = 0xF9F9F9;
+}
 
+@implementation ChromeTableViewStyler
+@synthesize tableViewSectionHeaderBlurEffect =
+    _tableViewSectionHeaderBlurEffect;
 @synthesize tableViewBackgroundColor = _tableViewBackgroundColor;
 @synthesize cellTitleColor = _cellTitleColor;
 @synthesize headerFooterTitleColor = _headerFooterTitleColor;
 
 - (instancetype)init {
   if ((self = [super init])) {
-    _tableViewBackgroundColor = [UIColor whiteColor];
+    _tableViewBackgroundColor = UIColorFromRGB(kTableViewBackgroundRGBColor, 1);
+
+    _tableViewSectionHeaderBlurEffect =
+        [UIBlurEffect effectWithStyle:UIBlurEffectStyleExtraLight];
   }
   return self;
 }
diff --git a/ios/chrome/browser/ui/table_view/table_view_navigation_controller.mm b/ios/chrome/browser/ui/table_view/table_view_navigation_controller.mm
index 9b4e2e92..ec813d32 100644
--- a/ios/chrome/browser/ui/table_view/table_view_navigation_controller.mm
+++ b/ios/chrome/browser/ui/table_view/table_view_navigation_controller.mm
@@ -28,16 +28,22 @@
 #pragma mark - View Lifecycle
 
 - (void)viewDidLoad {
-  [self.navigationBar setBackgroundImage:[UIImage new]
-                           forBarMetrics:UIBarMetricsDefault];
-  if (self.tableViewController.styler.tableViewBackgroundColor !=
-      [UIColor clearColor]) {
-    self.navigationBar.translucent = NO;
-  }
+  [super viewDidLoad];
 
-  if (@available(iOS 11, *)) {
+  UIVisualEffectView* visualEffectView = [[UIVisualEffectView alloc]
+      initWithEffect:[UIBlurEffect
+                         effectWithStyle:UIBlurEffectStyleExtraLight]];
+
+  self.navigationBar.translucent = YES;
+  self.navigationController.navigationBar.backgroundColor =
+      [UIColor clearColor];
+  [self.navigationController.navigationBar addSubview:visualEffectView];
+  if (@available(iOS 11, *))
     self.navigationBar.prefersLargeTitles = YES;
-  }
+
+  self.toolbar.clipsToBounds = YES;
+  self.toolbar.translucent = YES;
+  [self.toolbar addSubview:visualEffectView];
 }
 
 @end
diff --git a/ios/chrome/browser/ui/tabs/BUILD.gn b/ios/chrome/browser/ui/tabs/BUILD.gn
index 82a321f..bd852391 100644
--- a/ios/chrome/browser/ui/tabs/BUILD.gn
+++ b/ios/chrome/browser/ui/tabs/BUILD.gn
@@ -59,6 +59,8 @@
     "//ios/chrome/browser/ui/bubble",
     "//ios/chrome/browser/ui/colors",
     "//ios/chrome/browser/ui/commands",
+    "//ios/chrome/browser/ui/favicon/resources:default_favicon",
+    "//ios/chrome/browser/ui/favicon/resources:default_favicon_incognito",
     "//ios/chrome/browser/ui/fullscreen",
     "//ios/chrome/browser/ui/image_util",
     "//ios/chrome/browser/ui/tabs/requirements",
diff --git a/ios/chrome/browser/ui/toolbar/toolbar_egtest.mm b/ios/chrome/browser/ui/toolbar/toolbar_egtest.mm
index b56235a..2f73cca 100644
--- a/ios/chrome/browser/ui/toolbar/toolbar_egtest.mm
+++ b/ios/chrome/browser/ui/toolbar/toolbar_egtest.mm
@@ -96,6 +96,11 @@
 
   [ChromeEarlGrey loadURL:URL];
 
+  if (IsRefreshLocationBarEnabled()) {
+    [[EarlGrey
+        selectElementWithMatcher:chrome_test_util::DefocusedLocationView()]
+        performAction:grey_tap()];
+  }
   [[EarlGrey selectElementWithMatcher:chrome_test_util::Omnibox()]
       assertWithMatcher:chrome_test_util::OmniboxText(URL.GetContent())];
   [[EarlGrey selectElementWithMatcher:chrome_test_util::Omnibox()]
@@ -279,6 +284,11 @@
 
 // Verifies that copying and pasting a URL includes the hidden protocol prefix.
 - (void)testCopyPasteURL {
+  if (IsRefreshLocationBarEnabled()) {
+    // TODO(crbug.com/834345): Enable this test when long press on the steady
+    // location bar is supported.
+    EARL_GREY_TEST_SKIPPED(@"Test not supported yet in UI Refresh.");
+  }
   // TODO(crbug.com/849932): re-enable this test on iOS 10 once the share button
   // is implemented.
   if (!base::ios::IsRunningOnIOS11OrLater()) {
@@ -344,13 +354,6 @@
   }
 
   [ChromeEarlGrey loadURL:secondURL];
-
-  if (IsRefreshLocationBarEnabled()) {
-    // Tap on the steady location view to expose omnibox for pasting.
-    [[EarlGrey
-        selectElementWithMatcher:chrome_test_util::DefocusedLocationView()]
-        performAction:grey_tap()];
-  }
   [[EarlGrey selectElementWithMatcher:chrome_test_util::Omnibox()]
       performAction:grey_longPress()];
 
@@ -387,7 +390,13 @@
   [[EarlGrey selectElementWithMatcher:chrome_test_util::Omnibox()]
       assertWithMatcher:chrome_test_util::OmniboxText("foo")];
 
-  id<GREYMatcher> cancelButton = grey_accessibilityLabel(@"Clear Text");
+  id<GREYMatcher> cancelButton = nil;
+  if (IsRefreshLocationBarEnabled()) {
+    cancelButton = grey_accessibilityLabel(@"Clear text");
+  } else {
+    cancelButton = grey_accessibilityLabel(@"Clear Text");
+  }
+
   [[EarlGrey selectElementWithMatcher:cancelButton] performAction:grey_tap()];
 
   [[EarlGrey selectElementWithMatcher:chrome_test_util::Omnibox()]
@@ -407,11 +416,7 @@
   web::test::SetUpSimpleHttpServer(responses);
   [ChromeEarlGrey loadURL:GURL(URL)];
 
-  [[EarlGrey selectElementWithMatcher:chrome_test_util::Omnibox()]
-      performAction:grey_typeText(@"javascript:alert('Hello');")];
-
-  [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"Go")]
-      performAction:grey_tap()];
+  [ChromeEarlGreyUI focusOmniboxAndType:@"javascript:alert('Hello');\n"];
 
   [[EarlGrey selectElementWithMatcher:grey_accessibilityLabel(@"Hello")]
       assertWithMatcher:grey_notNil()];
@@ -426,11 +431,12 @@
     EARL_GREY_TEST_DISABLED(@"Disabled for iPad due to a typing bug.");
   }
   [ChromeEarlGrey loadURL:GURL("chrome://version")];
-  [[EarlGrey selectElementWithMatcher:chrome_test_util::Omnibox()]
-      performAction:grey_typeText(@"javascript:alert('Hello');")];
-
-  [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"Go")]
-      performAction:grey_tap()];
+  if (IsRefreshLocationBarEnabled()) {
+    [[EarlGrey
+        selectElementWithMatcher:chrome_test_util::DefocusedLocationView()]
+        performAction:grey_tap()];
+  }
+  [ChromeEarlGreyUI focusOmniboxAndType:@"javascript:alert('Hello');\n"];
 
   [[EarlGrey selectElementWithMatcher:grey_accessibilityLabel(@"Hello")]
       assertWithMatcher:grey_nil()];
diff --git a/ios/chrome/browser/web/browsing_egtest.mm b/ios/chrome/browser/web/browsing_egtest.mm
index f855684f..a7eb0950 100644
--- a/ios/chrome/browser/web/browsing_egtest.mm
+++ b/ios/chrome/browser/web/browsing_egtest.mm
@@ -406,10 +406,11 @@
   NSString* script =
       [NSString stringWithFormat:@"javascript:window.location='%s'",
                                  targetURL.spec().c_str()];
-  [[EarlGrey selectElementWithMatcher:chrome_test_util::Omnibox()]
-      performAction:grey_typeText(script)];
+
+  [ChromeEarlGreyUI focusOmniboxAndType:script];
   [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"Go")]
       performAction:grey_tap()];
+
   [ChromeEarlGrey waitForPageToFinishLoading];
 
   [[EarlGrey selectElementWithMatcher:OmniboxText(targetURL.GetContent())]
@@ -441,11 +442,7 @@
   [ChromeEarlGrey loadURL:secondURL];
 
   // Execute some JavaScript in the omnibox.
-  [[EarlGrey selectElementWithMatcher:chrome_test_util::Omnibox()]
-      performAction:grey_typeText(@"javascript:document.write('foo')")];
-  [[EarlGrey selectElementWithMatcher:grey_accessibilityID(@"Go")]
-      performAction:grey_tap()];
-
+  [ChromeEarlGreyUI focusOmniboxAndType:@"javascript:document.write('foo')\n"];
   [ChromeEarlGrey waitForWebViewContainingText:"foo"];
 
   // Verify that the JavaScript did not affect history by going back and then
diff --git a/ios/chrome/browser/web/cache_egtest.mm b/ios/chrome/browser/web/cache_egtest.mm
index 2ca5d1ef..52aa1f2 100644
--- a/ios/chrome/browser/web/cache_egtest.mm
+++ b/ios/chrome/browser/web/cache_egtest.mm
@@ -14,6 +14,7 @@
 #include "ios/chrome/test/app/navigation_test_util.h"
 #import "ios/chrome/test/app/web_view_interaction_test_util.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
+#import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h"
 #import "ios/chrome/test/earl_grey/chrome_matchers.h"
 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
 #include "ios/chrome/test/scoped_block_popups_pref.h"
@@ -211,8 +212,7 @@
   [ChromeEarlGrey waitForWebViewContainingText:"serverHitCounter: 1"];
 
   // Type a search into omnnibox and select the first suggestion (second row)
-  [[EarlGrey selectElementWithMatcher:chrome_test_util::Omnibox()]
-      performAction:grey_typeText(@"cachetestfirstpage")];
+  [ChromeEarlGreyUI focusOmniboxAndType:@"cachetestfirstpage"];
   [[EarlGrey
       selectElementWithMatcher:grey_accessibilityID(@"omnibox suggestion 1")]
       performAction:grey_tap()];
diff --git a/ios/chrome/test/earl_grey/chrome_earl_grey_ui.h b/ios/chrome/test/earl_grey/chrome_earl_grey_ui.h
index 2525ca06..2a38ff27 100644
--- a/ios/chrome/test/earl_grey/chrome_earl_grey_ui.h
+++ b/ios/chrome/test/earl_grey/chrome_earl_grey_ui.h
@@ -48,6 +48,10 @@
 // accounts menu is not open when this is called there will be a GREYAssert.
 + (void)tapAccountsMenuButton:(id<GREYMatcher>)buttonMatcher;
 
+// Focuses the omnibox by tapping and types |text| into it. The '\n' symbol can
+// be passed in order to commit the string.
++ (void)focusOmniboxAndType:(NSString*)text;
+
 // Open a new tab via the tools menu.
 + (void)openNewTab;
 
diff --git a/ios/chrome/test/earl_grey/chrome_earl_grey_ui.mm b/ios/chrome/test/earl_grey/chrome_earl_grey_ui.mm
index 51e5b94f..92e25466 100644
--- a/ios/chrome/test/earl_grey/chrome_earl_grey_ui.mm
+++ b/ios/chrome/test/earl_grey/chrome_earl_grey_ui.mm
@@ -109,6 +109,16 @@
       performAction:grey_tap()];
 }
 
++ (void)focusOmniboxAndType:(NSString*)text {
+  if (IsRefreshLocationBarEnabled()) {
+    [[EarlGrey
+        selectElementWithMatcher:chrome_test_util::DefocusedLocationView()]
+        performAction:grey_tap()];
+  }
+  [[EarlGrey selectElementWithMatcher:chrome_test_util::Omnibox()]
+      performAction:grey_typeText(text)];
+}
+
 + (void)openNewTab {
   [ChromeEarlGreyUI openToolsMenu];
   id<GREYMatcher> newTabButtonMatcher =
diff --git a/ios/chrome/test/earl_grey/chrome_matchers.h b/ios/chrome/test/earl_grey/chrome_matchers.h
index bf63f488..6d476e2e 100644
--- a/ios/chrome/test/earl_grey/chrome_matchers.h
+++ b/ios/chrome/test/earl_grey/chrome_matchers.h
@@ -19,6 +19,12 @@
 // accessibility trait UIAccessibilityTraitButton.
 id<GREYMatcher> ButtonWithAccessibilityLabel(NSString* label);
 
+// Matcher for element with an image corresponding to |image_id|.
+id<GREYMatcher> ImageViewWithImage(int image_id);
+
+// Matcher for element with an image defined by its name in the main bundle.
+id<GREYMatcher> ImageViewWithImageNamed(NSString* imageName);
+
 // Matcher for element with an image corresponding to |image_id| and
 // accessibility trait UIAccessibilityTraitButton.
 id<GREYMatcher> ButtonWithImage(int image_id);
@@ -57,6 +63,8 @@
 
 // Returns a matcher for the page security info button.
 id<GREYMatcher> PageSecurityInfoButton();
+// Returns a matcher for the page security info indicator.
+id<GREYMatcher> PageSecurityInfoIndicator();
 
 // Returns matcher for omnibox containing |text|. Performs an exact match of the
 // omnibox contents.
diff --git a/ios/chrome/test/earl_grey/chrome_matchers.mm b/ios/chrome/test/earl_grey/chrome_matchers.mm
index 62e372e..6800c7f 100644
--- a/ios/chrome/test/earl_grey/chrome_matchers.mm
+++ b/ios/chrome/test/earl_grey/chrome_matchers.mm
@@ -96,6 +96,40 @@
       l10n_util::GetNSStringWithFixup(message_id));
 }
 
+id<GREYMatcher> ImageViewWithImageNamed(NSString* imageName) {
+  UIImage* expected_image = [UIImage imageNamed:imageName];
+  MatchesBlock matches = ^BOOL(UIImageView* imageView) {
+    return ui::test::uiimage_utils::UIImagesAreEqual(expected_image,
+                                                     imageView.image);
+  };
+  NSString* description_string =
+      [NSString stringWithFormat:@"Images matching image named %@", imageName];
+  DescribeToBlock describe = ^(id<GREYDescription> description) {
+    [description appendText:description_string];
+  };
+  id<GREYMatcher> image_matcher =
+      [[GREYElementMatcherBlock alloc] initWithMatchesBlock:matches
+                                           descriptionBlock:describe];
+  return image_matcher;
+}
+
+id<GREYMatcher> ImageViewWithImage(int image_id) {
+  UIImage* expected_image = NativeImage(image_id);
+  MatchesBlock matches = ^BOOL(UIImageView* imageView) {
+    return ui::test::uiimage_utils::UIImagesAreEqual(expected_image,
+                                                     imageView.image);
+  };
+  NSString* description_string =
+      [NSString stringWithFormat:@"Images matching %i", image_id];
+  DescribeToBlock describe = ^(id<GREYDescription> description) {
+    [description appendText:description_string];
+  };
+  id<GREYMatcher> image_matcher =
+      [[GREYElementMatcherBlock alloc] initWithMatchesBlock:matches
+                                           descriptionBlock:describe];
+  return image_matcher;
+}
+
 id<GREYMatcher> ButtonWithImage(int image_id) {
   UIImage* expected_image = NativeImage(image_id);
   MatchesBlock matches = ^BOOL(UIButton* button) {
@@ -161,6 +195,10 @@
   return grey_accessibilityLabel(@"Page Security Info");
 }
 
+id<GREYMatcher> PageSecurityInfoIndicator() {
+  return grey_accessibilityLabel(@"Page Security Info");
+}
+
 id<GREYMatcher> OmniboxText(std::string text) {
   return grey_allOf(Omnibox(),
                     hasProperty(@"text", base::SysUTF8ToNSString(text)), nil);
diff --git a/ios/third_party/material_components_ios/README.chromium b/ios/third_party/material_components_ios/README.chromium
index 6363f688..50bb217 100644
--- a/ios/third_party/material_components_ios/README.chromium
+++ b/ios/third_party/material_components_ios/README.chromium
@@ -1,7 +1,7 @@
 Name: Material Components for iOS
 URL: https://github.com/material-components/material-components-ios
 Version: 0
-Revision: 7e7ca3549d8e21c8749c3daf1f9a6dce5be840d3
+Revision: 8fad5e937124a6b81415cb4fbc12dbef746af8e1
 License: Apache 2.0
 License File: LICENSE
 Security Critical: yes
diff --git a/ios/web_view/BUILD.gn b/ios/web_view/BUILD.gn
index bdde7af2..d48fedc 100644
--- a/ios/web_view/BUILD.gn
+++ b/ios/web_view/BUILD.gn
@@ -322,6 +322,7 @@
     "internal/cwv_html_element_unittest.mm",
     "internal/cwv_preferences_unittest.mm",
     "internal/cwv_preview_element_info_unittest.mm",
+    "internal/signin/cwv_identity_unittest.mm",
     "internal/translate/cwv_translation_controller_unittest.mm",
     "internal/translate/cwv_translation_language_unittest.mm",
     "internal/translate/cwv_translation_policy_unittest.mm",
diff --git a/ios/web_view/internal/autofill/cwv_autofill_controller.mm b/ios/web_view/internal/autofill/cwv_autofill_controller.mm
index a9684866..e1ecbaf4 100644
--- a/ios/web_view/internal/autofill/cwv_autofill_controller.mm
+++ b/ios/web_view/internal/autofill/cwv_autofill_controller.mm
@@ -120,13 +120,15 @@
 #pragma mark - Public Methods
 
 - (void)clearFormWithName:(NSString*)formName
+          fieldIdentifier:(NSString*)fieldIdentifier
         completionHandler:(nullable void (^)(void))completionHandler {
-  [_JSAutofillManager clearAutofilledFieldsForFormNamed:formName
-                                      completionHandler:^{
-                                        if (completionHandler) {
-                                          completionHandler();
-                                        }
-                                      }];
+  [_JSAutofillManager clearAutofilledFieldsForFormName:formName
+                                       fieldIdentifier:fieldIdentifier
+                                     completionHandler:^{
+                                       if (completionHandler) {
+                                         completionHandler();
+                                       }
+                                     }];
 }
 
 - (void)fetchSuggestionsForFormWithName:(NSString*)formName
diff --git a/ios/web_view/internal/autofill/cwv_autofill_controller_unittest.mm b/ios/web_view/internal/autofill/cwv_autofill_controller_unittest.mm
index a83c9e3..51b0119 100644
--- a/ios/web_view/internal/autofill/cwv_autofill_controller_unittest.mm
+++ b/ios/web_view/internal/autofill/cwv_autofill_controller_unittest.mm
@@ -143,6 +143,7 @@
 TEST_F(CWVAutofillControllerTest, ClearForm) {
   __block BOOL clear_form_completion_was_called = NO;
   [autofill_controller_ clearFormWithName:kTestFormName
+                          fieldIdentifier:kTestFieldIdentifier
                         completionHandler:^{
                           clear_form_completion_was_called = YES;
                         }];
@@ -152,6 +153,8 @@
     return clear_form_completion_was_called;
   }));
   EXPECT_NSEQ(kTestFormName, js_autofill_manager_.lastClearedFormName);
+  EXPECT_NSEQ(kTestFieldIdentifier,
+              js_autofill_manager_.lastClearedFieldIdentifier);
 }
 
 // Tests CWVAutofillController focus previous field.
diff --git a/ios/web_view/internal/signin/cwv_identity_unittest.mm b/ios/web_view/internal/signin/cwv_identity_unittest.mm
new file mode 100644
index 0000000..4f3d4d3c
--- /dev/null
+++ b/ios/web_view/internal/signin/cwv_identity_unittest.mm
@@ -0,0 +1,35 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/web_view/public/cwv_identity.h"
+
+#import <Foundation/Foundation.h>
+
+#include "testing/gtest/include/gtest/gtest.h"
+#import "testing/gtest_mac.h"
+#include "testing/platform_test.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+namespace ios_web_view {
+
+using CWVIdentityTest = PlatformTest;
+
+// Tests CWVIdentity initialization.
+TEST_F(CWVIdentityTest, Initialization) {
+  NSString* email = @"john.doe@chromium.org";
+  NSString* full_name = @"John Doe";
+  NSString* gaia_id = @"123456789";
+
+  CWVIdentity* identity = [[CWVIdentity alloc] initWithEmail:email
+                                                    fullName:full_name
+                                                      gaiaID:gaia_id];
+  EXPECT_NSEQ(email, identity.email);
+  EXPECT_NSEQ(full_name, identity.fullName);
+  EXPECT_NSEQ(gaia_id, identity.gaiaID);
+}
+
+}  // namespace ios_web_view
diff --git a/ios/web_view/public/cwv_autofill_controller.h b/ios/web_view/public/cwv_autofill_controller.h
index 715da8d..e9f4e661 100644
--- a/ios/web_view/public/cwv_autofill_controller.h
+++ b/ios/web_view/public/cwv_autofill_controller.h
@@ -24,15 +24,22 @@
 
 - (instancetype)init NS_UNAVAILABLE;
 
-// Clears the html form element with the 'name' attribute equal to |formName|.
-// No-op if no such form is found.
+// Clears the fields that belong to the same autofill section as the field
+// identified by |fieldIdentifier| in the form named |formName|.
+// No-op if no such form can be found in the current page. If the field
+// identified by |fieldIdentifier| cannot be found the entire form gets cleared.
+// |fieldIdentifier| identifies the field that had focus. It is passed to
+// CWVAutofillControllerDelegate and forwarded to this method.
 // |completionHandler| will only be called on success.
 - (void)clearFormWithName:(NSString*)formName
+          fieldIdentifier:(NSString*)fieldIdentifier
         completionHandler:(nullable void (^)(void))completionHandler;
 
 // For the field named |fieldName|, identified by |fieldIdentifier| in the form
 // named |formName|, fetches suggestions that can be used to autofill.
 // No-op if no such form and field can be found in the current page.
+// |fieldIdentifier| identifies the field that had focus. It is passed to
+// CWVAutofillControllerDelegate and forwarded to this method.
 // |completionHandler| will only be called on success.
 - (void)fetchSuggestionsForFormWithName:(NSString*)formName
                               fieldName:(NSString*)fieldName
diff --git a/ios/web_view/public/cwv_identity.h b/ios/web_view/public/cwv_identity.h
index 8995d48..ea5f4ad 100644
--- a/ios/web_view/public/cwv_identity.h
+++ b/ios/web_view/public/cwv_identity.h
@@ -12,6 +12,7 @@
 NS_ASSUME_NONNULL_BEGIN
 
 CWV_EXPORT
+// Represents a user in ChromeWebView.
 @interface CWVIdentity : NSObject
 
 - (instancetype)initWithEmail:(NSString*)email
@@ -20,17 +21,13 @@
 
 - (instancetype)init NS_UNAVAILABLE;
 
-// Identity/account email address. This can be shown to the user, but is not a
-// unique identifier (@see gaiaID).
+// The user's email address. e.g. john.doe@chromium.org.
 @property(nonatomic, copy, readonly) NSString* email;
 
-// Returns the full name of the identity.
-// Could be nil if no full name has been fetched for this account yet.
+// The user's full name. e.g. John Doe.
 @property(nonatomic, copy, readonly, nullable) NSString* fullName;
 
-// The unique GAIA user identifier for this identity/account.
-// Use this as a unique identifier to remember a particular identity.
-// Use SSOIdentity's |userID| property. See go/ios-sso-library for more info.
+// The unique GAIA (Google Accounts ID Administration) ID for this user.
 @property(nonatomic, copy, readonly) NSString* gaiaID;
 
 @end
diff --git a/ios/web_view/shell/shell_autofill_delegate.m b/ios/web_view/shell/shell_autofill_delegate.m
index 7e7133a..75dc5f82 100644
--- a/ios/web_view/shell/shell_autofill_delegate.m
+++ b/ios/web_view/shell/shell_autofill_delegate.m
@@ -64,13 +64,14 @@
     for (CWVAutofillSuggestion* suggestion in suggestions) {
       [alertController addAction:[self actionForSuggestion:suggestion]];
     }
-    UIAlertAction* clearAction =
-        [UIAlertAction actionWithTitle:@"Clear"
-                                 style:UIAlertActionStyleDefault
-                               handler:^(UIAlertAction* _Nonnull action) {
-                                 [autofillController clearFormWithName:formName
-                                                     completionHandler:nil];
-                               }];
+    UIAlertAction* clearAction = [UIAlertAction
+        actionWithTitle:@"Clear"
+                  style:UIAlertActionStyleDefault
+                handler:^(UIAlertAction* _Nonnull action) {
+                  [autofillController clearFormWithName:formName
+                                        fieldIdentifier:fieldIdentifier
+                                      completionHandler:nil];
+                }];
     [alertController addAction:clearAction];
 
     [strongSelf presentAlertController:alertController];
diff --git a/ios/web_view/test/web_view_autofill_inttest.mm b/ios/web_view/test/web_view_autofill_inttest.mm
index a22eb38..fb2040c9 100644
--- a/ios/web_view/test/web_view_autofill_inttest.mm
+++ b/ios/web_view/test/web_view_autofill_inttest.mm
@@ -199,7 +199,9 @@
     return [fetched_suggestion.value isEqualToString:filled_value];
   }));
   ASSERT_NSEQ(nil, filled_error);
-  [autofill_controller_ clearFormWithName:kTestFormName completionHandler:nil];
+  [autofill_controller_ clearFormWithName:kTestFormName
+                          fieldIdentifier:kTestFieldID
+                        completionHandler:nil];
   NSString* cleared_script = [NSString
       stringWithFormat:@"document.getElementById('%@').value", kTestFieldID];
   __block NSError* cleared_error = nil;
diff --git a/ios/web_view/tools/build.py b/ios/web_view/tools/build.py
index d7de99e..269d927 100755
--- a/ios/web_view/tools/build.py
+++ b/ios/web_view/tools/build.py
@@ -189,8 +189,8 @@
                       help='Additional gn args to pass through to ninja.')
   parser.add_argument('--include_cronet', action='store_true',
                       help='Combines Cronet and ChromeWebView as 1 framework.')
-  parser.add_argument('--enable_signin', action='store_true',
-                      help='Enables public API for signin.')
+  parser.add_argument('--enable_sync', action='store_true',
+                      help='Enables public API for sync.')
   parser.add_argument('--enable_autofill', action='store_true',
                       help='Enables public API for autofill.')
   build_configs = ['Debug', 'Release']
@@ -224,10 +224,10 @@
     output_name = 'CronetChromeWebView'
   else:
     extra_gn_options += 'ios_web_view_include_cronet=false '
-  if options.enable_signin:
-    extra_gn_options += 'ios_web_view_enable_signin=true '
+  if options.enable_sync:
+    extra_gn_options += 'ios_web_view_enable_sync=true '
   else:
-    extra_gn_options += 'ios_web_view_enable_signin=false '
+    extra_gn_options += 'ios_web_view_enable_sync=false '
   if options.enable_autofill:
     extra_gn_options += 'ios_web_view_enable_autofill=true '
   else:
diff --git a/media/audio/audio_device_thread.cc b/media/audio/audio_device_thread.cc
index 4f7f7061..beffbcc1 100644
--- a/media/audio/audio_device_thread.cc
+++ b/media/audio/audio_device_thread.cc
@@ -40,10 +40,11 @@
 
 AudioDeviceThread::AudioDeviceThread(Callback* callback,
                                      base::SyncSocket::Handle socket,
-                                     const char* thread_name)
+                                     const char* thread_name,
+                                     base::ThreadPriority thread_priority)
     : callback_(callback), thread_name_(thread_name), socket_(socket) {
-  CHECK(base::PlatformThread::CreateWithPriority(
-      0, this, &thread_handle_, base::ThreadPriority::REALTIME_AUDIO));
+  CHECK(base::PlatformThread::CreateWithPriority(0, this, &thread_handle_,
+                                                 thread_priority));
 
   DCHECK(!thread_handle_.is_null());
 }
diff --git a/media/audio/audio_device_thread.h b/media/audio/audio_device_thread.h
index 188647c..6aecb90 100644
--- a/media/audio/audio_device_thread.h
+++ b/media/audio/audio_device_thread.h
@@ -67,7 +67,8 @@
   // Creates and automatically starts the audio thread.
   AudioDeviceThread(Callback* callback,
                     base::SyncSocket::Handle socket,
-                    const char* thread_name);
+                    const char* thread_name,
+                    base::ThreadPriority thread_priority);
 
   // This tells the audio thread to stop and clean up the data; this is a
   // synchronous process and the thread will stop before the method returns.
diff --git a/media/audio/audio_input_device.cc b/media/audio/audio_input_device.cc
index c54ba81..e4a96ca 100644
--- a/media/audio/audio_input_device.cc
+++ b/media/audio/audio_input_device.cc
@@ -86,8 +86,10 @@
   DISALLOW_COPY_AND_ASSIGN(AudioThreadCallback);
 };
 
-AudioInputDevice::AudioInputDevice(std::unique_ptr<AudioInputIPC> ipc)
-    : callback_(nullptr),
+AudioInputDevice::AudioInputDevice(std::unique_ptr<AudioInputIPC> ipc,
+                                   base::ThreadPriority thread_priority)
+    : thread_priority_(thread_priority),
+      callback_(nullptr),
       ipc_(std::move(ipc)),
       state_(IDLE),
       agc_is_enabled_(false) {
@@ -247,8 +249,9 @@
       kRequestedSharedMemoryCount, callback_,
       base::BindRepeating(&AliveChecker::NotifyAlive,
                           base::Unretained(alive_checker_.get())));
-  audio_thread_ = std::make_unique<AudioDeviceThread>(
-      audio_callback_.get(), socket_handle, "AudioInputDevice");
+  audio_thread_ =
+      std::make_unique<AudioDeviceThread>(audio_callback_.get(), socket_handle,
+                                          "AudioInputDevice", thread_priority_);
 
   state_ = RECORDING;
   ipc_->RecordStream();
diff --git a/media/audio/audio_input_device.h b/media/audio/audio_input_device.h
index de00738..17351241 100644
--- a/media/audio/audio_input_device.h
+++ b/media/audio/audio_input_device.h
@@ -53,6 +53,7 @@
 #include "base/memory/read_only_shared_memory_region.h"
 #include "base/optional.h"
 #include "base/sequence_checker.h"
+#include "base/threading/platform_thread.h"
 #include "base/time/time.h"
 #include "media/audio/alive_checker.h"
 #include "media/audio/audio_device_thread.h"
@@ -67,7 +68,8 @@
                                       public AudioInputIPCDelegate {
  public:
   // NOTE: Clients must call Initialize() before using.
-  explicit AudioInputDevice(std::unique_ptr<AudioInputIPC> ipc);
+  AudioInputDevice(std::unique_ptr<AudioInputIPC> ipc,
+                   base::ThreadPriority thread_priority);
 
   // AudioCapturerSource implementation.
   void Initialize(const AudioParameters& params,
@@ -118,6 +120,8 @@
 
   AudioParameters audio_parameters_;
 
+  const base::ThreadPriority thread_priority_;
+
   CaptureCallback* callback_;
 
   // A pointer to the IPC layer that takes care of sending requests over to
diff --git a/media/audio/audio_input_device_unittest.cc b/media/audio/audio_input_device_unittest.cc
index 54fd2e27..e1f7a55 100644
--- a/media/audio/audio_input_device_unittest.cc
+++ b/media/audio/audio_input_device_unittest.cc
@@ -66,8 +66,8 @@
 TEST(AudioInputDeviceTest, Noop) {
   base::MessageLoopForIO io_loop;
   MockAudioInputIPC* input_ipc = new MockAudioInputIPC();
-  scoped_refptr<AudioInputDevice> device(
-      new AudioInputDevice(base::WrapUnique(input_ipc)));
+  scoped_refptr<AudioInputDevice> device(new AudioInputDevice(
+      base::WrapUnique(input_ipc), base::ThreadPriority::REALTIME_AUDIO));
 }
 
 ACTION_P(ReportStateChange, device) {
@@ -81,8 +81,8 @@
 
   MockCaptureCallback callback;
   MockAudioInputIPC* input_ipc = new MockAudioInputIPC();
-  scoped_refptr<AudioInputDevice> device(
-      new AudioInputDevice(base::WrapUnique(input_ipc)));
+  scoped_refptr<AudioInputDevice> device(new AudioInputDevice(
+      base::WrapUnique(input_ipc), base::ThreadPriority::REALTIME_AUDIO));
   device->Initialize(params, &callback);
   EXPECT_CALL(*input_ipc, CreateStream(_, _, _, _))
       .WillOnce(ReportStateChange(device.get()));
@@ -117,8 +117,8 @@
   base::test::ScopedTaskEnvironment ste;
   MockCaptureCallback callback;
   MockAudioInputIPC* input_ipc = new MockAudioInputIPC();
-  scoped_refptr<AudioInputDevice> device(
-      new AudioInputDevice(base::WrapUnique(input_ipc)));
+  scoped_refptr<AudioInputDevice> device(new AudioInputDevice(
+      base::WrapUnique(input_ipc), base::ThreadPriority::REALTIME_AUDIO));
   device->Initialize(params, &callback);
 
   EXPECT_CALL(*input_ipc, CreateStream(_, _, _, _))
diff --git a/media/audio/audio_output_device.cc b/media/audio/audio_output_device.cc
index 90ae483d..d10d9a7 100644
--- a/media/audio/audio_output_device.cc
+++ b/media/audio/audio_output_device.cc
@@ -14,6 +14,7 @@
 #include "base/macros.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/single_thread_task_runner.h"
+#include "base/threading/platform_thread.h"
 #include "base/threading/thread_restrictions.h"
 #include "base/timer/timer.h"
 #include "base/trace_event/trace_event.h"
@@ -402,7 +403,8 @@
     if (playing_automatically)
       audio_callback_->InitializePlayStartTime();
     audio_thread_.reset(new AudioDeviceThread(
-        audio_callback_.get(), socket_handle, "AudioOutputDevice"));
+        audio_callback_.get(), socket_handle, "AudioOutputDevice",
+        base::ThreadPriority::REALTIME_AUDIO));
   }
 }
 
diff --git a/media/base/key_systems.cc b/media/base/key_systems.cc
index a51a28df..0a82a30c 100644
--- a/media/base/key_systems.cc
+++ b/media/base/key_systems.cc
@@ -200,8 +200,6 @@
 
   std::string GetKeySystemNameForUMA(const std::string& key_system) const;
 
-  bool UseAesDecryptor(const std::string& key_system) const;
-
   // These two functions are for testing purpose only.
   void AddCodecMask(EmeMediaType media_type,
                     const std::string& codec,
@@ -211,6 +209,8 @@
   // Implementation of KeySystems interface.
   bool IsSupportedKeySystem(const std::string& key_system) const override;
 
+  bool CanUseAesDecryptor(const std::string& key_system) const override;
+
   bool IsSupportedInitDataType(const std::string& key_system,
                                EmeInitDataType init_data_type) const override;
 
@@ -531,18 +531,6 @@
   return kUnknownKeySystemNameForUMA;
 }
 
-bool KeySystemsImpl::UseAesDecryptor(const std::string& key_system) const {
-  DCHECK(thread_checker_.CalledOnValidThread());
-
-  KeySystemPropertiesMap::const_iterator key_system_iter =
-      key_system_properties_map_.find(key_system);
-  if (key_system_iter == key_system_properties_map_.end()) {
-    DLOG(ERROR) << key_system << " is not a known key system";
-    return false;
-  }
-  return key_system_iter->second->UseAesDecryptor();
-}
-
 void KeySystemsImpl::AddCodecMask(EmeMediaType media_type,
                                   const std::string& codec,
                                   uint32_t mask) {
@@ -570,6 +558,18 @@
   return true;
 }
 
+bool KeySystemsImpl::CanUseAesDecryptor(const std::string& key_system) const {
+  DCHECK(thread_checker_.CalledOnValidThread());
+
+  KeySystemPropertiesMap::const_iterator key_system_iter =
+      key_system_properties_map_.find(key_system);
+  if (key_system_iter == key_system_properties_map_.end()) {
+    DLOG(ERROR) << key_system << " is not a known key system";
+    return false;
+  }
+  return key_system_iter->second->UseAesDecryptor();
+}
+
 EmeConfigRule KeySystemsImpl::GetContentTypeConfigRule(
     const std::string& key_system,
     EmeMediaType media_type,
@@ -727,7 +727,7 @@
 }
 
 bool CanUseAesDecryptor(const std::string& key_system) {
-  return KeySystemsImpl::GetInstance()->UseAesDecryptor(key_system);
+  return KeySystemsImpl::GetInstance()->CanUseAesDecryptor(key_system);
 }
 
 // These two functions are for testing purpose only. The declaration in the
diff --git a/media/base/key_systems.h b/media/base/key_systems.h
index a99e45b..85e2ef0 100644
--- a/media/base/key_systems.h
+++ b/media/base/key_systems.h
@@ -31,6 +31,9 @@
   // Returns whether |key_system| is a supported key system.
   virtual bool IsSupportedKeySystem(const std::string& key_system) const = 0;
 
+  // Returns whether AesDecryptor can be used for the given |key_system|.
+  virtual bool CanUseAesDecryptor(const std::string& key_system) const = 0;
+
   // Returns whether |init_data_type| is supported by |key_system|.
   virtual bool IsSupportedInitDataType(
       const std::string& key_system,
diff --git a/media/blink/key_system_config_selector.cc b/media/blink/key_system_config_selector.cc
index b27eb858..8d02e07 100644
--- a/media/blink/key_system_config_selector.cc
+++ b/media/blink/key_system_config_selector.cc
@@ -337,8 +337,9 @@
   // is done primarily to validate extended codecs, but it also ensures that the
   // CDM cannot support codecs that Chrome does not (which could complicate the
   // robustness algorithm).
-  if (!is_supported_media_type_cb_.Run(container_lower, codecs,
-                                       CanUseAesDecryptor(key_system))) {
+  if (!is_supported_media_type_cb_.Run(
+          container_lower, codecs,
+          key_systems_->CanUseAesDecryptor(key_system))) {
     DVLOG(3) << "Container mime type and codecs are not supported";
     return false;
   }
diff --git a/media/blink/key_system_config_selector_unittest.cc b/media/blink/key_system_config_selector_unittest.cc
index 78a938b..0f1e176 100644
--- a/media/blink/key_system_config_selector_unittest.cc
+++ b/media/blink/key_system_config_selector_unittest.cc
@@ -158,9 +158,12 @@
 
   bool IsSupportedKeySystem(const std::string& key_system) const override {
     // Based on EME spec, Clear Key key system is always supported.
-    if (key_system == kSupportedKeySystem || key_system == kClearKeyKeySystem)
-      return true;
-    return false;
+    return key_system == kSupportedKeySystem ||
+           key_system == kClearKeyKeySystem;
+  }
+
+  bool CanUseAesDecryptor(const std::string& key_system) const override {
+    return key_system == kClearKeyKeySystem;
   }
 
   // TODO(sandersd): Move implementation into KeySystemConfigSelector?
diff --git a/net/BUILD.gn b/net/BUILD.gn
index 9cbaef9..4dbc4e2 100644
--- a/net/BUILD.gn
+++ b/net/BUILD.gn
@@ -1508,6 +1508,7 @@
       "third_party/quic/platform/api/quic_endian.h",
       "third_party/quic/platform/api/quic_estimate_memory_usage.h",
       "third_party/quic/platform/api/quic_export.h",
+      "third_party/quic/platform/api/quic_exported_stats.h",
       "third_party/quic/platform/api/quic_fallthrough.h",
       "third_party/quic/platform/api/quic_file_utils.h",
       "third_party/quic/platform/api/quic_flag_utils.h",
@@ -1552,6 +1553,7 @@
       "third_party/quic/platform/impl/quic_endian_impl.h",
       "third_party/quic/platform/impl/quic_estimate_memory_usage_impl.h",
       "third_party/quic/platform/impl/quic_export_impl.h",
+      "third_party/quic/platform/impl/quic_exported_stats_impl.h",
       "third_party/quic/platform/impl/quic_fallthrough_impl.h",
       "third_party/quic/platform/impl/quic_file_utils_impl.h",
       "third_party/quic/platform/impl/quic_flag_utils_impl.h",
diff --git a/net/third_party/quic/core/quic_connection.cc b/net/third_party/quic/core/quic_connection.cc
index 26e328ca..6311762 100644
--- a/net/third_party/quic/core/quic_connection.cc
+++ b/net/third_party/quic/core/quic_connection.cc
@@ -28,6 +28,7 @@
 #include "net/third_party/quic/core/quic_pending_retransmission.h"
 #include "net/third_party/quic/core/quic_utils.h"
 #include "net/third_party/quic/platform/api/quic_bug_tracker.h"
+#include "net/third_party/quic/platform/api/quic_exported_stats.h"
 #include "net/third_party/quic/platform/api/quic_flag_utils.h"
 #include "net/third_party/quic/platform/api/quic_flags.h"
 #include "net/third_party/quic/platform/api/quic_logging.h"
@@ -2113,6 +2114,13 @@
     DCHECK_EQ(WRITE_STATUS_BLOCKED, result.status);
   }
 
+  if (GetQuicReloadableFlag(quic_export_connection_write_packet_results)) {
+    QUIC_HISTOGRAM_ENUM(
+        "QuicConnection.WritePacketStatus", result.status,
+        WRITE_STATUS_NUM_VALUES,
+        "Status code returned by writer_->WritePacket() in QuicConnection.");
+  }
+
   if (result.status == WRITE_STATUS_BLOCKED) {
     // Ensure the writer is still write blocked, otherwise QUIC may continue
     // trying to write when it will not be able to.
diff --git a/net/third_party/quic/core/quic_flags_list.h b/net/third_party/quic/core/quic_flags_list.h
index 67a700e..b6d03c4 100644
--- a/net/third_party/quic/core/quic_flags_list.h
+++ b/net/third_party/quic/core/quic_flags_list.h
@@ -210,3 +210,9 @@
 
 // If true, enable QUIC v44.
 QUIC_FLAG(bool, FLAGS_quic_enable_version_44, false)
+
+// If true, export packet write results in QuicConnection.
+QUIC_FLAG(
+    bool,
+    FLAGS_quic_reloadable_flag_quic_export_connection_write_packet_results,
+    false)
diff --git a/net/third_party/quic/core/quic_types.h b/net/third_party/quic/core/quic_types.h
index b48ee6a..426c1c9d 100644
--- a/net/third_party/quic/core/quic_types.h
+++ b/net/third_party/quic/core/quic_types.h
@@ -81,6 +81,7 @@
   // - Errors MUST be added after WRITE_STATUS_ERROR.
   WRITE_STATUS_ERROR,
   WRITE_STATUS_MSG_TOO_BIG,
+  WRITE_STATUS_NUM_VALUES,
 };
 
 inline bool IsWriteError(WriteStatus status) {
diff --git a/net/third_party/quic/platform/api/quic_exported_stats.h b/net/third_party/quic/platform/api/quic_exported_stats.h
new file mode 100644
index 0000000..b796dd6
--- /dev/null
+++ b/net/third_party/quic/platform/api/quic_exported_stats.h
@@ -0,0 +1,80 @@
+// 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 NET_THIRD_PARTY_QUIC_PLATFORM_API_QUIC_EXPORTED_STATS_H_
+#define NET_THIRD_PARTY_QUIC_PLATFORM_API_QUIC_EXPORTED_STATS_H_
+
+#include "net/third_party/quic/platform/impl/quic_exported_stats_impl.h"
+
+namespace quic {
+
+// TODO(wub): Add support for counters. Only histograms are supported for now.
+
+//------------------------------------------------------------------------------
+// Enumeration histograms.
+//
+// Sample usage:
+//   // In Chrome, these values are persisted to logs. Entries should not be
+//   // renumbered and numeric values should never be reused.
+//   enum class MyEnum {
+//     FIRST_VALUE = 0,
+//     SECOND_VALUE = 1,
+//     ...
+//     FINAL_VALUE = N,
+//     COUNT
+//   };
+//   QUIC_HISTOGRAM_ENUM("My.Enumeration", MyEnum::SOME_VALUE, MyEnum::COUNT,
+//                       "Number of time $foo equals to some enum value");
+//
+// Note: The value in |sample| must be strictly less than |enum_size|.
+
+#define QUIC_HISTOGRAM_ENUM(name, sample, enum_size, docstring) \
+  QUIC_HISTOGRAM_ENUM_IMPL(name, sample, enum_size, docstring)
+
+//------------------------------------------------------------------------------
+// Histogram for boolean values.
+
+// Sample usage:
+//   QUIC_HISTOGRAM_BOOL("My.Boolean", bool,
+//                       "Number of times $foo is true or false");
+#define QUIC_HISTOGRAM_BOOL(name, sample, docstring) \
+  QUIC_HISTOGRAM_BOOL_IMPL(name, sample, docstring)
+
+//------------------------------------------------------------------------------
+// Timing histograms. These are used for collecting timing data (generally
+// latencies).
+
+// These macros create exponentially sized histograms (lengths of the bucket
+// ranges exponentially increase as the sample range increases). The units for
+// sample and max are unspecified, but they must be the same for one histogram.
+
+// Sample usage:
+//   QUIC_HISTOGRAM_TIMES("My.Timing.Histogram.InMs",
+//                        sample,     // Time spent in milliseconds.
+//                        10 * 1000,  // Record up to 10K milliseconds.
+//                        "Time spent in doing something");
+
+#define QUIC_HISTOGRAM_TIMES(name, sample, max, docstring) \
+  QUIC_HISTOGRAM_TIMES_IMPL(name, sample, max, 50, docstring)
+
+//------------------------------------------------------------------------------
+// Count histograms. These are used for collecting numeric data.
+
+// These macros default to exponential histograms - i.e. the lengths of the
+// bucket ranges exponentially increase as the sample range increases.
+
+// All of these macros must be called with |name| as a runtime constant.
+
+// Sample usage:
+//   QUIC_HISTOGRAM_COUNTS("My.Histogram",
+//                         sample,    // Number of something in this event.
+//                         1000,      // Record up to 1K of something.
+//                         "Number of something.");
+
+#define QUIC_HISTOGRAM_COUNTS(name, sample, max, docstring) \
+  QUIC_HISTOGRAM_COUNTS_IMPL(name, sample, max, 50, docstring)
+
+}  // namespace quic
+
+#endif  // NET_THIRD_PARTY_QUIC_PLATFORM_API_QUIC_EXPORTED_STATS_H_
diff --git a/net/third_party/quic/platform/impl/quic_exported_stats_impl.h b/net/third_party/quic/platform/impl/quic_exported_stats_impl.h
new file mode 100644
index 0000000..aacbf09a
--- /dev/null
+++ b/net/third_party/quic/platform/impl/quic_exported_stats_impl.h
@@ -0,0 +1,26 @@
+// 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 NET_THIRD_PARTY_QUIC_PLATFORM_IMPL_QUIC_EXPORTED_STATS_IMPL_H_
+#define NET_THIRD_PARTY_QUIC_PLATFORM_IMPL_QUIC_EXPORTED_STATS_IMPL_H_
+
+// By convention, all QUIC histograms are prefixed by "Net.".
+#define QUIC_HISTOGRAM_NAME(raw_name) "Net." raw_name
+
+#define QUIC_HISTOGRAM_ENUM_IMPL(name, sample, enum_size, docstring) \
+  UMA_HISTOGRAM_ENUMERATION(QUIC_HISTOGRAM_NAME(name), sample, enum_size)
+
+#define QUIC_HISTOGRAM_BOOL_IMPL(name, sample, docstring) \
+  UMA_HISTOGRAM_BOOLEAN(QUIC_HISTOGRAM_NAME(name), sample)
+
+#define QUIC_HISTOGRAM_TIMES_IMPL(name, sample, max, num_buckets, docstring)   \
+  UMA_HISTOGRAM_CUSTOM_TIMES(                                                  \
+      QUIC_HISTOGRAM_NAME(name), sample, base::TimeDelta::FromMilliseconds(1), \
+      base::TimeDelta::FromMilliseconds(max), num_buckets)
+
+#define QUIC_HISTOGRAM_COUNTS_IMPL(name, sample, max, num_buckets, docstring) \
+  UMA_HISTOGRAM_CUSTOM_COUNTS(QUIC_HISTOGRAM_NAME(name), sample, 1, max,      \
+                              num_buckets)
+
+#endif  // NET_THIRD_PARTY_QUIC_PLATFORM_IMPL_QUIC_EXPORTED_STATS_IMPL_H_
diff --git a/pdf/pdf_engine.h b/pdf/pdf_engine.h
index 88d8e3f..3bae8d4 100644
--- a/pdf/pdf_engine.h
+++ b/pdf/pdf_engine.h
@@ -406,13 +406,6 @@
   // document at page |index|.
   virtual void AppendPage(PDFEngine* engine, int index) = 0;
 
-#if defined(PDF_ENABLE_XFA)
-  // Allow client to set scroll positions in document coordinates. Note that
-  // this is meant for cases where the device scale factor changes, and not for
-  // general scrolling - the engine will not repaint due to this.
-  virtual void SetScrollPosition(const pp::Point& position) = 0;
-#endif
-
   virtual std::string GetMetadata(const std::string& key) = 0;
 
   virtual void SetCaretPosition(const pp::Point& position) = 0;
diff --git a/pdf/pdfium/pdfium_engine.cc b/pdf/pdfium/pdfium_engine.cc
index 65b278be..b9c739d 100644
--- a/pdf/pdfium/pdfium_engine.cc
+++ b/pdf/pdfium/pdfium_engine.cc
@@ -917,12 +917,6 @@
   client_->Invalidate(GetPageScreenRect(index));
 }
 
-#if defined(PDF_ENABLE_XFA)
-void PDFiumEngine::SetScrollPosition(const pp::Point& position) {
-  position_ = position;
-}
-#endif
-
 std::string PDFiumEngine::GetMetadata(const std::string& key) {
   return GetDocumentMetadata(doc(), key);
 }
diff --git a/pdf/pdfium/pdfium_engine.h b/pdf/pdfium/pdfium_engine.h
index c0df8bd..61fd100 100644
--- a/pdf/pdfium/pdfium_engine.h
+++ b/pdf/pdfium/pdfium_engine.h
@@ -119,9 +119,6 @@
   bool GetPageSizeAndUniformity(pp::Size* size) override;
   void AppendBlankPages(int num_pages) override;
   void AppendPage(PDFEngine* engine, int index) override;
-#if defined(PDF_ENABLE_XFA)
-  void SetScrollPosition(const pp::Point& position) override;
-#endif
   std::string GetMetadata(const std::string& key) override;
   void SetCaretPosition(const pp::Point& position) override;
   void MoveRangeSelectionExtent(const pp::Point& extent) override;
diff --git a/pdf/pdfium/pdfium_form_filler.cc b/pdf/pdfium/pdfium_form_filler.cc
index 0e273b9..83ff965 100644
--- a/pdf/pdfium/pdfium_form_filler.cc
+++ b/pdf/pdfium/pdfium_form_filler.cc
@@ -304,10 +304,7 @@
                                            FPDF_DOCUMENT document,
                                            int page) {
   PDFiumEngine* engine = GetEngine(param);
-  pp::Rect page_view_rect = engine->GetPageContentsRect(page);
-  engine->ScrolledToYPosition(page_view_rect.height());
-  pp::Point pos(1, page_view_rect.height());
-  engine->SetScrollPosition(pos);
+  engine->ScrollToPage(page);
 }
 
 // static
diff --git a/printing/BUILD.gn b/printing/BUILD.gn
index e4ed98b..ae715ad 100644
--- a/printing/BUILD.gn
+++ b/printing/BUILD.gn
@@ -112,6 +112,7 @@
     }
     libs = [
       "AppKit.framework",
+      "QuartzCore.framework",
       "ApplicationServices.framework",
       "CoreFoundation.framework",
       "CoreGraphics.framework",
diff --git a/printing/printing_context_mac.mm b/printing/printing_context_mac.mm
index c073a6d..51d94c64 100644
--- a/printing/printing_context_mac.mm
+++ b/printing/printing_context_mac.mm
@@ -5,6 +5,7 @@
 #include "printing/printing_context_mac.h"
 
 #import <AppKit/AppKit.h>
+#import <QuartzCore/QuartzCore.h>
 
 #import <iomanip>
 #import <numeric>
@@ -121,15 +122,23 @@
 
   // TODO(stuartmorgan): We really want a tab sheet here, not a modal window.
   // Will require restructuring the PrintingContext API to use a callback.
-  NSInteger selection = [panel runModalWithPrintInfo:printInfo];
-  if (selection == NSOKButton) {
-    print_info_.reset([[panel printInfo] retain]);
-    settings_.set_ranges(GetPageRangesFromPrintInfo());
-    InitPrintSettingsFromPrintInfo();
-    std::move(callback).Run(OK);
-  } else {
-    std::move(callback).Run(CANCEL);
-  }
+
+  // This function may be called in the middle of a CATransaction, where
+  // running a modal panel is forbidden. That situation isn't ideal, but from
+  // this code's POV the right answer is to defer running the panel until after
+  // the current transaction. See https://crbug.com/849538.
+  __block auto block_callback = std::move(callback);
+  [CATransaction setCompletionBlock:^{
+    NSInteger selection = [panel runModalWithPrintInfo:printInfo];
+    if (selection == NSOKButton) {
+      print_info_.reset([[panel printInfo] retain]);
+      settings_.set_ranges(GetPageRangesFromPrintInfo());
+      InitPrintSettingsFromPrintInfo();
+      std::move(block_callback).Run(OK);
+    } else {
+      std::move(block_callback).Run(CANCEL);
+    }
+  }];
 }
 
 gfx::Size PrintingContextMac::GetPdfPaperSizeDeviceUnits() {
diff --git a/sandbox/linux/tests/unit_tests.cc b/sandbox/linux/tests/unit_tests.cc
index c5543c1..2b32854 100644
--- a/sandbox/linux/tests/unit_tests.cc
+++ b/sandbox/linux/tests/unit_tests.cc
@@ -252,8 +252,11 @@
   ASSERT_TRUE(subprocess_terminated_normally) << details;
   int subprocess_exit_status = WEXITSTATUS(status);
   ASSERT_EQ(kExpectedValue, subprocess_exit_status) << details;
+#if !defined(LEAK_SANITIZER)
+  // LSan may print warnings to stdout, breaking this expectation.
   bool subprocess_exited_but_printed_messages = !msg.empty();
   EXPECT_FALSE(subprocess_exited_but_printed_messages) << details;
+#endif
 }
 
 void UnitTests::DeathSuccessAllowNoise(int status,
diff --git a/services/audio/public/cpp/device_factory.cc b/services/audio/public/cpp/device_factory.cc
index e92fb2f..b6fbdb1 100644
--- a/services/audio/public/cpp/device_factory.cc
+++ b/services/audio/public/cpp/device_factory.cc
@@ -7,6 +7,7 @@
 #include <memory>
 
 #include "base/bind.h"
+#include "base/threading/platform_thread.h"
 #include "services/audio/public/cpp/input_ipc.h"
 
 namespace audio {
@@ -18,7 +19,8 @@
   std::unique_ptr<media::AudioInputIPC> ipc = std::make_unique<InputIPC>(
       std::move(connector), device_id, std::move(log));
 
-  return base::MakeRefCounted<media::AudioInputDevice>(std::move(ipc));
+  return base::MakeRefCounted<media::AudioInputDevice>(
+      std::move(ipc), base::ThreadPriority::REALTIME_AUDIO);
 }
 
 scoped_refptr<media::AudioCapturerSource> CreateInputDevice(
@@ -27,7 +29,8 @@
   std::unique_ptr<media::AudioInputIPC> ipc =
       std::make_unique<InputIPC>(std::move(connector), device_id, nullptr);
 
-  return base::MakeRefCounted<media::AudioInputDevice>(std::move(ipc));
+  return base::MakeRefCounted<media::AudioInputDevice>(
+      std::move(ipc), base::ThreadPriority::REALTIME_AUDIO);
 }
 
 }  // namespace audio
diff --git a/services/resource_coordinator/coordination_unit/process_coordination_unit_impl.cc b/services/resource_coordinator/coordination_unit/process_coordination_unit_impl.cc
index 0a6c68d..2e413f1 100644
--- a/services/resource_coordinator/coordination_unit/process_coordination_unit_impl.cc
+++ b/services/resource_coordinator/coordination_unit/process_coordination_unit_impl.cc
@@ -67,6 +67,10 @@
   SetProperty(mojom::PropertyType::kPID, pid);
 }
 
+void ProcessCoordinationUnitImpl::OnRendererIsBloated() {
+  SendEvent(mojom::Event::kRendererIsBloated);
+}
+
 const std::set<FrameCoordinationUnitImpl*>&
 ProcessCoordinationUnitImpl::GetFrameCoordinationUnits() const {
   return frame_coordination_units_;
@@ -86,6 +90,11 @@
   return page_cus;
 }
 
+void ProcessCoordinationUnitImpl::OnEventReceived(mojom::Event event) {
+  for (auto& observer : observers())
+    observer.OnProcessEventReceived(this, event);
+}
+
 void ProcessCoordinationUnitImpl::OnPropertyChanged(
     const mojom::PropertyType property_type,
     int64_t value) {
diff --git a/services/resource_coordinator/coordination_unit/process_coordination_unit_impl.h b/services/resource_coordinator/coordination_unit/process_coordination_unit_impl.h
index 73d9213..c3ba5d2 100644
--- a/services/resource_coordinator/coordination_unit/process_coordination_unit_impl.h
+++ b/services/resource_coordinator/coordination_unit/process_coordination_unit_impl.h
@@ -35,6 +35,7 @@
   void SetLaunchTime(base::Time launch_time) override;
   void SetMainThreadTaskLoadIsLow(bool main_thread_task_load_is_low) override;
   void SetPID(int64_t pid) override;
+  void OnRendererIsBloated() override;
 
   // Private implementation properties.
   void set_private_footprint_kb(uint64_t private_footprint_kb) {
@@ -54,6 +55,7 @@
   friend class FrameCoordinationUnitImpl;
 
   // CoordinationUnitInterface implementation.
+  void OnEventReceived(mojom::Event event) override;
   void OnPropertyChanged(mojom::PropertyType property_type,
                          int64_t value) override;
 
diff --git a/services/resource_coordinator/observers/page_signal_generator_impl.cc b/services/resource_coordinator/observers/page_signal_generator_impl.cc
index ba3d53e5..59971021 100644
--- a/services/resource_coordinator/observers/page_signal_generator_impl.cc
+++ b/services/resource_coordinator/observers/page_signal_generator_impl.cc
@@ -6,6 +6,7 @@
 
 #include <utility>
 
+#include "base/metrics/histogram_macros.h"
 #include "services/resource_coordinator/coordination_unit/frame_coordination_unit_impl.h"
 #include "services/resource_coordinator/coordination_unit/page_coordination_unit_impl.h"
 #include "services/resource_coordinator/coordination_unit/process_coordination_unit_impl.h"
@@ -20,6 +21,24 @@
     receiver->METHOD(__VA_ARGS__);                                \
   });
 
+namespace {
+
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused.
+enum class BloatedRendererHandlingInResourceCoordinator {
+  kForwardedToBrowser = 0,
+  kIgnoredDueToMultiplePages = 1,
+  kMaxValue = kIgnoredDueToMultiplePages
+};
+
+void RecordBloatedRendererHandling(
+    BloatedRendererHandlingInResourceCoordinator handling) {
+  UMA_HISTOGRAM_ENUMERATION("BloatedRenderer.HandlingInResourceCoordinator",
+                            handling);
+}
+
+}  // anonymous namespace
+
 // static
 constexpr base::TimeDelta PageSignalGeneratorImpl::kLoadedAndIdlingTimeout =
     base::TimeDelta::FromSeconds(1);
@@ -55,6 +74,7 @@
 // Process CUs should be observed for:
 // 1- kExpectedTaskQueueingDuration property for reporting EQT
 // 2- kMainThreadTaskLoadIsLow property changes for PageAlmostIdle detection
+// 3- kRendererIsBloated event for reloading bloated pages.
 bool PageSignalGeneratorImpl::ShouldObserve(
     const CoordinationUnitBase* coordination_unit) {
   auto cu_type = coordination_unit->id().type;
@@ -175,6 +195,26 @@
   page_data->idling_timer.Stop();
 }
 
+void PageSignalGeneratorImpl::OnProcessEventReceived(
+    const ProcessCoordinationUnitImpl* process_cu,
+    const mojom::Event event) {
+  if (event == mojom::Event::kRendererIsBloated) {
+    std::set<PageCoordinationUnitImpl*> page_cus =
+        process_cu->GetAssociatedPageCoordinationUnits();
+    // Currently bloated renderer handling supports only a single page.
+    if (page_cus.size() == 1u) {
+      auto* page_cu = *page_cus.begin();
+      DISPATCH_PAGE_SIGNAL(receivers_, NotifyRendererIsBloated, page_cu->id());
+      RecordBloatedRendererHandling(
+          BloatedRendererHandlingInResourceCoordinator::kForwardedToBrowser);
+    } else {
+      RecordBloatedRendererHandling(
+          BloatedRendererHandlingInResourceCoordinator::
+              kIgnoredDueToMultiplePages);
+    }
+  }
+}
+
 void PageSignalGeneratorImpl::BindToInterface(
     resource_coordinator::mojom::PageSignalGeneratorRequest request,
     const service_manager::BindSourceInfo& source_info) {
diff --git a/services/resource_coordinator/observers/page_signal_generator_impl.h b/services/resource_coordinator/observers/page_signal_generator_impl.h
index dfbceec..22214bc 100644
--- a/services/resource_coordinator/observers/page_signal_generator_impl.h
+++ b/services/resource_coordinator/observers/page_signal_generator_impl.h
@@ -64,6 +64,8 @@
                             const mojom::Event event) override;
   void OnPageEventReceived(const PageCoordinationUnitImpl* page_cu,
                            const mojom::Event event) override;
+  void OnProcessEventReceived(const ProcessCoordinationUnitImpl* page_cu,
+                              const mojom::Event event) override;
 
   void BindToInterface(
       resource_coordinator::mojom::PageSignalGeneratorRequest request,
diff --git a/services/resource_coordinator/observers/page_signal_generator_impl_unittest.cc b/services/resource_coordinator/observers/page_signal_generator_impl_unittest.cc
index 65c580f..49e3cac 100644
--- a/services/resource_coordinator/observers/page_signal_generator_impl_unittest.cc
+++ b/services/resource_coordinator/observers/page_signal_generator_impl_unittest.cc
@@ -7,6 +7,8 @@
 #include "base/run_loop.h"
 #include "base/test/scoped_feature_list.h"
 #include "base/test/simple_test_tick_clock.h"
+#include "mojo/public/cpp/bindings/interface_request.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
 #include "services/resource_coordinator/coordination_unit/coordination_unit_test_harness.h"
 #include "services/resource_coordinator/coordination_unit/frame_coordination_unit_impl.h"
 #include "services/resource_coordinator/coordination_unit/mock_coordination_unit_graphs.h"
@@ -18,6 +20,8 @@
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+using ::testing::_;
+
 namespace resource_coordinator {
 
 class MockPageSignalGeneratorImpl : public PageSignalGeneratorImpl {
@@ -50,6 +54,7 @@
                          mojom::LifecycleState) override {}
   MOCK_METHOD1(NotifyNonPersistentNotificationCreated,
                void(const CoordinationUnitID& page_cu_id));
+  MOCK_METHOD1(NotifyRendererIsBloated, void(const CoordinationUnitID& cu_id));
 
  private:
   mojo::Binding<mojom::PageSignalReceiver> binding_;
@@ -309,4 +314,40 @@
   ::testing::Mock::VerifyAndClear(&mock_receiver);
 }
 
+TEST_F(PageSignalGeneratorImplTest, NotifyRendererIsBloatedSinglePage) {
+  MockSinglePageInSingleProcessCoordinationUnitGraph cu_graph(
+      coordination_unit_graph());
+  auto* process = cu_graph.process.get();
+  auto* psg = page_signal_generator();
+
+  // Create a mock receiver and register it against the psg.
+  mojom::PageSignalReceiverPtr mock_receiver_ptr;
+  MockPageSignalReceiver mock_receiver(mojo::MakeRequest(&mock_receiver_ptr));
+  psg->AddReceiver(std::move(mock_receiver_ptr));
+
+  base::RunLoop run_loop;
+  EXPECT_CALL(mock_receiver, NotifyRendererIsBloated(_));
+  process->OnRendererIsBloated();
+  run_loop.RunUntilIdle();
+  ::testing::Mock::VerifyAndClear(&mock_receiver);
+}
+
+TEST_F(PageSignalGeneratorImplTest, NotifyRendererIsBloatedMultiplePages) {
+  MockMultiplePagesInSingleProcessCoordinationUnitGraph cu_graph(
+      coordination_unit_graph());
+  auto* process = cu_graph.process.get();
+  auto* psg = page_signal_generator();
+
+  // Create a mock receiver and register it against the psg.
+  mojom::PageSignalReceiverPtr mock_receiver_ptr;
+  MockPageSignalReceiver mock_receiver(mojo::MakeRequest(&mock_receiver_ptr));
+  psg->AddReceiver(std::move(mock_receiver_ptr));
+
+  base::RunLoop run_loop;
+  EXPECT_CALL(mock_receiver, NotifyRendererIsBloated(_)).Times(0);
+  process->OnRendererIsBloated();
+  run_loop.RunUntilIdle();
+  ::testing::Mock::VerifyAndClear(&mock_receiver);
+}
+
 }  // namespace resource_coordinator
diff --git a/services/resource_coordinator/public/mojom/coordination_unit.mojom b/services/resource_coordinator/public/mojom/coordination_unit.mojom
index c397eac1..1a4934b 100644
--- a/services/resource_coordinator/public/mojom/coordination_unit.mojom
+++ b/services/resource_coordinator/public/mojom/coordination_unit.mojom
@@ -108,6 +108,12 @@
   SetLaunchTime(mojo_base.mojom.Time launch_time);
   SetMainThreadTaskLoadIsLow(bool main_thread_task_load_is_low);
   SetPID(int64 pid);
+
+  // Event signals.
+
+  // Fired when one of the renderer heaps is about to exceed its limit.
+  // If nothing is done, then the renderer is likely to crash with OOM.
+  OnRendererIsBloated();
 };
 
 // There is exactly one SystemCoordinationUnit at all times.
diff --git a/services/resource_coordinator/public/mojom/page_signal.mojom b/services/resource_coordinator/public/mojom/page_signal.mojom
index 3ff1996..5555e930 100644
--- a/services/resource_coordinator/public/mojom/page_signal.mojom
+++ b/services/resource_coordinator/public/mojom/page_signal.mojom
@@ -16,6 +16,7 @@
 // PageSignalGenerator::AddReceiver.
 interface PageSignalReceiver {
   NotifyPageAlmostIdle(CoordinationUnitID page_cu_id);
+  NotifyRendererIsBloated(CoordinationUnitID page_cu_id);
   SetExpectedTaskQueueingDuration(CoordinationUnitID page_cu_id,
                                   mojo_base.mojom.TimeDelta duration);
   SetLifecycleState(CoordinationUnitID page_cu_id,
diff --git a/services/resource_coordinator/public/mojom/signals.mojom b/services/resource_coordinator/public/mojom/signals.mojom
index 84519658..f7a1baa 100644
--- a/services/resource_coordinator/public/mojom/signals.mojom
+++ b/services/resource_coordinator/public/mojom/signals.mojom
@@ -17,6 +17,8 @@
   // This signal is sent to a SystemCU when all ProcessCU CPU usage estimates
   // have been updated and are coherent.
   kProcessCPUUsageReady,
+  // This signal is set to the renderer ProcessCU.
+  kRendererIsBloated,
 };
 
 // Defines the Storage property keys that can be get/set on the
diff --git a/services/viz/privileged/interfaces/gl/gpu_service.mojom b/services/viz/privileged/interfaces/gl/gpu_service.mojom
index a57810b..d480ac96 100644
--- a/services/viz/privileged/interfaces/gl/gpu_service.mojom
+++ b/services/viz/privileged/interfaces/gl/gpu_service.mojom
@@ -106,6 +106,15 @@
   // Called by the browser immediately after the application is foregrounded.
   OnForegrounded();
 
+  // Begin a batch of layer tree changes.
+  [EnableIf=is_mac]
+  BeginCATransaction();
+
+  // Commit a batch of layer tree changes atomically. Returns after the commit
+  // completes.
+  [EnableIf=is_mac]
+  CommitCATransaction() => ();
+
   Crash();
   Hang();
   ThrowJavaException();
diff --git a/testing/buildbot/chromium.clang.json b/testing/buildbot/chromium.clang.json
index 4a2fa34..e36b030 100644
--- a/testing/buildbot/chromium.clang.json
+++ b/testing/buildbot/chromium.clang.json
@@ -410,6 +410,18 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
+        "test": "headless_browsertests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "headless_unittests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
         "test": "interactive_ui_tests"
       },
       {
@@ -503,12 +515,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "mojo_core_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "mojo_unittests"
       },
       {
@@ -1108,6 +1114,18 @@
       },
       {
         "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "headless_browsertests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "headless_unittests"
+      },
+      {
+        "swarming": {
           "can_use_on_swarming_builders": true,
           "shards": 2
         },
@@ -1204,12 +1222,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "mojo_core_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "mojo_unittests"
       },
       {
@@ -12155,6 +12167,18 @@
       },
       {
         "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "headless_browsertests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "headless_unittests"
+      },
+      {
+        "swarming": {
           "can_use_on_swarming_builders": true,
           "shards": 2
         },
@@ -13531,6 +13555,18 @@
       },
       {
         "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "headless_browsertests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "headless_unittests"
+      },
+      {
+        "swarming": {
           "can_use_on_swarming_builders": true,
           "shards": 2
         },
@@ -14211,6 +14247,18 @@
       },
       {
         "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "headless_browsertests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "headless_unittests"
+      },
+      {
+        "swarming": {
           "can_use_on_swarming_builders": true,
           "shards": 2
         },
@@ -14890,6 +14938,18 @@
         "test": "gpu_unittests"
       },
       {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "headless_browsertests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "headless_unittests"
+      },
+      {
         "args": [
           "--enable-features=NetworkService"
         ],
@@ -22276,6 +22336,18 @@
         "test": "gpu_unittests"
       },
       {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "headless_browsertests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "headless_unittests"
+      },
+      {
         "args": [
           "--enable-features=NetworkService"
         ],
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index 2f530f6..2bc8d53 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -323,2264 +323,6 @@
       }
     ]
   },
-  "CFI Linux (icall)": {
-    "gtest_tests": [
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "accessibility_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "angle_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "app_shell_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "aura_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "base_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "battor_agent_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "blink_common_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "blink_heap_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "blink_platform_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "boringssl_crypto_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "boringssl_ssl_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 10
-        },
-        "test": "browser_tests"
-      },
-      {
-        "args": [
-          "--enable-features=NetworkService",
-          "--test-launcher-filter-file=../../testing/buildbot/filters/mojo.fyi.network_browser_tests.filter"
-        ],
-        "name": "network_service_browser_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 10
-        },
-        "test": "browser_tests"
-      },
-      {
-        "args": [
-          "--disable-site-isolation-trials"
-        ],
-        "name": "not_site_per_process_browser_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 10
-        },
-        "test": "browser_tests"
-      },
-      {
-        "args": [
-          "--enable-features=VizDisplayCompositor",
-          "--test-launcher-filter-file=../../testing/buildbot/filters/viz.browser_tests.filter"
-        ],
-        "name": "viz_browser_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 10
-        },
-        "test": "browser_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "cacheinvalidation_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "capture_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "cast_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "cc_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "chrome_app_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "chromedriver_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "components_browsertests"
-      },
-      {
-        "args": [
-          "--enable-features=NetworkService"
-        ],
-        "name": "network_service_components_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "components_browsertests"
-      },
-      {
-        "args": [
-          "--site-per-process"
-        ],
-        "name": "site_per_process_components_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "components_browsertests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "components_unittests"
-      },
-      {
-        "args": [
-          "--site-per-process"
-        ],
-        "name": "site_per_process_components_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "components_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "compositor_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "content_browsertests"
-      },
-      {
-        "args": [
-          "--enable-features=NetworkService",
-          "--test-launcher-filter-file=../../testing/buildbot/filters/mojo.fyi.network_content_browsertests.filter"
-        ],
-        "name": "network_service_content_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "content_browsertests"
-      },
-      {
-        "args": [
-          "--site-per-process",
-          "--test-launcher-filter-file=../../testing/buildbot/filters/site-per-process.content_browsertests.filter"
-        ],
-        "name": "site_per_process_content_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "content_browsertests"
-      },
-      {
-        "args": [
-          "--enable-features=VizDisplayCompositor",
-          "--test-launcher-filter-file=../../testing/buildbot/filters/viz.content_browsertests.filter"
-        ],
-        "name": "viz_content_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 2
-        },
-        "test": "content_browsertests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "content_unittests"
-      },
-      {
-        "args": [
-          "--site-per-process"
-        ],
-        "name": "site_per_process_content_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "content_unittests"
-      },
-      {
-        "args": [
-          "--enable-features=VizDisplayCompositor",
-          "--test-launcher-filter-file=../../testing/buildbot/filters/viz.content_unittests.filter"
-        ],
-        "name": "viz_content_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "content_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "cronet_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "cronet_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "crypto_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "dbus_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "device_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "display_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "events_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "extensions_browsertests"
-      },
-      {
-        "args": [
-          "--enable-features=NetworkService"
-        ],
-        "name": "network_service_extensions_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "extensions_browsertests"
-      },
-      {
-        "args": [
-          "--site-per-process"
-        ],
-        "name": "site_per_process_extensions_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "extensions_browsertests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "extensions_unittests"
-      },
-      {
-        "args": [
-          "--site-per-process"
-        ],
-        "name": "site_per_process_extensions_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "extensions_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "filesystem_service_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gcm_unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gfx_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gin_unittests"
-      },
-      {
-        "args": [
-          "--use-gpu-in-tests",
-          "--no-xvfb"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "10de:1cb3",
-              "os": "Ubuntu",
-              "pool": "Chrome-GPU"
-            }
-          ]
-        },
-        "test": "gl_unittests",
-        "use_xvfb": false
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gn_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "google_apis_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gpu_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "interactive_ui_tests"
-      },
-      {
-        "args": [
-          "--enable-features=NetworkService"
-        ],
-        "name": "network_service_interactive_ui_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 2
-        },
-        "test": "interactive_ui_tests"
-      },
-      {
-        "args": [
-          "--disable-site-isolation-trials"
-        ],
-        "name": "not_site_per_process_interactive_ui_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "interactive_ui_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ipc_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "jingle_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "keyboard_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "latency_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "leveldb_service_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "libjingle_xmpp_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "media_blink_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "media_service_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "media_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "message_center_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "midi_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "mojo_core_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "mojo_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "nacl_helper_nonsfi_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "nacl_loader_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "native_theme_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "net_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "pdf_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ppapi_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "printing_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "remoting_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sandbox_linux_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "service_manager_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "services_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "skia_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "snapshot_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sql_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "storage_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sync_integration_tests"
-      },
-      {
-        "args": [
-          "--disable-site-isolation-trials"
-        ],
-        "name": "not_site_per_process_sync_integration_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sync_integration_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "traffic_annotation_auditor_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ui_base_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ui_touch_selection_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "unit_tests"
-      },
-      {
-        "args": [
-          "--disable-site-isolation-trials"
-        ],
-        "name": "not_site_per_process_unit_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "url_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "views_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "viz_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "vr_common_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "vr_pixeltests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "webkit_unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "wm_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "wtf_unittests"
-      }
-    ]
-  },
-  "CFI Linux ToT": {
-    "gtest_tests": [
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "accessibility_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "angle_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "app_shell_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "aura_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "base_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "battor_agent_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "blink_common_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "blink_heap_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "blink_platform_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "boringssl_crypto_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "boringssl_ssl_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 10
-        },
-        "test": "browser_tests"
-      },
-      {
-        "args": [
-          "--enable-features=NetworkService",
-          "--test-launcher-filter-file=../../testing/buildbot/filters/mojo.fyi.network_browser_tests.filter"
-        ],
-        "name": "network_service_browser_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 10
-        },
-        "test": "browser_tests"
-      },
-      {
-        "args": [
-          "--disable-site-isolation-trials"
-        ],
-        "name": "not_site_per_process_browser_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 10
-        },
-        "test": "browser_tests"
-      },
-      {
-        "args": [
-          "--enable-features=VizDisplayCompositor",
-          "--test-launcher-filter-file=../../testing/buildbot/filters/viz.browser_tests.filter"
-        ],
-        "name": "viz_browser_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 10
-        },
-        "test": "browser_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "cacheinvalidation_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "capture_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "cast_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "cc_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "chrome_app_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "chromedriver_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "components_browsertests"
-      },
-      {
-        "args": [
-          "--enable-features=NetworkService"
-        ],
-        "name": "network_service_components_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "components_browsertests"
-      },
-      {
-        "args": [
-          "--site-per-process"
-        ],
-        "name": "site_per_process_components_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "components_browsertests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "components_unittests"
-      },
-      {
-        "args": [
-          "--site-per-process"
-        ],
-        "name": "site_per_process_components_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "components_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "compositor_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "content_browsertests"
-      },
-      {
-        "args": [
-          "--enable-features=NetworkService",
-          "--test-launcher-filter-file=../../testing/buildbot/filters/mojo.fyi.network_content_browsertests.filter"
-        ],
-        "name": "network_service_content_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "content_browsertests"
-      },
-      {
-        "args": [
-          "--site-per-process",
-          "--test-launcher-filter-file=../../testing/buildbot/filters/site-per-process.content_browsertests.filter"
-        ],
-        "name": "site_per_process_content_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "content_browsertests"
-      },
-      {
-        "args": [
-          "--enable-features=VizDisplayCompositor",
-          "--test-launcher-filter-file=../../testing/buildbot/filters/viz.content_browsertests.filter"
-        ],
-        "name": "viz_content_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 2
-        },
-        "test": "content_browsertests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "content_unittests"
-      },
-      {
-        "args": [
-          "--site-per-process"
-        ],
-        "name": "site_per_process_content_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "content_unittests"
-      },
-      {
-        "args": [
-          "--enable-features=VizDisplayCompositor",
-          "--test-launcher-filter-file=../../testing/buildbot/filters/viz.content_unittests.filter"
-        ],
-        "name": "viz_content_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "content_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "cronet_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "cronet_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "crypto_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "dbus_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "device_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "display_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "events_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "extensions_browsertests"
-      },
-      {
-        "args": [
-          "--enable-features=NetworkService"
-        ],
-        "name": "network_service_extensions_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "extensions_browsertests"
-      },
-      {
-        "args": [
-          "--site-per-process"
-        ],
-        "name": "site_per_process_extensions_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "extensions_browsertests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "extensions_unittests"
-      },
-      {
-        "args": [
-          "--site-per-process"
-        ],
-        "name": "site_per_process_extensions_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "extensions_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "filesystem_service_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gcm_unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gfx_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gin_unittests"
-      },
-      {
-        "args": [
-          "--use-gpu-in-tests",
-          "--no-xvfb"
-        ],
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "gpu": "10de:1cb3",
-              "os": "Ubuntu",
-              "pool": "Chrome-GPU"
-            }
-          ]
-        },
-        "test": "gl_unittests",
-        "use_xvfb": false
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gn_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "google_apis_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gpu_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 2
-        },
-        "test": "interactive_ui_tests"
-      },
-      {
-        "args": [
-          "--enable-features=NetworkService"
-        ],
-        "name": "network_service_interactive_ui_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 2
-        },
-        "test": "interactive_ui_tests"
-      },
-      {
-        "args": [
-          "--disable-site-isolation-trials"
-        ],
-        "name": "not_site_per_process_interactive_ui_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "interactive_ui_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ipc_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "jingle_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "keyboard_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "latency_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "leveldb_service_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "libjingle_xmpp_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "media_blink_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "media_service_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "media_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "message_center_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "midi_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "mojo_core_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "mojo_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "nacl_helper_nonsfi_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "nacl_loader_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "native_theme_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "net_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "pdf_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ppapi_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "printing_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "remoting_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sandbox_linux_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "service_manager_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "services_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "skia_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "snapshot_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sql_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "storage_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sync_integration_tests"
-      },
-      {
-        "args": [
-          "--disable-site-isolation-trials"
-        ],
-        "name": "not_site_per_process_sync_integration_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sync_integration_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "traffic_annotation_auditor_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ui_base_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ui_touch_selection_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "unit_tests"
-      },
-      {
-        "args": [
-          "--disable-site-isolation-trials"
-        ],
-        "name": "not_site_per_process_unit_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "url_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "views_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "viz_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "vr_common_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "vr_pixeltests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "webkit_unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "wm_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "wtf_unittests"
-      }
-    ]
-  },
-  "Chromium Mac 10.11": {
-    "gtest_tests": [
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "accessibility_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "app_shell_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "base_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "battor_agent_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "blink_common_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "blink_heap_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "blink_platform_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "boringssl_crypto_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "boringssl_ssl_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "browser_tests"
-      },
-      {
-        "args": [
-          "--enable-surface-synchronization"
-        ],
-        "name": "surface_sync_browser_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "browser_tests"
-      },
-      {
-        "args": [
-          "--enable-features=VizDisplayCompositor",
-          "--test-launcher-filter-file=../../testing/buildbot/filters/viz.browser_tests.filter"
-        ],
-        "name": "viz_browser_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "browser_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "cacheinvalidation_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "capture_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "cast_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "cc_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "chromedriver_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "components_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "content_browsertests"
-      },
-      {
-        "args": [
-          "--enable-surface-synchronization"
-        ],
-        "name": "surface_sync_content_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "content_browsertests"
-      },
-      {
-        "args": [
-          "--enable-features=VizDisplayCompositor",
-          "--test-launcher-filter-file=../../testing/buildbot/filters/viz.content_browsertests.filter"
-        ],
-        "name": "viz_content_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "content_browsertests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "content_unittests"
-      },
-      {
-        "args": [
-          "--enable-features=VizDisplayCompositor",
-          "--test-launcher-filter-file=../../testing/buildbot/filters/viz.content_unittests.filter"
-        ],
-        "name": "viz_content_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "content_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "crashpad_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "cronet_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "cronet_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "crypto_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "display_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "extensions_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "gcm_unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "gfx_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "google_apis_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "gpu_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "interactive_ui_tests"
-      },
-      {
-        "args": [
-          "--enable-features=VizDisplayCompositor"
-        ],
-        "name": "viz_interactive_ui_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "interactive_ui_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "ipc_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "jingle_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "libjingle_xmpp_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "media_blink_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "media_service_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "media_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "midi_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "mojo_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "native_theme_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "net_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "pdf_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "ppapi_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "printing_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "remoting_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "sandbox_mac_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "service_manager_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "skia_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "sql_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "storage_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "sync_integration_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "ui_base_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "url_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "views_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "viz_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "webkit_unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "wtf_unittests"
-      }
-    ],
-    "isolated_scripts": [
-      {
-        "args": [
-          "--test-type=integration"
-        ],
-        "isolate_name": "chromedriver_py_tests",
-        "name": "chromedriver_py_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        }
-      },
-      {
-        "isolate_name": "components_perftests",
-        "name": "components_perftests",
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        }
-      },
-      {
-        "isolate_name": "telemetry_gpu_unittests",
-        "name": "telemetry_gpu_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        }
-      },
-      {
-        "isolate_name": "telemetry_perf_unittests",
-        "name": "telemetry_perf_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        }
-      },
-      {
-        "args": [
-          "--jobs=1"
-        ],
-        "isolate_name": "telemetry_unittests",
-        "name": "telemetry_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        }
-      },
-      {
-        "isolate_name": "views_perftests",
-        "name": "views_perftests",
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        }
-      },
-      {
-        "isolate_name": "webkit_python_tests",
-        "name": "webkit_python_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        }
-      }
-    ]
-  },
-  "Chromium Mac 10.11 Force Mac Toolchain": {
-    "gtest_tests": [
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "accessibility_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "app_shell_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "base_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "battor_agent_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "blink_common_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "blink_heap_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "blink_platform_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "boringssl_crypto_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "boringssl_ssl_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "browser_tests"
-      },
-      {
-        "args": [
-          "--enable-surface-synchronization"
-        ],
-        "name": "surface_sync_browser_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "browser_tests"
-      },
-      {
-        "args": [
-          "--enable-features=VizDisplayCompositor",
-          "--test-launcher-filter-file=../../testing/buildbot/filters/viz.browser_tests.filter"
-        ],
-        "name": "viz_browser_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "browser_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "cacheinvalidation_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "capture_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "cast_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "cc_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "chromedriver_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "components_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "content_browsertests"
-      },
-      {
-        "args": [
-          "--enable-surface-synchronization"
-        ],
-        "name": "surface_sync_content_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "content_browsertests"
-      },
-      {
-        "args": [
-          "--enable-features=VizDisplayCompositor",
-          "--test-launcher-filter-file=../../testing/buildbot/filters/viz.content_browsertests.filter"
-        ],
-        "name": "viz_content_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "content_browsertests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "content_unittests"
-      },
-      {
-        "args": [
-          "--enable-features=VizDisplayCompositor",
-          "--test-launcher-filter-file=../../testing/buildbot/filters/viz.content_unittests.filter"
-        ],
-        "name": "viz_content_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "content_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "crashpad_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "cronet_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "cronet_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "crypto_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "extensions_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "gcm_unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "gfx_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "google_apis_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "gpu_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "interactive_ui_tests"
-      },
-      {
-        "args": [
-          "--enable-features=VizDisplayCompositor"
-        ],
-        "name": "viz_interactive_ui_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "interactive_ui_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "ipc_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "jingle_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "libjingle_xmpp_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "media_blink_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "media_service_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "media_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "midi_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "mojo_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "native_theme_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "net_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "pdf_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "ppapi_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "printing_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "remoting_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "sandbox_mac_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "service_manager_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "skia_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "sql_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "storage_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "sync_integration_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "ui_base_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "url_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "views_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "viz_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "webkit_unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": false
-        },
-        "test": "wtf_unittests"
-      }
-    ]
-  },
   "Chromium Mac 10.13": {
     "gtest_tests": [
       {
@@ -3066,547 +808,6 @@
       }
     ]
   },
-  "Chromium Win 10 GCE Tests": {
-    "gtest_tests": [
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "accessibility_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "angle_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "app_shell_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "aura_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "base_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "battor_agent_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "blink_common_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "blink_heap_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "blink_platform_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "boringssl_crypto_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "boringssl_ssl_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 10
-        },
-        "test": "browser_tests"
-      },
-      {
-        "args": [
-          "--enable-features=VizDisplayCompositor",
-          "--test-launcher-filter-file=../../testing/buildbot/filters/viz.browser_tests.filter"
-        ],
-        "name": "viz_browser_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 10
-        },
-        "test": "browser_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "cacheinvalidation_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "capture_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "cast_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "cc_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "chrome_app_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "chrome_cleaner_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "chrome_elf_import_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "chrome_elf_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "chromedriver_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "components_browsertests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "components_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "compositor_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "content_browsertests"
-      },
-      {
-        "args": [
-          "--enable-features=VizDisplayCompositor",
-          "--test-launcher-filter-file=../../testing/buildbot/filters/viz.content_browsertests.filter"
-        ],
-        "name": "viz_content_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 2
-        },
-        "test": "content_browsertests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "content_unittests"
-      },
-      {
-        "args": [
-          "--enable-features=VizDisplayCompositor",
-          "--test-launcher-filter-file=../../testing/buildbot/filters/viz.content_unittests.filter"
-        ],
-        "name": "viz_content_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "content_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "courgette_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "cronet_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "cronet_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "crypto_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "device_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "display_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "elevation_service_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "events_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "extensions_browsertests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "extensions_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gcm_unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gfx_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gn_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "google_apis_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "gpu_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "headless_browsertests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "headless_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "install_static_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "integrity": "high"
-            }
-          ]
-        },
-        "test": "installer_util_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ipc_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "jingle_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "keyboard_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "latency_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "libjingle_xmpp_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "media_blink_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "media_service_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "media_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "message_center_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "midi_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "mojo_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "nacl_loader_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "native_theme_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "net_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "notification_helper_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "pdf_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ppapi_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "printing_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "remoting_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "integrity": "high"
-            }
-          ]
-        },
-        "test": "sbox_integration_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sbox_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sbox_validation_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "services_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "integrity": "high"
-            }
-          ]
-        },
-        "test": "setup_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "skia_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sql_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "storage_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "sync_integration_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ui_base_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "ui_touch_selection_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "url_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "views_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "webkit_unit_tests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "wm_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "wtf_unittests"
-      }
-    ]
-  },
   "Dummy WebKit Mac10.13": {
     "isolated_scripts": [
       {
@@ -5847,6 +3048,18 @@
       },
       {
         "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "headless_browsertests"
+      },
+      {
+        "swarming": {
+          "can_use_on_swarming_builders": true
+        },
+        "test": "headless_unittests"
+      },
+      {
+        "swarming": {
           "can_use_on_swarming_builders": true,
           "shards": 2
         },
diff --git a/testing/buildbot/chromium.lkgr.json b/testing/buildbot/chromium.lkgr.json
index 2f27f02..a4bc7d6 100644
--- a/testing/buildbot/chromium.lkgr.json
+++ b/testing/buildbot/chromium.lkgr.json
@@ -6,27 +6,27 @@
       "chromium_builder_asan"
     ]
   },
-  "ASAN Debug (32-bit x86 with V8-ARM)": {
-    "additional_compile_targets": [
-      "chromium_builder_asan"
-    ]
-  },
   "ASAN Release": {
     "additional_compile_targets": [
       "chromium_builder_asan"
     ]
   },
-  "ASAN Release (32-bit x86 with V8-ARM)": {
-    "additional_compile_targets": [
-      "chromium_builder_asan"
-    ]
-  },
   "ASAN Release Media": {
     "additional_compile_targets": [
       "chromium_builder_asan"
     ]
   },
-  "ASAN Release Media (32-bit x86 with V8-ARM)": {
+  "ASan Debug (32-bit x86 with V8-ARM)": {
+    "additional_compile_targets": [
+      "chromium_builder_asan"
+    ]
+  },
+  "ASan Release (32-bit x86 with V8-ARM)": {
+    "additional_compile_targets": [
+      "chromium_builder_asan"
+    ]
+  },
+  "ASan Release Media (32-bit x86 with V8-ARM)": {
     "additional_compile_targets": [
       "chromium_builder_asan"
     ]
@@ -46,17 +46,17 @@
       "chromium_builder_asan"
     ]
   },
-  "Mac ASan Debug": {
+  "Mac ASAN Debug": {
     "additional_compile_targets": [
       "chromium_builder_asan"
     ]
   },
-  "Mac ASan Release": {
+  "Mac ASAN Release": {
     "additional_compile_targets": [
       "chromium_builder_asan"
     ]
   },
-  "Mac ASan Release Media": {
+  "Mac ASAN Release Media": {
     "additional_compile_targets": [
       "chromium_builder_asan"
     ]
diff --git a/testing/buildbot/chromium.memory.json b/testing/buildbot/chromium.memory.json
index 6d260e2..228c512 100644
--- a/testing/buildbot/chromium.memory.json
+++ b/testing/buildbot/chromium.memory.json
@@ -3751,12 +3751,6 @@
         "swarming": {
           "can_use_on_swarming_builders": true
         },
-        "test": "mojo_core_unittests"
-      },
-      {
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
         "test": "mojo_unittests"
       },
       {
diff --git a/testing/buildbot/generate_buildbot_json.py b/testing/buildbot/generate_buildbot_json.py
index 9090bae..e47cb18 100755
--- a/testing/buildbot/generate_buildbot_json.py
+++ b/testing/buildbot/generate_buildbot_json.py
@@ -784,6 +784,15 @@
       'Optional Win10 Release (Intel HD 630)',
       'Optional Win10 Release (NVIDIA)',
       'Win7 ANGLE Tryserver (AMD)',
+      # chromium.android.fyi
+      'Unswarmed N5 Tests Dummy Builder',
+      'Unswarmed N5X Tests Dummy Builder',
+      # chromium.fyi
+      'chromeos-amd64-generic-rel-vm-tests',
+      'Dummy WebKit Mac10.13',
+      'WebKit Linux layout_ng Dummy Builder',
+      'WebKit Linux root_layer_scrolls Dummy Builder',
+      'WebKit Linux slimming_paint_v2 Dummy Builder',
     ]
 
   def check_input_file_consistency(self):
@@ -798,9 +807,7 @@
         if bot_name in bots_that_dont_exist:
           continue  # pragma: no cover
         if bot_name not in bot_names:
-          if waterfall['name'] in ['chromium.android.fyi', 'chromium.fyi',
-                                   'chromium.lkgr', 'client.v8.chromium',
-                                   'client.v8.fyi']:
+          if waterfall['name'] in ['client.v8.chromium', 'client.v8.fyi']:
             # TODO(thakis): Remove this once these bots move to luci.
             continue  # pragma: no cover
           if waterfall['name'] in ['tryserver.webrtc']:
diff --git a/testing/buildbot/gn_isolate_map.pyl b/testing/buildbot/gn_isolate_map.pyl
index ab38fbf1..0109f63 100644
--- a/testing/buildbot/gn_isolate_map.pyl
+++ b/testing/buildbot/gn_isolate_map.pyl
@@ -287,10 +287,6 @@
     "label": "//chrome/test:chrome_app_unittests",
     "type": "console_test_launcher",
   },
-  "chrome_cleaner_unittests": {
-    "label": "//chrome/chrome_cleaner:chrome_cleaner_unittests",
-    "type": "console_test_launcher",
-  },
   "chrome_elf_import_unittests": {
     "label": "//chrome_elf:chrome_elf_import_unittests",
     "type": "raw",
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl
index 7e63f1d..a64c342 100644
--- a/testing/buildbot/test_suite_exceptions.pyl
+++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -70,8 +70,6 @@
     'remove_from': [
       # chromium.fyi
       'mac-views-rel',
-      'Chromium Mac 10.11',
-      'Chromium Mac 10.11 Force Mac Toolchain',
       'Chromium Mac 10.13',
       # chromium.gpu and chromium.gpu.fyi
       # On Android, these are already run on the main waterfall.
@@ -367,8 +365,6 @@
     'remove_from': [
       # chromium.fyi
       'mac-views-rel',
-      'Chromium Mac 10.11',
-      'Chromium Mac 10.11 Force Mac Toolchain',
       'Chromium Mac 10.13',
       'Out of Process Profiling Mac',
     ],
@@ -615,8 +611,6 @@
       'linux-chromeos-rel',
       # chromium.fyi
       'mac-views-rel',
-      'Chromium Mac 10.11',
-      'Chromium Mac 10.11 Force Mac Toolchain',
       'Chromium Mac 10.13',
       'Out of Process Profiling Linux',
       'Out of Process Profiling Mac',
@@ -883,7 +877,6 @@
   'content_shell_crash_test': {
     'remove_from': [
       # chromium.fyi
-      'Chromium Mac 10.11',
       'Chromium Mac 10.13',
       'Out of Process Profiling Mac',
       # On chromium.linux, unclear why these only run on "Linux Tests".
@@ -1066,8 +1059,6 @@
     'remove_from': [
       # chromium.clang
       'linux-win_cross-rel', # https://crbug.com/762167
-      # chromium.fyi
-      'Chromium Win 10 GCE Tests',
     ],
   },
   'cronet_test_instrumentation_apk': {
@@ -1096,8 +1087,6 @@
     'remove_from': [
       # chromium.fyi
       'mac-views-rel',
-      'Chromium Mac 10.11',
-      'Chromium Mac 10.11 Force Mac Toolchain',
       'Chromium Mac 10.13',
       'Out of Process Profiling Mac',
       # chromium.win
@@ -1143,7 +1132,6 @@
     'remove_from': [
       # chromium.fyi, unclear why these aren't run.
       'mac-views-rel',
-      'Chromium Mac 10.11 Force Mac Toolchain',
       # chromium.win
       'Win7 Tests (dbg)(1)',
     ],
@@ -1171,8 +1159,6 @@
     'remove_from': [
       # chromium.fyi
       'mac-views-rel',
-      'Chromium Mac 10.11',
-      'Chromium Mac 10.11 Force Mac Toolchain',
       'Chromium Mac 10.13',
       'Out of Process Profiling Linux',
       'Out of Process Profiling Mac',
@@ -1204,10 +1190,7 @@
       'ToTLinuxASan',  # https://crbug.com/831667
       # chromium.fyi
       'mac-views-rel',
-      'Chromium Mac 10.11',
-      'Chromium Mac 10.11 Force Mac Toolchain',
       'Chromium Mac 10.13',
-      'Chromium Win 10 GCE Tests',
       'Out of Process Profiling Linux',
       'Out of Process Profiling Mac',
       # On chromium.linux, unclear why these aren't run on Cast.
@@ -1426,8 +1409,6 @@
     'remove_from': [
       # chromium.fyi
       'mac-views-rel',
-      'Chromium Mac 10.11',
-      'Chromium Mac 10.11 Force Mac Toolchain',
       'Chromium Mac 10.13',
       'Out of Process Profiling Linux',
       'Out of Process Profiling Mac',
@@ -1435,6 +1416,9 @@
   },
   'headless_browsertests': {
     'remove_from': [
+      # chromium.clang
+      'ToTLinuxASan',  # https://crbug.com/843732
+      # chromium.linux
       'Linux Tests (dbg)(1)(32)',
       # On chromium.mac, unclear why these aren't run on "Mac10.11 Tests".
       'Mac10.11 Tests',
@@ -1446,6 +1430,9 @@
   },
   'headless_unittests': {
     'remove_from': [
+      # chromium.clang
+      'ToTLinuxASan',  # https://crbug.com/843732
+      # chromium.linux
       'Linux Tests (dbg)(1)(32)',
       # On chromium.mac, unclear why these aren't run on "Mac10.11 Tests".
       'Mac10.11 Tests',
@@ -1479,8 +1466,6 @@
       # chromium.clang
       'ToTLinuxUBSanVptr',
       'UBSanVptr Linux',
-      # chromium.fyi
-      'Chromium Win 10 GCE Tests',
       # chromium.memory
       'Linux TSan Tests',
     ],
@@ -1658,8 +1643,6 @@
     'remove_from': [
       # chromium.fyi
       'mac-views-rel',
-      'Chromium Mac 10.11',
-      'Chromium Mac 10.11 Force Mac Toolchain',
       'Chromium Mac 10.13',
       'Out of Process Profiling Mac',
     ],
@@ -1698,8 +1681,6 @@
 
       # chromium.fyi
       'mac-views-rel',
-      'Chromium Mac 10.11',
-      'Chromium Mac 10.11 Force Mac Toolchain',
       'Chromium Mac 10.13',
       'Out of Process Profiling Mac',
 
@@ -1714,7 +1695,6 @@
   'metrics_python_tests': {
     'remove_from': [
       # chromium.fyi
-      'Chromium Mac 10.11',
       'Chromium Mac 10.13',
       'Out of Process Profiling Mac',
     ],
@@ -1725,6 +1705,15 @@
       'linux-win_cross-rel',  # https://crbug.com/799827
     ],
   },
+  'mojo_core_unittests': {
+    'remove_from': [
+      # chromium.clang
+      'CFI Linux (icall)',  # https://crbug.com/850464
+      'CFI Linux ToT',  # https://crbug.com/850464
+      # chromium.memory
+      'Linux CFI',  # https://crbug.com/850464
+    ],
+  },
   'mojo_test_apk': {
     'modifications': {
       # chromium.clang
@@ -1751,8 +1740,6 @@
     'remove_from': [
       # chromium.fyi
       'mac-views-rel',
-      'Chromium Mac 10.11',
-      'Chromium Mac 10.11 Force Mac Toolchain',
       'Chromium Mac 10.13',
       'Out of Process Profiling Mac',
       # chromium.clang
@@ -1893,8 +1880,6 @@
       # chromium.chromiumos
       'linux-chromeos-dbg',
       'linux-chromeos-rel',
-      # chromium.fyi
-      'Chromium Win 10 GCE Tests',
       # chromium.linux
       'Cast Audio Linux',
       'Cast Linux',
@@ -1920,8 +1905,6 @@
       'Mac Pro FYI Release (AMD)',
       # chromium.fyi
       'mac-views-rel',
-      'Chromium Mac 10.11',
-      'Chromium Mac 10.11 Force Mac Toolchain',
       'Chromium Mac 10.13',
       'Win 10 Fast Ring',
       # On chromium.linux, unclear why these aren't run on Cast.
@@ -2064,8 +2047,6 @@
       'linux-chromeos-rel',
       # chromium.fyi
       'mac-views-rel',
-      'Chromium Mac 10.11',
-      'Chromium Mac 10.11 Force Mac Toolchain',
       'Chromium Mac 10.13',
       'Out of Process Profiling Mac',
       # On chromium.win, unclear why these aren't run.
@@ -2515,7 +2496,6 @@
   'viz_unittests': {
     'remove_from': [
       # chromium.fyi
-      'Chromium Win 10 GCE Tests',
       'Out of Process Profiling Android',
       'Out of Process Profiling Linux',
       # chromium.win
@@ -2546,8 +2526,6 @@
   },
   'vr_common_unittests': {
     'remove_from': [
-      # chromium.fyi
-      'Chromium Win 10 GCE Tests',
       'Out of Process Profiling Android',
       # chromium.win
       'Win 7 Tests x64 (1)',
@@ -2591,7 +2569,6 @@
   'vr_pixeltests': {
     'remove_from': [
       # chromium.fyi
-      'Chromium Win 10 GCE Tests',
       'Out of Process Profiling Android',
       'VR Linux',
       # chromium.win
@@ -2657,7 +2634,6 @@
   'webkit_layout_tests': {
     'remove_from': [
       # chromium.fyi
-      'Chromium Mac 10.11',
       'Out of Process Profiling Mac',
       # chromium.linux
       'Linux Tests (dbg)(1)',
@@ -3029,8 +3005,6 @@
   },
   'zucchini_unittests': {
     'remove_from': [
-      # chromium.fyi
-      'Chromium Win 10 GCE Tests',
       # chromium.win
       'Win10 Tests x64',
     ],
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl
index abad025..4066612 100644
--- a/testing/buildbot/test_suites.pyl
+++ b/testing/buildbot/test_suites.pyl
@@ -337,10 +337,6 @@
     },
   },
 
-  'chrome_cleaner_gtests': {
-    'chrome_cleaner_unittests': {}
-  },
-
   'chromedriver_py_tests_isolated_scripts': {
     'chromedriver_py_tests': {
       "args": [
@@ -618,7 +614,7 @@
       }
     },
   },
-  'clang_gl_gtests': {
+  'gl_gtests': {
     'gl_tests': {},
     'gl_unittests': {},
   },
@@ -1929,6 +1925,8 @@
     'gn_unittests': {},
   },
 
+  # TODO(thakis): merge with non_android_and_cast_and_chromeos_chromium_gtests
+  # once https://crbug.com/844865 is resolved.
   'non_android_and_cast_and_chromeos_and_clang_and_mac_fyi_chromium_gtests': {
     'headless_browsertests': {},
     'headless_unittests': {},
@@ -2400,7 +2398,9 @@
     'linux_flavor_specific_chromium_gtests',
   ],
 
-  'chromium_linux_clang_gtests': [
+  # gl_tests requires dedicated slaves with GPUs on linux, so have a separate
+  # test list with gl_tests included. This is chromium_linux_gtests + gl_gtests.
+  'chromium_linux_and_gl_gtests': [
     'aura_gtests',
     'chromium_gtests',
     'chromium_gtests_for_devices_with_graphical_output',
@@ -2411,30 +2411,13 @@
     'network_service_gtests',
     'non_android_chromium_gtests',
     'non_android_and_cast_and_chromeos_chromium_gtests',
+    'non_android_and_cast_and_chromeos_and_clang_and_mac_fyi_chromium_gtests',
     'non_mac_chromium_gtests',
     'site_isolation_chromium_gtests',
     'site_isolation_chromium_linux_gtests',
     'viz_gtests',
     'vr_platform_specific_chromium_gtests',
-  ],
-
-  'chromium_linux_clang_and_gl_gtests': [
-    'aura_gtests',
-    'chromium_gtests',
-    'chromium_gtests_for_devices_with_graphical_output',
-    'chromium_gtests_for_linux_and_chromeos_only',
-    'linux_and_mac_specific_chromium_gtests',
-    'clang_gl_gtests',
-    'linux_flavor_specific_chromium_gtests',
-    'linux_specific_chromium_gtests',
-    'network_service_gtests',
-    'non_android_chromium_gtests',
-    'non_android_and_cast_and_chromeos_chromium_gtests',
-    'non_mac_chromium_gtests',
-    'site_isolation_chromium_gtests',
-    'site_isolation_chromium_linux_gtests',
-    'viz_gtests',
-    'vr_platform_specific_chromium_gtests',
+    'gl_gtests',
   ],
 
   'chromium_linux_gtests': [
@@ -2544,7 +2527,7 @@
     'chromium_gtests',
     'chromium_gtests_for_devices_with_graphical_output',
     'chromium_gtests_for_linux_and_chromeos_only',
-    'clang_gl_gtests',
+    'gl_gtests',
     'linux_and_mac_specific_chromium_gtests',
     'linux_flavor_specific_chromium_gtests',
     'linux_specific_chromium_gtests',
@@ -2555,21 +2538,6 @@
     'vr_platform_specific_chromium_gtests',
   ],
 
-  'chromium_win_fyi_gtests': [
-    'aura_gtests',
-    'chrome_cleaner_gtests',
-    'chromium_gtests',
-    'chromium_gtests_for_devices_with_graphical_output',
-    'non_android_chromium_gtests',
-    'non_android_and_cast_and_chromeos_chromium_gtests',
-    'non_android_and_cast_and_chromeos_and_clang_and_mac_fyi_chromium_gtests',
-    'non_linux_chromium_gtests',
-    'non_mac_chromium_gtests',
-    'viz_gtests',
-    'vr_platform_specific_chromium_gtests',
-    'win_specific_chromium_gtests',
-  ],
-
   'chromium_win_gtests': [
     'aura_gtests',
     'chromium_gtests',
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl
index 9d95556d..c7d59096 100644
--- a/testing/buildbot/waterfalls.pyl
+++ b/testing/buildbot/waterfalls.pyl
@@ -521,12 +521,12 @@
     'machines': {
       'CFI Linux (icall)': {
         'test_suites': {
-          'gtest_tests': 'chromium_linux_clang_and_gl_gtests',
+          'gtest_tests': 'chromium_linux_and_gl_gtests',
         },
       },
       'CFI Linux ToT': {
         'test_suites': {
-          'gtest_tests': 'chromium_linux_clang_and_gl_gtests',
+          'gtest_tests': 'chromium_linux_and_gl_gtests',
         },
       },
       'CrWinAsan': {
@@ -648,7 +648,7 @@
       },
       'ToTLinux': {
         'test_suites': {
-          'gtest_tests': 'chromium_linux_clang_gtests',
+          'gtest_tests': 'chromium_linux_gtests',
           'scripts': 'check_gn_headers_script',
         },
       },
@@ -662,17 +662,17 @@
           'all',
         ],
         'test_suites': {
-          'gtest_tests': 'chromium_linux_clang_gtests',
+          'gtest_tests': 'chromium_linux_gtests',
         },
       },
       'ToTLinuxMSan': {
         'test_suites': {
-          'gtest_tests': 'chromium_linux_clang_gtests',
+          'gtest_tests': 'chromium_linux_gtests',
         },
       },
       'ToTLinuxThinLTO': {
         'test_suites': {
-          'gtest_tests': 'chromium_linux_clang_and_gl_gtests',
+          'gtest_tests': 'chromium_linux_and_gl_gtests',
         },
       },
       'ToTLinuxUBSanVptr': {
@@ -682,7 +682,7 @@
         'test_suites': {
           # no "_and_gl":gl_unittests doesn't pass yet,
           # crbug.com/https://crbug.com/815183
-          'gtest_tests': 'chromium_linux_clang_gtests',
+          'gtest_tests': 'chromium_linux_gtests',
         },
       },
       'ToTMac': {
@@ -762,7 +762,7 @@
         'test_suites': {
           # no "_and_gl":gl_unittests doesn't pass yet,
           # crbug.com/https://crbug.com/815183
-          'gtest_tests': 'chromium_linux_clang_gtests',
+          'gtest_tests': 'chromium_linux_gtests',
         },
       },
     },
@@ -2040,40 +2040,12 @@
         'os_type': 'android',
         'skip_output_links': True,
       },
-      'CFI Linux (icall)': {
-        'test_suites': {
-          'gtest_tests': 'chromium_linux_clang_and_gl_gtests',
-        },
-      },
-      'CFI Linux ToT': {
-        'test_suites': {
-          'gtest_tests': 'chromium_linux_clang_and_gl_gtests',
-        },
-      },
-      'Chromium Mac 10.11': {
-        'test_suites': {
-          'gtest_tests': 'chromium_mac_fyi_gtests',
-          'isolated_scripts': 'chromium_rel_isolated_scripts',
-        },
-        'use_swarming': False,
-      },
-      'Chromium Mac 10.11 Force Mac Toolchain': {
-        'test_suites': {
-          'gtest_tests': 'chromium_mac_fyi_gtests',
-        },
-        'use_swarming': False,
-      },
       'Chromium Mac 10.13': {
         'test_suites': {
           'gtest_tests': 'chromium_mac_fyi_gtests',
           'isolated_scripts': 'chromium_rel_isolated_scripts',
         },
       },
-      'Chromium Win 10 GCE Tests': {
-        'test_suites': {
-          'gtest_tests': 'chromium_win_fyi_gtests',
-        },
-      },
       'chromeos-amd64-generic-rel-goma-canary': {
         'additional_compile_targets': [
           'chromiumos_preflight',
@@ -2366,9 +2338,7 @@
       },
       'Out of Process Profiling Linux': {
         'test_suites': {
-          # TODO(kbr): it's weird that this has the most in common with the
-          # clang testers' test suites.
-          'gtest_tests': 'chromium_linux_clang_and_gl_gtests',
+          'gtest_tests': 'chromium_linux_and_gl_gtests',
         },
       },
       'Out of Process Profiling Mac': {
@@ -2671,7 +2641,7 @@
           'chromium_builder_asan',
         ],
       },
-      'ASAN Debug (32-bit x86 with V8-ARM)': {
+      'ASan Debug (32-bit x86 with V8-ARM)': {
         'additional_compile_targets': [
           'chromium_builder_asan',
         ],
@@ -2681,7 +2651,7 @@
           'chromium_builder_asan',
         ],
       },
-      'ASAN Release (32-bit x86 with V8-ARM)': {
+      'ASan Release (32-bit x86 with V8-ARM)': {
         'additional_compile_targets': [
           'chromium_builder_asan',
         ],
@@ -2691,7 +2661,7 @@
           'chromium_builder_asan',
         ],
       },
-      'ASAN Release Media (32-bit x86 with V8-ARM)': {
+      'ASan Release Media (32-bit x86 with V8-ARM)': {
         'additional_compile_targets': [
           'chromium_builder_asan',
         ],
@@ -2701,17 +2671,17 @@
           'chromium_builder_asan',
         ],
       },
-      'Mac ASan Debug': {
+      'Mac ASAN Debug': {
         'additional_compile_targets': [
           'chromium_builder_asan',
         ],
       },
-      'Mac ASan Release': {
+      'Mac ASAN Release': {
         'additional_compile_targets': [
           'chromium_builder_asan',
         ],
       },
-      'Mac ASan Release Media': {
+      'Mac ASAN Release Media': {
         'additional_compile_targets': [
           'chromium_builder_asan',
         ],
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
index 2958036..fb83c7c 100644
--- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
+++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
@@ -168,9 +168,6 @@
 crbug.com/591099 external/wpt/css/CSS2/normal-flow/root-box-001.xht [ Failure ]
 crbug.com/591099 external/wpt/css/CSS2/text/white-space-mixed-003.xht [ Pass ]
 crbug.com/591099 external/wpt/css/css-backgrounds/box-shadow-syntax-001.xht [ Failure ]
-crbug.com/591099 external/wpt/css/css-display/display-contents-dynamic-list-001-inline.html [ Failure ]
-crbug.com/591099 external/wpt/css/css-display/display-contents-dynamic-list-001-none.html [ Failure ]
-crbug.com/591099 external/wpt/css/css-display/display-contents-list-001.html [ Failure ]
 crbug.com/591099 external/wpt/css/css-filter/filtered-inline-is-container.html [ Crash ]
 crbug.com/714962 external/wpt/css/css-fonts/font-features-across-space-1.html [ Pass ]
 crbug.com/714962 external/wpt/css/css-fonts/font-features-across-space-3.html [ Pass ]
@@ -596,7 +593,7 @@
 crbug.com/591099 fast/multicol/vertical-lr/nested-columns.html [ Failure ]
 crbug.com/591099 fast/multicol/vertical-lr/unsplittable-inline-block.html [ Failure ]
 crbug.com/714962 fast/overflow/line-clamp-hides-trailing-anchor.html [ Failure ]
-crbug.com/59109caret-contenteditable-content9 fast/overflow/line-clamp.html [ Failure ]
+crbug.com/591099 fast/overflow/line-clamp.html [ Failure ]
 crbug.com/591099 fast/overflow/overflow-update-transform.html [ Failure ]
 crbug.com/591099 fast/overflow/recompute-overflow-of-layout-root-container.html [ Failure ]
 crbug.com/591099 fast/pagination/modal-dialog.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index 99d6144..aea0f7b 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -2349,7 +2349,6 @@
 
 # These tests are skipped as there is no touch support on Mac.
 crbug.com/613672 [ Mac ] external/wpt/feature-policy/experimental-features/vertical-scroll-touch-block-manual.tentative.html [ Skip ]
-crbug.com/613672 [ Mac ] virtual/threaded/external/wpt/feature-policy/experimental-features/vertical-scroll-touch-block-manual.tentative.html [ Skip ]
 crbug.com/613672 [ Mac ] virtual/picture-in-picture/external/wpt/feature-policy/experimental-features/vertical-scroll-touch-block-manual.tentative.html [ Skip ]
 crbug.com/613672 [ Mac ] virtual/unified-autoplay/external/wpt/feature-policy/experimental-features/vertical-scroll-touch-block-manual.tentative.html [ Skip ]
 crbug.com/613672 [ Mac ] external/wpt/feature-policy/experimental-features/vertical-scroll-touch-action-manual.tentative.html [ Skip ]
@@ -2365,6 +2364,9 @@
 crbug.com/613672 [ Mac ] virtual/mouseevent_fractional/fast/events/pointerevents/pointer-event-in-slop-region.html [ Skip ]
 crbug.com/613672 [ Mac ] virtual/threaded/fast/events/pointerevents/pinch/pointerevent_touch-action-pinch_zoom_touch.html [ Skip ]
 crbug.com/613672 [ Mac ] external/wpt/pointerevents/compat/pointerevent_touch-action_two-finger_interaction-manual.html [ Skip ]
+# In addition to having no support on Mac, the following test times out
+# regularly on Windows.
+crbug.com/613672 [ Mac Win ] virtual/threaded/external/wpt/feature-policy/experimental-features/vertical-scroll-touch-block-manual.tentative.html [ Skip ]
 
 crbug.com/802067 [ Mac ] external/wpt/pointerlock/movementX_Y_basic-manual.html [ Failure ]
 crbug.com/802067 [ Mac ] external/wpt/pointerevents/pointerlock/pointerevent_movementxy-manual.html [ Failure ]
@@ -2766,7 +2768,10 @@
 crbug.com/800898 external/wpt/FileAPI/url/url-with-fetch.any.worker.html [ Pass Failure ]
 crbug.com/800898 external/wpt/FileAPI/url/url-with-xhr.any.worker.html [ Pass Failure ]
 crbug.com/800898 external/wpt/FileAPI/url/url-in-tags-revoke.window.html [ Timeout ]
-crbug.com/800901 virtual/mojo-blob-urls/external/wpt/FileAPI/url/sandboxed-iframe.html [ Timeout ]
+
+crbug.com/849737 virtual/mojo-blob-urls/external/wpt/FileAPI/url/sandboxed-iframe.html [ Pass Timeout ]
+crbug.com/849737 virtual/mojo-blob-urls/external/wpt/FileAPI/url/url-format.any.html [ Pass Timeout ]
+crbug.com/849737 virtual/mojo-blob-urls/external/wpt/FileAPI/url/url-format.any.worker.html [ Pass Timeout ]
 
 # Websockets
 crbug.com/803558 external/wpt/websockets/opening-handshake/003-sets-origin.worker.html [ Timeout ]
@@ -2795,6 +2800,9 @@
 crbug.com/849859 external/wpt/web-animations/timing-model/animations/pausing-an-animation.html [ Failure ]
 
 # ====== New tests from wpt-importer added here ======
+crbug.com/626703 external/wpt/html/browsers/the-window-object/window-open-noopener.html?_parent [ Timeout ]
+crbug.com/626703 external/wpt/html/browsers/the-window-object/window-open-noopener.html?_top [ Timeout ]
+crbug.com/626703 external/wpt/html/browsers/the-window-object/window-open-noopener.html?_self [ Timeout ]
 crbug.com/626703 external/wpt/css/css-ui/cursor-pointer-links-001-manual.html [ Skip ]
 crbug.com/626703 external/wpt/css/css-ui/cursor-pointer-links-002-manual.html [ Skip ]
 crbug.com/626703 external/wpt/css/css-ui/cursor-pointer-links-003-manual.html [ Skip ]
@@ -2995,7 +3003,6 @@
 crbug.com/626703 [ Win7 ] external/wpt/css/css-fonts/variations/font-opentype-collections.html [ Timeout ]
 crbug.com/626703 external/wpt/html/editing/focus/focus-01.html [ Timeout ]
 crbug.com/626703 external/wpt/html/editing/dnd/the-datatransfer-interface/DataTransfer-types-manual.html [ Skip ]
-crbug.com/626703 external/wpt/webvr/idlharness.https.html [ Timeout ]
 crbug.com/626703 external/wpt/css/geometry/interfaces.worker.html [ Timeout ]
 crbug.com/626703 external/wpt/css/css-transitions/transition-property-017.html [ Skip ]
 crbug.com/626703 external/wpt/css/css-transitions/transition-property-030.html [ Skip ]
@@ -4287,7 +4294,8 @@
 crbug.com/669329 virtual/threaded/http/tests/devtools/tracing/timeline-js/timeline-runtime-stats.js [ Pass Failure Crash ]
 
 crbug.com/799619 [ Debug ] http/tests/devtools/profiler/heap-snapshot-inspect-dom-wrapper.js [ Pass Timeout ]
-crbug.com/760543 http/tests/devtools/tracing/timeline-style/timeline-style-recalc-all-invalidator-types.js [ Pass Timeout ]
+# The following test is flaky since 2018-06-08 (see section below) fix crbug.com/850892 before reintroducing this expectation
+# crbug.com/760543 http/tests/devtools/tracing/timeline-style/timeline-style-recalc-all-invalidator-types.js [ Pass Timeout ]
 
 crbug.com/769347 [ Mac ] fast/dom/inert/inert-node-is-uneditable.html [ Failure ]
 
@@ -4304,6 +4312,8 @@
 crbug.com/694855 virtual/video-surface-layer/media/audio-src-suspend-after-have-metadata.html [ Skip ]
 crbug.com/694855 virtual/video-surface-layer/media/video-src-suspend-after-have-metadata.html [ Skip ]
 
+crbug.com/849979 media/video-layer-crash.html [ Pass Timeout ]
+
 crbug.com/770232 [ Win10 ] editing/selection/paint-hyphen.html [ Failure ]
 crbug.com/770232 [ Win10 ] fast/text/hyphenate-character.html [ Failure ]
 crbug.com/770232 [ Win10 ] fast/text/unicode-fallback-font.html [ Failure ]
@@ -4664,6 +4674,9 @@
 crbug.com/826936 external/wpt/webauthn/getcredential-extensions.https.html [ Pass Timeout ]
 crbug.com/826936 external/wpt/webauthn/getcredential-passing.https.html [ Pass Timeout ]
 crbug.com/826936 external/wpt/webauthn/getcredential-timeout.https.html [ Pass Timeout ]
+crbug.com/826936 external/wpt/webauthn/createcredential-pubkeycredparams.https.html [ Pass Timeout ]
+crbug.com/826936 http/tests/credentialmanager/credentialscontainer-get-from-nested-frame.html [ Pass Timeout ]
+crbug.com/826936 http/tests/credentialmanager/credentialscontainer-get-with-virtual-authenticator.html [ Pass Timeout ]
 
 # WebRTC with Unified Plan
 crbug.com/828866 virtual/webrtc-wpt-unified-plan/external/wpt/webrtc/RTCPeerConnection-setRemoteDescription-tracks.https.html [ Timeout ]
@@ -4768,6 +4781,9 @@
 crbug.com/849040 [ Mac ] virtual/threaded/http/tests/devtools/tracing/timeline-paint/paint-profiler-update.js [ Crash Timeout Pass ]
 crbug.com/841567 fast/scrolling/scrollbar-tickmarks-hittest.html [ Failure Pass ]
 
+# Now that upgrade-insecure-requests enforcing is fixed for redirects, this test will fail while reporting is implemented.
+crbug.com/615885 external/wpt/content-security-policy/securitypolicyviolation/img-src-redirect-upgrade-reporting.https.html [ Timeout ]
+
 # Flakes 2018-06-04
 crbug.com/847870 fast/webgl/texImage-imageBitmap-from-canvas-resize.html [ Timeout Pass ]
 crbug.com/847697 virtual/video-surface-layer/media/controls/overflow-menu-always-visible.html [ Pass Failure ]
@@ -4786,3 +4802,22 @@
 crbug.com/850358 http/tests/devtools/editor/text-editor-enter-behaviour.js [ Pass Failure ]
 crbug.com/850206 virtual/stable/webexposed/global-interface-listing.html [ Pass Failure ]
 crbug.com/849978 http/tests/devtools/elements/styles-4/stylesheet-source-url-comment.js [ Pass Failure ]
+
+# Sheriff 2018-06-08
+crbug.com/850170 [ Mac ] virtual/reporting-api/external/wpt/content-security-policy/reporting-api/reporting-api-doesnt-send-reports-without-violation.https.sub.html [ Pass Timeout ]
+crbug.com/850892 http/tests/devtools/tracing/console-timeline.js [ Pass Failure ]
+crbug.com/850892 http/tests/devtools/tracing/timeline-js/timeline-script-id.js [ Pass Failure ]
+crbug.com/850892 http/tests/devtools/tracing/timeline-layout/timeline-layout-with-invalidations.js [ Pass Failure ]
+crbug.com/850892 http/tests/devtools/tracing/timeline-paint/paint-profiler-update.js [ Pass Failure ]
+crbug.com/850892 http/tests/devtools/tracing/timeline-paint/timeline-paint-image.js [ Pass Failure ]
+crbug.com/850892 http/tests/devtools/tracing/timeline-style/timeline-style-recalc-with-invalidator-invalidations.js [ Pass Failure ]
+crbug.com/850892 http/tests/devtools/tracing/timeline-time/timeline-usertiming.js [ Pass Failure ]
+crbug.com/850892 http/tests/devtools/tracing/timeline-worker-events.js [ Pass Failure ]
+crbug.com/850892 virtual/threaded/http/tests/devtools/tracing/timeline-misc/timeline-event-causes.js [ Pass Failure ]
+crbug.com/850892 virtual/threaded/http/tests/devtools/tracing/timeline-paint/timeline-paint-and-multiple-style-invalidations.js [ Pass Failure ]
+crbug.com/850892 virtual/threaded/http/tests/devtools/tracing/timeline-paint/timeline-paint-with-layout-invalidations-on-deleted-node.js [ Pass Failure ]
+crbug.com/850892 virtual/threaded/http/tests/devtools/tracing/timeline-style/timeline-style-recalc-with-invalidator-invalidations.js [ Pass Failure ]
+crbug.com/850892 virtual/threaded/http/tests/devtools/tracing/timeline-time/timeline-usertiming.js [ Pass Failure ]
+# The following test is known to timeout due to crbug.com/760543.
+crbug.com/850892 http/tests/devtools/tracing/timeline-style/timeline-style-recalc-all-invalidator-types.js [ Pass Timeout Failure ]
+crbug.com/851090 virtual/mouseevent_fractional/fast/events/middleClickAutoscroll-click-hyperlink.html [ Pass Failure ]
diff --git a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
index 143d1412..bd9ca033 100644
--- a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
+++ b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
@@ -100652,6 +100652,16 @@
      {}
     ]
    ],
+   "FileAPI/idlharness-expected.txt": [
+    [
+     {}
+    ]
+   ],
+   "FileAPI/idlharness.worker-expected.txt": [
+    [
+     {}
+    ]
+   ],
    "FileAPI/reading-data-section/support/blue-100x100.png": [
     [
      {}
@@ -100767,16 +100777,6 @@
      {}
     ]
    ],
-   "IndexedDB/interfaces.any-expected.txt": [
-    [
-     {}
-    ]
-   ],
-   "IndexedDB/interfaces.any.worker-expected.txt": [
-    [
-     {}
-    ]
-   ],
    "IndexedDB/interleaved-cursors-common.js": [
     [
      {}
@@ -122202,6 +122202,11 @@
      {}
     ]
    ],
+   "css/css-masking/idlharness-expected.txt": [
+    [
+     {}
+    ]
+   ],
    "css/css-masking/parsing/clip-path-invalid-expected.txt": [
     [
      {}
@@ -138612,16 +138617,6 @@
      {}
     ]
    ],
-   "domparsing/interfaces.any-expected.txt": [
-    [
-     {}
-    ]
-   ],
-   "domparsing/interfaces.any.worker-expected.txt": [
-    [
-     {}
-    ]
-   ],
    "domxpath/001-expected.txt": [
     [
      {}
@@ -142282,11 +142277,6 @@
      {}
     ]
    ],
-   "fullscreen/interfaces-expected.txt": [
-    [
-     {}
-    ]
-   ],
    "fullscreen/rendering/fullscreen-pseudo-class-manual-expected.txt": [
     [
      {}
@@ -142327,11 +142317,6 @@
      {}
     ]
    ],
-   "generic-sensor/idlharness.https-expected.txt": [
-    [
-     {}
-    ]
-   ],
    "geolocation-API/OWNERS": [
     [
      {}
@@ -142467,11 +142452,6 @@
      {}
     ]
    ],
-   "gyroscope/idlharness.https-expected.txt": [
-    [
-     {}
-    ]
-   ],
    "hr-time/OWNERS": [
     [
      {}
@@ -142687,11 +142667,6 @@
      {}
     ]
    ],
-   "html/browsers/browsing-the-web/history-traversal/popstate_event-expected.txt": [
-    [
-     {}
-    ]
-   ],
    "html/browsers/browsing-the-web/history-traversal/resources/a.html": [
     [
      {}
@@ -144247,6 +144222,11 @@
      {}
     ]
    ],
+   "html/browsers/the-window-object/window-open-noopener_indexed-expected.txt": [
+    [
+     {}
+    ]
+   ],
    "html/browsers/the-window-object/window-properties.https-expected.txt": [
     [
      {}
@@ -156022,6 +156002,11 @@
      {}
     ]
    ],
+   "input-device-capabilities/interfaces-expected.txt": [
+    [
+     {}
+    ]
+   ],
    "input-events/OWNERS": [
     [
      {}
@@ -156047,6 +156032,16 @@
      {}
     ]
    ],
+   "interfaces/InputDeviceCapabilities.idl": [
+    [
+     {}
+    ]
+   ],
+   "interfaces/ResizeObserver.idl": [
+    [
+     {}
+    ]
+   ],
    "interfaces/ServiceWorker.idl": [
     [
      {}
@@ -156112,6 +156107,11 @@
      {}
     ]
    ],
+   "interfaces/css-masking.idl": [
+    [
+     {}
+    ]
+   ],
    "interfaces/css-typed-om.idl": [
     [
      {}
@@ -156252,6 +156252,11 @@
      {}
     ]
    ],
+   "interfaces/performance-timeline.idl": [
+    [
+     {}
+    ]
+   ],
    "interfaces/permissions.idl": [
     [
      {}
@@ -156312,6 +156317,11 @@
      {}
     ]
    ],
+   "interfaces/user-timing.idl": [
+    [
+     {}
+    ]
+   ],
    "interfaces/vibration.idl": [
     [
      {}
@@ -158057,11 +158067,6 @@
      {}
     ]
    ],
-   "orientation-sensor/idlharness.https-expected.txt": [
-    [
-     {}
-    ]
-   ],
    "orientation-sensor/orientation-sensor-tests.js": [
     [
      {}
@@ -158342,6 +158347,16 @@
      {}
     ]
    ],
+   "permissions/interfaces.any-expected.txt": [
+    [
+     {}
+    ]
+   ],
+   "permissions/interfaces.any.worker-expected.txt": [
+    [
+     {}
+    ]
+   ],
    "picture-in-picture/resources/picture-in-picture-helpers.js": [
     [
      {}
@@ -161667,6 +161682,11 @@
      {}
     ]
    ],
+   "resize-observer/idlharness-expected.txt": [
+    [
+     {}
+    ]
+   ],
    "resize-observer/resources/iframe.html": [
     [
      {}
@@ -161887,11 +161907,6 @@
      {}
     ]
    ],
-   "screen-orientation/interfaces-expected.txt": [
-    [
-     {}
-    ]
-   ],
    "screen-orientation/orientation-reading-expected.txt": [
     [
      {}
@@ -165977,11 +165992,6 @@
      {}
     ]
    ],
-   "uievents/interfaces-expected.txt": [
-    [
-     {}
-    ]
-   ],
    "uievents/keyboard/README.md": [
     [
      {}
@@ -166532,6 +166542,21 @@
      {}
     ]
    ],
+   "user-timing/idlharness.any.sharedworker-expected.txt": [
+    [
+     {}
+    ]
+   ],
+   "user-timing/idlharness.any.worker-expected.txt": [
+    [
+     {}
+    ]
+   ],
+   "user-timing/idlharness.https.any.serviceworker-expected.txt": [
+    [
+     {}
+    ]
+   ],
    "user-timing/resources/webperftestharness.js": [
     [
      {}
@@ -168337,6 +168362,11 @@
      {}
     ]
    ],
+   "webusb/idlharness.https-expected.txt": [
+    [
+     {}
+    ]
+   ],
    "webusb/resources/fake-devices.js": [
     [
      {}
@@ -168377,6 +168407,16 @@
      {}
     ]
    ],
+   "webusb/worker/idlharness.dedicatedworker.https-expected.txt": [
+    [
+     {}
+    ]
+   ],
+   "webusb/worker/idlharness.sharedworker.https-expected.txt": [
+    [
+     {}
+    ]
+   ],
    "webusb/worker/usb.serviceworker.https-expected.txt": [
     [
      {}
@@ -171437,11 +171477,6 @@
      {}
     ]
    ],
-   "xhr/interfaces-expected.txt": [
-    [
-     {}
-    ]
-   ],
    "xhr/no-utf16-json-expected.txt": [
     [
      {}
@@ -188028,6 +188063,12 @@
      {}
     ]
    ],
+   "css/css-masking/idlharness.html": [
+    [
+     "/css/css-masking/idlharness.html",
+     {}
+    ]
+   ],
    "css/css-masking/parsing/clip-invalid.html": [
     [
      "/css/css-masking/parsing/clip-invalid.html",
@@ -209016,7 +209057,19 @@
    ],
    "html/browsers/the-window-object/window-open-noopener.html": [
     [
-     "/html/browsers/the-window-object/window-open-noopener.html",
+     "/html/browsers/the-window-object/window-open-noopener.html?_parent",
+     {}
+    ],
+    [
+     "/html/browsers/the-window-object/window-open-noopener.html?_self",
+     {}
+    ],
+    [
+     "/html/browsers/the-window-object/window-open-noopener.html?_top",
+     {}
+    ],
+    [
+     "/html/browsers/the-window-object/window-open-noopener.html?indexed",
      {}
     ]
    ],
@@ -219710,6 +219763,12 @@
      }
     ]
    ],
+   "input-device-capabilities/interfaces.html": [
+    [
+     "/input-device-capabilities/interfaces.html",
+     {}
+    ]
+   ],
    "input-events/idlharness.html": [
     [
      "/input-events/idlharness.html",
@@ -231778,9 +231837,21 @@
      {}
     ]
    ],
-   "performance-timeline/idlharness.html": [
+   "performance-timeline/idlharness.any.js": [
     [
-     "/performance-timeline/idlharness.html",
+     "/performance-timeline/idlharness.any.html",
+     {}
+    ],
+    [
+     "/performance-timeline/idlharness.any.sharedworker.html",
+     {}
+    ],
+    [
+     "/performance-timeline/idlharness.any.worker.html",
+     {}
+    ],
+    [
+     "/performance-timeline/idlharness.https.any.serviceworker.html",
      {}
     ]
    ],
@@ -241104,6 +241175,12 @@
      {}
     ]
    ],
+   "resize-observer/idlharness.html": [
+    [
+     "/resize-observer/idlharness.html",
+     {}
+    ]
+   ],
    "resize-observer/notify.html": [
     [
      "/resize-observer/notify.html",
@@ -242907,7 +242984,9 @@
    "service-workers/service-worker/registration-updateviacache.https.html": [
     [
      "/service-workers/service-worker/registration-updateviacache.https.html",
-     {}
+     {
+      "timeout": "long"
+     }
     ]
    ],
    "service-workers/service-worker/rejections.https.html": [
@@ -246002,9 +246081,21 @@
      {}
     ]
    ],
-   "user-timing/idlharness.html": [
+   "user-timing/idlharness.any.js": [
     [
-     "/user-timing/idlharness.html",
+     "/user-timing/idlharness.any.html",
+     {}
+    ],
+    [
+     "/user-timing/idlharness.any.sharedworker.html",
+     {}
+    ],
+    [
+     "/user-timing/idlharness.any.worker.html",
+     {}
+    ],
+    [
+     "/user-timing/idlharness.https.any.serviceworker.html",
      {}
     ]
    ],
@@ -260390,7 +260481,7 @@
    "support"
   ],
   "./README.md": [
-   "ce5fb6c1b9f899ffab603cbfc4086b00dbff5384",
+   "bbaa29655c73c0be3dc1e5e1aae85607284cc7b9",
    "support"
   ],
   "./lint.whitelist": [
@@ -264721,10 +264812,18 @@
    "8a0e866521c4cbfb010260c29777f1c93101a576",
    "testharness"
   ],
+  "FileAPI/idlharness-expected.txt": [
+   "2d0dd3c240e3df95df3c7e9773228d687a348ff6",
+   "support"
+  ],
   "FileAPI/idlharness.html": [
    "b12d3e9d4d69b4b922f8fb588f94db7bbdacbef9",
    "testharness"
   ],
+  "FileAPI/idlharness.worker-expected.txt": [
+   "7352fd2546b1bf49d16c2a0a17ff8296fcdc9872",
+   "support"
+  ],
   "FileAPI/idlharness.worker.js": [
    "cda6c4911582d2cd707598bbb7be17400eab2517",
    "testharness"
@@ -266121,18 +266220,10 @@
    "251a828d333bdd3face9d20a2a28ddf0c0ffeb49",
    "testharness"
   ],
-  "IndexedDB/interfaces.any-expected.txt": [
-   "325a44ee279579cf6441fab6830c1cec733089d4",
-   "support"
-  ],
   "IndexedDB/interfaces.any.js": [
    "ae562d6b568c1005c5eef5a230b8869729719dff",
    "testharness"
   ],
-  "IndexedDB/interfaces.any.worker-expected.txt": [
-   "325a44ee279579cf6441fab6830c1cec733089d4",
-   "support"
-  ],
   "IndexedDB/interleaved-cursors-common.js": [
    "6744105fe1a15a91058e3e5993f8a1f88548e3a3",
    "support"
@@ -267166,7 +267257,7 @@
    "support"
   ],
   "accelerometer/idlharness.https-expected.txt": [
-   "f56432fa45355f0a65c087b821d04f39772694b3",
+   "41c6d2c3d9b32694e4256220daa4ec9fa92a1d5b",
    "support"
   ],
   "accelerometer/idlharness.https.html": [
@@ -267898,11 +267989,11 @@
    "testharness"
   ],
   "background-fetch/interfaces-expected.txt": [
-   "74aa2d04a6e984b6bad2d68d55dcdbcd44643c56",
+   "610600c981732946c6ee3b3ca950a4344f89e861",
    "support"
   ],
   "background-fetch/interfaces-worker.https-expected.txt": [
-   "8393e3172c854e18970e87426633026a518e0500",
+   "88211a0d44012d229af146366440ced5d12b0988",
    "support"
   ],
   "background-fetch/interfaces-worker.https.html": [
@@ -267914,7 +268005,7 @@
    "testharness"
   ],
   "background-fetch/interfaces.worker-expected.txt": [
-   "5453d79743c43a705d2276fb4ea7ea1967056e5a",
+   "a8c15d8086ed570c858d0f2495423301b3c38e42",
    "support"
   ],
   "background-fetch/interfaces.worker.js": [
@@ -268886,7 +268977,7 @@
    "testharness"
   ],
   "budget-api/interfaces.any-expected.txt": [
-   "25d68d63509ea934c3c278eb8e049fd1a8514a17",
+   "0d4b07999f0f3bc3d5deb01dcbdf6c2391351f4f",
    "support"
   ],
   "budget-api/interfaces.any.js": [
@@ -268894,7 +268985,7 @@
    "testharness"
   ],
   "budget-api/interfaces.any.worker-expected.txt": [
-   "25d68d63509ea934c3c278eb8e049fd1a8514a17",
+   "8c5e84dbcc4a43ee2e568d600ba630347f85969e",
    "support"
   ],
   "clear-site-data/OWNERS": [
@@ -269214,7 +269305,7 @@
    "testharness"
   ],
   "compat/interfaces.any-expected.txt": [
-   "94145253ee2248b5e44a88f3ad360a06638b6d70",
+   "4704062c6329d49eb322c03d514d11efe7faca49",
    "support"
   ],
   "compat/interfaces.any.js": [
@@ -269222,7 +269313,7 @@
    "testharness"
   ],
   "compat/interfaces.any.worker-expected.txt": [
-   "dd136edd0999c6e04a80fb0c80d673c9704a0d35",
+   "ec03c693d69bb98735d0235cf84ad797829a1457",
    "support"
   ],
   "compat/webkit-appearance.tentative.html": [
@@ -297106,7 +297197,7 @@
    "testharness"
   ],
   "css/css-fonts/idlharness-expected.txt": [
-   "96932c2240c248c8748809de53c9a3b83ae6d78e",
+   "7f731841428732b2306a63e6c286dedd9cc8a8a5",
    "support"
   ],
   "css/css-fonts/idlharness.html": [
@@ -306638,7 +306729,7 @@
    "testharness"
   ],
   "css/css-logical/logicalprops-quirklength.html": [
-   "3024bbd54e4cbe1ee55e59684188587e2a56fda6",
+   "04c724e71003824ad8c9fe37c5d4b309d2954282",
    "testharness"
   ],
   "css/css-logical/resources/test-box-properties.js": [
@@ -307445,6 +307536,14 @@
    "8853e79d6e9c3d262ebb38c569e97932f3b27cd4",
    "support"
   ],
+  "css/css-masking/idlharness-expected.txt": [
+   "9b12d4c19096aabd22c41a794198d6502fa73121",
+   "support"
+  ],
+  "css/css-masking/idlharness.html": [
+   "527fb8b8884e00d898c047f092221af56211bbcd",
+   "testharness"
+  ],
   "css/css-masking/parsing/clip-invalid.html": [
    "81cd98170ea4abe216c0cf155aa493c58079bd53",
    "testharness"
@@ -322722,7 +322821,7 @@
    "testharness"
   ],
   "css/css-typed-om/interfaces-expected.txt": [
-   "dca9bad99c0e48cc5c4624e090cae2e0da48f2b1",
+   "62977fc97de95d105fca0b68ed17306606c61f14",
    "support"
   ],
   "css/css-typed-om/interfaces.html": [
@@ -333714,7 +333813,7 @@
    "support"
   ],
   "css/cssom-view/interfaces-expected.txt": [
-   "6ab8c24a3f4536d859b08889dd6e851e2e0670a8",
+   "44410a59b6c9a8183577a9b0696c0f453fc9b358",
    "support"
   ],
   "css/cssom-view/interfaces.html": [
@@ -334122,7 +334221,7 @@
    "testharness"
   ],
   "css/cssom/computed-style-set-property.html": [
-   "ce05e756acf5a53d37d854e5e635bb68febf84a1",
+   "cb05ff525eb659d43bf234d932fd860795959c9e",
    "testharness"
   ],
   "css/cssom/css-style-attr-decl-block.html": [
@@ -334266,7 +334365,7 @@
    "testharness"
   ],
   "css/cssom/interfaces-expected.txt": [
-   "754b97e87b41ad65b012136f995d08ec3837f1ef",
+   "3aac22204bbcfffe6cca0dafba96b5122ea1a7e0",
    "support"
   ],
   "css/cssom/interfaces.html": [
@@ -341346,7 +341445,7 @@
    "testharness"
   ],
   "dom/interfaces-expected.txt": [
-   "36eedaa2ff15780192c4c680c274651f9c8f3ae2",
+   "2ef353ba438792f7a93ec6b21c3226504a1ffcab",
    "support"
   ],
   "dom/interfaces.html": [
@@ -342817,18 +342916,10 @@
    "b26dd3780474b79d71d302cea37dc18bf5038145",
    "support"
   ],
-  "domparsing/interfaces.any-expected.txt": [
-   "325a44ee279579cf6441fab6830c1cec733089d4",
-   "support"
-  ],
   "domparsing/interfaces.any.js": [
    "c839218d1a8dd146fa204f2d4d366bb0958770b9",
    "testharness"
   ],
-  "domparsing/interfaces.any.worker-expected.txt": [
-   "325a44ee279579cf6441fab6830c1cec733089d4",
-   "support"
-  ],
   "domparsing/outerhtml-01.html": [
    "8c5c0ac91406ee6c8da4845b8ac10c7fec42a7d3",
    "testharness"
@@ -345486,7 +345577,7 @@
    "manual"
   ],
   "entries-api/interfaces-expected.txt": [
-   "23f3fe2f29cc9f4458c65101c93f2edbf664ad7a",
+   "9d52901a0ae91a9e70858a5a0d74d17c7f04d002",
    "support"
   ],
   "entries-api/interfaces-manual.html": [
@@ -348177,10 +348268,6 @@
    "ba59db02939bc5ba00825befe4777c66cee64b4c",
    "support"
   ],
-  "fullscreen/interfaces-expected.txt": [
-   "325a44ee279579cf6441fab6830c1cec733089d4",
-   "support"
-  ],
   "fullscreen/interfaces.html": [
    "f6f0dbc8a505896a0e7ec7aca2746bbd5c1eb7d9",
    "testharness"
@@ -348265,10 +348352,6 @@
    "3a427e0ebd3191c2a6b982b74d139250d8fb085a",
    "support"
   ],
-  "generic-sensor/idlharness.https-expected.txt": [
-   "a59998e0abacd23c5f8af28eca564425f8bfdfcc",
-   "support"
-  ],
   "generic-sensor/idlharness.https.html": [
    "02c734b907075c8abb7504fc7e2b93730ac80a0c",
    "testharness"
@@ -348529,10 +348612,6 @@
    "3f4a18cda77fd2fcb47f8892192c691cf201c574",
    "support"
   ],
-  "gyroscope/idlharness.https-expected.txt": [
-   "7e7ea06b007cc3c9b5611213fa8dfcaa4976d7e1",
-   "support"
-  ],
   "gyroscope/idlharness.https.html": [
    "8b9b8fcdc6d33fb20c174b67306a182bdbb707fd",
    "testharness"
@@ -348714,7 +348793,7 @@
    "manual"
   ],
   "html-media-capture/idlharness-expected.txt": [
-   "042ff81eca3ba88988db5ba97a84a879b88370bf",
+   "2fb681a80db7d1874e391d7896fe135dd9b2e2f9",
    "support"
   ],
   "html-media-capture/idlharness.html": [
@@ -348873,10 +348952,6 @@
    "8f266717a7be3336b00b8bcef70e003bbb2c2e9d",
    "testharness"
   ],
-  "html/browsers/browsing-the-web/history-traversal/popstate_event-expected.txt": [
-   "c9a6c9c9872da13babc2e36308b6eaa5fa1178db",
-   "support"
-  ],
   "html/browsers/browsing-the-web/history-traversal/popstate_event.html": [
    "ed84161a523f48546ffc2fd8ba92d16ba0f247fb",
    "testharness"
@@ -351146,9 +351221,13 @@
    "testharness"
   ],
   "html/browsers/the-window-object/window-open-noopener.html": [
-   "2e20bfcd1dfe9bee00a9747b87cdaf42004d6415",
+   "ee8d53b12b8034d1c0ede3b2c6516a345890915e",
    "testharness"
   ],
+  "html/browsers/the-window-object/window-open-noopener_indexed-expected.txt": [
+   "962b4c8294870c48be25010e9395b18ca93ac60f",
+   "support"
+  ],
   "html/browsers/the-window-object/window-properties.https-expected.txt": [
    "f3ce1d8416df1174e77ecd1c78e08f082dab3581",
    "support"
@@ -353306,7 +353385,7 @@
    "support"
   ],
   "html/dom/interfaces.https-expected.txt": [
-   "5e007a8a93d704167bc009abdabbe2587f260207",
+   "385ad47dc1de59a3c908d8692948163cc8ebf433",
    "support"
   ],
   "html/dom/interfaces.https.html": [
@@ -353314,7 +353393,7 @@
    "testharness"
   ],
   "html/dom/interfaces.worker-expected.txt": [
-   "4610698c744b6dcb05c79b7d5b943af78b19a703",
+   "756cb7e7ff6bf84a408b301c5d20cec93a2fecc0",
    "support"
   ],
   "html/dom/interfaces.worker.js": [
@@ -368757,6 +368836,14 @@
    "0d88ab8cc2adc0da4cd08cbaca7b8e8706f7ca42",
    "support"
   ],
+  "input-device-capabilities/interfaces-expected.txt": [
+   "f446be0cabe297fbb5626d5e6cdd03eaf7b913fc",
+   "support"
+  ],
+  "input-device-capabilities/interfaces.html": [
+   "327ff946ec80b347be627814ea9260ebd7ef6c1d",
+   "testharness"
+  ],
   "input-events/OWNERS": [
    "9ebd0fb0f1eae3b8b1c53e25fdb15f80c34251e2",
    "support"
@@ -368797,6 +368884,14 @@
    "149cca0098cf37769391b4caa0650a7182ed8212",
    "support"
   ],
+  "interfaces/InputDeviceCapabilities.idl": [
+   "75bf10b0d1bda48c56cb5cd2ac1c73eb59f744fc",
+   "support"
+  ],
+  "interfaces/ResizeObserver.idl": [
+   "2835174993c1648c5f8e2a4639727118d62e2d77",
+   "support"
+  ],
   "interfaces/ServiceWorker.idl": [
    "7884feabcb4c9d0a447cccfa2359e3c45eef5455",
    "support"
@@ -368849,6 +368944,10 @@
    "ff2d83e9468c743993c9b4a1ecf3fab09684dc16",
    "support"
   ],
+  "interfaces/css-masking.idl": [
+   "5f4ed3d8922e30ab3ddb714d185c6e6f794e5a29",
+   "support"
+  ],
   "interfaces/css-typed-om.idl": [
    "36526913c07a04f9fd329a5650430db82407d766",
    "support"
@@ -368961,6 +369060,10 @@
    "594179265efe3f056059ba834da5e1873c3e6174",
    "support"
   ],
+  "interfaces/performance-timeline.idl": [
+   "57f26fe863d12c7672905d185e9a2c7ab9cb98a0",
+   "support"
+  ],
   "interfaces/permissions.idl": [
    "7fec46d25cf175390524b681cdbec7b0b76c89b9",
    "support"
@@ -369009,6 +369112,10 @@
    "416ee65b3ba9e438a3178c6c04a414f42d759fc8",
    "support"
   ],
+  "interfaces/user-timing.idl": [
+   "41c00eec8e9c1b2137bd05e85bdc029b7a87c349",
+   "support"
+  ],
   "interfaces/vibration.idl": [
    "d1f3f51b0c6a46958d4bb3e9cc8bbc85e8a74512",
    "support"
@@ -369390,7 +369497,7 @@
    "support"
   ],
   "magnetometer/idlharness.https-expected.txt": [
-   "e441e2adabcaaa962682ab83e7296a2bf050b0cc",
+   "1a7613a0efc56736823db66dc17ca111c5799855",
    "support"
   ],
   "magnetometer/idlharness.https.html": [
@@ -369410,7 +369517,7 @@
    "testharness"
   ],
   "media-capabilities/idlharness-expected.txt": [
-   "019888949f6f15017a82db75a343bfeac247f700",
+   "28418a44e4367394bab797c9631c94711e7658c4",
    "support"
   ],
   "media-capabilities/idlharness.html": [
@@ -369478,7 +369585,7 @@
    "support"
   ],
   "media-source/interfaces-expected.txt": [
-   "de7948ff901dae5cd77a1389e23008831682c706",
+   "9d50f1aca321f6a5be2ef513e76f08da402f0c3b",
    "support"
   ],
   "media-source/interfaces.html": [
@@ -370026,7 +370133,7 @@
    "testharness"
   ],
   "mediacapture-fromelement/idlharness-expected.txt": [
-   "4befc7133cb86ec98fba704361945f99415b077c",
+   "36d6f2375c122b2702ae26685bf3f17f748bc0b7",
    "support"
   ],
   "mediacapture-fromelement/idlharness.html": [
@@ -370098,7 +370205,7 @@
    "testharness"
   ],
   "mediacapture-streams/MediaDevices-IDL-all-expected.txt": [
-   "63000ec3c8cfd3c0f0c2195e2a702e25188295dd",
+   "fa2c7f735bff9cf534cea9d16e6d2838050a2a02",
    "support"
   ],
   "mediacapture-streams/MediaDevices-IDL-all.html": [
@@ -370106,7 +370213,7 @@
    "testharness"
   ],
   "mediacapture-streams/MediaDevices-IDL-enumerateDevices-expected.txt": [
-   "67c20a2d57949e965b2680db32d10b287f44b393",
+   "296328da85a5eb016d8b6db9cffe315520e27d31",
    "support"
   ],
   "mediacapture-streams/MediaDevices-IDL-enumerateDevices.html": [
@@ -370214,7 +370321,7 @@
    "testharness"
   ],
   "mediacapture-streams/MediaStreamTrack-idl.https-expected.txt": [
-   "325a44ee279579cf6441fab6830c1cec733089d4",
+   "9a587b8e86799e95dfd3c90f38340bc2105c3391",
    "support"
   ],
   "mediacapture-streams/MediaStreamTrack-idl.https.html": [
@@ -378130,7 +378237,7 @@
    "manual"
   ],
   "orientation-event/idlharness-expected.txt": [
-   "7edbcf0e70f0ee23e9650ff7d5caaf2120eb099e",
+   "097967a0076ecae8de3bd38ebbba4fbde8403da3",
    "support"
   ],
   "orientation-event/idlharness.html": [
@@ -378289,10 +378396,6 @@
    "9bf83c64eb5dcf284eb6c45db8ac278ab3c637a2",
    "testharness"
   ],
-  "orientation-sensor/idlharness.https-expected.txt": [
-   "177f93dc3360a7bfc456931ffe185cfcbdc38a04",
-   "support"
-  ],
   "orientation-sensor/idlharness.https.html": [
    "1f94329cb330a1a904d409a6e158a5fe9f8dd709",
    "testharness"
@@ -378702,7 +378805,7 @@
    "testharness"
   ],
   "payment-request/interfaces.https-expected.txt": [
-   "11129a25b340eeeee13d307ce28b6a6981f751a8",
+   "92c5778c542afb2ac71b3854a8bf6d6741cc24f9",
    "support"
   ],
   "payment-request/interfaces.https.html": [
@@ -378877,8 +378980,8 @@
    "9c6b6edf19800a2730de2dfe601a7cd2503cf87d",
    "testharness"
   ],
-  "performance-timeline/idlharness.html": [
-   "d6ce8e5c21b42843caea8e61c1637d75c2e51d64",
+  "performance-timeline/idlharness.any.js": [
+   "0a3ea0b532a1634008b776489b7409b348952d6f",
    "testharness"
   ],
   "performance-timeline/performanceentry-tojson.html": [
@@ -378953,10 +379056,18 @@
    "dc978fd8669d67118109fcab245010fdd7d799b0",
    "testharness"
   ],
+  "permissions/interfaces.any-expected.txt": [
+   "af00b6ec8a79617bfb5e487d9c33c6bc1aa95400",
+   "support"
+  ],
   "permissions/interfaces.any.js": [
    "2b16f91ae23a516d2c58299b81e0b3895cba117b",
    "testharness"
   ],
+  "permissions/interfaces.any.worker-expected.txt": [
+   "b97513af21d1a93031f3edb1c055c9f3e153993c",
+   "support"
+  ],
   "picture-in-picture/disable-picture-in-picture.html": [
    "d97bf03a6e2f991c173248f9e28bd713da19a6f4",
    "testharness"
@@ -388149,6 +388260,14 @@
    "a508a8bd68ef64bd826f76cc6f0967d2a5f1d3e9",
    "testharness"
   ],
+  "resize-observer/idlharness-expected.txt": [
+   "369f73cd032f618992d1746184927d0e78a920e8",
+   "support"
+  ],
+  "resize-observer/idlharness.html": [
+   "2b1960834f7164e351cdbba119694830055dcf17",
+   "testharness"
+  ],
   "resize-observer/notify.html": [
    "29f22b18a6ae894b80bec599dd71fc5050dbb292",
    "testharness"
@@ -388485,10 +388604,6 @@
    "970c0e5b33815109f17231ffeaf4cea22cf9096c",
    "support"
   ],
-  "screen-orientation/interfaces-expected.txt": [
-   "5c3f535f9643b6eda1020fef17e415f9ef797c11",
-   "support"
-  ],
   "screen-orientation/interfaces.html": [
    "d54475008731fafd00c3cae73f11eac94dba0883",
    "testharness"
@@ -388778,7 +388893,7 @@
    "testharness"
   ],
   "selection/interfaces-expected.txt": [
-   "3a228ece24f5df5e9421d35f981ac3fc0e96b3a8",
+   "8a53b2e46fc24e712365a3e1484acdca85752864",
    "support"
   ],
   "selection/interfaces.html": [
@@ -390690,7 +390805,7 @@
    "testharness"
   ],
   "service-workers/service-worker/registration-updateviacache.https.html": [
-   "c5fe71cfb142f80d451f541accaa0120d9923f2b",
+   "7a640f15203c284cfa9b228da98c55efe5a2219d",
    "testharness"
   ],
   "service-workers/service-worker/rejections.https.html": [
@@ -394390,7 +394505,7 @@
    "testharness"
   ],
   "svg/interfaces-expected.txt": [
-   "0346df8b8c200bd2f4c6afa712182a08b449a12b",
+   "1a9bf0c8fb17f538fab799d2cad3313cd6128e49",
    "support"
   ],
   "svg/interfaces.html": [
@@ -394945,10 +395060,6 @@
    "551486b9882d33a0ce31740809eaec0352403d69",
    "manual"
   ],
-  "uievents/interfaces-expected.txt": [
-   "325a44ee279579cf6441fab6830c1cec733089d4",
-   "support"
-  ],
   "uievents/interfaces.html": [
    "e755618e522288e9bf6dc4fc592fd6658dc97aba",
    "testharness"
@@ -395613,10 +395724,22 @@
    "bb08ac2ee06bc12e75cc44b76f06d3f0262f44ba",
    "testharness"
   ],
-  "user-timing/idlharness.html": [
-   "b24d4d5faf5df5d67135560d5fe362cc6d72c28f",
+  "user-timing/idlharness.any.js": [
+   "6a0dcd26b5ff16b18603c50b9257d55e6e25f0ce",
    "testharness"
   ],
+  "user-timing/idlharness.any.sharedworker-expected.txt": [
+   "52a0c5d8d5120e0f5134fa1deafb6d7ea7461386",
+   "support"
+  ],
+  "user-timing/idlharness.any.worker-expected.txt": [
+   "52a0c5d8d5120e0f5134fa1deafb6d7ea7461386",
+   "support"
+  ],
+  "user-timing/idlharness.https.any.serviceworker-expected.txt": [
+   "52a0c5d8d5120e0f5134fa1deafb6d7ea7461386",
+   "support"
+  ],
   "user-timing/invoke_with_timing_attributes.html": [
    "05283be9a7230ba0c4af09fb5dac98d828bfaf2e",
    "testharness"
@@ -398198,7 +398321,7 @@
    "support"
   ],
   "webrtc/RTCDTMFSender-insertDTMF.https.html": [
-   "a5fc15d44fe572744c07d933b9204d9319c968cd",
+   "efe15e018bbfe29b6c79e88d3380300844ec4189",
    "testharness"
   ],
   "webrtc/RTCDTMFSender-ontonechange-long.https.html": [
@@ -398210,7 +398333,7 @@
    "support"
   ],
   "webrtc/RTCDTMFSender-ontonechange.https.html": [
-   "ecc1e77f083cb91af78b1bcb7311fe4b5b96313e",
+   "9b5635c4757c983ec7ee7b6e0b62b267e89b28b0",
    "testharness"
   ],
   "webrtc/RTCDataChannel-bufferedAmount-expected.txt": [
@@ -398222,7 +398345,7 @@
    "testharness"
   ],
   "webrtc/RTCDataChannel-id.html": [
-   "28ce3983bf04db02c62ed29b332a4a4b612affd2",
+   "492cf27f7b8565ba6b2c4d1a9c8ea603a5dfdf96",
    "testharness"
   ],
   "webrtc/RTCDataChannel-send-expected.txt": [
@@ -398242,7 +398365,7 @@
    "support"
   ],
   "webrtc/RTCDtlsTransport-getRemoteCertificates.html": [
-   "7d6ea59253879cac114e2a7b162fa67926a39635",
+   "a419f71efed644f79bb198b9f410818bb85fa8d5",
    "testharness"
   ],
   "webrtc/RTCIceCandidate-constructor-expected.txt": [
@@ -398258,7 +398381,7 @@
    "support"
   ],
   "webrtc/RTCIceTransport.html": [
-   "db758cc2a744c049c291575e408dbb5f280cdf19",
+   "1b593c8ed167fd998195a2e2051bc489473f1bf4",
    "testharness"
   ],
   "webrtc/RTCPeerConnection-add-track-no-deadlock.https.html": [
@@ -398270,7 +398393,7 @@
    "support"
   ],
   "webrtc/RTCPeerConnection-addIceCandidate.html": [
-   "dd19f1d7a8d12ee85101e53bb30c553e94d67b6a",
+   "6d6351d16a2ce4f3e5b91757498c1a7c4caa3289",
    "testharness"
   ],
   "webrtc/RTCPeerConnection-addTrack.https-expected.txt": [
@@ -398278,7 +398401,7 @@
    "support"
   ],
   "webrtc/RTCPeerConnection-addTrack.https.html": [
-   "c434d2cdcb134f28b203df07cecca04e11195700",
+   "0255e15f335741d135647679fc0366a5c89df2a4",
    "testharness"
   ],
   "webrtc/RTCPeerConnection-addTransceiver-expected.txt": [
@@ -398294,7 +398417,7 @@
    "support"
   ],
   "webrtc/RTCPeerConnection-canTrickleIceCandidates.html": [
-   "8401fdc22f8f8867aa361f6a83834cdeb7a2a9d1",
+   "b19badd054a12905d636e1c125293b5c9157906f",
    "testharness"
   ],
   "webrtc/RTCPeerConnection-connectionState-expected.txt": [
@@ -398302,7 +398425,7 @@
    "support"
   ],
   "webrtc/RTCPeerConnection-connectionState.html": [
-   "a733cd1ae59aace10832a7b5f98913967afb87f1",
+   "4cbc2ec967d13623df2ff2dd87e35cc984cabe78",
    "testharness"
   ],
   "webrtc/RTCPeerConnection-constructor-expected.txt": [
@@ -398318,7 +398441,7 @@
    "support"
   ],
   "webrtc/RTCPeerConnection-createAnswer.html": [
-   "d70701dac44c536f793b124c0b1f86e7a08b2fd5",
+   "6fc00f6ac52190a82f11097ab1b80c66abcabe36",
    "testharness"
   ],
   "webrtc/RTCPeerConnection-createDataChannel-expected.txt": [
@@ -398326,7 +398449,7 @@
    "support"
   ],
   "webrtc/RTCPeerConnection-createDataChannel.html": [
-   "102de47ea13e20fe6d196077e47a525911957a00",
+   "19cb6b495cbeb8bbd9d721fc508f2f9709ea75d3",
    "testharness"
   ],
   "webrtc/RTCPeerConnection-createOffer-expected.txt": [
@@ -398338,11 +398461,11 @@
    "support"
   ],
   "webrtc/RTCPeerConnection-createOffer-offerToReceive.html": [
-   "91905d7efc95500ebba085ca4b1fc682a496e228",
+   "978387f8ca0cf6bfc9e5147ee01e870f3f2b4223",
    "testharness"
   ],
   "webrtc/RTCPeerConnection-createOffer.html": [
-   "c3687cea8887f61fc797a7cfb73786699b97a8d7",
+   "fb66c7d17d237b3a1752ce67ab7963a6f8c719d0",
    "testharness"
   ],
   "webrtc/RTCPeerConnection-generateCertificate-expected.txt": [
@@ -398378,7 +398501,7 @@
    "support"
   ],
   "webrtc/RTCPeerConnection-getStats.https.html": [
-   "913cbc3d2aaf724e70108e7854f56ad5bb9b2283",
+   "a8a0f98c9ebf3510cf4def16e569dbbeadd558d5",
    "testharness"
   ],
   "webrtc/RTCPeerConnection-getTransceivers-expected.txt": [
@@ -398398,7 +398521,7 @@
    "support"
   ],
   "webrtc/RTCPeerConnection-iceConnectionState.html": [
-   "dad0787100a817c05dd871bf892a94464916a74a",
+   "718973199ab2bbdba519500e0e508ab51e2d8ddb",
    "testharness"
   ],
   "webrtc/RTCPeerConnection-iceGatheringState-expected.txt": [
@@ -398406,7 +398529,7 @@
    "support"
   ],
   "webrtc/RTCPeerConnection-iceGatheringState.html": [
-   "ed3226f9673bc0b69c2a9f9ec6e1ccfa8e83e2e2",
+   "cfa693af6b6fb3a4ba6ff04e9e2fa1845016f6da",
    "testharness"
   ],
   "webrtc/RTCPeerConnection-ondatachannel-expected.txt": [
@@ -398414,7 +398537,7 @@
    "support"
   ],
   "webrtc/RTCPeerConnection-ondatachannel.html": [
-   "6096ee14d729894e39eb2217828e8b0a5abc7f19",
+   "37eeb67a20c600c92ef3fe9634fdcf44ab796703",
    "testharness"
   ],
   "webrtc/RTCPeerConnection-onnegotiationneeded-expected.txt": [
@@ -398422,7 +398545,7 @@
    "support"
   ],
   "webrtc/RTCPeerConnection-onnegotiationneeded.html": [
-   "ca1cbd230de7aec4844879ae43f822941f566620",
+   "fb890b5e4175672627122fb9d5efdcd062b8f47d",
    "testharness"
   ],
   "webrtc/RTCPeerConnection-ontrack.https-expected.txt": [
@@ -398430,7 +398553,7 @@
    "support"
   ],
   "webrtc/RTCPeerConnection-ontrack.https.html": [
-   "3db4d8b29f4e1372055a50a279cae525f52cbb40",
+   "7c5857534be80343928cacbe89a01d34ed3f0972",
    "testharness"
   ],
   "webrtc/RTCPeerConnection-peerIdentity-expected.txt": [
@@ -398438,7 +398561,7 @@
    "support"
   ],
   "webrtc/RTCPeerConnection-peerIdentity.html": [
-   "d821c1516578820206ecc4a9f36dc4f28f2e52dd",
+   "d1e2441af750d0c698ecdfc1423d32d37dbb5f5f",
    "testharness"
   ],
   "webrtc/RTCPeerConnection-removeTrack.https-expected.txt": [
@@ -398446,7 +398569,7 @@
    "support"
   ],
   "webrtc/RTCPeerConnection-removeTrack.https.html": [
-   "561575bea206ec1c9572e1e5e6f97d1e0bebe2d1",
+   "15f5c03bdc9e4b3479594c302eecf4403b86c4e7",
    "testharness"
   ],
   "webrtc/RTCPeerConnection-setDescription-transceiver-expected.txt": [
@@ -398454,7 +398577,7 @@
    "support"
   ],
   "webrtc/RTCPeerConnection-setDescription-transceiver.html": [
-   "a21fe04592ad6941aa4277535d6482519b67ae74",
+   "47d2f81b1e5f0c81eb249261829fded2f4b00a95",
    "testharness"
   ],
   "webrtc/RTCPeerConnection-setLocalDescription-answer-expected.txt": [
@@ -398462,7 +398585,7 @@
    "support"
   ],
   "webrtc/RTCPeerConnection-setLocalDescription-answer.html": [
-   "90b1305e820a7c768f4773f7e995b04832754015",
+   "35f5d5f3da4914fb5f42cd77d122fb3cf88ba790",
    "testharness"
   ],
   "webrtc/RTCPeerConnection-setLocalDescription-expected.txt": [
@@ -398474,7 +398597,7 @@
    "support"
   ],
   "webrtc/RTCPeerConnection-setLocalDescription-offer.html": [
-   "25807994834322acb7c191e03001a55deaaab4ae",
+   "ce7f1e2fc7adb243a840587a1d011b683ecfbfbd",
    "testharness"
   ],
   "webrtc/RTCPeerConnection-setLocalDescription-pranswer-expected.txt": [
@@ -398482,7 +398605,7 @@
    "support"
   ],
   "webrtc/RTCPeerConnection-setLocalDescription-pranswer.html": [
-   "33bd3f0ba3a5065f8dcb239ad7e042dc58c93100",
+   "acc815368303f8d79d2d8f504f675092581f6724",
    "testharness"
   ],
   "webrtc/RTCPeerConnection-setLocalDescription-rollback-expected.txt": [
@@ -398490,11 +398613,11 @@
    "support"
   ],
   "webrtc/RTCPeerConnection-setLocalDescription-rollback.html": [
-   "90b738d362e795d472acabdc356089ab59d864bc",
+   "45f66d3133c760a8be7e6667df089df5e890ba08",
    "testharness"
   ],
   "webrtc/RTCPeerConnection-setLocalDescription.html": [
-   "ec2abe797f22b824a71b2c476ec313e338866df8",
+   "460de818ecbd5cb476c27a38c5f39f567060bda2",
    "testharness"
   ],
   "webrtc/RTCPeerConnection-setRemoteDescription-answer-expected.txt": [
@@ -398502,7 +398625,7 @@
    "support"
   ],
   "webrtc/RTCPeerConnection-setRemoteDescription-answer.html": [
-   "2b263abc36ed0f2431825d47e81120503bdd988a",
+   "c4a942e907e8d0506cd6a6dce4f45c59e12a12e6",
    "testharness"
   ],
   "webrtc/RTCPeerConnection-setRemoteDescription-expected.txt": [
@@ -398514,7 +398637,7 @@
    "support"
   ],
   "webrtc/RTCPeerConnection-setRemoteDescription-offer.html": [
-   "c987426037472bcf617ee4a6212b2bfb81513369",
+   "455b414593df9fde32cc3e873fb05327aa73e8a7",
    "testharness"
   ],
   "webrtc/RTCPeerConnection-setRemoteDescription-pranswer-expected.txt": [
@@ -398522,7 +398645,7 @@
    "support"
   ],
   "webrtc/RTCPeerConnection-setRemoteDescription-pranswer.html": [
-   "90c11c58394b7b3d3c1fa1e416382c06c1b0cd61",
+   "d61781c76e6e831c9a513b9a91f709761bf425f7",
    "testharness"
   ],
   "webrtc/RTCPeerConnection-setRemoteDescription-replaceTrack.https-expected.txt": [
@@ -398530,7 +398653,7 @@
    "support"
   ],
   "webrtc/RTCPeerConnection-setRemoteDescription-replaceTrack.https.html": [
-   "38f2588fadab58203a7f22d25e0d828b1373fbd3",
+   "f898128a0de6b757bc48f93707e13663e72c2410",
    "testharness"
   ],
   "webrtc/RTCPeerConnection-setRemoteDescription-rollback-expected.txt": [
@@ -398538,7 +398661,7 @@
    "support"
   ],
   "webrtc/RTCPeerConnection-setRemoteDescription-rollback.html": [
-   "69edabd4812f662862fc3820f56a823741fcc045",
+   "af10b6542e99a190bb62c8375a1896c6681a8022",
    "testharness"
   ],
   "webrtc/RTCPeerConnection-setRemoteDescription-tracks.https-expected.txt": [
@@ -398546,7 +398669,7 @@
    "support"
   ],
   "webrtc/RTCPeerConnection-setRemoteDescription-tracks.https.html": [
-   "3f1bcf8c14486cac9baf7fba1d4cedab16e172f1",
+   "b40a9d3d52fd846f695482671877634359e86ab3",
    "testharness"
   ],
   "webrtc/RTCPeerConnection-setRemoteDescription.html": [
@@ -398558,7 +398681,7 @@
    "support"
   ],
   "webrtc/RTCPeerConnection-track-stats.https.html": [
-   "c764f697b787a50882375dec88d32c6be515a9d4",
+   "d40ed4a64f9e769c21060b0ba9b593938d8f8403",
    "testharness"
   ],
   "webrtc/RTCPeerConnectionIceEvent-constructor-expected.txt": [
@@ -398578,7 +398701,7 @@
    "support"
   ],
   "webrtc/RTCRtpParameters-codecs.html": [
-   "b9ba3d410e50400b7f8a41956439c4e19b14daf0",
+   "56f7ca6bd03087b3858c6decde1387cd4017fd3b",
    "testharness"
   ],
   "webrtc/RTCRtpParameters-degradationPreference-expected.txt": [
@@ -398586,7 +398709,7 @@
    "support"
   ],
   "webrtc/RTCRtpParameters-degradationPreference.html": [
-   "8f03fb8300b92360e907f567d35660dec84d6343",
+   "8da53caafd7b98c462f75ef45ed0488a74c378c7",
    "testharness"
   ],
   "webrtc/RTCRtpParameters-encodings-expected.txt": [
@@ -398594,7 +398717,7 @@
    "support"
   ],
   "webrtc/RTCRtpParameters-encodings.html": [
-   "e7ff72c2ef0066bc05842ebbb3c991bc9320c102",
+   "76d4a6dccec508ea25d8c0bc3037a25a7db3f3ac",
    "testharness"
   ],
   "webrtc/RTCRtpParameters-headerExtensions-expected.txt": [
@@ -398602,7 +398725,7 @@
    "support"
   ],
   "webrtc/RTCRtpParameters-headerExtensions.html": [
-   "8bc6b13b74eb1026240822672b0267381a7b984a",
+   "11af81bd75e189e541468a7766b4af77034914f4",
    "testharness"
   ],
   "webrtc/RTCRtpParameters-helper.js": [
@@ -398614,7 +398737,7 @@
    "support"
   ],
   "webrtc/RTCRtpParameters-rtcp.html": [
-   "275b24f5688c7eeca316afa3fccda8533e1e0eda",
+   "1fa435f3f9be15799f4d45de4dc0995dcc01b156",
    "testharness"
   ],
   "webrtc/RTCRtpParameters-transactionId-expected.txt": [
@@ -398622,7 +398745,7 @@
    "support"
   ],
   "webrtc/RTCRtpParameters-transactionId.html": [
-   "7d94448a9767caafd0f0b341b4d61e0c586942ed",
+   "acb3d37db30fb2d436cc130c4a47601aa38625c8",
    "testharness"
   ],
   "webrtc/RTCRtpReceiver-getCapabilities-expected.txt": [
@@ -398638,7 +398761,7 @@
    "support"
   ],
   "webrtc/RTCRtpReceiver-getContributingSources.https.html": [
-   "11a63da6218738b5d67f0a7f15e57a077e76ba89",
+   "ce5367315aad59d4e0c847643b05318cea1cd31c",
    "testharness"
   ],
   "webrtc/RTCRtpReceiver-getParameters-expected.txt": [
@@ -398654,7 +398777,7 @@
    "support"
   ],
   "webrtc/RTCRtpReceiver-getStats.https.html": [
-   "ac5c0244fe64a5c07a7d255003c783e27a699728",
+   "0ead17ad0504866cac28dbb9be20376b55e60a1a",
    "testharness"
   ],
   "webrtc/RTCRtpReceiver-getSynchronizationSources.https-expected.txt": [
@@ -398662,7 +398785,7 @@
    "support"
   ],
   "webrtc/RTCRtpReceiver-getSynchronizationSources.https.html": [
-   "11aa1d9f6833dd019ae7ade7b9ec14780f271650",
+   "621d3a3fc636d4c4a065998333405977c38f87b1",
    "testharness"
   ],
   "webrtc/RTCRtpSender-getCapabilities-expected.txt": [
@@ -398678,7 +398801,7 @@
    "support"
   ],
   "webrtc/RTCRtpSender-getStats.https.html": [
-   "ee215306e1d9d1fdcb65bd5244da09fb2005e799",
+   "ba31d1217805d647f5efc31e6d4cadc09a8ae426",
    "testharness"
   ],
   "webrtc/RTCRtpSender-replaceTrack-expected.txt": [
@@ -398686,7 +398809,7 @@
    "support"
   ],
   "webrtc/RTCRtpSender-replaceTrack.html": [
-   "f7b8caa578c9c818e8ca11777daf664ccb9457ec",
+   "ea6ff719d0939e22fd5af2c72af009a1c9602c93",
    "testharness"
   ],
   "webrtc/RTCRtpSender-setParameters-expected.txt": [
@@ -398694,7 +398817,7 @@
    "support"
   ],
   "webrtc/RTCRtpSender-setParameters.html": [
-   "615bd9591e0f9c873827c9ae8e787b12d2efaf0f",
+   "b01436d8c7b71b84b4bdc1b58ea329967889bc32",
    "testharness"
   ],
   "webrtc/RTCRtpTransceiver-setCodecPreferences-expected.txt": [
@@ -398710,7 +398833,7 @@
    "support"
   ],
   "webrtc/RTCRtpTransceiver-setDirection.html": [
-   "539eaba516eef7419c5e543d7218a41f850f5e7b",
+   "98e0693d3a142f44bdff04137e68e8f3050fe187",
    "testharness"
   ],
   "webrtc/RTCSctpTransport-constructor-expected.txt": [
@@ -398718,7 +398841,7 @@
    "support"
   ],
   "webrtc/RTCSctpTransport-constructor.html": [
-   "b92f3acf5113a475b58892f48406aafc9634be07",
+   "1d2b261ccea3ed00f2c91e877838ca5866023877",
    "testharness"
   ],
   "webrtc/RTCSctpTransport-maxMessageSize-expected.txt": [
@@ -398726,7 +398849,7 @@
    "support"
   ],
   "webrtc/RTCSctpTransport-maxMessageSize.html": [
-   "4534a810f47cdca106f5300939acc36275222637",
+   "d9d9712b2be76d3d43d7a7199e2d44ddef757261",
    "testharness"
   ],
   "webrtc/RTCStats-helper.js": [
@@ -400141,6 +400264,10 @@
    "34eaa588ed78672070782cb556939ea711a18caf",
    "support"
   ],
+  "webusb/idlharness.https-expected.txt": [
+   "8075cc9a82676b6aa168911d70ea3e1733a9d256",
+   "support"
+  ],
   "webusb/idlharness.https.html": [
    "5a97c893eb0e23e3cba14501de9955cfbb0b385a",
    "testharness"
@@ -400237,10 +400364,18 @@
    "f08a98a927d57cda8b780a8304a0fa6cf727cc81",
    "testharness"
   ],
+  "webusb/worker/idlharness.dedicatedworker.https-expected.txt": [
+   "8b1c712fabf1386283095092eb35e4b9069643b2",
+   "support"
+  ],
   "webusb/worker/idlharness.dedicatedworker.https.html": [
    "159ede02aac087e0409632c2fcbac3a597ec4c45",
    "testharness"
   ],
+  "webusb/worker/idlharness.sharedworker.https-expected.txt": [
+   "8b1c712fabf1386283095092eb35e4b9069643b2",
+   "support"
+  ],
   "webusb/worker/idlharness.sharedworker.https.html": [
    "4dc8b85f2590397f6e8bcbf63dc64381b1f95559",
    "testharness"
@@ -400270,7 +400405,7 @@
    "support"
   ],
   "webvr/idlharness.https-expected.txt": [
-   "269060d5d14e45f275a036ddbac0d29d81963402",
+   "bd39e3612b6081f806e667bdf5906783ff82ca9e",
    "support"
   ],
   "webvr/idlharness.https.html": [
@@ -403178,7 +403313,7 @@
    "support"
   ],
   "webxr/interfaces.https-expected.txt": [
-   "4784c0fbd89f5367f538218af96859523dc75d8f",
+   "c5671a172cff81a9c539caaa89df5f729ade2058",
    "support"
   ],
   "webxr/interfaces.https.html": [
@@ -405181,10 +405316,6 @@
    "1cb82348a9d6f3be34da762267cce7389f715f7c",
    "testharness"
   ],
-  "xhr/interfaces-expected.txt": [
-   "325a44ee279579cf6441fab6830c1cec733089d4",
-   "support"
-  ],
   "xhr/interfaces.html": [
    "eb4babf67805d1d65bcbc44c6dcc1cb3ca793695",
    "testharness"
diff --git a/third_party/WebKit/LayoutTests/external/wpt/FileAPI/idlharness-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/FileAPI/idlharness-expected.txt
new file mode 100644
index 0000000..b8ff4c27
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/FileAPI/idlharness-expected.txt
@@ -0,0 +1,125 @@
+This is a testharness.js-based test.
+Found 121 tests; 120 PASS, 1 FAIL, 0 TIMEOUT, 0 NOTRUN.
+PASS Partial interface URL: original interface defined
+FAIL Partial interface URL: valid exposure set Partial URL interface is exposed to 'DedicatedWorker', the original interface is not.
+PASS URL interface: operation createObjectURL(Blob)
+PASS Unscopable handled correctly for createObjectURL(Blob) on URL
+PASS URL interface: operation revokeObjectURL(DOMString)
+PASS Unscopable handled correctly for revokeObjectURL(DOMString) on URL
+PASS Blob interface: existence and properties of interface object
+PASS Blob interface object length
+PASS Blob interface object name
+PASS Blob interface: existence and properties of interface prototype object
+PASS Blob interface: existence and properties of interface prototype object's "constructor" property
+PASS Blob interface: existence and properties of interface prototype object's @@unscopables property
+PASS Blob interface: attribute size
+PASS Unscopable handled correctly for size property on Blob
+PASS Blob interface: attribute type
+PASS Unscopable handled correctly for type property on Blob
+PASS Blob interface: operation slice(long long, long long, DOMString)
+PASS Unscopable handled correctly for slice(long long, long long, DOMString) on Blob
+PASS Blob must be primary interface of new Blob(["TEST"])
+PASS Stringification of new Blob(["TEST"])
+PASS Blob interface: new Blob(["TEST"]) must inherit property "size" with the proper type
+PASS Blob interface: new Blob(["TEST"]) must inherit property "type" with the proper type
+PASS Blob interface: new Blob(["TEST"]) must inherit property "slice(long long, long long, DOMString)" with the proper type
+PASS Blob interface: calling slice(long long, long long, DOMString) on new Blob(["TEST"]) with too few arguments must throw TypeError
+PASS File interface: existence and properties of interface object
+PASS File interface object length
+PASS File interface object name
+PASS File interface: existence and properties of interface prototype object
+PASS File interface: existence and properties of interface prototype object's "constructor" property
+PASS File interface: existence and properties of interface prototype object's @@unscopables property
+PASS File interface: attribute name
+PASS Unscopable handled correctly for name property on File
+PASS File interface: attribute lastModified
+PASS Unscopable handled correctly for lastModified property on File
+PASS File must be primary interface of new File(["myFileBits"], "myFileName")
+PASS Stringification of new File(["myFileBits"], "myFileName")
+PASS File interface: new File(["myFileBits"], "myFileName") must inherit property "name" with the proper type
+PASS File interface: new File(["myFileBits"], "myFileName") must inherit property "lastModified" with the proper type
+PASS Blob interface: new File(["myFileBits"], "myFileName") must inherit property "size" with the proper type
+PASS Blob interface: new File(["myFileBits"], "myFileName") must inherit property "type" with the proper type
+PASS Blob interface: new File(["myFileBits"], "myFileName") must inherit property "slice(long long, long long, DOMString)" with the proper type
+PASS Blob interface: calling slice(long long, long long, DOMString) on new File(["myFileBits"], "myFileName") with too few arguments must throw TypeError
+PASS FileList interface: existence and properties of interface object
+PASS FileList interface object length
+PASS FileList interface object name
+PASS FileList interface: existence and properties of interface prototype object
+PASS FileList interface: existence and properties of interface prototype object's "constructor" property
+PASS FileList interface: existence and properties of interface prototype object's @@unscopables property
+PASS FileList interface: operation item(unsigned long)
+PASS Unscopable handled correctly for item(unsigned long) on FileList
+PASS FileList interface: attribute length
+PASS Unscopable handled correctly for length property on FileList
+PASS FileList must be primary interface of file_input.files
+PASS Stringification of file_input.files
+PASS FileList interface: file_input.files must inherit property "item(unsigned long)" with the proper type
+PASS FileList interface: calling item(unsigned long) on file_input.files with too few arguments must throw TypeError
+PASS FileList interface: file_input.files must inherit property "length" with the proper type
+PASS FileReader interface: existence and properties of interface object
+PASS FileReader interface object length
+PASS FileReader interface object name
+PASS FileReader interface: existence and properties of interface prototype object
+PASS FileReader interface: existence and properties of interface prototype object's "constructor" property
+PASS FileReader interface: existence and properties of interface prototype object's @@unscopables property
+PASS FileReader interface: operation readAsArrayBuffer(Blob)
+PASS Unscopable handled correctly for readAsArrayBuffer(Blob) on FileReader
+PASS FileReader interface: operation readAsBinaryString(Blob)
+PASS Unscopable handled correctly for readAsBinaryString(Blob) on FileReader
+PASS FileReader interface: operation readAsText(Blob, DOMString)
+PASS Unscopable handled correctly for readAsText(Blob, DOMString) on FileReader
+PASS FileReader interface: operation readAsDataURL(Blob)
+PASS Unscopable handled correctly for readAsDataURL(Blob) on FileReader
+PASS FileReader interface: operation abort()
+PASS Unscopable handled correctly for abort() on FileReader
+PASS FileReader interface: constant EMPTY on interface object
+PASS FileReader interface: constant EMPTY on interface prototype object
+PASS FileReader interface: constant LOADING on interface object
+PASS FileReader interface: constant LOADING on interface prototype object
+PASS FileReader interface: constant DONE on interface object
+PASS FileReader interface: constant DONE on interface prototype object
+PASS FileReader interface: attribute readyState
+PASS Unscopable handled correctly for readyState property on FileReader
+PASS FileReader interface: attribute result
+PASS Unscopable handled correctly for result property on FileReader
+PASS FileReader interface: attribute error
+PASS Unscopable handled correctly for error property on FileReader
+PASS FileReader interface: attribute onloadstart
+PASS Unscopable handled correctly for onloadstart property on FileReader
+PASS FileReader interface: attribute onprogress
+PASS Unscopable handled correctly for onprogress property on FileReader
+PASS FileReader interface: attribute onload
+PASS Unscopable handled correctly for onload property on FileReader
+PASS FileReader interface: attribute onabort
+PASS Unscopable handled correctly for onabort property on FileReader
+PASS FileReader interface: attribute onerror
+PASS Unscopable handled correctly for onerror property on FileReader
+PASS FileReader interface: attribute onloadend
+PASS Unscopable handled correctly for onloadend property on FileReader
+PASS FileReader must be primary interface of new FileReader()
+PASS Stringification of new FileReader()
+PASS FileReader interface: new FileReader() must inherit property "readAsArrayBuffer(Blob)" with the proper type
+PASS FileReader interface: calling readAsArrayBuffer(Blob) on new FileReader() with too few arguments must throw TypeError
+PASS FileReader interface: new FileReader() must inherit property "readAsBinaryString(Blob)" with the proper type
+PASS FileReader interface: calling readAsBinaryString(Blob) on new FileReader() with too few arguments must throw TypeError
+PASS FileReader interface: new FileReader() must inherit property "readAsText(Blob, DOMString)" with the proper type
+PASS FileReader interface: calling readAsText(Blob, DOMString) on new FileReader() with too few arguments must throw TypeError
+PASS FileReader interface: new FileReader() must inherit property "readAsDataURL(Blob)" with the proper type
+PASS FileReader interface: calling readAsDataURL(Blob) on new FileReader() with too few arguments must throw TypeError
+PASS FileReader interface: new FileReader() must inherit property "abort()" with the proper type
+PASS FileReader interface: new FileReader() must inherit property "EMPTY" with the proper type
+PASS FileReader interface: new FileReader() must inherit property "LOADING" with the proper type
+PASS FileReader interface: new FileReader() must inherit property "DONE" with the proper type
+PASS FileReader interface: new FileReader() must inherit property "readyState" with the proper type
+PASS FileReader interface: new FileReader() must inherit property "result" with the proper type
+PASS FileReader interface: new FileReader() must inherit property "error" with the proper type
+PASS FileReader interface: new FileReader() must inherit property "onloadstart" with the proper type
+PASS FileReader interface: new FileReader() must inherit property "onprogress" with the proper type
+PASS FileReader interface: new FileReader() must inherit property "onload" with the proper type
+PASS FileReader interface: new FileReader() must inherit property "onabort" with the proper type
+PASS FileReader interface: new FileReader() must inherit property "onerror" with the proper type
+PASS FileReader interface: new FileReader() must inherit property "onloadend" with the proper type
+PASS FileReaderSync interface: existence and properties of interface object
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/FileAPI/idlharness.worker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/FileAPI/idlharness.worker-expected.txt
new file mode 100644
index 0000000..d1294e4e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/FileAPI/idlharness.worker-expected.txt
@@ -0,0 +1,141 @@
+This is a testharness.js-based test.
+Found 137 tests; 135 PASS, 2 FAIL, 0 TIMEOUT, 0 NOTRUN.
+PASS Partial interface URL: original interface defined
+FAIL Partial interface URL: valid exposure set Partial URL interface is exposed to 'DedicatedWorker', the original interface is not.
+PASS Window interface: existence and properties of interface object
+FAIL URL interface: existence and properties of interface object assert_false: expected false got true
+PASS Blob interface: existence and properties of interface object
+PASS Blob interface object length
+PASS Blob interface object name
+PASS Blob interface: existence and properties of interface prototype object
+PASS Blob interface: existence and properties of interface prototype object's "constructor" property
+PASS Blob interface: existence and properties of interface prototype object's @@unscopables property
+PASS Blob interface: attribute size
+PASS Unscopable handled correctly for size property on Blob
+PASS Blob interface: attribute type
+PASS Unscopable handled correctly for type property on Blob
+PASS Blob interface: operation slice(long long, long long, DOMString)
+PASS Unscopable handled correctly for slice(long long, long long, DOMString) on Blob
+PASS Blob must be primary interface of new Blob(["TEST"])
+PASS Stringification of new Blob(["TEST"])
+PASS Blob interface: new Blob(["TEST"]) must inherit property "size" with the proper type
+PASS Blob interface: new Blob(["TEST"]) must inherit property "type" with the proper type
+PASS Blob interface: new Blob(["TEST"]) must inherit property "slice(long long, long long, DOMString)" with the proper type
+PASS Blob interface: calling slice(long long, long long, DOMString) on new Blob(["TEST"]) with too few arguments must throw TypeError
+PASS File interface: existence and properties of interface object
+PASS File interface object length
+PASS File interface object name
+PASS File interface: existence and properties of interface prototype object
+PASS File interface: existence and properties of interface prototype object's "constructor" property
+PASS File interface: existence and properties of interface prototype object's @@unscopables property
+PASS File interface: attribute name
+PASS Unscopable handled correctly for name property on File
+PASS File interface: attribute lastModified
+PASS Unscopable handled correctly for lastModified property on File
+PASS File must be primary interface of new File(["myFileBits"], "myFileName")
+PASS Stringification of new File(["myFileBits"], "myFileName")
+PASS File interface: new File(["myFileBits"], "myFileName") must inherit property "name" with the proper type
+PASS File interface: new File(["myFileBits"], "myFileName") must inherit property "lastModified" with the proper type
+PASS Blob interface: new File(["myFileBits"], "myFileName") must inherit property "size" with the proper type
+PASS Blob interface: new File(["myFileBits"], "myFileName") must inherit property "type" with the proper type
+PASS Blob interface: new File(["myFileBits"], "myFileName") must inherit property "slice(long long, long long, DOMString)" with the proper type
+PASS Blob interface: calling slice(long long, long long, DOMString) on new File(["myFileBits"], "myFileName") with too few arguments must throw TypeError
+PASS FileList interface: existence and properties of interface object
+PASS FileList interface object length
+PASS FileList interface object name
+PASS FileList interface: existence and properties of interface prototype object
+PASS FileList interface: existence and properties of interface prototype object's "constructor" property
+PASS FileList interface: existence and properties of interface prototype object's @@unscopables property
+PASS FileList interface: operation item(unsigned long)
+PASS Unscopable handled correctly for item(unsigned long) on FileList
+PASS FileList interface: attribute length
+PASS Unscopable handled correctly for length property on FileList
+PASS FileReader interface: existence and properties of interface object
+PASS FileReader interface object length
+PASS FileReader interface object name
+PASS FileReader interface: existence and properties of interface prototype object
+PASS FileReader interface: existence and properties of interface prototype object's "constructor" property
+PASS FileReader interface: existence and properties of interface prototype object's @@unscopables property
+PASS FileReader interface: operation readAsArrayBuffer(Blob)
+PASS Unscopable handled correctly for readAsArrayBuffer(Blob) on FileReader
+PASS FileReader interface: operation readAsBinaryString(Blob)
+PASS Unscopable handled correctly for readAsBinaryString(Blob) on FileReader
+PASS FileReader interface: operation readAsText(Blob, DOMString)
+PASS Unscopable handled correctly for readAsText(Blob, DOMString) on FileReader
+PASS FileReader interface: operation readAsDataURL(Blob)
+PASS Unscopable handled correctly for readAsDataURL(Blob) on FileReader
+PASS FileReader interface: operation abort()
+PASS Unscopable handled correctly for abort() on FileReader
+PASS FileReader interface: constant EMPTY on interface object
+PASS FileReader interface: constant EMPTY on interface prototype object
+PASS FileReader interface: constant LOADING on interface object
+PASS FileReader interface: constant LOADING on interface prototype object
+PASS FileReader interface: constant DONE on interface object
+PASS FileReader interface: constant DONE on interface prototype object
+PASS FileReader interface: attribute readyState
+PASS Unscopable handled correctly for readyState property on FileReader
+PASS FileReader interface: attribute result
+PASS Unscopable handled correctly for result property on FileReader
+PASS FileReader interface: attribute error
+PASS Unscopable handled correctly for error property on FileReader
+PASS FileReader interface: attribute onloadstart
+PASS Unscopable handled correctly for onloadstart property on FileReader
+PASS FileReader interface: attribute onprogress
+PASS Unscopable handled correctly for onprogress property on FileReader
+PASS FileReader interface: attribute onload
+PASS Unscopable handled correctly for onload property on FileReader
+PASS FileReader interface: attribute onabort
+PASS Unscopable handled correctly for onabort property on FileReader
+PASS FileReader interface: attribute onerror
+PASS Unscopable handled correctly for onerror property on FileReader
+PASS FileReader interface: attribute onloadend
+PASS Unscopable handled correctly for onloadend property on FileReader
+PASS FileReader must be primary interface of new FileReader()
+PASS Stringification of new FileReader()
+PASS FileReader interface: new FileReader() must inherit property "readAsArrayBuffer(Blob)" with the proper type
+PASS FileReader interface: calling readAsArrayBuffer(Blob) on new FileReader() with too few arguments must throw TypeError
+PASS FileReader interface: new FileReader() must inherit property "readAsBinaryString(Blob)" with the proper type
+PASS FileReader interface: calling readAsBinaryString(Blob) on new FileReader() with too few arguments must throw TypeError
+PASS FileReader interface: new FileReader() must inherit property "readAsText(Blob, DOMString)" with the proper type
+PASS FileReader interface: calling readAsText(Blob, DOMString) on new FileReader() with too few arguments must throw TypeError
+PASS FileReader interface: new FileReader() must inherit property "readAsDataURL(Blob)" with the proper type
+PASS FileReader interface: calling readAsDataURL(Blob) on new FileReader() with too few arguments must throw TypeError
+PASS FileReader interface: new FileReader() must inherit property "abort()" with the proper type
+PASS FileReader interface: new FileReader() must inherit property "EMPTY" with the proper type
+PASS FileReader interface: new FileReader() must inherit property "LOADING" with the proper type
+PASS FileReader interface: new FileReader() must inherit property "DONE" with the proper type
+PASS FileReader interface: new FileReader() must inherit property "readyState" with the proper type
+PASS FileReader interface: new FileReader() must inherit property "result" with the proper type
+PASS FileReader interface: new FileReader() must inherit property "error" with the proper type
+PASS FileReader interface: new FileReader() must inherit property "onloadstart" with the proper type
+PASS FileReader interface: new FileReader() must inherit property "onprogress" with the proper type
+PASS FileReader interface: new FileReader() must inherit property "onload" with the proper type
+PASS FileReader interface: new FileReader() must inherit property "onabort" with the proper type
+PASS FileReader interface: new FileReader() must inherit property "onerror" with the proper type
+PASS FileReader interface: new FileReader() must inherit property "onloadend" with the proper type
+PASS FileReaderSync interface: existence and properties of interface object
+PASS FileReaderSync interface object length
+PASS FileReaderSync interface object name
+PASS FileReaderSync interface: existence and properties of interface prototype object
+PASS FileReaderSync interface: existence and properties of interface prototype object's "constructor" property
+PASS FileReaderSync interface: existence and properties of interface prototype object's @@unscopables property
+PASS FileReaderSync interface: operation readAsArrayBuffer(Blob)
+PASS Unscopable handled correctly for readAsArrayBuffer(Blob) on FileReaderSync
+PASS FileReaderSync interface: operation readAsBinaryString(Blob)
+PASS Unscopable handled correctly for readAsBinaryString(Blob) on FileReaderSync
+PASS FileReaderSync interface: operation readAsText(Blob, DOMString)
+PASS Unscopable handled correctly for readAsText(Blob, DOMString) on FileReaderSync
+PASS FileReaderSync interface: operation readAsDataURL(Blob)
+PASS Unscopable handled correctly for readAsDataURL(Blob) on FileReaderSync
+PASS FileReaderSync must be primary interface of new FileReaderSync()
+PASS Stringification of new FileReaderSync()
+PASS FileReaderSync interface: new FileReaderSync() must inherit property "readAsArrayBuffer(Blob)" with the proper type
+PASS FileReaderSync interface: calling readAsArrayBuffer(Blob) on new FileReaderSync() with too few arguments must throw TypeError
+PASS FileReaderSync interface: new FileReaderSync() must inherit property "readAsBinaryString(Blob)" with the proper type
+PASS FileReaderSync interface: calling readAsBinaryString(Blob) on new FileReaderSync() with too few arguments must throw TypeError
+PASS FileReaderSync interface: new FileReaderSync() must inherit property "readAsText(Blob, DOMString)" with the proper type
+PASS FileReaderSync interface: calling readAsText(Blob, DOMString) on new FileReaderSync() with too few arguments must throw TypeError
+PASS FileReaderSync interface: new FileReaderSync() must inherit property "readAsDataURL(Blob)" with the proper type
+PASS FileReaderSync interface: calling readAsDataURL(Blob) on new FileReaderSync() with too few arguments must throw TypeError
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/interfaces.any-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/interfaces.any-expected.txt
deleted file mode 100644
index a20681d..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/interfaces.any-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-FAIL Test driver promise_test: Unhandled rejection with value: object "Partial interface Window with no original interface"
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/interfaces.any.worker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/interfaces.any.worker-expected.txt
deleted file mode 100644
index a20681d..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/interfaces.any.worker-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-FAIL Test driver promise_test: Unhandled rejection with value: object "Partial interface Window with no original interface"
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/README.md b/third_party/WebKit/LayoutTests/external/wpt/README.md
index 84cd627..773dbf3 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/README.md
+++ b/third_party/WebKit/LayoutTests/external/wpt/README.md
@@ -433,7 +433,7 @@
 Search filters to find things to review:
 
 * [Open PRs (excluding vendor exports)](https://github.com/web-platform-tests/wpt/pulls?utf8=%E2%9C%93&q=is%3Apr+is%3Aopen+-label%3A%22mozilla%3Agecko-sync%22+-label%3A%22chromium-export%22+-label%3A%22webkit-export%22+-label%3A%22servo-export%22)
-* [Reviewed but still open PRs (excluding vendor exports)](https://github.com/web-platform-tests/wpt/pulls?q=is%3Apr+is%3Aopen+-label%3Amozilla%3Agecko-sync+-label%3Achromium-export+-label%3Awebkit-export+-label%3Aservo-export+review%3Aapproved) (Merge? Something left to fix? Ping other reviewer?)
+* [Reviewed but still open PRs (excluding vendor exports)](https://github.com/web-platform-tests/wpt/pulls?utf8=%E2%9C%93&q=is%3Apr+is%3Aopen+-label%3Amozilla%3Agecko-sync+-label%3Achromium-export+-label%3Awebkit-export+-label%3Aservo-export+review%3Aapproved+-label%3A%22do+not+merge+yet%22+-label%3A%22status%3Aneeds-spec-decision%22) (Merge? Something left to fix? Ping other reviewer?)
 * [Open PRs without owners](https://github.com/web-platform-tests/wpt/pulls?q=is%3Apr+is%3Aopen+label%3Astatus%3Aneeds-owners)
 * [Open PRs with label `infra` (excluding vendor exports)](https://github.com/web-platform-tests/wpt/pulls?utf8=%E2%9C%93&q=is%3Apr+is%3Aopen+label%3Ainfra+-label%3A%22mozilla%3Agecko-sync%22+-label%3A%22chromium-export%22+-label%3A%22webkit-export%22+-label%3A%22servo-export%22)
 * [Open PRs with label `docs` (excluding vendor exports)](https://github.com/web-platform-tests/wpt/pulls?utf8=%E2%9C%93&q=is%3Apr+is%3Aopen+label%3Adocs+-label%3A%22mozilla%3Agecko-sync%22+-label%3A%22chromium-export%22+-label%3A%22webkit-export%22+-label%3A%22servo-export%22)
diff --git a/third_party/WebKit/LayoutTests/external/wpt/accelerometer/idlharness.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/accelerometer/idlharness.https-expected.txt
index d7263a21..1911e73ae 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/accelerometer/idlharness.https-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/accelerometer/idlharness.https-expected.txt
@@ -1,4 +1,89 @@
 This is a testharness.js-based test.
-FAIL Test IDL implementation of Accelerometer Sensor promise_test: Unhandled rejection with value: object "Partial interface Window with no original interface"
+PASS Test IDL implementation of Accelerometer Sensor
+PASS Sensor interface: existence and properties of interface object
+PASS Sensor interface object length
+PASS Sensor interface object name
+PASS Sensor interface: existence and properties of interface prototype object
+PASS Sensor interface: existence and properties of interface prototype object's "constructor" property
+PASS Sensor interface: existence and properties of interface prototype object's @@unscopables property
+PASS Sensor interface: attribute activated
+PASS Unscopable handled correctly for activated property on Sensor
+PASS Sensor interface: attribute hasReading
+PASS Unscopable handled correctly for hasReading property on Sensor
+PASS Sensor interface: attribute timestamp
+PASS Unscopable handled correctly for timestamp property on Sensor
+PASS Sensor interface: operation start()
+PASS Unscopable handled correctly for start() on Sensor
+PASS Sensor interface: operation stop()
+PASS Unscopable handled correctly for stop() on Sensor
+PASS Sensor interface: attribute onreading
+PASS Unscopable handled correctly for onreading property on Sensor
+PASS Sensor interface: attribute onactivate
+PASS Unscopable handled correctly for onactivate property on Sensor
+PASS Sensor interface: attribute onerror
+PASS Unscopable handled correctly for onerror property on Sensor
+PASS Accelerometer interface: existence and properties of interface object
+PASS Accelerometer interface object length
+PASS Accelerometer interface object name
+PASS Accelerometer interface: existence and properties of interface prototype object
+PASS Accelerometer interface: existence and properties of interface prototype object's "constructor" property
+PASS Accelerometer interface: existence and properties of interface prototype object's @@unscopables property
+PASS Accelerometer interface: attribute x
+PASS Unscopable handled correctly for x property on Accelerometer
+PASS Accelerometer interface: attribute y
+PASS Unscopable handled correctly for y property on Accelerometer
+PASS Accelerometer interface: attribute z
+PASS Unscopable handled correctly for z property on Accelerometer
+PASS Accelerometer must be primary interface of new Accelerometer();
+PASS Stringification of new Accelerometer();
+PASS Accelerometer interface: new Accelerometer(); must inherit property "x" with the proper type
+PASS Accelerometer interface: new Accelerometer(); must inherit property "y" with the proper type
+PASS Accelerometer interface: new Accelerometer(); must inherit property "z" with the proper type
+PASS Sensor interface: new Accelerometer(); must inherit property "activated" with the proper type
+PASS Sensor interface: new Accelerometer(); must inherit property "hasReading" with the proper type
+PASS Sensor interface: new Accelerometer(); must inherit property "timestamp" with the proper type
+PASS Sensor interface: new Accelerometer(); must inherit property "start()" with the proper type
+PASS Sensor interface: new Accelerometer(); must inherit property "stop()" with the proper type
+PASS Sensor interface: new Accelerometer(); must inherit property "onreading" with the proper type
+PASS Sensor interface: new Accelerometer(); must inherit property "onactivate" with the proper type
+PASS Sensor interface: new Accelerometer(); must inherit property "onerror" with the proper type
+PASS LinearAccelerationSensor interface: existence and properties of interface object
+PASS LinearAccelerationSensor interface object length
+PASS LinearAccelerationSensor interface object name
+PASS LinearAccelerationSensor interface: existence and properties of interface prototype object
+PASS LinearAccelerationSensor interface: existence and properties of interface prototype object's "constructor" property
+PASS LinearAccelerationSensor interface: existence and properties of interface prototype object's @@unscopables property
+PASS LinearAccelerationSensor must be primary interface of new LinearAccelerationSensor();
+PASS Stringification of new LinearAccelerationSensor();
+PASS Accelerometer interface: new LinearAccelerationSensor(); must inherit property "x" with the proper type
+PASS Accelerometer interface: new LinearAccelerationSensor(); must inherit property "y" with the proper type
+PASS Accelerometer interface: new LinearAccelerationSensor(); must inherit property "z" with the proper type
+PASS Sensor interface: new LinearAccelerationSensor(); must inherit property "activated" with the proper type
+PASS Sensor interface: new LinearAccelerationSensor(); must inherit property "hasReading" with the proper type
+PASS Sensor interface: new LinearAccelerationSensor(); must inherit property "timestamp" with the proper type
+PASS Sensor interface: new LinearAccelerationSensor(); must inherit property "start()" with the proper type
+PASS Sensor interface: new LinearAccelerationSensor(); must inherit property "stop()" with the proper type
+PASS Sensor interface: new LinearAccelerationSensor(); must inherit property "onreading" with the proper type
+PASS Sensor interface: new LinearAccelerationSensor(); must inherit property "onactivate" with the proper type
+PASS Sensor interface: new LinearAccelerationSensor(); must inherit property "onerror" with the proper type
+FAIL GravitySensor interface: existence and properties of interface object assert_own_property: self does not have own property "GravitySensor" expected property "GravitySensor" missing
+FAIL GravitySensor interface object length assert_own_property: self does not have own property "GravitySensor" expected property "GravitySensor" missing
+FAIL GravitySensor interface object name assert_own_property: self does not have own property "GravitySensor" expected property "GravitySensor" missing
+FAIL GravitySensor interface: existence and properties of interface prototype object assert_own_property: self does not have own property "GravitySensor" expected property "GravitySensor" missing
+FAIL GravitySensor interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "GravitySensor" expected property "GravitySensor" missing
+FAIL GravitySensor interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "GravitySensor" expected property "GravitySensor" missing
+FAIL GravitySensor must be primary interface of new GravitySensor(); assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: GravitySensor is not defined"
+FAIL Stringification of new GravitySensor(); assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: GravitySensor is not defined"
+FAIL Accelerometer interface: new GravitySensor(); must inherit property "x" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: GravitySensor is not defined"
+FAIL Accelerometer interface: new GravitySensor(); must inherit property "y" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: GravitySensor is not defined"
+FAIL Accelerometer interface: new GravitySensor(); must inherit property "z" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: GravitySensor is not defined"
+FAIL Sensor interface: new GravitySensor(); must inherit property "activated" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: GravitySensor is not defined"
+FAIL Sensor interface: new GravitySensor(); must inherit property "hasReading" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: GravitySensor is not defined"
+FAIL Sensor interface: new GravitySensor(); must inherit property "timestamp" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: GravitySensor is not defined"
+FAIL Sensor interface: new GravitySensor(); must inherit property "start()" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: GravitySensor is not defined"
+FAIL Sensor interface: new GravitySensor(); must inherit property "stop()" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: GravitySensor is not defined"
+FAIL Sensor interface: new GravitySensor(); must inherit property "onreading" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: GravitySensor is not defined"
+FAIL Sensor interface: new GravitySensor(); must inherit property "onactivate" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: GravitySensor is not defined"
+FAIL Sensor interface: new GravitySensor(); must inherit property "onerror" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: GravitySensor is not defined"
 Harness: the test ran to completion.
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/background-fetch/interfaces-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/background-fetch/interfaces-expected.txt
index ca96873..f6ef5a2 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/background-fetch/interfaces-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/background-fetch/interfaces-expected.txt
@@ -1,6 +1,8 @@
 This is a testharness.js-based test.
-Found 70 tests; 54 PASS, 16 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 72 tests; 56 PASS, 16 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Exposed interfaces in a Document.
+PASS Partial interface ServiceWorkerGlobalScope: original interface defined
+PASS Partial interface ServiceWorkerRegistration: original interface defined
 PASS ServiceWorkerRegistration interface: attribute backgroundFetch
 PASS Unscopable handled correctly for backgroundFetch property on ServiceWorkerRegistration
 PASS ServiceWorkerGlobalScope interface: existence and properties of interface object
diff --git a/third_party/WebKit/LayoutTests/external/wpt/background-fetch/interfaces-worker.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/background-fetch/interfaces-worker.https-expected.txt
index af6f1333..58dcb19 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/background-fetch/interfaces-worker.https-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/background-fetch/interfaces-worker.https-expected.txt
@@ -1,6 +1,8 @@
 This is a testharness.js-based test.
 PASS Service Worker-scoped tests.
 PASS Exposed interfaces in a Service Worker.
+PASS Partial interface ServiceWorkerGlobalScope: original interface defined
+PASS Partial interface ServiceWorkerRegistration: original interface defined
 FAIL ServiceWorkerRegistration interface: existence and properties of interface object assert_false: expected false got true
 FAIL ServiceWorkerGlobalScope interface: attribute onbackgroundfetched assert_true: The prototype object must have a property "onbackgroundfetched" expected true got false
 PASS Unscopable handled correctly for onbackgroundfetched property on ServiceWorkerGlobalScope
diff --git a/third_party/WebKit/LayoutTests/external/wpt/background-fetch/interfaces.worker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/background-fetch/interfaces.worker-expected.txt
index ef51655..fb83daa 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/background-fetch/interfaces.worker-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/background-fetch/interfaces.worker-expected.txt
@@ -1,6 +1,8 @@
 This is a testharness.js-based test.
-Found 77 tests; 56 PASS, 21 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 79 tests; 58 PASS, 21 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Exposed interfaces in a Service Worker.
+PASS Partial interface ServiceWorkerGlobalScope: original interface defined
+PASS Partial interface ServiceWorkerRegistration: original interface defined
 FAIL ServiceWorkerRegistration interface: existence and properties of interface object assert_false: expected false got true
 FAIL ServiceWorkerGlobalScope interface: attribute onbackgroundfetched assert_own_property: self does not have own property "ServiceWorkerGlobalScope" expected property "ServiceWorkerGlobalScope" missing
 PASS Unscopable handled correctly for onbackgroundfetched property on ServiceWorkerGlobalScope
diff --git a/third_party/WebKit/LayoutTests/external/wpt/budget-api/interfaces.any-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/budget-api/interfaces.any-expected.txt
index 397dfb4c..0864daf1 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/budget-api/interfaces.any-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/budget-api/interfaces.any-expected.txt
@@ -1,4 +1,36 @@
 This is a testharness.js-based test.
-FAIL budget-api interfaces. promise_test: Unhandled rejection with value: object "Multiple 'Exposed' extended attributes on Navigator"
+PASS budget-api interfaces.
+PASS Partial interface Navigator: original interface defined
+PASS Partial interface Navigator: valid exposure set
+PASS Partial interface WorkerNavigator: original interface defined
+PASS Partial interface WorkerNavigator: valid exposure set
+PASS Navigator interface: attribute budget
+PASS Unscopable handled correctly for budget property on Navigator
+PASS WorkerGlobalScope interface: existence and properties of interface object
+PASS DedicatedWorkerGlobalScope interface: existence and properties of interface object
+PASS WorkerNavigator interface: existence and properties of interface object
+PASS WorkerLocation interface: existence and properties of interface object
+FAIL BudgetService interface: existence and properties of interface object assert_own_property: self does not have own property "BudgetService" expected property "BudgetService" missing
+FAIL BudgetService interface object length assert_own_property: self does not have own property "BudgetService" expected property "BudgetService" missing
+FAIL BudgetService interface object name assert_own_property: self does not have own property "BudgetService" expected property "BudgetService" missing
+FAIL BudgetService interface: existence and properties of interface prototype object assert_own_property: self does not have own property "BudgetService" expected property "BudgetService" missing
+FAIL BudgetService interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "BudgetService" expected property "BudgetService" missing
+FAIL BudgetService interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "BudgetService" expected property "BudgetService" missing
+FAIL BudgetService interface: operation getCost(OperationType) assert_own_property: self does not have own property "BudgetService" expected property "BudgetService" missing
+PASS Unscopable handled correctly for getCost(OperationType) on BudgetService
+FAIL BudgetService interface: operation getBudget() assert_own_property: self does not have own property "BudgetService" expected property "BudgetService" missing
+PASS Unscopable handled correctly for getBudget() on BudgetService
+FAIL BudgetService interface: operation reserve(OperationType) assert_own_property: self does not have own property "BudgetService" expected property "BudgetService" missing
+PASS Unscopable handled correctly for reserve(OperationType) on BudgetService
+PASS BudgetState interface: existence and properties of interface object
+PASS BudgetState interface object length
+PASS BudgetState interface object name
+PASS BudgetState interface: existence and properties of interface prototype object
+PASS BudgetState interface: existence and properties of interface prototype object's "constructor" property
+PASS BudgetState interface: existence and properties of interface prototype object's @@unscopables property
+PASS BudgetState interface: attribute budgetAt
+PASS Unscopable handled correctly for budgetAt property on BudgetState
+PASS BudgetState interface: attribute time
+PASS Unscopable handled correctly for time property on BudgetState
 Harness: the test ran to completion.
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/budget-api/interfaces.any.worker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/budget-api/interfaces.any.worker-expected.txt
index 397dfb4c..792fe2e 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/budget-api/interfaces.any.worker-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/budget-api/interfaces.any.worker-expected.txt
@@ -1,4 +1,34 @@
 This is a testharness.js-based test.
-FAIL budget-api interfaces. promise_test: Unhandled rejection with value: object "Multiple 'Exposed' extended attributes on Navigator"
+PASS budget-api interfaces.
+PASS Partial interface Navigator: original interface defined
+PASS Partial interface Navigator: valid exposure set
+PASS Partial interface WorkerNavigator: original interface defined
+PASS Partial interface WorkerNavigator: valid exposure set
+PASS Navigator interface: existence and properties of interface object
+PASS EventListener interface: existence and properties of interface object
+PASS WorkerNavigator interface: attribute budget
+PASS Unscopable handled correctly for budget property on WorkerNavigator
+FAIL BudgetService interface: existence and properties of interface object assert_own_property: self does not have own property "BudgetService" expected property "BudgetService" missing
+FAIL BudgetService interface object length assert_own_property: self does not have own property "BudgetService" expected property "BudgetService" missing
+FAIL BudgetService interface object name assert_own_property: self does not have own property "BudgetService" expected property "BudgetService" missing
+FAIL BudgetService interface: existence and properties of interface prototype object assert_own_property: self does not have own property "BudgetService" expected property "BudgetService" missing
+FAIL BudgetService interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "BudgetService" expected property "BudgetService" missing
+FAIL BudgetService interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "BudgetService" expected property "BudgetService" missing
+FAIL BudgetService interface: operation getCost(OperationType) assert_own_property: self does not have own property "BudgetService" expected property "BudgetService" missing
+PASS Unscopable handled correctly for getCost(OperationType) on BudgetService
+FAIL BudgetService interface: operation getBudget() assert_own_property: self does not have own property "BudgetService" expected property "BudgetService" missing
+PASS Unscopable handled correctly for getBudget() on BudgetService
+FAIL BudgetService interface: operation reserve(OperationType) assert_own_property: self does not have own property "BudgetService" expected property "BudgetService" missing
+PASS Unscopable handled correctly for reserve(OperationType) on BudgetService
+PASS BudgetState interface: existence and properties of interface object
+PASS BudgetState interface object length
+PASS BudgetState interface object name
+PASS BudgetState interface: existence and properties of interface prototype object
+PASS BudgetState interface: existence and properties of interface prototype object's "constructor" property
+PASS BudgetState interface: existence and properties of interface prototype object's @@unscopables property
+PASS BudgetState interface: attribute budgetAt
+PASS Unscopable handled correctly for budgetAt property on BudgetState
+PASS BudgetState interface: attribute time
+PASS Unscopable handled correctly for time property on BudgetState
 Harness: the test ran to completion.
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/compat/interfaces.any-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/compat/interfaces.any-expected.txt
index 9a4306b..78c93b9 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/compat/interfaces.any-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/compat/interfaces.any-expected.txt
@@ -1,5 +1,7 @@
 This is a testharness.js-based test.
 PASS compat interfaces.
+PASS Partial interface Window: original interface defined
+PASS Partial interface HTMLBodyElement: original interface defined
 FAIL Window interface: attribute orientation assert_true: The prototype object must have a property "orientation" expected true got false
 PASS Unscopable handled correctly for orientation property on Window
 FAIL Window interface: attribute onorientationchange assert_true: The prototype object must have a property "onorientationchange" expected true got false
diff --git a/third_party/WebKit/LayoutTests/external/wpt/compat/interfaces.any.worker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/compat/interfaces.any.worker-expected.txt
index 70e5f023..baea3e7 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/compat/interfaces.any.worker-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/compat/interfaces.any.worker-expected.txt
@@ -1,5 +1,7 @@
 This is a testharness.js-based test.
 PASS compat interfaces.
+PASS Partial interface Window: original interface defined
+PASS Partial interface HTMLBodyElement: original interface defined
 PASS Window interface: existence and properties of interface object
 FAIL EventTarget interface: existence and properties of interface object assert_false: expected false got true
 PASS HTMLBodyElement interface: existence and properties of interface object
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts/idlharness-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts/idlharness-expected.txt
index 87affae..cb23c300 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts/idlharness-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-fonts/idlharness-expected.txt
@@ -1,6 +1,8 @@
 This is a testharness.js-based test.
-Found 51 tests; 19 PASS, 32 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 53 tests; 21 PASS, 32 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Test IDL implementation of css-fonts API
+PASS Partial interface CSSRule: original interface defined
+PASS Partial interface CSSRule[2]: original interface defined
 PASS CSSFontFaceRule interface: existence and properties of interface object
 PASS CSSFontFaceRule interface object length
 PASS CSSFontFaceRule interface object name
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-logical/logicalprops-quirklength.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-logical/logicalprops-quirklength.html
index 0431783..3e133db8 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-logical/logicalprops-quirklength.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-logical/logicalprops-quirklength.html
@@ -1,7 +1,8 @@
 <meta charset="utf-8">
-<title>CSS Logical Properties: {max-,min-}block-size</title>
+<title>CSS Logical Properties</title>
 <link rel="author" title="Xu Xing" href="mailto:openxu@gmail.com">
 <link rel="help" href="https://drafts.csswg.org/css-logical-props-1/#logical-dimension-properties">
+<link rel="help" href="https://drafts.csswg.org/css-logical-props-1/#logical-prop">
 <link rel="help" href="https://drafts.csswg.org/css-writing-modes-3/#logical-to-physical">
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
@@ -23,7 +24,12 @@
   {cssText:"inline-size: 1"},
   {cssText:"min-inline-size: 1"},
   {cssText:"max-inline-size: 1"},
+  {cssText:"margin-block-start: 1"},
+  {cssText:"margin-block-end: 1"},
+  {cssText:"margin-inline-start: 1"},
+  {cssText:"margin-inline-end: 1"},
 ];
+
 tests.forEach(function(t) {
   test(() => assert_false(isValidDeclaration(t.cssText)), 'Check that "' + t.cssText + '" is not valid in quirks mode');
 });
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-masking/idlharness-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/css/css-masking/idlharness-expected.txt
new file mode 100644
index 0000000..4b9da1a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-masking/idlharness-expected.txt
@@ -0,0 +1,44 @@
+This is a testharness.js-based test.
+PASS Test IDL implementation of css-masking
+FAIL SVGClipPathElement interface: existence and properties of interface object assert_equals: prototype of SVGClipPathElement is not SVGElement expected function "function SVGElement() { [native code] }" but got function "function SVGGraphicsElement() { [native code] }"
+PASS SVGClipPathElement interface object length
+PASS SVGClipPathElement interface object name
+FAIL SVGClipPathElement interface: existence and properties of interface prototype object assert_equals: prototype of SVGClipPathElement.prototype is not SVGElement.prototype expected object "[object SVGElement]" but got object "[object SVGGraphicsElement]"
+PASS SVGClipPathElement interface: existence and properties of interface prototype object's "constructor" property
+PASS SVGClipPathElement interface: existence and properties of interface prototype object's @@unscopables property
+PASS SVGClipPathElement interface: attribute clipPathUnits
+PASS Unscopable handled correctly for clipPathUnits property on SVGClipPathElement
+FAIL SVGClipPathElement interface: attribute transform assert_own_property: expected property "transform" missing
+PASS Unscopable handled correctly for transform property on SVGClipPathElement
+PASS SVGClipPathElement must be primary interface of [object SVGClipPathElement]
+PASS Stringification of [object SVGClipPathElement]
+PASS SVGClipPathElement interface: [object SVGClipPathElement] must inherit property "clipPathUnits" with the proper type
+PASS SVGClipPathElement interface: [object SVGClipPathElement] must inherit property "transform" with the proper type
+PASS SVGMaskElement interface: existence and properties of interface object
+PASS SVGMaskElement interface object length
+PASS SVGMaskElement interface object name
+PASS SVGMaskElement interface: existence and properties of interface prototype object
+PASS SVGMaskElement interface: existence and properties of interface prototype object's "constructor" property
+PASS SVGMaskElement interface: existence and properties of interface prototype object's @@unscopables property
+PASS SVGMaskElement interface: attribute maskUnits
+PASS Unscopable handled correctly for maskUnits property on SVGMaskElement
+PASS SVGMaskElement interface: attribute maskContentUnits
+PASS Unscopable handled correctly for maskContentUnits property on SVGMaskElement
+PASS SVGMaskElement interface: attribute x
+PASS Unscopable handled correctly for x property on SVGMaskElement
+PASS SVGMaskElement interface: attribute y
+PASS Unscopable handled correctly for y property on SVGMaskElement
+PASS SVGMaskElement interface: attribute width
+PASS Unscopable handled correctly for width property on SVGMaskElement
+PASS SVGMaskElement interface: attribute height
+PASS Unscopable handled correctly for height property on SVGMaskElement
+PASS SVGMaskElement must be primary interface of [object SVGMaskElement]
+PASS Stringification of [object SVGMaskElement]
+PASS SVGMaskElement interface: [object SVGMaskElement] must inherit property "maskUnits" with the proper type
+PASS SVGMaskElement interface: [object SVGMaskElement] must inherit property "maskContentUnits" with the proper type
+PASS SVGMaskElement interface: [object SVGMaskElement] must inherit property "x" with the proper type
+PASS SVGMaskElement interface: [object SVGMaskElement] must inherit property "y" with the proper type
+PASS SVGMaskElement interface: [object SVGMaskElement] must inherit property "width" with the proper type
+PASS SVGMaskElement interface: [object SVGMaskElement] must inherit property "height" with the proper type
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-masking/idlharness.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-masking/idlharness.html
new file mode 100644
index 0000000..71cca64c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-masking/idlharness.html
@@ -0,0 +1,36 @@
+<!doctype html>
+<title>css-masking IDL tests</title>
+<link rel="help" href="https://drafts.fxtf.org/css-masking-1/">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/WebIDLParser.js"></script>
+<script src="/resources/idlharness.js"></script>
+<script>
+  "use strict";
+
+  promise_test(async () => {
+    const idl_array = new IdlArray();
+    const idl = await fetch("/interfaces/css-masking.idl").then(r => r.text());
+    const dom = await fetch("/interfaces/dom.idl").then(r => r.text());
+    idl_array.add_idls(idl);
+    idl_array.add_untested_idls('interface SVGElement : Element {};');
+    idl_array.add_untested_idls('interface SVGAnimatedEnumeration {};');
+    idl_array.add_untested_idls('interface SVGAnimatedLength {};');
+    idl_array.add_untested_idls('interface SVGAnimatedTransformList {};');
+    idl_array.add_dependency_idls(dom); // Needed for Element
+    idl_array.add_objects({
+      SVGClipPathElement: [document.querySelector('#clip1')],
+      SVGMaskElement: [document.querySelector('#mask1')],
+    });
+    idl_array.test();
+  }, "Test IDL implementation of css-masking");
+</script>
+
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:html="http://www.w3.org/1999/xhtml">
+  <clipPath id="clip1">
+    <rect x="50" y="50" width="100" height="100" />
+  </clipPath>
+  <mask id="mask1" x="0" y="0" width="1" height="1" maskContentUnits="objectBoundingBox">
+    <rect x="0" y="0" width="1" height="1" fill="white" />
+  </mask>
+</svg>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/interfaces-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/interfaces-expected.txt
index 394df6ee..e1c61727 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/interfaces-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/interfaces-expected.txt
@@ -1,6 +1,9 @@
 This is a testharness.js-based test.
-Found 333 tests; 323 PASS, 10 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 336 tests; 326 PASS, 10 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS CSS Typed OM IDL test
+PASS Partial interface Element: original interface defined
+PASS Partial interface CSSStyleRule: original interface defined
+PASS Partial interface ElementCSSInlineStyle: original interface defined
 PASS CSSStyleValue interface: existence and properties of interface object
 PASS CSSStyleValue interface object length
 PASS CSSStyleValue interface object name
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/cssom-view/interfaces-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/css/cssom-view/interfaces-expected.txt
index 3514a3c4..b9bdbc0f 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/cssom-view/interfaces-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/cssom-view/interfaces-expected.txt
@@ -1,6 +1,12 @@
 This is a testharness.js-based test.
-Found 385 tests; 310 PASS, 75 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 391 tests; 316 PASS, 75 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Test driver
+PASS Partial interface Window: original interface defined
+PASS Partial interface Document: original interface defined
+PASS Partial interface Element: original interface defined
+PASS Partial interface HTMLElement: original interface defined
+PASS Partial interface HTMLImageElement: original interface defined
+PASS Partial interface Range: original interface defined
 PASS HTMLElement interface: attribute offsetParent
 PASS Unscopable handled correctly for offsetParent property on HTMLElement
 PASS HTMLElement interface: attribute offsetTop
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/cssom/interfaces-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/css/cssom/interfaces-expected.txt
index 4caff94..53012bf 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/css/cssom/interfaces-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/cssom/interfaces-expected.txt
@@ -1,6 +1,8 @@
 This is a testharness.js-based test.
-Found 442 tests; 386 PASS, 56 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 444 tests; 388 PASS, 56 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Test driver
+PASS Partial interface Document: original interface defined
+PASS Partial interface Window: original interface defined
 PASS HTMLElement interface: attribute style
 PASS Unscopable handled correctly for style property on HTMLElement
 PASS HTMLElement interface: style_element must inherit property "style" with the proper type
diff --git a/third_party/WebKit/LayoutTests/external/wpt/dom/interfaces-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/dom/interfaces-expected.txt
index 41820eae..648f8f6 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/dom/interfaces-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/dom/interfaces-expected.txt
@@ -1,6 +1,7 @@
 This is a testharness.js-based test.
-Found 1974 tests; 1953 PASS, 21 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 1975 tests; 1954 PASS, 21 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Test driver
+PASS Partial interface Window: original interface defined
 PASS Event interface: existence and properties of interface object
 PASS Event interface object length
 PASS Event interface object name
diff --git a/third_party/WebKit/LayoutTests/external/wpt/domparsing/interfaces.any-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/domparsing/interfaces.any-expected.txt
deleted file mode 100644
index a20681d..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/domparsing/interfaces.any-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-FAIL Test driver promise_test: Unhandled rejection with value: object "Partial interface Window with no original interface"
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/domparsing/interfaces.any.worker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/domparsing/interfaces.any.worker-expected.txt
deleted file mode 100644
index a20681d..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/domparsing/interfaces.any.worker-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-FAIL Test driver promise_test: Unhandled rejection with value: object "Partial interface Window with no original interface"
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/entries-api/interfaces-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/entries-api/interfaces-expected.txt
index 1d7771b5..9b1ae66 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/entries-api/interfaces-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/entries-api/interfaces-expected.txt
@@ -1,6 +1,9 @@
 This is a testharness.js-based test.
-Found 68 tests; 25 PASS, 43 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 71 tests; 28 PASS, 43 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Entries API: IDL
+PASS Partial interface File: original interface defined
+PASS Partial interface HTMLInputElement: original interface defined
+PASS Partial interface DataTransferItem: original interface defined
 PASS File interface: attribute webkitRelativePath
 PASS Unscopable handled correctly for webkitRelativePath property on File
 PASS File interface: new File([], "example.txt") must inherit property "webkitRelativePath" with the proper type
diff --git a/third_party/WebKit/LayoutTests/external/wpt/fullscreen/interfaces-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/fullscreen/interfaces-expected.txt
deleted file mode 100644
index a20681d..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/fullscreen/interfaces-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-FAIL Test driver promise_test: Unhandled rejection with value: object "Partial interface Window with no original interface"
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/generic-sensor/idlharness.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/generic-sensor/idlharness.https-expected.txt
deleted file mode 100644
index 49a2f3f..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/generic-sensor/idlharness.https-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-FAIL Test IDL implementation of Generic Sensor promise_test: Unhandled rejection with value: object "Partial interface Window with no original interface"
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/gyroscope/idlharness.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/gyroscope/idlharness.https-expected.txt
deleted file mode 100644
index 8b3e3cd..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/gyroscope/idlharness.https-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-FAIL Test IDL implementation of Gyroscope Sensor promise_test: Unhandled rejection with value: object "Partial interface Window with no original interface"
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html-media-capture/idlharness-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html-media-capture/idlharness-expected.txt
index ee3ce07..dcd770d0 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/html-media-capture/idlharness-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/html-media-capture/idlharness-expected.txt
@@ -1,4 +1,5 @@
 This is a testharness.js-based test.
+PASS Partial interface HTMLInputElement: original interface defined
 FAIL HTMLInputElement interface: attribute capture assert_true: The prototype object must have a property "capture" expected true got false
 PASS Unscopable handled correctly for capture property on HTMLInputElement
 FAIL HTMLInputElement interface: [object HTMLInputElement] must inherit property "capture" with the proper type assert_inherits: property "capture" not found in prototype chain
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/browsers/browsing-the-web/history-traversal/popstate_event-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/browsing-the-web/history-traversal/popstate_event-expected.txt
deleted file mode 100644
index 765b112..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/html/browsers/browsing-the-web/history-traversal/popstate_event-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-FAIL Queue a task to fire popstate event assert_false: cancelable expected false got true
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/browsers/the-window-object/window-open-noopener.html b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/the-window-object/window-open-noopener.html
index f9489c3..7d1d430c 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/html/browsers/the-window-object/window-open-noopener.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/the-window-object/window-open-noopener.html
@@ -1,6 +1,12 @@
 <!doctype html>
 <meta charset=utf-8>
 <title>window.open() with "noopener" tests</title>
+
+<meta name="variant" content="?indexed">
+<meta name="variant" content="?_self">
+<meta name="variant" content="?_parent">
+<meta name="variant" content="?_top">
+
 <script src=/resources/testharness.js></script>
 <script src=/resources/testharnessreport.js></script>
 <script>
@@ -28,7 +34,6 @@
     shouldReuse: false },
 ];
 
-var tests = [];
 /**
  * Loop over our testData array and kick off an async test for each entry.  Each
  * async test opens a window using window.open() with some per-test unique name,
@@ -39,56 +44,59 @@
  * cases and non-null in the cases when the existing window gets reused) and so
  * forth.
  */
-for (var i = 0; i < testData.length; ++i) {
-  var test = testData[i];
-  var t = async_test(test.testDescription);
-  tests.push(t);
-  t.secondWindowFeatureString = test.secondWindowFeatureString;
-  t.windowName = "someuniquename" + i;
+function indexedTests() {
+  var tests = [];
+  for(var i = 0; i < testData.length; ++i) {
+    var test = testData[i];
+    var t = async_test(test.testDescription);
+    tests.push(t);
+    t.secondWindowFeatureString = test.secondWindowFeatureString;
+    t.windowName = "someuniquename" + i;
 
-  if (test.shouldReuse) {
-    t.step(function() {
-      var windowName = this.windowName;
+    if (test.shouldReuse) {
+      t.step(function() {
+        var windowName = this.windowName;
 
-      var w1 = window.open("", windowName);
-      this.add_cleanup(function() { w1.close(); });
+        var w1 = window.open("", windowName);
+        this.add_cleanup(function() { w1.close(); });
 
-      assert_equals(w1.opener, window);
-
-      var w2 = window.open("", windowName, this.secondWindowFeatureString);
-      assert_equals(w2, w1);
-      assert_equals(w2.opener, w1.opener);
-      assert_equals(w2.opener, window);
-      this.done();
-    });
-  } else {
-    t.step(function() {
-      var w1;
-      this.add_cleanup(function() {
-        w1.close();
-        channel.postMessage(null);
-      });
-
-      var windowName = this.windowName;
-      var channel = new BroadcastChannel(windowName);
-
-      channel.onmessage = this.step_func_done(function(e) {
-        var data = e.data;
-        assert_equals(data.name, windowName, "Should have the right name");
-        assert_equals(data.haveOpener, false, "Should not have opener");
         assert_equals(w1.opener, window);
-        assert_equals(w1.location.href, "about:blank");
+
+        var w2 = window.open("", windowName, this.secondWindowFeatureString);
+        assert_equals(w2, w1);
+        assert_equals(w2.opener, w1.opener);
+        assert_equals(w2.opener, window);
+        this.done();
       });
+    } else {
+      t.step(function() {
+        var w1;
+        this.add_cleanup(function() {
+          w1.close();
+          channel.postMessage(null);
+        });
 
-      w1 = window.open("", windowName);
-      assert_equals(w1.opener, window);
+        var windowName = this.windowName;
+        var channel = new BroadcastChannel(windowName);
 
-      var w2 = window.open("support/noopener-target.html?" + windowName,
-                           windowName, this.secondWindowFeatureString);
-      assert_equals(w2, null);
+        channel.onmessage = this.step_func_done(function(e) {
+          var data = e.data;
+          assert_equals(data.name, windowName, "Should have the right name");
+          assert_equals(data.haveOpener, false, "Should not have opener");
+          assert_equals(w1.opener, window);
+          assert_equals(w1.location.href, "about:blank");
+        });
 
-      assert_equals(w1.opener, window);
-    });
+        w1 = window.open("", windowName);
+        assert_equals(w1.opener, window);
+
+        var w2 = window.open("support/noopener-target.html?" + windowName,
+                            windowName, this.secondWindowFeatureString);
+        assert_equals(w2, null);
+
+        assert_equals(w1.opener, window);
+      });
+    }
   }
 }
 
@@ -96,13 +104,27 @@
  * Loop over the special targets that ignore noopener and check that doing a
  * window.open() with those targets correctly reuses the existing window.
  */
-for (var target of ["_self", "_parent", "_top"]) {
-  var t = async_test("noopener window.open targeting " + target);
-  tests.push(t);
-  t.openedWindow = window.open(`javascript:var w2 = window.open("", "${target}", "noopener"); this.checkValues(w2); this.close(); void(0);`);
-  assert_equals(t.openedWindow.opener, window);
-  t.openedWindow.checkValues = t.step_func_done(function(win) {
-    assert_equals(win, this.openedWindow);
-  });
+function specialTargetTest(target) {
+  if (["_self", "_parent", "_top"].includes(target)) {
+    var t = async_test("noopener window.open targeting " + target);
+    t.openedWindow = window.open(`javascript:var w2 = window.open("", "${target}", "noopener"); this.checkValues(w2); this.close(); void(0);`);
+    assert_equals(t.openedWindow.opener, window);
+    t.openedWindow.checkValues = t.step_func_done(function(win) {
+      assert_equals(win, this.openedWindow);
+    });
+  } else {
+    throw 'testError: special target must be one of: _self, _parent, _top'
+  }
+}
+
+/**
+ * Parse the Query string, check if it matches keyword 'indexed' to run the indexed tests,
+ * otherwise test it as a special target
+ */
+var variant = window.location.href.split("?")[1]
+if(variant == "indexed") {
+  indexedTests();
+} else {
+  specialTargetTest(variant);
 }
 </script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/browsers/the-window-object/window-open-noopener_indexed-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/the-window-object/window-open-noopener_indexed-expected.txt
new file mode 100644
index 0000000..191f49c4
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/the-window-object/window-open-noopener_indexed-expected.txt
@@ -0,0 +1,10 @@
+This is a testharness.js-based test.
+PASS window.open() with 'noopener' should not reuse existing target
+FAIL noopener needs to be present as a token on its own assert_equals: expected object "[object Window]" but got null
+FAIL noopener needs to be present as a token on its own again assert_equals: expected object "[object Window]" but got null
+FAIL noopener needs to be present as a token on its own yet again assert_equals: expected object "[object Window]" but got null
+PASS Trailing noopener should work
+PASS Leading noopener should work
+PASS Interior noopener should work
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/dom/interfaces.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/dom/interfaces.https-expected.txt
index 1c2e0f2..479cbf8c 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/html/dom/interfaces.https-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/html/dom/interfaces.https-expected.txt
@@ -1,5 +1,41 @@
 This is a testharness.js-based test.
 PASS Test driver
+PASS Partial interface Document: original interface defined
+PASS Partial interface NavigatorID: original interface defined
+PASS Partial interface HTMLAnchorElement: original interface defined
+PASS Partial interface HTMLAreaElement: original interface defined
+PASS Partial interface HTMLBodyElement: original interface defined
+PASS Partial interface HTMLBRElement: original interface defined
+PASS Partial interface HTMLTableCaptionElement: original interface defined
+PASS Partial interface HTMLTableColElement: original interface defined
+PASS Partial interface HTMLDivElement: original interface defined
+PASS Partial interface HTMLDListElement: original interface defined
+PASS Partial interface HTMLEmbedElement: original interface defined
+PASS Partial interface HTMLHeadingElement: original interface defined
+PASS Partial interface HTMLHRElement: original interface defined
+PASS Partial interface HTMLHtmlElement: original interface defined
+PASS Partial interface HTMLIFrameElement: original interface defined
+PASS Partial interface HTMLImageElement: original interface defined
+PASS Partial interface HTMLInputElement: original interface defined
+PASS Partial interface HTMLLegendElement: original interface defined
+PASS Partial interface HTMLLIElement: original interface defined
+PASS Partial interface HTMLLinkElement: original interface defined
+PASS Partial interface HTMLMenuElement: original interface defined
+PASS Partial interface HTMLMetaElement: original interface defined
+PASS Partial interface HTMLObjectElement: original interface defined
+PASS Partial interface HTMLOListElement: original interface defined
+PASS Partial interface HTMLParagraphElement: original interface defined
+PASS Partial interface HTMLParamElement: original interface defined
+PASS Partial interface HTMLPreElement: original interface defined
+PASS Partial interface HTMLStyleElement: original interface defined
+PASS Partial interface HTMLScriptElement: original interface defined
+PASS Partial interface HTMLTableElement: original interface defined
+PASS Partial interface HTMLTableSectionElement: original interface defined
+PASS Partial interface HTMLTableCellElement: original interface defined
+PASS Partial interface HTMLTableRowElement: original interface defined
+PASS Partial interface HTMLUListElement: original interface defined
+PASS Partial interface Document[2]: original interface defined
+PASS Partial interface Window: original interface defined
 PASS Document interface: attribute domain
 PASS Unscopable handled correctly for domain property on Document
 PASS Document interface: attribute referrer
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/dom/interfaces.worker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/dom/interfaces.worker-expected.txt
index f2473ff..5cf29a9 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/html/dom/interfaces.worker-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/html/dom/interfaces.worker-expected.txt
@@ -1,4 +1,40 @@
 This is a testharness.js-based test.
 FAIL Test driver promise_test: Unhandled rejection with value: "SVGElement implements ElementCSSInlineStyle, but SVGElement is undefined."
+PASS Partial interface Document: original interface defined
+PASS Partial interface NavigatorID: original interface defined
+PASS Partial interface HTMLAnchorElement: original interface defined
+PASS Partial interface HTMLAreaElement: original interface defined
+PASS Partial interface HTMLBodyElement: original interface defined
+PASS Partial interface HTMLBRElement: original interface defined
+PASS Partial interface HTMLTableCaptionElement: original interface defined
+PASS Partial interface HTMLTableColElement: original interface defined
+PASS Partial interface HTMLDivElement: original interface defined
+PASS Partial interface HTMLDListElement: original interface defined
+PASS Partial interface HTMLEmbedElement: original interface defined
+PASS Partial interface HTMLHeadingElement: original interface defined
+PASS Partial interface HTMLHRElement: original interface defined
+PASS Partial interface HTMLHtmlElement: original interface defined
+PASS Partial interface HTMLIFrameElement: original interface defined
+PASS Partial interface HTMLImageElement: original interface defined
+PASS Partial interface HTMLInputElement: original interface defined
+PASS Partial interface HTMLLegendElement: original interface defined
+PASS Partial interface HTMLLIElement: original interface defined
+PASS Partial interface HTMLLinkElement: original interface defined
+PASS Partial interface HTMLMenuElement: original interface defined
+PASS Partial interface HTMLMetaElement: original interface defined
+PASS Partial interface HTMLObjectElement: original interface defined
+PASS Partial interface HTMLOListElement: original interface defined
+PASS Partial interface HTMLParagraphElement: original interface defined
+PASS Partial interface HTMLParamElement: original interface defined
+PASS Partial interface HTMLPreElement: original interface defined
+PASS Partial interface HTMLStyleElement: original interface defined
+PASS Partial interface HTMLScriptElement: original interface defined
+PASS Partial interface HTMLTableElement: original interface defined
+PASS Partial interface HTMLTableSectionElement: original interface defined
+PASS Partial interface HTMLTableCellElement: original interface defined
+PASS Partial interface HTMLTableRowElement: original interface defined
+PASS Partial interface HTMLUListElement: original interface defined
+PASS Partial interface Document[2]: original interface defined
+PASS Partial interface Window: original interface defined
 Harness: the test ran to completion.
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/input-device-capabilities/interfaces-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/input-device-capabilities/interfaces-expected.txt
new file mode 100644
index 0000000..6ac1423
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/input-device-capabilities/interfaces-expected.txt
@@ -0,0 +1,22 @@
+This is a testharness.js-based test.
+PASS Test driver
+PASS Partial interface UIEvent: original interface defined
+PASS Partial dictionary UIEventInit: original dictionary defined
+PASS InputDeviceCapabilities interface: existence and properties of interface object
+PASS InputDeviceCapabilities interface object length
+PASS InputDeviceCapabilities interface object name
+PASS InputDeviceCapabilities interface: existence and properties of interface prototype object
+PASS InputDeviceCapabilities interface: existence and properties of interface prototype object's "constructor" property
+PASS InputDeviceCapabilities interface: existence and properties of interface prototype object's @@unscopables property
+PASS InputDeviceCapabilities interface: attribute firesTouchEvents
+PASS Unscopable handled correctly for firesTouchEvents property on InputDeviceCapabilities
+FAIL InputDeviceCapabilities interface: attribute pointerMovementScrolls assert_true: The prototype object must have a property "pointerMovementScrolls" expected true got false
+PASS Unscopable handled correctly for pointerMovementScrolls property on InputDeviceCapabilities
+PASS InputDeviceCapabilities must be primary interface of new InputDeviceCapabilities
+PASS Stringification of new InputDeviceCapabilities
+PASS InputDeviceCapabilities interface: new InputDeviceCapabilities must inherit property "firesTouchEvents" with the proper type
+FAIL InputDeviceCapabilities interface: new InputDeviceCapabilities must inherit property "pointerMovementScrolls" with the proper type assert_inherits: property "pointerMovementScrolls" not found in prototype chain
+PASS UIEvent interface: attribute sourceCapabilities
+PASS Unscopable handled correctly for sourceCapabilities property on UIEvent
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/input-device-capabilities/interfaces.html b/third_party/WebKit/LayoutTests/external/wpt/input-device-capabilities/interfaces.html
new file mode 100644
index 0000000..178ce5a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/input-device-capabilities/interfaces.html
@@ -0,0 +1,24 @@
+<!doctype html>
+<title>Input Device Capabilities IDL tests</title>
+<link rel="help" href="https://wicg.github.io/InputDeviceCapabilities/">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/WebIDLParser.js"></script>
+<script src="/resources/idlharness.js"></script>
+<script>
+  "use strict";
+
+  promise_test(async () => {
+    const idl_array = new IdlArray();
+    const idl = await (await fetch("/interfaces/InputDeviceCapabilities.idl")).text();
+    const uievents = await (await fetch("/interfaces/uievents.idl")).text();
+    const dom = await (await fetch("/interfaces/dom.idl")).text();
+    idl_array.add_idls(idl);
+    idl_array.add_dependency_idls(uievents);
+    idl_array.add_dependency_idls(dom);
+    idl_array.add_objects({
+      InputDeviceCapabilities: ["new InputDeviceCapabilities"],
+    });
+    idl_array.test();
+  }, "Test driver");
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/interfaces/InputDeviceCapabilities.idl b/third_party/WebKit/LayoutTests/external/wpt/interfaces/InputDeviceCapabilities.idl
new file mode 100644
index 0000000..6be9be7
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/interfaces/InputDeviceCapabilities.idl
@@ -0,0 +1,22 @@
+// GENERATED CONTENT - DO NOT EDIT
+// Content of this file was automatically extracted from the
+// "Input Device Capabilities" spec.
+// See: https://wicg.github.io/InputDeviceCapabilities/
+
+[Constructor(optional InputDeviceCapabilitiesInit deviceInitDict)]
+interface InputDeviceCapabilities {
+    readonly attribute boolean firesTouchEvents;
+    readonly attribute boolean pointerMovementScrolls;
+};
+
+dictionary InputDeviceCapabilitiesInit {
+    boolean firesTouchEvents = false;
+    boolean pointerMovementScrolls = false;
+};
+partial interface UIEvent {
+    readonly attribute InputDeviceCapabilities? sourceCapabilities;
+};
+
+partial dictionary UIEventInit {
+    InputDeviceCapabilities? sourceCapabilities = null;
+};
diff --git a/third_party/WebKit/LayoutTests/external/wpt/interfaces/ResizeObserver.idl b/third_party/WebKit/LayoutTests/external/wpt/interfaces/ResizeObserver.idl
new file mode 100644
index 0000000..a75a11c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/interfaces/ResizeObserver.idl
@@ -0,0 +1,30 @@
+// GENERATED CONTENT - DO NOT EDIT
+// Content of this file was automatically extracted from the
+// "Resize Observer 1" spec.
+// See: https://wicg.github.io/ResizeObserver/
+
+[Constructor(ResizeObserverCallback callback),
+    Exposed=Window]
+interface ResizeObserver {
+    void observe(Element target);
+    void unobserve(Element target);
+    void disconnect();
+};
+
+callback ResizeObserverCallback = void (sequence<ResizeObserverEntry> entries, ResizeObserver observer);
+
+[Constructor(Element target)
+]
+interface ResizeObserverEntry {
+    readonly attribute Element target;
+    readonly attribute DOMRectReadOnly contentRect;
+};
+
+[Constructor(Element target)
+]
+interface ResizeObservation {
+    readonly attribute Element target;
+    readonly attribute float broadcastWidth;
+    readonly attribute float broadcastHeight;
+    boolean isActive();
+};
diff --git a/third_party/WebKit/LayoutTests/external/wpt/interfaces/css-masking.idl b/third_party/WebKit/LayoutTests/external/wpt/interfaces/css-masking.idl
new file mode 100644
index 0000000..726e0a0
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/interfaces/css-masking.idl
@@ -0,0 +1,18 @@
+// GENERATED CONTENT - DO NOT EDIT
+// Content of this file was automatically extracted from the
+// "CSS Masking Module Level 1" spec.
+// See: https://drafts.fxtf.org/css-masking-1/
+
+interface SVGClipPathElement : SVGElement {
+  readonly attribute SVGAnimatedEnumeration clipPathUnits;
+  readonly attribute SVGAnimatedTransformList transform;
+};
+
+interface SVGMaskElement : SVGElement {
+  readonly attribute SVGAnimatedEnumeration maskUnits;
+  readonly attribute SVGAnimatedEnumeration maskContentUnits;
+  readonly attribute SVGAnimatedLength x;
+  readonly attribute SVGAnimatedLength y;
+  readonly attribute SVGAnimatedLength width;
+  readonly attribute SVGAnimatedLength height;
+};
diff --git a/third_party/WebKit/LayoutTests/external/wpt/interfaces/performance-timeline.idl b/third_party/WebKit/LayoutTests/external/wpt/interfaces/performance-timeline.idl
new file mode 100644
index 0000000..857be8c
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/interfaces/performance-timeline.idl
@@ -0,0 +1,40 @@
+// GENERATED CONTENT - DO NOT EDIT
+// Content of this file was automatically extracted from the
+// "Performance Timeline Level 2" spec.
+// See: https://w3c.github.io/performance-timeline/
+
+partial interface Performance {
+    PerformanceEntryList getEntries();
+    PerformanceEntryList getEntriesByType(DOMString type);
+    PerformanceEntryList getEntriesByName(DOMString name,
+                                          optional DOMString type);
+};
+typedef sequence<PerformanceEntry> PerformanceEntryList;
+[Exposed=(Window,Worker)]
+interface PerformanceEntry {
+    readonly attribute DOMString           name;
+    readonly attribute DOMString           entryType;
+    readonly attribute DOMHighResTimeStamp startTime;
+    readonly attribute DOMHighResTimeStamp duration;
+    [Default] object toJSON();
+};
+callback PerformanceObserverCallback = void (PerformanceObserverEntryList entries,
+                                             PerformanceObserver observer);
+[Constructor(PerformanceObserverCallback callback),
+ Exposed=(Window,Worker)]
+interface PerformanceObserver {
+    void                 observe(PerformanceObserverInit options);
+    void                 disconnect();
+    PerformanceEntryList takeRecords();
+};
+dictionary PerformanceObserverInit {
+    required sequence<DOMString> entryTypes;
+             boolean             buffered = false;
+};
+[Exposed=(Window,Worker)]
+interface PerformanceObserverEntryList {
+    PerformanceEntryList getEntries();
+    PerformanceEntryList getEntriesByType(DOMString type);
+    PerformanceEntryList getEntriesByName(DOMString name,
+                                          optional DOMString type);
+};
diff --git a/third_party/WebKit/LayoutTests/external/wpt/interfaces/user-timing.idl b/third_party/WebKit/LayoutTests/external/wpt/interfaces/user-timing.idl
new file mode 100644
index 0000000..576ee53
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/interfaces/user-timing.idl
@@ -0,0 +1,19 @@
+// GENERATED CONTENT - DO NOT EDIT
+// Content of this file was automatically extracted from the
+// "User Timing Level 2" spec.
+// See: https://w3c.github.io/user-timing/
+
+partial interface Performance {
+    void mark(DOMString markName);
+    void clearMarks(optional DOMString markName);
+    void measure(DOMString measureName,
+                 optional DOMString startMark,
+                 optional DOMString endMark);
+    void clearMeasures(optional DOMString measureName);
+};
+[Exposed=(Window,Worker)]
+interface PerformanceMark : PerformanceEntry {
+};
+[Exposed=(Window,Worker)]
+interface PerformanceMeasure : PerformanceEntry {
+};
diff --git a/third_party/WebKit/LayoutTests/external/wpt/magnetometer/idlharness.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/magnetometer/idlharness.https-expected.txt
index 0d560f6..49822f4 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/magnetometer/idlharness.https-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/magnetometer/idlharness.https-expected.txt
@@ -1,4 +1,85 @@
 This is a testharness.js-based test.
-FAIL Test IDL implementation of Magnetometer Sensor promise_test: Unhandled rejection with value: object "Partial interface Window with no original interface"
+PASS Test IDL implementation of Magnetometer Sensor
+PASS Sensor interface: existence and properties of interface object
+PASS Sensor interface object length
+PASS Sensor interface object name
+PASS Sensor interface: existence and properties of interface prototype object
+PASS Sensor interface: existence and properties of interface prototype object's "constructor" property
+PASS Sensor interface: existence and properties of interface prototype object's @@unscopables property
+PASS Sensor interface: attribute activated
+PASS Unscopable handled correctly for activated property on Sensor
+PASS Sensor interface: attribute hasReading
+PASS Unscopable handled correctly for hasReading property on Sensor
+PASS Sensor interface: attribute timestamp
+PASS Unscopable handled correctly for timestamp property on Sensor
+PASS Sensor interface: operation start()
+PASS Unscopable handled correctly for start() on Sensor
+PASS Sensor interface: operation stop()
+PASS Unscopable handled correctly for stop() on Sensor
+PASS Sensor interface: attribute onreading
+PASS Unscopable handled correctly for onreading property on Sensor
+PASS Sensor interface: attribute onactivate
+PASS Unscopable handled correctly for onactivate property on Sensor
+PASS Sensor interface: attribute onerror
+PASS Unscopable handled correctly for onerror property on Sensor
+PASS Magnetometer interface: existence and properties of interface object
+PASS Magnetometer interface object length
+PASS Magnetometer interface object name
+PASS Magnetometer interface: existence and properties of interface prototype object
+PASS Magnetometer interface: existence and properties of interface prototype object's "constructor" property
+PASS Magnetometer interface: existence and properties of interface prototype object's @@unscopables property
+PASS Magnetometer interface: attribute x
+PASS Unscopable handled correctly for x property on Magnetometer
+PASS Magnetometer interface: attribute y
+PASS Unscopable handled correctly for y property on Magnetometer
+PASS Magnetometer interface: attribute z
+PASS Unscopable handled correctly for z property on Magnetometer
+PASS Magnetometer must be primary interface of new Magnetometer();
+PASS Stringification of new Magnetometer();
+PASS Magnetometer interface: new Magnetometer(); must inherit property "x" with the proper type
+PASS Magnetometer interface: new Magnetometer(); must inherit property "y" with the proper type
+PASS Magnetometer interface: new Magnetometer(); must inherit property "z" with the proper type
+PASS Sensor interface: new Magnetometer(); must inherit property "activated" with the proper type
+PASS Sensor interface: new Magnetometer(); must inherit property "hasReading" with the proper type
+PASS Sensor interface: new Magnetometer(); must inherit property "timestamp" with the proper type
+PASS Sensor interface: new Magnetometer(); must inherit property "start()" with the proper type
+PASS Sensor interface: new Magnetometer(); must inherit property "stop()" with the proper type
+PASS Sensor interface: new Magnetometer(); must inherit property "onreading" with the proper type
+PASS Sensor interface: new Magnetometer(); must inherit property "onactivate" with the proper type
+PASS Sensor interface: new Magnetometer(); must inherit property "onerror" with the proper type
+FAIL UncalibratedMagnetometer interface: existence and properties of interface object assert_own_property: self does not have own property "UncalibratedMagnetometer" expected property "UncalibratedMagnetometer" missing
+FAIL UncalibratedMagnetometer interface object length assert_own_property: self does not have own property "UncalibratedMagnetometer" expected property "UncalibratedMagnetometer" missing
+FAIL UncalibratedMagnetometer interface object name assert_own_property: self does not have own property "UncalibratedMagnetometer" expected property "UncalibratedMagnetometer" missing
+FAIL UncalibratedMagnetometer interface: existence and properties of interface prototype object assert_own_property: self does not have own property "UncalibratedMagnetometer" expected property "UncalibratedMagnetometer" missing
+FAIL UncalibratedMagnetometer interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "UncalibratedMagnetometer" expected property "UncalibratedMagnetometer" missing
+FAIL UncalibratedMagnetometer interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "UncalibratedMagnetometer" expected property "UncalibratedMagnetometer" missing
+FAIL UncalibratedMagnetometer interface: attribute x assert_own_property: self does not have own property "UncalibratedMagnetometer" expected property "UncalibratedMagnetometer" missing
+PASS Unscopable handled correctly for x property on UncalibratedMagnetometer
+FAIL UncalibratedMagnetometer interface: attribute y assert_own_property: self does not have own property "UncalibratedMagnetometer" expected property "UncalibratedMagnetometer" missing
+PASS Unscopable handled correctly for y property on UncalibratedMagnetometer
+FAIL UncalibratedMagnetometer interface: attribute z assert_own_property: self does not have own property "UncalibratedMagnetometer" expected property "UncalibratedMagnetometer" missing
+PASS Unscopable handled correctly for z property on UncalibratedMagnetometer
+FAIL UncalibratedMagnetometer interface: attribute xBias assert_own_property: self does not have own property "UncalibratedMagnetometer" expected property "UncalibratedMagnetometer" missing
+PASS Unscopable handled correctly for xBias property on UncalibratedMagnetometer
+FAIL UncalibratedMagnetometer interface: attribute yBias assert_own_property: self does not have own property "UncalibratedMagnetometer" expected property "UncalibratedMagnetometer" missing
+PASS Unscopable handled correctly for yBias property on UncalibratedMagnetometer
+FAIL UncalibratedMagnetometer interface: attribute zBias assert_own_property: self does not have own property "UncalibratedMagnetometer" expected property "UncalibratedMagnetometer" missing
+PASS Unscopable handled correctly for zBias property on UncalibratedMagnetometer
+FAIL UncalibratedMagnetometer must be primary interface of new UncalibratedMagnetometer(); assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: UncalibratedMagnetometer is not defined"
+FAIL Stringification of new UncalibratedMagnetometer(); assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: UncalibratedMagnetometer is not defined"
+FAIL UncalibratedMagnetometer interface: new UncalibratedMagnetometer(); must inherit property "x" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: UncalibratedMagnetometer is not defined"
+FAIL UncalibratedMagnetometer interface: new UncalibratedMagnetometer(); must inherit property "y" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: UncalibratedMagnetometer is not defined"
+FAIL UncalibratedMagnetometer interface: new UncalibratedMagnetometer(); must inherit property "z" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: UncalibratedMagnetometer is not defined"
+FAIL UncalibratedMagnetometer interface: new UncalibratedMagnetometer(); must inherit property "xBias" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: UncalibratedMagnetometer is not defined"
+FAIL UncalibratedMagnetometer interface: new UncalibratedMagnetometer(); must inherit property "yBias" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: UncalibratedMagnetometer is not defined"
+FAIL UncalibratedMagnetometer interface: new UncalibratedMagnetometer(); must inherit property "zBias" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: UncalibratedMagnetometer is not defined"
+FAIL Sensor interface: new UncalibratedMagnetometer(); must inherit property "activated" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: UncalibratedMagnetometer is not defined"
+FAIL Sensor interface: new UncalibratedMagnetometer(); must inherit property "hasReading" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: UncalibratedMagnetometer is not defined"
+FAIL Sensor interface: new UncalibratedMagnetometer(); must inherit property "timestamp" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: UncalibratedMagnetometer is not defined"
+FAIL Sensor interface: new UncalibratedMagnetometer(); must inherit property "start()" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: UncalibratedMagnetometer is not defined"
+FAIL Sensor interface: new UncalibratedMagnetometer(); must inherit property "stop()" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: UncalibratedMagnetometer is not defined"
+FAIL Sensor interface: new UncalibratedMagnetometer(); must inherit property "onreading" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: UncalibratedMagnetometer is not defined"
+FAIL Sensor interface: new UncalibratedMagnetometer(); must inherit property "onactivate" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: UncalibratedMagnetometer is not defined"
+FAIL Sensor interface: new UncalibratedMagnetometer(); must inherit property "onerror" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: UncalibratedMagnetometer is not defined"
 Harness: the test ran to completion.
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/media-capabilities/idlharness-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/media-capabilities/idlharness-expected.txt
index c5c0eb8..680d20f 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/media-capabilities/idlharness-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/media-capabilities/idlharness-expected.txt
@@ -1,9 +1,15 @@
 This is a testharness.js-based test.
+Found 50 tests; 36 PASS, 14 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Test IDL implementation of Media Capabilities
+PASS Partial interface Navigator: original interface defined
+PASS Partial interface Navigator: valid exposure set
+PASS Partial interface WorkerNavigator: original interface defined
+FAIL Partial interface WorkerNavigator: valid exposure set Partial WorkerNavigator interface is exposed to 'DedicatedWorker', the original interface is not.
+PASS Partial interface Screen: original interface defined
 PASS Navigator interface: attribute mediaCapabilities
 PASS Unscopable handled correctly for mediaCapabilities property on Navigator
 PASS Navigator interface: navigator must inherit property "mediaCapabilities" with the proper type
-PASS WorkerNavigator interface: existence and properties of interface object
+FAIL WorkerNavigator interface: member mediaCapabilities Cannot use 'in' operator to search for 'mediaCapabilities' in undefined
 FAIL Screen interface: attribute colorGamut assert_true: The prototype object must have a property "colorGamut" expected true got false
 PASS Unscopable handled correctly for colorGamut property on Screen
 FAIL Screen interface: attribute luminance assert_true: The prototype object must have a property "luminance" expected true got false
diff --git a/third_party/WebKit/LayoutTests/external/wpt/media-source/interfaces-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/media-source/interfaces-expected.txt
index b626df4..c23e2f7d 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/media-source/interfaces-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/media-source/interfaces-expected.txt
@@ -1,5 +1,10 @@
 This is a testharness.js-based test.
-Found 138 tests; 135 PASS, 3 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 143 tests; 140 PASS, 3 FAIL, 0 TIMEOUT, 0 NOTRUN.
+PASS Partial interface URL: original interface defined
+PASS Partial interface URL: valid exposure set
+PASS Partial interface AudioTrack: original interface defined
+PASS Partial interface VideoTrack: original interface defined
+PASS Partial interface TextTrack: original interface defined
 PASS URL interface: operation createObjectURL(MediaSource)
 PASS Unscopable handled correctly for createObjectURL(MediaSource) on URL
 PASS AudioTrack interface: attribute sourceBuffer
diff --git a/third_party/WebKit/LayoutTests/external/wpt/mediacapture-fromelement/idlharness-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/mediacapture-fromelement/idlharness-expected.txt
index dcbc5d1..1da140d 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/mediacapture-fromelement/idlharness-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/mediacapture-fromelement/idlharness-expected.txt
@@ -1,4 +1,6 @@
 This is a testharness.js-based test.
+PASS Partial interface HTMLMediaElement: original interface defined
+PASS Partial interface HTMLCanvasElement: original interface defined
 PASS HTMLCanvasElement interface: operation captureStream(double)
 PASS Unscopable handled correctly for captureStream(double) on HTMLCanvasElement
 PASS HTMLCanvasElement interface: [object HTMLCanvasElement] must inherit property "captureStream(double)" with the proper type
diff --git a/third_party/WebKit/LayoutTests/external/wpt/mediacapture-streams/MediaDevices-IDL-all-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/mediacapture-streams/MediaDevices-IDL-all-expected.txt
index 7efe128..359e0d6 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/mediacapture-streams/MediaDevices-IDL-all-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/mediacapture-streams/MediaDevices-IDL-all-expected.txt
@@ -1,6 +1,8 @@
 This is a testharness.js-based test.
-Found 135 tests; 127 PASS, 8 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 137 tests; 129 PASS, 8 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Test driver
+PASS Partial interface NavigatorUserMedia: original interface defined
+PASS Partial interface MediaDevices: original interface defined
 PASS Navigator interface: attribute mediaDevices
 PASS Unscopable handled correctly for mediaDevices property on Navigator
 PASS Navigator interface: operation getUserMedia(MediaStreamConstraints, NavigatorUserMediaSuccessCallback, NavigatorUserMediaErrorCallback)
diff --git a/third_party/WebKit/LayoutTests/external/wpt/mediacapture-streams/MediaDevices-IDL-enumerateDevices-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/mediacapture-streams/MediaDevices-IDL-enumerateDevices-expected.txt
index a882132..70cf1c48 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/mediacapture-streams/MediaDevices-IDL-enumerateDevices-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/mediacapture-streams/MediaDevices-IDL-enumerateDevices-expected.txt
@@ -1,6 +1,8 @@
 This is a testharness.js-based test.
-Found 134 tests; 126 PASS, 8 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 136 tests; 128 PASS, 8 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Test MediaDevices.enumerateDevices call and result. Types only.
+PASS Partial interface NavigatorUserMedia: original interface defined
+PASS Partial interface MediaDevices: original interface defined
 PASS Navigator interface: attribute mediaDevices
 PASS Unscopable handled correctly for mediaDevices property on Navigator
 PASS Navigator interface: operation getUserMedia(MediaStreamConstraints, NavigatorUserMediaSuccessCallback, NavigatorUserMediaErrorCallback)
diff --git a/third_party/WebKit/LayoutTests/external/wpt/mediacapture-streams/MediaStreamTrack-idl.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/mediacapture-streams/MediaStreamTrack-idl.https-expected.txt
index a20681d..124aa42 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/mediacapture-streams/MediaStreamTrack-idl.https-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/mediacapture-streams/MediaStreamTrack-idl.https-expected.txt
@@ -1,4 +1,61 @@
 This is a testharness.js-based test.
-FAIL Test driver promise_test: Unhandled rejection with value: object "Partial interface Window with no original interface"
+PASS Test driver
+PASS MediaStreamTrack interface: existence and properties of interface object
+PASS MediaStreamTrack interface object length
+PASS MediaStreamTrack interface object name
+PASS MediaStreamTrack interface: existence and properties of interface prototype object
+PASS MediaStreamTrack interface: existence and properties of interface prototype object's "constructor" property
+PASS MediaStreamTrack interface: existence and properties of interface prototype object's @@unscopables property
+PASS MediaStreamTrack interface: attribute kind
+PASS Unscopable handled correctly for kind property on MediaStreamTrack
+PASS MediaStreamTrack interface: attribute id
+PASS Unscopable handled correctly for id property on MediaStreamTrack
+PASS MediaStreamTrack interface: attribute label
+PASS Unscopable handled correctly for label property on MediaStreamTrack
+PASS MediaStreamTrack interface: attribute enabled
+PASS Unscopable handled correctly for enabled property on MediaStreamTrack
+PASS MediaStreamTrack interface: attribute muted
+PASS Unscopable handled correctly for muted property on MediaStreamTrack
+PASS MediaStreamTrack interface: attribute onmute
+PASS Unscopable handled correctly for onmute property on MediaStreamTrack
+PASS MediaStreamTrack interface: attribute onunmute
+PASS Unscopable handled correctly for onunmute property on MediaStreamTrack
+PASS MediaStreamTrack interface: attribute readyState
+PASS Unscopable handled correctly for readyState property on MediaStreamTrack
+PASS MediaStreamTrack interface: attribute onended
+PASS Unscopable handled correctly for onended property on MediaStreamTrack
+FAIL MediaStreamTrack interface: attribute onoverconstrained assert_true: The prototype object must have a property "onoverconstrained" expected true got false
+PASS Unscopable handled correctly for onoverconstrained property on MediaStreamTrack
+PASS MediaStreamTrack interface: operation clone()
+PASS Unscopable handled correctly for clone() on MediaStreamTrack
+PASS MediaStreamTrack interface: operation stop()
+PASS Unscopable handled correctly for stop() on MediaStreamTrack
+PASS MediaStreamTrack interface: operation getCapabilities()
+PASS Unscopable handled correctly for getCapabilities() on MediaStreamTrack
+PASS MediaStreamTrack interface: operation getConstraints()
+PASS Unscopable handled correctly for getConstraints() on MediaStreamTrack
+PASS MediaStreamTrack interface: operation getSettings()
+PASS Unscopable handled correctly for getSettings() on MediaStreamTrack
+PASS MediaStreamTrack interface: operation applyConstraints(MediaTrackConstraints)
+PASS Unscopable handled correctly for applyConstraints(MediaTrackConstraints) on MediaStreamTrack
+PASS MediaStreamTrack must be primary interface of track
+PASS Stringification of track
+PASS MediaStreamTrack interface: track must inherit property "kind" with the proper type
+PASS MediaStreamTrack interface: track must inherit property "id" with the proper type
+PASS MediaStreamTrack interface: track must inherit property "label" with the proper type
+PASS MediaStreamTrack interface: track must inherit property "enabled" with the proper type
+PASS MediaStreamTrack interface: track must inherit property "muted" with the proper type
+PASS MediaStreamTrack interface: track must inherit property "onmute" with the proper type
+PASS MediaStreamTrack interface: track must inherit property "onunmute" with the proper type
+PASS MediaStreamTrack interface: track must inherit property "readyState" with the proper type
+PASS MediaStreamTrack interface: track must inherit property "onended" with the proper type
+FAIL MediaStreamTrack interface: track must inherit property "onoverconstrained" with the proper type assert_inherits: property "onoverconstrained" not found in prototype chain
+PASS MediaStreamTrack interface: track must inherit property "clone()" with the proper type
+PASS MediaStreamTrack interface: track must inherit property "stop()" with the proper type
+PASS MediaStreamTrack interface: track must inherit property "getCapabilities()" with the proper type
+PASS MediaStreamTrack interface: track must inherit property "getConstraints()" with the proper type
+PASS MediaStreamTrack interface: track must inherit property "getSettings()" with the proper type
+PASS MediaStreamTrack interface: track must inherit property "applyConstraints(MediaTrackConstraints)" with the proper type
+PASS MediaStreamTrack interface: calling applyConstraints(MediaTrackConstraints) on track with too few arguments must throw TypeError
 Harness: the test ran to completion.
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/orientation-event/idlharness-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/orientation-event/idlharness-expected.txt
index 31e9ba4..75e7694 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/orientation-event/idlharness-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/orientation-event/idlharness-expected.txt
@@ -1,4 +1,5 @@
 This is a testharness.js-based test.
+PASS Partial interface Window: original interface defined
 FAIL Window interface: attribute ondeviceorientation assert_true: The prototype object must have a property "ondeviceorientation" expected true got false
 PASS Unscopable handled correctly for ondeviceorientation property on Window
 FAIL Window interface: attribute ondevicemotion assert_true: The prototype object must have a property "ondevicemotion" expected true got false
diff --git a/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/idlharness.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/idlharness.https-expected.txt
deleted file mode 100644
index 822cdff5..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/orientation-sensor/idlharness.https-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-FAIL Test IDL implementation of Orientation Sensor promise_test: Unhandled rejection with value: object "Partial interface Window with no original interface"
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/payment-request/interfaces.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/payment-request/interfaces.https-expected.txt
index 821fefe6..729b0df5c 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/payment-request/interfaces.https-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/payment-request/interfaces.https-expected.txt
@@ -1,4 +1,106 @@
 This is a testharness.js-based test.
-FAIL Setup for Payment Request API IDL tests. promise_test: Unhandled rejection with value: object "Partial interface Window with no original interface"
+PASS Setup for Payment Request API IDL tests.
+PASS PaymentRequest interface: existence and properties of interface object
+PASS PaymentRequest interface object length
+PASS PaymentRequest interface object name
+PASS PaymentRequest interface: existence and properties of interface prototype object
+PASS PaymentRequest interface: existence and properties of interface prototype object's "constructor" property
+PASS PaymentRequest interface: existence and properties of interface prototype object's @@unscopables property
+PASS PaymentRequest interface: operation show([object Object])
+PASS Unscopable handled correctly for show([object Object]) on PaymentRequest
+PASS PaymentRequest interface: operation abort()
+PASS Unscopable handled correctly for abort() on PaymentRequest
+PASS PaymentRequest interface: operation canMakePayment()
+PASS Unscopable handled correctly for canMakePayment() on PaymentRequest
+PASS PaymentRequest interface: attribute id
+PASS Unscopable handled correctly for id property on PaymentRequest
+PASS PaymentRequest interface: attribute shippingAddress
+PASS Unscopable handled correctly for shippingAddress property on PaymentRequest
+PASS PaymentRequest interface: attribute shippingOption
+PASS Unscopable handled correctly for shippingOption property on PaymentRequest
+PASS PaymentRequest interface: attribute shippingType
+PASS Unscopable handled correctly for shippingType property on PaymentRequest
+PASS PaymentRequest interface: attribute onshippingaddresschange
+PASS Unscopable handled correctly for onshippingaddresschange property on PaymentRequest
+PASS PaymentRequest interface: attribute onshippingoptionchange
+PASS Unscopable handled correctly for onshippingoptionchange property on PaymentRequest
+PASS PaymentRequest must be primary interface of new PaymentRequest([{supportedMethods: 'foo'}], {total: {label: 'bar', amount: {currency: 'USD', value: '0'}} })
+PASS Stringification of new PaymentRequest([{supportedMethods: 'foo'}], {total: {label: 'bar', amount: {currency: 'USD', value: '0'}} })
+PASS PaymentRequest interface: new PaymentRequest([{supportedMethods: 'foo'}], {total: {label: 'bar', amount: {currency: 'USD', value: '0'}} }) must inherit property "show([object Object])" with the proper type
+PASS PaymentRequest interface: calling show([object Object]) on new PaymentRequest([{supportedMethods: 'foo'}], {total: {label: 'bar', amount: {currency: 'USD', value: '0'}} }) with too few arguments must throw TypeError
+PASS PaymentRequest interface: new PaymentRequest([{supportedMethods: 'foo'}], {total: {label: 'bar', amount: {currency: 'USD', value: '0'}} }) must inherit property "abort()" with the proper type
+PASS PaymentRequest interface: new PaymentRequest([{supportedMethods: 'foo'}], {total: {label: 'bar', amount: {currency: 'USD', value: '0'}} }) must inherit property "canMakePayment()" with the proper type
+PASS PaymentRequest interface: new PaymentRequest([{supportedMethods: 'foo'}], {total: {label: 'bar', amount: {currency: 'USD', value: '0'}} }) must inherit property "id" with the proper type
+PASS PaymentRequest interface: new PaymentRequest([{supportedMethods: 'foo'}], {total: {label: 'bar', amount: {currency: 'USD', value: '0'}} }) must inherit property "shippingAddress" with the proper type
+PASS PaymentRequest interface: new PaymentRequest([{supportedMethods: 'foo'}], {total: {label: 'bar', amount: {currency: 'USD', value: '0'}} }) must inherit property "shippingOption" with the proper type
+PASS PaymentRequest interface: new PaymentRequest([{supportedMethods: 'foo'}], {total: {label: 'bar', amount: {currency: 'USD', value: '0'}} }) must inherit property "shippingType" with the proper type
+PASS PaymentRequest interface: new PaymentRequest([{supportedMethods: 'foo'}], {total: {label: 'bar', amount: {currency: 'USD', value: '0'}} }) must inherit property "onshippingaddresschange" with the proper type
+PASS PaymentRequest interface: new PaymentRequest([{supportedMethods: 'foo'}], {total: {label: 'bar', amount: {currency: 'USD', value: '0'}} }) must inherit property "onshippingoptionchange" with the proper type
+PASS PaymentAddress interface: existence and properties of interface object
+PASS PaymentAddress interface object length
+PASS PaymentAddress interface object name
+PASS PaymentAddress interface: existence and properties of interface prototype object
+PASS PaymentAddress interface: existence and properties of interface prototype object's "constructor" property
+PASS PaymentAddress interface: existence and properties of interface prototype object's @@unscopables property
+PASS PaymentAddress interface: operation toJSON()
+PASS Unscopable handled correctly for toJSON() on PaymentAddress
+PASS PaymentAddress interface: attribute city
+PASS Unscopable handled correctly for city property on PaymentAddress
+PASS PaymentAddress interface: attribute country
+PASS Unscopable handled correctly for country property on PaymentAddress
+PASS PaymentAddress interface: attribute dependentLocality
+PASS Unscopable handled correctly for dependentLocality property on PaymentAddress
+PASS PaymentAddress interface: attribute languageCode
+PASS Unscopable handled correctly for languageCode property on PaymentAddress
+PASS PaymentAddress interface: attribute organization
+PASS Unscopable handled correctly for organization property on PaymentAddress
+PASS PaymentAddress interface: attribute phone
+PASS Unscopable handled correctly for phone property on PaymentAddress
+PASS PaymentAddress interface: attribute postalCode
+PASS Unscopable handled correctly for postalCode property on PaymentAddress
+PASS PaymentAddress interface: attribute recipient
+PASS Unscopable handled correctly for recipient property on PaymentAddress
+PASS PaymentAddress interface: attribute region
+PASS Unscopable handled correctly for region property on PaymentAddress
+FAIL PaymentAddress interface: attribute regionCode assert_true: The prototype object must have a property "regionCode" expected true got false
+PASS Unscopable handled correctly for regionCode property on PaymentAddress
+PASS PaymentAddress interface: attribute sortingCode
+PASS Unscopable handled correctly for sortingCode property on PaymentAddress
+PASS PaymentAddress interface: attribute addressLine
+PASS Unscopable handled correctly for addressLine property on PaymentAddress
+PASS PaymentResponse interface: existence and properties of interface object
+PASS PaymentResponse interface object length
+PASS PaymentResponse interface object name
+PASS PaymentResponse interface: existence and properties of interface prototype object
+PASS PaymentResponse interface: existence and properties of interface prototype object's "constructor" property
+PASS PaymentResponse interface: existence and properties of interface prototype object's @@unscopables property
+PASS PaymentResponse interface: operation toJSON()
+PASS Unscopable handled correctly for toJSON() on PaymentResponse
+PASS PaymentResponse interface: attribute requestId
+PASS Unscopable handled correctly for requestId property on PaymentResponse
+PASS PaymentResponse interface: attribute methodName
+PASS Unscopable handled correctly for methodName property on PaymentResponse
+PASS PaymentResponse interface: attribute details
+PASS Unscopable handled correctly for details property on PaymentResponse
+PASS PaymentResponse interface: attribute shippingAddress
+PASS Unscopable handled correctly for shippingAddress property on PaymentResponse
+PASS PaymentResponse interface: attribute shippingOption
+PASS Unscopable handled correctly for shippingOption property on PaymentResponse
+PASS PaymentResponse interface: attribute payerName
+PASS Unscopable handled correctly for payerName property on PaymentResponse
+PASS PaymentResponse interface: attribute payerEmail
+PASS Unscopable handled correctly for payerEmail property on PaymentResponse
+PASS PaymentResponse interface: attribute payerPhone
+PASS Unscopable handled correctly for payerPhone property on PaymentResponse
+PASS PaymentResponse interface: operation complete(PaymentComplete)
+PASS Unscopable handled correctly for complete(PaymentComplete) on PaymentResponse
+PASS PaymentRequestUpdateEvent interface: existence and properties of interface object
+PASS PaymentRequestUpdateEvent interface object length
+PASS PaymentRequestUpdateEvent interface object name
+PASS PaymentRequestUpdateEvent interface: existence and properties of interface prototype object
+PASS PaymentRequestUpdateEvent interface: existence and properties of interface prototype object's "constructor" property
+PASS PaymentRequestUpdateEvent interface: existence and properties of interface prototype object's @@unscopables property
+PASS PaymentRequestUpdateEvent interface: operation updateWith([object Object])
+PASS Unscopable handled correctly for updateWith([object Object]) on PaymentRequestUpdateEvent
 Harness: the test ran to completion.
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/performance-timeline/idlharness.any.js b/third_party/WebKit/LayoutTests/external/wpt/performance-timeline/idlharness.any.js
new file mode 100644
index 0000000..b15a667
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/performance-timeline/idlharness.any.js
@@ -0,0 +1,26 @@
+// META: global=window,worker
+// META: script=/resources/WebIDLParser.js
+// META: script=/resources/idlharness.js
+
+// https://w3c.github.io/performance-timeline/
+
+'use strict';
+
+promise_test(async () => {
+  const idl_array = new IdlArray();
+  const idl = await fetch("/interfaces/performance-timeline.idl").then(r => r.text());
+  const dom = await fetch("/interfaces/dom.idl").then(r => r.text());
+  const hrtime = await fetch("/interfaces/hr-time.idl").then(r => r.text());
+
+  // create first mark
+  self.performance.mark("mark");
+
+  idl_array.add_idls(idl);
+  idl_array.add_dependency_idls(hrtime);
+  idl_array.add_dependency_idls(dom);
+  idl_array.add_objects({
+    Performance: ["performance"],
+    PerformanceMark: [self.performance.getEntriesByName("mark")[0]],
+  });
+  idl_array.test();
+}, "Test IDL implementation of performance-timeline API");
diff --git a/third_party/WebKit/LayoutTests/external/wpt/performance-timeline/idlharness.html b/third_party/WebKit/LayoutTests/external/wpt/performance-timeline/idlharness.html
deleted file mode 100644
index 8cef4fb3..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/performance-timeline/idlharness.html
+++ /dev/null
@@ -1,90 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<meta charset="utf-8">
-<title>Performance Timeline IDL tests</title>
-<link rel="author" title="W3C" href="http://www.w3.org/" />
-<link rel="help" href="http://www.w3.org/TR/performance-timeline/#performanceentry"/>
-<link rel="help" href="http://www.w3.org/TR/performance-timeline/#performance"/>
-<link rel="help" href="http://www.w3.org/TR/performance-timeline/#performanceentrylist"/>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="/resources/WebIDLParser.js"></script>
-<script src="/resources/idlharness.js"></script>
-</head>
-<body>
-<h1>Performance Timeline IDL tests</h1>
-<div id="log"></div>
-
-<pre id='untested_idl' style='display:none'>
-interface Performance {
-};
-
-typedef double DOMHighResTimeStamp;
-
-[Exposed=(Window,Worker)]
-interface PerformanceMark : PerformanceEntry {
-};
-</pre>
-
-<pre id='idl'>
-[Exposed=(Window,Worker)]
-interface PerformanceEntry {
-    readonly attribute DOMString           name;
-    readonly attribute DOMString           entryType;
-    readonly attribute DOMHighResTimeStamp startTime;
-    readonly attribute DOMHighResTimeStamp duration;
-    [Default] object toJSON();
-};
-
-partial interface Performance {
-    PerformanceEntryList getEntries();
-    PerformanceEntryList getEntriesByType(DOMString type);
-    PerformanceEntryList getEntriesByName(DOMString name,
-                                          optional DOMString type);
-};
-
-typedef sequence &lt;PerformanceEntry> PerformanceEntryList;
-
-dictionary PerformanceObserverInit {
-    required sequence&lt;DOMString> entryTypes;
-    boolean             buffered = false;
-};
-
-[Exposed=(Window,Worker)]
-interface PerformanceObserverEntryList {
-    PerformanceEntryList getEntries();
-    PerformanceEntryList getEntriesByType(DOMString type);
-    PerformanceEntryList getEntriesByName(DOMString name,
-                                          optional DOMString type);
-};
-
-callback PerformanceObserverCallback = void (PerformanceObserverEntryList entries,
-                                             PerformanceObserver observer);
-
-[Constructor(PerformanceObserverCallback callback),
- Exposed=(Window,Worker)]
-interface PerformanceObserver {
-    void observe(PerformanceObserverInit options);
-    void disconnect();
-    PerformanceEntryList takeRecords();
-};
-</pre>
-
-<script>
-var idl_array;
-setup(function() {
-  idl_array = new IdlArray();
-  idl_array.add_untested_idls(document.getElementById("untested_idl").textContent);
-  idl_array.add_idls(document.getElementById("idl").textContent);
-  // create first mark
-  self.performance.mark("mark");
-  idl_array.add_objects({
-    Performance: ["window.performance"],
-    PerformanceMark: [self.performance.getEntriesByName("mark")[0]]
-  });
-});
-idl_array.test();
-</script>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/permissions/interfaces.any-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/permissions/interfaces.any-expected.txt
new file mode 100644
index 0000000..e4108c2
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/permissions/interfaces.any-expected.txt
@@ -0,0 +1,38 @@
+This is a testharness.js-based test.
+PASS Test IDL implementation of Permissions API
+PASS Partial interface Navigator: original interface defined
+PASS Partial interface Navigator: valid exposure set
+PASS Partial interface WorkerNavigator: original interface defined
+FAIL Partial interface WorkerNavigator: valid exposure set Partial WorkerNavigator interface is exposed to 'DedicatedWorker', the original interface is not.
+PASS Navigator interface: attribute permissions
+PASS Unscopable handled correctly for permissions property on Navigator
+PASS Navigator interface: navigator must inherit property "permissions" with the proper type
+FAIL WorkerNavigator interface: member permissions Cannot use 'in' operator to search for 'permissions' in undefined
+PASS PermissionStatus interface: existence and properties of interface object
+PASS PermissionStatus interface object length
+PASS PermissionStatus interface object name
+PASS PermissionStatus interface: existence and properties of interface prototype object
+PASS PermissionStatus interface: existence and properties of interface prototype object's "constructor" property
+PASS PermissionStatus interface: existence and properties of interface prototype object's @@unscopables property
+PASS PermissionStatus interface: attribute state
+PASS Unscopable handled correctly for state property on PermissionStatus
+PASS PermissionStatus interface: attribute onchange
+PASS Unscopable handled correctly for onchange property on PermissionStatus
+PASS PermissionStatus must be primary interface of permissionStatus
+PASS Stringification of permissionStatus
+PASS PermissionStatus interface: permissionStatus must inherit property "state" with the proper type
+PASS PermissionStatus interface: permissionStatus must inherit property "onchange" with the proper type
+PASS Permissions interface: existence and properties of interface object
+PASS Permissions interface object length
+PASS Permissions interface object name
+PASS Permissions interface: existence and properties of interface prototype object
+PASS Permissions interface: existence and properties of interface prototype object's "constructor" property
+PASS Permissions interface: existence and properties of interface prototype object's @@unscopables property
+PASS Permissions interface: operation query(object)
+PASS Unscopable handled correctly for query(object) on Permissions
+PASS Permissions must be primary interface of navigator.permissions
+PASS Stringification of navigator.permissions
+PASS Permissions interface: navigator.permissions must inherit property "query(object)" with the proper type
+PASS Permissions interface: calling query(object) on navigator.permissions with too few arguments must throw TypeError
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/permissions/interfaces.any.worker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/permissions/interfaces.any.worker-expected.txt
new file mode 100644
index 0000000..6ddaf70
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/permissions/interfaces.any.worker-expected.txt
@@ -0,0 +1,38 @@
+This is a testharness.js-based test.
+PASS Test IDL implementation of Permissions API
+PASS Partial interface Navigator: original interface defined
+PASS Partial interface Navigator: valid exposure set
+PASS Partial interface WorkerNavigator: original interface defined
+FAIL Partial interface WorkerNavigator: valid exposure set Partial WorkerNavigator interface is exposed to 'DedicatedWorker', the original interface is not.
+PASS Navigator interface: existence and properties of interface object
+PASS EventHandler interface: existence and properties of interface object
+FAIL WorkerNavigator interface: existence and properties of interface object assert_false: expected false got true
+PASS WorkerNavigator interface: navigator must inherit property "permissions" with the proper type
+PASS PermissionStatus interface: existence and properties of interface object
+PASS PermissionStatus interface object length
+PASS PermissionStatus interface object name
+PASS PermissionStatus interface: existence and properties of interface prototype object
+PASS PermissionStatus interface: existence and properties of interface prototype object's "constructor" property
+PASS PermissionStatus interface: existence and properties of interface prototype object's @@unscopables property
+PASS PermissionStatus interface: attribute state
+PASS Unscopable handled correctly for state property on PermissionStatus
+PASS PermissionStatus interface: attribute onchange
+PASS Unscopable handled correctly for onchange property on PermissionStatus
+PASS PermissionStatus must be primary interface of permissionStatus
+PASS Stringification of permissionStatus
+PASS PermissionStatus interface: permissionStatus must inherit property "state" with the proper type
+PASS PermissionStatus interface: permissionStatus must inherit property "onchange" with the proper type
+PASS Permissions interface: existence and properties of interface object
+PASS Permissions interface object length
+PASS Permissions interface object name
+PASS Permissions interface: existence and properties of interface prototype object
+PASS Permissions interface: existence and properties of interface prototype object's "constructor" property
+PASS Permissions interface: existence and properties of interface prototype object's @@unscopables property
+PASS Permissions interface: operation query(object)
+PASS Unscopable handled correctly for query(object) on Permissions
+PASS Permissions must be primary interface of navigator.permissions
+PASS Stringification of navigator.permissions
+PASS Permissions interface: navigator.permissions must inherit property "query(object)" with the proper type
+PASS Permissions interface: calling query(object) on navigator.permissions with too few arguments must throw TypeError
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/resize-observer/idlharness-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/resize-observer/idlharness-expected.txt
new file mode 100644
index 0000000..526a572
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/resize-observer/idlharness-expected.txt
@@ -0,0 +1,47 @@
+This is a testharness.js-based test.
+PASS Test IDL implementation of ResizeObserver
+PASS ResizeObserver interface: existence and properties of interface object
+PASS ResizeObserver interface object length
+PASS ResizeObserver interface object name
+PASS ResizeObserver interface: existence and properties of interface prototype object
+PASS ResizeObserver interface: existence and properties of interface prototype object's "constructor" property
+PASS ResizeObserver interface: existence and properties of interface prototype object's @@unscopables property
+PASS ResizeObserver interface: operation observe(Element)
+PASS Unscopable handled correctly for observe(Element) on ResizeObserver
+PASS ResizeObserver interface: operation unobserve(Element)
+PASS Unscopable handled correctly for unobserve(Element) on ResizeObserver
+PASS ResizeObserver interface: operation disconnect()
+PASS Unscopable handled correctly for disconnect() on ResizeObserver
+PASS ResizeObserver must be primary interface of new ResizeObserver(entries => {})
+PASS Stringification of new ResizeObserver(entries => {})
+PASS ResizeObserver interface: new ResizeObserver(entries => {}) must inherit property "observe(Element)" with the proper type
+PASS ResizeObserver interface: calling observe(Element) on new ResizeObserver(entries => {}) with too few arguments must throw TypeError
+PASS ResizeObserver interface: new ResizeObserver(entries => {}) must inherit property "unobserve(Element)" with the proper type
+PASS ResizeObserver interface: calling unobserve(Element) on new ResizeObserver(entries => {}) with too few arguments must throw TypeError
+PASS ResizeObserver interface: new ResizeObserver(entries => {}) must inherit property "disconnect()" with the proper type
+PASS ResizeObserverEntry interface: existence and properties of interface object
+FAIL ResizeObserverEntry interface object length assert_equals: wrong value for ResizeObserverEntry.length expected 1 but got 0
+PASS ResizeObserverEntry interface object name
+PASS ResizeObserverEntry interface: existence and properties of interface prototype object
+PASS ResizeObserverEntry interface: existence and properties of interface prototype object's "constructor" property
+PASS ResizeObserverEntry interface: existence and properties of interface prototype object's @@unscopables property
+PASS ResizeObserverEntry interface: attribute target
+PASS Unscopable handled correctly for target property on ResizeObserverEntry
+PASS ResizeObserverEntry interface: attribute contentRect
+PASS Unscopable handled correctly for contentRect property on ResizeObserverEntry
+FAIL ResizeObservation interface: existence and properties of interface object assert_own_property: self does not have own property "ResizeObservation" expected property "ResizeObservation" missing
+FAIL ResizeObservation interface object length assert_own_property: self does not have own property "ResizeObservation" expected property "ResizeObservation" missing
+FAIL ResizeObservation interface object name assert_own_property: self does not have own property "ResizeObservation" expected property "ResizeObservation" missing
+FAIL ResizeObservation interface: existence and properties of interface prototype object assert_own_property: self does not have own property "ResizeObservation" expected property "ResizeObservation" missing
+FAIL ResizeObservation interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "ResizeObservation" expected property "ResizeObservation" missing
+FAIL ResizeObservation interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "ResizeObservation" expected property "ResizeObservation" missing
+FAIL ResizeObservation interface: attribute target assert_own_property: self does not have own property "ResizeObservation" expected property "ResizeObservation" missing
+PASS Unscopable handled correctly for target property on ResizeObservation
+FAIL ResizeObservation interface: attribute broadcastWidth assert_own_property: self does not have own property "ResizeObservation" expected property "ResizeObservation" missing
+PASS Unscopable handled correctly for broadcastWidth property on ResizeObservation
+FAIL ResizeObservation interface: attribute broadcastHeight assert_own_property: self does not have own property "ResizeObservation" expected property "ResizeObservation" missing
+PASS Unscopable handled correctly for broadcastHeight property on ResizeObservation
+FAIL ResizeObservation interface: operation isActive() assert_own_property: self does not have own property "ResizeObservation" expected property "ResizeObservation" missing
+PASS Unscopable handled correctly for isActive() on ResizeObservation
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/resize-observer/idlharness.html b/third_party/WebKit/LayoutTests/external/wpt/resize-observer/idlharness.html
new file mode 100644
index 0000000..51ab4fd
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/resize-observer/idlharness.html
@@ -0,0 +1,20 @@
+<!doctype html>
+<title>ResizeObserver IDL tests</title>
+<link rel="help" href="https://wicg.github.io/ResizeObserver/">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/WebIDLParser.js"></script>
+<script src="/resources/idlharness.js"></script>
+<script>
+  "use strict";
+
+  promise_test(async () => {
+    const idl_array = new IdlArray();
+    const idl = await fetch("/interfaces/ResizeObserver.idl").then(r => r.text());
+    idl_array.add_idls(idl);
+    idl_array.add_objects({
+      ResizeObserver: ["new ResizeObserver(entries => {})"],
+    });
+    idl_array.test();
+  }, "Test IDL implementation of ResizeObserver");
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/resources/idlharness.js b/third_party/WebKit/LayoutTests/external/wpt/resources/idlharness.js
index d0057249..484094e 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/resources/idlharness.js
+++ b/third_party/WebKit/LayoutTests/external/wpt/resources/idlharness.js
@@ -662,42 +662,48 @@
 };
 
 function exposure_set(object, default_set) {
-    var exposed = object.extAttrs.filter(function(a) { return a.name == "Exposed" });
-    if (exposed.length > 1) {
+    var exposed = object.extAttrs && object.extAttrs.filter(a => a.name === "Exposed");
+    if (exposed && exposed.length > 1) {
         throw new IdlHarnessError(
             `Multiple 'Exposed' extended attributes on ${object.name}`);
     }
 
-    if (exposed.length === 0) {
-        return default_set;
+    let result = default_set || ["Window"];
+    if (result && !(result instanceof Set)) {
+        result = new Set(result);
     }
-
-    var set = exposed[0].rhs.value;
-    // Could be a list or a string.
-    if (typeof set == "string") {
-        set = [ set ];
+    if (exposed && exposed.length) {
+        var set = exposed[0].rhs.value;
+        // Could be a list or a string.
+        if (typeof set == "string") {
+            set = [ set ];
+        }
+        result = new Set(set);
     }
-    return set;
+    if (result && result.has("Worker")) {
+        result.delete("Worker");
+        result.add("DedicatedWorker");
+        result.add("ServiceWorker");
+        result.add("SharedWorker");
+    }
+    return result;
 }
 
 function exposed_in(globals) {
     if ('document' in self) {
-        return globals.indexOf("Window") >= 0;
+        return globals.has("Window");
     }
     if ('DedicatedWorkerGlobalScope' in self &&
         self instanceof DedicatedWorkerGlobalScope) {
-        return globals.indexOf("Worker") >= 0 ||
-               globals.indexOf("DedicatedWorker") >= 0;
+        return globals.has("DedicatedWorker");
     }
     if ('SharedWorkerGlobalScope' in self &&
         self instanceof SharedWorkerGlobalScope) {
-        return globals.indexOf("Worker") >= 0 ||
-               globals.indexOf("SharedWorker") >= 0;
+        return globals.has("SharedWorker");
     }
     if ('ServiceWorkerGlobalScope' in self &&
         self instanceof ServiceWorkerGlobalScope) {
-        return globals.indexOf("Worker") >= 0 ||
-               globals.indexOf("ServiceWorker") >= 0;
+        return globals.has("ServiceWorker");
     }
     throw new IdlHarnessError("Unexpected global object");
 }
@@ -737,27 +743,7 @@
 
     // First merge in all the partial interfaces and implements statements we
     // encountered.
-    this.partials.forEach(function(parsed_idl)
-    {
-        if (!(parsed_idl.name in this.members)
-            || !(this.members[parsed_idl.name] instanceof IdlInterface
-                 || this.members[parsed_idl.name] instanceof IdlDictionary))
-        {
-            throw new IdlHarnessError(`Partial ${parsed_idl.type} ${parsed_idl.name} with no original ${parsed_idl.type}`);
-        }
-        if (parsed_idl.extAttrs)
-        {
-            parsed_idl.extAttrs.forEach(function(extAttr)
-            {
-                this.members[parsed_idl.name].extAttrs.push(extAttr);
-            }.bind(this));
-        }
-        parsed_idl.members.forEach(function(member)
-        {
-            this.members[parsed_idl.name].members.push(new IdlInterfaceMember(member));
-        }.bind(this));
-    }.bind(this));
-    this.partials = [];
+    this.collapse_partials();
 
     for (var lhs in this["implements"])
     {
@@ -814,7 +800,7 @@
             return;
         }
 
-        var globals = exposure_set(member, ["Window"]);
+        var globals = exposure_set(member);
         member.exposed = exposed_in(globals);
         member.exposureSet = globals;
     }.bind(this));
@@ -834,6 +820,78 @@
 };
 
 //@}
+IdlArray.prototype.collapse_partials = function()
+//@{
+{
+    const testedPartials = new Map();
+    this.partials.forEach(function(parsed_idl)
+    {
+        const originalExists = parsed_idl.name in this.members
+            && (this.members[parsed_idl.name] instanceof IdlInterface
+                || this.members[parsed_idl.name] instanceof IdlDictionary);
+
+        let partialTestName = parsed_idl.name;
+        if (!parsed_idl.untested) {
+            // Ensure unique test name in case of multiple partials.
+            let partialTestCount = 1;
+            if (testedPartials.has(parsed_idl.name)) {
+                partialTestCount += testedPartials.get(parsed_idl.name);
+                partialTestName = `${partialTestName}[${partialTestCount}]`;
+            }
+            testedPartials.set(parsed_idl.name, partialTestCount);
+
+            test(function () {
+                assert_true(originalExists, `Original ${parsed_idl.type} should be defined`);
+            }.bind(this), `Partial ${parsed_idl.type} ${partialTestName}: original ${parsed_idl.type} defined`);
+        }
+        if (!originalExists) {
+            // Not good.. but keep calm and carry on.
+            return;
+        }
+
+        if (parsed_idl.extAttrs)
+        {
+            // Special-case "Exposed". Must be a subset of original interface's exposure.
+            // Exposed on a partial is the equivalent of having the same Exposed on all nested members.
+            // See https://github.com/heycam/webidl/issues/154 for discrepency between Exposed and
+            // other extended attributes on partial interfaces.
+            const exposureAttr = parsed_idl.extAttrs.find(a => a.name === "Exposed");
+            if (exposureAttr) {
+                if (!parsed_idl.untested) {
+                    test(function () {
+                        const partialExposure = exposure_set(parsed_idl);
+                        const memberExposure = exposure_set(this.members[parsed_idl.name]);
+                        partialExposure.forEach(name => {
+                            if (!memberExposure || !memberExposure.has(name)) {
+                                throw new IdlHarnessError(
+                                    `Partial ${parsed_idl.name} ${parsed_idl.type} is exposed to '${name}', the original ${parsed_idl.type} is not.`);
+                            }
+                        });
+                    }.bind(this), `Partial ${parsed_idl.type} ${partialTestName}: valid exposure set`);
+                }
+                parsed_idl.members.forEach(function (member) {
+                    member.extAttrs.push(exposureAttr);
+                }.bind(this));
+            }
+
+            parsed_idl.extAttrs.forEach(function(extAttr)
+            {
+                // "Exposed" already handled above.
+                if (extAttr.name === "Exposed") {
+                    return;
+                }
+                this.members[parsed_idl.name].extAttrs.push(extAttr);
+            }.bind(this));
+        }
+        parsed_idl.members.forEach(function(member)
+        {
+            this.members[parsed_idl.name].members.push(new IdlInterfaceMember(member));
+        }.bind(this));
+    }.bind(this));
+    this.partials = [];
+}
+
+//@}
 IdlArray.prototype.assert_type_is = function(value, type)
 //@{
 {
@@ -1529,7 +1587,7 @@
             if (this.is_callback()) {
                 throw new IdlHarnessError("Invalid IDL: LegacyWindowAlias extended attribute on non-interface " + this.name);
             }
-            if (this.exposureSet.indexOf("Window") === -1) {
+            if (!this.exposureSet.has("Window")) {
                 throw new IdlHarnessError("Invalid IDL: LegacyWindowAlias extended attribute on " + this.name + " which is not exposed in Window");
             }
             // TODO: when testing of [NoInterfaceObject] interfaces is supported,
diff --git a/third_party/WebKit/LayoutTests/external/wpt/screen-orientation/interfaces-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/screen-orientation/interfaces-expected.txt
deleted file mode 100644
index b9da9d3..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/screen-orientation/interfaces-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-FAIL Test IDL implementation of Screen Orientation API promise_test: Unhandled rejection with value: object "Partial interface Window with no original interface"
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/selection/interfaces-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/selection/interfaces-expected.txt
index db256ea..0839184 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/selection/interfaces-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/selection/interfaces-expected.txt
@@ -1,6 +1,9 @@
 This is a testharness.js-based test.
-Found 103 tests; 99 PASS, 4 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 106 tests; 102 PASS, 4 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS Test driver
+PASS Partial interface Document: original interface defined
+PASS Partial interface Window: original interface defined
+PASS Partial interface GlobalEventHandlers: original interface defined
 PASS Document interface: operation getSelection()
 PASS Unscopable handled correctly for getSelection() on Document
 PASS Document interface: attribute onselectstart
diff --git a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/registration-updateviacache.https.html b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/registration-updateviacache.https.html
index 64c277d9..dbcc6eab 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/registration-updateviacache.https.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/registration-updateviacache.https.html
@@ -1,5 +1,6 @@
 <!DOCTYPE html>
 <title>Service Worker: Registration-updateViaCache</title>
+<meta name="timeout" content="long">
 <script src="/resources/testharness.js"></script>
 <script src="resources/testharness-helpers.js"></script>
 <script src="/resources/testharnessreport.js"></script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/svg/interfaces-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/svg/interfaces-expected.txt
index 645b555..4e71ea45 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/svg/interfaces-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/svg/interfaces-expected.txt
@@ -1,5 +1,6 @@
 This is a testharness.js-based test.
-Found 3017 tests; 2935 PASS, 82 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 3018 tests; 2936 PASS, 82 FAIL, 0 TIMEOUT, 0 NOTRUN.
+PASS Partial interface Document: original interface defined
 PASS Document interface: attribute rootElement
 PASS Unscopable handled correctly for rootElement property on Document
 PASS SVGElement interface: existence and properties of interface object
diff --git a/third_party/WebKit/LayoutTests/external/wpt/uievents/interfaces-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/uievents/interfaces-expected.txt
deleted file mode 100644
index a20681d..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/uievents/interfaces-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-FAIL Test driver promise_test: Unhandled rejection with value: object "Partial interface Window with no original interface"
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/upgrade-insecure-requests/image-redirect-upgrade.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/upgrade-insecure-requests/image-redirect-upgrade.https-expected.txt
deleted file mode 100644
index ea6241c..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/upgrade-insecure-requests/image-redirect-upgrade.https-expected.txt
+++ /dev/null
@@ -1,51 +0,0 @@
-This is a testharness.js-based test.
-FAIL insecure/same-origin => insecure/same-origin image assert_unreached: http://web-platform.test:8444/common/redirect.py?location=http%3A%2F%2Fweb-platform.test%3A8444%2Fupgrade-insecure-requests%2Fsupport%2Fpass.png should load successfully. Reached unreachable code
-FAIL insecure/same-origin => insecure/same-origin image in <iframe srcdoc> assert_unreached: http://web-platform.test:8444/common/redirect.py?location=http%3A%2F%2Fweb-platform.test%3A8444%2Fupgrade-insecure-requests%2Fsupport%2Fpass.png should load successfully. Reached unreachable code
-FAIL insecure/same-origin => insecure/same-origin image in <iframe> assert_unreached: http://web-platform.test:8444/common/redirect.py?location=http%3A%2F%2Fweb-platform.test%3A8444%2Fupgrade-insecure-requests%2Fsupport%2Fpass.png should load successfully. Reached unreachable code
-PASS insecure/same-origin => secure/same-origin image
-PASS insecure/same-origin => secure/same-origin image in <iframe srcdoc>
-PASS insecure/same-origin => secure/same-origin image in <iframe>
-FAIL insecure/same-origin => insecure/cross-origin image assert_unreached: http://web-platform.test:8444/common/redirect.py?location=http%3A%2F%2Fxn--n8j6ds53lwwkrqhv28a.web-platform.test%3A8444%2Fupgrade-insecure-requests%2Fsupport%2Fpass.png should load successfully. Reached unreachable code
-FAIL insecure/same-origin => insecure/cross-origin image in <iframe srcdoc> assert_unreached: http://web-platform.test:8444/common/redirect.py?location=http%3A%2F%2Fxn--n8j6ds53lwwkrqhv28a.web-platform.test%3A8444%2Fupgrade-insecure-requests%2Fsupport%2Fpass.png should load successfully. Reached unreachable code
-FAIL insecure/same-origin => insecure/cross-origin image in <iframe> assert_unreached: http://web-platform.test:8444/common/redirect.py?location=http%3A%2F%2Fxn--n8j6ds53lwwkrqhv28a.web-platform.test%3A8444%2Fupgrade-insecure-requests%2Fsupport%2Fpass.png should load successfully. Reached unreachable code
-PASS insecure/same-origin => secure/cross-origin image
-PASS insecure/same-origin => secure/cross-origin image in <iframe srcdoc>
-PASS insecure/same-origin => secure/cross-origin image in <iframe>
-FAIL secure/same-origin => insecure/same-origin image assert_unreached: http://web-platform.test:8444/common/redirect.py?location=http%3A%2F%2Fweb-platform.test%3A8444%2Fupgrade-insecure-requests%2Fsupport%2Fpass.png should load successfully. Reached unreachable code
-FAIL secure/same-origin => insecure/same-origin image in <iframe srcdoc> assert_unreached: http://web-platform.test:8444/common/redirect.py?location=http%3A%2F%2Fweb-platform.test%3A8444%2Fupgrade-insecure-requests%2Fsupport%2Fpass.png should load successfully. Reached unreachable code
-FAIL secure/same-origin => insecure/same-origin image in <iframe> assert_unreached: http://web-platform.test:8444/common/redirect.py?location=http%3A%2F%2Fweb-platform.test%3A8444%2Fupgrade-insecure-requests%2Fsupport%2Fpass.png should load successfully. Reached unreachable code
-PASS secure/same-origin => secure/same-origin image
-PASS secure/same-origin => secure/same-origin image in <iframe srcdoc>
-PASS secure/same-origin => secure/same-origin image in <iframe>
-FAIL secure/same-origin => insecure/cross-origin image assert_unreached: http://web-platform.test:8444/common/redirect.py?location=http%3A%2F%2Fxn--n8j6ds53lwwkrqhv28a.web-platform.test%3A8444%2Fupgrade-insecure-requests%2Fsupport%2Fpass.png should load successfully. Reached unreachable code
-FAIL secure/same-origin => insecure/cross-origin image in <iframe srcdoc> assert_unreached: http://web-platform.test:8444/common/redirect.py?location=http%3A%2F%2Fxn--n8j6ds53lwwkrqhv28a.web-platform.test%3A8444%2Fupgrade-insecure-requests%2Fsupport%2Fpass.png should load successfully. Reached unreachable code
-FAIL secure/same-origin => insecure/cross-origin image in <iframe> assert_unreached: http://web-platform.test:8444/common/redirect.py?location=http%3A%2F%2Fxn--n8j6ds53lwwkrqhv28a.web-platform.test%3A8444%2Fupgrade-insecure-requests%2Fsupport%2Fpass.png should load successfully. Reached unreachable code
-PASS secure/same-origin => secure/cross-origin image
-PASS secure/same-origin => secure/cross-origin image in <iframe srcdoc>
-PASS secure/same-origin => secure/cross-origin image in <iframe>
-FAIL insecure/cross-origin => insecure/same-origin image assert_unreached: http://web-platform.test:8444/common/redirect.py?location=http%3A%2F%2Fweb-platform.test%3A8444%2Fupgrade-insecure-requests%2Fsupport%2Fpass.png should load successfully. Reached unreachable code
-FAIL insecure/cross-origin => insecure/same-origin image in <iframe srcdoc> assert_unreached: http://web-platform.test:8444/common/redirect.py?location=http%3A%2F%2Fweb-platform.test%3A8444%2Fupgrade-insecure-requests%2Fsupport%2Fpass.png should load successfully. Reached unreachable code
-FAIL insecure/cross-origin => insecure/same-origin image in <iframe> assert_unreached: http://web-platform.test:8444/common/redirect.py?location=http%3A%2F%2Fweb-platform.test%3A8444%2Fupgrade-insecure-requests%2Fsupport%2Fpass.png should load successfully. Reached unreachable code
-PASS insecure/cross-origin => secure/same-origin image
-PASS insecure/cross-origin => secure/same-origin image in <iframe srcdoc>
-PASS insecure/cross-origin => secure/same-origin image in <iframe>
-FAIL insecure/cross-origin => insecure/cross-origin image assert_unreached: http://web-platform.test:8444/common/redirect.py?location=http%3A%2F%2Fxn--n8j6ds53lwwkrqhv28a.web-platform.test%3A8444%2Fupgrade-insecure-requests%2Fsupport%2Fpass.png should load successfully. Reached unreachable code
-FAIL insecure/cross-origin => insecure/cross-origin image in <iframe srcdoc> assert_unreached: http://web-platform.test:8444/common/redirect.py?location=http%3A%2F%2Fxn--n8j6ds53lwwkrqhv28a.web-platform.test%3A8444%2Fupgrade-insecure-requests%2Fsupport%2Fpass.png should load successfully. Reached unreachable code
-FAIL insecure/cross-origin => insecure/cross-origin image in <iframe> assert_unreached: http://web-platform.test:8444/common/redirect.py?location=http%3A%2F%2Fxn--n8j6ds53lwwkrqhv28a.web-platform.test%3A8444%2Fupgrade-insecure-requests%2Fsupport%2Fpass.png should load successfully. Reached unreachable code
-PASS insecure/cross-origin => secure/cross-origin image
-PASS insecure/cross-origin => secure/cross-origin image in <iframe srcdoc>
-PASS insecure/cross-origin => secure/cross-origin image in <iframe>
-FAIL secure/cross-origin => insecure/same-origin image assert_unreached: http://web-platform.test:8444/common/redirect.py?location=http%3A%2F%2Fweb-platform.test%3A8444%2Fupgrade-insecure-requests%2Fsupport%2Fpass.png should load successfully. Reached unreachable code
-FAIL secure/cross-origin => insecure/same-origin image in <iframe srcdoc> assert_unreached: http://web-platform.test:8444/common/redirect.py?location=http%3A%2F%2Fweb-platform.test%3A8444%2Fupgrade-insecure-requests%2Fsupport%2Fpass.png should load successfully. Reached unreachable code
-FAIL secure/cross-origin => insecure/same-origin image in <iframe> assert_unreached: http://web-platform.test:8444/common/redirect.py?location=http%3A%2F%2Fweb-platform.test%3A8444%2Fupgrade-insecure-requests%2Fsupport%2Fpass.png should load successfully. Reached unreachable code
-PASS secure/cross-origin => secure/same-origin image
-PASS secure/cross-origin => secure/same-origin image in <iframe srcdoc>
-PASS secure/cross-origin => secure/same-origin image in <iframe>
-FAIL secure/cross-origin => insecure/cross-origin image assert_unreached: http://web-platform.test:8444/common/redirect.py?location=http%3A%2F%2Fxn--n8j6ds53lwwkrqhv28a.web-platform.test%3A8444%2Fupgrade-insecure-requests%2Fsupport%2Fpass.png should load successfully. Reached unreachable code
-FAIL secure/cross-origin => insecure/cross-origin image in <iframe srcdoc> assert_unreached: http://web-platform.test:8444/common/redirect.py?location=http%3A%2F%2Fxn--n8j6ds53lwwkrqhv28a.web-platform.test%3A8444%2Fupgrade-insecure-requests%2Fsupport%2Fpass.png should load successfully. Reached unreachable code
-FAIL secure/cross-origin => insecure/cross-origin image in <iframe> assert_unreached: http://web-platform.test:8444/common/redirect.py?location=http%3A%2F%2Fxn--n8j6ds53lwwkrqhv28a.web-platform.test%3A8444%2Fupgrade-insecure-requests%2Fsupport%2Fpass.png should load successfully. Reached unreachable code
-PASS secure/cross-origin => secure/cross-origin image
-PASS secure/cross-origin => secure/cross-origin image in <iframe srcdoc>
-PASS secure/cross-origin => secure/cross-origin image in <iframe>
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/user-timing/idlharness.any.js b/third_party/WebKit/LayoutTests/external/wpt/user-timing/idlharness.any.js
new file mode 100644
index 0000000..47300bd
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/user-timing/idlharness.any.js
@@ -0,0 +1,24 @@
+// META: global=window,worker
+// META: script=/resources/WebIDLParser.js
+// META: script=/resources/idlharness.js
+
+// https://w3c.github.io/user-timing/
+
+'use strict';
+
+promise_test(async () => {
+  const idl_array = new IdlArray();
+  const idl = await fetch("/interfaces/user-timing.idl").then(r => r.text());
+  const hrtime = await fetch("/interfaces/hr-time.idl").then(r => r.text());
+  const perf = await fetch("/interfaces/performance-timeline.idl").then(r => r.text());
+  const dom = await fetch("/interfaces/dom.idl").then(r => r.text());
+
+  idl_array.add_idls(idl);
+  idl_array.add_dependency_idls(hrtime);
+  idl_array.add_dependency_idls(perf);
+  idl_array.add_dependency_idls(dom);
+  idl_array.add_objects({
+    Performance: ["performance"]
+  });
+  idl_array.test();
+}, "Test IDL implementation of user-timing API");
diff --git a/third_party/WebKit/LayoutTests/external/wpt/user-timing/idlharness.any.sharedworker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/user-timing/idlharness.any.sharedworker-expected.txt
new file mode 100644
index 0000000..aead771b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/user-timing/idlharness.any.sharedworker-expected.txt
@@ -0,0 +1,33 @@
+This is a testharness.js-based test.
+PASS Test IDL implementation of user-timing API
+PASS Partial interface Performance: original interface defined
+FAIL PerformanceMark interface: existence and properties of interface object assert_own_property: self does not have own property "PerformanceMark" expected property "PerformanceMark" missing
+FAIL PerformanceMark interface object length assert_own_property: self does not have own property "PerformanceMark" expected property "PerformanceMark" missing
+FAIL PerformanceMark interface object name assert_own_property: self does not have own property "PerformanceMark" expected property "PerformanceMark" missing
+FAIL PerformanceMark interface: existence and properties of interface prototype object assert_own_property: self does not have own property "PerformanceMark" expected property "PerformanceMark" missing
+FAIL PerformanceMark interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "PerformanceMark" expected property "PerformanceMark" missing
+FAIL PerformanceMark interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "PerformanceMark" expected property "PerformanceMark" missing
+FAIL PerformanceMeasure interface: existence and properties of interface object assert_own_property: self does not have own property "PerformanceMeasure" expected property "PerformanceMeasure" missing
+FAIL PerformanceMeasure interface object length assert_own_property: self does not have own property "PerformanceMeasure" expected property "PerformanceMeasure" missing
+FAIL PerformanceMeasure interface object name assert_own_property: self does not have own property "PerformanceMeasure" expected property "PerformanceMeasure" missing
+FAIL PerformanceMeasure interface: existence and properties of interface prototype object assert_own_property: self does not have own property "PerformanceMeasure" expected property "PerformanceMeasure" missing
+FAIL PerformanceMeasure interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "PerformanceMeasure" expected property "PerformanceMeasure" missing
+FAIL PerformanceMeasure interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "PerformanceMeasure" expected property "PerformanceMeasure" missing
+PASS Performance interface: operation mark(DOMString)
+PASS Unscopable handled correctly for mark(DOMString) on Performance
+PASS Performance interface: operation clearMarks(DOMString)
+PASS Unscopable handled correctly for clearMarks(DOMString) on Performance
+PASS Performance interface: operation measure(DOMString, DOMString, DOMString)
+PASS Unscopable handled correctly for measure(DOMString, DOMString, DOMString) on Performance
+PASS Performance interface: operation clearMeasures(DOMString)
+PASS Unscopable handled correctly for clearMeasures(DOMString) on Performance
+PASS Performance interface: performance must inherit property "mark(DOMString)" with the proper type
+PASS Performance interface: calling mark(DOMString) on performance with too few arguments must throw TypeError
+PASS Performance interface: performance must inherit property "clearMarks(DOMString)" with the proper type
+PASS Performance interface: calling clearMarks(DOMString) on performance with too few arguments must throw TypeError
+PASS Performance interface: performance must inherit property "measure(DOMString, DOMString, DOMString)" with the proper type
+PASS Performance interface: calling measure(DOMString, DOMString, DOMString) on performance with too few arguments must throw TypeError
+PASS Performance interface: performance must inherit property "clearMeasures(DOMString)" with the proper type
+PASS Performance interface: calling clearMeasures(DOMString) on performance with too few arguments must throw TypeError
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/user-timing/idlharness.any.worker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/user-timing/idlharness.any.worker-expected.txt
new file mode 100644
index 0000000..aead771b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/user-timing/idlharness.any.worker-expected.txt
@@ -0,0 +1,33 @@
+This is a testharness.js-based test.
+PASS Test IDL implementation of user-timing API
+PASS Partial interface Performance: original interface defined
+FAIL PerformanceMark interface: existence and properties of interface object assert_own_property: self does not have own property "PerformanceMark" expected property "PerformanceMark" missing
+FAIL PerformanceMark interface object length assert_own_property: self does not have own property "PerformanceMark" expected property "PerformanceMark" missing
+FAIL PerformanceMark interface object name assert_own_property: self does not have own property "PerformanceMark" expected property "PerformanceMark" missing
+FAIL PerformanceMark interface: existence and properties of interface prototype object assert_own_property: self does not have own property "PerformanceMark" expected property "PerformanceMark" missing
+FAIL PerformanceMark interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "PerformanceMark" expected property "PerformanceMark" missing
+FAIL PerformanceMark interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "PerformanceMark" expected property "PerformanceMark" missing
+FAIL PerformanceMeasure interface: existence and properties of interface object assert_own_property: self does not have own property "PerformanceMeasure" expected property "PerformanceMeasure" missing
+FAIL PerformanceMeasure interface object length assert_own_property: self does not have own property "PerformanceMeasure" expected property "PerformanceMeasure" missing
+FAIL PerformanceMeasure interface object name assert_own_property: self does not have own property "PerformanceMeasure" expected property "PerformanceMeasure" missing
+FAIL PerformanceMeasure interface: existence and properties of interface prototype object assert_own_property: self does not have own property "PerformanceMeasure" expected property "PerformanceMeasure" missing
+FAIL PerformanceMeasure interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "PerformanceMeasure" expected property "PerformanceMeasure" missing
+FAIL PerformanceMeasure interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "PerformanceMeasure" expected property "PerformanceMeasure" missing
+PASS Performance interface: operation mark(DOMString)
+PASS Unscopable handled correctly for mark(DOMString) on Performance
+PASS Performance interface: operation clearMarks(DOMString)
+PASS Unscopable handled correctly for clearMarks(DOMString) on Performance
+PASS Performance interface: operation measure(DOMString, DOMString, DOMString)
+PASS Unscopable handled correctly for measure(DOMString, DOMString, DOMString) on Performance
+PASS Performance interface: operation clearMeasures(DOMString)
+PASS Unscopable handled correctly for clearMeasures(DOMString) on Performance
+PASS Performance interface: performance must inherit property "mark(DOMString)" with the proper type
+PASS Performance interface: calling mark(DOMString) on performance with too few arguments must throw TypeError
+PASS Performance interface: performance must inherit property "clearMarks(DOMString)" with the proper type
+PASS Performance interface: calling clearMarks(DOMString) on performance with too few arguments must throw TypeError
+PASS Performance interface: performance must inherit property "measure(DOMString, DOMString, DOMString)" with the proper type
+PASS Performance interface: calling measure(DOMString, DOMString, DOMString) on performance with too few arguments must throw TypeError
+PASS Performance interface: performance must inherit property "clearMeasures(DOMString)" with the proper type
+PASS Performance interface: calling clearMeasures(DOMString) on performance with too few arguments must throw TypeError
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/user-timing/idlharness.html b/third_party/WebKit/LayoutTests/external/wpt/user-timing/idlharness.html
deleted file mode 100644
index ca5f7c3..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/user-timing/idlharness.html
+++ /dev/null
@@ -1,63 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<meta charset="utf-8">
-<title>User Timing IDL tests</title>
-<link rel="author" title="W3C" href="http://www.w3.org/" />
-<link rel="help" href="http://www.w3.org/TR/user-timing/#extensions-performance-interface"/>
-<link rel="help" href="http://www.w3.org/TR/user-timing/#performancemark"/>
-<link rel="help" href="http://www.w3.org/TR/user-timing/#performancemeasure"/>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="/resources/WebIDLParser.js"></script>
-<script src="/resources/idlharness.js"></script>
-</head>
-<body>
-<h1>User Timing IDL tests</h1>
-<div id="log"></div>
-
-<pre id='untested_idl' style='display:none'>
-[Exposed=(Window,Worker)]
-interface Performance {
-};
-
-[Exposed=(Window,Worker)]
-interface PerformanceEntry {
-};
-</pre>
-
-<pre id='idl'>
-partial interface Performance {
-    void mark(DOMString markName);
-    void clearMarks(optional  DOMString markName);
-
-    void measure(DOMString measureName, optional DOMString startMark, optional DOMString endMark);
-    void clearMeasures(optional DOMString measureName);
-};
-
-[Exposed=(Window,Worker)]
-interface PerformanceMark : PerformanceEntry {
-};
-
-[Exposed=(Window,Worker)]
-interface PerformanceMeasure : PerformanceEntry {
-};
-
-</pre>
-
-<script>
-
-(function() {
-  var idl_array = new IdlArray();
-
-  idl_array.add_untested_idls(document.getElementById("untested_idl").textContent);
-  idl_array.add_idls(document.getElementById("idl").textContent);
-
-  idl_array.add_objects({Performance: ["window.performance"]});
-
-  idl_array.test();
-})();
-
-</script>
-</body>
-</html>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/user-timing/idlharness.https.any.serviceworker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/user-timing/idlharness.https.any.serviceworker-expected.txt
new file mode 100644
index 0000000..aead771b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/user-timing/idlharness.https.any.serviceworker-expected.txt
@@ -0,0 +1,33 @@
+This is a testharness.js-based test.
+PASS Test IDL implementation of user-timing API
+PASS Partial interface Performance: original interface defined
+FAIL PerformanceMark interface: existence and properties of interface object assert_own_property: self does not have own property "PerformanceMark" expected property "PerformanceMark" missing
+FAIL PerformanceMark interface object length assert_own_property: self does not have own property "PerformanceMark" expected property "PerformanceMark" missing
+FAIL PerformanceMark interface object name assert_own_property: self does not have own property "PerformanceMark" expected property "PerformanceMark" missing
+FAIL PerformanceMark interface: existence and properties of interface prototype object assert_own_property: self does not have own property "PerformanceMark" expected property "PerformanceMark" missing
+FAIL PerformanceMark interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "PerformanceMark" expected property "PerformanceMark" missing
+FAIL PerformanceMark interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "PerformanceMark" expected property "PerformanceMark" missing
+FAIL PerformanceMeasure interface: existence and properties of interface object assert_own_property: self does not have own property "PerformanceMeasure" expected property "PerformanceMeasure" missing
+FAIL PerformanceMeasure interface object length assert_own_property: self does not have own property "PerformanceMeasure" expected property "PerformanceMeasure" missing
+FAIL PerformanceMeasure interface object name assert_own_property: self does not have own property "PerformanceMeasure" expected property "PerformanceMeasure" missing
+FAIL PerformanceMeasure interface: existence and properties of interface prototype object assert_own_property: self does not have own property "PerformanceMeasure" expected property "PerformanceMeasure" missing
+FAIL PerformanceMeasure interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "PerformanceMeasure" expected property "PerformanceMeasure" missing
+FAIL PerformanceMeasure interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "PerformanceMeasure" expected property "PerformanceMeasure" missing
+PASS Performance interface: operation mark(DOMString)
+PASS Unscopable handled correctly for mark(DOMString) on Performance
+PASS Performance interface: operation clearMarks(DOMString)
+PASS Unscopable handled correctly for clearMarks(DOMString) on Performance
+PASS Performance interface: operation measure(DOMString, DOMString, DOMString)
+PASS Unscopable handled correctly for measure(DOMString, DOMString, DOMString) on Performance
+PASS Performance interface: operation clearMeasures(DOMString)
+PASS Unscopable handled correctly for clearMeasures(DOMString) on Performance
+PASS Performance interface: performance must inherit property "mark(DOMString)" with the proper type
+PASS Performance interface: calling mark(DOMString) on performance with too few arguments must throw TypeError
+PASS Performance interface: performance must inherit property "clearMarks(DOMString)" with the proper type
+PASS Performance interface: calling clearMarks(DOMString) on performance with too few arguments must throw TypeError
+PASS Performance interface: performance must inherit property "measure(DOMString, DOMString, DOMString)" with the proper type
+PASS Performance interface: calling measure(DOMString, DOMString, DOMString) on performance with too few arguments must throw TypeError
+PASS Performance interface: performance must inherit property "clearMeasures(DOMString)" with the proper type
+PASS Performance interface: calling clearMeasures(DOMString) on performance with too few arguments must throw TypeError
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webusb/idlharness.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/webusb/idlharness.https-expected.txt
new file mode 100644
index 0000000..d0f9e4a3
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/webusb/idlharness.https-expected.txt
@@ -0,0 +1,320 @@
+This is a testharness.js-based test.
+PASS WebUSB IDL test
+PASS Partial interface Navigator: original interface defined
+PASS Partial interface Navigator: valid exposure set
+PASS Partial interface WorkerNavigator: original interface defined
+FAIL Partial interface WorkerNavigator: valid exposure set Partial WorkerNavigator interface is exposed to 'DedicatedWorker', the original interface is not.
+PASS USB interface: existence and properties of interface object
+PASS USB interface object length
+PASS USB interface object name
+PASS USB interface: existence and properties of interface prototype object
+PASS USB interface: existence and properties of interface prototype object's "constructor" property
+PASS USB interface: existence and properties of interface prototype object's @@unscopables property
+PASS USB interface: attribute onconnect
+PASS Unscopable handled correctly for onconnect property on USB
+PASS USB interface: attribute ondisconnect
+PASS Unscopable handled correctly for ondisconnect property on USB
+PASS USB interface: operation getDevices()
+PASS Unscopable handled correctly for getDevices() on USB
+PASS USB interface: operation requestDevice(USBDeviceRequestOptions)
+PASS Unscopable handled correctly for requestDevice(USBDeviceRequestOptions) on USB
+PASS USB must be primary interface of navigator.usb
+PASS Stringification of navigator.usb
+PASS USB interface: navigator.usb must inherit property "onconnect" with the proper type
+PASS USB interface: navigator.usb must inherit property "ondisconnect" with the proper type
+PASS USB interface: navigator.usb must inherit property "getDevices()" with the proper type
+PASS USB interface: navigator.usb must inherit property "requestDevice(USBDeviceRequestOptions)" with the proper type
+PASS USB interface: calling requestDevice(USBDeviceRequestOptions) on navigator.usb with too few arguments must throw TypeError
+PASS USBConnectionEvent interface: existence and properties of interface object
+PASS USBConnectionEvent interface object length
+PASS USBConnectionEvent interface object name
+PASS USBConnectionEvent interface: existence and properties of interface prototype object
+PASS USBConnectionEvent interface: existence and properties of interface prototype object's "constructor" property
+PASS USBConnectionEvent interface: existence and properties of interface prototype object's @@unscopables property
+PASS USBConnectionEvent interface: attribute device
+PASS Unscopable handled correctly for device property on USBConnectionEvent
+PASS USBConnectionEvent must be primary interface of usbConnectionEvent
+PASS Stringification of usbConnectionEvent
+PASS USBConnectionEvent interface: usbConnectionEvent must inherit property "device" with the proper type
+PASS USBDevice interface: existence and properties of interface object
+PASS USBDevice interface object length
+PASS USBDevice interface object name
+PASS USBDevice interface: existence and properties of interface prototype object
+PASS USBDevice interface: existence and properties of interface prototype object's "constructor" property
+PASS USBDevice interface: existence and properties of interface prototype object's @@unscopables property
+PASS USBDevice interface: attribute usbVersionMajor
+PASS Unscopable handled correctly for usbVersionMajor property on USBDevice
+PASS USBDevice interface: attribute usbVersionMinor
+PASS Unscopable handled correctly for usbVersionMinor property on USBDevice
+PASS USBDevice interface: attribute usbVersionSubminor
+PASS Unscopable handled correctly for usbVersionSubminor property on USBDevice
+PASS USBDevice interface: attribute deviceClass
+PASS Unscopable handled correctly for deviceClass property on USBDevice
+PASS USBDevice interface: attribute deviceSubclass
+PASS Unscopable handled correctly for deviceSubclass property on USBDevice
+PASS USBDevice interface: attribute deviceProtocol
+PASS Unscopable handled correctly for deviceProtocol property on USBDevice
+PASS USBDevice interface: attribute vendorId
+PASS Unscopable handled correctly for vendorId property on USBDevice
+PASS USBDevice interface: attribute productId
+PASS Unscopable handled correctly for productId property on USBDevice
+PASS USBDevice interface: attribute deviceVersionMajor
+PASS Unscopable handled correctly for deviceVersionMajor property on USBDevice
+PASS USBDevice interface: attribute deviceVersionMinor
+PASS Unscopable handled correctly for deviceVersionMinor property on USBDevice
+PASS USBDevice interface: attribute deviceVersionSubminor
+PASS Unscopable handled correctly for deviceVersionSubminor property on USBDevice
+PASS USBDevice interface: attribute manufacturerName
+PASS Unscopable handled correctly for manufacturerName property on USBDevice
+PASS USBDevice interface: attribute productName
+PASS Unscopable handled correctly for productName property on USBDevice
+PASS USBDevice interface: attribute serialNumber
+PASS Unscopable handled correctly for serialNumber property on USBDevice
+PASS USBDevice interface: attribute configuration
+PASS Unscopable handled correctly for configuration property on USBDevice
+PASS USBDevice interface: attribute configurations
+PASS Unscopable handled correctly for configurations property on USBDevice
+PASS USBDevice interface: attribute opened
+PASS Unscopable handled correctly for opened property on USBDevice
+PASS USBDevice interface: operation open()
+PASS Unscopable handled correctly for open() on USBDevice
+PASS USBDevice interface: operation close()
+PASS Unscopable handled correctly for close() on USBDevice
+PASS USBDevice interface: operation selectConfiguration(octet)
+PASS Unscopable handled correctly for selectConfiguration(octet) on USBDevice
+PASS USBDevice interface: operation claimInterface(octet)
+PASS Unscopable handled correctly for claimInterface(octet) on USBDevice
+PASS USBDevice interface: operation releaseInterface(octet)
+PASS Unscopable handled correctly for releaseInterface(octet) on USBDevice
+PASS USBDevice interface: operation selectAlternateInterface(octet, octet)
+PASS Unscopable handled correctly for selectAlternateInterface(octet, octet) on USBDevice
+PASS USBDevice interface: operation controlTransferIn(USBControlTransferParameters, unsigned short)
+PASS Unscopable handled correctly for controlTransferIn(USBControlTransferParameters, unsigned short) on USBDevice
+PASS USBDevice interface: operation controlTransferOut(USBControlTransferParameters, BufferSource)
+PASS Unscopable handled correctly for controlTransferOut(USBControlTransferParameters, BufferSource) on USBDevice
+PASS USBDevice interface: operation clearHalt(USBDirection, octet)
+PASS Unscopable handled correctly for clearHalt(USBDirection, octet) on USBDevice
+PASS USBDevice interface: operation transferIn(octet, unsigned long)
+PASS Unscopable handled correctly for transferIn(octet, unsigned long) on USBDevice
+PASS USBDevice interface: operation transferOut(octet, BufferSource)
+PASS Unscopable handled correctly for transferOut(octet, BufferSource) on USBDevice
+PASS USBDevice interface: operation isochronousTransferIn(octet, [object Object])
+PASS Unscopable handled correctly for isochronousTransferIn(octet, [object Object]) on USBDevice
+PASS USBDevice interface: operation isochronousTransferOut(octet, BufferSource, [object Object])
+PASS Unscopable handled correctly for isochronousTransferOut(octet, BufferSource, [object Object]) on USBDevice
+PASS USBDevice interface: operation reset()
+PASS Unscopable handled correctly for reset() on USBDevice
+PASS USBDevice must be primary interface of usbDevice
+PASS Stringification of usbDevice
+PASS USBDevice interface: usbDevice must inherit property "usbVersionMajor" with the proper type
+PASS USBDevice interface: usbDevice must inherit property "usbVersionMinor" with the proper type
+PASS USBDevice interface: usbDevice must inherit property "usbVersionSubminor" with the proper type
+PASS USBDevice interface: usbDevice must inherit property "deviceClass" with the proper type
+PASS USBDevice interface: usbDevice must inherit property "deviceSubclass" with the proper type
+PASS USBDevice interface: usbDevice must inherit property "deviceProtocol" with the proper type
+PASS USBDevice interface: usbDevice must inherit property "vendorId" with the proper type
+PASS USBDevice interface: usbDevice must inherit property "productId" with the proper type
+PASS USBDevice interface: usbDevice must inherit property "deviceVersionMajor" with the proper type
+PASS USBDevice interface: usbDevice must inherit property "deviceVersionMinor" with the proper type
+PASS USBDevice interface: usbDevice must inherit property "deviceVersionSubminor" with the proper type
+PASS USBDevice interface: usbDevice must inherit property "manufacturerName" with the proper type
+PASS USBDevice interface: usbDevice must inherit property "productName" with the proper type
+PASS USBDevice interface: usbDevice must inherit property "serialNumber" with the proper type
+PASS USBDevice interface: usbDevice must inherit property "configuration" with the proper type
+PASS USBDevice interface: usbDevice must inherit property "configurations" with the proper type
+PASS USBDevice interface: usbDevice must inherit property "opened" with the proper type
+PASS USBDevice interface: usbDevice must inherit property "open()" with the proper type
+PASS USBDevice interface: usbDevice must inherit property "close()" with the proper type
+PASS USBDevice interface: usbDevice must inherit property "selectConfiguration(octet)" with the proper type
+PASS USBDevice interface: calling selectConfiguration(octet) on usbDevice with too few arguments must throw TypeError
+PASS USBDevice interface: usbDevice must inherit property "claimInterface(octet)" with the proper type
+PASS USBDevice interface: calling claimInterface(octet) on usbDevice with too few arguments must throw TypeError
+PASS USBDevice interface: usbDevice must inherit property "releaseInterface(octet)" with the proper type
+PASS USBDevice interface: calling releaseInterface(octet) on usbDevice with too few arguments must throw TypeError
+PASS USBDevice interface: usbDevice must inherit property "selectAlternateInterface(octet, octet)" with the proper type
+PASS USBDevice interface: calling selectAlternateInterface(octet, octet) on usbDevice with too few arguments must throw TypeError
+PASS USBDevice interface: usbDevice must inherit property "controlTransferIn(USBControlTransferParameters, unsigned short)" with the proper type
+PASS USBDevice interface: calling controlTransferIn(USBControlTransferParameters, unsigned short) on usbDevice with too few arguments must throw TypeError
+PASS USBDevice interface: usbDevice must inherit property "controlTransferOut(USBControlTransferParameters, BufferSource)" with the proper type
+PASS USBDevice interface: calling controlTransferOut(USBControlTransferParameters, BufferSource) on usbDevice with too few arguments must throw TypeError
+PASS USBDevice interface: usbDevice must inherit property "clearHalt(USBDirection, octet)" with the proper type
+PASS USBDevice interface: calling clearHalt(USBDirection, octet) on usbDevice with too few arguments must throw TypeError
+PASS USBDevice interface: usbDevice must inherit property "transferIn(octet, unsigned long)" with the proper type
+PASS USBDevice interface: calling transferIn(octet, unsigned long) on usbDevice with too few arguments must throw TypeError
+PASS USBDevice interface: usbDevice must inherit property "transferOut(octet, BufferSource)" with the proper type
+PASS USBDevice interface: calling transferOut(octet, BufferSource) on usbDevice with too few arguments must throw TypeError
+PASS USBDevice interface: usbDevice must inherit property "isochronousTransferIn(octet, [object Object])" with the proper type
+PASS USBDevice interface: calling isochronousTransferIn(octet, [object Object]) on usbDevice with too few arguments must throw TypeError
+PASS USBDevice interface: usbDevice must inherit property "isochronousTransferOut(octet, BufferSource, [object Object])" with the proper type
+PASS USBDevice interface: calling isochronousTransferOut(octet, BufferSource, [object Object]) on usbDevice with too few arguments must throw TypeError
+PASS USBDevice interface: usbDevice must inherit property "reset()" with the proper type
+PASS USBInTransferResult interface: existence and properties of interface object
+PASS USBInTransferResult interface object length
+PASS USBInTransferResult interface object name
+PASS USBInTransferResult interface: existence and properties of interface prototype object
+PASS USBInTransferResult interface: existence and properties of interface prototype object's "constructor" property
+PASS USBInTransferResult interface: existence and properties of interface prototype object's @@unscopables property
+PASS USBInTransferResult interface: attribute data
+PASS Unscopable handled correctly for data property on USBInTransferResult
+PASS USBInTransferResult interface: attribute status
+PASS Unscopable handled correctly for status property on USBInTransferResult
+PASS USBInTransferResult must be primary interface of new USBInTransferResult("ok")
+PASS Stringification of new USBInTransferResult("ok")
+PASS USBInTransferResult interface: new USBInTransferResult("ok") must inherit property "data" with the proper type
+PASS USBInTransferResult interface: new USBInTransferResult("ok") must inherit property "status" with the proper type
+PASS USBOutTransferResult interface: existence and properties of interface object
+PASS USBOutTransferResult interface object length
+PASS USBOutTransferResult interface object name
+PASS USBOutTransferResult interface: existence and properties of interface prototype object
+PASS USBOutTransferResult interface: existence and properties of interface prototype object's "constructor" property
+PASS USBOutTransferResult interface: existence and properties of interface prototype object's @@unscopables property
+PASS USBOutTransferResult interface: attribute bytesWritten
+PASS Unscopable handled correctly for bytesWritten property on USBOutTransferResult
+PASS USBOutTransferResult interface: attribute status
+PASS Unscopable handled correctly for status property on USBOutTransferResult
+PASS USBOutTransferResult must be primary interface of new USBOutTransferResult("ok")
+PASS Stringification of new USBOutTransferResult("ok")
+PASS USBOutTransferResult interface: new USBOutTransferResult("ok") must inherit property "bytesWritten" with the proper type
+PASS USBOutTransferResult interface: new USBOutTransferResult("ok") must inherit property "status" with the proper type
+PASS USBIsochronousInTransferPacket interface: existence and properties of interface object
+PASS USBIsochronousInTransferPacket interface object length
+PASS USBIsochronousInTransferPacket interface object name
+PASS USBIsochronousInTransferPacket interface: existence and properties of interface prototype object
+PASS USBIsochronousInTransferPacket interface: existence and properties of interface prototype object's "constructor" property
+PASS USBIsochronousInTransferPacket interface: existence and properties of interface prototype object's @@unscopables property
+PASS USBIsochronousInTransferPacket interface: attribute data
+PASS Unscopable handled correctly for data property on USBIsochronousInTransferPacket
+PASS USBIsochronousInTransferPacket interface: attribute status
+PASS Unscopable handled correctly for status property on USBIsochronousInTransferPacket
+PASS USBIsochronousInTransferPacket must be primary interface of new USBIsochronousInTransferPacket("ok")
+PASS Stringification of new USBIsochronousInTransferPacket("ok")
+PASS USBIsochronousInTransferPacket interface: new USBIsochronousInTransferPacket("ok") must inherit property "data" with the proper type
+PASS USBIsochronousInTransferPacket interface: new USBIsochronousInTransferPacket("ok") must inherit property "status" with the proper type
+PASS USBIsochronousInTransferResult interface: existence and properties of interface object
+PASS USBIsochronousInTransferResult interface object length
+PASS USBIsochronousInTransferResult interface object name
+PASS USBIsochronousInTransferResult interface: existence and properties of interface prototype object
+PASS USBIsochronousInTransferResult interface: existence and properties of interface prototype object's "constructor" property
+PASS USBIsochronousInTransferResult interface: existence and properties of interface prototype object's @@unscopables property
+PASS USBIsochronousInTransferResult interface: attribute data
+PASS Unscopable handled correctly for data property on USBIsochronousInTransferResult
+PASS USBIsochronousInTransferResult interface: attribute packets
+PASS Unscopable handled correctly for packets property on USBIsochronousInTransferResult
+PASS USBIsochronousInTransferResult must be primary interface of new USBIsochronousInTransferResult([])
+PASS Stringification of new USBIsochronousInTransferResult([])
+PASS USBIsochronousInTransferResult interface: new USBIsochronousInTransferResult([]) must inherit property "data" with the proper type
+PASS USBIsochronousInTransferResult interface: new USBIsochronousInTransferResult([]) must inherit property "packets" with the proper type
+PASS USBIsochronousOutTransferPacket interface: existence and properties of interface object
+PASS USBIsochronousOutTransferPacket interface object length
+PASS USBIsochronousOutTransferPacket interface object name
+PASS USBIsochronousOutTransferPacket interface: existence and properties of interface prototype object
+PASS USBIsochronousOutTransferPacket interface: existence and properties of interface prototype object's "constructor" property
+PASS USBIsochronousOutTransferPacket interface: existence and properties of interface prototype object's @@unscopables property
+PASS USBIsochronousOutTransferPacket interface: attribute bytesWritten
+PASS Unscopable handled correctly for bytesWritten property on USBIsochronousOutTransferPacket
+PASS USBIsochronousOutTransferPacket interface: attribute status
+PASS Unscopable handled correctly for status property on USBIsochronousOutTransferPacket
+PASS USBIsochronousOutTransferPacket must be primary interface of new USBIsochronousOutTransferPacket("ok")
+PASS Stringification of new USBIsochronousOutTransferPacket("ok")
+PASS USBIsochronousOutTransferPacket interface: new USBIsochronousOutTransferPacket("ok") must inherit property "bytesWritten" with the proper type
+PASS USBIsochronousOutTransferPacket interface: new USBIsochronousOutTransferPacket("ok") must inherit property "status" with the proper type
+PASS USBIsochronousOutTransferResult interface: existence and properties of interface object
+PASS USBIsochronousOutTransferResult interface object length
+PASS USBIsochronousOutTransferResult interface object name
+PASS USBIsochronousOutTransferResult interface: existence and properties of interface prototype object
+PASS USBIsochronousOutTransferResult interface: existence and properties of interface prototype object's "constructor" property
+PASS USBIsochronousOutTransferResult interface: existence and properties of interface prototype object's @@unscopables property
+PASS USBIsochronousOutTransferResult interface: attribute packets
+PASS Unscopable handled correctly for packets property on USBIsochronousOutTransferResult
+PASS USBIsochronousOutTransferResult must be primary interface of new USBIsochronousOutTransferResult([])
+PASS Stringification of new USBIsochronousOutTransferResult([])
+PASS USBIsochronousOutTransferResult interface: new USBIsochronousOutTransferResult([]) must inherit property "packets" with the proper type
+PASS USBConfiguration interface: existence and properties of interface object
+PASS USBConfiguration interface object length
+PASS USBConfiguration interface object name
+PASS USBConfiguration interface: existence and properties of interface prototype object
+PASS USBConfiguration interface: existence and properties of interface prototype object's "constructor" property
+PASS USBConfiguration interface: existence and properties of interface prototype object's @@unscopables property
+PASS USBConfiguration interface: attribute configurationValue
+PASS Unscopable handled correctly for configurationValue property on USBConfiguration
+PASS USBConfiguration interface: attribute configurationName
+PASS Unscopable handled correctly for configurationName property on USBConfiguration
+PASS USBConfiguration interface: attribute interfaces
+PASS Unscopable handled correctly for interfaces property on USBConfiguration
+PASS USBConfiguration must be primary interface of usbConfiguration
+PASS Stringification of usbConfiguration
+PASS USBConfiguration interface: usbConfiguration must inherit property "configurationValue" with the proper type
+PASS USBConfiguration interface: usbConfiguration must inherit property "configurationName" with the proper type
+PASS USBConfiguration interface: usbConfiguration must inherit property "interfaces" with the proper type
+PASS USBInterface interface: existence and properties of interface object
+PASS USBInterface interface object length
+PASS USBInterface interface object name
+PASS USBInterface interface: existence and properties of interface prototype object
+PASS USBInterface interface: existence and properties of interface prototype object's "constructor" property
+PASS USBInterface interface: existence and properties of interface prototype object's @@unscopables property
+PASS USBInterface interface: attribute interfaceNumber
+PASS Unscopable handled correctly for interfaceNumber property on USBInterface
+PASS USBInterface interface: attribute alternate
+PASS Unscopable handled correctly for alternate property on USBInterface
+PASS USBInterface interface: attribute alternates
+PASS Unscopable handled correctly for alternates property on USBInterface
+PASS USBInterface interface: attribute claimed
+PASS Unscopable handled correctly for claimed property on USBInterface
+PASS USBInterface must be primary interface of usbInterface
+PASS Stringification of usbInterface
+PASS USBInterface interface: usbInterface must inherit property "interfaceNumber" with the proper type
+PASS USBInterface interface: usbInterface must inherit property "alternate" with the proper type
+PASS USBInterface interface: usbInterface must inherit property "alternates" with the proper type
+PASS USBInterface interface: usbInterface must inherit property "claimed" with the proper type
+PASS USBAlternateInterface interface: existence and properties of interface object
+PASS USBAlternateInterface interface object length
+PASS USBAlternateInterface interface object name
+PASS USBAlternateInterface interface: existence and properties of interface prototype object
+PASS USBAlternateInterface interface: existence and properties of interface prototype object's "constructor" property
+PASS USBAlternateInterface interface: existence and properties of interface prototype object's @@unscopables property
+PASS USBAlternateInterface interface: attribute alternateSetting
+PASS Unscopable handled correctly for alternateSetting property on USBAlternateInterface
+PASS USBAlternateInterface interface: attribute interfaceClass
+PASS Unscopable handled correctly for interfaceClass property on USBAlternateInterface
+PASS USBAlternateInterface interface: attribute interfaceSubclass
+PASS Unscopable handled correctly for interfaceSubclass property on USBAlternateInterface
+PASS USBAlternateInterface interface: attribute interfaceProtocol
+PASS Unscopable handled correctly for interfaceProtocol property on USBAlternateInterface
+PASS USBAlternateInterface interface: attribute interfaceName
+PASS Unscopable handled correctly for interfaceName property on USBAlternateInterface
+PASS USBAlternateInterface interface: attribute endpoints
+PASS Unscopable handled correctly for endpoints property on USBAlternateInterface
+PASS USBAlternateInterface must be primary interface of usbAlternateInterface
+PASS Stringification of usbAlternateInterface
+PASS USBAlternateInterface interface: usbAlternateInterface must inherit property "alternateSetting" with the proper type
+PASS USBAlternateInterface interface: usbAlternateInterface must inherit property "interfaceClass" with the proper type
+PASS USBAlternateInterface interface: usbAlternateInterface must inherit property "interfaceSubclass" with the proper type
+PASS USBAlternateInterface interface: usbAlternateInterface must inherit property "interfaceProtocol" with the proper type
+PASS USBAlternateInterface interface: usbAlternateInterface must inherit property "interfaceName" with the proper type
+PASS USBAlternateInterface interface: usbAlternateInterface must inherit property "endpoints" with the proper type
+PASS USBEndpoint interface: existence and properties of interface object
+PASS USBEndpoint interface object length
+PASS USBEndpoint interface object name
+PASS USBEndpoint interface: existence and properties of interface prototype object
+PASS USBEndpoint interface: existence and properties of interface prototype object's "constructor" property
+PASS USBEndpoint interface: existence and properties of interface prototype object's @@unscopables property
+PASS USBEndpoint interface: attribute endpointNumber
+PASS Unscopable handled correctly for endpointNumber property on USBEndpoint
+PASS USBEndpoint interface: attribute direction
+PASS Unscopable handled correctly for direction property on USBEndpoint
+PASS USBEndpoint interface: attribute type
+PASS Unscopable handled correctly for type property on USBEndpoint
+PASS USBEndpoint interface: attribute packetSize
+PASS Unscopable handled correctly for packetSize property on USBEndpoint
+PASS USBEndpoint must be primary interface of usbEndpoint
+PASS Stringification of usbEndpoint
+PASS USBEndpoint interface: usbEndpoint must inherit property "endpointNumber" with the proper type
+PASS USBEndpoint interface: usbEndpoint must inherit property "direction" with the proper type
+PASS USBEndpoint interface: usbEndpoint must inherit property "type" with the proper type
+PASS USBEndpoint interface: usbEndpoint must inherit property "packetSize" with the proper type
+PASS Navigator interface: attribute usb
+PASS Unscopable handled correctly for usb property on Navigator
+PASS Navigator interface: navigator must inherit property "usb" with the proper type
+FAIL WorkerNavigator interface: member usb Cannot use 'in' operator to search for 'usb' in undefined
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webusb/worker/idlharness.dedicatedworker.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/webusb/worker/idlharness.dedicatedworker.https-expected.txt
new file mode 100644
index 0000000..14ea2486
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/webusb/worker/idlharness.dedicatedworker.https-expected.txt
@@ -0,0 +1,318 @@
+This is a testharness.js-based test.
+PASS WebUSB on Workers IDL test
+PASS Partial interface Navigator: original interface defined
+PASS Partial interface Navigator: valid exposure set
+PASS Partial interface WorkerNavigator: original interface defined
+FAIL Partial interface WorkerNavigator: valid exposure set Partial WorkerNavigator interface is exposed to 'DedicatedWorker', the original interface is not.
+PASS USB interface: existence and properties of interface object
+PASS USB interface object length
+PASS USB interface object name
+PASS USB interface: existence and properties of interface prototype object
+PASS USB interface: existence and properties of interface prototype object's "constructor" property
+PASS USB interface: existence and properties of interface prototype object's @@unscopables property
+PASS USB interface: attribute onconnect
+PASS Unscopable handled correctly for onconnect property on USB
+PASS USB interface: attribute ondisconnect
+PASS Unscopable handled correctly for ondisconnect property on USB
+PASS USB interface: operation getDevices()
+PASS Unscopable handled correctly for getDevices() on USB
+PASS USB interface: member requestDevice
+PASS USB must be primary interface of navigator.usb
+PASS Stringification of navigator.usb
+PASS USB interface: navigator.usb must inherit property "onconnect" with the proper type
+PASS USB interface: navigator.usb must inherit property "ondisconnect" with the proper type
+PASS USB interface: navigator.usb must inherit property "getDevices()" with the proper type
+PASS USB interface: navigator.usb must not have property "requestDevice"
+PASS USBConnectionEvent interface: existence and properties of interface object
+PASS USBConnectionEvent interface object length
+PASS USBConnectionEvent interface object name
+PASS USBConnectionEvent interface: existence and properties of interface prototype object
+PASS USBConnectionEvent interface: existence and properties of interface prototype object's "constructor" property
+PASS USBConnectionEvent interface: existence and properties of interface prototype object's @@unscopables property
+PASS USBConnectionEvent interface: attribute device
+PASS Unscopable handled correctly for device property on USBConnectionEvent
+PASS USBConnectionEvent must be primary interface of usbConnectionEvent
+PASS Stringification of usbConnectionEvent
+PASS USBConnectionEvent interface: usbConnectionEvent must inherit property "device" with the proper type
+PASS USBDevice interface: existence and properties of interface object
+PASS USBDevice interface object length
+PASS USBDevice interface object name
+PASS USBDevice interface: existence and properties of interface prototype object
+PASS USBDevice interface: existence and properties of interface prototype object's "constructor" property
+PASS USBDevice interface: existence and properties of interface prototype object's @@unscopables property
+PASS USBDevice interface: attribute usbVersionMajor
+PASS Unscopable handled correctly for usbVersionMajor property on USBDevice
+PASS USBDevice interface: attribute usbVersionMinor
+PASS Unscopable handled correctly for usbVersionMinor property on USBDevice
+PASS USBDevice interface: attribute usbVersionSubminor
+PASS Unscopable handled correctly for usbVersionSubminor property on USBDevice
+PASS USBDevice interface: attribute deviceClass
+PASS Unscopable handled correctly for deviceClass property on USBDevice
+PASS USBDevice interface: attribute deviceSubclass
+PASS Unscopable handled correctly for deviceSubclass property on USBDevice
+PASS USBDevice interface: attribute deviceProtocol
+PASS Unscopable handled correctly for deviceProtocol property on USBDevice
+PASS USBDevice interface: attribute vendorId
+PASS Unscopable handled correctly for vendorId property on USBDevice
+PASS USBDevice interface: attribute productId
+PASS Unscopable handled correctly for productId property on USBDevice
+PASS USBDevice interface: attribute deviceVersionMajor
+PASS Unscopable handled correctly for deviceVersionMajor property on USBDevice
+PASS USBDevice interface: attribute deviceVersionMinor
+PASS Unscopable handled correctly for deviceVersionMinor property on USBDevice
+PASS USBDevice interface: attribute deviceVersionSubminor
+PASS Unscopable handled correctly for deviceVersionSubminor property on USBDevice
+PASS USBDevice interface: attribute manufacturerName
+PASS Unscopable handled correctly for manufacturerName property on USBDevice
+PASS USBDevice interface: attribute productName
+PASS Unscopable handled correctly for productName property on USBDevice
+PASS USBDevice interface: attribute serialNumber
+PASS Unscopable handled correctly for serialNumber property on USBDevice
+PASS USBDevice interface: attribute configuration
+PASS Unscopable handled correctly for configuration property on USBDevice
+PASS USBDevice interface: attribute configurations
+PASS Unscopable handled correctly for configurations property on USBDevice
+PASS USBDevice interface: attribute opened
+PASS Unscopable handled correctly for opened property on USBDevice
+PASS USBDevice interface: operation open()
+PASS Unscopable handled correctly for open() on USBDevice
+PASS USBDevice interface: operation close()
+PASS Unscopable handled correctly for close() on USBDevice
+PASS USBDevice interface: operation selectConfiguration(octet)
+PASS Unscopable handled correctly for selectConfiguration(octet) on USBDevice
+PASS USBDevice interface: operation claimInterface(octet)
+PASS Unscopable handled correctly for claimInterface(octet) on USBDevice
+PASS USBDevice interface: operation releaseInterface(octet)
+PASS Unscopable handled correctly for releaseInterface(octet) on USBDevice
+PASS USBDevice interface: operation selectAlternateInterface(octet, octet)
+PASS Unscopable handled correctly for selectAlternateInterface(octet, octet) on USBDevice
+PASS USBDevice interface: operation controlTransferIn(USBControlTransferParameters, unsigned short)
+PASS Unscopable handled correctly for controlTransferIn(USBControlTransferParameters, unsigned short) on USBDevice
+PASS USBDevice interface: operation controlTransferOut(USBControlTransferParameters, BufferSource)
+PASS Unscopable handled correctly for controlTransferOut(USBControlTransferParameters, BufferSource) on USBDevice
+PASS USBDevice interface: operation clearHalt(USBDirection, octet)
+PASS Unscopable handled correctly for clearHalt(USBDirection, octet) on USBDevice
+PASS USBDevice interface: operation transferIn(octet, unsigned long)
+PASS Unscopable handled correctly for transferIn(octet, unsigned long) on USBDevice
+PASS USBDevice interface: operation transferOut(octet, BufferSource)
+PASS Unscopable handled correctly for transferOut(octet, BufferSource) on USBDevice
+PASS USBDevice interface: operation isochronousTransferIn(octet, [object Object])
+PASS Unscopable handled correctly for isochronousTransferIn(octet, [object Object]) on USBDevice
+PASS USBDevice interface: operation isochronousTransferOut(octet, BufferSource, [object Object])
+PASS Unscopable handled correctly for isochronousTransferOut(octet, BufferSource, [object Object]) on USBDevice
+PASS USBDevice interface: operation reset()
+PASS Unscopable handled correctly for reset() on USBDevice
+PASS USBDevice must be primary interface of usbDevice
+PASS Stringification of usbDevice
+PASS USBDevice interface: usbDevice must inherit property "usbVersionMajor" with the proper type
+PASS USBDevice interface: usbDevice must inherit property "usbVersionMinor" with the proper type
+PASS USBDevice interface: usbDevice must inherit property "usbVersionSubminor" with the proper type
+PASS USBDevice interface: usbDevice must inherit property "deviceClass" with the proper type
+PASS USBDevice interface: usbDevice must inherit property "deviceSubclass" with the proper type
+PASS USBDevice interface: usbDevice must inherit property "deviceProtocol" with the proper type
+PASS USBDevice interface: usbDevice must inherit property "vendorId" with the proper type
+PASS USBDevice interface: usbDevice must inherit property "productId" with the proper type
+PASS USBDevice interface: usbDevice must inherit property "deviceVersionMajor" with the proper type
+PASS USBDevice interface: usbDevice must inherit property "deviceVersionMinor" with the proper type
+PASS USBDevice interface: usbDevice must inherit property "deviceVersionSubminor" with the proper type
+PASS USBDevice interface: usbDevice must inherit property "manufacturerName" with the proper type
+PASS USBDevice interface: usbDevice must inherit property "productName" with the proper type
+PASS USBDevice interface: usbDevice must inherit property "serialNumber" with the proper type
+PASS USBDevice interface: usbDevice must inherit property "configuration" with the proper type
+PASS USBDevice interface: usbDevice must inherit property "configurations" with the proper type
+PASS USBDevice interface: usbDevice must inherit property "opened" with the proper type
+PASS USBDevice interface: usbDevice must inherit property "open()" with the proper type
+PASS USBDevice interface: usbDevice must inherit property "close()" with the proper type
+PASS USBDevice interface: usbDevice must inherit property "selectConfiguration(octet)" with the proper type
+PASS USBDevice interface: calling selectConfiguration(octet) on usbDevice with too few arguments must throw TypeError
+PASS USBDevice interface: usbDevice must inherit property "claimInterface(octet)" with the proper type
+PASS USBDevice interface: calling claimInterface(octet) on usbDevice with too few arguments must throw TypeError
+PASS USBDevice interface: usbDevice must inherit property "releaseInterface(octet)" with the proper type
+PASS USBDevice interface: calling releaseInterface(octet) on usbDevice with too few arguments must throw TypeError
+PASS USBDevice interface: usbDevice must inherit property "selectAlternateInterface(octet, octet)" with the proper type
+PASS USBDevice interface: calling selectAlternateInterface(octet, octet) on usbDevice with too few arguments must throw TypeError
+PASS USBDevice interface: usbDevice must inherit property "controlTransferIn(USBControlTransferParameters, unsigned short)" with the proper type
+PASS USBDevice interface: calling controlTransferIn(USBControlTransferParameters, unsigned short) on usbDevice with too few arguments must throw TypeError
+PASS USBDevice interface: usbDevice must inherit property "controlTransferOut(USBControlTransferParameters, BufferSource)" with the proper type
+PASS USBDevice interface: calling controlTransferOut(USBControlTransferParameters, BufferSource) on usbDevice with too few arguments must throw TypeError
+PASS USBDevice interface: usbDevice must inherit property "clearHalt(USBDirection, octet)" with the proper type
+PASS USBDevice interface: calling clearHalt(USBDirection, octet) on usbDevice with too few arguments must throw TypeError
+PASS USBDevice interface: usbDevice must inherit property "transferIn(octet, unsigned long)" with the proper type
+PASS USBDevice interface: calling transferIn(octet, unsigned long) on usbDevice with too few arguments must throw TypeError
+PASS USBDevice interface: usbDevice must inherit property "transferOut(octet, BufferSource)" with the proper type
+PASS USBDevice interface: calling transferOut(octet, BufferSource) on usbDevice with too few arguments must throw TypeError
+PASS USBDevice interface: usbDevice must inherit property "isochronousTransferIn(octet, [object Object])" with the proper type
+PASS USBDevice interface: calling isochronousTransferIn(octet, [object Object]) on usbDevice with too few arguments must throw TypeError
+PASS USBDevice interface: usbDevice must inherit property "isochronousTransferOut(octet, BufferSource, [object Object])" with the proper type
+PASS USBDevice interface: calling isochronousTransferOut(octet, BufferSource, [object Object]) on usbDevice with too few arguments must throw TypeError
+PASS USBDevice interface: usbDevice must inherit property "reset()" with the proper type
+PASS USBInTransferResult interface: existence and properties of interface object
+PASS USBInTransferResult interface object length
+PASS USBInTransferResult interface object name
+PASS USBInTransferResult interface: existence and properties of interface prototype object
+PASS USBInTransferResult interface: existence and properties of interface prototype object's "constructor" property
+PASS USBInTransferResult interface: existence and properties of interface prototype object's @@unscopables property
+PASS USBInTransferResult interface: attribute data
+PASS Unscopable handled correctly for data property on USBInTransferResult
+PASS USBInTransferResult interface: attribute status
+PASS Unscopable handled correctly for status property on USBInTransferResult
+PASS USBInTransferResult must be primary interface of new USBInTransferResult("ok")
+PASS Stringification of new USBInTransferResult("ok")
+PASS USBInTransferResult interface: new USBInTransferResult("ok") must inherit property "data" with the proper type
+PASS USBInTransferResult interface: new USBInTransferResult("ok") must inherit property "status" with the proper type
+PASS USBOutTransferResult interface: existence and properties of interface object
+PASS USBOutTransferResult interface object length
+PASS USBOutTransferResult interface object name
+PASS USBOutTransferResult interface: existence and properties of interface prototype object
+PASS USBOutTransferResult interface: existence and properties of interface prototype object's "constructor" property
+PASS USBOutTransferResult interface: existence and properties of interface prototype object's @@unscopables property
+PASS USBOutTransferResult interface: attribute bytesWritten
+PASS Unscopable handled correctly for bytesWritten property on USBOutTransferResult
+PASS USBOutTransferResult interface: attribute status
+PASS Unscopable handled correctly for status property on USBOutTransferResult
+PASS USBOutTransferResult must be primary interface of new USBOutTransferResult("ok")
+PASS Stringification of new USBOutTransferResult("ok")
+PASS USBOutTransferResult interface: new USBOutTransferResult("ok") must inherit property "bytesWritten" with the proper type
+PASS USBOutTransferResult interface: new USBOutTransferResult("ok") must inherit property "status" with the proper type
+PASS USBIsochronousInTransferPacket interface: existence and properties of interface object
+PASS USBIsochronousInTransferPacket interface object length
+PASS USBIsochronousInTransferPacket interface object name
+PASS USBIsochronousInTransferPacket interface: existence and properties of interface prototype object
+PASS USBIsochronousInTransferPacket interface: existence and properties of interface prototype object's "constructor" property
+PASS USBIsochronousInTransferPacket interface: existence and properties of interface prototype object's @@unscopables property
+PASS USBIsochronousInTransferPacket interface: attribute data
+PASS Unscopable handled correctly for data property on USBIsochronousInTransferPacket
+PASS USBIsochronousInTransferPacket interface: attribute status
+PASS Unscopable handled correctly for status property on USBIsochronousInTransferPacket
+PASS USBIsochronousInTransferPacket must be primary interface of new USBIsochronousInTransferPacket("ok")
+PASS Stringification of new USBIsochronousInTransferPacket("ok")
+PASS USBIsochronousInTransferPacket interface: new USBIsochronousInTransferPacket("ok") must inherit property "data" with the proper type
+PASS USBIsochronousInTransferPacket interface: new USBIsochronousInTransferPacket("ok") must inherit property "status" with the proper type
+PASS USBIsochronousInTransferResult interface: existence and properties of interface object
+PASS USBIsochronousInTransferResult interface object length
+PASS USBIsochronousInTransferResult interface object name
+PASS USBIsochronousInTransferResult interface: existence and properties of interface prototype object
+PASS USBIsochronousInTransferResult interface: existence and properties of interface prototype object's "constructor" property
+PASS USBIsochronousInTransferResult interface: existence and properties of interface prototype object's @@unscopables property
+PASS USBIsochronousInTransferResult interface: attribute data
+PASS Unscopable handled correctly for data property on USBIsochronousInTransferResult
+PASS USBIsochronousInTransferResult interface: attribute packets
+PASS Unscopable handled correctly for packets property on USBIsochronousInTransferResult
+PASS USBIsochronousInTransferResult must be primary interface of new USBIsochronousInTransferResult([])
+PASS Stringification of new USBIsochronousInTransferResult([])
+PASS USBIsochronousInTransferResult interface: new USBIsochronousInTransferResult([]) must inherit property "data" with the proper type
+PASS USBIsochronousInTransferResult interface: new USBIsochronousInTransferResult([]) must inherit property "packets" with the proper type
+PASS USBIsochronousOutTransferPacket interface: existence and properties of interface object
+PASS USBIsochronousOutTransferPacket interface object length
+PASS USBIsochronousOutTransferPacket interface object name
+PASS USBIsochronousOutTransferPacket interface: existence and properties of interface prototype object
+PASS USBIsochronousOutTransferPacket interface: existence and properties of interface prototype object's "constructor" property
+PASS USBIsochronousOutTransferPacket interface: existence and properties of interface prototype object's @@unscopables property
+PASS USBIsochronousOutTransferPacket interface: attribute bytesWritten
+PASS Unscopable handled correctly for bytesWritten property on USBIsochronousOutTransferPacket
+PASS USBIsochronousOutTransferPacket interface: attribute status
+PASS Unscopable handled correctly for status property on USBIsochronousOutTransferPacket
+PASS USBIsochronousOutTransferPacket must be primary interface of new USBIsochronousOutTransferPacket("ok")
+PASS Stringification of new USBIsochronousOutTransferPacket("ok")
+PASS USBIsochronousOutTransferPacket interface: new USBIsochronousOutTransferPacket("ok") must inherit property "bytesWritten" with the proper type
+PASS USBIsochronousOutTransferPacket interface: new USBIsochronousOutTransferPacket("ok") must inherit property "status" with the proper type
+PASS USBIsochronousOutTransferResult interface: existence and properties of interface object
+PASS USBIsochronousOutTransferResult interface object length
+PASS USBIsochronousOutTransferResult interface object name
+PASS USBIsochronousOutTransferResult interface: existence and properties of interface prototype object
+PASS USBIsochronousOutTransferResult interface: existence and properties of interface prototype object's "constructor" property
+PASS USBIsochronousOutTransferResult interface: existence and properties of interface prototype object's @@unscopables property
+PASS USBIsochronousOutTransferResult interface: attribute packets
+PASS Unscopable handled correctly for packets property on USBIsochronousOutTransferResult
+PASS USBIsochronousOutTransferResult must be primary interface of new USBIsochronousOutTransferResult([])
+PASS Stringification of new USBIsochronousOutTransferResult([])
+PASS USBIsochronousOutTransferResult interface: new USBIsochronousOutTransferResult([]) must inherit property "packets" with the proper type
+PASS USBConfiguration interface: existence and properties of interface object
+PASS USBConfiguration interface object length
+PASS USBConfiguration interface object name
+PASS USBConfiguration interface: existence and properties of interface prototype object
+PASS USBConfiguration interface: existence and properties of interface prototype object's "constructor" property
+PASS USBConfiguration interface: existence and properties of interface prototype object's @@unscopables property
+PASS USBConfiguration interface: attribute configurationValue
+PASS Unscopable handled correctly for configurationValue property on USBConfiguration
+PASS USBConfiguration interface: attribute configurationName
+PASS Unscopable handled correctly for configurationName property on USBConfiguration
+PASS USBConfiguration interface: attribute interfaces
+PASS Unscopable handled correctly for interfaces property on USBConfiguration
+PASS USBConfiguration must be primary interface of usbConfiguration
+PASS Stringification of usbConfiguration
+PASS USBConfiguration interface: usbConfiguration must inherit property "configurationValue" with the proper type
+PASS USBConfiguration interface: usbConfiguration must inherit property "configurationName" with the proper type
+PASS USBConfiguration interface: usbConfiguration must inherit property "interfaces" with the proper type
+PASS USBInterface interface: existence and properties of interface object
+PASS USBInterface interface object length
+PASS USBInterface interface object name
+PASS USBInterface interface: existence and properties of interface prototype object
+PASS USBInterface interface: existence and properties of interface prototype object's "constructor" property
+PASS USBInterface interface: existence and properties of interface prototype object's @@unscopables property
+PASS USBInterface interface: attribute interfaceNumber
+PASS Unscopable handled correctly for interfaceNumber property on USBInterface
+PASS USBInterface interface: attribute alternate
+PASS Unscopable handled correctly for alternate property on USBInterface
+PASS USBInterface interface: attribute alternates
+PASS Unscopable handled correctly for alternates property on USBInterface
+PASS USBInterface interface: attribute claimed
+PASS Unscopable handled correctly for claimed property on USBInterface
+PASS USBInterface must be primary interface of usbInterface
+PASS Stringification of usbInterface
+PASS USBInterface interface: usbInterface must inherit property "interfaceNumber" with the proper type
+PASS USBInterface interface: usbInterface must inherit property "alternate" with the proper type
+PASS USBInterface interface: usbInterface must inherit property "alternates" with the proper type
+PASS USBInterface interface: usbInterface must inherit property "claimed" with the proper type
+PASS USBAlternateInterface interface: existence and properties of interface object
+PASS USBAlternateInterface interface object length
+PASS USBAlternateInterface interface object name
+PASS USBAlternateInterface interface: existence and properties of interface prototype object
+PASS USBAlternateInterface interface: existence and properties of interface prototype object's "constructor" property
+PASS USBAlternateInterface interface: existence and properties of interface prototype object's @@unscopables property
+PASS USBAlternateInterface interface: attribute alternateSetting
+PASS Unscopable handled correctly for alternateSetting property on USBAlternateInterface
+PASS USBAlternateInterface interface: attribute interfaceClass
+PASS Unscopable handled correctly for interfaceClass property on USBAlternateInterface
+PASS USBAlternateInterface interface: attribute interfaceSubclass
+PASS Unscopable handled correctly for interfaceSubclass property on USBAlternateInterface
+PASS USBAlternateInterface interface: attribute interfaceProtocol
+PASS Unscopable handled correctly for interfaceProtocol property on USBAlternateInterface
+PASS USBAlternateInterface interface: attribute interfaceName
+PASS Unscopable handled correctly for interfaceName property on USBAlternateInterface
+PASS USBAlternateInterface interface: attribute endpoints
+PASS Unscopable handled correctly for endpoints property on USBAlternateInterface
+PASS USBAlternateInterface must be primary interface of usbAlternateInterface
+PASS Stringification of usbAlternateInterface
+PASS USBAlternateInterface interface: usbAlternateInterface must inherit property "alternateSetting" with the proper type
+PASS USBAlternateInterface interface: usbAlternateInterface must inherit property "interfaceClass" with the proper type
+PASS USBAlternateInterface interface: usbAlternateInterface must inherit property "interfaceSubclass" with the proper type
+PASS USBAlternateInterface interface: usbAlternateInterface must inherit property "interfaceProtocol" with the proper type
+PASS USBAlternateInterface interface: usbAlternateInterface must inherit property "interfaceName" with the proper type
+PASS USBAlternateInterface interface: usbAlternateInterface must inherit property "endpoints" with the proper type
+PASS USBEndpoint interface: existence and properties of interface object
+PASS USBEndpoint interface object length
+PASS USBEndpoint interface object name
+PASS USBEndpoint interface: existence and properties of interface prototype object
+PASS USBEndpoint interface: existence and properties of interface prototype object's "constructor" property
+PASS USBEndpoint interface: existence and properties of interface prototype object's @@unscopables property
+PASS USBEndpoint interface: attribute endpointNumber
+PASS Unscopable handled correctly for endpointNumber property on USBEndpoint
+PASS USBEndpoint interface: attribute direction
+PASS Unscopable handled correctly for direction property on USBEndpoint
+PASS USBEndpoint interface: attribute type
+PASS Unscopable handled correctly for type property on USBEndpoint
+PASS USBEndpoint interface: attribute packetSize
+PASS Unscopable handled correctly for packetSize property on USBEndpoint
+PASS USBEndpoint must be primary interface of usbEndpoint
+PASS Stringification of usbEndpoint
+PASS USBEndpoint interface: usbEndpoint must inherit property "endpointNumber" with the proper type
+PASS USBEndpoint interface: usbEndpoint must inherit property "direction" with the proper type
+PASS USBEndpoint interface: usbEndpoint must inherit property "type" with the proper type
+PASS USBEndpoint interface: usbEndpoint must inherit property "packetSize" with the proper type
+PASS EventHandler interface: existence and properties of interface object
+PASS Navigator interface: existence and properties of interface object
+FAIL WorkerNavigator interface: existence and properties of interface object assert_false: expected false got true
+PASS WorkerNavigator interface: navigator must inherit property "usb" with the proper type
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webusb/worker/idlharness.sharedworker.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/webusb/worker/idlharness.sharedworker.https-expected.txt
new file mode 100644
index 0000000..14ea2486
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/webusb/worker/idlharness.sharedworker.https-expected.txt
@@ -0,0 +1,318 @@
+This is a testharness.js-based test.
+PASS WebUSB on Workers IDL test
+PASS Partial interface Navigator: original interface defined
+PASS Partial interface Navigator: valid exposure set
+PASS Partial interface WorkerNavigator: original interface defined
+FAIL Partial interface WorkerNavigator: valid exposure set Partial WorkerNavigator interface is exposed to 'DedicatedWorker', the original interface is not.
+PASS USB interface: existence and properties of interface object
+PASS USB interface object length
+PASS USB interface object name
+PASS USB interface: existence and properties of interface prototype object
+PASS USB interface: existence and properties of interface prototype object's "constructor" property
+PASS USB interface: existence and properties of interface prototype object's @@unscopables property
+PASS USB interface: attribute onconnect
+PASS Unscopable handled correctly for onconnect property on USB
+PASS USB interface: attribute ondisconnect
+PASS Unscopable handled correctly for ondisconnect property on USB
+PASS USB interface: operation getDevices()
+PASS Unscopable handled correctly for getDevices() on USB
+PASS USB interface: member requestDevice
+PASS USB must be primary interface of navigator.usb
+PASS Stringification of navigator.usb
+PASS USB interface: navigator.usb must inherit property "onconnect" with the proper type
+PASS USB interface: navigator.usb must inherit property "ondisconnect" with the proper type
+PASS USB interface: navigator.usb must inherit property "getDevices()" with the proper type
+PASS USB interface: navigator.usb must not have property "requestDevice"
+PASS USBConnectionEvent interface: existence and properties of interface object
+PASS USBConnectionEvent interface object length
+PASS USBConnectionEvent interface object name
+PASS USBConnectionEvent interface: existence and properties of interface prototype object
+PASS USBConnectionEvent interface: existence and properties of interface prototype object's "constructor" property
+PASS USBConnectionEvent interface: existence and properties of interface prototype object's @@unscopables property
+PASS USBConnectionEvent interface: attribute device
+PASS Unscopable handled correctly for device property on USBConnectionEvent
+PASS USBConnectionEvent must be primary interface of usbConnectionEvent
+PASS Stringification of usbConnectionEvent
+PASS USBConnectionEvent interface: usbConnectionEvent must inherit property "device" with the proper type
+PASS USBDevice interface: existence and properties of interface object
+PASS USBDevice interface object length
+PASS USBDevice interface object name
+PASS USBDevice interface: existence and properties of interface prototype object
+PASS USBDevice interface: existence and properties of interface prototype object's "constructor" property
+PASS USBDevice interface: existence and properties of interface prototype object's @@unscopables property
+PASS USBDevice interface: attribute usbVersionMajor
+PASS Unscopable handled correctly for usbVersionMajor property on USBDevice
+PASS USBDevice interface: attribute usbVersionMinor
+PASS Unscopable handled correctly for usbVersionMinor property on USBDevice
+PASS USBDevice interface: attribute usbVersionSubminor
+PASS Unscopable handled correctly for usbVersionSubminor property on USBDevice
+PASS USBDevice interface: attribute deviceClass
+PASS Unscopable handled correctly for deviceClass property on USBDevice
+PASS USBDevice interface: attribute deviceSubclass
+PASS Unscopable handled correctly for deviceSubclass property on USBDevice
+PASS USBDevice interface: attribute deviceProtocol
+PASS Unscopable handled correctly for deviceProtocol property on USBDevice
+PASS USBDevice interface: attribute vendorId
+PASS Unscopable handled correctly for vendorId property on USBDevice
+PASS USBDevice interface: attribute productId
+PASS Unscopable handled correctly for productId property on USBDevice
+PASS USBDevice interface: attribute deviceVersionMajor
+PASS Unscopable handled correctly for deviceVersionMajor property on USBDevice
+PASS USBDevice interface: attribute deviceVersionMinor
+PASS Unscopable handled correctly for deviceVersionMinor property on USBDevice
+PASS USBDevice interface: attribute deviceVersionSubminor
+PASS Unscopable handled correctly for deviceVersionSubminor property on USBDevice
+PASS USBDevice interface: attribute manufacturerName
+PASS Unscopable handled correctly for manufacturerName property on USBDevice
+PASS USBDevice interface: attribute productName
+PASS Unscopable handled correctly for productName property on USBDevice
+PASS USBDevice interface: attribute serialNumber
+PASS Unscopable handled correctly for serialNumber property on USBDevice
+PASS USBDevice interface: attribute configuration
+PASS Unscopable handled correctly for configuration property on USBDevice
+PASS USBDevice interface: attribute configurations
+PASS Unscopable handled correctly for configurations property on USBDevice
+PASS USBDevice interface: attribute opened
+PASS Unscopable handled correctly for opened property on USBDevice
+PASS USBDevice interface: operation open()
+PASS Unscopable handled correctly for open() on USBDevice
+PASS USBDevice interface: operation close()
+PASS Unscopable handled correctly for close() on USBDevice
+PASS USBDevice interface: operation selectConfiguration(octet)
+PASS Unscopable handled correctly for selectConfiguration(octet) on USBDevice
+PASS USBDevice interface: operation claimInterface(octet)
+PASS Unscopable handled correctly for claimInterface(octet) on USBDevice
+PASS USBDevice interface: operation releaseInterface(octet)
+PASS Unscopable handled correctly for releaseInterface(octet) on USBDevice
+PASS USBDevice interface: operation selectAlternateInterface(octet, octet)
+PASS Unscopable handled correctly for selectAlternateInterface(octet, octet) on USBDevice
+PASS USBDevice interface: operation controlTransferIn(USBControlTransferParameters, unsigned short)
+PASS Unscopable handled correctly for controlTransferIn(USBControlTransferParameters, unsigned short) on USBDevice
+PASS USBDevice interface: operation controlTransferOut(USBControlTransferParameters, BufferSource)
+PASS Unscopable handled correctly for controlTransferOut(USBControlTransferParameters, BufferSource) on USBDevice
+PASS USBDevice interface: operation clearHalt(USBDirection, octet)
+PASS Unscopable handled correctly for clearHalt(USBDirection, octet) on USBDevice
+PASS USBDevice interface: operation transferIn(octet, unsigned long)
+PASS Unscopable handled correctly for transferIn(octet, unsigned long) on USBDevice
+PASS USBDevice interface: operation transferOut(octet, BufferSource)
+PASS Unscopable handled correctly for transferOut(octet, BufferSource) on USBDevice
+PASS USBDevice interface: operation isochronousTransferIn(octet, [object Object])
+PASS Unscopable handled correctly for isochronousTransferIn(octet, [object Object]) on USBDevice
+PASS USBDevice interface: operation isochronousTransferOut(octet, BufferSource, [object Object])
+PASS Unscopable handled correctly for isochronousTransferOut(octet, BufferSource, [object Object]) on USBDevice
+PASS USBDevice interface: operation reset()
+PASS Unscopable handled correctly for reset() on USBDevice
+PASS USBDevice must be primary interface of usbDevice
+PASS Stringification of usbDevice
+PASS USBDevice interface: usbDevice must inherit property "usbVersionMajor" with the proper type
+PASS USBDevice interface: usbDevice must inherit property "usbVersionMinor" with the proper type
+PASS USBDevice interface: usbDevice must inherit property "usbVersionSubminor" with the proper type
+PASS USBDevice interface: usbDevice must inherit property "deviceClass" with the proper type
+PASS USBDevice interface: usbDevice must inherit property "deviceSubclass" with the proper type
+PASS USBDevice interface: usbDevice must inherit property "deviceProtocol" with the proper type
+PASS USBDevice interface: usbDevice must inherit property "vendorId" with the proper type
+PASS USBDevice interface: usbDevice must inherit property "productId" with the proper type
+PASS USBDevice interface: usbDevice must inherit property "deviceVersionMajor" with the proper type
+PASS USBDevice interface: usbDevice must inherit property "deviceVersionMinor" with the proper type
+PASS USBDevice interface: usbDevice must inherit property "deviceVersionSubminor" with the proper type
+PASS USBDevice interface: usbDevice must inherit property "manufacturerName" with the proper type
+PASS USBDevice interface: usbDevice must inherit property "productName" with the proper type
+PASS USBDevice interface: usbDevice must inherit property "serialNumber" with the proper type
+PASS USBDevice interface: usbDevice must inherit property "configuration" with the proper type
+PASS USBDevice interface: usbDevice must inherit property "configurations" with the proper type
+PASS USBDevice interface: usbDevice must inherit property "opened" with the proper type
+PASS USBDevice interface: usbDevice must inherit property "open()" with the proper type
+PASS USBDevice interface: usbDevice must inherit property "close()" with the proper type
+PASS USBDevice interface: usbDevice must inherit property "selectConfiguration(octet)" with the proper type
+PASS USBDevice interface: calling selectConfiguration(octet) on usbDevice with too few arguments must throw TypeError
+PASS USBDevice interface: usbDevice must inherit property "claimInterface(octet)" with the proper type
+PASS USBDevice interface: calling claimInterface(octet) on usbDevice with too few arguments must throw TypeError
+PASS USBDevice interface: usbDevice must inherit property "releaseInterface(octet)" with the proper type
+PASS USBDevice interface: calling releaseInterface(octet) on usbDevice with too few arguments must throw TypeError
+PASS USBDevice interface: usbDevice must inherit property "selectAlternateInterface(octet, octet)" with the proper type
+PASS USBDevice interface: calling selectAlternateInterface(octet, octet) on usbDevice with too few arguments must throw TypeError
+PASS USBDevice interface: usbDevice must inherit property "controlTransferIn(USBControlTransferParameters, unsigned short)" with the proper type
+PASS USBDevice interface: calling controlTransferIn(USBControlTransferParameters, unsigned short) on usbDevice with too few arguments must throw TypeError
+PASS USBDevice interface: usbDevice must inherit property "controlTransferOut(USBControlTransferParameters, BufferSource)" with the proper type
+PASS USBDevice interface: calling controlTransferOut(USBControlTransferParameters, BufferSource) on usbDevice with too few arguments must throw TypeError
+PASS USBDevice interface: usbDevice must inherit property "clearHalt(USBDirection, octet)" with the proper type
+PASS USBDevice interface: calling clearHalt(USBDirection, octet) on usbDevice with too few arguments must throw TypeError
+PASS USBDevice interface: usbDevice must inherit property "transferIn(octet, unsigned long)" with the proper type
+PASS USBDevice interface: calling transferIn(octet, unsigned long) on usbDevice with too few arguments must throw TypeError
+PASS USBDevice interface: usbDevice must inherit property "transferOut(octet, BufferSource)" with the proper type
+PASS USBDevice interface: calling transferOut(octet, BufferSource) on usbDevice with too few arguments must throw TypeError
+PASS USBDevice interface: usbDevice must inherit property "isochronousTransferIn(octet, [object Object])" with the proper type
+PASS USBDevice interface: calling isochronousTransferIn(octet, [object Object]) on usbDevice with too few arguments must throw TypeError
+PASS USBDevice interface: usbDevice must inherit property "isochronousTransferOut(octet, BufferSource, [object Object])" with the proper type
+PASS USBDevice interface: calling isochronousTransferOut(octet, BufferSource, [object Object]) on usbDevice with too few arguments must throw TypeError
+PASS USBDevice interface: usbDevice must inherit property "reset()" with the proper type
+PASS USBInTransferResult interface: existence and properties of interface object
+PASS USBInTransferResult interface object length
+PASS USBInTransferResult interface object name
+PASS USBInTransferResult interface: existence and properties of interface prototype object
+PASS USBInTransferResult interface: existence and properties of interface prototype object's "constructor" property
+PASS USBInTransferResult interface: existence and properties of interface prototype object's @@unscopables property
+PASS USBInTransferResult interface: attribute data
+PASS Unscopable handled correctly for data property on USBInTransferResult
+PASS USBInTransferResult interface: attribute status
+PASS Unscopable handled correctly for status property on USBInTransferResult
+PASS USBInTransferResult must be primary interface of new USBInTransferResult("ok")
+PASS Stringification of new USBInTransferResult("ok")
+PASS USBInTransferResult interface: new USBInTransferResult("ok") must inherit property "data" with the proper type
+PASS USBInTransferResult interface: new USBInTransferResult("ok") must inherit property "status" with the proper type
+PASS USBOutTransferResult interface: existence and properties of interface object
+PASS USBOutTransferResult interface object length
+PASS USBOutTransferResult interface object name
+PASS USBOutTransferResult interface: existence and properties of interface prototype object
+PASS USBOutTransferResult interface: existence and properties of interface prototype object's "constructor" property
+PASS USBOutTransferResult interface: existence and properties of interface prototype object's @@unscopables property
+PASS USBOutTransferResult interface: attribute bytesWritten
+PASS Unscopable handled correctly for bytesWritten property on USBOutTransferResult
+PASS USBOutTransferResult interface: attribute status
+PASS Unscopable handled correctly for status property on USBOutTransferResult
+PASS USBOutTransferResult must be primary interface of new USBOutTransferResult("ok")
+PASS Stringification of new USBOutTransferResult("ok")
+PASS USBOutTransferResult interface: new USBOutTransferResult("ok") must inherit property "bytesWritten" with the proper type
+PASS USBOutTransferResult interface: new USBOutTransferResult("ok") must inherit property "status" with the proper type
+PASS USBIsochronousInTransferPacket interface: existence and properties of interface object
+PASS USBIsochronousInTransferPacket interface object length
+PASS USBIsochronousInTransferPacket interface object name
+PASS USBIsochronousInTransferPacket interface: existence and properties of interface prototype object
+PASS USBIsochronousInTransferPacket interface: existence and properties of interface prototype object's "constructor" property
+PASS USBIsochronousInTransferPacket interface: existence and properties of interface prototype object's @@unscopables property
+PASS USBIsochronousInTransferPacket interface: attribute data
+PASS Unscopable handled correctly for data property on USBIsochronousInTransferPacket
+PASS USBIsochronousInTransferPacket interface: attribute status
+PASS Unscopable handled correctly for status property on USBIsochronousInTransferPacket
+PASS USBIsochronousInTransferPacket must be primary interface of new USBIsochronousInTransferPacket("ok")
+PASS Stringification of new USBIsochronousInTransferPacket("ok")
+PASS USBIsochronousInTransferPacket interface: new USBIsochronousInTransferPacket("ok") must inherit property "data" with the proper type
+PASS USBIsochronousInTransferPacket interface: new USBIsochronousInTransferPacket("ok") must inherit property "status" with the proper type
+PASS USBIsochronousInTransferResult interface: existence and properties of interface object
+PASS USBIsochronousInTransferResult interface object length
+PASS USBIsochronousInTransferResult interface object name
+PASS USBIsochronousInTransferResult interface: existence and properties of interface prototype object
+PASS USBIsochronousInTransferResult interface: existence and properties of interface prototype object's "constructor" property
+PASS USBIsochronousInTransferResult interface: existence and properties of interface prototype object's @@unscopables property
+PASS USBIsochronousInTransferResult interface: attribute data
+PASS Unscopable handled correctly for data property on USBIsochronousInTransferResult
+PASS USBIsochronousInTransferResult interface: attribute packets
+PASS Unscopable handled correctly for packets property on USBIsochronousInTransferResult
+PASS USBIsochronousInTransferResult must be primary interface of new USBIsochronousInTransferResult([])
+PASS Stringification of new USBIsochronousInTransferResult([])
+PASS USBIsochronousInTransferResult interface: new USBIsochronousInTransferResult([]) must inherit property "data" with the proper type
+PASS USBIsochronousInTransferResult interface: new USBIsochronousInTransferResult([]) must inherit property "packets" with the proper type
+PASS USBIsochronousOutTransferPacket interface: existence and properties of interface object
+PASS USBIsochronousOutTransferPacket interface object length
+PASS USBIsochronousOutTransferPacket interface object name
+PASS USBIsochronousOutTransferPacket interface: existence and properties of interface prototype object
+PASS USBIsochronousOutTransferPacket interface: existence and properties of interface prototype object's "constructor" property
+PASS USBIsochronousOutTransferPacket interface: existence and properties of interface prototype object's @@unscopables property
+PASS USBIsochronousOutTransferPacket interface: attribute bytesWritten
+PASS Unscopable handled correctly for bytesWritten property on USBIsochronousOutTransferPacket
+PASS USBIsochronousOutTransferPacket interface: attribute status
+PASS Unscopable handled correctly for status property on USBIsochronousOutTransferPacket
+PASS USBIsochronousOutTransferPacket must be primary interface of new USBIsochronousOutTransferPacket("ok")
+PASS Stringification of new USBIsochronousOutTransferPacket("ok")
+PASS USBIsochronousOutTransferPacket interface: new USBIsochronousOutTransferPacket("ok") must inherit property "bytesWritten" with the proper type
+PASS USBIsochronousOutTransferPacket interface: new USBIsochronousOutTransferPacket("ok") must inherit property "status" with the proper type
+PASS USBIsochronousOutTransferResult interface: existence and properties of interface object
+PASS USBIsochronousOutTransferResult interface object length
+PASS USBIsochronousOutTransferResult interface object name
+PASS USBIsochronousOutTransferResult interface: existence and properties of interface prototype object
+PASS USBIsochronousOutTransferResult interface: existence and properties of interface prototype object's "constructor" property
+PASS USBIsochronousOutTransferResult interface: existence and properties of interface prototype object's @@unscopables property
+PASS USBIsochronousOutTransferResult interface: attribute packets
+PASS Unscopable handled correctly for packets property on USBIsochronousOutTransferResult
+PASS USBIsochronousOutTransferResult must be primary interface of new USBIsochronousOutTransferResult([])
+PASS Stringification of new USBIsochronousOutTransferResult([])
+PASS USBIsochronousOutTransferResult interface: new USBIsochronousOutTransferResult([]) must inherit property "packets" with the proper type
+PASS USBConfiguration interface: existence and properties of interface object
+PASS USBConfiguration interface object length
+PASS USBConfiguration interface object name
+PASS USBConfiguration interface: existence and properties of interface prototype object
+PASS USBConfiguration interface: existence and properties of interface prototype object's "constructor" property
+PASS USBConfiguration interface: existence and properties of interface prototype object's @@unscopables property
+PASS USBConfiguration interface: attribute configurationValue
+PASS Unscopable handled correctly for configurationValue property on USBConfiguration
+PASS USBConfiguration interface: attribute configurationName
+PASS Unscopable handled correctly for configurationName property on USBConfiguration
+PASS USBConfiguration interface: attribute interfaces
+PASS Unscopable handled correctly for interfaces property on USBConfiguration
+PASS USBConfiguration must be primary interface of usbConfiguration
+PASS Stringification of usbConfiguration
+PASS USBConfiguration interface: usbConfiguration must inherit property "configurationValue" with the proper type
+PASS USBConfiguration interface: usbConfiguration must inherit property "configurationName" with the proper type
+PASS USBConfiguration interface: usbConfiguration must inherit property "interfaces" with the proper type
+PASS USBInterface interface: existence and properties of interface object
+PASS USBInterface interface object length
+PASS USBInterface interface object name
+PASS USBInterface interface: existence and properties of interface prototype object
+PASS USBInterface interface: existence and properties of interface prototype object's "constructor" property
+PASS USBInterface interface: existence and properties of interface prototype object's @@unscopables property
+PASS USBInterface interface: attribute interfaceNumber
+PASS Unscopable handled correctly for interfaceNumber property on USBInterface
+PASS USBInterface interface: attribute alternate
+PASS Unscopable handled correctly for alternate property on USBInterface
+PASS USBInterface interface: attribute alternates
+PASS Unscopable handled correctly for alternates property on USBInterface
+PASS USBInterface interface: attribute claimed
+PASS Unscopable handled correctly for claimed property on USBInterface
+PASS USBInterface must be primary interface of usbInterface
+PASS Stringification of usbInterface
+PASS USBInterface interface: usbInterface must inherit property "interfaceNumber" with the proper type
+PASS USBInterface interface: usbInterface must inherit property "alternate" with the proper type
+PASS USBInterface interface: usbInterface must inherit property "alternates" with the proper type
+PASS USBInterface interface: usbInterface must inherit property "claimed" with the proper type
+PASS USBAlternateInterface interface: existence and properties of interface object
+PASS USBAlternateInterface interface object length
+PASS USBAlternateInterface interface object name
+PASS USBAlternateInterface interface: existence and properties of interface prototype object
+PASS USBAlternateInterface interface: existence and properties of interface prototype object's "constructor" property
+PASS USBAlternateInterface interface: existence and properties of interface prototype object's @@unscopables property
+PASS USBAlternateInterface interface: attribute alternateSetting
+PASS Unscopable handled correctly for alternateSetting property on USBAlternateInterface
+PASS USBAlternateInterface interface: attribute interfaceClass
+PASS Unscopable handled correctly for interfaceClass property on USBAlternateInterface
+PASS USBAlternateInterface interface: attribute interfaceSubclass
+PASS Unscopable handled correctly for interfaceSubclass property on USBAlternateInterface
+PASS USBAlternateInterface interface: attribute interfaceProtocol
+PASS Unscopable handled correctly for interfaceProtocol property on USBAlternateInterface
+PASS USBAlternateInterface interface: attribute interfaceName
+PASS Unscopable handled correctly for interfaceName property on USBAlternateInterface
+PASS USBAlternateInterface interface: attribute endpoints
+PASS Unscopable handled correctly for endpoints property on USBAlternateInterface
+PASS USBAlternateInterface must be primary interface of usbAlternateInterface
+PASS Stringification of usbAlternateInterface
+PASS USBAlternateInterface interface: usbAlternateInterface must inherit property "alternateSetting" with the proper type
+PASS USBAlternateInterface interface: usbAlternateInterface must inherit property "interfaceClass" with the proper type
+PASS USBAlternateInterface interface: usbAlternateInterface must inherit property "interfaceSubclass" with the proper type
+PASS USBAlternateInterface interface: usbAlternateInterface must inherit property "interfaceProtocol" with the proper type
+PASS USBAlternateInterface interface: usbAlternateInterface must inherit property "interfaceName" with the proper type
+PASS USBAlternateInterface interface: usbAlternateInterface must inherit property "endpoints" with the proper type
+PASS USBEndpoint interface: existence and properties of interface object
+PASS USBEndpoint interface object length
+PASS USBEndpoint interface object name
+PASS USBEndpoint interface: existence and properties of interface prototype object
+PASS USBEndpoint interface: existence and properties of interface prototype object's "constructor" property
+PASS USBEndpoint interface: existence and properties of interface prototype object's @@unscopables property
+PASS USBEndpoint interface: attribute endpointNumber
+PASS Unscopable handled correctly for endpointNumber property on USBEndpoint
+PASS USBEndpoint interface: attribute direction
+PASS Unscopable handled correctly for direction property on USBEndpoint
+PASS USBEndpoint interface: attribute type
+PASS Unscopable handled correctly for type property on USBEndpoint
+PASS USBEndpoint interface: attribute packetSize
+PASS Unscopable handled correctly for packetSize property on USBEndpoint
+PASS USBEndpoint must be primary interface of usbEndpoint
+PASS Stringification of usbEndpoint
+PASS USBEndpoint interface: usbEndpoint must inherit property "endpointNumber" with the proper type
+PASS USBEndpoint interface: usbEndpoint must inherit property "direction" with the proper type
+PASS USBEndpoint interface: usbEndpoint must inherit property "type" with the proper type
+PASS USBEndpoint interface: usbEndpoint must inherit property "packetSize" with the proper type
+PASS EventHandler interface: existence and properties of interface object
+PASS Navigator interface: existence and properties of interface object
+FAIL WorkerNavigator interface: existence and properties of interface object assert_false: expected false got true
+PASS WorkerNavigator interface: navigator must inherit property "usb" with the proper type
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webvr/idlharness.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/webvr/idlharness.https-expected.txt
index 264fe95..344f8e3 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/webvr/idlharness.https-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/webvr/idlharness.https-expected.txt
@@ -1,4 +1,7 @@
 This is a testharness.js-based test.
+PASS Partial interface Navigator: original interface defined
+PASS Partial interface Window: original interface defined
+PASS Partial interface Gamepad: original interface defined
 FAIL Window interface: attribute onvrdisplayconnect assert_own_property: The global object must have a property "onvrdisplayconnect" expected property "onvrdisplayconnect" missing
 PASS Unscopable handled correctly for onvrdisplayconnect property on Window
 FAIL Window interface: attribute onvrdisplaydisconnect assert_own_property: The global object must have a property "onvrdisplaydisconnect" expected property "onvrdisplaydisconnect" missing
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webxr/interfaces.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/webxr/interfaces.https-expected.txt
index 6856a21..0bacd06 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/webxr/interfaces.https-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/webxr/interfaces.https-expected.txt
@@ -1,4 +1,203 @@
 This is a testharness.js-based test.
-FAIL Test IDL implementation of WebXR API promise_test: Unhandled rejection with value: object "Partial interface Window with no original interface"
+PASS Test IDL implementation of WebXR API
+PASS Partial interface Navigator: original interface defined
+PASS Partial dictionary WebGLContextAttributes: original dictionary defined
+PASS Navigator interface: attribute xr
+PASS Unscopable handled correctly for xr property on Navigator
+PASS Navigator interface: navigator must inherit property "xr" with the proper type
+PASS XR interface: existence and properties of interface object
+PASS XR interface object length
+PASS XR interface object name
+PASS XR interface: existence and properties of interface prototype object
+PASS XR interface: existence and properties of interface prototype object's "constructor" property
+PASS XR interface: existence and properties of interface prototype object's @@unscopables property
+PASS XR interface: operation requestDevice()
+PASS Unscopable handled correctly for requestDevice() on XR
+PASS XR interface: attribute ondevicechange
+PASS Unscopable handled correctly for ondevicechange property on XR
+PASS XRDevice interface: existence and properties of interface object
+PASS XRDevice interface object length
+PASS XRDevice interface object name
+PASS XRDevice interface: existence and properties of interface prototype object
+PASS XRDevice interface: existence and properties of interface prototype object's "constructor" property
+PASS XRDevice interface: existence and properties of interface prototype object's @@unscopables property
+PASS XRDevice interface: operation supportsSession(XRSessionCreationOptions)
+PASS Unscopable handled correctly for supportsSession(XRSessionCreationOptions) on XRDevice
+PASS XRDevice interface: operation requestSession(XRSessionCreationOptions)
+PASS Unscopable handled correctly for requestSession(XRSessionCreationOptions) on XRDevice
+PASS XRSession interface: existence and properties of interface object
+PASS XRSession interface object length
+PASS XRSession interface object name
+PASS XRSession interface: existence and properties of interface prototype object
+PASS XRSession interface: existence and properties of interface prototype object's "constructor" property
+PASS XRSession interface: existence and properties of interface prototype object's @@unscopables property
+PASS XRSession interface: attribute device
+PASS Unscopable handled correctly for device property on XRSession
+PASS XRSession interface: attribute exclusive
+PASS Unscopable handled correctly for exclusive property on XRSession
+PASS XRSession interface: attribute outputContext
+PASS Unscopable handled correctly for outputContext property on XRSession
+PASS XRSession interface: attribute depthNear
+PASS Unscopable handled correctly for depthNear property on XRSession
+PASS XRSession interface: attribute depthFar
+PASS Unscopable handled correctly for depthFar property on XRSession
+PASS XRSession interface: attribute baseLayer
+PASS Unscopable handled correctly for baseLayer property on XRSession
+PASS XRSession interface: operation requestFrameOfReference(XRFrameOfReferenceType, XRFrameOfReferenceOptions)
+PASS Unscopable handled correctly for requestFrameOfReference(XRFrameOfReferenceType, XRFrameOfReferenceOptions) on XRSession
+PASS XRSession interface: operation requestAnimationFrame(XRFrameRequestCallback)
+PASS Unscopable handled correctly for requestAnimationFrame(XRFrameRequestCallback) on XRSession
+PASS XRSession interface: operation cancelAnimationFrame(long)
+PASS Unscopable handled correctly for cancelAnimationFrame(long) on XRSession
+PASS XRSession interface: operation end()
+PASS Unscopable handled correctly for end() on XRSession
+PASS XRSession interface: attribute onblur
+PASS Unscopable handled correctly for onblur property on XRSession
+PASS XRSession interface: attribute onfocus
+PASS Unscopable handled correctly for onfocus property on XRSession
+PASS XRSession interface: attribute onresetpose
+PASS Unscopable handled correctly for onresetpose property on XRSession
+PASS XRSession interface: attribute onend
+PASS Unscopable handled correctly for onend property on XRSession
+PASS XRPresentationFrame interface: existence and properties of interface object
+PASS XRPresentationFrame interface object length
+PASS XRPresentationFrame interface object name
+PASS XRPresentationFrame interface: existence and properties of interface prototype object
+PASS XRPresentationFrame interface: existence and properties of interface prototype object's "constructor" property
+PASS XRPresentationFrame interface: existence and properties of interface prototype object's @@unscopables property
+PASS XRPresentationFrame interface: attribute views
+PASS Unscopable handled correctly for views property on XRPresentationFrame
+PASS XRPresentationFrame interface: operation getDevicePose(XRCoordinateSystem)
+PASS Unscopable handled correctly for getDevicePose(XRCoordinateSystem) on XRPresentationFrame
+FAIL XRCoordinateSystem interface: existence and properties of interface object assert_equals: prototype of XRCoordinateSystem is not EventTarget expected function "function EventTarget() { [native code] }" but got function "function () { [native code] }"
+PASS XRCoordinateSystem interface object length
+PASS XRCoordinateSystem interface object name
+FAIL XRCoordinateSystem interface: existence and properties of interface prototype object assert_equals: prototype of XRCoordinateSystem.prototype is not EventTarget.prototype expected object "[object EventTarget]" but got object "[object Object]"
+PASS XRCoordinateSystem interface: existence and properties of interface prototype object's "constructor" property
+PASS XRCoordinateSystem interface: existence and properties of interface prototype object's @@unscopables property
+PASS XRCoordinateSystem interface: operation getTransformTo(XRCoordinateSystem)
+PASS Unscopable handled correctly for getTransformTo(XRCoordinateSystem) on XRCoordinateSystem
+PASS XRFrameOfReference interface: existence and properties of interface object
+PASS XRFrameOfReference interface object length
+PASS XRFrameOfReference interface object name
+PASS XRFrameOfReference interface: existence and properties of interface prototype object
+PASS XRFrameOfReference interface: existence and properties of interface prototype object's "constructor" property
+PASS XRFrameOfReference interface: existence and properties of interface prototype object's @@unscopables property
+PASS XRFrameOfReference interface: attribute bounds
+PASS Unscopable handled correctly for bounds property on XRFrameOfReference
+PASS XRFrameOfReference interface: attribute emulatedHeight
+PASS Unscopable handled correctly for emulatedHeight property on XRFrameOfReference
+FAIL XRFrameOfReference interface: attribute onboundschange assert_true: The prototype object must have a property "onboundschange" expected true got false
+PASS Unscopable handled correctly for onboundschange property on XRFrameOfReference
+PASS XRStageBounds interface: existence and properties of interface object
+PASS XRStageBounds interface object length
+PASS XRStageBounds interface object name
+PASS XRStageBounds interface: existence and properties of interface prototype object
+PASS XRStageBounds interface: existence and properties of interface prototype object's "constructor" property
+PASS XRStageBounds interface: existence and properties of interface prototype object's @@unscopables property
+PASS XRStageBounds interface: attribute geometry
+PASS Unscopable handled correctly for geometry property on XRStageBounds
+PASS XRStageBoundsPoint interface: existence and properties of interface object
+PASS XRStageBoundsPoint interface object length
+PASS XRStageBoundsPoint interface object name
+PASS XRStageBoundsPoint interface: existence and properties of interface prototype object
+PASS XRStageBoundsPoint interface: existence and properties of interface prototype object's "constructor" property
+PASS XRStageBoundsPoint interface: existence and properties of interface prototype object's @@unscopables property
+PASS XRStageBoundsPoint interface: attribute x
+PASS Unscopable handled correctly for x property on XRStageBoundsPoint
+PASS XRStageBoundsPoint interface: attribute z
+PASS Unscopable handled correctly for z property on XRStageBoundsPoint
+PASS XRView interface: existence and properties of interface object
+PASS XRView interface object length
+PASS XRView interface object name
+PASS XRView interface: existence and properties of interface prototype object
+PASS XRView interface: existence and properties of interface prototype object's "constructor" property
+PASS XRView interface: existence and properties of interface prototype object's @@unscopables property
+PASS XRView interface: attribute eye
+PASS Unscopable handled correctly for eye property on XRView
+PASS XRView interface: attribute projectionMatrix
+PASS Unscopable handled correctly for projectionMatrix property on XRView
+PASS XRViewport interface: existence and properties of interface object
+PASS XRViewport interface object length
+PASS XRViewport interface object name
+PASS XRViewport interface: existence and properties of interface prototype object
+PASS XRViewport interface: existence and properties of interface prototype object's "constructor" property
+PASS XRViewport interface: existence and properties of interface prototype object's @@unscopables property
+PASS XRViewport interface: attribute x
+PASS Unscopable handled correctly for x property on XRViewport
+PASS XRViewport interface: attribute y
+PASS Unscopable handled correctly for y property on XRViewport
+PASS XRViewport interface: attribute width
+PASS Unscopable handled correctly for width property on XRViewport
+PASS XRViewport interface: attribute height
+PASS Unscopable handled correctly for height property on XRViewport
+PASS XRDevicePose interface: existence and properties of interface object
+PASS XRDevicePose interface object length
+PASS XRDevicePose interface object name
+PASS XRDevicePose interface: existence and properties of interface prototype object
+PASS XRDevicePose interface: existence and properties of interface prototype object's "constructor" property
+PASS XRDevicePose interface: existence and properties of interface prototype object's @@unscopables property
+PASS XRDevicePose interface: attribute poseModelMatrix
+PASS Unscopable handled correctly for poseModelMatrix property on XRDevicePose
+PASS XRDevicePose interface: operation getViewMatrix(XRView)
+PASS Unscopable handled correctly for getViewMatrix(XRView) on XRDevicePose
+PASS XRLayer interface: existence and properties of interface object
+PASS XRLayer interface object length
+PASS XRLayer interface object name
+PASS XRLayer interface: existence and properties of interface prototype object
+PASS XRLayer interface: existence and properties of interface prototype object's "constructor" property
+PASS XRLayer interface: existence and properties of interface prototype object's @@unscopables property
+PASS XRWebGLLayer interface: existence and properties of interface object
+PASS XRWebGLLayer interface object length
+PASS XRWebGLLayer interface object name
+PASS XRWebGLLayer interface: existence and properties of interface prototype object
+PASS XRWebGLLayer interface: existence and properties of interface prototype object's "constructor" property
+PASS XRWebGLLayer interface: existence and properties of interface prototype object's @@unscopables property
+PASS XRWebGLLayer interface: attribute context
+PASS Unscopable handled correctly for context property on XRWebGLLayer
+PASS XRWebGLLayer interface: attribute antialias
+PASS Unscopable handled correctly for antialias property on XRWebGLLayer
+PASS XRWebGLLayer interface: attribute depth
+PASS Unscopable handled correctly for depth property on XRWebGLLayer
+PASS XRWebGLLayer interface: attribute stencil
+PASS Unscopable handled correctly for stencil property on XRWebGLLayer
+PASS XRWebGLLayer interface: attribute alpha
+PASS Unscopable handled correctly for alpha property on XRWebGLLayer
+PASS XRWebGLLayer interface: attribute multiview
+PASS Unscopable handled correctly for multiview property on XRWebGLLayer
+PASS XRWebGLLayer interface: attribute framebuffer
+PASS Unscopable handled correctly for framebuffer property on XRWebGLLayer
+PASS XRWebGLLayer interface: attribute framebufferWidth
+PASS Unscopable handled correctly for framebufferWidth property on XRWebGLLayer
+PASS XRWebGLLayer interface: attribute framebufferHeight
+PASS Unscopable handled correctly for framebufferHeight property on XRWebGLLayer
+PASS XRWebGLLayer interface: operation getViewport(XRView)
+PASS Unscopable handled correctly for getViewport(XRView) on XRWebGLLayer
+PASS XRWebGLLayer interface: operation requestViewportScaling(double)
+PASS Unscopable handled correctly for requestViewportScaling(double) on XRWebGLLayer
+PASS XRPresentationContext interface: existence and properties of interface object
+PASS XRPresentationContext interface object length
+PASS XRPresentationContext interface object name
+PASS XRPresentationContext interface: existence and properties of interface prototype object
+PASS XRPresentationContext interface: existence and properties of interface prototype object's "constructor" property
+PASS XRPresentationContext interface: existence and properties of interface prototype object's @@unscopables property
+PASS XRPresentationContext interface: attribute canvas
+PASS Unscopable handled correctly for canvas property on XRPresentationContext
+PASS XRSessionEvent interface: existence and properties of interface object
+PASS XRSessionEvent interface object length
+PASS XRSessionEvent interface object name
+PASS XRSessionEvent interface: existence and properties of interface prototype object
+PASS XRSessionEvent interface: existence and properties of interface prototype object's "constructor" property
+PASS XRSessionEvent interface: existence and properties of interface prototype object's @@unscopables property
+PASS XRSessionEvent interface: attribute session
+PASS Unscopable handled correctly for session property on XRSessionEvent
+FAIL XRCoordinateSystemEvent interface: existence and properties of interface object assert_own_property: self does not have own property "XRCoordinateSystemEvent" expected property "XRCoordinateSystemEvent" missing
+FAIL XRCoordinateSystemEvent interface object length assert_own_property: self does not have own property "XRCoordinateSystemEvent" expected property "XRCoordinateSystemEvent" missing
+FAIL XRCoordinateSystemEvent interface object name assert_own_property: self does not have own property "XRCoordinateSystemEvent" expected property "XRCoordinateSystemEvent" missing
+FAIL XRCoordinateSystemEvent interface: existence and properties of interface prototype object assert_own_property: self does not have own property "XRCoordinateSystemEvent" expected property "XRCoordinateSystemEvent" missing
+FAIL XRCoordinateSystemEvent interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "XRCoordinateSystemEvent" expected property "XRCoordinateSystemEvent" missing
+FAIL XRCoordinateSystemEvent interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "XRCoordinateSystemEvent" expected property "XRCoordinateSystemEvent" missing
+FAIL XRCoordinateSystemEvent interface: attribute coordinateSystem assert_own_property: self does not have own property "XRCoordinateSystemEvent" expected property "XRCoordinateSystemEvent" missing
+PASS Unscopable handled correctly for coordinateSystem property on XRCoordinateSystemEvent
 Harness: the test ran to completion.
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/xhr/interfaces-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/xhr/interfaces-expected.txt
deleted file mode 100644
index a20681d..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/xhr/interfaces-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-FAIL Test driver promise_test: Unhandled rejection with value: object "Partial interface Window with no original interface"
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/20110323/list-style-position-005-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/20110323/list-style-position-005-expected.txt
index bc0c8c4..7e248cf 100644
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/20110323/list-style-position-005-expected.txt
+++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/css2.1/20110323/list-style-position-005-expected.txt
@@ -13,8 +13,9 @@
           text run at (124,0) width 274: " be a green bar stacked on top of a blue bar."
       LayoutNGListItem {DIV} at (0,36) size 784x202 [color=#00FF00] [bgcolor=#00FF00]
         LayoutNGBlockFlow (anonymous) at (0,0) size 784x101
-          LayoutInline (anonymous) at (0,0) size 0x0
-            LayoutText (anonymous) at (0,0) size 0x0
+          LayoutInline (anonymous) at (0,0) size 30x97
+            LayoutText (anonymous) at (-1,2) size 30x97
+              text run at (-1,2) width 30: "\x{2022}"
         LayoutNGBlockFlow {DIV} at (0,101) size 784x101 [bgcolor=#0000FF]
           LayoutText {#text} at (0,2) size 21x97
             text run at (0,2) width 21: " "
diff --git a/third_party/WebKit/LayoutTests/performance/event-timing/event-timing-timingconditions.html b/third_party/WebKit/LayoutTests/performance/event-timing/event-timing-timingconditions.html
new file mode 100644
index 0000000..25e560a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/performance/event-timing/event-timing-timingconditions.html
@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+<html>
+<meta charset=utf-8 />
+<title>Event Timing only times certain types of trusted event.
+</title>
+<button id='button' onclick='mainThreadBusy(500)'
+  onfocus='mainThreadBusy(500)'>Generate a 'click' event</button>
+<script src=../../resources/testharness.js></script>
+<script src=../../resources/testharnessreport.js></script>
+<script src=./resources/event-timing-support.js></script>
+<script>
+  let trustedClickStart = 0;
+  function trustedClickAndBlockMain(id) {
+    return new Promise((resolve, reject) => {
+      trustedClickStart = performance.now();
+      clickOnElement(id);
+      mainThreadBusy(500);
+      resolve();
+    });
+  }
+
+  function untrustedClickAndBlockMain(id) {
+    return new Promise((resolve, reject) => {
+      const target = document.getElementById(id);
+      target.dispatchEvent(new MouseEvent('click'));
+      // Block mainthread in the callback, as dispatchEvent() is an sync call.
+      resolve();
+    });
+  }
+
+  function trustedFocusAndBlockMain(id) {
+    return new Promise((resolve, reject) => {
+      const target = document.getElementById(id);
+      trustedFocusStart = performance.now();
+      target.focus();
+      // Block mainthread in the callback,  as focus() is an sync call.
+      resolve();
+    });
+  }
+
+  async_test(function(t) {
+    new PerformanceObserver(entryList => {
+      const observerCallbackTime = performance.now();
+      const entries = entryList.getEntries();
+      t.step(()=>{
+        assert_equals(entries.length, 1,
+            "Observe more than one entries: " +
+            JSON.stringify(entries) + ".");
+        assert_equals(entries[0].name, 'click',
+            "The observed entry should be a click");
+        assert_greater_than(observerCallbackTime, entries[0].startTime,
+            "assert(untrustedClickStart > entries[0].startTime) failed");
+        assert_greater_than(entries[0].startTime, trustedClickStart,
+            "assert(entries[0].startTime > trustedClickStart) failed");
+      });
+      t.done();
+    }).observe({ entryTypes: ['event'] });
+    // untrusted event of a type event timing cares about
+    untrustedClickAndBlockMain('button').then(wait);
+    // trusted event of a type event timing doesn't cares about
+    trustedFocusAndBlockMain('button').then(wait);
+    // trusted event of a type event timing cares about
+    trustedClickAndBlockMain('button').then(wait);
+  }, "Event Timing only times certain types of trusted event.");
+</script>
+</html>
diff --git a/third_party/WebKit/LayoutTests/virtual/picture-in-picture/external/wpt/feature-policy/README.txt b/third_party/WebKit/LayoutTests/virtual/picture-in-picture/external/wpt/feature-policy/README.txt
index 72016a7..e808a099 100644
--- a/third_party/WebKit/LayoutTests/virtual/picture-in-picture/external/wpt/feature-policy/README.txt
+++ b/third_party/WebKit/LayoutTests/virtual/picture-in-picture/external/wpt/feature-policy/README.txt
@@ -1 +1 @@
-This suite runs Picture-in-Picture tests with PictureInPicture and UseSurfaceLayerForVideo features enabled.
+This suite runs Picture-in-Picture tests with the UseSurfaceLayerForVideo feature enabled.
diff --git a/third_party/WebKit/LayoutTests/virtual/picture-in-picture/external/wpt/picture-in-picture/README.txt b/third_party/WebKit/LayoutTests/virtual/picture-in-picture/external/wpt/picture-in-picture/README.txt
index 72016a7..e808a099 100644
--- a/third_party/WebKit/LayoutTests/virtual/picture-in-picture/external/wpt/picture-in-picture/README.txt
+++ b/third_party/WebKit/LayoutTests/virtual/picture-in-picture/external/wpt/picture-in-picture/README.txt
@@ -1 +1 @@
-This suite runs Picture-in-Picture tests with PictureInPicture and UseSurfaceLayerForVideo features enabled.
+This suite runs Picture-in-Picture tests with the UseSurfaceLayerForVideo feature enabled.
diff --git a/third_party/blink/public/platform/task_type.h b/third_party/blink/public/platform/task_type.h
index c2d5a85..93a7f15 100644
--- a/third_party/blink/public/platform/task_type.h
+++ b/third_party/blink/public/platform/task_type.h
@@ -187,14 +187,6 @@
   kWorkerThreadTaskQueueV8 = 47,
   kWorkerThreadTaskQueueCompositor = 48,
 
-  ///////////////////////////////////////
-  // The following task types are DEPRECATED! Use kInternal* instead.
-  ///////////////////////////////////////
-
-  // Tasks that must not be throttled should be posted here, but the usage
-  // should be very limited.
-  kUnthrottled = 25,
-
   kCount = 49,
 };
 
diff --git a/third_party/blink/public/platform/web_graphics_context_3d_provider.h b/third_party/blink/public/platform/web_graphics_context_3d_provider.h
index ce08386..a6e2e16 100644
--- a/third_party/blink/public/platform/web_graphics_context_3d_provider.h
+++ b/third_party/blink/public/platform/web_graphics_context_3d_provider.h
@@ -67,12 +67,6 @@
   // method cannot return null.
   virtual viz::GLHelper* GetGLHelper() = 0;
 
-  // Returns true if the context is driven by software emulation of GL. In
-  // this scenario, the compositor would not be using GPU.
-  // TODO(danakj): Make this IsSoftwareCompositing() instead, based on the
-  // CompositingModeWatcher.
-  virtual bool IsSoftwareRendering() const = 0;
-
   virtual void SetLostContextCallback(base::RepeatingClosure) = 0;
   virtual void SetErrorMessageCallback(
       base::RepeatingCallback<void(const char* msg, int32_t id)>) = 0;
diff --git a/third_party/blink/renderer/controller/bloated_renderer_detector.cc b/third_party/blink/renderer/controller/bloated_renderer_detector.cc
index 459e076..6544d7f2 100644
--- a/third_party/blink/renderer/controller/bloated_renderer_detector.cc
+++ b/third_party/blink/renderer/controller/bloated_renderer_detector.cc
@@ -5,6 +5,7 @@
 #include "third_party/blink/renderer/controller/bloated_renderer_detector.h"
 
 #include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h"
+#include "third_party/blink/renderer/platform/instrumentation/resource_coordinator/renderer_resource_coordinator.h"
 
 namespace blink {
 
@@ -26,7 +27,7 @@
   if (uptime.InMinutes() < kMinimumUptimeInMinutes) {
     return NearV8HeapLimitHandling::kIgnoredDueToSmallUptime;
   }
-  // TODO(ulan): Send message to the browser.
+  RendererResourceCoordinator::Get().OnRendererIsBloated();
   return NearV8HeapLimitHandling::kForwardedToBrowser;
 }
 
diff --git a/third_party/blink/renderer/core/css/resolver/style_resolver.cc b/third_party/blink/renderer/core/css/resolver/style_resolver.cc
index d20b39f..1ff04d73 100644
--- a/third_party/blink/renderer/core/css/resolver/style_resolver.cc
+++ b/third_party/blink/renderer/core/css/resolver/style_resolver.cc
@@ -86,7 +86,6 @@
 #include "third_party/blink/renderer/core/html/html_iframe_element.h"
 #include "third_party/blink/renderer/core/html/html_slot_element.h"
 #include "third_party/blink/renderer/core/html_names.h"
-#include "third_party/blink/renderer/core/layout/generated_children.h"
 #include "third_party/blink/renderer/core/media_type_names.h"
 #include "third_party/blink/renderer/core/probe/core_probes.h"
 #include "third_party/blink/renderer/core/style/style_inherited_variables.h"
@@ -810,16 +809,6 @@
   if (!parent.CanGeneratePseudoElement(pseudo_id))
     return nullptr;
 
-  LayoutObject* parent_layout_object = parent.GetLayoutObject();
-  if (!parent_layout_object) {
-    DCHECK(parent.HasDisplayContentsStyle());
-    parent_layout_object =
-        LayoutTreeBuilderTraversal::ParentLayoutObject(parent);
-  }
-
-  if (!parent_layout_object)
-    return nullptr;
-
   ComputedStyle* parent_style = parent.MutableComputedStyle();
   DCHECK(parent_style);
 
@@ -830,22 +819,11 @@
     return nullptr;
   }
 
-  if (pseudo_id == kPseudoIdBackdrop && !parent.IsInTopLayer())
-    return nullptr;
-
   if (pseudo_id == kPseudoIdFirstLetter &&
       (parent.IsSVGElement() ||
        !FirstLetterPseudoElement::FirstLetterTextLayoutObject(parent)))
     return nullptr;
 
-  // The backdrop pseudo element generates a new stacking context and its
-  // layout object does not become a child of |parentLayoutObject|. The
-  // exemption is needed so that replaced content also gets a backdrop.
-  if (pseudo_id != kPseudoIdBackdrop &&
-      !CanHaveGeneratedChildren(*parent_layout_object)) {
-    return nullptr;
-  }
-
   if (ComputedStyle* cached_style =
           parent_style->GetCachedPseudoStyle(pseudo_id)) {
     if (!PseudoElementLayoutObjectIsNeeded(cached_style))
@@ -853,8 +831,16 @@
     return PseudoElement::Create(&parent, pseudo_id);
   }
 
+  const ComputedStyle* layout_parent_style = parent_style;
+  if (parent.HasDisplayContentsStyle()) {
+    ContainerNode* layout_parent =
+        LayoutTreeBuilderTraversal::LayoutParent(parent);
+    DCHECK(layout_parent);
+    layout_parent_style = layout_parent->GetComputedStyle();
+  }
+
   StyleResolverState state(GetDocument(), &parent, parent_style,
-                           parent_layout_object->Style());
+                           layout_parent_style);
   if (!PseudoStyleForElementInternal(parent, pseudo_id, parent_style, state))
     return nullptr;
   scoped_refptr<ComputedStyle> style = state.TakeStyle();
diff --git a/third_party/blink/renderer/core/dom/element.cc b/third_party/blink/renderer/core/dom/element.cc
index 33a5a7f..f173056 100644
--- a/third_party/blink/renderer/core/dom/element.cc
+++ b/third_party/blink/renderer/core/dom/element.cc
@@ -3990,13 +3990,22 @@
   return GetDocument().EnsureStyleResolver().PseudoStyleForElement(
       this, request, parent_style, parent_style);
 }
-// For display: contents elements, we still need to generate ::before and
-// ::after, but the rest of the pseudo-elements should only be used for elements
-// with an actual layout object.
+
 bool Element::CanGeneratePseudoElement(PseudoId pseudo_id) const {
-  if (HasDisplayContentsStyle())
-    return pseudo_id == kPseudoIdBefore || pseudo_id == kPseudoIdAfter;
-  return !!GetLayoutObject();
+  if (pseudo_id == kPseudoIdBackdrop && !IsInTopLayer())
+    return false;
+  if (const ComputedStyle* style = GetComputedStyle()) {
+    if (style->Display() == EDisplay::kNone)
+      return false;
+    if (style->Display() == EDisplay::kContents) {
+      // For display: contents elements, we still need to generate ::before and
+      // ::after, but the rest of the pseudo-elements should only be used for
+      // elements with an actual layout object.
+      return pseudo_id == kPseudoIdBefore || pseudo_id == kPseudoIdAfter;
+    }
+    return true;
+  }
+  return false;
 }
 
 bool Element::MayTriggerVirtualKeyboard() const {
diff --git a/third_party/blink/renderer/core/dom/events/event.cc b/third_party/blink/renderer/core/dom/events/event.cc
index db962a8..09546e4 100644
--- a/third_party/blink/renderer/core/dom/events/event.cc
+++ b/third_party/blink/renderer/core/dom/events/event.cc
@@ -216,6 +216,10 @@
   return false;
 }
 
+bool Event::IsCompositionEvent() const {
+  return false;
+}
+
 bool Event::IsClipboardEvent() const {
   return false;
 }
diff --git a/third_party/blink/renderer/core/dom/events/event.h b/third_party/blink/renderer/core/dom/events/event.h
index 98b229a7..5b08c65 100644
--- a/third_party/blink/renderer/core/dom/events/event.h
+++ b/third_party/blink/renderer/core/dom/events/event.h
@@ -179,6 +179,7 @@
   virtual bool IsRelatedEvent() const;
   virtual bool IsPointerEvent() const;
   virtual bool IsInputEvent() const;
+  virtual bool IsCompositionEvent() const;
 
   // Drag events are a subset of mouse events.
   virtual bool IsDragEvent() const;
diff --git a/third_party/blink/renderer/core/dom/layout_tree_builder.cc b/third_party/blink/renderer/core/dom/layout_tree_builder.cc
index 1ddb25c7..932ae46 100644
--- a/third_party/blink/renderer/core/dom/layout_tree_builder.cc
+++ b/third_party/blink/renderer/core/dom/layout_tree_builder.cc
@@ -37,6 +37,7 @@
 #include "third_party/blink/renderer/core/dom/v0_insertion_point.h"
 #include "third_party/blink/renderer/core/dom/whitespace_attacher.h"
 #include "third_party/blink/renderer/core/html_names.h"
+#include "third_party/blink/renderer/core/layout/generated_children.h"
 #include "third_party/blink/renderer/core/layout/layout_inline.h"
 #include "third_party/blink/renderer/core/layout/layout_object.h"
 #include "third_party/blink/renderer/core/layout/layout_text.h"
@@ -122,6 +123,10 @@
     return false;
   if (!parent_layout_object->CanHaveChildren())
     return false;
+  if (node_->IsPseudoElement() &&
+      !CanHaveGeneratedChildren(*parent_layout_object)) {
+    return false;
+  }
   return node_->LayoutObjectIsNeeded(Style());
 }
 
diff --git a/third_party/blink/renderer/core/dom/pseudo_element.cc b/third_party/blink/renderer/core/dom/pseudo_element.cc
index 54f8c98..8a1d557 100644
--- a/third_party/blink/renderer/core/dom/pseudo_element.cc
+++ b/third_party/blink/renderer/core/dom/pseudo_element.cc
@@ -148,9 +148,9 @@
   if (!layout_object)
     return;
 
-  // This is to ensure that bypassing the canHaveGeneratedChildren check in
-  // StyleResolver::createPseudoElementIfNeeded does not result in the
-  // backdrop pseudo element's layout object becoming the child of a layout
+  // This is to ensure that bypassing the CanHaveGeneratedChildren() check in
+  // LayoutTreeBuilderForElement::ShouldCreateLayoutObject() does not result in
+  // the backdrop pseudo element's layout object becoming the child of a layout
   // object that doesn't allow children.
   DCHECK(layout_object->Parent());
   DCHECK(CanHaveGeneratedChildren(*layout_object->Parent()));
diff --git a/third_party/blink/renderer/core/events/composition_event.cc b/third_party/blink/renderer/core/events/composition_event.cc
index 9020324..820fd12 100644
--- a/third_party/blink/renderer/core/events/composition_event.cc
+++ b/third_party/blink/renderer/core/events/composition_event.cc
@@ -72,6 +72,10 @@
   return EventNames::CompositionEvent;
 }
 
+bool CompositionEvent::IsCompositionEvent() const {
+  return true;
+}
+
 void CompositionEvent::Trace(blink::Visitor* visitor) {
   UIEvent::Trace(visitor);
 }
diff --git a/third_party/blink/renderer/core/events/composition_event.h b/third_party/blink/renderer/core/events/composition_event.h
index 48898c3..5eaecdd 100644
--- a/third_party/blink/renderer/core/events/composition_event.h
+++ b/third_party/blink/renderer/core/events/composition_event.h
@@ -61,6 +61,8 @@
 
   const AtomicString& InterfaceName() const override;
 
+  bool IsCompositionEvent() const override;
+
   void Trace(blink::Visitor*) override;
 
  private:
diff --git a/third_party/blink/renderer/core/events/pop_state_event.cc b/third_party/blink/renderer/core/events/pop_state_event.cc
index 67ab0eb..09c491fc 100644
--- a/third_party/blink/renderer/core/events/pop_state_event.cc
+++ b/third_party/blink/renderer/core/events/pop_state_event.cc
@@ -47,7 +47,7 @@
 PopStateEvent::PopStateEvent(
     scoped_refptr<SerializedScriptValue> serialized_state,
     History* history)
-    : Event(EventTypeNames::popstate, Bubbles::kNo, Cancelable::kYes),
+    : Event(EventTypeNames::popstate, Bubbles::kNo, Cancelable::kNo),
       serialized_state_(std::move(serialized_state)),
       history_(history) {}
 
diff --git a/third_party/blink/renderer/core/frame/local_dom_window.cc b/third_party/blink/renderer/core/frame/local_dom_window.cc
index fb0e03a..763289a 100644
--- a/third_party/blink/renderer/core/frame/local_dom_window.cc
+++ b/third_party/blink/renderer/core/frame/local_dom_window.cc
@@ -317,13 +317,10 @@
 
   document_ = CreateDocument(mime_type, init, force_xhtml);
 
-  // This queue is unthrottled because throttling IndexedDB events may break
-  // scenarios where several tabs, some of which are backgrounded, access
-  // the same database concurrently.
   // TODO(hajimehoshi): Task type should be determined by a posted event instead
   // of specifying here.
   event_queue_ =
-      EventQueueImpl::Create(document_.Get(), TaskType::kUnthrottled);
+      EventQueueImpl::Create(document_.Get(), TaskType::kInternalDefault);
   document_->Initialize();
 
   if (!GetFrame())
diff --git a/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_item.cc b/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_item.cc
index b390c088..6f44e23 100644
--- a/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_item.cc
+++ b/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_item.cc
@@ -63,6 +63,15 @@
 }
 
 void LayoutNGListItem::SubtreeDidChange() {
+  if (!marker_)
+    return;
+
+  // Make sure marker is the direct child of ListItem.
+  if (marker_->Parent() && marker_->Parent() != this) {
+    marker_->Remove();
+    AddChild(marker_, FirstChild());
+  }
+
   UpdateMarkerContentIfNeeded();
 }
 
@@ -239,8 +248,7 @@
 }
 
 void LayoutNGListItem::UpdateMarkerContentIfNeeded() {
-  if (!marker_)
-    return;
+  DCHECK(marker_);
 
   LayoutObject* child = marker_->SlowFirstChild();
   if (IsMarkerImage()) {
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc
index 1a28e06..e7aed44 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc
@@ -955,6 +955,13 @@
   bool is_non_empty_inline =
       child.IsInline() && !ToNGInlineNode(child).IsEmptyInline();
 
+  // We update marker text in WillCollectInlines(). If ListItem isn't
+  // ChildrenInline(), we should WillCollectInlines() manually.
+  if (Node().IsListItem() && !child.IsInline()) {
+    LayoutBlockFlow* block = ToLayoutBlockFlow(Node().GetLayoutObject());
+    block->WillCollectInlines();
+  }
+
   bool has_clearance_past_adjoining_floats =
       child.IsBlock() &&
       HasClearancePastAdjoiningFloats(container_builder_.AdjoiningFloatTypes(),
diff --git a/third_party/blink/renderer/core/loader/frame_loader.cc b/third_party/blink/renderer/core/loader/frame_loader.cc
index e8185dd..2d2e310 100644
--- a/third_party/blink/renderer/core/loader/frame_loader.cc
+++ b/third_party/blink/renderer/core/loader/frame_loader.cc
@@ -854,35 +854,13 @@
                                   FrameLoadType frame_load_type,
                                   HistoryItem* history_item) {
   CHECK(!passed_request.GetSubstituteData().IsValid());
-  CHECK(frame_load_type != kFrameLoadTypeBackForward);
+  CHECK(!IsBackForwardLoadType(frame_load_type));
   CHECK(!history_item);
-  return LoadInternal(passed_request, frame_load_type, history_item,
-                      true /* check_with_client */);
-}
 
-void FrameLoader::CommitNavigation(const FrameLoadRequest& passed_request,
-                                   FrameLoadType frame_load_type,
-                                   HistoryItem* history_item) {
-  CHECK(!passed_request.OriginDocument());
-  CHECK(passed_request.FrameName().IsEmpty());
-  CHECK(!passed_request.TriggeringEvent());
-  CHECK(!passed_request.Form());
-  return LoadInternal(passed_request, frame_load_type, history_item,
-                      false /* check_with_client */);
-}
-
-void FrameLoader::LoadInternal(const FrameLoadRequest& passed_request,
-                               FrameLoadType frame_load_type,
-                               HistoryItem* history_item,
-                               bool check_with_client) {
   DCHECK(frame_->GetDocument());
-
   if (HTMLFrameOwnerElement* element = frame_->DeprecatedLocalOwner())
     element->CancelPendingLazyLoad();
 
-  if (IsBackForwardLoadType(frame_load_type) && !frame_->IsNavigationAllowed())
-    return;
-
   if (in_stop_all_loaders_)
     return;
 
@@ -937,26 +915,63 @@
     return;
 
   const KURL& url = request.GetResourceRequest().Url();
-  FrameLoadType new_load_type = (frame_load_type == kFrameLoadTypeStandard)
-                                    ? DetermineFrameLoadType(request)
-                                    : frame_load_type;
+  if (frame_load_type == kFrameLoadTypeStandard)
+    frame_load_type = DetermineFrameLoadType(request);
 
   bool same_document_navigation =
       policy == kNavigationPolicyCurrentTab &&
       ShouldPerformFragmentNavigation(request.Form(),
                                       request.GetResourceRequest().HttpMethod(),
-                                      new_load_type, url);
+                                      frame_load_type, url);
 
   // Perform same document navigation.
   if (same_document_navigation) {
     CommitSameDocumentNavigation(
-        request.GetResourceRequest().Url(), new_load_type, history_item,
+        request.GetResourceRequest().Url(), frame_load_type, nullptr,
         request.ClientRedirect(), request.OriginDocument(),
         request.TriggeringEvent());
     return;
   }
 
-  StartLoad(request, new_load_type, policy, history_item, check_with_client);
+  StartLoad(request, frame_load_type, policy, nullptr,
+            true /* check_with_client */);
+}
+
+void FrameLoader::CommitNavigation(const FrameLoadRequest& passed_request,
+                                   FrameLoadType frame_load_type,
+                                   HistoryItem* history_item) {
+  CHECK(!passed_request.OriginDocument());
+  CHECK(passed_request.FrameName().IsEmpty());
+  CHECK(!passed_request.TriggeringEvent());
+  CHECK(!passed_request.Form());
+
+  DCHECK(frame_->GetDocument());
+  DCHECK(!in_stop_all_loaders_);
+  DCHECK(frame_->IsNavigationAllowed());
+
+  // TODO(dgozman): figure out the better place for this check
+  // to cancel lazy load both on start and commit. Perhaps
+  // CreateDocumentLoader() is a good one.
+  if (HTMLFrameOwnerElement* element = frame_->DeprecatedLocalOwner())
+    element->CancelPendingLazyLoad();
+
+  FrameLoadRequest request(passed_request);
+  request.GetResourceRequest().SetHasUserGesture(
+      Frame::HasTransientUserActivation(frame_));
+
+  if (frame_load_type == kFrameLoadTypeStandard)
+    frame_load_type = DetermineFrameLoadType(request);
+
+  // Note: we might actually classify this navigation as same document
+  // right here in the following circumstances:
+  // - the loader has already committed a navigation and notified the browser
+  //   process which did not receive a message about that just yet;
+  // - meanwhile, the browser process sent us a command to commit this new
+  //   "cross-document" navigation, while it's actually same-document
+  //   with regards to the last commit.
+  // In this rare case, we intentionally proceed as cross-document.
+  StartLoad(request, frame_load_type, kNavigationPolicyCurrentTab, history_item,
+            false /* check_with_client */);
 }
 
 mojom::CommitResult FrameLoader::CommitSameDocumentNavigation(
diff --git a/third_party/blink/renderer/core/loader/frame_loader.h b/third_party/blink/renderer/core/loader/frame_loader.h
index 7c86e5e..492f14d 100644
--- a/third_party/blink/renderer/core/loader/frame_loader.h
+++ b/third_party/blink/renderer/core/loader/frame_loader.h
@@ -266,10 +266,6 @@
                                      NavigationPolicy,
                                      NavigationType,
                                      bool check_with_client);
-  void LoadInternal(const FrameLoadRequest&,
-                    FrameLoadType,
-                    HistoryItem*,
-                    bool check_with_client);
   void StartLoad(FrameLoadRequest&,
                  FrameLoadType,
                  NavigationPolicy,
diff --git a/third_party/blink/renderer/core/timing/event_timing.cc b/third_party/blink/renderer/core/timing/event_timing.cc
index 1bb48a0..9683a90 100644
--- a/third_party/blink/renderer/core/timing/event_timing.cc
+++ b/third_party/blink/renderer/core/timing/event_timing.cc
@@ -22,10 +22,18 @@
   performance_ = DOMWindowPerformance::performance(*window);
 }
 
+bool EventTiming::ShouldReportForEventTiming(const Event* event) const {
+  return (event->IsMouseEvent() || event->IsPointerEvent() ||
+          event->IsTouchEvent() || event->IsKeyboardEvent() ||
+          event->IsWheelEvent() || event->IsInputEvent() ||
+          event->IsCompositionEvent()) &&
+         event->isTrusted();
+}
+
 void EventTiming::WillDispatchEvent(const Event* event) {
   // Assume each event can be dispatched only once.
   DCHECK(!finished_will_dispatch_event_);
-  if (!performance_ || !event->isTrusted())
+  if (!performance_ || !ShouldReportForEventTiming(event))
     return;
 
   // Although we screen the events for timing by setting these conditions here,
diff --git a/third_party/blink/renderer/core/timing/event_timing.h b/third_party/blink/renderer/core/timing/event_timing.h
index f04827f..21216c94 100644
--- a/third_party/blink/renderer/core/timing/event_timing.h
+++ b/third_party/blink/renderer/core/timing/event_timing.h
@@ -26,6 +26,7 @@
   void DidDispatchEvent(const Event*);
 
  private:
+  bool ShouldReportForEventTiming(const Event* event) const;
   // The time the first event handler or default action started to execute.
   TimeTicks processing_start_;
   bool finished_will_dispatch_event_ = false;
diff --git a/third_party/blink/renderer/core/workers/parent_execution_context_task_runners.cc b/third_party/blink/renderer/core/workers/parent_execution_context_task_runners.cc
index 8c1c6e4..6366c7a7 100644
--- a/third_party/blink/renderer/core/workers/parent_execution_context_task_runners.cc
+++ b/third_party/blink/renderer/core/workers/parent_execution_context_task_runners.cc
@@ -31,8 +31,7 @@
   for (auto type : {TaskType::kNetworking, TaskType::kPostedMessage,
                     TaskType::kInternalDefault, TaskType::kInternalLoading,
                     TaskType::kInternalTest, TaskType::kInternalMedia,
-                    TaskType::kInternalInspector, TaskType::kInternalWorker,
-                    TaskType::kUnthrottled}) {
+                    TaskType::kInternalInspector, TaskType::kInternalWorker}) {
     auto task_runner =
         context ? context->GetTaskRunner(type)
                 : Platform::Current()->CurrentThread()->GetTaskRunner();
diff --git a/third_party/blink/renderer/modules/BUILD.gn b/third_party/blink/renderer/modules/BUILD.gn
index 99f6dc24..3bac35f 100644
--- a/third_party/blink/renderer/modules/BUILD.gn
+++ b/third_party/blink/renderer/modules/BUILD.gn
@@ -230,6 +230,8 @@
     "accessibility/ax_position_test.cc",
     "accessibility/ax_range_test.cc",
     "accessibility/ax_selection_test.cc",
+    "accessibility/testing/accessibility_selection_test.cc",
+    "accessibility/testing/accessibility_selection_test.h",
     "accessibility/testing/accessibility_test.cc",
     "accessibility/testing/accessibility_test.h",
     "animationworklet/animation_worklet_global_scope_test.cc",
diff --git a/third_party/blink/renderer/modules/accessibility/ax_selection_test.cc b/third_party/blink/renderer/modules/accessibility/ax_selection_test.cc
index d7e0c8b..a1ba17b 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_selection_test.cc
+++ b/third_party/blink/renderer/modules/accessibility/ax_selection_test.cc
@@ -10,7 +10,7 @@
 #include "third_party/blink/renderer/core/editing/selection_template.h"
 #include "third_party/blink/renderer/modules/accessibility/ax_object.h"
 #include "third_party/blink/renderer/modules/accessibility/ax_position.h"
-#include "third_party/blink/renderer/modules/accessibility/testing/accessibility_test.h"
+#include "third_party/blink/renderer/modules/accessibility/testing/accessibility_selection_test.h"
 
 namespace blink {
 
@@ -18,13 +18,14 @@
 // Basic tests.
 //
 
-TEST_F(AccessibilityTest, SetSelectionInText) {
+TEST_F(AccessibilitySelectionTest, SetSelectionInText) {
   SetBodyInnerHTML(R"HTML(<p id='paragraph'>Hello</p>)HTML");
   const Node* text = GetElementById("paragraph")->firstChild();
   ASSERT_NE(nullptr, text);
   const AXObject* ax_static_text =
       GetAXObjectByElementId("paragraph")->FirstChild();
   ASSERT_NE(nullptr, ax_static_text);
+
   const auto ax_base =
       AXPosition::CreatePositionInTextObject(*ax_static_text, 3);
   const auto ax_extent = AXPosition::CreatePositionAfterObject(*ax_static_text);
@@ -37,15 +38,18 @@
   EXPECT_EQ(3, dom_selection.Base().OffsetInContainerNode());
   EXPECT_EQ(text, dom_selection.Extent().AnchorNode());
   EXPECT_EQ(5, dom_selection.Extent().OffsetInContainerNode());
+  EXPECT_EQ("<Paragraph: ><StaticText: Hel^lo|>",
+            GetSelectionText(ax_selection));
 }
 
-TEST_F(AccessibilityTest, SetSelectionInTextWithWhiteSpace) {
+TEST_F(AccessibilitySelectionTest, SetSelectionInTextWithWhiteSpace) {
   SetBodyInnerHTML(R"HTML(<p id='paragraph'>     Hello</p>)HTML");
   const Node* text = GetElementById("paragraph")->firstChild();
   ASSERT_NE(nullptr, text);
   const AXObject* ax_static_text =
       GetAXObjectByElementId("paragraph")->FirstChild();
   ASSERT_NE(nullptr, ax_static_text);
+
   const auto ax_base =
       AXPosition::CreatePositionInTextObject(*ax_static_text, 3);
   const auto ax_extent = AXPosition::CreatePositionAfterObject(*ax_static_text);
@@ -58,6 +62,8 @@
   EXPECT_EQ(8, dom_selection.Base().OffsetInContainerNode());
   EXPECT_EQ(text, dom_selection.Extent().AnchorNode());
   EXPECT_EQ(10, dom_selection.Extent().OffsetInContainerNode());
+  EXPECT_EQ("<Paragraph: ><StaticText: Hel^lo|>",
+            GetSelectionText(ax_selection));
 }
 
 //
diff --git a/third_party/blink/renderer/modules/accessibility/testing/accessibility_selection_test.cc b/third_party/blink/renderer/modules/accessibility/testing/accessibility_selection_test.cc
new file mode 100644
index 0000000..002495b
--- /dev/null
+++ b/third_party/blink/renderer/modules/accessibility/testing/accessibility_selection_test.cc
@@ -0,0 +1,159 @@
+// 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 "third_party/blink/renderer/modules/accessibility/testing/accessibility_selection_test.h"
+
+#include "third_party/blink/renderer/modules/accessibility/ax_object.h"
+#include "third_party/blink/renderer/modules/accessibility/ax_position.h"
+#include "third_party/blink/renderer/modules/accessibility/ax_selection.h"
+#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
+
+namespace blink {
+
+namespace {
+
+// Serialize accessibility subtree to selection text.
+// Adds a '^' at the selection anchor offset and a '|' at the focus offset.
+class AXSelectionSerializer final {
+  STACK_ALLOCATED();
+
+ public:
+  explicit AXSelectionSerializer(const AXSelection& selection)
+      : selection_(selection) {}
+
+  std::string Serialize(const AXObject& subtree) {
+    if (!selection_.IsValid())
+      return {};
+    SerializeSubtree(subtree);
+    return builder_.ToString().Utf8().data();
+  }
+
+ private:
+  void HandleTextObject(const AXObject& text_object) {
+    builder_.Append('<');
+    builder_.Append(AXObject::InternalRoleName(text_object.RoleValue()));
+    builder_.Append(": ");
+    const String name = text_object.ComputedName() + '>';
+    const AXObject& base_container = *selection_.Base().ContainerObject();
+    const AXObject& extent_container = *selection_.Extent().ContainerObject();
+
+    if (base_container == text_object && extent_container == text_object) {
+      DCHECK(selection_.Base().IsTextPosition() &&
+             selection_.Extent().IsTextPosition());
+      const int base_offset = selection_.Base().TextOffset();
+      const int extent_offset = selection_.Extent().TextOffset();
+
+      if (base_offset == extent_offset) {
+        builder_.Append(name.Left(base_offset));
+        builder_.Append('|');
+        builder_.Append(name.Substring(base_offset));
+        return;
+      }
+
+      if (base_offset < extent_offset) {
+        builder_.Append(name.Left(base_offset));
+        builder_.Append('^');
+        builder_.Append(
+            name.Substring(base_offset, extent_offset - base_offset));
+        builder_.Append('|');
+        builder_.Append(name.Substring(extent_offset));
+        return;
+      }
+
+      builder_.Append(name.Left(extent_offset));
+      builder_.Append('|');
+      builder_.Append(
+          name.Substring(extent_offset, base_offset - extent_offset));
+      builder_.Append('^');
+      builder_.Append(name.Substring(base_offset));
+      return;
+    }
+
+    if (base_container == text_object) {
+      DCHECK(selection_.Base().IsTextPosition());
+      const int base_offset = selection_.Base().TextOffset();
+
+      builder_.Append(name.Left(base_offset));
+      builder_.Append('^');
+      builder_.Append(name.Substring(base_offset));
+      return;
+    }
+
+    if (extent_container == text_object) {
+      DCHECK(selection_.Extent().IsTextPosition());
+      const int extent_offset = selection_.Extent().TextOffset();
+
+      builder_.Append(name.Left(extent_offset));
+      builder_.Append('|');
+      builder_.Append(name.Substring(extent_offset));
+      return;
+    }
+
+    builder_.Append(name);
+  }
+
+  void HandleObject(const AXObject& object) {
+    builder_.Append('<');
+    builder_.Append(AXObject::InternalRoleName(object.RoleValue()));
+    builder_.Append(": ");
+    builder_.Append(object.ComputedName());
+    builder_.Append('>');
+    SerializeSubtree(object);
+  }
+
+  void HandleSelection(const AXPosition& position) {
+    if (!position.IsValid())
+      return;
+
+    if (selection_.Extent() == position) {
+      builder_.Append('|');
+      return;
+    }
+
+    if (selection_.Base() != position)
+      return;
+
+    builder_.Append('^');
+  }
+
+  void SerializeSubtree(const AXObject& subtree) {
+    for (const Member<AXObject>& child : subtree.Children()) {
+      if (!child)
+        continue;
+      const auto position = AXPosition::CreatePositionBeforeObject(*child);
+      HandleSelection(position);
+      if (position.IsTextPosition()) {
+        HandleTextObject(*child);
+      } else {
+        HandleObject(*child);
+      }
+    }
+    HandleSelection(AXPosition::CreateLastPositionInObject(subtree));
+  }
+
+  StringBuilder builder_;
+  AXSelection selection_;
+};
+
+}  // namespace
+
+AccessibilitySelectionTest::AccessibilitySelectionTest(
+    LocalFrameClient* local_frame_client)
+    : AccessibilityTest(local_frame_client) {}
+
+std::string AccessibilitySelectionTest::GetSelectionText(
+    const AXSelection& selection) const {
+  const AXObject* root = GetAXRootObject();
+  if (!root)
+    return {};
+  return AXSelectionSerializer(selection).Serialize(*root);
+}
+
+std::string AccessibilitySelectionTest::GetSelectionText(
+    const AXSelection& selection,
+    const AXObject& subtree) const {
+  return AXSelectionSerializer(selection).Serialize(subtree);
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/modules/accessibility/testing/accessibility_selection_test.h b/third_party/blink/renderer/modules/accessibility/testing/accessibility_selection_test.h
new file mode 100644
index 0000000..d0c49499
--- /dev/null
+++ b/third_party/blink/renderer/modules/accessibility/testing/accessibility_selection_test.h
@@ -0,0 +1,34 @@
+// 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 THIRD_PARTY_BLINK_RENDERER_MODULES_ACCESSIBILITY_TESTING_ACCESSIBILITY_SELECTION_TEST_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_ACCESSIBILITY_TESTING_ACCESSIBILITY_SELECTION_TEST_H_
+
+#include <string>
+
+#include "third_party/blink/renderer/modules/accessibility/testing/accessibility_test.h"
+#include "third_party/blink/renderer/platform/wtf/allocator.h"
+
+namespace blink {
+
+class AXObject;
+class AXSelection;
+class LocalFrameClient;
+
+// Makes writing and debugging selection tests easier.
+class AccessibilitySelectionTest : public AccessibilityTest {
+  USING_FAST_MALLOC(AccessibilitySelectionTest);
+
+ public:
+  AccessibilitySelectionTest(LocalFrameClient* local_frame_client = nullptr);
+
+ protected:
+  std::string GetSelectionText(const AXSelection& selection) const;
+  std::string GetSelectionText(const AXSelection& selection,
+                               const AXObject& subtree) const;
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_MODULES_ACCESSIBILITY_TESTING_ACCESSIBILITY_SELECTION_TEST_H_
diff --git a/third_party/blink/renderer/modules/accessibility/testing/accessibility_test.cc b/third_party/blink/renderer/modules/accessibility/testing/accessibility_test.cc
index ac7e538..c2f0705 100644
--- a/third_party/blink/renderer/modules/accessibility/testing/accessibility_test.cc
+++ b/third_party/blink/renderer/modules/accessibility/testing/accessibility_test.cc
@@ -13,6 +13,9 @@
 
 namespace blink {
 
+AccessibilityTest::AccessibilityTest(LocalFrameClient* local_frame_client)
+    : RenderingTest(local_frame_client) {}
+
 void AccessibilityTest::SetUp() {
   RenderingTest::SetUp();
   DCHECK(GetDocument().GetSettings());
diff --git a/third_party/blink/renderer/modules/accessibility/testing/accessibility_test.h b/third_party/blink/renderer/modules/accessibility/testing/accessibility_test.h
index 6b7bfad..b15f578 100644
--- a/third_party/blink/renderer/modules/accessibility/testing/accessibility_test.h
+++ b/third_party/blink/renderer/modules/accessibility/testing/accessibility_test.h
@@ -22,8 +22,7 @@
   USING_FAST_MALLOC(AccessibilityTest);
 
  public:
-  AccessibilityTest(LocalFrameClient* local_frame_client = nullptr)
-      : RenderingTest(local_frame_client) {}
+  AccessibilityTest(LocalFrameClient* local_frame_client = nullptr);
 
  protected:
   void SetUp() override;
diff --git a/third_party/blink/renderer/modules/sensor/README.md b/third_party/blink/renderer/modules/sensor/README.md
index b3b3faa..7cb9d81b 100644
--- a/third_party/blink/renderer/modules/sensor/README.md
+++ b/third_party/blink/renderer/modules/sensor/README.md
@@ -1,7 +1,7 @@
 # Generic Sensor
 
 `third_party/blink/renderer/modules/sensor` implements the following concrete
-sensor intrefaces based on the [Generic Sensor API]
+sensor interfaces based on the [Generic Sensor API]
 (https://w3c.github.io/sensors):
 1. [Ambient Light Sensor] (https://w3c.github.io/ambient-light)
 1. [Accelerometer] (https://w3c.github.io/accelerometer)
@@ -10,7 +10,7 @@
 1. [Absolute Orientation Sensor] (https://w3c.github.io/orientation-sensor)
 
 The platform-specific parts of the implementation are located in
-`device/generic_sensor`.
+`services/device/generic_sensor`.
 
 
 ## Testing
diff --git a/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer_test_helpers.h b/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer_test_helpers.h
index 3982c82..8bfbf1f 100644
--- a/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer_test_helpers.h
+++ b/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer_test_helpers.h
@@ -38,7 +38,6 @@
       : gl_(std::move(gl)) {}
 
   gpu::gles2::GLES2Interface* ContextGL() override { return gl_.get(); }
-  bool IsSoftwareRendering() const override { return false; }
 
   // Not used by WebGL code.
   GrContext* GetGrContext() override { return nullptr; }
diff --git a/third_party/blink/renderer/platform/graphics/test/fake_web_graphics_context_3d_provider.h b/third_party/blink/renderer/platform/graphics/test/fake_web_graphics_context_3d_provider.h
index 71063e9..0c65090 100644
--- a/third_party/blink/renderer/platform/graphics/test/fake_web_graphics_context_3d_provider.h
+++ b/third_party/blink/renderer/platform/graphics/test/fake_web_graphics_context_3d_provider.h
@@ -40,8 +40,6 @@
 
   viz::GLHelper* GetGLHelper() override { return nullptr; }
 
-  bool IsSoftwareRendering() const override { return false; }
-
   gpu::gles2::GLES2Interface* ContextGL() override { return gl_; }
 
   bool BindToCurrentThread() override { return false; }
diff --git a/third_party/blink/renderer/platform/instrumentation/resource_coordinator/renderer_resource_coordinator.cc b/third_party/blink/renderer/platform/instrumentation/resource_coordinator/renderer_resource_coordinator.cc
index b3f6767..9a7de51a8 100644
--- a/third_party/blink/renderer/platform/instrumentation/resource_coordinator/renderer_resource_coordinator.cc
+++ b/third_party/blink/renderer/platform/instrumentation/resource_coordinator/renderer_resource_coordinator.cc
@@ -62,4 +62,10 @@
   service_->SetMainThreadTaskLoadIsLow(main_thread_task_load_is_low);
 }
 
+void RendererResourceCoordinator::OnRendererIsBloated() {
+  if (!service_)
+    return;
+  service_->OnRendererIsBloated();
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/instrumentation/resource_coordinator/renderer_resource_coordinator.h b/third_party/blink/renderer/platform/instrumentation/resource_coordinator/renderer_resource_coordinator.h
index 049c2066..4c0e9c1 100644
--- a/third_party/blink/renderer/platform/instrumentation/resource_coordinator/renderer_resource_coordinator.h
+++ b/third_party/blink/renderer/platform/instrumentation/resource_coordinator/renderer_resource_coordinator.h
@@ -30,6 +30,7 @@
 
   void SetExpectedTaskQueueingDuration(base::TimeDelta);
   void SetMainThreadTaskLoadIsLow(bool);
+  void OnRendererIsBloated();
 
  protected:
   RendererResourceCoordinator();
diff --git a/third_party/blink/renderer/platform/scheduler/BUILD.gn b/third_party/blink/renderer/platform/scheduler/BUILD.gn
index a580840b..80115c56 100644
--- a/third_party/blink/renderer/platform/scheduler/BUILD.gn
+++ b/third_party/blink/renderer/platform/scheduler/BUILD.gn
@@ -13,11 +13,10 @@
     "base/graceful_queue_shutdown_helper.h",
     "base/intrusive_heap.h",
     "base/lazily_deallocated_deque.h",
-    "base/moveable_auto_lock.h",
     "base/real_time_domain.cc",
     "base/real_time_domain.h",
     "base/task_queue.cc",
-    "base/task_queue.h",
+    "base/task_queue_forward.h",
     "base/task_queue_impl.cc",
     "base/task_queue_impl.h",
     "base/task_queue_manager.h",
diff --git a/third_party/blink/renderer/platform/scheduler/base/task_queue.cc b/third_party/blink/renderer/platform/scheduler/base/task_queue.cc
index 2f450e4..59df2d8b 100644
--- a/third_party/blink/renderer/platform/scheduler/base/task_queue.cc
+++ b/third_party/blink/renderer/platform/scheduler/base/task_queue.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 "third_party/blink/renderer/platform/scheduler/base/task_queue.h"
+#include "third_party/blink/renderer/platform/scheduler/base/task_queue_forward.h"
 
 #include "base/bind_helpers.h"
 #include "base/optional.h"
diff --git a/third_party/blink/renderer/platform/scheduler/base/task_queue_forward.h b/third_party/blink/renderer/platform/scheduler/base/task_queue_forward.h
new file mode 100644
index 0000000..a37f961
--- /dev/null
+++ b/third_party/blink/renderer/platform/scheduler/base/task_queue_forward.h
@@ -0,0 +1,19 @@
+// 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 THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_TASK_QUEUE_FORWARD_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_TASK_QUEUE_FORWARD_H_
+
+// Currently the implementation is located in Blink because scheduler/base move
+// is in progress https://crbug.com/783309.
+// TODO(kraynov): Remove this header after the move.
+
+// Must be included first.
+#include "third_party/blink/renderer/platform/platform_export.h"
+
+#define HACKDEF_INCLUDED_FROM_BLINK
+#include "base/task/sequence_manager/task_queue.h"
+#undef HACKDEF_INCLUDED_FROM_BLINK
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_TASK_QUEUE_FORWARD_H_
diff --git a/third_party/blink/renderer/platform/scheduler/base/task_queue_impl.h b/third_party/blink/renderer/platform/scheduler/base/task_queue_impl.h
index 5dec440..fa1d004 100644
--- a/third_party/blink/renderer/platform/scheduler/base/task_queue_impl.h
+++ b/third_party/blink/renderer/platform/scheduler/base/task_queue_impl.h
@@ -23,7 +23,7 @@
 #include "third_party/blink/renderer/platform/scheduler/base/graceful_queue_shutdown_helper.h"
 #include "third_party/blink/renderer/platform/scheduler/base/intrusive_heap.h"
 #include "third_party/blink/renderer/platform/scheduler/base/lazily_deallocated_deque.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue.h"
+#include "third_party/blink/renderer/platform/scheduler/base/task_queue_forward.h"
 
 namespace base {
 namespace sequence_manager {
diff --git a/third_party/blink/renderer/platform/scheduler/base/task_queue_manager_impl.h b/third_party/blink/renderer/platform/scheduler/base/task_queue_manager_impl.h
index 35b6cd1..1316163 100644
--- a/third_party/blink/renderer/platform/scheduler/base/task_queue_manager_impl.h
+++ b/third_party/blink/renderer/platform/scheduler/base/task_queue_manager_impl.h
@@ -25,11 +25,11 @@
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/synchronization/lock.h"
+#include "base/task/sequence_manager/moveable_auto_lock.h"
 #include "base/task/sequence_manager/thread_controller.h"
 #include "base/threading/thread_checker.h"
 #include "third_party/blink/renderer/platform/scheduler/base/enqueue_order.h"
 #include "third_party/blink/renderer/platform/scheduler/base/graceful_queue_shutdown_helper.h"
-#include "third_party/blink/renderer/platform/scheduler/base/moveable_auto_lock.h"
 #include "third_party/blink/renderer/platform/scheduler/base/task_queue_impl.h"
 #include "third_party/blink/renderer/platform/scheduler/base/task_queue_manager.h"
 #include "third_party/blink/renderer/platform/scheduler/base/task_queue_selector.h"
diff --git a/third_party/blink/renderer/platform/scheduler/base/test/test_task_queue.h b/third_party/blink/renderer/platform/scheduler/base/test/test_task_queue.h
index 0c728ed..e8c05d6 100644
--- a/third_party/blink/renderer/platform/scheduler/base/test/test_task_queue.h
+++ b/third_party/blink/renderer/platform/scheduler/base/test/test_task_queue.h
@@ -6,7 +6,7 @@
 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_TEST_TEST_TASK_QUEUE_H_
 
 #include "base/memory/weak_ptr.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue.h"
+#include "third_party/blink/renderer/platform/scheduler/base/task_queue_forward.h"
 
 namespace base {
 namespace sequence_manager {
diff --git a/third_party/blink/renderer/platform/scheduler/child/task_queue_with_task_type.cc b/third_party/blink/renderer/platform/scheduler/child/task_queue_with_task_type.cc
index 4096827..391c521 100644
--- a/third_party/blink/renderer/platform/scheduler/child/task_queue_with_task_type.cc
+++ b/third_party/blink/renderer/platform/scheduler/child/task_queue_with_task_type.cc
@@ -8,7 +8,7 @@
 
 #include "base/bind.h"
 #include "base/location.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue.h"
+#include "third_party/blink/renderer/platform/scheduler/base/task_queue_forward.h"
 
 namespace blink {
 namespace scheduler {
diff --git a/third_party/blink/renderer/platform/scheduler/child/webthread_impl_for_worker_scheduler.cc b/third_party/blink/renderer/platform/scheduler/child/webthread_impl_for_worker_scheduler.cc
index 0493005..33b3c19 100644
--- a/third_party/blink/renderer/platform/scheduler/child/webthread_impl_for_worker_scheduler.cc
+++ b/third_party/blink/renderer/platform/scheduler/child/webthread_impl_for_worker_scheduler.cc
@@ -11,7 +11,7 @@
 #include "base/synchronization/waitable_event.h"
 #include "base/time/default_tick_clock.h"
 #include "third_party/blink/public/platform/task_type.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue.h"
+#include "third_party/blink/renderer/platform/scheduler/base/task_queue_forward.h"
 #include "third_party/blink/renderer/platform/scheduler/child/task_queue_with_task_type.h"
 #include "third_party/blink/renderer/platform/scheduler/worker/worker_scheduler_proxy.h"
 #include "third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.h"
diff --git a/third_party/blink/renderer/platform/scheduler/common/idle_canceled_delayed_task_sweeper_unittest.cc b/third_party/blink/renderer/platform/scheduler/common/idle_canceled_delayed_task_sweeper_unittest.cc
index e29e289..8bdc87c 100644
--- a/third_party/blink/renderer/platform/scheduler/common/idle_canceled_delayed_task_sweeper_unittest.cc
+++ b/third_party/blink/renderer/platform/scheduler/common/idle_canceled_delayed_task_sweeper_unittest.cc
@@ -8,7 +8,7 @@
 #include "base/test/simple_test_tick_clock.h"
 #include "components/viz/test/ordered_simple_task_runner.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue.h"
+#include "third_party/blink/renderer/platform/scheduler/base/task_queue_forward.h"
 #include "third_party/blink/renderer/platform/scheduler/base/test/task_queue_manager_for_test.h"
 #include "third_party/blink/renderer/platform/scheduler/common/idle_helper.h"
 #include "third_party/blink/renderer/platform/scheduler/common/scheduler_helper.h"
diff --git a/third_party/blink/renderer/platform/scheduler/common/idle_helper.cc b/third_party/blink/renderer/platform/scheduler/common/idle_helper.cc
index a585657..baad046 100644
--- a/third_party/blink/renderer/platform/scheduler/common/idle_helper.cc
+++ b/third_party/blink/renderer/platform/scheduler/common/idle_helper.cc
@@ -8,7 +8,7 @@
 #include "base/trace_event/trace_event.h"
 #include "base/trace_event/trace_event_argument.h"
 #include "third_party/blink/renderer/platform/scheduler/base/real_time_domain.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue.h"
+#include "third_party/blink/renderer/platform/scheduler/base/task_queue_forward.h"
 #include "third_party/blink/renderer/platform/scheduler/base/task_queue_manager.h"
 #include "third_party/blink/renderer/platform/scheduler/child/task_queue_with_task_type.h"
 #include "third_party/blink/renderer/platform/scheduler/common/scheduler_helper.h"
diff --git a/third_party/blink/renderer/platform/scheduler/common/idle_helper_unittest.cc b/third_party/blink/renderer/platform/scheduler/common/idle_helper_unittest.cc
index 04e5453..4bc89c2 100644
--- a/third_party/blink/renderer/platform/scheduler/common/idle_helper_unittest.cc
+++ b/third_party/blink/renderer/platform/scheduler/common/idle_helper_unittest.cc
@@ -16,7 +16,7 @@
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/renderer/platform/scheduler/base/real_time_domain.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue.h"
+#include "third_party/blink/renderer/platform/scheduler/base/task_queue_forward.h"
 #include "third_party/blink/renderer/platform/scheduler/base/task_queue_manager.h"
 #include "third_party/blink/renderer/platform/scheduler/base/test/task_queue_manager_for_test.h"
 #include "third_party/blink/renderer/platform/scheduler/common/scheduler_helper.h"
diff --git a/third_party/blink/renderer/platform/scheduler/common/metrics_helper.h b/third_party/blink/renderer/platform/scheduler/common/metrics_helper.h
index a6ce89a..05b9930 100644
--- a/third_party/blink/renderer/platform/scheduler/common/metrics_helper.h
+++ b/third_party/blink/renderer/platform/scheduler/common/metrics_helper.h
@@ -8,7 +8,7 @@
 #include "base/optional.h"
 #include "base/time/time.h"
 #include "third_party/blink/public/platform/web_thread_type.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue.h"
+#include "third_party/blink/renderer/platform/scheduler/base/task_queue_forward.h"
 #include "third_party/blink/renderer/platform/scheduler/util/task_duration_metric_reporter.h"
 
 namespace base {
diff --git a/third_party/blink/renderer/platform/scheduler/common/scheduler_helper_unittest.cc b/third_party/blink/renderer/platform/scheduler/common/scheduler_helper_unittest.cc
index cf11225..b5191a19 100644
--- a/third_party/blink/renderer/platform/scheduler/common/scheduler_helper_unittest.cc
+++ b/third_party/blink/renderer/platform/scheduler/common/scheduler_helper_unittest.cc
@@ -13,7 +13,7 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue.h"
+#include "third_party/blink/renderer/platform/scheduler/base/task_queue_forward.h"
 #include "third_party/blink/renderer/platform/scheduler/base/test/task_queue_manager_for_test.h"
 #include "third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler_helper.h"
 
diff --git a/third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler.h b/third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler.h
index 34a5b3cb..da00727 100644
--- a/third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler.h
+++ b/third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler.h
@@ -14,7 +14,7 @@
 #include "base/optional.h"
 #include "base/threading/thread_checker.h"
 #include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue.h"
+#include "third_party/blink/renderer/platform/scheduler/base/task_queue_forward.h"
 #include "third_party/blink/renderer/platform/scheduler/base/time_domain.h"
 #include "third_party/blink/renderer/platform/scheduler/common/cancelable_closure_holder.h"
 #include "third_party/blink/renderer/platform/scheduler/common/throttling/budget_pool.h"
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/deadline_task_runner_unittest.cc b/third_party/blink/renderer/platform/scheduler/main_thread/deadline_task_runner_unittest.cc
index f56d0e87..555d782 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/deadline_task_runner_unittest.cc
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/deadline_task_runner_unittest.cc
@@ -6,8 +6,8 @@
 
 #include <memory>
 
-#include "base/test/simple_test_tick_clock.h"
-#include "components/viz/test/ordered_simple_task_runner.h"
+#include "base/test/scoped_task_environment.h"
+#include "base/time/tick_clock.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -16,86 +16,88 @@
 
 class DeadlineTaskRunnerTest : public testing::Test {
  public:
-  DeadlineTaskRunnerTest() = default;
+  DeadlineTaskRunnerTest()
+      : task_environment_(
+            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME,
+            base::test::ScopedTaskEnvironment::ExecutionMode::QUEUED) {
+    // Null clock might trigger some assertions.
+    task_environment_.FastForwardBy(base::TimeDelta::FromMilliseconds(5));
+  }
   ~DeadlineTaskRunnerTest() override = default;
 
   void SetUp() override {
-    clock_.reset(new base::SimpleTestTickClock());
-    clock_->Advance(base::TimeDelta::FromMicroseconds(5000));
-    mock_task_runner_ = new cc::OrderedSimpleTaskRunner(clock_.get(), true);
     deadline_task_runner_.reset(new DeadlineTaskRunner(
         base::BindRepeating(&DeadlineTaskRunnerTest::TestTask,
                             base::Unretained(this)),
-        mock_task_runner_));
+        task_environment_.GetMainThreadTaskRunner()));
     run_times_.clear();
   }
 
-  bool RunUntilIdle() { return mock_task_runner_->RunUntilIdle(); }
+  base::TimeTicks Now() {
+    return task_environment_.GetMockTickClock()->NowTicks();
+  }
 
-  void TestTask() { run_times_.push_back(clock_->NowTicks()); }
+  void TestTask() { run_times_.push_back(Now()); }
 
-  std::unique_ptr<base::SimpleTestTickClock> clock_;
-  scoped_refptr<cc::OrderedSimpleTaskRunner> mock_task_runner_;
+  base::test::ScopedTaskEnvironment task_environment_;
   std::unique_ptr<DeadlineTaskRunner> deadline_task_runner_;
   std::vector<base::TimeTicks> run_times_;
 };
 
 TEST_F(DeadlineTaskRunnerTest, RunOnce) {
-  base::TimeTicks start_time = clock_->NowTicks();
+  base::TimeTicks start_time = Now();
   base::TimeDelta delay = base::TimeDelta::FromMilliseconds(10);
-  deadline_task_runner_->SetDeadline(FROM_HERE, delay, clock_->NowTicks());
-  RunUntilIdle();
+  deadline_task_runner_->SetDeadline(FROM_HERE, delay, Now());
+  task_environment_.FastForwardUntilNoTasksRemain();
 
   EXPECT_THAT(run_times_, testing::ElementsAre(start_time + delay));
 };
 
 TEST_F(DeadlineTaskRunnerTest, RunTwice) {
   base::TimeDelta delay1 = base::TimeDelta::FromMilliseconds(10);
-  base::TimeTicks deadline1 = clock_->NowTicks() + delay1;
-  deadline_task_runner_->SetDeadline(FROM_HERE, delay1, clock_->NowTicks());
-  RunUntilIdle();
+  base::TimeTicks deadline1 = Now() + delay1;
+  deadline_task_runner_->SetDeadline(FROM_HERE, delay1, Now());
+  task_environment_.FastForwardUntilNoTasksRemain();
 
   base::TimeDelta delay2 = base::TimeDelta::FromMilliseconds(100);
-  base::TimeTicks deadline2 = clock_->NowTicks() + delay2;
-  deadline_task_runner_->SetDeadline(FROM_HERE, delay2, clock_->NowTicks());
-  RunUntilIdle();
+  base::TimeTicks deadline2 = Now() + delay2;
+  deadline_task_runner_->SetDeadline(FROM_HERE, delay2, Now());
+  task_environment_.FastForwardUntilNoTasksRemain();
 
   EXPECT_THAT(run_times_, testing::ElementsAre(deadline1, deadline2));
 };
 
 TEST_F(DeadlineTaskRunnerTest, EarlierDeadlinesTakePrecidence) {
-  base::TimeTicks start_time = clock_->NowTicks();
+  base::TimeTicks start_time = Now();
   base::TimeDelta delay1 = base::TimeDelta::FromMilliseconds(1);
   base::TimeDelta delay10 = base::TimeDelta::FromMilliseconds(10);
   base::TimeDelta delay100 = base::TimeDelta::FromMilliseconds(100);
-  deadline_task_runner_->SetDeadline(FROM_HERE, delay100, clock_->NowTicks());
-  deadline_task_runner_->SetDeadline(FROM_HERE, delay10, clock_->NowTicks());
-  deadline_task_runner_->SetDeadline(FROM_HERE, delay1, clock_->NowTicks());
-
-  RunUntilIdle();
+  deadline_task_runner_->SetDeadline(FROM_HERE, delay100, Now());
+  deadline_task_runner_->SetDeadline(FROM_HERE, delay10, Now());
+  deadline_task_runner_->SetDeadline(FROM_HERE, delay1, Now());
+  task_environment_.FastForwardUntilNoTasksRemain();
 
   EXPECT_THAT(run_times_, testing::ElementsAre(start_time + delay1));
 };
 
 TEST_F(DeadlineTaskRunnerTest, LaterDeadlinesIgnored) {
-  base::TimeTicks start_time = clock_->NowTicks();
+  base::TimeTicks start_time = Now();
   base::TimeDelta delay100 = base::TimeDelta::FromMilliseconds(100);
   base::TimeDelta delay10000 = base::TimeDelta::FromMilliseconds(10000);
-  deadline_task_runner_->SetDeadline(FROM_HERE, delay100, clock_->NowTicks());
-  deadline_task_runner_->SetDeadline(FROM_HERE, delay10000, clock_->NowTicks());
-
-  RunUntilIdle();
+  deadline_task_runner_->SetDeadline(FROM_HERE, delay100, Now());
+  deadline_task_runner_->SetDeadline(FROM_HERE, delay10000, Now());
+  task_environment_.FastForwardUntilNoTasksRemain();
 
   EXPECT_THAT(run_times_, testing::ElementsAre(start_time + delay100));
 };
 
 TEST_F(DeadlineTaskRunnerTest, DeleteDeadlineTaskRunnerAfterPosting) {
   deadline_task_runner_->SetDeadline(
-      FROM_HERE, base::TimeDelta::FromMilliseconds(10), clock_->NowTicks());
+      FROM_HERE, base::TimeDelta::FromMilliseconds(10), Now());
 
   // Deleting the pending task should cancel it.
   deadline_task_runner_.reset(nullptr);
-  RunUntilIdle();
+  task_environment_.FastForwardUntilNoTasksRemain();
 
   EXPECT_TRUE(run_times_.empty());
 };
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc b/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc
index 19c8f9f..fd4612f 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc
@@ -320,7 +320,6 @@
     case TaskType::kInternalMediaRealTime:
     case TaskType::kInternalUserInteraction:
     case TaskType::kInternalIntersectionObserver:
-    case TaskType::kUnthrottled:
       return TaskQueueWithTaskType::Create(PausableTaskQueue(), type);
     case TaskType::kInternalIPC:
     // The TaskType of Inspector tasks needs to be unpausable because they need
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h b/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h
index 088823e..df9242f 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h
@@ -13,7 +13,7 @@
 #include "base/single_thread_task_runner.h"
 #include "base/trace_event/trace_event.h"
 #include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue.h"
+#include "third_party/blink/renderer/platform/scheduler/base/task_queue_forward.h"
 #include "third_party/blink/renderer/platform/scheduler/main_thread/frame_origin_type.h"
 #include "third_party/blink/renderer/platform/scheduler/main_thread/page_visibility_state.h"
 #include "third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h"
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/idle_time_estimator.h b/third_party/blink/renderer/platform/scheduler/main_thread/idle_time_estimator.h
index 4814165..46768b9b 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/idle_time_estimator.h
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/idle_time_estimator.h
@@ -10,7 +10,7 @@
 #include "base/time/tick_clock.h"
 #include "cc/base/rolling_time_delta_history.h"
 #include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue.h"
+#include "third_party/blink/renderer/platform/scheduler/base/task_queue_forward.h"
 
 namespace blink {
 namespace scheduler {
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/idle_time_estimator_unittest.cc b/third_party/blink/renderer/platform/scheduler/main_thread/idle_time_estimator_unittest.cc
index 57b5b94..10ff76e3 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/idle_time_estimator_unittest.cc
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/idle_time_estimator_unittest.cc
@@ -5,12 +5,12 @@
 #include "third_party/blink/renderer/platform/scheduler/main_thread/idle_time_estimator.h"
 
 #include <memory>
+
 #include "base/memory/scoped_refptr.h"
-#include "base/test/simple_test_tick_clock.h"
-#include "components/viz/test/ordered_simple_task_runner.h"
+#include "base/test/scoped_task_environment.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue.h"
+#include "third_party/blink/renderer/platform/scheduler/base/task_queue_forward.h"
 #include "third_party/blink/renderer/platform/scheduler/base/task_queue_manager.h"
 #include "third_party/blink/renderer/platform/scheduler/base/test/task_queue_manager_for_test.h"
 #include "third_party/blink/renderer/platform/scheduler/base/test/test_task_queue.h"
@@ -36,21 +36,25 @@
 class IdleTimeEstimatorTest : public testing::Test {
  public:
   IdleTimeEstimatorTest()
-      : frame_length_(base::TimeDelta::FromMilliseconds(16)) {}
+      : task_environment_(
+            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME,
+            base::test::ScopedTaskEnvironment::ExecutionMode::QUEUED),
+        frame_length_(base::TimeDelta::FromMilliseconds(16)) {
+    // Null clock might trigger some assertions.
+    task_environment_.FastForwardBy(base::TimeDelta::FromMilliseconds(5));
+  }
 
   ~IdleTimeEstimatorTest() override = default;
 
   void SetUp() override {
-    clock_.Advance(base::TimeDelta::FromMicroseconds(5000));
-    mock_task_runner_ =
-        base::MakeRefCounted<cc::OrderedSimpleTaskRunner>(&clock_, false);
     manager_ = base::sequence_manager::TaskQueueManagerForTest::Create(
-        nullptr, mock_task_runner_, &clock_);
+        nullptr, task_environment_.GetMainThreadTaskRunner(),
+        task_environment_.GetMockTickClock());
     compositor_task_queue_ =
         manager_->CreateTaskQueue<base::sequence_manager::TestTaskQueue>(
             base::sequence_manager::TaskQueue::Spec("test_tq"));
-    estimator_.reset(
-        new IdleTimeEstimatorForTest(compositor_task_queue_, &clock_, 10, 50));
+    estimator_.reset(new IdleTimeEstimatorForTest(
+        compositor_task_queue_, task_environment_.GetMockTickClock(), 10, 50));
   }
 
   void SimulateFrameWithOneCompositorTask(int compositor_time) {
@@ -58,11 +62,11 @@
         base::TimeDelta::FromMilliseconds(compositor_time);
     base::PendingTask task(FROM_HERE, base::Closure());
     estimator_->WillProcessTask(task);
-    clock_.Advance(non_idle_time);
+    task_environment_.FastForwardBy(non_idle_time);
     estimator_->DidCommitFrameToCompositor();
     estimator_->DidProcessTask(task);
     if (non_idle_time < frame_length_)
-      clock_.Advance(frame_length_ - non_idle_time);
+      task_environment_.FastForwardBy(frame_length_ - non_idle_time);
   }
 
   void SimulateFrameWithTwoCompositorTasks(int compositor_time1,
@@ -73,20 +77,19 @@
         base::TimeDelta::FromMilliseconds(compositor_time2);
     base::PendingTask task(FROM_HERE, base::Closure());
     estimator_->WillProcessTask(task);
-    clock_.Advance(non_idle_time1);
+    task_environment_.FastForwardBy(non_idle_time1);
     estimator_->DidProcessTask(task);
 
     estimator_->WillProcessTask(task);
-    clock_.Advance(non_idle_time2);
+    task_environment_.FastForwardBy(non_idle_time2);
     estimator_->DidCommitFrameToCompositor();
     estimator_->DidProcessTask(task);
 
     base::TimeDelta idle_time = frame_length_ - non_idle_time1 - non_idle_time2;
-    clock_.Advance(idle_time);
+    task_environment_.FastForwardBy(idle_time);
   }
 
-  base::SimpleTestTickClock clock_;
-  scoped_refptr<cc::OrderedSimpleTaskRunner> mock_task_runner_;
+  base::test::ScopedTaskEnvironment task_environment_;
   std::unique_ptr<base::sequence_manager::TaskQueueManager> manager_;
   scoped_refptr<base::sequence_manager::TaskQueue> compositor_task_queue_;
   std::unique_ptr<IdleTimeEstimatorForTest> estimator_;
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc
index ef8b6aa..e0ec924 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc
@@ -168,8 +168,6 @@
       return "InternalDefault";
     case TaskType::kInternalLoading:
       return "InternalLoading";
-    case TaskType::kUnthrottled:
-      return "Unthrottled";
     case TaskType::kInternalTest:
       return "InternalTest";
     case TaskType::kInternalWebCrypto:
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h
index ef8fe22..49a6da7f 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h
@@ -23,7 +23,7 @@
 #include "build/build_config.h"
 #include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h"
 #include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue.h"
+#include "third_party/blink/renderer/platform/scheduler/base/task_queue_forward.h"
 #include "third_party/blink/renderer/platform/scheduler/base/task_time_observer.h"
 #include "third_party/blink/renderer/platform/scheduler/child/pollable_thread_safe_flag.h"
 #include "third_party/blink/renderer/platform/scheduler/child/task_queue_with_task_type.h"
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.h b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.h
index 5fa3a74..bb1b33b 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.h
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_task_queue.h
@@ -5,7 +5,7 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_MAIN_THREAD_TASK_QUEUE_H_
 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_MAIN_THREAD_MAIN_THREAD_TASK_QUEUE_H_
 
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue.h"
+#include "third_party/blink/renderer/platform/scheduler/base/task_queue_forward.h"
 #include "third_party/blink/renderer/platform/scheduler/base/task_queue_impl.h"
 #include "third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h"
 #include "third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h"
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.h b/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.h
index aa456aa1..9d0f975 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.h
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.h
@@ -13,7 +13,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
 #include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue.h"
+#include "third_party/blink/renderer/platform/scheduler/base/task_queue_forward.h"
 #include "third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler.h"
 #include "third_party/blink/renderer/platform/scheduler/main_thread/page_visibility_state.h"
 #include "third_party/blink/renderer/platform/scheduler/public/page_scheduler.h"
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl_unittest.cc b/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl_unittest.cc
index 67771e9..a987e9a 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl_unittest.cc
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl_unittest.cc
@@ -13,8 +13,7 @@
 #include "base/metrics/field_trial_params.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/stringprintf.h"
-#include "base/test/simple_test_tick_clock.h"
-#include "components/viz/test/ordered_simple_task_runner.h"
+#include "base/test/test_mock_time_task_runner.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/renderer/platform/scheduler/base/test/task_queue_manager_for_test.h"
@@ -37,18 +36,18 @@
   PageSchedulerImplTest() = default;
   ~PageSchedulerImplTest() override = default;
 
+ protected:
   void SetUp() override {
-    clock_.Advance(base::TimeDelta::FromMicroseconds(5000));
-    mock_task_runner_ =
-        base::MakeRefCounted<cc::OrderedSimpleTaskRunner>(&clock_, true);
+    test_task_runner_ = base::WrapRefCounted(new base::TestMockTimeTaskRunner(
+        base::TestMockTimeTaskRunner::Type::kBoundToThread));
+    // A null clock triggers some assertions.
+    test_task_runner_->AdvanceMockTickClock(
+        base::TimeDelta::FromMilliseconds(5));
     scheduler_.reset(new MainThreadSchedulerImpl(
         base::sequence_manager::TaskQueueManagerForTest::Create(
-            nullptr, mock_task_runner_, &clock_),
+            nullptr, test_task_runner_, test_task_runner_->GetMockTickClock()),
         base::nullopt));
-    page_scheduler_.reset(new PageSchedulerImpl(
-        nullptr, scheduler_.get(), DisableBackgroundTimerThrottling()));
-    frame_scheduler_ = page_scheduler_->CreateFrameSchedulerImpl(
-        nullptr, FrameScheduler::FrameType::kSubframe);
+    CreatePageScheduler(false);
   }
 
   void TearDown() override {
@@ -58,9 +57,21 @@
     scheduler_.reset();
   }
 
-  virtual bool DisableBackgroundTimerThrottling() const { return false; }
+  void CreatePageScheduler(bool disable_background_timer_throttling) {
+    if (frame_scheduler_)
+      frame_scheduler_.reset();
+    page_scheduler_.reset(new PageSchedulerImpl(
+        nullptr, scheduler_.get(), disable_background_timer_throttling));
+    frame_scheduler_ = page_scheduler_->CreateFrameSchedulerImpl(
+        nullptr, FrameScheduler::FrameType::kSubframe);
+  }
 
- protected:
+  void FastForwardTo(base::TimeTicks time) {
+    base::TimeTicks now = test_task_runner_->GetMockTickClock()->NowTicks();
+    CHECK_LE(now, time);
+    test_task_runner_->FastForwardBy(time - now);
+  }
+
   static scoped_refptr<TaskQueue> ThrottleableTaskQueueForScheduler(
       FrameSchedulerImpl* scheduler) {
     return scheduler->ThrottleableTaskQueue();
@@ -96,8 +107,7 @@
     return frame_scheduler_->UnpausableTaskQueue();
   }
 
-  base::SimpleTestTickClock clock_;
-  scoped_refptr<cc::OrderedSimpleTaskRunner> mock_task_runner_;
+  scoped_refptr<base::TestMockTimeTaskRunner> test_task_runner_;
   std::unique_ptr<MainThreadSchedulerImpl> scheduler_;
   std::unique_ptr<PageSchedulerImpl> page_scheduler_;
   std::unique_ptr<FrameSchedulerImpl> frame_scheduler_;
@@ -138,7 +148,10 @@
 void RunRepeatingTask(scoped_refptr<TaskQueue> task_queue,
                       int* run_count,
                       base::TimeDelta delay) {
-  ++*run_count;
+  // Limit the number of repetitions.
+  // Test cases can make expectations against this number.
+  if (++*run_count == 2000)
+    return;
   TaskQueue* task_queue_ptr = task_queue.get();
   task_queue_ptr->PostDelayedTask(
       FROM_HERE, MakeRepeatingTask(std::move(task_queue_ptr), run_count, delay),
@@ -157,7 +170,7 @@
                         base::TimeDelta::FromMilliseconds(1)),
       base::TimeDelta::FromMilliseconds(1));
 
-  mock_task_runner_->RunForPeriod(base::TimeDelta::FromSeconds(1));
+  test_task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(1));
   EXPECT_EQ(1000, run_count);
 }
 
@@ -171,7 +184,7 @@
                         base::TimeDelta::FromMilliseconds(20)),
       base::TimeDelta::FromMilliseconds(20));
 
-  mock_task_runner_->RunForPeriod(base::TimeDelta::FromSeconds(1));
+  test_task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(1));
   EXPECT_EQ(1, run_count);
 
   // Make sure there's no delay in throttling being removed for pages that have
@@ -179,7 +192,7 @@
   page_scheduler_->SetPageVisible(true);
 
   run_count = 0;
-  mock_task_runner_->RunForPeriod(base::TimeDelta::FromSeconds(1));
+  test_task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(1));
   EXPECT_EQ(50, run_count);
 }
 
@@ -193,7 +206,7 @@
                         base::TimeDelta::FromMilliseconds(1)),
       base::TimeDelta::FromMilliseconds(1));
 
-  mock_task_runner_->RunForPeriod(base::TimeDelta::FromSeconds(1));
+  test_task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(1));
   EXPECT_EQ(1000, run_count);  // Loading tasks should not be throttled
 }
 
@@ -222,7 +235,7 @@
               &run_count2, base::TimeDelta::FromMilliseconds(20)),
           base::TimeDelta::FromMilliseconds(20));
 
-  mock_task_runner_->RunForPeriod(base::TimeDelta::FromSeconds(1));
+  test_task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(1));
   EXPECT_EQ(50, run_count1);
   EXPECT_EQ(1, run_count2);
 }
@@ -230,7 +243,7 @@
 namespace {
 
 void RunVirtualTimeRecorderTask(
-    base::SimpleTestTickClock* clock,
+    const base::TickClock* clock,
     MainThreadSchedulerImpl* scheduler,
     std::vector<base::TimeTicks>* out_real_times,
     std::vector<base::TimeTicks>* out_virtual_times) {
@@ -239,13 +252,14 @@
 }
 
 base::OnceClosure MakeVirtualTimeRecorderTask(
-    base::SimpleTestTickClock* clock,
+    const base::TickClock* clock,
     MainThreadSchedulerImpl* scheduler,
     std::vector<base::TimeTicks>* out_real_times,
     std::vector<base::TimeTicks>* out_virtual_times) {
-  return WTF::Bind(&RunVirtualTimeRecorderTask, WTF::Unretained(clock),
-                   WTF::Unretained(scheduler), WTF::Unretained(out_real_times),
-                   WTF::Unretained(out_virtual_times));
+  return base::BindOnce(&RunVirtualTimeRecorderTask, base::Unretained(clock),
+                        base::Unretained(scheduler),
+                        base::Unretained(out_real_times),
+                        base::Unretained(out_virtual_times));
 }
 }  // namespace
 
@@ -261,23 +275,26 @@
 
   ThrottleableTaskRunner()->PostDelayedTask(
       FROM_HERE,
-      MakeVirtualTimeRecorderTask(&clock_, scheduler_.get(), &real_times,
+      MakeVirtualTimeRecorderTask(test_task_runner_->GetMockTickClock(),
+                                  scheduler_.get(), &real_times,
                                   &virtual_times),
       base::TimeDelta::FromMilliseconds(2));
 
   ThrottleableTaskRunner()->PostDelayedTask(
       FROM_HERE,
-      MakeVirtualTimeRecorderTask(&clock_, scheduler_.get(), &real_times,
+      MakeVirtualTimeRecorderTask(test_task_runner_->GetMockTickClock(),
+                                  scheduler_.get(), &real_times,
                                   &virtual_times),
       base::TimeDelta::FromMilliseconds(20));
 
   ThrottleableTaskRunner()->PostDelayedTask(
       FROM_HERE,
-      MakeVirtualTimeRecorderTask(&clock_, scheduler_.get(), &real_times,
+      MakeVirtualTimeRecorderTask(test_task_runner_->GetMockTickClock(),
+                                  scheduler_.get(), &real_times,
                                   &virtual_times),
       base::TimeDelta::FromMilliseconds(200));
 
-  mock_task_runner_->RunUntilIdle();
+  test_task_runner_->FastForwardUntilNoTasksRemain();
 
   EXPECT_THAT(real_times, ElementsAre(initial_real_time, initial_real_time,
                                       initial_real_time));
@@ -301,23 +318,26 @@
 
   LoadingTaskRunner()->PostDelayedTask(
       FROM_HERE,
-      MakeVirtualTimeRecorderTask(&clock_, scheduler_.get(), &real_times,
+      MakeVirtualTimeRecorderTask(test_task_runner_->GetMockTickClock(),
+                                  scheduler_.get(), &real_times,
                                   &virtual_times),
       base::TimeDelta::FromMilliseconds(2));
 
   LoadingTaskRunner()->PostDelayedTask(
       FROM_HERE,
-      MakeVirtualTimeRecorderTask(&clock_, scheduler_.get(), &real_times,
+      MakeVirtualTimeRecorderTask(test_task_runner_->GetMockTickClock(),
+                                  scheduler_.get(), &real_times,
                                   &virtual_times),
       base::TimeDelta::FromMilliseconds(20));
 
   LoadingTaskRunner()->PostDelayedTask(
       FROM_HERE,
-      MakeVirtualTimeRecorderTask(&clock_, scheduler_.get(), &real_times,
+      MakeVirtualTimeRecorderTask(test_task_runner_->GetMockTickClock(),
+                                  scheduler_.get(), &real_times,
                                   &virtual_times),
       base::TimeDelta::FromMilliseconds(200));
 
-  mock_task_runner_->RunUntilIdle();
+  test_task_runner_->FastForwardUntilNoTasksRemain();
 
   EXPECT_THAT(real_times, ElementsAre(initial_real_time, initial_real_time,
                                       initial_real_time));
@@ -343,9 +363,10 @@
                         base::TimeDelta::FromMilliseconds(1)),
       base::TimeDelta::FromMilliseconds(1));
 
-  mock_task_runner_->RunTasksWhile(mock_task_runner_->TaskRunCountBelow(2000));
+  test_task_runner_->RunUntilIdle();
   // Virtual time means page visibility is ignored.
-  EXPECT_EQ(1999, run_count);
+  // 2000 is the |run_count| limit, we expect to reach it.
+  EXPECT_EQ(2000, run_count);
 
   // The global tick clock has not moved, yet we ran a large number of "delayed"
   // tasks despite calling setPageVisible(false).
@@ -390,7 +411,7 @@
                      base::Unretained(&run_order)),
       base::TimeDelta::FromMilliseconds(4));
 
-  mock_task_runner_->RunUntilIdle();
+  test_task_runner_->FastForwardUntilNoTasksRemain();
 
   // No timer tasks are allowed to run.
   EXPECT_THAT(run_order, ElementsAre());
@@ -418,23 +439,14 @@
                      base::Unretained(&run_order)),
       base::TimeDelta::FromMilliseconds(4));
 
-  mock_task_runner_->RunUntilIdle();
+  test_task_runner_->FastForwardUntilNoTasksRemain();
 
   EXPECT_THAT(run_order, ElementsAre(0, 1, 2, 3, 4));
 }
 
-class PageSchedulerImplTestWithDisabledBackgroundTimerThrottling
-    : public PageSchedulerImplTest {
- public:
-  PageSchedulerImplTestWithDisabledBackgroundTimerThrottling() = default;
-  ~PageSchedulerImplTestWithDisabledBackgroundTimerThrottling() override =
-      default;
-
-  bool DisableBackgroundTimerThrottling() const override { return true; }
-};
-
-TEST_F(PageSchedulerImplTestWithDisabledBackgroundTimerThrottling,
-       RepeatingTimer_PageInBackground) {
+TEST_F(PageSchedulerImplTest, RepeatingTimer_PageInBackground) {
+  // Disable background timer throttling.
+  CreatePageScheduler(true);
   page_scheduler_->SetPageVisible(false);
 
   int run_count = 0;
@@ -444,7 +456,7 @@
                         base::TimeDelta::FromMilliseconds(1)),
       base::TimeDelta::FromMilliseconds(1));
 
-  mock_task_runner_->RunForPeriod(base::TimeDelta::FromSeconds(1));
+  test_task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(1));
   EXPECT_EQ(1000, run_count);
 }
 
@@ -464,11 +476,11 @@
           base::BindOnce(&RunOrderTask, 1, base::Unretained(&run_order)),
           base::TimeDelta::FromMilliseconds(1));
 
-  mock_task_runner_->RunUntilIdle();
+  test_task_runner_->FastForwardUntilNoTasksRemain();
   EXPECT_TRUE(run_order.empty());
 
   page_scheduler_->SetVirtualTimePolicy(VirtualTimePolicy::kAdvance);
-  mock_task_runner_->RunUntilIdle();
+  test_task_runner_->FastForwardUntilNoTasksRemain();
 
   EXPECT_THAT(run_order, ElementsAre(1));
 }
@@ -493,13 +505,13 @@
         ->PostDelayedTask(FROM_HERE, MakeDeletionTask(frame_scheduler),
                           base::TimeDelta::FromMilliseconds(1));
   }
-  mock_task_runner_->RunUntilIdle();
+  test_task_runner_->FastForwardUntilNoTasksRemain();
 }
 
 TEST_F(PageSchedulerImplTest, DeletePageScheduler_InTask) {
   ThrottleableTaskQueue()->PostTask(
       FROM_HERE, MakeDeletionTask(page_scheduler_.release()));
-  mock_task_runner_->RunUntilIdle();
+  test_task_runner_->FastForwardUntilNoTasksRemain();
 }
 
 TEST_F(PageSchedulerImplTest, DeleteThrottledQueue_InTask) {
@@ -526,7 +538,7 @@
                                     MakeDeletionTask(frame_scheduler),
                                     base::TimeDelta::FromMilliseconds(9990));
 
-  mock_task_runner_->RunForPeriod(base::TimeDelta::FromSeconds(20));
+  test_task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(20));
   EXPECT_EQ(110, run_count);
 }
 
@@ -634,19 +646,20 @@
   // additional 10ms due to WebScopedVirtualTimePauser's delay.
   ThrottleableTaskRunner()->PostDelayedTask(
       FROM_HERE,
-      WTF::Bind(&PauseAndUnpauseVirtualTime, WTF::Unretained(scheduler_.get()),
-                WTF::Unretained(frame_scheduler.get()),
-                WTF::Unretained(&time_paused), WTF::Unretained(&time_unpaused)),
+      base::BindOnce(
+          &PauseAndUnpauseVirtualTime, base::Unretained(scheduler_.get()),
+          base::Unretained(frame_scheduler.get()),
+          base::Unretained(&time_paused), base::Unretained(&time_unpaused)),
       base::TimeDelta::FromMilliseconds(3));
 
   // Will run after the first task has advanced virtual time past 5ms.
   ThrottleableTaskRunner()->PostDelayedTask(
       FROM_HERE,
-      WTF::Bind(&RecordVirtualTime, WTF::Unretained(scheduler_.get()),
-                WTF::Unretained(&time_second_task)),
+      base::BindOnce(&RecordVirtualTime, base::Unretained(scheduler_.get()),
+                     base::Unretained(&time_second_task)),
       base::TimeDelta::FromMilliseconds(5));
 
-  mock_task_runner_->RunUntilIdle();
+  test_task_runner_->FastForwardUntilNoTasksRemain();
 
   EXPECT_EQ(time_paused,
             initial_virtual_time + base::TimeDelta::FromMilliseconds(3));
@@ -710,11 +723,11 @@
       ->PostTask(FROM_HERE, base::BindOnce(&RunOrderTask, 1,
                                            base::Unretained(&run_order)));
 
-  mock_task_runner_->RunUntilIdle();
+  test_task_runner_->FastForwardUntilNoTasksRemain();
   EXPECT_TRUE(run_order.empty());
 
   page_scheduler_->SetVirtualTimePolicy(VirtualTimePolicy::kAdvance);
-  mock_task_runner_->RunUntilIdle();
+  test_task_runner_->FastForwardUntilNoTasksRemain();
 
   EXPECT_THAT(run_order, ElementsAre(1));
 }
@@ -731,37 +744,41 @@
 
   ThrottleableTaskRunner()->PostDelayedTask(
       FROM_HERE,
-      MakeVirtualTimeRecorderTask(&clock_, scheduler_.get(), &real_times,
+      MakeVirtualTimeRecorderTask(test_task_runner_->GetMockTickClock(),
+                                  scheduler_.get(), &real_times,
                                   &virtual_times),
       base::TimeDelta::FromMilliseconds(1));
 
   ThrottleableTaskRunner()->PostDelayedTask(
       FROM_HERE,
-      MakeVirtualTimeRecorderTask(&clock_, scheduler_.get(), &real_times,
+      MakeVirtualTimeRecorderTask(test_task_runner_->GetMockTickClock(),
+                                  scheduler_.get(), &real_times,
                                   &virtual_times),
       base::TimeDelta::FromMilliseconds(2));
 
   ThrottleableTaskRunner()->PostDelayedTask(
       FROM_HERE,
-      MakeVirtualTimeRecorderTask(&clock_, scheduler_.get(), &real_times,
+      MakeVirtualTimeRecorderTask(test_task_runner_->GetMockTickClock(),
+                                  scheduler_.get(), &real_times,
                                   &virtual_times),
       base::TimeDelta::FromMilliseconds(5));
 
   ThrottleableTaskRunner()->PostDelayedTask(
       FROM_HERE,
-      MakeVirtualTimeRecorderTask(&clock_, scheduler_.get(), &real_times,
+      MakeVirtualTimeRecorderTask(test_task_runner_->GetMockTickClock(),
+                                  scheduler_.get(), &real_times,
                                   &virtual_times),
       base::TimeDelta::FromMilliseconds(7));
 
   page_scheduler_->GrantVirtualTimeBudget(
       base::TimeDelta::FromMilliseconds(5),
-      WTF::Bind(
+      base::BindOnce(
           [](PageScheduler* scheduler) {
             scheduler->SetVirtualTimePolicy(VirtualTimePolicy::kPause);
           },
-          WTF::Unretained(page_scheduler_.get())));
+          base::Unretained(page_scheduler_.get())));
 
-  mock_task_runner_->RunUntilIdle();
+  test_task_runner_->FastForwardUntilNoTasksRemain();
 
   // The timer that is scheduled for the exact point in time when virtual time
   // expires will not run.
@@ -821,13 +838,13 @@
 
   page_scheduler_->GrantVirtualTimeBudget(
       base::TimeDelta::FromMilliseconds(1000),
-      WTF::Bind(
+      base::BindOnce(
           [](PageScheduler* scheduler) {
             scheduler->SetVirtualTimePolicy(VirtualTimePolicy::kPause);
           },
-          WTF::Unretained(page_scheduler_.get())));
+          base::Unretained(page_scheduler_.get())));
 
-  mock_task_runner_->RunUntilIdle();
+  test_task_runner_->FastForwardUntilNoTasksRemain();
 
   EXPECT_THAT(
       mock_observer.virtual_time_log(),
@@ -870,13 +887,13 @@
 
   page_scheduler_->GrantVirtualTimeBudget(
       base::TimeDelta::FromMilliseconds(1000),
-      WTF::Bind(
+      base::BindOnce(
           [](PageScheduler* scheduler) {
             scheduler->SetVirtualTimePolicy(VirtualTimePolicy::kPause);
           },
-          WTF::Unretained(page_scheduler_.get())));
+          base::Unretained(page_scheduler_.get())));
 
-  mock_task_runner_->RunUntilIdle();
+  test_task_runner_->FastForwardUntilNoTasksRemain();
 
   // Two delayed tasks with a run of 100 tasks, plus initial call.
   EXPECT_EQ(201, count);
@@ -895,19 +912,19 @@
   RepostingTask(ThrottleableTaskQueue(), 1000, &count);
   ThrottleableTaskQueue()->PostDelayedTask(
       FROM_HERE,
-      base::BindOnce(DelayedTask, WTF::Unretained(&count),
-                     WTF::Unretained(&delayed_task_run_at_count)),
+      base::BindOnce(DelayedTask, base::Unretained(&count),
+                     base::Unretained(&delayed_task_run_at_count)),
       base::TimeDelta::FromMilliseconds(10));
 
   page_scheduler_->GrantVirtualTimeBudget(
       base::TimeDelta::FromMilliseconds(1000),
-      WTF::Bind(
+      base::BindOnce(
           [](PageScheduler* scheduler) {
             scheduler->SetVirtualTimePolicy(VirtualTimePolicy::kPause);
           },
-          WTF::Unretained(page_scheduler_.get())));
+          base::Unretained(page_scheduler_.get())));
 
-  mock_task_runner_->RunUntilIdle();
+  test_task_runner_->FastForwardUntilNoTasksRemain();
 
   EXPECT_EQ(1000, count);
   EXPECT_EQ(1000, delayed_task_run_at_count);
@@ -923,19 +940,19 @@
   RepostingTask(ThrottleableTaskQueue(), 1000, &count);
   ThrottleableTaskQueue()->PostDelayedTask(
       FROM_HERE,
-      base::BindOnce(DelayedTask, WTF::Unretained(&count),
-                     WTF::Unretained(&delayed_task_run_at_count)),
+      base::BindOnce(DelayedTask, base::Unretained(&count),
+                     base::Unretained(&delayed_task_run_at_count)),
       base::TimeDelta::FromMilliseconds(10));
 
   page_scheduler_->GrantVirtualTimeBudget(
       base::TimeDelta::FromMilliseconds(1000),
-      WTF::Bind(
+      base::BindOnce(
           [](PageScheduler* scheduler) {
             scheduler->SetVirtualTimePolicy(VirtualTimePolicy::kPause);
           },
-          WTF::Unretained(page_scheduler_.get())));
+          base::Unretained(page_scheduler_.get())));
 
-  mock_task_runner_->RunUntilIdle();
+  test_task_runner_->FastForwardUntilNoTasksRemain();
 
   EXPECT_EQ(1000, count);
   // If the initial count had been higher, the delayed task could have been
@@ -945,10 +962,10 @@
 
 namespace {
 
-void ExpensiveTestTask(base::SimpleTestTickClock* clock,
+void ExpensiveTestTask(scoped_refptr<base::TestMockTimeTaskRunner> task_runner,
                        std::vector<base::TimeTicks>* run_times) {
-  run_times->push_back(clock->NowTicks());
-  clock->Advance(base::TimeDelta::FromMilliseconds(250));
+  run_times->push_back(task_runner->GetMockTickClock()->NowTicks());
+  task_runner->AdvanceMockTickClock(base::TimeDelta::FromMilliseconds(250));
 }
 
 void InitializeTrialParams() {
@@ -985,18 +1002,18 @@
   page_scheduler_->SetPageVisible(true);
   EXPECT_FALSE(page_scheduler_->IsThrottled());
 
-  mock_task_runner_->RunUntilTime(base::TimeTicks() +
-                                  base::TimeDelta::FromMilliseconds(2500));
+  FastForwardTo(base::TimeTicks() + base::TimeDelta::FromMilliseconds(2500));
 
   ThrottleableTaskQueue()->PostDelayedTask(
-      FROM_HERE, base::BindOnce(&ExpensiveTestTask, &clock_, &run_times),
+      FROM_HERE,
+      base::BindOnce(&ExpensiveTestTask, test_task_runner_, &run_times),
       base::TimeDelta::FromMilliseconds(1));
   ThrottleableTaskQueue()->PostDelayedTask(
-      FROM_HERE, base::BindOnce(&ExpensiveTestTask, &clock_, &run_times),
+      FROM_HERE,
+      base::BindOnce(&ExpensiveTestTask, test_task_runner_, &run_times),
       base::TimeDelta::FromMilliseconds(1));
 
-  mock_task_runner_->RunUntilTime(base::TimeTicks() +
-                                  base::TimeDelta::FromMilliseconds(3500));
+  FastForwardTo(base::TimeTicks() + base::TimeDelta::FromMilliseconds(3500));
 
   // Check that these tasks are aligned, but are not subject to budget-based
   // throttling.
@@ -1010,18 +1027,19 @@
   EXPECT_FALSE(page_scheduler_->IsThrottled());
 
   // Ensure that the page is fully throttled.
-  mock_task_runner_->RunUntilTime(base::TimeTicks() +
-                                  base::TimeDelta::FromSeconds(15));
+  FastForwardTo(base::TimeTicks() + base::TimeDelta::FromSeconds(15));
   EXPECT_TRUE(page_scheduler_->IsThrottled());
 
   ThrottleableTaskQueue()->PostDelayedTask(
-      FROM_HERE, base::BindOnce(&ExpensiveTestTask, &clock_, &run_times),
+      FROM_HERE,
+      base::BindOnce(&ExpensiveTestTask, test_task_runner_, &run_times),
       base::TimeDelta::FromMicroseconds(1));
   ThrottleableTaskQueue()->PostDelayedTask(
-      FROM_HERE, base::BindOnce(&ExpensiveTestTask, &clock_, &run_times),
+      FROM_HERE,
+      base::BindOnce(&ExpensiveTestTask, test_task_runner_, &run_times),
       base::TimeDelta::FromMicroseconds(1));
 
-  mock_task_runner_->RunUntilIdle();
+  test_task_runner_->FastForwardUntilNoTasksRemain();
 
   // Check that tasks are aligned and throttled.
   EXPECT_THAT(
@@ -1054,18 +1072,17 @@
   page_scheduler->SetPageVisible(false);
 
   // Wait for 20s to avoid initial throttling delay.
-  mock_task_runner_->RunUntilTime(base::TimeTicks() +
-                                  base::TimeDelta::FromMilliseconds(20500));
+  FastForwardTo(base::TimeTicks() + base::TimeDelta::FromMilliseconds(20500));
 
   for (size_t i = 0; i < 3; ++i) {
     ThrottleableTaskQueueForScheduler(frame_scheduler1.get())
         ->PostDelayedTask(
-            FROM_HERE, base::BindOnce(&ExpensiveTestTask, &clock_, &run_times),
+            FROM_HERE,
+            base::BindOnce(&ExpensiveTestTask, test_task_runner_, &run_times),
             base::TimeDelta::FromMilliseconds(1));
   }
 
-  mock_task_runner_->RunUntilTime(base::TimeTicks() +
-                                  base::TimeDelta::FromMilliseconds(55500));
+  FastForwardTo(base::TimeTicks() + base::TimeDelta::FromMilliseconds(55500));
 
   // Check that tasks are throttled.
   EXPECT_THAT(
@@ -1081,12 +1098,12 @@
   for (size_t i = 0; i < 3; ++i) {
     ThrottleableTaskQueueForScheduler(frame_scheduler1.get())
         ->PostDelayedTask(
-            FROM_HERE, base::BindOnce(&ExpensiveTestTask, &clock_, &run_times),
+            FROM_HERE,
+            base::BindOnce(&ExpensiveTestTask, test_task_runner_, &run_times),
             base::TimeDelta::FromMilliseconds(1));
   }
 
-  mock_task_runner_->RunUntilTime(base::TimeTicks() +
-                                  base::TimeDelta::FromMilliseconds(58500));
+  FastForwardTo(base::TimeTicks() + base::TimeDelta::FromMilliseconds(58500));
 
   // Check that the timer task queue from the first frame is aligned,
   // but not throttled.
@@ -1101,12 +1118,12 @@
   for (size_t i = 0; i < 3; ++i) {
     ThrottleableTaskQueueForScheduler(frame_scheduler2.get())
         ->PostDelayedTask(
-            FROM_HERE, base::BindOnce(&ExpensiveTestTask, &clock_, &run_times),
+            FROM_HERE,
+            base::BindOnce(&ExpensiveTestTask, test_task_runner_, &run_times),
             base::TimeDelta::FromMilliseconds(1));
   }
 
-  mock_task_runner_->RunUntilTime(base::TimeTicks() +
-                                  base::TimeDelta::FromMilliseconds(59500));
+  FastForwardTo(base::TimeTicks() + base::TimeDelta::FromMilliseconds(59500));
 
   // Check that the second frame scheduler becomes unthrottled.
   EXPECT_THAT(
@@ -1120,17 +1137,17 @@
   websocket_connection.reset();
 
   // Wait for 10s to enable throttling back.
-  mock_task_runner_->RunUntilTime(base::TimeTicks() +
-                                  base::TimeDelta::FromMilliseconds(70500));
+  FastForwardTo(base::TimeTicks() + base::TimeDelta::FromMilliseconds(70500));
 
   for (size_t i = 0; i < 3; ++i) {
     ThrottleableTaskQueueForScheduler(frame_scheduler1.get())
         ->PostDelayedTask(
-            FROM_HERE, base::BindOnce(&ExpensiveTestTask, &clock_, &run_times),
+            FROM_HERE,
+            base::BindOnce(&ExpensiveTestTask, test_task_runner_, &run_times),
             base::TimeDelta::FromMilliseconds(1));
   }
 
-  mock_task_runner_->RunUntilIdle();
+  test_task_runner_->FastForwardUntilNoTasksRemain();
 
   // WebSocket is closed, budget-based throttling now applies.
   EXPECT_THAT(
@@ -1168,7 +1185,7 @@
   EXPECT_EQ(false, page_scheduler_->IsFrozen());
 
   // In a backgrounded active page, all queues should run.
-  mock_task_runner_->RunUntilIdle();
+  test_task_runner_->FastForwardUntilNoTasksRemain();
   EXPECT_EQ(5, counter);
 
   LoadingTaskQueue()->PostTask(
@@ -1187,7 +1204,7 @@
   EXPECT_EQ(true, page_scheduler_->IsFrozen());
 
   // In a backgrounded frozen page, only Unpausable queue should run.
-  mock_task_runner_->RunUntilIdle();
+  test_task_runner_->FastForwardUntilNoTasksRemain();
   EXPECT_EQ(1, counter);
 
   // A visible page should not be frozen.
@@ -1195,7 +1212,7 @@
   EXPECT_EQ(false, page_scheduler_->IsFrozen());
 
   // Once the page is unfrozen, the rest of the queues should run.
-  mock_task_runner_->RunUntilIdle();
+  test_task_runner_->FastForwardUntilNoTasksRemain();
   EXPECT_EQ(5, counter);
 }
 
@@ -1207,14 +1224,14 @@
   // We are audible for a certain period after raw signal disappearing.
   EXPECT_TRUE(page_scheduler_->IsAudioPlaying());
 
-  mock_task_runner_->RunForPeriod(base::TimeDelta::FromSeconds(3));
+  test_task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(3));
 
   page_scheduler_->AudioStateChanged(false);
   // We are still audible. A new call to AudioStateChanged shouldn't change
   // anything.
   EXPECT_TRUE(page_scheduler_->IsAudioPlaying());
 
-  mock_task_runner_->RunForPeriod(base::TimeDelta::FromSeconds(3));
+  test_task_runner_->FastForwardBy(base::TimeDelta::FromSeconds(3));
 
   // Audio is finally silent.
   EXPECT_FALSE(page_scheduler_->IsAudioPlaying());
@@ -1227,7 +1244,7 @@
 
   page_scheduler_.reset();
 
-  mock_task_runner_->RunUntilIdle();
+  test_task_runner_->FastForwardUntilNoTasksRemain();
 }
 
 TEST_F(PageSchedulerImplTest, AudiblePagesAreNotThrottled) {
@@ -1246,7 +1263,7 @@
       ThrottleableTaskQueue().get()));
 
   // Eventually throttling is reenabled again.
-  mock_task_runner_->RunUntilIdle();
+  test_task_runner_->FastForwardUntilNoTasksRemain();
   EXPECT_TRUE(scheduler_->task_queue_throttler()->IsThrottled(
       ThrottleableTaskQueue().get()));
 }
@@ -1259,8 +1276,7 @@
   scheduler_->SetSchedulerKeepActive(true);
 
   std::unique_ptr<PageSchedulerImpl> page_scheduler2 =
-      std::make_unique<PageSchedulerImpl>(nullptr, scheduler_.get(),
-                                          DisableBackgroundTimerThrottling());
+      std::make_unique<PageSchedulerImpl>(nullptr, scheduler_.get(), false);
 
   EXPECT_TRUE(page_scheduler_->KeepActive());
   EXPECT_TRUE(page_scheduler2->KeepActive());
diff --git a/third_party/blink/renderer/platform/scheduler/public/worker_scheduler.h b/third_party/blink/renderer/platform/scheduler/public/worker_scheduler.h
index a58cf6e..634099d 100644
--- a/third_party/blink/renderer/platform/scheduler/public/worker_scheduler.h
+++ b/third_party/blink/renderer/platform/scheduler/public/worker_scheduler.h
@@ -8,7 +8,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/single_thread_task_runner.h"
 #include "third_party/blink/public/platform/task_type.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue.h"
+#include "third_party/blink/renderer/platform/scheduler/base/task_queue_forward.h"
 #include "third_party/blink/renderer/platform/scheduler/public/frame_or_worker_scheduler.h"
 #include "third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h"
 
diff --git a/third_party/blink/renderer/platform/scheduler/renderer/webthread_impl_for_renderer_scheduler.cc b/third_party/blink/renderer/platform/scheduler/renderer/webthread_impl_for_renderer_scheduler.cc
index 3b318227..ebf510f 100644
--- a/third_party/blink/renderer/platform/scheduler/renderer/webthread_impl_for_renderer_scheduler.cc
+++ b/third_party/blink/renderer/platform/scheduler/renderer/webthread_impl_for_renderer_scheduler.cc
@@ -5,7 +5,7 @@
 #include "third_party/blink/renderer/platform/scheduler/renderer/webthread_impl_for_renderer_scheduler.h"
 
 #include "base/location.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue.h"
+#include "third_party/blink/renderer/platform/scheduler/base/task_queue_forward.h"
 #include "third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h"
 
 namespace blink {
diff --git a/third_party/blink/renderer/platform/scheduler/worker/compositor_thread_scheduler.cc b/third_party/blink/renderer/platform/scheduler/worker/compositor_thread_scheduler.cc
index f27f9091..0d1a229 100644
--- a/third_party/blink/renderer/platform/scheduler/worker/compositor_thread_scheduler.cc
+++ b/third_party/blink/renderer/platform/scheduler/worker/compositor_thread_scheduler.cc
@@ -12,7 +12,7 @@
 #include "base/threading/thread.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "third_party/blink/public/platform/task_type.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue.h"
+#include "third_party/blink/renderer/platform/scheduler/base/task_queue_forward.h"
 #include "third_party/blink/renderer/platform/scheduler/child/task_queue_with_task_type.h"
 #include "third_party/blink/renderer/platform/scheduler/common/scheduler_helper.h"
 
@@ -36,7 +36,7 @@
 
 scoped_refptr<NonMainThreadTaskQueue>
 CompositorThreadScheduler::DefaultTaskQueue() {
-  return helper_->DefaultNonMainThreadTaskQueue();
+  return helper()->DefaultNonMainThreadTaskQueue();
 }
 
 void CompositorThreadScheduler::InitImpl() {}
@@ -93,12 +93,12 @@
 
 void CompositorThreadScheduler::AddTaskObserver(
     base::MessageLoop::TaskObserver* task_observer) {
-  helper_->AddTaskObserver(task_observer);
+  helper()->AddTaskObserver(task_observer);
 }
 
 void CompositorThreadScheduler::RemoveTaskObserver(
     base::MessageLoop::TaskObserver* task_observer) {
-  helper_->RemoveTaskObserver(task_observer);
+  helper()->RemoveTaskObserver(task_observer);
 }
 
 void CompositorThreadScheduler::Shutdown() {}
diff --git a/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler_impl.cc b/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler_impl.cc
index aacbc38e..58dc8c9 100644
--- a/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler_impl.cc
+++ b/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler_impl.cc
@@ -8,8 +8,6 @@
 
 #include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/renderer/platform/scheduler/child/task_queue_with_task_type.h"
-#include "third_party/blink/renderer/platform/scheduler/common/throttling/task_queue_throttler.h"
-#include "third_party/blink/renderer/platform/scheduler/common/throttling/wake_up_budget_pool.h"
 #include "third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.h"
 
 namespace blink {
@@ -19,9 +17,7 @@
     std::unique_ptr<NonMainThreadSchedulerHelper> helper)
     : helper_(std::move(helper)) {}
 
-NonMainThreadSchedulerImpl::~NonMainThreadSchedulerImpl() {
-  DCHECK(worker_schedulers_.empty());
-}
+NonMainThreadSchedulerImpl::~NonMainThreadSchedulerImpl() = default;
 
 // static
 std::unique_ptr<NonMainThreadSchedulerImpl> NonMainThreadSchedulerImpl::Create(
@@ -82,17 +78,6 @@
   return base::TimeTicks::Now();
 }
 
-void NonMainThreadSchedulerImpl::RegisterWorkerScheduler(
-    WorkerScheduler* worker_scheduler) {
-  worker_schedulers_.insert(worker_scheduler);
-}
-
-void NonMainThreadSchedulerImpl::UnregisterWorkerScheduler(
-    WorkerScheduler* worker_scheduler) {
-  DCHECK(worker_schedulers_.find(worker_scheduler) != worker_schedulers_.end());
-  worker_schedulers_.erase(worker_scheduler);
-}
-
 scoped_refptr<base::SingleThreadTaskRunner>
 NonMainThreadSchedulerImpl::ControlTaskRunner() {
   return helper_->ControlNonMainThreadTaskQueue();
diff --git a/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler_impl.h b/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler_impl.h
index 7536cf2..2c88e6f 100644
--- a/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler_impl.h
+++ b/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler_impl.h
@@ -12,7 +12,7 @@
 #include "third_party/blink/public/platform/scheduler/web_thread_scheduler.h"
 #include "third_party/blink/public/platform/web_thread_type.h"
 #include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue.h"
+#include "third_party/blink/renderer/platform/scheduler/base/task_queue_forward.h"
 #include "third_party/blink/renderer/platform/scheduler/common/thread_scheduler_impl.h"
 #include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h"
 #include "third_party/blink/renderer/platform/scheduler/util/tracing_helper.h"
@@ -21,11 +21,8 @@
 
 namespace blink {
 namespace scheduler {
+
 class WorkerSchedulerProxy;
-class WorkerScheduler;
-class TaskQueueThrottler;
-class WakeUpBudgetPool;
-class CPUTimeBudgetPool;
 
 class PLATFORM_EXPORT NonMainThreadSchedulerImpl : public ThreadSchedulerImpl {
  public:
@@ -90,46 +87,21 @@
 
   scoped_refptr<NonMainThreadTaskQueue> CreateTaskRunner();
 
-  // TaskQueueThrottler might be null if throttling is not enabled or
-  // not supported.
-  TaskQueueThrottler* task_queue_throttler() const {
-    return task_queue_throttler_.get();
-  }
-  WakeUpBudgetPool* wake_up_budget_pool() const { return wake_up_budget_pool_; }
-  CPUTimeBudgetPool* cpu_time_budget_pool() const {
-    return cpu_time_budget_pool_;
-  }
-
  protected:
+  static void RunIdleTask(WebThread::IdleTask task, base::TimeTicks deadline);
+
   explicit NonMainThreadSchedulerImpl(
       std::unique_ptr<NonMainThreadSchedulerHelper> helper);
 
   friend class WorkerScheduler;
 
-  // Each WorkerScheduler should notify NonMainThreadSchedulerImpl when it is
-  // created or destroyed.
-  virtual void RegisterWorkerScheduler(WorkerScheduler* worker_scheduler);
-  virtual void UnregisterWorkerScheduler(WorkerScheduler* worker_scheduler);
-
   // Called during Init() for delayed initialization for subclasses.
   virtual void InitImpl() = 0;
 
-  // This controller should be initialized before any TraceableVariables
-  // because they require one to initialize themselves.
-  TraceableVariableController traceable_variable_controller_;
-
-  std::unique_ptr<NonMainThreadSchedulerHelper> helper_;
-
-  // Worker schedulers associated with this thread.
-  std::unordered_set<WorkerScheduler*> worker_schedulers_;
-
-  std::unique_ptr<TaskQueueThrottler> task_queue_throttler_;
-  // Owned by |task_queue_throttler_|.
-  WakeUpBudgetPool* wake_up_budget_pool_ = nullptr;
-  CPUTimeBudgetPool* cpu_time_budget_pool_ = nullptr;
+  NonMainThreadSchedulerHelper* helper() { return helper_.get(); }
 
  private:
-  static void RunIdleTask(WebThread::IdleTask task, base::TimeTicks deadline);
+  std::unique_ptr<NonMainThreadSchedulerHelper> helper_;
 
   DISALLOW_COPY_AND_ASSIGN(NonMainThreadSchedulerImpl);
 };
diff --git a/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_task_queue.h b/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_task_queue.h
index 7042124..4e4c1e44 100644
--- a/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_task_queue.h
+++ b/third_party/blink/renderer/platform/scheduler/worker/non_main_thread_task_queue.h
@@ -5,7 +5,7 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_WORKER_NON_MAIN_THREAD_TASK_QUEUE_H_
 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_WORKER_NON_MAIN_THREAD_TASK_QUEUE_H_
 
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue.h"
+#include "third_party/blink/renderer/platform/scheduler/base/task_queue_forward.h"
 
 namespace blink {
 namespace scheduler {
diff --git a/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler.cc b/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler.cc
index 109a221..c7948119 100644
--- a/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler.cc
+++ b/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler.cc
@@ -114,7 +114,6 @@
     case TaskType::kMiscPlatformAPI:
     case TaskType::kInternalDefault:
     case TaskType::kInternalLoading:
-    case TaskType::kUnthrottled:
     case TaskType::kInternalTest:
     case TaskType::kInternalWebCrypto:
     case TaskType::kInternalIndexedDB:
diff --git a/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler_unittest.cc b/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler_unittest.cc
index ca7aaa5..a6405d1 100644
--- a/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler_unittest.cc
+++ b/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler_unittest.cc
@@ -58,7 +58,7 @@
       : WorkerThreadScheduler(thread_type, std::move(manager), proxy) {}
 
   const std::unordered_set<WorkerScheduler*>& worker_schedulers() {
-    return worker_schedulers_;
+    return GetWorkerSchedulersForTesting();
   }
 
   using WorkerThreadScheduler::CreateTaskQueueThrottler;
diff --git a/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.cc b/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.cc
index fdb1b18..0a8c37b 100644
--- a/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.cc
+++ b/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.cc
@@ -14,7 +14,7 @@
 #include "base/trace_event/trace_event.h"
 #include "base/trace_event/trace_event_argument.h"
 #include "third_party/blink/renderer/platform/histogram.h"
-#include "third_party/blink/renderer/platform/scheduler/base/task_queue.h"
+#include "third_party/blink/renderer/platform/scheduler/base/task_queue_forward.h"
 #include "third_party/blink/renderer/platform/scheduler/base/task_queue_manager.h"
 #include "third_party/blink/renderer/platform/scheduler/child/features.h"
 #include "third_party/blink/renderer/platform/scheduler/child/task_queue_with_task_type.h"
@@ -22,6 +22,7 @@
 #include "third_party/blink/renderer/platform/scheduler/public/worker_scheduler.h"
 #include "third_party/blink/renderer/platform/scheduler/worker/non_main_thread_scheduler_helper.h"
 #include "third_party/blink/renderer/platform/scheduler/worker/worker_scheduler_proxy.h"
+#include "third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.h"
 
 namespace blink {
 namespace scheduler {
@@ -109,25 +110,25 @@
           std::move(task_queue_manager),
           this,
           TaskType::kWorkerThreadTaskQueueDefault)),
-      idle_helper_(helper_.get(),
+      idle_helper_(helper(),
                    this,
                    "WorkerSchedulerIdlePeriod",
                    base::TimeDelta::FromMilliseconds(300),
-                   helper_->NewTaskQueue(TaskQueue::Spec("worker_idle_tq"))),
-      idle_canceled_delayed_task_sweeper_(helper_.get(),
+                   helper()->NewTaskQueue(TaskQueue::Spec("worker_idle_tq"))),
+      idle_canceled_delayed_task_sweeper_(helper(),
                                           idle_helper_.IdleTaskRunner()),
-      load_tracker_(helper_->NowTicks(),
+      load_tracker_(helper()->NowTicks(),
                     base::BindRepeating(&ReportWorkerTaskLoad),
                     kUnspecifiedWorkerThreadLoadTrackerReportingInterval),
       lifecycle_state_(proxy ? proxy->lifecycle_state()
                              : SchedulingLifecycleState::kNotThrottled),
       worker_metrics_helper_(thread_type),
       default_task_runner_(TaskQueueWithTaskType::Create(
-          helper_->DefaultNonMainThreadTaskQueue(),
+          helper()->DefaultNonMainThreadTaskQueue(),
           TaskType::kWorkerThreadTaskQueueDefault)) {
-  thread_start_time_ = helper_->NowTicks();
+  thread_start_time_ = helper()->NowTicks();
   load_tracker_.Resume(thread_start_time_);
-  helper_->AddTaskTimeObserver(this);
+  helper()->AddTaskTimeObserver(this);
 
   if (proxy && proxy->parent_frame_type())
     worker_metrics_helper_.SetParentFrameType(*proxy->parent_frame_type());
@@ -145,7 +146,9 @@
   TRACE_EVENT_OBJECT_DELETED_WITH_ID(
       TRACE_DISABLED_BY_DEFAULT("worker.scheduler"), "WorkerScheduler", this);
 
-  helper_->RemoveTaskTimeObserver(this);
+  helper()->RemoveTaskTimeObserver(this);
+
+  DCHECK(worker_schedulers_.empty());
 }
 
 scoped_refptr<base::SingleThreadTaskRunner>
@@ -189,19 +192,19 @@
 void WorkerThreadScheduler::AddTaskObserver(
     base::MessageLoop::TaskObserver* task_observer) {
   DCHECK(initialized_);
-  helper_->AddTaskObserver(task_observer);
+  helper()->AddTaskObserver(task_observer);
 }
 
 void WorkerThreadScheduler::RemoveTaskObserver(
     base::MessageLoop::TaskObserver* task_observer) {
   DCHECK(initialized_);
-  helper_->RemoveTaskObserver(task_observer);
+  helper()->RemoveTaskObserver(task_observer);
 }
 
 void WorkerThreadScheduler::Shutdown() {
   DCHECK(initialized_);
-  load_tracker_.RecordIdle(helper_->NowTicks());
-  base::TimeTicks end_time = helper_->NowTicks();
+  load_tracker_.RecordIdle(helper()->NowTicks());
+  base::TimeTicks end_time = helper()->NowTicks();
   base::TimeDelta delta = end_time - thread_start_time_;
 
   // The lifetime could be radically different for different workers,
@@ -211,13 +214,13 @@
       "WorkerThread.Runtime", delta, base::TimeDelta::FromSeconds(1),
       base::TimeDelta::FromDays(1), 50 /* bucket count */);
   task_queue_throttler_.reset();
-  helper_->Shutdown();
+  helper()->Shutdown();
 }
 
 scoped_refptr<NonMainThreadTaskQueue>
 WorkerThreadScheduler::DefaultTaskQueue() {
   DCHECK(initialized_);
-  return helper_->DefaultNonMainThreadTaskQueue();
+  return helper()->DefaultNonMainThreadTaskQueue();
 }
 
 void WorkerThreadScheduler::InitImpl() {
@@ -245,7 +248,7 @@
 }
 
 SchedulerHelper* WorkerThreadScheduler::GetSchedulerHelperForTesting() {
-  return helper_.get();
+  return helper();
 }
 
 bool WorkerThreadScheduler::CanEnterLongIdlePeriod(base::TimeTicks,
@@ -280,13 +283,19 @@
 
 void WorkerThreadScheduler::RegisterWorkerScheduler(
     WorkerScheduler* worker_scheduler) {
-  NonMainThreadSchedulerImpl::RegisterWorkerScheduler(worker_scheduler);
+  worker_schedulers_.insert(worker_scheduler);
   worker_scheduler->OnLifecycleStateChanged(lifecycle_state_);
 }
 
+void WorkerThreadScheduler::UnregisterWorkerScheduler(
+    WorkerScheduler* worker_scheduler) {
+  DCHECK(worker_schedulers_.find(worker_scheduler) != worker_schedulers_.end());
+  worker_schedulers_.erase(worker_scheduler);
+}
+
 scoped_refptr<NonMainThreadTaskQueue>
 WorkerThreadScheduler::ControlTaskQueue() {
-  return helper_->ControlNonMainThreadTaskQueue();
+  return helper()->ControlNonMainThreadTaskQueue();
 }
 
 void WorkerThreadScheduler::CreateTaskQueueThrottler() {
@@ -311,5 +320,10 @@
   cpu_time_budget_pool_ = cpu_time_budget_pool;
 }
 
+std::unordered_set<WorkerScheduler*>&
+WorkerThreadScheduler::GetWorkerSchedulersForTesting() {
+  return worker_schedulers_;
+}
+
 }  // namespace scheduler
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.h b/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.h
index 71b74cc..c3db653 100644
--- a/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.h
+++ b/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler.h
@@ -27,7 +27,11 @@
 namespace blink {
 namespace scheduler {
 
+class WorkerScheduler;
 class WorkerSchedulerProxy;
+class TaskQueueThrottler;
+class WakeUpBudgetPool;
+class CPUTimeBudgetPool;
 
 class PLATFORM_EXPORT WorkerThreadScheduler
     : public NonMainThreadSchedulerImpl,
@@ -75,13 +79,26 @@
 
   SchedulingLifecycleState lifecycle_state() const { return lifecycle_state_; }
 
-  void RegisterWorkerScheduler(WorkerScheduler* worker_scheduler) override;
+  // Each WorkerScheduler should notify NonMainThreadSchedulerImpl when it is
+  // created or destroyed.
+  void RegisterWorkerScheduler(WorkerScheduler* worker_scheduler);
+  void UnregisterWorkerScheduler(WorkerScheduler* worker_scheduler);
 
   // Returns the control task queue.  Tasks posted to this queue are executed
   // with the highest priority. Care must be taken to avoid starvation of other
   // task queues.
   scoped_refptr<NonMainThreadTaskQueue> ControlTaskQueue();
 
+  // TaskQueueThrottler might be null if throttling is not enabled or
+  // not supported.
+  TaskQueueThrottler* task_queue_throttler() const {
+    return task_queue_throttler_.get();
+  }
+  WakeUpBudgetPool* wake_up_budget_pool() const { return wake_up_budget_pool_; }
+  CPUTimeBudgetPool* cpu_time_budget_pool() const {
+    return cpu_time_budget_pool_;
+  }
+
  protected:
   // NonMainThreadScheduler implementation:
   void InitImpl() override;
@@ -99,6 +116,8 @@
 
   void SetCPUTimeBudgetPoolForTesting(CPUTimeBudgetPool* cpu_time_budget_pool);
 
+  std::unordered_set<WorkerScheduler*>& GetWorkerSchedulersForTesting();
+
  private:
   void MaybeStartLongIdlePeriod();
 
@@ -116,6 +135,18 @@
 
   scoped_refptr<base::SingleThreadTaskRunner> default_task_runner_;
 
+  // This controller should be initialized before any TraceableVariables
+  // because they require one to initialize themselves.
+  TraceableVariableController traceable_variable_controller_;
+
+  // Worker schedulers associated with this thread.
+  std::unordered_set<WorkerScheduler*> worker_schedulers_;
+
+  std::unique_ptr<TaskQueueThrottler> task_queue_throttler_;
+  // Owned by |task_queue_throttler_|.
+  WakeUpBudgetPool* wake_up_budget_pool_ = nullptr;
+  CPUTimeBudgetPool* cpu_time_budget_pool_ = nullptr;
+
   DISALLOW_COPY_AND_ASSIGN(WorkerThreadScheduler);
 };
 
diff --git a/third_party/blink/tools/blinkpy/web_tests/update_expectations.py b/third_party/blink/tools/blinkpy/web_tests/update_expectations.py
index 2b77df8..1df3f18e 100644
--- a/third_party/blink/tools/blinkpy/web_tests/update_expectations.py
+++ b/third_party/blink/tools/blinkpy/web_tests/update_expectations.py
@@ -48,8 +48,7 @@
                         default='all',
                         help='type of expectations to update (default: %(default)s)')
     parser.add_argument('--verbose', '-v', action='store_true', default=False, help='enable more verbose logging')
-    parser.add_argument('--show-results',
-                        '-s',
+    parser.add_argument('--show-results', '-s',
                         action='store_true',
                         default=False,
                         help='Open results dashboard for all removed lines')
@@ -388,9 +387,9 @@
 
     def _bug_numbers(self):
         """Returns the list of all bug numbers affected by this change."""
-        numbers = []
+        numbers = set()
         for line in self._expectations_to_remove():
             for bug in line.bugs:
                 if bug.startswith(CHROMIUM_BUG_PREFIX):
-                    numbers.append(bug[len(CHROMIUM_BUG_PREFIX):])
+                    numbers.add(bug[len(CHROMIUM_BUG_PREFIX):])
         return sorted(numbers)
diff --git a/third_party/blink/tools/blinkpy/web_tests/update_expectations_unittest.py b/third_party/blink/tools/blinkpy/web_tests/update_expectations_unittest.py
index 24c9724..4b52b47 100644
--- a/third_party/blink/tools/blinkpy/web_tests/update_expectations_unittest.py
+++ b/third_party/blink/tools/blinkpy/web_tests/update_expectations_unittest.py
@@ -1411,13 +1411,13 @@
         """
         test_expectations_before = (
             """# Remove this since it's passing all runs.
-            crbug.com/2222 test/a.html [ Failure Pass ]
+            crbug.com/1111 test/a.html [ Failure Pass ]
             # Remove this since, although there's a failure, it's not a timeout.
             crbug.com/1111 test/b.html [ Pass Timeout ]
             # Keep since we have both crashes and passes.
-            crbug.com/3333 test/c.html [ Crash Pass ]
+            crbug.com/2222 test/c.html [ Crash Pass ]
             # Remove since it's passing all runs.
-            crbug.com/4444 test/d.html [ Failure ]""")
+            crbug.com/3333 test/d.html [ Failure ]""")
 
         self._expectations_remover = self._create_expectations_remover()
         self._define_builders({
@@ -1440,14 +1440,14 @@
         }
         self._expectations_remover.print_suggested_commit_description()
         self.assertLog([
-            'INFO: Deleting line "crbug.com/2222 test/a.html [ Failure Pass ]"\n',
+            'INFO: Deleting line "crbug.com/1111 test/a.html [ Failure Pass ]"\n',
             'INFO: Deleting line "crbug.com/1111 test/b.html [ Pass Timeout ]"\n',
-            'INFO: Deleting line "crbug.com/4444 test/d.html [ Failure ]"\n',
+            'INFO: Deleting line "crbug.com/3333 test/d.html [ Failure ]"\n',
             'INFO: Suggested commit description:\n'
             'Remove TestExpectations which are not failing in the specified way.\n\n'
             'This change was made by the update_expectations.py script.\n\n'
             'Recent test results history:\n'
             'https://test-results.appspot.com/dashboards/flakiness_dashboard.html'
             '#testType=webkit_layout_tests&tests=test/a.html,test/b.html,test/d.html\n\n'
-            'Bug: 1111, 2222, 4444\n'
+            'Bug: 1111, 3333\n'
         ])
diff --git a/third_party/libFuzzer/BUILD.gn b/third_party/libFuzzer/BUILD.gn
index 432f07e2..553999e0 100644
--- a/third_party/libFuzzer/BUILD.gn
+++ b/third_party/libFuzzer/BUILD.gn
@@ -13,8 +13,8 @@
 
 source_set("libfuzzer") {
   sources = [
-    "src/FuzzerClangCounters.cpp",
     "src/FuzzerCrossOver.cpp",
+    "src/FuzzerDataFlowTrace.cpp",
     "src/FuzzerDriver.cpp",
     "src/FuzzerExtFunctionsDlsym.cpp",
     "src/FuzzerExtFunctionsDlsymWin.cpp",
@@ -29,11 +29,13 @@
     "src/FuzzerMerge.cpp",
     "src/FuzzerMutate.cpp",
     "src/FuzzerSHA1.cpp",
+    "src/FuzzerShmemFuchsia.cpp",
     "src/FuzzerShmemPosix.cpp",
     "src/FuzzerShmemWindows.cpp",
     "src/FuzzerTracePC.cpp",
     "src/FuzzerUtil.cpp",
     "src/FuzzerUtilDarwin.cpp",
+    "src/FuzzerUtilFuchsia.cpp",
     "src/FuzzerUtilLinux.cpp",
     "src/FuzzerUtilPosix.cpp",
     "src/FuzzerUtilWindows.cpp",
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl
index 85b6e1c..dbfef75 100644
--- a/tools/mb/mb_config.pyl
+++ b/tools/mb/mb_config.pyl
@@ -168,8 +168,6 @@
       'Linux x64 Goma Canary LocalOutputCache': 'release_bot',
 
       'mac-views-rel': 'mac_views_browser_release_bot',
-      'Chromium Mac 10.11': 'release_bot',
-      'Chromium Mac 10.11 Force Mac Toolchain': 'release_bot_mac_new_sdk',
       'Chromium Mac 10.13': 'release_bot',
 
       'Mac Builder Goma Canary': 'gpu_tests_release_bot',
@@ -178,15 +176,6 @@
       'Mac Builder (dbg) Goma Canary (clobber)': 'debug_bot',
       'Mac Goma Canary LocalOutputCache': 'release_bot_mac_strip',
 
-      'Chromium Win 10 GCE Tests': 'release_bot_minimal_symbols',
-      'Chromium Win PGO Builder': {
-        '1': 'official_optimize_chrome_pgo_phase_1_x86',
-        '2': 'official_optimize_chrome_pgo_phase_2_x86',
-      },
-      'Chromium Win x64 PGO Builder': {
-        '1': 'official_optimize_chrome_pgo_phase_1',
-        '2': 'official_optimize_chrome_pgo_phase_2',
-      },
       'Chromium Windows Analyze': 'windows_analyze',
 
       'Win7 Builder Goma Canary': 'release_bot_x86_minimal_symbols',
@@ -704,14 +693,6 @@
       'win_nacl_sdk': 'release_bot_x86_minimal_symbols',
       'win_nacl_sdk_build': 'release_bot_x86_minimal_symbols',
       'win_optional_gpu_tests_rel': 'gpu_fyi_tests_release_trybot_x86',
-      'win_pgo': {
-        '1': 'official_optimize_chrome_pgo_phase_1_x86',
-        '2': 'official_optimize_chrome_pgo_phase_2_x86',
-      },
-      'win_pgo_x64': {
-        '1': 'official_optimize_chrome_pgo_phase_1',
-        '2': 'official_optimize_chrome_pgo_phase_2',
-      },
       'win_upload_clang': 'release_bot',
       'win_chrome_official': 'official_goma_x86',
     },
@@ -1450,22 +1431,6 @@
       'official', 'goma', 'x86',
     ],
 
-    'official_optimize_chrome_pgo_phase_1': [
-      'official_optimize', 'chrome_pgo_phase_1',
-    ],
-
-    'official_optimize_chrome_pgo_phase_1_x86': [
-      'official_optimize', 'chrome_pgo_phase_1', 'x86',
-    ],
-
-    'official_optimize_chrome_pgo_phase_2': [
-      'official_optimize', 'chrome_pgo_phase_2',
-    ],
-
-    'official_optimize_chrome_pgo_phase_2_x86': [
-      'official_optimize', 'chrome_pgo_phase_2', 'x86',
-    ],
-
     'ozone_linux_release_bot': [
       'ozone_linux', 'release_bot',
     ],
@@ -1519,10 +1484,6 @@
       'release_bot', 'fuchsia', 'arm64', 'cast', 'cast_audio', 'no_symbols',
     ],
 
-    'release_bot_mac_new_sdk': [
-      'release_bot', 'mac_new_sdk',
-    ],
-
     'release_bot_mac_strip': [
       'release_bot', 'mac_strip',
     ],
@@ -1756,14 +1717,6 @@
       'gn_args': 'use_cfi_recover=true',
     },
 
-    'chrome_pgo_phase_1': {
-      'gn_args': 'chrome_pgo_phase=1 is_clang=false',
-    },
-
-    'chrome_pgo_phase_2': {
-      'gn_args': 'chrome_pgo_phase=2 is_clang=false',
-    },
-
     'chrome_with_codecs': {
       'mixins': ['ffmpeg_branding_chrome', 'proprietary_codecs'],
     },
@@ -1917,10 +1870,6 @@
       'mixins': ['chrome_with_codecs'],
     },
 
-    'mac_new_sdk': {
-      'gn_args': 'mac_sdk_min="10.12"',
-    },
-
     'headless': {
       'args_file': '//build/args/headless.gn',
     },
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 503580a..c0ceff75 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -3311,6 +3311,17 @@
   <int value="5" label="Blacklist disabled."/>
 </enum>
 
+<enum name="BloatedRendererHandlingInBrowser">
+  <int value="0" label="Reloaded the bloated tab"/>
+  <int value="1" label="Cannot reload the bloated tab"/>
+  <int value="2" label="Cannot shutdown the renderer process"/>
+</enum>
+
+<enum name="BloatedRendererHandlingInResourceCoordinator">
+  <int value="0" label="Forwarded handling to the browser process"/>
+  <int value="1" label="Ignored due to multiple pages in the renderer process"/>
+</enum>
+
 <enum name="BlobBrokenReason">
   <int value="0" label="Unknown"/>
   <int value="1" label="There is not enough memory to store this blob"/>
@@ -39236,6 +39247,13 @@
   <int value="5" label="NOTIFY_FACTORY_OF_SESSION_CLOSED"/>
 </enum>
 
+<enum name="QuicWriteStatus">
+  <int value="0" label="WRITE_STATUS_OK"/>
+  <int value="1" label="WRITE_STATUS_BLOCKED"/>
+  <int value="2" label="WRITE_STATUS_ERROR"/>
+  <int value="3" label="WRITE_STATUS_MSG_TOO_BIG"/>
+</enum>
+
 <enum name="QuotaOriginTypes">
   <int value="0" label="Other"/>
   <int value="1" label="None"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index a6cf6af..6ee5c134 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -8742,6 +8742,23 @@
   </summary>
 </histogram>
 
+<histogram name="BloatedRenderer.HandlingInBrowser"
+    enum="BloatedRendererHandlingInBrowser">
+  <owner>ulan@chromium.org</owner>
+  <summary>
+    Records how a bloated renderer was handled in the browser process.
+  </summary>
+</histogram>
+
+<histogram name="BloatedRenderer.HandlingInResourceCoordinator"
+    enum="BloatedRendererHandlingInResourceCoordinator">
+  <owner>ulan@chromium.org</owner>
+  <summary>
+    Records how a bloated renderer was handled in the resource coordinator
+    service.
+  </summary>
+</histogram>
+
 <histogram name="BloatedRenderer.V8.NearV8HeapLimitHandling"
     enum="NearV8HeapLimitHandling">
   <owner>ulan@chromium.org</owner>
@@ -45310,6 +45327,14 @@
   </summary>
 </histogram>
 
+<histogram name="Navigation.Intercept.Ignored" enum="Boolean">
+  <owner>csharrison@chromium.org</owner>
+  <summary>
+    Records whether the InterceptNavigationThrottle ignored the navigation. This
+    is recorded at the end of every navigation the throttle observes.
+  </summary>
+</histogram>
+
 <histogram name="Navigation.Intercept.WillStart" units="microseconds">
   <owner>csharrison@chromium.org</owner>
   <summary>
@@ -50976,6 +51001,14 @@
   </summary>
 </histogram>
 
+<histogram name="Net.QuicConnection.WritePacketStatus" enum="QuicWriteStatus">
+  <owner>wub@chromium.org</owner>
+  <summary>
+    The write result returned by the packet writer when the connection attempts
+    to write a packet.
+  </summary>
+</histogram>
+
 <histogram name="Net.QuicCryptoClientConfig.PopulatedFromCanonicalConfig"
     enum="BooleanPopulated">
   <owner>rch@chromium.org</owner>
diff --git a/tools/perf/benchmarks/smoothness.py b/tools/perf/benchmarks/smoothness.py
index 0034f69..803bb9c 100644
--- a/tools/perf/benchmarks/smoothness.py
+++ b/tools/perf/benchmarks/smoothness.py
@@ -6,7 +6,6 @@
 from benchmarks import silk_flags
 from measurements import smoothness
 import page_sets
-import page_sets.key_silk_cases
 from telemetry import benchmark
 from telemetry import story as story_module
 
diff --git a/tools/perf/expectations.config b/tools/perf/expectations.config
index 0d2c199..a570c01 100644
--- a/tools/perf/expectations.config
+++ b/tools/perf/expectations.config
@@ -183,6 +183,19 @@
 crbug.com/785473 [ Android_Webview ] rendering.mobile/canvas_90000_pixels_per_second [ Skip ]
 crbug.com/850295 [ All ] rendering.mobile/aquarium_20k [ Skip ]
 crbug.com/795060 [ Android_One ] rendering.mobile/extra_large_texture_uploads [ Skip ]
+crbug.com/780525 [ All ] rendering.mobile/polymer_topeka [ Skip ]
+crbug.com/461127 [ All ] rendering.mobile/famo_us_twitter_demo [ Skip ]
+crbug.com/685342 [ Nexus_7 ] rendering.mobile/cnn_pathological [ Skip ]
+crbug.com/685342 [ Nexus_7 ] rendering.mobile/espn_pathological [ Skip ]
+crbug.com/685342 [ Nexus_7 ] rendering.mobile/recode_pathological [ Skip ]
+crbug.com/685342 [ Nexus_7 ] rendering.mobile/yahoo_sports_pathological [ Skip ]
+crbug.com/685342 [ Nexus_7 ] rendering.mobile/latimes_pathological [ Skip ]
+crbug.com/685342 [ Nexus_7 ] rendering.mobile/pbs_pathological [ Skip ]
+crbug.com/685342 [ Nexus_7 ] rendering.mobile/guardian_pathological [ Skip ]
+crbug.com/685342 [ Nexus_7 ] rendering.mobile/wow_wiki_pathological [ Skip ]
+crbug.com/685342 [ Nexus_7 ] rendering.mobile/zdnet_pathological [ Skip ]
+crbug.com/685342 [ Nexus_7 ] rendering.mobile/linkedin_pathological [ Skip ]
+crbug.com/822925 [ Android_Webview ] rendering.mobile/yahoo_sports_pathological [ Skip ]
 
 # Benchmark: smoothness.gpu_rasterization.polymer
 [ All ] smoothness.gpu_rasterization.polymer/* [ Skip ] # Test needs to be modernized.
diff --git a/tools/perf/page_sets/data/rendering_mobile.json b/tools/perf/page_sets/data/rendering_mobile.json
index ccd5477..277fe72 100644
--- a/tools/perf/page_sets/data/rendering_mobile.json
+++ b/tools/perf/page_sets/data/rendering_mobile.json
@@ -704,6 +704,102 @@
         },
         "cats_viewport_width": {
             "DEFAULT": "tough_image_decode_cases_000.wprgo"
+	},
+	"list_recycle_transform": {
+            "DEFAULT": "key_silk_cases_001.wprgo"
+        },
+        "sticky_using_webkit": {
+            "DEFAULT": "key_silk_cases_001.wprgo"
+        },
+	"card_expansion": {
+            "DEFAULT": "key_silk_cases_014.wprgo"
+        },
+        "card_expansion_animated": {
+            "DEFAULT": "key_silk_cases_014.wprgo"
+        },
+        "card_flying": {
+            "DEFAULT": "key_silk_cases_014.wprgo"
+        },
+        "zoom_in_animation": {
+            "DEFAULT": "key_silk_cases_014.wprgo"
+        },
+        "swipe_to_dismiss": {
+            "DEFAULT": "key_silk_cases_014.wprgo"
+        },
+        "horizontal_vertical_expansion": {
+            "DEFAULT": "key_silk_cases_014.wprgo"
+        },
+        "vertical_expansion": {
+            "DEFAULT": "key_silk_cases_014.wprgo"
+        },
+        "parallax_effect": {
+            "DEFAULT": "key_silk_cases_014.wprgo"
+        },
+        "coordinated_animation": {
+            "DEFAULT": "key_silk_cases_014.wprgo"
+        },
+        "mask_transition_animation": {
+            "DEFAULT": "key_silk_cases_014.wprgo"
+        },
+        "card_expansion_images_text": {
+            "DEFAULT": "key_silk_cases_015.wprgo"
+        },
+        "physical_simulation": {
+            "DEFAULT": "key_silk_cases_014.wprgo"
+        },
+        "basic_stream": {
+            "DEFAULT": "key_silk_cases_002.wprgo"
+        },
+        "google_news_ios": {
+            "DEFAULT": "key_silk_cases_002.wprgo"
+        },
+        "mobile_news_sandbox": {
+            "DEFAULT": "key_silk_cases_002.wprgo"
+        },
+        "famo_us_twitter_demo": {
+            "DEFAULT": "key_silk_cases_002.wprgo"
+        },
+        "svg_icon_raster": {
+            "DEFAULT": "key_silk_cases_016.wprgo"
+        },
+        "gws_google_expansion": {
+            "DEFAULT": "key_silk_cases_002.wprgo"
+        },
+        "gws_boogie_expansion": {
+            "DEFAULT": "key_silk_cases_017.wprgo"
+        },
+        "polymer_topeka": {
+            "DEFAULT": "key_silk_cases_018.wprgo"
+	},
+	"cnn_pathological": {
+            "DEFAULT": "pathological_mobile_sites_000.wprgo"
+        },
+        "espn_pathological": {
+            "DEFAULT": "pathological_mobile_sites_000.wprgo"
+        },
+        "recode_pathological": {
+            "DEFAULT": "pathological_mobile_sites_000.wprgo"
+        },
+        "yahoo_sports_pathological": {
+            "DEFAULT": "pathological_mobile_sites_001.wprgo"
+        },
+        "latimes_pathological": {
+            "DEFAULT": "pathological_mobile_sites_000.wprgo"
+        },
+        "pbs_pathological": {
+            "DEFAULT": "pathological_mobile_sites_000.wprgo"
+        },
+        "guardian_pathological": {
+            "DEFAULT": "pathological_mobile_sites_010.wprgo"
+        },
+        "wow_wiki_pathological": {
+            "DEFAULT": "pathological_mobile_sites_008.wprgo"
+        },
+        "zdnet_pathological": {
+            "DEFAULT": "pathological_mobile_sites_000.wprgo"
+        },
+        "linkedin_pathological": {
+            "DEFAULT": "pathological_mobile_sites_009.wprgo"
         }
     },
     "description": "Describes the Web Page Replay archives for a story set. Don't edit by hand! Use record_wpr for updating.",
diff --git a/tools/perf/page_sets/key_silk_cases.py b/tools/perf/page_sets/key_silk_cases.py
deleted file mode 100644
index bb830702..0000000
--- a/tools/perf/page_sets/key_silk_cases.py
+++ /dev/null
@@ -1,801 +0,0 @@
-# Copyright 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-from telemetry.page import page as page_module
-from telemetry.page import shared_page_state
-from telemetry import story
-
-
-class KeySilkCasesPage(page_module.Page):
-
-  def __init__(self, name, url, page_set, run_no_page_interactions):
-    """ Base class for all key silk cases pages.
-
-    Args:
-      run_no_page_interactions: whether the page will run any interactions after
-        navigate steps.
-    """
-    super(KeySilkCasesPage, self).__init__(
-        url=url, page_set=page_set,
-        shared_page_state_class=shared_page_state.SharedMobilePageState,
-        name=name)
-    self._run_no_page_interactions = run_no_page_interactions
-
-  def RunNavigateSteps(self, action_runner):
-    super(KeySilkCasesPage, self).RunNavigateSteps(action_runner)
-    action_runner.Wait(2)
-
-  def RunPageInteractions(self, action_runner):
-    # If a key silk case page wants to customize it actions, it should
-    # overrides the PerformPageInteractions method instead of this method.
-    if self._run_no_page_interactions:
-      return
-    self.PerformPageInteractions(action_runner)
-
-  def PerformPageInteractions(self, action_runner):
-    """ Perform interactions on page after navigate steps.
-    Override this to define custom actions to be run after navigate steps.
-    """
-    with action_runner.CreateGestureInteraction('ScrollAction'):
-      action_runner.ScrollPage()
-
-
-class Page1(KeySilkCasesPage):
-
-  """ Why: Infinite scroll. Brings out all of our perf issues. """
-
-  def __init__(self, page_set, run_no_page_interactions):
-    super(Page1, self).__init__(
-      name='list_recycle_transform',
-      url='http://groupcloned.com/test/plain/list-recycle-transform.html',
-      page_set=page_set, run_no_page_interactions=run_no_page_interactions)
-
-  def PerformPageInteractions(self, action_runner):
-    with action_runner.CreateGestureInteraction('ScrollAction'):
-      action_runner.ScrollElement(selector='#scrollable')
-
-
-class Page2(KeySilkCasesPage):
-
-  """ Why: Brings out layer management bottlenecks. """
-
-  def __init__(self, page_set, run_no_page_interactions):
-    super(Page2, self).__init__(
-      name='list_animation_simple',
-      url='file://key_silk_cases/list_animation_simple.html',
-      page_set=page_set, run_no_page_interactions=run_no_page_interactions)
-
-  def PerformPageInteractions(self, action_runner):
-    with action_runner.CreateInteraction('SimpleAnimation'):
-      action_runner.Wait(2)
-
-
-class Page3(KeySilkCasesPage):
-
-  """
-  Why: Best-known method for fake sticky. Janks sometimes. Interacts badly with
-  compositor scrolls.
-  """
-
-  def __init__(self, page_set, run_no_page_interactions):
-    super(Page3, self).__init__(
-      name='sticky_using_webkit',
-      # pylint: disable=line-too-long
-      url='http://groupcloned.com/test/plain/sticky-using-webkit-backface-visibility.html',
-      page_set=page_set, run_no_page_interactions=run_no_page_interactions)
-
-  def PerformPageInteractions(self, action_runner):
-    with action_runner.CreateGestureInteraction('ScrollAction'):
-      action_runner.ScrollElement(selector='#container')
-
-
-class Page4(KeySilkCasesPage):
-
-  """
-  Why: Card expansion: only the card should repaint, but in reality lots of
-  storms happen.
-  """
-
-  def __init__(self, page_set, run_no_page_interactions):
-    super(Page4, self).__init__(
-      name='card_expansion',
-      url='http://jsfiddle.net/3yDKh/15/show/',
-      page_set=page_set, run_no_page_interactions=run_no_page_interactions)
-
-  def PerformPageInteractions(self, action_runner):
-    with action_runner.CreateInteraction('CardExpansionAnimation'):
-      action_runner.Wait(3)
-
-
-class Page5(KeySilkCasesPage):
-
-  """
-  Why: Card expansion with animated contents, using will-change on the card
-  """
-
-  def __init__(self, page_set, run_no_page_interactions):
-    super(Page5, self).__init__(
-      name='card_expansion_animated',
-      url='http://jsfiddle.net/jx5De/14/show/',
-      page_set=page_set, run_no_page_interactions=run_no_page_interactions)
-
-    self.gpu_raster = True
-
-  def PerformPageInteractions(self, action_runner):
-    with action_runner.CreateInteraction('CardExpansionAnimation'):
-      action_runner.Wait(4)
-
-
-class Page6(KeySilkCasesPage):
-
-  """
-  Why: Card fly-in: It should be fast to animate in a bunch of cards using
-  margin-top and letting layout do the rest.
-  """
-
-  def __init__(self, page_set, run_no_page_interactions):
-    super(Page6, self).__init__(
-      name='card_flying',
-      url='http://jsfiddle.net/3yDKh/16/show/',
-      page_set=page_set, run_no_page_interactions=run_no_page_interactions)
-
-  def PerformPageInteractions(self, action_runner):
-    with action_runner.CreateInteraction('CardFlyingAnimation'):
-      action_runner.Wait(3)
-
-
-class Page7(KeySilkCasesPage):
-
-  """
-  Why: Image search expands a spacer div when you click an image to accomplish
-  a zoomin effect. Each image has a layer. Even so, this triggers a lot of
-  unnecessary repainting.
-  """
-
-  def __init__(self, page_set, run_no_page_interactions):
-    super(Page7, self).__init__(
-      name='zoom_in_animation',
-      url='http://jsfiddle.net/R8DX9/4/show/',
-      page_set=page_set, run_no_page_interactions=run_no_page_interactions)
-
-  def PerformPageInteractions(self, action_runner):
-    with action_runner.CreateInteraction('ZoominAnimation'):
-      action_runner.Wait(3)
-
-
-class Page8(KeySilkCasesPage):
-
-  """
-  Why: Swipe to dismiss of an element that has a fixed-position child that is
-  its pseudo-sticky header. Brings out issues with layer creation and
-  repainting.
-  """
-
-  def __init__(self, page_set, run_no_page_interactions):
-    super(Page8, self).__init__(
-      name='swipe_to_dismiss',
-      url='http://jsfiddle.net/rF9Gh/7/show/',
-      page_set=page_set, run_no_page_interactions=run_no_page_interactions)
-
-  def PerformPageInteractions(self, action_runner):
-    with action_runner.CreateInteraction('SwipeToDismissAnimation'):
-      action_runner.Wait(3)
-
-
-class Page9(KeySilkCasesPage):
-
-  """
-  Why: Horizontal and vertical expansion of a card that is cheap to layout but
-  costly to rasterize.
-  """
-
-  def __init__(self, page_set, run_no_page_interactions):
-    super(Page9, self).__init__(
-      name='horizontal_vertical_expansion',
-      url='http://jsfiddle.net/TLXLu/3/show/',
-      page_set=page_set, run_no_page_interactions=run_no_page_interactions)
-
-    self.gpu_raster = True
-
-  def PerformPageInteractions(self, action_runner):
-    with action_runner.CreateInteraction('CardExpansionAnimation'):
-      action_runner.Wait(4)
-
-
-class Page10(KeySilkCasesPage):
-
-  """
-  Why: Vertical Expansion of a card that is cheap to layout but costly to
-  rasterize.
-  """
-
-  def __init__(self, page_set, run_no_page_interactions):
-    super(Page10, self).__init__(
-      name='vertical_expansion',
-      url='http://jsfiddle.net/cKB9D/7/show/',
-      page_set=page_set, run_no_page_interactions=run_no_page_interactions)
-
-    self.gpu_raster = True
-
-  def PerformPageInteractions(self, action_runner):
-    with action_runner.CreateInteraction('CardExpansionAnimation'):
-      action_runner.Wait(4)
-
-
-class Page11(KeySilkCasesPage):
-
-  """
-  Why: Parallax effect is common on photo-viewer-like applications, overloading
-  software rasterization
-  """
-
-  def __init__(self, page_set, run_no_page_interactions):
-    super(Page11, self).__init__(
-      name='parallax_effect',
-      url='http://jsfiddle.net/vBQHH/11/show/',
-      page_set=page_set, run_no_page_interactions=run_no_page_interactions)
-
-    self.gpu_raster = True
-
-  def PerformPageInteractions(self, action_runner):
-    with action_runner.CreateInteraction('ParallaxAnimation'):
-      action_runner.Wait(4)
-
-
-class Page12(KeySilkCasesPage):
-
-  """ Why: Addressing paint storms during coordinated animations. """
-
-  def __init__(self, page_set, run_no_page_interactions):
-    super(Page12, self).__init__(
-      name='coordinated_animation',
-      url='http://jsfiddle.net/ugkd4/10/show/',
-      page_set=page_set, run_no_page_interactions=run_no_page_interactions)
-
-  def PerformPageInteractions(self, action_runner):
-    with action_runner.CreateInteraction('CoordinatedAnimation'):
-      action_runner.Wait(5)
-
-
-class Page13(KeySilkCasesPage):
-
-  """ Why: Mask transitions are common mobile use cases. """
-
-  def __init__(self, page_set, run_no_page_interactions):
-    super(Page13, self).__init__(
-      name='mask_transition_animation',
-      url='http://jsfiddle.net/xLuvC/1/show/',
-      page_set=page_set, run_no_page_interactions=run_no_page_interactions)
-
-    self.gpu_raster = True
-
-  def PerformPageInteractions(self, action_runner):
-    with action_runner.CreateInteraction('MaskTransitionAnimation'):
-      action_runner.Wait(4)
-
-
-class Page14(KeySilkCasesPage):
-
-  """ Why: Card expansions with images and text are pretty and common. """
-
-  def __init__(self, page_set, run_no_page_interactions):
-    super(Page14, self).__init__(
-      name='card_expansion_images_text',
-      url='http://jsfiddle.net/bNp2h/3/show/',
-      page_set=page_set, run_no_page_interactions=run_no_page_interactions)
-
-    self.gpu_raster = True
-
-  def PerformPageInteractions(self, action_runner):
-    with action_runner.CreateInteraction('CardExpansionAnimation'):
-      action_runner.Wait(4)
-
-
-class Page15(KeySilkCasesPage):
-
-  """ Why: Coordinated animations for expanding elements. """
-
-  def __init__(self, page_set, run_no_page_interactions):
-    super(Page15, self).__init__(
-      name='font_wipe',
-      url='file://key_silk_cases/font_wipe.html',
-      page_set=page_set, run_no_page_interactions=run_no_page_interactions)
-
-  def PerformPageInteractions(self, action_runner):
-    with action_runner.CreateInteraction('CoordinatedAnimation'):
-      action_runner.Wait(5)
-
-
-class Page16(KeySilkCasesPage):
-
-  def __init__(self, page_set, run_no_page_interactions):
-    super(Page16, self).__init__(
-      name='swipe_action',
-      url='file://key_silk_cases/inbox_app.html?swipe_to_dismiss',
-      page_set=page_set, run_no_page_interactions=run_no_page_interactions)
-
-  def SwipeToDismiss(self, action_runner):
-    with action_runner.CreateGestureInteraction('SwipeAction'):
-      action_runner.SwipeElement(
-          left_start_ratio=0.8, top_start_ratio=0.2,
-          direction='left', distance=400, speed_in_pixels_per_second=5000,
-          element_function='document.getElementsByClassName("message")[2]')
-
-  def PerformPageInteractions(self, action_runner):
-    self.SwipeToDismiss(action_runner)
-
-
-class Page17(KeySilkCasesPage):
-
-  def __init__(self, page_set, run_no_page_interactions):
-    super(Page17, self).__init__(
-      name='stress_hidey_bars',
-      url='file://key_silk_cases/inbox_app.html?stress_hidey_bars',
-      page_set=page_set, run_no_page_interactions=run_no_page_interactions)
-
-  def PerformPageInteractions(self, action_runner):
-    self.StressHideyBars(action_runner)
-
-  def StressHideyBars(self, action_runner):
-    with action_runner.CreateGestureInteraction(
-        'ScrollAction', repeatable=True):
-      action_runner.WaitForElement(selector='#messages')
-      action_runner.ScrollElement(
-        selector='#messages', direction='down', speed_in_pixels_per_second=200)
-    with action_runner.CreateGestureInteraction(
-        'ScrollAction', repeatable=True):
-      action_runner.WaitForElement(selector='#messages')
-      action_runner.ScrollElement(
-          selector='#messages', direction='up', speed_in_pixels_per_second=200)
-    with action_runner.CreateGestureInteraction(
-        'ScrollAction', repeatable=True):
-      action_runner.WaitForElement(selector='#messages')
-      action_runner.ScrollElement(
-          selector='#messages', direction='down',
-          speed_in_pixels_per_second=200)
-
-
-class Page18(KeySilkCasesPage):
-
-  def __init__(self, page_set, run_no_page_interactions):
-    super(Page18, self).__init__(
-      name='toggle_drawer',
-      url='file://key_silk_cases/inbox_app.html?toggle_drawer',
-      page_set=page_set, run_no_page_interactions=run_no_page_interactions)
-
-  def PerformPageInteractions(self, action_runner):
-    for _ in xrange(6):
-      self.ToggleDrawer(action_runner)
-
-  def ToggleDrawer(self, action_runner):
-    with action_runner.CreateInteraction('Action_TapAction', repeatable=True):
-      action_runner.TapElement('#menu-button')
-      action_runner.Wait(1)
-
-
-class Page19(KeySilkCasesPage):
-
-  def __init__(self, page_set, run_no_page_interactions):
-    super(Page19, self).__init__(
-      name='slide_drawer',
-      url='file://key_silk_cases/inbox_app.html?slide_drawer',
-      page_set=page_set, run_no_page_interactions=run_no_page_interactions)
-
-  def ToggleDrawer(self, action_runner):
-    with action_runner.CreateGestureInteraction('TapAction'):
-      action_runner.TapElement('#menu-button')
-
-    with action_runner.CreateInteraction('Wait'):
-      action_runner.WaitForJavaScriptCondition('''
-          document.getElementById("nav-drawer").active &&
-          document.getElementById("nav-drawer").children[0]
-              .getBoundingClientRect().left == 0''')
-
-  def RunNavigateSteps(self, action_runner):
-    super(Page19, self).RunNavigateSteps(action_runner)
-    action_runner.Wait(2)
-    self.ToggleDrawer(action_runner)
-
-  def PerformPageInteractions(self, action_runner):
-    self.SlideDrawer(action_runner)
-
-  def SlideDrawer(self, action_runner):
-    with action_runner.CreateInteraction('Action_SwipeAction'):
-      action_runner.SwipeElement(
-          left_start_ratio=0.8, top_start_ratio=0.2,
-          direction='left', distance=200,
-          element_function='document.getElementById("nav-drawer").children[0]')
-      action_runner.WaitForJavaScriptCondition(
-          '!document.getElementById("nav-drawer").active')
-
-
-class Page20(KeySilkCasesPage):
-
-  """ Why: Shadow DOM infinite scrolling. """
-
-  def __init__(self, page_set, run_no_page_interactions):
-    super(Page20, self).__init__(
-      name='infinite_scrolling',
-      url='file://key_silk_cases/infinite_scrolling.html',
-      page_set=page_set, run_no_page_interactions=run_no_page_interactions)
-
-  def PerformPageInteractions(self, action_runner):
-    with action_runner.CreateGestureInteraction('ScrollAction'):
-      action_runner.ScrollElement(
-          selector='#container', speed_in_pixels_per_second=5000)
-
-
-class GwsExpansionPage(KeySilkCasesPage):
-  """Abstract base class for pages that expand Google knowledge panels."""
-
-  def NavigateWait(self, action_runner):
-    super(GwsExpansionPage, self).RunNavigateSteps(action_runner)
-    action_runner.Wait(3)
-
-  def ExpandKnowledgeCard(self, action_runner):
-    # expand card
-    with action_runner.CreateInteraction('Action_TapAction'):
-      action_runner.TapElement(
-          element_function='document.getElementsByClassName("vk_arc")[0]')
-      action_runner.Wait(2)
-
-  def ScrollKnowledgeCardToTop(self, action_runner, card_id):
-    # scroll until the knowledge card is at the top
-    action_runner.ExecuteJavaScript(
-        "document.getElementById({{ card_id }}).scrollIntoView()",
-        card_id=card_id)
-
-  def PerformPageInteractions(self, action_runner):
-    self.ExpandKnowledgeCard(action_runner)
-
-
-class GwsGoogleExpansion(GwsExpansionPage):
-
-  """ Why: Animating height of a complex content card is common. """
-
-  def __init__(self, page_set, run_no_page_interactions):
-    super(GwsGoogleExpansion, self).__init__(
-      name='gws_google_expansion',
-      url='http://www.google.com/#q=google',
-      page_set=page_set, run_no_page_interactions=run_no_page_interactions)
-
-  def RunNavigateSteps(self, action_runner):
-    self.NavigateWait(action_runner)
-    self.ScrollKnowledgeCardToTop(action_runner, 'kno-result')
-
-
-class GwsBoogieExpansion(GwsExpansionPage):
-
-  """ Why: Same case as Google expansion but text-heavy rather than image. """
-
-  def __init__(self, page_set, run_no_page_interactions):
-    super(GwsBoogieExpansion, self).__init__(
-      name='gws_boogie_expansion',
-      url='https://www.google.com/search?hl=en&q=define%3Aboogie',
-      page_set=page_set, run_no_page_interactions=run_no_page_interactions)
-
-  def RunNavigateSteps(self, action_runner):
-    self.NavigateWait(action_runner)
-    self.ScrollKnowledgeCardToTop(action_runner, 'rso')
-
-
-class Page22(KeySilkCasesPage):
-
-  def __init__(self, page_set, run_no_page_interactions):
-    super(Page22, self).__init__(
-      name='basic_stream',
-      url='http://plus.google.com/app/basic/stream',
-      page_set=page_set, run_no_page_interactions=run_no_page_interactions)
-
-  def RunNavigateSteps(self, action_runner):
-    super(Page22, self).RunNavigateSteps(action_runner)
-    action_runner.WaitForJavaScriptCondition(
-        'document.getElementsByClassName("fHa").length > 0')
-    action_runner.Wait(2)
-
-  def PerformPageInteractions(self, action_runner):
-    with action_runner.CreateGestureInteraction('ScrollAction'):
-      action_runner.ScrollElement(selector='#mainContent')
-
-
-class Page23(KeySilkCasesPage):
-
-  """
-  Why: Physical simulation demo that does a lot of element.style mutation
-  triggering JS and recalc slowness
-  """
-
-  def __init__(self, page_set, run_no_page_interactions):
-    super(Page23, self).__init__(
-      name='physical_simulation',
-      url='http://jsbin.com/UVIgUTa/38/quiet',
-      page_set=page_set, run_no_page_interactions=run_no_page_interactions)
-
-  def PerformPageInteractions(self, action_runner):
-    with action_runner.CreateGestureInteraction('ScrollAction',
-                                                repeatable=True):
-      action_runner.ScrollPage(
-          distance_expr='window.innerHeight / 2',
-          direction='down',
-          use_touch=True)
-    with action_runner.CreateGestureInteraction('ScrollAction',
-                                                repeatable=True):
-      action_runner.Wait(1)
-
-
-class Page24(KeySilkCasesPage):
-
-  """
-  Why: Google News: this iOS version is slower than accelerated scrolling
-  """
-
-  def __init__(self, page_set, run_no_page_interactions):
-    super(Page24, self).__init__(
-      name='google_news_ios',
-      url='http://mobile-news.sandbox.google.com/news/pt0?scroll',
-      page_set=page_set, run_no_page_interactions=run_no_page_interactions)
-
-  def RunNavigateSteps(self, action_runner):
-    super(Page24, self).RunNavigateSteps(action_runner)
-    action_runner.WaitForJavaScriptCondition(
-        'document.getElementById(":h") != null')
-    action_runner.Wait(1)
-
-  def PerformPageInteractions(self, action_runner):
-    with action_runner.CreateGestureInteraction('ScrollAction'):
-      action_runner.ScrollElement(
-          element_function='document.getElementById(":5")',
-          distance=2500,
-          use_touch=True)
-
-
-class Page25(KeySilkCasesPage):
-
-  def __init__(self, page_set, run_no_page_interactions):
-    super(Page25, self).__init__(
-      name='mobile_news_sandbox',
-      url='http://mobile-news.sandbox.google.com/news/pt0?swipe',
-      page_set=page_set, run_no_page_interactions=run_no_page_interactions)
-
-  def RunNavigateSteps(self, action_runner):
-    super(Page25, self).RunNavigateSteps(action_runner)
-    action_runner.WaitForJavaScriptCondition(
-        'document.getElementById(":h") != null')
-    action_runner.Wait(1)
-
-  def PerformPageInteractions(self, action_runner):
-    with action_runner.CreateGestureInteraction('SwipeAction', repeatable=True):
-      action_runner.SwipeElement(
-          direction='left', distance=100,
-          element_function='document.getElementById(":f")')
-    with action_runner.CreateGestureInteraction('SwipeAction', repeatable=True):
-      action_runner.Wait(1)
-
-
-class Page26(KeySilkCasesPage):
-
-  """ Why: famo.us twitter demo """
-
-  def __init__(self, page_set, run_no_page_interactions):
-    super(Page26, self).__init__(
-      name='famo_us_twitter_demo',
-      url='http://s.codepen.io/befamous/fullpage/pFsqb?scroll',
-      page_set=page_set, run_no_page_interactions=run_no_page_interactions)
-
-  def RunNavigateSteps(self, action_runner):
-    super(Page26, self).RunNavigateSteps(action_runner)
-    action_runner.WaitForJavaScriptCondition(
-        'document.getElementsByClassName("tweet").length > 0')
-    action_runner.Wait(1)
-
-  def PerformPageInteractions(self, action_runner):
-    # Add a touch-action: none because this page prevent defaults all
-    # touch moves.
-    action_runner.ExecuteJavaScript('''
-        var style = document.createElement("style");
-        document.head.appendChild(style);
-        style.sheet.insertRule("body { touch-action: none }", 0);
-        ''')
-    with action_runner.CreateGestureInteraction('ScrollAction'):
-      action_runner.ScrollPage(distance=5000)
-
-
-class SVGIconRaster(KeySilkCasesPage):
-
-  """ Why: Mutating SVG icons; these paint storm and paint slowly. """
-
-  def __init__(self, page_set, run_no_page_interactions):
-    super(SVGIconRaster, self).__init__(
-      name='svg_icon_raster',
-      url='http://wiltzius.github.io/shape-shifter/',
-      page_set=page_set, run_no_page_interactions=run_no_page_interactions)
-
-  def RunNavigateSteps(self, action_runner):
-    super(SVGIconRaster, self).RunNavigateSteps(action_runner)
-    action_runner.WaitForJavaScriptCondition(
-        'loaded = true')
-    action_runner.Wait(1)
-
-  def PerformPageInteractions(self, action_runner):
-    for i in xrange(9):
-      button_func = ('document.getElementById("demo").$.'
-                     'buttons.children[%d]') % i
-      with action_runner.CreateInteraction('Action_TapAction', repeatable=True):
-        action_runner.TapElement(element_function=button_func)
-        action_runner.Wait(1)
-
-
-class UpdateHistoryState(KeySilkCasesPage):
-
-  """ Why: Modern apps often update history state, which currently is janky."""
-
-  def __init__(self, page_set, run_no_page_interactions):
-    super(UpdateHistoryState, self).__init__(
-      name='update_history_state',
-      url='file://key_silk_cases/pushState.html',
-      page_set=page_set, run_no_page_interactions=run_no_page_interactions)
-
-  def RunNavigateSteps(self, action_runner):
-    super(UpdateHistoryState, self).RunNavigateSteps(action_runner)
-    action_runner.ExecuteJavaScript('''
-        window.requestAnimationFrame(function() {
-            window.__history_state_loaded = true;
-          });
-        ''')
-    action_runner.WaitForJavaScriptCondition(
-        'window.__history_state_loaded == true;')
-
-  def PerformPageInteractions(self, action_runner):
-    with action_runner.CreateInteraction('animation_interaction'):
-      action_runner.Wait(5) # JS runs the animation continuously on the page
-
-
-class SilkFinance(KeySilkCasesPage):
-
-  """ Why: Some effects repaint the page, possibly including plenty of text. """
-
-  def __init__(self, page_set, run_no_page_interactions):
-    super(SilkFinance, self).__init__(
-      name='silk_finance',
-      url='file://key_silk_cases/silk_finance.html',
-      page_set=page_set, run_no_page_interactions=run_no_page_interactions)
-
-  def PerformPageInteractions(self, action_runner):
-    with action_runner.CreateInteraction('animation_interaction'):
-      action_runner.Wait(10) # animation runs automatically
-
-
-class PolymerTopeka(KeySilkCasesPage):
-
-  """ Why: Sample Polymer app. """
-
-  def __init__(self, page_set, run_no_page_interactions):
-    super(PolymerTopeka, self).__init__(
-      name='polymer_topeka',
-      url='https://polymer-topeka.appspot.com/',
-      page_set=page_set, run_no_page_interactions=run_no_page_interactions)
-
-  def PerformPageInteractions(self, action_runner):
-    profile = 'html /deep/ topeka-profile /deep/ '
-    first_name = profile + 'paper-input#first /deep/ input'
-    action_runner.WaitForElement(selector=first_name)
-    # Input First Name:
-    action_runner.ExecuteJavaScript('''
-        var fn = document.querySelector({{ first_name }});
-        fn.value = 'Chrome';
-        fn.fire('input');''',
-        first_name=first_name)
-    # Input Last Initial:
-    action_runner.ExecuteJavaScript('''
-        var li = document.querySelector({{ selector }});
-        li.value = 'E';
-        li.fire('input');''',
-        selector='%s paper-input#last /deep/ input' % profile)
-    with action_runner.CreateInteraction('animation_interaction'):
-      # Click the check-mark to login:
-      action_runner.ExecuteJavaScript('''
-          window.topeka_page_transitions = 0;
-          [].forEach.call(document.querySelectorAll(
-              'html /deep/ core-animated-pages'), function(p){
-                  p.addEventListener(
-                      'core-animated-pages-transition-end', function(e) {
-                          window.topeka_page_transitions++;
-                      });
-              });
-          document.querySelector({{ selector }}).fire('tap')''',
-          selector='%s paper-fab' % profile)
-      # Wait for category list to animate in:
-      action_runner.WaitForJavaScriptCondition('''
-          window.topeka_page_transitions === 1''')
-      # Click a category to start a quiz:
-      action_runner.ExecuteJavaScript('''
-          document.querySelector('\
-              html /deep/ core-selector.category-list').fire(
-              'tap',1,document.querySelector('html /deep/ \
-                      div.category-item.red-theme'));''')
-      # Wait for the category splash to animate in:
-      action_runner.WaitForJavaScriptCondition('''
-          window.topeka_page_transitions === 2''')
-      # Click to start the quiz:
-      action_runner.ExecuteJavaScript('''
-          document.querySelector('html /deep/ topeka-category-front-page /deep/\
-              paper-fab').fire('tap');''')
-      action_runner.WaitForJavaScriptCondition('''
-          window.topeka_page_transitions === 4''')
-      # Input a mostly correct answer:
-      action_runner.ExecuteJavaScript('''
-          document.querySelector('html /deep/ topeka-quiz-fill-blank /deep/\
-              input').value = 'arkinsaw';
-          document.querySelector('html /deep/ topeka-quiz-fill-blank /deep/\
-              input').fire('input');
-          document.querySelector('html /deep/ topeka-quizzes /deep/ \
-              paper-fab').fire('tap');''')
-      action_runner.WaitForJavaScriptCondition('''
-          window.topeka_page_transitions === 6''')
-
-class Masonry(KeySilkCasesPage):
-
-  """ Why: Popular layout hack. """
-
-  def __init__(self, page_set, run_no_page_interactions):
-    super(Masonry, self).__init__(
-      name='masonry',
-      url='file://key_silk_cases/masonry.html',
-      page_set=page_set, run_no_page_interactions=run_no_page_interactions)
-
-  def PerformPageInteractions(self, action_runner):
-    with action_runner.CreateInteraction('animation_interaction'):
-      action_runner.ExecuteJavaScript('window.brick()')
-      action_runner.WaitForJavaScriptCondition('window.done')
-
-
-class KeySilkCasesPageSet(story.StorySet):
-
-  """ Pages hand-picked for project Silk. """
-
-  def __init__(self, run_no_page_interactions=False):
-    super(KeySilkCasesPageSet, self).__init__(
-      archive_data_file='data/key_silk_cases.json',
-      cloud_storage_bucket=story.PARTNER_BUCKET)
-
-    self.AddStory(Page1(self, run_no_page_interactions))
-    self.AddStory(Page2(self, run_no_page_interactions))
-    self.AddStory(Page3(self, run_no_page_interactions))
-    self.AddStory(Page4(self, run_no_page_interactions))
-    self.AddStory(Page5(self, run_no_page_interactions))
-    self.AddStory(Page6(self, run_no_page_interactions))
-    self.AddStory(Page7(self, run_no_page_interactions))
-    self.AddStory(Page8(self, run_no_page_interactions))
-    self.AddStory(Page9(self, run_no_page_interactions))
-    self.AddStory(Page10(self, run_no_page_interactions))
-    self.AddStory(Page11(self, run_no_page_interactions))
-    self.AddStory(Page12(self, run_no_page_interactions))
-    self.AddStory(Page13(self, run_no_page_interactions))
-    self.AddStory(Page14(self, run_no_page_interactions))
-    self.AddStory(Page15(self, run_no_page_interactions))
-    self.AddStory(Page16(self, run_no_page_interactions))
-    self.AddStory(Page17(self, run_no_page_interactions))
-    self.AddStory(Page18(self, run_no_page_interactions))
-    # Missing frames during tap interaction; crbug.com/446332
-    self.AddStory(Page19(self, run_no_page_interactions))
-    self.AddStory(Page20(self, run_no_page_interactions))
-    self.AddStory(GwsGoogleExpansion(self, run_no_page_interactions))
-    self.AddStory(GwsBoogieExpansion(self, run_no_page_interactions))
-    # Times out on Windows; crbug.com/338838
-    self.AddStory(Page22(self, run_no_page_interactions))
-    self.AddStory(Page23(self, run_no_page_interactions))
-    self.AddStory(Page24(self, run_no_page_interactions))
-    self.AddStory(Page25(self, run_no_page_interactions))
-    self.AddStory(Page26(self, run_no_page_interactions))
-    self.AddStory(SVGIconRaster(self, run_no_page_interactions))
-    self.AddStory(UpdateHistoryState(self, run_no_page_interactions))
-    self.AddStory(SilkFinance(self, run_no_page_interactions))
-    # Flaky interaction steps on Android; crbug.com/507865
-    self.AddStory(PolymerTopeka(self, run_no_page_interactions))
-    self.AddStory(Masonry(self, run_no_page_interactions))
-
-    for page in self:
-      assert (page.__class__.RunPageInteractions ==
-              KeySilkCasesPage.RunPageInteractions), (
-              'Pages in this page set must not override KeySilkCasesPage\' '
-              'RunPageInteractions method.')
diff --git a/tools/perf/page_sets/pathological_mobile_sites.py b/tools/perf/page_sets/pathological_mobile_sites.py
deleted file mode 100644
index ef2ec9c2..0000000
--- a/tools/perf/page_sets/pathological_mobile_sites.py
+++ /dev/null
@@ -1,48 +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.
-from telemetry.page import page as page_module
-from telemetry.page import shared_page_state
-from telemetry import story
-
-
-class PathologicalMobileSitesPage(page_module.Page):
-
-  def __init__(self, name, url, page_set):
-    super(PathologicalMobileSitesPage, self).__init__(
-        url=url, page_set=page_set,
-        shared_page_state_class=shared_page_state.SharedMobilePageState,
-        name=name)
-
-  def RunPageInteractions(self, action_runner):
-    with action_runner.CreateGestureInteraction('ScrollAction'):
-      action_runner.ScrollPage()
-
-
-class PathologicalMobileSitesPageSet(story.StorySet):
-
-  """Pathologically bad and janky sites on mobile."""
-
-  def __init__(self):
-    super(PathologicalMobileSitesPageSet, self).__init__(
-        archive_data_file='data/pathological_mobile_sites.json',
-        cloud_storage_bucket=story.PARTNER_BUCKET)
-
-    sites = [('cnn_pathological', 'http://edition.cnn.com'),
-             ('espn_pathological', 'http://m.espn.go.com/nhl/rankings'),
-             ('recode_pathological', 'http://recode.net'),
-             ('yahoo_sports_pathological', 'http://sports.yahoo.com/'),
-             ('latimes_pathological', 'http://www.latimes.com'),
-             ('pbs_pathological', 'http://www.pbs.org/newshour/bb/'
-              'much-really-cost-live-city-like-seattle/#the-rundown'),
-             ('guardian_pathological', 'http://www.theguardian.com/politics/2015/mar/09/'
-              'ed-balls-tory-spending-plans-nhs-charging'),
-             ('zdnet_pathological', 'http://www.zdnet.com'),
-             ('wow_wiki_pathological', 'http://www.wowwiki.com/'
-              'World_of_Warcraft:_Mists_of_Pandaria'),
-             ('linkedin_pathological', 'https://www.linkedin.com/in/linustorvalds')]
-
-    for name, site in sites:
-      self.AddStory(PathologicalMobileSitesPage(name=name,
-                                                url=site,
-                                                page_set=self))
diff --git a/tools/perf/page_sets/rendering/key_silk_cases.py b/tools/perf/page_sets/rendering/key_silk_cases.py
new file mode 100644
index 0000000..39837d5
--- /dev/null
+++ b/tools/perf/page_sets/rendering/key_silk_cases.py
@@ -0,0 +1,783 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+from telemetry.page import shared_page_state
+from telemetry import story
+
+from page_sets.rendering import rendering_story
+from page_sets.system_health import platforms
+
+
+class KeySilkPage(rendering_story.RenderingStory):
+  """ Base class for all key silk cases pages."""
+
+  ABSTRACT_STORY = True
+  SUPPORTED_PLATFORMS = platforms.MOBILE_ONLY
+
+  def __init__(self,
+               page_set,
+               shared_page_state_class=shared_page_state.SharedMobilePageState,
+               name_suffix='',
+               extra_browser_args=None):
+    super(KeySilkPage, self).__init__(
+        page_set=page_set,
+        shared_page_state_class=shared_page_state_class,
+        name_suffix=name_suffix,
+        extra_browser_args=extra_browser_args)
+
+  def RunNavigateSteps(self, action_runner):
+    super(KeySilkPage, self).RunNavigateSteps(action_runner)
+    action_runner.Wait(2)
+
+  def RunPageInteractions(self, action_runner):
+    # If a key silk case page wants to customize it actions, it should
+    # overrides the PerformPageInteractions method instead of this method.
+    self.PerformPageInteractions(action_runner)
+
+  def PerformPageInteractions(self, action_runner):
+    """ Perform interactions on page after navigate steps.
+    Override this to define custom actions to be run after navigate steps.
+    """
+    with action_runner.CreateGestureInteraction('ScrollAction'):
+      action_runner.ScrollPage()
+
+
+class Page1(KeySilkPage):
+
+  """ Why: Infinite scroll. Brings out all of our perf issues. """
+
+  BASE_NAME = 'list_recycle_transform'
+  URL = 'http://groupcloned.com/test/plain/list-recycle-transform.html'
+
+  def PerformPageInteractions(self, action_runner):
+    with action_runner.CreateGestureInteraction('ScrollAction'):
+      action_runner.ScrollElement(selector='#scrollable')
+
+
+class Page2(KeySilkPage):
+
+  """ Why: Brings out layer management bottlenecks. """
+
+  BASE_NAME = 'list_animation_simple'
+  URL = 'file://../key_silk_cases/list_animation_simple.html'
+
+  def PerformPageInteractions(self, action_runner):
+    with action_runner.CreateInteraction('SimpleAnimation'):
+      action_runner.Wait(2)
+
+
+class Page3(KeySilkPage):
+
+  """
+  Why: Best-known method for fake sticky. Janks sometimes. Interacts badly with
+  compositor scrolls.
+  """
+
+  BASE_NAME = 'sticky_using_webkit'
+  # pylint: disable=line-too-long
+  URL = 'http://groupcloned.com/test/plain/sticky-using-webkit-backface-visibility.html'
+
+  def PerformPageInteractions(self, action_runner):
+    with action_runner.CreateGestureInteraction('ScrollAction'):
+      action_runner.ScrollElement(selector='#container')
+
+
+class Page4(KeySilkPage):
+
+  """
+  Why: Card expansion: only the card should repaint, but in reality lots of
+  storms happen.
+  """
+
+  BASE_NAME = 'card_expansion'
+  URL = 'http://jsfiddle.net/3yDKh/15/show/'
+
+  def PerformPageInteractions(self, action_runner):
+    with action_runner.CreateInteraction('CardExpansionAnimation'):
+      action_runner.Wait(3)
+
+
+class Page5(KeySilkPage):
+
+  """
+  Why: Card expansion with animated contents, using will-change on the card
+  """
+
+  BASE_NAME = 'card_expansion_animated'
+  URL = 'http://jsfiddle.net/jx5De/14/show/'
+
+  def __init__(self,
+               page_set,
+               shared_page_state_class=shared_page_state.SharedMobilePageState,
+               name_suffix='',
+               extra_browser_args=None):
+    super(Page5, self).__init__(
+        page_set=page_set,
+        shared_page_state_class=shared_page_state_class,
+        name_suffix=name_suffix,
+        extra_browser_args=extra_browser_args)
+
+    self.gpu_raster = True
+
+  def PerformPageInteractions(self, action_runner):
+    with action_runner.CreateInteraction('CardExpansionAnimation'):
+      action_runner.Wait(4)
+
+
+class Page6(KeySilkPage):
+
+  """
+  Why: Card fly-in: It should be fast to animate in a bunch of cards using
+  margin-top and letting layout do the rest.
+  """
+
+  BASE_NAME = 'card_flying'
+  URL = 'http://jsfiddle.net/3yDKh/16/show/'
+
+  def PerformPageInteractions(self, action_runner):
+    with action_runner.CreateInteraction('CardFlyingAnimation'):
+      action_runner.Wait(3)
+
+
+class Page7(KeySilkPage):
+
+  """
+  Why: Image search expands a spacer div when you click an image to accomplish
+  a zoomin effect. Each image has a layer. Even so, this triggers a lot of
+  unnecessary repainting.
+  """
+
+  BASE_NAME = 'zoom_in_animation'
+  URL = 'http://jsfiddle.net/R8DX9/4/show/'
+
+  def PerformPageInteractions(self, action_runner):
+    with action_runner.CreateInteraction('ZoominAnimation'):
+      action_runner.Wait(3)
+
+
+class Page8(KeySilkPage):
+
+  """
+  Why: Swipe to dismiss of an element that has a fixed-position child that is
+  its pseudo-sticky header. Brings out issues with layer creation and
+  repainting.
+  """
+
+  BASE_NAME = 'swipe_to_dismiss'
+  URL = 'http://jsfiddle.net/rF9Gh/7/show/'
+
+  def PerformPageInteractions(self, action_runner):
+    with action_runner.CreateInteraction('SwipeToDismissAnimation'):
+      action_runner.Wait(3)
+
+
+class Page9(KeySilkPage):
+
+  """
+  Why: Horizontal and vertical expansion of a card that is cheap to layout but
+  costly to rasterize.
+  """
+
+  BASE_NAME = 'horizontal_vertical_expansion'
+  URL = 'http://jsfiddle.net/TLXLu/3/show/'
+
+  def __init__(self,
+               page_set,
+               shared_page_state_class=shared_page_state.SharedMobilePageState,
+               name_suffix='',
+               extra_browser_args=None):
+    super(Page9, self).__init__(
+        page_set=page_set,
+        shared_page_state_class=shared_page_state_class,
+        name_suffix=name_suffix,
+        extra_browser_args=extra_browser_args)
+
+    self.gpu_raster = True
+
+  def PerformPageInteractions(self, action_runner):
+    with action_runner.CreateInteraction('CardExpansionAnimation'):
+      action_runner.Wait(4)
+
+
+class Page10(KeySilkPage):
+
+  """
+  Why: Vertical Expansion of a card that is cheap to layout but costly to
+  rasterize.
+  """
+
+  BASE_NAME = 'vertical_expansion'
+  URL = 'http://jsfiddle.net/cKB9D/7/show/'
+
+  def __init__(self,
+               page_set,
+               shared_page_state_class=shared_page_state.SharedMobilePageState,
+               name_suffix='',
+               extra_browser_args=None):
+    super(Page10, self).__init__(
+        page_set=page_set,
+        shared_page_state_class=shared_page_state_class,
+        name_suffix=name_suffix,
+        extra_browser_args=extra_browser_args)
+
+    self.gpu_raster = True
+
+  def PerformPageInteractions(self, action_runner):
+    with action_runner.CreateInteraction('CardExpansionAnimation'):
+      action_runner.Wait(4)
+
+
+class Page11(KeySilkPage):
+
+  """
+  Why: Parallax effect is common on photo-viewer-like applications, overloading
+  software rasterization
+  """
+
+  BASE_NAME = 'parallax_effect'
+  URL = 'http://jsfiddle.net/vBQHH/11/show/'
+
+  def __init__(self,
+               page_set,
+               shared_page_state_class=shared_page_state.SharedMobilePageState,
+               name_suffix='',
+               extra_browser_args=None):
+    super(Page11, self).__init__(
+        page_set=page_set,
+        shared_page_state_class=shared_page_state_class,
+        name_suffix=name_suffix,
+        extra_browser_args=extra_browser_args)
+
+    self.gpu_raster = True
+
+  def PerformPageInteractions(self, action_runner):
+    with action_runner.CreateInteraction('ParallaxAnimation'):
+      action_runner.Wait(4)
+
+
+class Page12(KeySilkPage):
+
+  """ Why: Addressing paint storms during coordinated animations. """
+
+  BASE_NAME = 'coordinated_animation'
+  URL = 'http://jsfiddle.net/ugkd4/10/show/'
+
+  def PerformPageInteractions(self, action_runner):
+    with action_runner.CreateInteraction('CoordinatedAnimation'):
+      action_runner.Wait(5)
+
+
+class Page13(KeySilkPage):
+
+  """ Why: Mask transitions are common mobile use cases. """
+
+  BASE_NAME = 'mask_transition_animation'
+  URL = 'http://jsfiddle.net/xLuvC/1/show/'
+
+  def __init__(self,
+               page_set,
+               shared_page_state_class=shared_page_state.SharedMobilePageState,
+               name_suffix='',
+               extra_browser_args=None):
+    super(Page13, self).__init__(
+        page_set=page_set,
+        shared_page_state_class=shared_page_state_class,
+        name_suffix=name_suffix,
+        extra_browser_args=extra_browser_args)
+
+    self.gpu_raster = True
+
+  def PerformPageInteractions(self, action_runner):
+    with action_runner.CreateInteraction('MaskTransitionAnimation'):
+      action_runner.Wait(4)
+
+
+class Page14(KeySilkPage):
+
+  """ Why: Card expansions with images and text are pretty and common. """
+
+  BASE_NAME = 'card_expansion_images_text'
+  URL = 'http://jsfiddle.net/bNp2h/3/show/'
+
+  def __init__(self,
+               page_set,
+               shared_page_state_class=shared_page_state.SharedMobilePageState,
+               name_suffix='',
+               extra_browser_args=None):
+    super(Page14, self).__init__(
+        page_set=page_set,
+        shared_page_state_class=shared_page_state_class,
+        name_suffix=name_suffix,
+        extra_browser_args=extra_browser_args)
+
+    self.gpu_raster = True
+
+  def PerformPageInteractions(self, action_runner):
+    with action_runner.CreateInteraction('CardExpansionAnimation'):
+      action_runner.Wait(4)
+
+
+class Page15(KeySilkPage):
+
+  """ Why: Coordinated animations for expanding elements. """
+
+  BASE_NAME = 'font_wipe'
+  URL = 'file://../key_silk_cases/font_wipe.html'
+
+  def PerformPageInteractions(self, action_runner):
+    with action_runner.CreateInteraction('CoordinatedAnimation'):
+      action_runner.Wait(5)
+
+
+class Page16(KeySilkPage):
+
+  BASE_NAME = 'swipe_action'
+  URL = 'file://../key_silk_cases/inbox_app.html?swipe_to_dismiss'
+
+  def SwipeToDismiss(self, action_runner):
+    with action_runner.CreateGestureInteraction('SwipeAction'):
+      action_runner.SwipeElement(
+          left_start_ratio=0.8, top_start_ratio=0.2,
+          direction='left', distance=400, speed_in_pixels_per_second=5000,
+          element_function='document.getElementsByClassName("message")[2]')
+
+  def PerformPageInteractions(self, action_runner):
+    self.SwipeToDismiss(action_runner)
+
+
+class Page17(KeySilkPage):
+
+  BASE_NAME = 'stress_hidey_bars'
+  URL = 'file://../key_silk_cases/inbox_app.html?stress_hidey_bars'
+
+  def PerformPageInteractions(self, action_runner):
+    self.StressHideyBars(action_runner)
+
+  def StressHideyBars(self, action_runner):
+    with action_runner.CreateGestureInteraction(
+        'ScrollAction', repeatable=True):
+      action_runner.WaitForElement(selector='#messages')
+      action_runner.ScrollElement(
+        selector='#messages', direction='down', speed_in_pixels_per_second=200)
+    with action_runner.CreateGestureInteraction(
+        'ScrollAction', repeatable=True):
+      action_runner.WaitForElement(selector='#messages')
+      action_runner.ScrollElement(
+          selector='#messages', direction='up', speed_in_pixels_per_second=200)
+    with action_runner.CreateGestureInteraction(
+        'ScrollAction', repeatable=True):
+      action_runner.WaitForElement(selector='#messages')
+      action_runner.ScrollElement(
+          selector='#messages', direction='down',
+          speed_in_pixels_per_second=200)
+
+
+class Page18(KeySilkPage):
+
+  BASE_NAME = 'toggle_drawer'
+  URL = 'file://../key_silk_cases/inbox_app.html?toggle_drawer'
+
+  def PerformPageInteractions(self, action_runner):
+    for _ in xrange(6):
+      self.ToggleDrawer(action_runner)
+
+  def ToggleDrawer(self, action_runner):
+    with action_runner.CreateInteraction('Action_TapAction', repeatable=True):
+      action_runner.TapElement('#menu-button')
+      action_runner.Wait(1)
+
+
+class Page19(KeySilkPage):
+
+  BASE_NAME = 'slide_drawer'
+  URL = 'file://../key_silk_cases/inbox_app.html?slide_drawer'
+
+  def ToggleDrawer(self, action_runner):
+    with action_runner.CreateGestureInteraction('TapAction'):
+      action_runner.TapElement('#menu-button')
+
+    with action_runner.CreateInteraction('Wait'):
+      action_runner.WaitForJavaScriptCondition('''
+          document.getElementById("nav-drawer").active &&
+          document.getElementById("nav-drawer").children[0]
+              .getBoundingClientRect().left == 0''')
+
+  def RunNavigateSteps(self, action_runner):
+    super(Page19, self).RunNavigateSteps(action_runner)
+    action_runner.Wait(2)
+    self.ToggleDrawer(action_runner)
+
+  def PerformPageInteractions(self, action_runner):
+    self.SlideDrawer(action_runner)
+
+  def SlideDrawer(self, action_runner):
+    with action_runner.CreateInteraction('Action_SwipeAction'):
+      action_runner.SwipeElement(
+          left_start_ratio=0.8, top_start_ratio=0.2,
+          direction='left', distance=200,
+          element_function='document.getElementById("nav-drawer").children[0]')
+      action_runner.WaitForJavaScriptCondition(
+          '!document.getElementById("nav-drawer").active')
+
+
+class Page20(KeySilkPage):
+
+  """ Why: Shadow DOM infinite scrolling. """
+
+  BASE_NAME = 'infinite_scrolling'
+  URL = 'file://../key_silk_cases/infinite_scrolling.html'
+
+  def PerformPageInteractions(self, action_runner):
+    with action_runner.CreateGestureInteraction('ScrollAction'):
+      action_runner.ScrollElement(
+          selector='#container', speed_in_pixels_per_second=5000)
+
+
+class GwsExpansionPage(KeySilkPage):
+
+  """Abstract base class for pages that expand Google knowledge panels."""
+
+  ABSTRACT_STORY = True
+
+  def NavigateWait(self, action_runner):
+    super(GwsExpansionPage, self).RunNavigateSteps(action_runner)
+    action_runner.Wait(3)
+
+  def ExpandKnowledgeCard(self, action_runner):
+    # expand card
+    with action_runner.CreateInteraction('Action_TapAction'):
+      action_runner.TapElement(
+          element_function='document.getElementsByClassName("vk_arc")[0]')
+      action_runner.Wait(2)
+
+  def ScrollKnowledgeCardToTop(self, action_runner, card_id):
+    # scroll until the knowledge card is at the top
+    action_runner.ExecuteJavaScript(
+        "document.getElementById({{ card_id }}).scrollIntoView()",
+        card_id=card_id)
+
+  def PerformPageInteractions(self, action_runner):
+    self.ExpandKnowledgeCard(action_runner)
+
+
+class GwsGoogleExpansion(GwsExpansionPage):
+
+  """ Why: Animating height of a complex content card is common. """
+
+  BASE_NAME = 'gws_google_expansion'
+  URL = 'http://www.google.com/#q=google'
+
+  def RunNavigateSteps(self, action_runner):
+    self.NavigateWait(action_runner)
+    self.ScrollKnowledgeCardToTop(action_runner, 'kno-result')
+
+
+class GwsBoogieExpansion(GwsExpansionPage):
+
+  """ Why: Same case as Google expansion but text-heavy rather than image. """
+
+  BASE_NAME = 'gws_boogie_expansion'
+  URL = 'https://www.google.com/search?hl=en&q=define%3Aboogie'
+
+  def RunNavigateSteps(self, action_runner):
+    self.NavigateWait(action_runner)
+    self.ScrollKnowledgeCardToTop(action_runner, 'rso')
+
+
+class Page22(KeySilkPage):
+
+  BASE_NAME = 'basic_stream'
+  URL = 'http://plus.google.com/app/basic/stream'
+
+  def RunNavigateSteps(self, action_runner):
+    super(Page22, self).RunNavigateSteps(action_runner)
+    action_runner.WaitForJavaScriptCondition(
+        'document.getElementsByClassName("fHa").length > 0')
+    action_runner.Wait(2)
+
+  def PerformPageInteractions(self, action_runner):
+    with action_runner.CreateGestureInteraction('ScrollAction'):
+      action_runner.ScrollElement(selector='#mainContent')
+
+
+class Page23(KeySilkPage):
+
+  """
+  Why: Physical simulation demo that does a lot of element.style mutation
+  triggering JS and recalc slowness
+  """
+
+  BASE_NAME = 'physical_simulation'
+  URL = 'http://jsbin.com/UVIgUTa/38/quiet'
+
+  def PerformPageInteractions(self, action_runner):
+    with action_runner.CreateGestureInteraction('ScrollAction',
+                                                repeatable=True):
+      action_runner.ScrollPage(
+          distance_expr='window.innerHeight / 2',
+          direction='down',
+          use_touch=True)
+    with action_runner.CreateGestureInteraction('ScrollAction',
+                                                repeatable=True):
+      action_runner.Wait(1)
+
+
+class Page24(KeySilkPage):
+
+  """
+  Why: Google News: this iOS version is slower than accelerated scrolling
+  """
+
+  BASE_NAME = 'google_news_ios'
+  URL = 'http://mobile-news.sandbox.google.com/news/pt0?scroll'
+
+  def RunNavigateSteps(self, action_runner):
+    super(Page24, self).RunNavigateSteps(action_runner)
+    action_runner.WaitForJavaScriptCondition(
+        'document.getElementById(":h") != null')
+    action_runner.Wait(1)
+
+  def PerformPageInteractions(self, action_runner):
+    with action_runner.CreateGestureInteraction('ScrollAction'):
+      action_runner.ScrollElement(
+          element_function='document.getElementById(":5")',
+          distance=2500,
+          use_touch=True)
+
+
+class Page25(KeySilkPage):
+
+  BASE_NAME = 'mobile_news_sandbox'
+  URL = 'http://mobile-news.sandbox.google.com/news/pt0?swipe'
+
+  def RunNavigateSteps(self, action_runner):
+    super(Page25, self).RunNavigateSteps(action_runner)
+    action_runner.WaitForJavaScriptCondition(
+        'document.getElementById(":h") != null')
+    action_runner.Wait(1)
+
+  def PerformPageInteractions(self, action_runner):
+    with action_runner.CreateGestureInteraction('SwipeAction', repeatable=True):
+      action_runner.SwipeElement(
+          direction='left', distance=100,
+          element_function='document.getElementById(":f")')
+    with action_runner.CreateGestureInteraction('SwipeAction', repeatable=True):
+      action_runner.Wait(1)
+
+
+class Page26(KeySilkPage):
+
+  """ Why: famo.us twitter demo """
+
+  BASE_NAME = 'famo_us_twitter_demo'
+  URL = 'http://s.codepen.io/befamous/fullpage/pFsqb?scroll'
+
+  def RunNavigateSteps(self, action_runner):
+    super(Page26, self).RunNavigateSteps(action_runner)
+    action_runner.WaitForJavaScriptCondition(
+        'document.getElementsByClassName("tweet").length > 0')
+    action_runner.Wait(1)
+
+  def PerformPageInteractions(self, action_runner):
+    # Add a touch-action: none because this page prevent defaults all
+    # touch moves.
+    action_runner.ExecuteJavaScript('''
+        var style = document.createElement("style");
+        document.head.appendChild(style);
+        style.sheet.insertRule("body { touch-action: none }", 0);
+        ''')
+    with action_runner.CreateGestureInteraction('ScrollAction'):
+      action_runner.ScrollPage(distance=5000)
+
+
+class SVGIconRaster(KeySilkPage):
+
+  """ Why: Mutating SVG icons; these paint storm and paint slowly. """
+
+  BASE_NAME = 'svg_icon_raster'
+  URL = 'http://wiltzius.github.io/shape-shifter/'
+
+  def RunNavigateSteps(self, action_runner):
+    super(SVGIconRaster, self).RunNavigateSteps(action_runner)
+    action_runner.WaitForJavaScriptCondition(
+        'loaded = true')
+    action_runner.Wait(1)
+
+  def PerformPageInteractions(self, action_runner):
+    for i in xrange(9):
+      button_func = ('document.getElementById("demo").$.'
+                     'buttons.children[%d]') % i
+      with action_runner.CreateInteraction('Action_TapAction', repeatable=True):
+        action_runner.TapElement(element_function=button_func)
+        action_runner.Wait(1)
+
+
+class UpdateHistoryState(KeySilkPage):
+
+  """ Why: Modern apps often update history state, which currently is janky."""
+
+  BASE_NAME = 'update_history_state'
+  URL = 'file://../key_silk_cases/pushState.html'
+
+  def RunNavigateSteps(self, action_runner):
+    super(UpdateHistoryState, self).RunNavigateSteps(action_runner)
+    action_runner.ExecuteJavaScript('''
+        window.requestAnimationFrame(function() {
+            window.__history_state_loaded = true;
+          });
+        ''')
+    action_runner.WaitForJavaScriptCondition(
+        'window.__history_state_loaded == true;')
+
+  def PerformPageInteractions(self, action_runner):
+    with action_runner.CreateInteraction('animation_interaction'):
+      action_runner.Wait(5) # JS runs the animation continuously on the page
+
+
+class SilkFinance(KeySilkPage):
+
+  """ Why: Some effects repaint the page, possibly including plenty of text. """
+
+  BASE_NAME = 'silk_finance'
+  URL = 'file://../key_silk_cases/silk_finance.html'
+
+  def PerformPageInteractions(self, action_runner):
+    with action_runner.CreateInteraction('animation_interaction'):
+      action_runner.Wait(10) # animation runs automatically
+
+
+class PolymerTopeka(KeySilkPage):
+
+  """ Why: Sample Polymer app. """
+
+  BASE_NAME = 'polymer_topeka'
+  URL = 'https://polymer-topeka.appspot.com/'
+
+  def PerformPageInteractions(self, action_runner):
+    profile = 'html /deep/ topeka-profile /deep/ '
+    first_name = profile + 'paper-input#first /deep/ input'
+    action_runner.WaitForElement(selector=first_name)
+    # Input First Name:
+    action_runner.ExecuteJavaScript('''
+        var fn = document.querySelector({{ first_name }});
+        fn.value = 'Chrome';
+        fn.fire('input');''',
+        first_name=first_name)
+    # Input Last Initial:
+    action_runner.ExecuteJavaScript('''
+        var li = document.querySelector({{ selector }});
+        li.value = 'E';
+        li.fire('input');''',
+        selector='%s paper-input#last /deep/ input' % profile)
+    with action_runner.CreateInteraction('animation_interaction'):
+      # Click the check-mark to login:
+      action_runner.ExecuteJavaScript('''
+          window.topeka_page_transitions = 0;
+          [].forEach.call(document.querySelectorAll(
+              'html /deep/ core-animated-pages'), function(p){
+                  p.addEventListener(
+                      'core-animated-pages-transition-end', function(e) {
+                          window.topeka_page_transitions++;
+                      });
+              });
+          document.querySelector({{ selector }}).fire('tap')''',
+          selector='%s paper-fab' % profile)
+      # Wait for category list to animate in:
+      action_runner.WaitForJavaScriptCondition('''
+          window.topeka_page_transitions === 1''')
+      # Click a category to start a quiz:
+      action_runner.ExecuteJavaScript('''
+          document.querySelector('\
+              html /deep/ core-selector.category-list').fire(
+              'tap',1,document.querySelector('html /deep/ \
+                      div.category-item.red-theme'));''')
+      # Wait for the category splash to animate in:
+      action_runner.WaitForJavaScriptCondition('''
+          window.topeka_page_transitions === 2''')
+      # Click to start the quiz:
+      action_runner.ExecuteJavaScript('''
+          document.querySelector('html /deep/ topeka-category-front-page /deep/\
+              paper-fab').fire('tap');''')
+      action_runner.WaitForJavaScriptCondition('''
+          window.topeka_page_transitions === 4''')
+      # Input a mostly correct answer:
+      action_runner.ExecuteJavaScript('''
+          document.querySelector('html /deep/ topeka-quiz-fill-blank /deep/\
+              input').value = 'arkinsaw';
+          document.querySelector('html /deep/ topeka-quiz-fill-blank /deep/\
+              input').fire('input');
+          document.querySelector('html /deep/ topeka-quizzes /deep/ \
+              paper-fab').fire('tap');''')
+      action_runner.WaitForJavaScriptCondition('''
+          window.topeka_page_transitions === 6''')
+
+class Masonry(KeySilkPage):
+
+  """ Why: Popular layout hack. """
+
+  BASE_NAME = 'masonry'
+  URL = 'file://../key_silk_cases/masonry.html'
+
+  def PerformPageInteractions(self, action_runner):
+    with action_runner.CreateInteraction('animation_interaction'):
+      action_runner.ExecuteJavaScript('window.brick()')
+      action_runner.WaitForJavaScriptCondition('window.done')
+
+
+# TODO(crbug.com/760553):remove this class after smoothness.key_silk_cases
+# benchmark is completely replaced by rendering benchmarks
+class KeySilkCasesPageSet(story.StorySet):
+
+  """ Pages hand-picked for project Silk. """
+
+  def __init__(self):
+    super(KeySilkCasesPageSet, self).__init__(
+      archive_data_file='../data/key_silk_cases.json',
+      cloud_storage_bucket=story.PARTNER_BUCKET)
+
+    page_classes = [
+      Page1,
+      Page2,
+      Page3,
+      Page4,
+      Page5,
+      Page6,
+      Page7,
+      Page8,
+      Page9,
+      Page10,
+      Page11,
+      Page12,
+      Page13,
+      Page14,
+      Page15,
+      Page16,
+      Page17,
+      # Missing frames during tap interaction; crbug.com/446332
+      Page18,
+      Page19,
+      Page20,
+      GwsGoogleExpansion,
+      GwsBoogieExpansion,
+      # Times out on Windows; crbug.com/338838,
+      Page22,
+      Page23,
+      Page24,
+      Page25,
+      Page26,
+      SVGIconRaster,
+      UpdateHistoryState,
+      SilkFinance,
+      # Flaky interaction steps on Android; crbug.com/507865,
+      PolymerTopeka,
+      Masonry
+    ]
+
+    for page_class in page_classes:
+      self.AddStory(page_class(self))
+
+    for page in self:
+      assert (page.__class__.RunPageInteractions ==
+              KeySilkPage.RunPageInteractions), (
+              'Pages in this page set must not override KeySilkPage\' '
+              'RunPageInteractions method.')
diff --git a/tools/perf/page_sets/rendering/pathological_mobile_sites.py b/tools/perf/page_sets/rendering/pathological_mobile_sites.py
new file mode 100644
index 0000000..bf4fb846
--- /dev/null
+++ b/tools/perf/page_sets/rendering/pathological_mobile_sites.py
@@ -0,0 +1,107 @@
+# 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.
+from telemetry.page import shared_page_state
+from telemetry import story
+
+from page_sets.rendering import rendering_story
+from page_sets.system_health import platforms
+
+
+class PathologicalMobileSitesPage(rendering_story.RenderingStory):
+  ABSTRACT_STORY = True
+  SUPPORTED_PLATFORMS = platforms.MOBILE_ONLY
+
+  def __init__(self,
+               page_set,
+               shared_page_state_class=shared_page_state.SharedMobilePageState,
+               name_suffix='',
+               extra_browser_args=None):
+    super(PathologicalMobileSitesPage, self).__init__(
+        page_set=page_set,
+        shared_page_state_class=shared_page_state_class,
+        name_suffix=name_suffix,
+        extra_browser_args=extra_browser_args)
+
+  def RunPageInteractions(self, action_runner):
+    with action_runner.CreateGestureInteraction('ScrollAction'):
+      action_runner.ScrollPage()
+
+
+class CnnPathologicalPage(PathologicalMobileSitesPage):
+  BASE_NAME = 'cnn_pathological'
+  URL = 'http://edition.cnn.com'
+
+
+class EspnPathologicalPage(PathologicalMobileSitesPage):
+  BASE_NAME = 'espn_pathological'
+  URL = 'http://m.espn.go.com/nhl/rankings'
+
+
+class RecodePathologicalPage(PathologicalMobileSitesPage):
+  BASE_NAME = 'recode_pathological'
+  URL = 'http://recode.net'
+
+
+class YahooSportsPathologicalPage(PathologicalMobileSitesPage):
+  BASE_NAME = 'yahoo_sports_pathological'
+  URL = 'http://sports.yahoo.com/'
+
+
+class LaTimesPathologicalPage(PathologicalMobileSitesPage):
+  BASE_NAME = 'latimes_pathological'
+  URL = 'http://www.latimes.com'
+
+
+class PbsPathologicalPage(PathologicalMobileSitesPage):
+  BASE_NAME = 'pbs_pathological'
+  # pylint: disable=line-too-long
+  URL = 'http://www.pbs.org/newshour/bb/much-really-cost-live-city-like-seattle/#the-rundown'
+
+
+class GuardianPathologicalPage(PathologicalMobileSitesPage):
+  BASE_NAME = 'guardian_pathological'
+  # pylint: disable=line-too-long
+  URL = 'http://www.theguardian.com/politics/2015/mar/09/ed-balls-tory-spending-plans-nhs-charging'
+
+
+class ZDNetPathologicalPage(PathologicalMobileSitesPage):
+  BASE_NAME = 'zdnet_pathological'
+  URL = 'http://www.zdnet.com'
+
+
+class WowWikkiPathologicalPage(PathologicalMobileSitesPage):
+  BASE_NAME = 'wow_wiki_pathological'
+  URL = 'http://www.wowwiki.com/World_of_Warcraft:_Mists_of_Pandaria'
+
+
+class LinkedInPathologicalPage(PathologicalMobileSitesPage):
+  BASE_NAME = 'linkedin_pathological'
+  URL = 'https://www.linkedin.com/in/linustorvalds'
+
+
+# TODO(crbug.com/760553):remove this class after
+# smoothness.pathological_mobile_sites benchmark is completely
+# replaced by rendering benchmarks
+class PathologicalMobileSitesPageSet(story.StorySet):
+
+  """Pathologically bad and janky sites on mobile."""
+
+  def __init__(self):
+    super(PathologicalMobileSitesPageSet, self).__init__(
+        archive_data_file='../data/pathological_mobile_sites.json',
+        cloud_storage_bucket=story.PARTNER_BUCKET)
+
+    page_classes = [CnnPathologicalPage,
+                    EspnPathologicalPage,
+                    RecodePathologicalPage,
+                    YahooSportsPathologicalPage,
+                    LaTimesPathologicalPage,
+                    PbsPathologicalPage,
+                    GuardianPathologicalPage,
+                    ZDNetPathologicalPage,
+                    WowWikkiPathologicalPage,
+                    LinkedInPathologicalPage]
+
+    for page_class in page_classes:
+      self.AddStory(page_class(self))
diff --git a/ui/accelerated_widget_mac/ca_transaction_observer.h b/ui/accelerated_widget_mac/ca_transaction_observer.h
index 955b469..a5e22b97 100644
--- a/ui/accelerated_widget_mac/ca_transaction_observer.h
+++ b/ui/accelerated_widget_mac/ca_transaction_observer.h
@@ -60,10 +60,7 @@
 
   static CATransactionCoordinator& Get();
 
-  void Synchronize() {
-    if (@available(macos 10.11, *))
-      SynchronizeImpl();
-  }
+  void Synchronize();
 
   void AddPreCommitObserver(PreCommitObserver*);
   void RemovePreCommitObserver(PreCommitObserver*);
diff --git a/ui/accelerated_widget_mac/ca_transaction_observer.mm b/ui/accelerated_widget_mac/ca_transaction_observer.mm
index d24de62..8e8128b 100644
--- a/ui/accelerated_widget_mac/ca_transaction_observer.mm
+++ b/ui/accelerated_widget_mac/ca_transaction_observer.mm
@@ -8,6 +8,7 @@
 #include "base/trace_event/trace_event.h"
 
 #import <AppKit/AppKit.h>
+#import <CoreFoundation/CoreFoundation.h>
 #import <QuartzCore/QuartzCore.h>
 
 typedef enum {
@@ -25,6 +26,7 @@
 namespace ui {
 
 namespace {
+NSString* kRunLoopMode = @"Chrome CATransactionCoordinator commit handler";
 constexpr auto kPostCommitTimeout = base::TimeDelta::FromMilliseconds(50);
 }  // namespace
 
@@ -34,6 +36,12 @@
 }
 
 void CATransactionCoordinator::SynchronizeImpl() {
+  static bool registeredRunLoopMode = false;
+  if (!registeredRunLoopMode) {
+    CFRunLoopAddCommonMode(CFRunLoopGetCurrent(),
+                           static_cast<CFStringRef>(kRunLoopMode));
+    registeredRunLoopMode = true;
+  }
   if (active_)
     return;
   active_ = true;
@@ -55,8 +63,7 @@
           [start_date dateByAddingTimeInterval:timeout.InSecondsF()];
       if ([deadline isLessThanOrEqualTo:[NSDate date]])
         break;
-      [NSRunLoop.currentRunLoop runMode:NSDefaultRunLoopMode
-                             beforeDate:deadline];
+      [NSRunLoop.currentRunLoop runMode:kRunLoopMode beforeDate:deadline];
     }
   }
                          forPhase:kCATransactionPhasePreCommit];
@@ -76,8 +83,7 @@
         break;
       if ([deadline isLessThanOrEqualTo:[NSDate date]])
         break;
-      [NSRunLoop.currentRunLoop runMode:NSDefaultRunLoopMode
-                             beforeDate:deadline];
+      [NSRunLoop.currentRunLoop runMode:kRunLoopMode beforeDate:deadline];
     }
     active_ = false;
   }
@@ -87,6 +93,11 @@
 CATransactionCoordinator::CATransactionCoordinator() = default;
 CATransactionCoordinator::~CATransactionCoordinator() = default;
 
+void CATransactionCoordinator::Synchronize() {
+  if (@available(macos 10.11, *))
+    SynchronizeImpl();
+}
+
 void CATransactionCoordinator::AddPreCommitObserver(
     PreCommitObserver* observer) {
   pre_commit_observers_.AddObserver(observer);
diff --git a/ui/base/BUILD.gn b/ui/base/BUILD.gn
index d96932d4..5953b4fe 100644
--- a/ui/base/BUILD.gn
+++ b/ui/base/BUILD.gn
@@ -137,6 +137,8 @@
     "cocoa/nsgraphics_context_additions.mm",
     "cocoa/nsview_additions.h",
     "cocoa/nsview_additions.mm",
+    "cocoa/quartz_util.h",
+    "cocoa/quartz_util.mm",
     "cocoa/remote_layer_api.h",
     "cocoa/remote_layer_api.mm",
     "cocoa/scoped_cg_context_smooth_fonts.h",
@@ -584,6 +586,7 @@
     libs += [
       "Accelerate.framework",
       "AppKit.framework",
+      "QuartzCore.framework",
       "AudioUnit.framework",
       "Carbon.framework",
       "CoreVideo.framework",
diff --git a/ui/base/cocoa/quartz_util.h b/ui/base/cocoa/quartz_util.h
new file mode 100644
index 0000000..dd3201f
--- /dev/null
+++ b/ui/base/cocoa/quartz_util.h
@@ -0,0 +1,20 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_BASE_COCOA_QUARTZ_UTIL_H_
+#define UI_BASE_COCOA_QUARTZ_UTIL_H_
+
+#include "ui/base/ui_base_export.h"
+
+namespace ui {
+
+// Calls +[CATransaction begin].
+UI_BASE_EXPORT void BeginCATransaction();
+
+// Calls +[CATransaction commit].
+UI_BASE_EXPORT void CommitCATransaction();
+
+}  // namespace ui
+
+#endif  // UI_BASE_COCOA_QUARTZ_UTIL_H_
diff --git a/ui/base/cocoa/quartz_util.mm b/ui/base/cocoa/quartz_util.mm
new file mode 100644
index 0000000..f9151fc
--- /dev/null
+++ b/ui/base/cocoa/quartz_util.mm
@@ -0,0 +1,19 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/base/cocoa/quartz_util.h"
+
+#include <QuartzCore/QuartzCore.h>
+
+namespace ui {
+
+void BeginCATransaction() {
+  [CATransaction begin];
+}
+
+void CommitCATransaction() {
+  [CATransaction commit];
+}
+
+}  // namespace ui
diff --git a/ui/base/ime/input_method_win_base.cc b/ui/base/ime/input_method_win_base.cc
index 499a1b11..db76ef3d 100644
--- a/ui/base/ime/input_method_win_base.cc
+++ b/ui/base/ime/input_method_win_base.cc
@@ -37,7 +37,7 @@
 std::unique_ptr<InputMethodKeyboardController> CreateKeyboardController(
     HWND toplevel_window_handle) {
   if (base::FeatureList::IsEnabled(features::kInputPaneOnScreenKeyboard) &&
-      base::win::GetVersion() >= base::win::VERSION_WIN10_RS1) {
+      base::win::GetVersion() >= base::win::VERSION_WIN10_RS4) {
     return std::make_unique<OnScreenKeyboardDisplayManagerInputPane>(
         toplevel_window_handle);
   } else if (base::win::GetVersion() >= base::win::VERSION_WIN8) {
diff --git a/ui/ozone/platform/drm/gpu/drm_device.h b/ui/ozone/platform/drm/gpu/drm_device.h
index f6ba1f50..d9fc7aa 100644
--- a/ui/ozone/platform/drm/gpu/drm_device.h
+++ b/ui/ozone/platform/drm/gpu/drm_device.h
@@ -68,7 +68,7 @@
 
     // Depending on the property, this may be an actual value describing the
     // property or an ID of another property.
-    uint32_t value;
+    uint64_t value;
   };
 
   DrmDevice(const base::FilePath& device_path,
diff --git a/ui/webui/resources/cr_components/certificate_manager/certificate_password_decryption_dialog.html b/ui/webui/resources/cr_components/certificate_manager/certificate_password_decryption_dialog.html
index 664a410d..f5dedd66 100644
--- a/ui/webui/resources/cr_components/certificate_manager/certificate_password_decryption_dialog.html
+++ b/ui/webui/resources/cr_components/certificate_manager/certificate_password_decryption_dialog.html
@@ -1,24 +1,28 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
 <link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_input/cr_input.html">
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-input/paper-input.html">
 <link rel="import" href="certificate_shared_css.html">
 <link rel="import" href="certificates_browser_proxy.html">
 
 <dom-module id="certificate-password-decryption-dialog">
   <template>
-    <style include="certificate-shared"></style>
+    <style include="certificate-shared">
+      cr-input {
+        --cr-input-error-display: none;
+      }
+    </style>
     <cr-dialog id="dialog" close-text="[[i18n('close')]]">
       <div slot="title">
         [[i18n('certificateManagerDecryptPasswordTitle')]]
       </div>
       <div slot="body">
-        <paper-input type="password" id="password"
+        <cr-input type="password" id="password"
             label="[[i18n('certificateManagerPassword')]]"
             value="{{password_}}">
-        </paper-input>
+        </cr-input>
       </div>
       <div slot="button-container">
         <paper-button class="cancel-button" on-tap="onCancelTap_">
diff --git a/ui/webui/resources/cr_components/certificate_manager/certificate_password_encryption_dialog.html b/ui/webui/resources/cr_components/certificate_manager/certificate_password_encryption_dialog.html
index a3ad6fd2..6541eeaa 100644
--- a/ui/webui/resources/cr_components/certificate_manager/certificate_password_encryption_dialog.html
+++ b/ui/webui/resources/cr_components/certificate_manager/certificate_password_encryption_dialog.html
@@ -1,15 +1,21 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
 <link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_input/cr_input.html">
+<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-input/paper-input.html">
 <link rel="import" href="certificate_shared_css.html">
 <link rel="import" href="certificates_browser_proxy.html">
 
 <dom-module id="certificate-password-encryption-dialog">
   <template>
     <style include="certificate-shared">
+      cr-input {
+        --cr-input-error-display: none;
+        margin-top: var(--cr-form-field-bottom-spacing);
+      }
+
       .password-buttons {
         margin-bottom: 20px;
       }
@@ -21,13 +27,13 @@
       <div slot="body">
         <div>[[i18n('certificateManagerEncryptPasswordDescription')]]</div>
         <div class="password-buttons">
-          <paper-input type="password" value="{{password_}}" id="password"
+          <cr-input type="password" value="{{password_}}" id="password"
               label="[[i18n('certificateManagerPassword')]]"
-              on-input="validate_"></paper-input>
-          <paper-input type="password"
+              on-input="validate_"></cr-input>
+          <cr-input type="password"
               value="{{confirmPassword_}}" id="confirmPassword"
               label="[[i18n('certificateManagerConfirmPassword')]]"
-              on-input="validate_"></paper-input>
+              on-input="validate_"></cr-input>
         </div>
       </div>
       <div slot="button-container">
diff --git a/ui/webui/resources/cr_components/chromeos/network/BUILD.gn b/ui/webui/resources/cr_components/chromeos/network/BUILD.gn
index b64b9364..ae1eab83 100644
--- a/ui/webui/resources/cr_components/chromeos/network/BUILD.gn
+++ b/ui/webui/resources/cr_components/chromeos/network/BUILD.gn
@@ -9,10 +9,10 @@
     ":network_apnlist",
     ":network_choose_mobile",
     ":network_config",
-    ":network_config_input",
     ":network_config_select",
     ":network_ip_config",
     ":network_nameservers",
+    ":network_password_input",
     ":network_property_list",
     ":network_proxy",
     ":network_proxy_exclusions",
@@ -48,12 +48,6 @@
   extra_sources = [ "$interfaces_path/networking_private_interface.js" ]
 }
 
-js_library("network_config_input") {
-  deps = [
-    "//ui/webui/resources/js:i18n_behavior",
-  ]
-}
-
 js_library("network_config_select") {
   deps = [
     "//ui/webui/resources/js:assert",
@@ -77,6 +71,12 @@
   ]
 }
 
+js_library("network_password_input") {
+  deps = [
+    "//ui/webui/resources/js:i18n_behavior",
+  ]
+}
+
 js_library("network_property_list") {
   deps = [
     "//ui/webui/resources/cr_elements/chromeos/network:cr_onc_types",
@@ -107,7 +107,6 @@
 
 js_library("network_siminfo") {
   deps = [
-    "//third_party/polymer/v1_0/components-chromium/paper-input:paper-input-extracted",
     "//ui/webui/resources/cr_elements/chromeos/network:cr_onc_types",
     "//ui/webui/resources/js:assert",
     "//ui/webui/resources/js:i18n_behavior",
diff --git a/ui/webui/resources/cr_components/chromeos/network/compiled_resources2.gyp b/ui/webui/resources/cr_components/chromeos/network/compiled_resources2.gyp
index 16bf315a..b351da3 100644
--- a/ui/webui/resources/cr_components/chromeos/network/compiled_resources2.gyp
+++ b/ui/webui/resources/cr_components/chromeos/network/compiled_resources2.gyp
@@ -34,13 +34,6 @@
       'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
     },
     {
-      'target_name': 'network_config_input',
-      'dependencies': [
-        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
-      ],
-      'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
-    },
-    {
       'target_name': 'network_config_select',
       'dependencies': [
         '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
@@ -67,6 +60,13 @@
       'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
     },
     {
+      'target_name': 'network_password_input',
+      'dependencies': [
+        '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
+      ],
+      'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
+    },
+    {
       'target_name': 'network_property_list',
       'dependencies': [
         '<(DEPTH)/ui/webui/resources/cr_elements/chromeos/network/compiled_resources2.gyp:cr_onc_types',
@@ -101,7 +101,6 @@
     {
       'target_name': 'network_siminfo',
       'dependencies': [
-        '<(DEPTH)/third_party/polymer/v1_0/components-chromium/paper-input/compiled_resources2.gyp:paper-input-extracted',
         '<(DEPTH)/ui/webui/resources/cr_elements/chromeos/network/compiled_resources2.gyp:cr_onc_types',
         '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
         '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
diff --git a/ui/webui/resources/cr_components/chromeos/network/network_config.html b/ui/webui/resources/cr_components/chromeos/network/network_config.html
index 5b89fa3..341e4bb 100644
--- a/ui/webui/resources/cr_components/chromeos/network/network_config.html
+++ b/ui/webui/resources/cr_components/chromeos/network/network_config.html
@@ -1,12 +1,13 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
 <link rel="import" href="chrome://resources/cr_elements/chromeos/network/cr_onc_types.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_input/cr_input.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_toggle/cr_toggle.html">
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-a11y-keys/iron-a11y-keys.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html">
 <link rel="import" href="network_shared_css.html">
-<link rel="import" href="network_config_input.html">
+<link rel="import" href="network_password_input.html">
 <link rel="import" href="network_config_select.html">
 
 <dom-module id="network-config">
@@ -16,9 +17,9 @@
 
     <!-- SSID (WiFi) -->
     <template is="dom-if" if="[[isType_(NetworkType_.WI_FI, type)]]" restamp>
-      <network-config-input id="ssid" label="[[i18n('OncWiFi-SSID')]]"
+      <cr-input id="ssid" label="[[i18n('OncWiFi-SSID')]]"
           value="{{configProperties_.WiFi.SSID}}" disabled="[[hasGuid_(guid)]]">
-      </network-config-input>
+      </cr-input>
     </template>
 
     <!-- Security (WiFi and Ethernet) -->
@@ -34,51 +35,51 @@
     <!-- Passphrase (WiFi) -->
     <template is="dom-if" if="[[configRequiresPassphrase_(type, security_)]]"
         restamp>
-      <network-config-input label="[[i18n('OncWiFi-Passphrase')]]"
-          value="{{configProperties_.WiFi.Passphrase}}" password>
+      <network-password-input label="[[i18n('OncWiFi-Passphrase')]]"
+          value="{{configProperties_.WiFi.Passphrase}}">
         <iron-a11y-keys keys="enter" on-keys-pressed="connectIfConfigured_">
         </iron-a11y-keys>
-      </network-config-input>
+      </network-password-input>
     </template>
 
     <!-- VPN -->
     <template is="dom-if" if="[[showVpn_]]" restamp>
-      <network-config-input label="[[i18n('OncVPN-Host')]]"
+      <cr-input label="[[i18n('OncVPN-Host')]]"
           value="{{configProperties_.VPN.Host}}">
-      </network-config-input>
-      <network-config-input label="[[i18n('OncName')]]"
+      </cr-input>
+      <cr-input label="[[i18n('OncName')]]"
           value="{{configProperties_.Name}}" disabled="[[hasGuid_(guid)]]">
-      </network-config-input>
+      </cr-input>
       <network-config-select id="outer" label="[[i18n('OncVPN-Type')]]"
           value="{{vpnType_}}" items="[[vpnTypeItems_]]"
           onc-prefix="VPN.Type" disabled="[[hasGuid_(guid)]]">
       </network-config-select>
       <template is="dom-if" if="[[!showVpn_.OpenVPN]]">
-        <network-config-input label="[[i18n('OncVPN-L2TP-Username')]]"
+        <cr-input label="[[i18n('OncVPN-L2TP-Username')]]"
             value="{{configProperties_.VPN.L2TP.Username}}">
-        </network-config-input>
-        <network-config-input label="[[i18n('OncVPN-L2TP-Password')]]"
-            value="{{configProperties_.VPN.L2TP.Password}}" password>
-        </network-config-input>
-        <network-config-input label="[[i18n('OncVPN-IPsec-Group')]]"
+        </cr-input>
+        <network-password-input label="[[i18n('OncVPN-L2TP-Password')]]"
+            value="{{configProperties_.VPN.L2TP.Password}}">
+        </network-password-input>
+        <cr-input label="[[i18n('OncVPN-IPsec-Group')]]"
             value="{{configProperties_.VPN.IPsec.Group}}">
-        </network-config-input>
+        </cr-input>
         <template is="dom-if" if="[[!showVpn_.Cert]]">
-          <network-config-input label="[[i18n('OncVPN-IPsec-PSK')]]"
-              value="{{configProperties_.VPN.IPsec.PSK}}" password>
-          </network-config-input>
+          <network-password-input label="[[i18n('OncVPN-IPsec-PSK')]]"
+              value="{{configProperties_.VPN.IPsec.PSK}}">
+          </network-password-input>
         </template>
       </template>
       <template is="dom-if" if="[[showVpn_.OpenVPN]]">
-        <network-config-input label="[[i18n('OncVPN-OpenVPN-Username')]]"
+        <cr-input label="[[i18n('OncVPN-OpenVPN-Username')]]"
             value="{{configProperties_.VPN.OpenVPN.Username}}">
-        </network-config-input>
-        <network-config-input label="[[i18n('OncVPN-OpenVPN-Password')]]"
-            value="{{configProperties_.VPN.OpenVPN.Password}}" password>
-        </network-config-input>
-        <network-config-input label="[[i18n('OncVPN-OpenVPN-OTP')]]"
+        </cr-input>
+        <network-password-input label="[[i18n('OncVPN-OpenVPN-Password')]]"
+            value="{{configProperties_.VPN.OpenVPN.Password}}">
+        </network-password-input>
+        <cr-input label="[[i18n('OncVPN-OpenVPN-OTP')]]"
             value="{{configProperties_.VPN.OpenVPN.OTP}}">
-        </network-config-input>
+        </cr-input>
       </template>
       <template is="dom-if" if="[[showVpn_.Cert]]">
         <network-config-select id="vpnServerCa"
@@ -117,25 +118,24 @@
           value="{{selectedServerCaHash_}}" items="[[serverCaCerts_]]"
           hidden="[[!showEap_.ServerCA]]" cert-list>
       </network-config-select>
-      <network-config-input label="[[i18n('OncEAP-SubjectMatch')]]"
+      <cr-input label="[[i18n('OncEAP-SubjectMatch')]]"
           value="{{eapProperties_.SubjectMatch}}"
           hidden="[[!showEap_.SubjectMatch]]">
-      </network-config-input>
+      </cr-input>
       <network-config-select id="userCert" label="[[i18n('OncEAP-UserCert')]]"
           value="{{selectedUserCertHash_}}" items="[[userCerts_]]"
           hidden="[[!showEap_.UserCert]]" cert-list>
       </network-config-select>
-      <network-config-input label="[[i18n('OncEAP-Identity')]]"
+      <cr-input label="[[i18n('OncEAP-Identity')]]"
           value="{{eapProperties_.Identity}}" hidden="[[!showEap_.Identity]]">
-      </network-config-input>
-      <network-config-input label="[[i18n('OncEAP-Password')]]"
-          value="{{eapProperties_.Password}}" hidden="[[!showEap_.Password]]"
-          password>
-      </network-config-input>
-      <network-config-input label="[[i18n('OncEAP-AnonymousIdentity')]]"
+      </cr-input>
+      <network-password-input label="[[i18n('OncEAP-Password')]]"
+          value="{{eapProperties_.Password}}" hidden="[[!showEap_.Password]]">
+      </network-password-input>
+      <cr-input label="[[i18n('OncEAP-AnonymousIdentity')]]"
           value="{{eapProperties_.AnonymousIdentity}}"
           hidden="[[!showEap_.AnonymousIdentity]]">
-      </network-config-input>
+      </cr-input>
       <div class="property-box">
         <div id="eapSaveCredentialsLabel" class="start">
           [[i18n('networkConfigSaveCredentials')]]
diff --git a/ui/webui/resources/cr_components/chromeos/network/network_config.js b/ui/webui/resources/cr_components/chromeos/network/network_config.js
index 2077d6a..cf5f094 100644
--- a/ui/webui/resources/cr_components/chromeos/network/network_config.js
+++ b/ui/webui/resources/cr_components/chromeos/network/network_config.js
@@ -405,7 +405,8 @@
   focusFirstInput_: function() {
     Polymer.dom.flush();
     var e = this.$$(
-        'network-config-input:not([disabled]),' +
+        'cr-input:not([disabled]),' +
+        'network-password-input:not([disabled]),' +
         'network-config-select:not([disabled])');
     if (e)
       e.focus();
diff --git a/ui/webui/resources/cr_components/chromeos/network/network_config_input.html b/ui/webui/resources/cr_components/chromeos/network/network_config_input.html
deleted file mode 100644
index b8c7afea..0000000
--- a/ui/webui/resources/cr_components/chromeos/network/network_config_input.html
+++ /dev/null
@@ -1,51 +0,0 @@
-<link rel="import" href="chrome://resources/html/polymer.html">
-<link rel="import" href="chrome://resources/cr_elements/cr_icons_css.html">
-<link rel="import" href="chrome://resources/html/i18n_behavior.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/iron-input/iron-input.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-input/paper-input-container.html">
-<link rel="import" href="network_shared_css.html">
-
-<dom-module id="network-config-input">
-  <template>
-    <style include="network-shared">
-      paper-input-container {
-        --paper-input-container-color: var(--secondary-text-color);
-        --paper-input-container-focus-color: var(--secondary-text-color);
-        --paper-input-container-input-color: var(--primary-text-color);
-        flex: 1;
-      }
-
-      #iconDiv {
-        -webkit-margin-start: var(--cr-icon-button-margin-start);
-        justify-content: center;
-        width: var(--network-control-margin);
-      }
-
-      #iconDiv paper-icon-button-light {
-        margin: 0;
-      }
-    </style>
-
-    <div class="control-box">
-      <paper-input-container always-float-label>
-        <label id="label" slot="label">[[label]]</label>
-        <iron-input slot="input" bind-value="{{value}}">
-          <input tabindex="1" disabled="[[disabled]]" aria-label$="[[label]]"
-              value="{{value::input}}"
-              type="[[getInputType_(password, showPassword)]]">
-        </iron-input>
-      </paper-input-container>
-      <div id="iconDiv">
-        <template is="dom-if" if="[[password]]">
-          <paper-icon-button-light class$="[[getIconClass_(showPassword)]]">
-            <button on-tap="onShowPasswordTap_"
-                title="[[getShowPasswordTitle_(showPassword)]]">
-            </button>
-          </paper-icon-button-light>
-        </template>
-      </div>
-    </div>
-  </template>
-  <script src="network_config_input.js"></script>
-</dom-module>
diff --git a/ui/webui/resources/cr_components/chromeos/network/network_config_select.html b/ui/webui/resources/cr_components/chromeos/network/network_config_select.html
index 32aaf018..a103010 100644
--- a/ui/webui/resources/cr_components/chromeos/network/network_config_select.html
+++ b/ui/webui/resources/cr_components/chromeos/network/network_config_select.html
@@ -5,25 +5,26 @@
 <dom-module id="network-config-select">
   <template>
     <style include="network-shared md-select">
-      #label {
-        color: var(--secondary-text-color);
-      }
-
       .md-select {
         color: var(--primary-text-color);
         width: 100%;
       }
 
-      .control-box {
-        -webkit-padding-end: calc(var(--network-control-margin) +
-            var(--cr-icon-button-margin-start));
+      #label {
+        @apply --cr-form-field-label;
+      }
+
+      #outer {
         align-items: stretch;
+        display: flex;
         flex-direction: column;
         justify-content: center;
+        margin-bottom: var(--cr-form-field-bottom-spacing);
+        padding: 0;
       }
     </style>
 
-    <div class="control-box">
+    <div id="outer">
       <div id="label">[[label]]</div>
       <select class="md-select" disabled="[[disabled]]"
           value="{{value::change}}" aria-label$="[[label]]">
diff --git a/ui/webui/resources/cr_components/chromeos/network/network_ip_config.html b/ui/webui/resources/cr_components/chromeos/network/network_ip_config.html
index cbe21aa..f3a3ca1 100644
--- a/ui/webui/resources/cr_components/chromeos/network/network_ip_config.html
+++ b/ui/webui/resources/cr_components/chromeos/network/network_ip_config.html
@@ -20,7 +20,7 @@
     </div>
     <template is="dom-if" if="[[hasIpConfigFields_(ipConfig_)]]">
       <div class="property-box single-column indented stretch">
-        <network-property-list
+        <network-property-list editable
             fields="[[ipConfigFields_]]" property-dict="[[ipConfig_]]"
             edit-field-types="[[getIPEditFields_(editable, automatic_)]]"
             on-property-change="onIPChange_">
diff --git a/ui/webui/resources/cr_components/chromeos/network/network_nameservers.html b/ui/webui/resources/cr_components/chromeos/network/network_nameservers.html
index c7042cd..9652ec4 100644
--- a/ui/webui/resources/cr_components/chromeos/network/network_nameservers.html
+++ b/ui/webui/resources/cr_components/chromeos/network/network_nameservers.html
@@ -1,12 +1,11 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
 <link rel="import" href="chrome://resources/cr_elements/chromeos/network/cr_onc_types.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_input/cr_input.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_radio_button/cr_radio_button.html">
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
 <link rel="import" href="chrome://resources/html/md_select_css.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/iron-input/iron-input.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-input/paper-input-container.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-radio-group/paper-radio-group.html">
 <link rel="import" href="network_shared_css.html">
 
@@ -17,10 +16,10 @@
         -webkit-margin-start: 4px;
       }
 
-      paper-input-container {
+      cr-input {
         /* Aligns with the start of cr-radio-button's text. */
         -webkit-margin-start: 38px;
-        height: 36px;
+        margin-bottom: 4px;
       }
 
       paper-radio-group {
@@ -85,12 +84,10 @@
             'custom')]]">
           <div class="property-box single-column two-line">
             <template is="dom-repeat" items="[[nameservers_]]">
-              <paper-input-container no-label-float>
-                <iron-input slot="input" bind-value="[[item]]">
-                  <input id="nameserver[[index]]" on-change="onValueChange_"
-                      disabled="[[!canEdit_(editable, nameserversType_)]]">
-                </iron-input>
-              </paper-input-container>
+              <cr-input id="nameserver[[index]]" value="[[item]]"
+                  on-change="onValueChange_"
+                  disabled="[[!canEdit_(editable, nameserversType_)]]">
+              </cr-input>
             </template>
           </div>
         </template>
diff --git a/ui/webui/resources/cr_components/chromeos/network/network_password_input.html b/ui/webui/resources/cr_components/chromeos/network/network_password_input.html
new file mode 100644
index 0000000..48aadd71
--- /dev/null
+++ b/ui/webui/resources/cr_components/chromeos/network/network_password_input.html
@@ -0,0 +1,32 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_icons_css.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_input/cr_input.html">
+<link rel="import" href="chrome://resources/html/i18n_behavior.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
+<link rel="import" href="network_shared_css.html">
+
+<dom-module id="network-password-input">
+  <template>
+    <style include="network-shared">
+      cr-input {
+        width: 100%;
+      }
+
+      paper-icon-button-light {
+        margin: 0;
+        width: var(--network-control-margin);
+      }
+    </style>
+
+    <cr-input label="[[label]]" value="{{value}}" disabled="[[disabled]]"
+        type="[[getInputType_(showPassword)]]">
+      <paper-icon-button-light id="icon" slot="suffix"
+          class$="[[getIconClass_(showPassword)]]">
+        <button on-tap="onShowPasswordTap_"
+            title="[[getShowPasswordTitle_(showPassword)]]">
+        </button>
+      </paper-icon-button-light>
+    </cr-input>
+  </template>
+  <script src="network_password_input.js"></script>
+</dom-module>
diff --git a/ui/webui/resources/cr_components/chromeos/network/network_config_input.js b/ui/webui/resources/cr_components/chromeos/network/network_password_input.js
similarity index 79%
rename from ui/webui/resources/cr_components/chromeos/network/network_config_input.js
rename to ui/webui/resources/cr_components/chromeos/network/network_password_input.js
index 11342ab7..c28ba6b 100644
--- a/ui/webui/resources/cr_components/chromeos/network/network_config_input.js
+++ b/ui/webui/resources/cr_components/chromeos/network/network_password_input.js
@@ -3,15 +3,18 @@
 // found in the LICENSE file.
 
 /**
- * @fileoverview Polymer element for network configuration input fields.
+ * @fileoverview Polymer element for network password input fields.
  */
 Polymer({
-  is: 'network-config-input',
+  is: 'network-password-input',
 
   behaviors: [I18nBehavior],
 
   properties: {
-    label: String,
+    label: {
+      type: String,
+      reflectToAttribute: true,
+    },
 
     disabled: {
       type: Boolean,
@@ -23,8 +26,6 @@
       notify: true,
     },
 
-    password: Boolean,
-
     showPassword: {
       type: Boolean,
       value: false,
@@ -32,7 +33,7 @@
   },
 
   focus: function() {
-    this.$$('input').focus();
+    this.$$('cr-input').focus();
   },
 
   /**
@@ -40,7 +41,7 @@
    * @private
    */
   getInputType_: function() {
-    return (this.password && !this.showPassword) ? 'password' : 'text';
+    return this.showPassword ? 'text' : 'password';
   },
 
   /**
diff --git a/ui/webui/resources/cr_components/chromeos/network/network_property_list.html b/ui/webui/resources/cr_components/chromeos/network/network_property_list.html
index 29fcbf2..9cdcd91 100644
--- a/ui/webui/resources/cr_components/chromeos/network/network_property_list.html
+++ b/ui/webui/resources/cr_components/chromeos/network/network_property_list.html
@@ -1,12 +1,11 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
 <link rel="import" href="chrome://resources/cr_elements/chromeos/network/cr_onc_types.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_input/cr_input.html">
 <link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_network_behavior.html">
 <link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_network_indicator.html">
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/iron-input/iron-input.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-input/paper-input-container.html">
 <link rel="import" href="network_shared_css.html">
 
 <dom-module id="network-property-list">
@@ -17,6 +16,10 @@
         padding: 0;
       }
 
+      cr-input[readonly] {
+        --cr-input-background: transparent;
+      }
+
       cr-policy-network-indicator {
         -webkit-margin-start: var(--settings-controlled-by-spacing);
       }
@@ -28,7 +31,7 @@
         <div class="layout horizontal center">
           <div>[[getPropertyLabel_(item, prefix)]]</div>
           <template is="dom-if" restamp
-              if="[[isEditTypeAny_(item, editFieldTypes)]]">
+              if="[[isEditType_(item, editFieldTypes)]]">
             <cr-policy-network-indicator
                 property="[[getProperty_(item, propertyDict)]]">
             </cr-policy-network-indicator>
@@ -36,23 +39,21 @@
         </div>
         <!-- Uneditable property value -->
         <template is="dom-if" restamp
-            if="[[!isEditable_(item, propertyDict, editFieldTypes)]]">
+            if="[[!showEditable_(item, propertyDict, editFieldTypes)]]">
           <div class="secondary">
             [[getPropertyValue_(item, prefix, propertyDict)]]
           </div>
         </template>
-        <!-- Editable String property value -->
+        <!-- Editable property value -->
         <template is="dom-if" restamp
-            if="[[isEditTypeInput_(item, propertyDict, editFieldTypes)]]">
-          <paper-input-container no-label-float>
-            <iron-input slot="input"
-                bind-value="[[getPropertyValue_(item, prefix, propertyDict)]]">
-              <input id="[[item]]" on-change="onValueChange_"
-                  type="[[getEditInputType_(item, editFieldTypes)]]">
-            </iron-input>
-          </paper-input-container>
+            if="[[showEditable_(item, propertyDict, editFieldTypes)]]">
+          <cr-input id="[[item]]"
+              readonly="[[!isEditable_(item, propertyDict, editFieldTypes)]]"
+              value="[[getPropertyValue_(item, prefix, propertyDict)]]"
+              on-change="onValueChange_"
+              type="[[getEditInputType_(item, editFieldTypes)]]">
+          </cr-input>
         </template>
-        <!-- TODO(stevenjb): Support other types (number, boolean)? -->
       </div>
     </template>
   </template>
diff --git a/ui/webui/resources/cr_components/chromeos/network/network_property_list.js b/ui/webui/resources/cr_components/chromeos/network/network_property_list.js
index 3362979..547f81f 100644
--- a/ui/webui/resources/cr_components/chromeos/network/network_property_list.js
+++ b/ui/webui/resources/cr_components/chromeos/network/network_property_list.js
@@ -14,6 +14,16 @@
 
   properties: {
     /**
+     * If true, all fields are shown as editable. Fields without an edit type
+     * or that are policy enforced will be shown as 'readonly'. Used for lists
+     * with dynamic edit types (e.g. network-ip-config).
+     */
+    editable: {
+      type: Boolean,
+      value: false,
+    },
+
+    /**
      * The dictionary containing the properties to display.
      * @type {!Object|undefined}
      */
@@ -38,7 +48,6 @@
      *       separated list of strings.
      *   'Password' - A string with input type = password.
      *   TODO(stevenjb): Support types with custom validation, e.g. IPAddress.
-     *   TODO(stevenjb): Support 'Number'.
      * When a field changes, the 'property-change' event will be fired with
      * the field name and the new value provided in the event detail.
      */
@@ -140,23 +149,10 @@
   /**
    * @param {string} key The property key.
    * @param {!Object} editFieldTypes
-   * @return {boolean}
+   * @return {boolean} True if the edit type for the key is a valid type.
    * @private
    */
-  isEditTypeAny_: function(key, editFieldTypes) {
-    return editFieldTypes[key] !== undefined;
-  },
-
-  /**
-   * @param {string} key The property key.
-   * @param {!Object} propertyDict
-   * @param {!Object} editFieldTypes
-   * @return {boolean}
-   * @private
-   */
-  isEditTypeInput_: function(key, propertyDict, editFieldTypes) {
-    if (!this.isPropertyEditable_(key, propertyDict))
-      return false;
+  isEditType_: function(key, editFieldTypes) {
     var editType = editFieldTypes[key];
     return editType == 'String' || editType == 'StringArray' ||
         editType == 'Password';
@@ -164,25 +160,35 @@
 
   /**
    * @param {string} key The property key.
-   * @param {!Object} editFieldTypes
-   * @return {string}
-   * @private
-   */
-  getEditInputType_: function(key, editFieldTypes) {
-    return editFieldTypes[key] == 'Password' ? 'password' : 'text';
-  },
-
-  /**
-   * @param {string} key The property key.
    * @param {!Object} propertyDict
    * @param {!Object} editFieldTypes
    * @return {boolean}
    * @private
    */
   isEditable_: function(key, propertyDict, editFieldTypes) {
-    if (!this.isPropertyEditable_(key, propertyDict))
-      return false;
-    return this.isEditTypeAny_(key, editFieldTypes);
+    return this.isEditType_(key, editFieldTypes) &&
+        this.isPropertyEditable_(key, propertyDict);
+  },
+
+  /**
+   * @param {string} key The property key.
+   * @param {!Object} propertyDict
+   * @param {!Object} editFieldTypes
+   * @return {boolean}
+   * @private
+   */
+  showEditable_: function(key, propertyDict, editFieldTypes) {
+    return this.isEditable_(key, propertyDict, editFieldTypes) || this.editable;
+  },
+
+  /**
+   * @param {string} key The property key.
+   * @param {!Object} editFieldTypes
+   * @return {string}
+   * @private
+   */
+  getEditInputType_: function(key, editFieldTypes) {
+    return editFieldTypes[key] == 'Password' ? 'password' : 'text';
   },
 
   /**
diff --git a/ui/webui/resources/cr_components/chromeos/network/network_proxy.html b/ui/webui/resources/cr_components/chromeos/network/network_proxy.html
index cc181083..98d06c9 100644
--- a/ui/webui/resources/cr_components/chromeos/network/network_proxy.html
+++ b/ui/webui/resources/cr_components/chromeos/network/network_proxy.html
@@ -1,6 +1,7 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
 <link rel="import" href="chrome://resources/cr_elements/chromeos/network/cr_onc_types.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_input/cr_input.html">
 <link rel="import" href="chrome://resources/cr_elements/cr_toggle/cr_toggle.html">
 <link rel="import" href="chrome://resources/cr_elements/hidden_style_css.html">
 <link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_network_behavior.html">
@@ -11,8 +12,6 @@
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-input/iron-input.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-input/paper-input-container.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-input/paper-input.html">
 <link rel="import" href="network_proxy_exclusions.html">
 <link rel="import" href="network_proxy_input.html">
 <link rel="import" href="network_shared_css.html">
@@ -28,6 +27,14 @@
         margin: 10px 0;
       }
 
+      #addException {
+        margin-top: 8px;
+      }
+
+      #addException cr-input {
+        margin-bottom: 0;
+      }
+
       #manualProxy {
         -webkit-padding-start: var(--cr-section-padding);
       }
@@ -50,12 +57,12 @@
     <!-- Autoconfiguration (PAC) -->
     <div class="property-box indented"
         hidden$="[[!matches_(proxy_.Type, ProxySettingsType_.PAC)]]">
-      <div>[[i18n('networkProxyAutoConfig')]]</div>
-      <paper-input id="pacInput" no-label-float class="middle"
+      <cr-input id="pacInput" class="flex"
+          label="[[i18n('networkProxyAutoConfig')]]"
           value="{{proxy_.PAC}}" on-change="onPACChange_"
           disabled="[[!isEditable_('PAC', networkProperties, editable,
               useSharedProxies)]]">
-      </paper-input>
+      </cr-input>
     </div>
 
     <!-- Web Proxy Auto Discovery (WPAD) -->
@@ -128,15 +135,12 @@
             editable="[[isEditable_('ExcludeDomains', networkProperties,
                 editable, useSharedProxies)]]">
         </network-proxy-exclusions>
-        <div class="layout horizontal">
-          <paper-input-container no-label-float class="flex">
-            <iron-input slot="input">
-              <input id="proxyExclusion">
-            </iron-input>
-            <iron-a11y-keys keys="enter" slot="add-on"
+        <div id="addException" class="layout horizontal center">
+          <cr-input id="proxyExclusion" class="flex">
+            <iron-a11y-keys keys="enter"
                 on-keys-pressed="onAddProxyExclusionTap_">
             </iron-a11y-keys>
-          </paper-input-container>
+          </cr-input>
           <paper-button on-tap="onAddProxyExclusionTap_">
             [[i18n('networkProxyAddException')]]
           </paper-button>
diff --git a/ui/webui/resources/cr_components/chromeos/network/network_proxy_input.html b/ui/webui/resources/cr_components/chromeos/network/network_proxy_input.html
index 4bda30a..444ab62b 100644
--- a/ui/webui/resources/cr_components/chromeos/network/network_proxy_input.html
+++ b/ui/webui/resources/cr_components/chromeos/network/network_proxy_input.html
@@ -1,15 +1,14 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
 
+<link rel="import" href="chrome://resources/cr_elements/cr_input/cr_input.html">
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/iron-input/iron-input.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-input/paper-input-container.html">
 <link rel="import" href="network_shared_css.html">
 
 <dom-module id="network-proxy-input">
   <template>
     <style include="network-shared">
-      paper-input-container {
-        -webkit-margin-start: 10px;
+      cr-input {
+        margin: 0 var(--cr-button-edge-spacing);
       }
 
       #container {
@@ -33,17 +32,13 @@
     </style>
     <div id="container">
       <div id="label">[[label]]</div>
-      <paper-input-container id="host" no-label-float disabled$="[[!editable]]">
-        <iron-input slot="input" bind-value="{{value.Host}}">
-          <input disabled$="[[!editable]]" on-change="onValueChange_">
-        </iron-input>
-      </paper-input-container>
+      <cr-input id="host" readonly="[[!editable]]" value="{{value.Host}}"
+          on-change="onValueChange_">
+      </cr-input>
       <div>[[i18n('networkProxyPort')]]</div>
-      <paper-input-container id="port" no-label-float disabled$="[[!editable]]">
-        <iron-input slot="input" bind-value="{{value.Port}}">
-          <input disabled$="[[!editable]]" on-change="onValueChange_">
-        </iron-input>
-      </paper-input-container>
+      <cr-input id="port" readonly="[[!editable]]" value="{{value.Port}}"
+          on-change="onValueChange_">
+      </cr-input>
     </div>
   </template>
   <script src="network_proxy_input.js"></script>
diff --git a/ui/webui/resources/cr_components/chromeos/network/network_proxy_input.js b/ui/webui/resources/cr_components/chromeos/network/network_proxy_input.js
index cb22d24e..4f22091b 100644
--- a/ui/webui/resources/cr_components/chromeos/network/network_proxy_input.js
+++ b/ui/webui/resources/cr_components/chromeos/network/network_proxy_input.js
@@ -44,7 +44,7 @@
   },
 
   focus: function() {
-    this.$$('input').focus();
+    this.$$('cr-input').focus();
   },
 
   /**
diff --git a/ui/webui/resources/cr_components/chromeos/network/network_shared_css.html b/ui/webui/resources/cr_components/chromeos/network/network_shared_css.html
index f0b88ca..bb92d28 100644
--- a/ui/webui/resources/cr_components/chromeos/network/network_shared_css.html
+++ b/ui/webui/resources/cr_components/chromeos/network/network_shared_css.html
@@ -10,13 +10,6 @@
         --network-control-margin: 40px;
       }
 
-      .control-box {
-        align-items: center;
-        display: flex;
-        height: 58px;  /* Matches height of paper-input */
-        padding: 0;
-      }
-
       .property-box {
         @apply --cr-section;
         border-top: none;
@@ -61,23 +54,9 @@
         @apply --cr-secondary-text;
       }
 
-      paper-input-container {
-        --paper-input-container-input: {
-          color: var(--paper-grey-600);
-          font-size: inherit;
-          font-weight: 400;
-        };
-        --paper-input-container-input-color: var(--secondary-text-color);
-        margin-bottom: -12px;
-        margin-top: -10px;
-        width: 250px;
-      }
-
-      iron-input input {
-        @apply --paper-input-container-shared-input-style;
-        @apply --cr-secondary-text;
-        font-size: inherit;
-        line-height: inherit;
+      cr-input {
+        --cr-input-error-display: none;
+        margin-bottom: var(--cr-form-field-bottom-spacing);
       }
     </style>
   </template>
diff --git a/ui/webui/resources/cr_components/chromeos/network/network_siminfo.html b/ui/webui/resources/cr_components/chromeos/network/network_siminfo.html
index bbdfe8f..786ffb9 100644
--- a/ui/webui/resources/cr_components/chromeos/network/network_siminfo.html
+++ b/ui/webui/resources/cr_components/chromeos/network/network_siminfo.html
@@ -12,7 +12,7 @@
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
-<link rel="import" href="network_config_input.html">
+<link rel="import" href="network_password_input.html">
 <link rel="import" href="network_shared_css.html">
 
 <dom-module id="network-siminfo">
@@ -95,16 +95,19 @@
         on-close="onEnterPinDialogClose_">
       <div slot="title">[[i18n('networkSimEnterPinTitle')]]</div>
       <div slot="body">
-        <network-config-input id="enterPin" password
+        <network-password-input id="enterPin"
             label="[[i18n('networkSimEnterPin')]]">
           <iron-a11y-keys keys="enter" on-keys-pressed="sendEnterPin_">
           </iron-a11y-keys>
-        </network-config-input>
+        </network-password-input>
         <div class="dialog-error">
           [[getErrorMsg_(error_, networkProperties)]]
         </div>
       </div>
       <div slot="button-container">
+        <paper-button class="cancel-button" on-tap="closeDialogs_">
+          [[i18n('cancel')]]
+        </paper-button>
         <paper-button on-tap="sendEnterPin_" disabled="[[inProgress_]]">
           [[i18n('networkSimEnter')]]
         </paper-button>
@@ -116,22 +119,25 @@
         on-close="onChangePinDialogClose_">
       <div slot="title">[[i18n('networkSimChangePinTitle')]]</div>
       <div slot="body">
-        <network-config-input id="changePinOld" password
+        <network-password-input id="changePinOld"
             label="[[i18n('networkSimEnterOldPin')]]">
-        </network-config-input>
-        <network-config-input id="changePinNew1" password
+        </network-password-input>
+        <network-password-input id="changePinNew1"
             label="[[i18n('networkSimEnterNewPin')]]">
-        </network-config-input>
-        <network-config-input id="changePinNew2" password
+        </network-password-input>
+        <network-password-input id="changePinNew2"
             label="[[i18n('networkSimReEnterNewPin')]]">
           <iron-a11y-keys keys="enter" on-keys-pressed="sendChangePin_">
           </iron-a11y-keys>
-        </network-config-input>
+        </network-password-input>
         <div class="dialog-error">
           [[getErrorMsg_(error_, networkProperties)]]
         </div>
       </div>
       <div slot="button-container">
+        <paper-button class="cancel-button" on-tap="closeDialogs_">
+          [[i18n('cancel')]]
+        </paper-button>
         <paper-button class="action-button" on-tap="sendChangePin_"
             disabled="[[inProgress_]]">
           [[i18n('networkSimChange')]]
@@ -144,16 +150,19 @@
         on-close="onUnlockPinDialogClose_">
       <div slot="title">[[i18n('networkSimLockedTitle')]]</div>
       <div slot="body">
-        <network-config-input id="unlockPin" password
+        <network-password-input id="unlockPin"
             label="[[i18n('networkSimEnterPin')]]">
           <iron-a11y-keys keys="enter" on-keys-pressed="sendUnlockPin_">
           </iron-a11y-keys>
-        </network-config-input>
+        </network-password-input>
         <div class="dialog-error">
           [[getErrorMsg_(error_, networkProperties)]]
         </div>
       </div>
       <div slot="button-container">
+        <paper-button class="cancel-button" on-tap="closeDialogs_">
+          [[i18n('cancel')]]
+        </paper-button>
         <paper-button on-tap="sendUnlockPin_" disabled="[[inProgress_]]">
           [[i18n('networkSimUnlock')]]
         </paper-button>
@@ -168,17 +177,17 @@
         <div>
           Enter the 8-digit PIN Unblocking Key provided by your carrier
         </div>
-        <network-config-input id="unlockPuk" password
+        <network-password-input id="unlockPuk"
             label="[[i18n('networkSimEnterPuk')]]">
-        </network-config-input>
-        <network-config-input id="unlockPin1" password
+        </network-password-input>
+        <network-password-input id="unlockPin1"
             label="[[i18n('networkSimEnterNewPin')]]">
-        </network-config-input>
-        <network-config-input id="unlockPin2" password
+        </network-password-input>
+        <network-password-input id="unlockPin2"
             label="[[i18n('networkSimReEnterNewPin')]]">
           <iron-a11y-keys keys="enter" on-keys-pressed="sendUnlockPuk_">
           </iron-a11y-keys>
-        </network-config-input>
+        </network-password-input>
         <div class="dialog-error">
           [[i18n('networkSimLockedWarning')]]
         </div>
@@ -187,6 +196,9 @@
         </div>
       </div>
       <div slot="button-container">
+        <paper-button class="cancel-button" on-tap="closeDialogs_">
+          [[i18n('cancel')]]
+        </paper-button>
         <paper-button on-tap="sendUnlockPuk_" disabled="[[inProgress_]]">
           [[i18n('networkSimUnlock')]]
         </paper-button>
diff --git a/ui/webui/resources/cr_components/chromeos/network/network_siminfo.js b/ui/webui/resources/cr_components/chromeos/network/network_siminfo.js
index 0a4cfa1..9e1ed25ec 100644
--- a/ui/webui/resources/cr_components/chromeos/network/network_siminfo.js
+++ b/ui/webui/resources/cr_components/chromeos/network/network_siminfo.js
@@ -90,8 +90,15 @@
 
   /** @override */
   detached: function() {
-    if (this.$.enterPinDialog.open)
+    this.closeDialogs_();
+  },
+
+  /** @private */
+  closeDialogs_: function() {
+    if (this.$.enterPinDialog.open) {
+      this.onEnterPinDialogCancel_();
       this.$.enterPinDialog.close();
+    }
     if (this.$.changePinDialog.open)
       this.$.changePinDialog.close();
     if (this.$.unlockPinDialog.open)
@@ -215,7 +222,7 @@
       this.inProgress_ = false;
       if (chrome.runtime.lastError) {
         this.error_ = ErrorType.INCORRECT_PIN;
-        this.$.enterPin.inputElement.select();
+        this.$.enterPin.focus();
       } else {
         this.error_ = ErrorType.NONE;
         this.$.enterPinDialog.close();
@@ -265,7 +272,7 @@
       this.inProgress_ = false;
       if (chrome.runtime.lastError) {
         this.error_ = ErrorType.INCORRECT_PIN;
-        this.$.changePinOld.inputElement.select();
+        this.$.changePinOld.focus();
       } else {
         this.error_ = ErrorType.NONE;
         this.$.changePinDialog.close();
@@ -305,7 +312,7 @@
       this.inProgress_ = false;
       if (chrome.runtime.lastError) {
         this.error_ = ErrorType.INCORRECT_PIN;
-        this.$.unlockPin.inputElement.select();
+        this.$.unlockPin.focus();
       } else {
         this.error_ = ErrorType.NONE;
         this.$.unlockPinDialog.close();
@@ -356,7 +363,7 @@
       this.inProgress_ = false;
       if (chrome.runtime.lastError) {
         this.error_ = ErrorType.INCORRECT_PUK;
-        this.$.unlockPuk.inputElement.select();
+        this.$.unlockPuk.focus();
       } else {
         this.error_ = ErrorType.NONE;
         this.$.unlockPukDialog.close();
diff --git a/ui/webui/resources/cr_components/cr_components_resources.grdp b/ui/webui/resources/cr_components/cr_components_resources.grdp
index 46a47e7..2ff0de40 100644
--- a/ui/webui/resources/cr_components/cr_components_resources.grdp
+++ b/ui/webui/resources/cr_components/cr_components_resources.grdp
@@ -131,14 +131,6 @@
                file="cr_components/chromeos/network/network_config.js"
                type="chrome_html"
                compress="gzip" />
-    <structure name="IDR_WEBUI_CHROMEOS__NETWORK_CONFIG_INPUT_HTML"
-               file="cr_components/chromeos/network/network_config_input.html"
-               type="chrome_html"
-               compress="gzip" />
-    <structure name="IDR_WEBUI_CHROMEOS__NETWORK_CONFIG_INPUT_JS"
-               file="cr_components/chromeos/network/network_config_input.js"
-               type="chrome_html"
-               compress="gzip" />
     <structure name="IDR_WEBUI_CHROMEOS__NETWORK_CONFIG_SELECT_HTML"
                file="cr_components/chromeos/network/network_config_select.html"
                type="chrome_html"
@@ -163,6 +155,14 @@
                file="cr_components/chromeos/network/network_nameservers.js"
                type="chrome_html"
                compress="gzip" />
+    <structure name="IDR_WEBUI_CHROMEOS__NETWORK_PASSWORD_INPUT_HTML"
+               file="cr_components/chromeos/network/network_password_input.html"
+               type="chrome_html"
+               compress="gzip" />
+    <structure name="IDR_WEBUI_CHROMEOS__NETWORK_PASSWORD_INPUT_JS"
+               file="cr_components/chromeos/network/network_password_input.js"
+               type="chrome_html"
+               compress="gzip" />
     <structure name="IDR_WEBUI_CHROMEOS_NETWORK_PROPERTY_LIST_HTML"
                file="cr_components/chromeos/network/network_property_list.html"
                type="chrome_html"
diff --git a/ui/webui/resources/cr_elements/cr_input/cr_input.html b/ui/webui/resources/cr_elements/cr_input/cr_input.html
index 72ae3607..b874956 100644
--- a/ui/webui/resources/cr_elements/cr_input/cr_input.html
+++ b/ui/webui/resources/cr_elements/cr_input/cr_input.html
@@ -26,6 +26,7 @@
       */
 
       :host {
+        --cr-input-background: var(--google-grey-refresh-100);
         --cr-input-error-color: var(--google-red-600);
         --cr-input-focus-color: var(--google-blue-600);
         display: block;
@@ -60,7 +61,7 @@
 
       input {
         -webkit-appearance: none;
-        background: var(--google-grey-refresh-100);
+        background: var(--cr-input-background);
         border: none;
         box-sizing: border-box;
         caret-color: var(--cr-input-focus-color);