diff --git a/DEPS b/DEPS
index ca5677ab..bf29e61b 100644
--- a/DEPS
+++ b/DEPS
@@ -138,7 +138,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': '5ec1b8ff3f45e5bbd9d21cdf60217e417118d0ed',
+  'skia_revision': '84294229864728da3a212401d57d90b46ba60c3c',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
@@ -150,15 +150,15 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
-  'angle_revision': 'f1a40a848d29e696e5e00aea4b9a26940b9df23d',
+  'angle_revision': '28394c2295335929c17bbfe0ab74f923cd234ff2',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
-  'swiftshader_revision': '83818b444fc39e43649616d4b207a5085766d1fa',
+  'swiftshader_revision': '9659e34fb45129efb2d971dee8d581bbb759a125',
   # 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': '6b231685b74bcf5327cb67da1fd0a9ef6e33d7f0',
+  'pdfium_revision': 'bfc6f146c3434be0116fcdfb573b1f174da3c288',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling BoringSSL
   # and whatever else without interference from each other.
@@ -201,7 +201,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling catapult
   # and whatever else without interference from each other.
-  'catapult_revision': '9ba3fdcb3aef252bea4b93c7beb3205a17c3e984',
+  'catapult_revision': '505424fcab37a5b913a96325211f20ddf7897935',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -273,7 +273,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'dawn_revision': '2b82eb290220668cc1459a591558d20d03614800',
+  'dawn_revision': 'fa8190ae44d23df92c1ed67c63f50c6d79843c83',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -807,7 +807,7 @@
 
   # Build tools for Chrome OS. Note: This depends on third_party/pyelftools.
   'src/third_party/chromite': {
-      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'a3211a4a0c9aae0e20b5b106719e14d14081ec64',
+      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'cf248ba6d90b3438b090bfa04889a709a0050a40',
       'condition': 'checkout_linux',
   },
 
@@ -1396,7 +1396,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@0379d9c272d6debca36b43b96f0f088bdefe5e10',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@e8424c6da09b016cdf1c2698e6ab99e26ade8ea6',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/WATCHLISTS b/WATCHLISTS
index dd675039..7c7d3c27 100644
--- a/WATCHLISTS
+++ b/WATCHLISTS
@@ -1455,6 +1455,10 @@
                   '|third_party/blink/renderer/modules/presentation/' \
                   '|third_party/blink/web_tests/(virtual/)?presentation/'
     },
+    'preview_features': {
+      'filepath': 'components/previews/core/previews_features' \
+                  '|components/previews/core/previews_experiments'
+    },
     'print_preview': {
       'filepath': 'chrome/browser/resources/print_preview/' \
                   '|chrome/browser/ui/webui/print_preview/'
@@ -2495,6 +2499,7 @@
     'prerender': ['gavinp+prer@chromium.org',
                   'tburkard+watch@chromium.org'],
     'presentation': ['mfoltz+watch@chromium.org'],
+    'preview_features': ['chrome-lite-pages+watch@google.com'],
     'print_preview': ['rbpotter@chromium.org'],
     'push_messaging': ['peter@chromium.org'],
     'reading_list': ['stkhapugin@chromium.org'],
diff --git a/android_webview/browser/aw_autofill_client.cc b/android_webview/browser/aw_autofill_client.cc
index 12268b42..94ad76d5 100644
--- a/android_webview/browser/aw_autofill_client.cc
+++ b/android_webview/browser/aw_autofill_client.cc
@@ -173,6 +173,10 @@
   NOTIMPLEMENTED();
 }
 
+void AwAutofillClient::CreditCardUploadCompleted() {
+  NOTIMPLEMENTED();
+}
+
 void AwAutofillClient::ConfirmCreditCardFillAssist(
     const autofill::CreditCard& card,
     base::OnceClosure callback) {
diff --git a/android_webview/browser/aw_autofill_client.h b/android_webview/browser/aw_autofill_client.h
index f1eaae9..b3c88a9 100644
--- a/android_webview/browser/aw_autofill_client.h
+++ b/android_webview/browser/aw_autofill_client.h
@@ -110,6 +110,7 @@
       std::unique_ptr<base::DictionaryValue> legal_message,
       SaveCreditCardOptions options,
       UploadSaveCardPromptCallback callback) override;
+  void CreditCardUploadCompleted() override;
   void ConfirmCreditCardFillAssist(const autofill::CreditCard& card,
                                    base::OnceClosure callback) override;
   bool HasCreditCardScanFeature() override;
diff --git a/ash/app_list/app_list_controller_impl.cc b/ash/app_list/app_list_controller_impl.cc
index a81a5aaef..44b1b19 100644
--- a/ash/app_list/app_list_controller_impl.cc
+++ b/ash/app_list/app_list_controller_impl.cc
@@ -700,6 +700,21 @@
       // |ShowEmbeddedAssistantUI(false)|, which will show previous state page
       // in Launcher and make the UI flash.
       if (IsHomeScreenAvailable()) {
+        base::Optional<
+            app_list::ContentsView::ScopedSetActiveStateAnimationDisabler>
+            set_active_state_animation_disabler;
+        // When taking a screenshot by Assistant, we do not want to animate to
+        // the final state. Otherwise the screenshot may have tansient state
+        // during the animation. In tablet mode, we want to go back to
+        // kStateApps immediately, i.e. skipping the animation in
+        // |SetActiveStateInternal|, which are called from
+        // |ShowEmbeddedAssistantUI(false)| and
+        // |ClearSearchAndDeactivateSearchBox()|.
+        if (exit_point == AssistantExitPoint::kScreenshot) {
+          set_active_state_animation_disabler.emplace(
+              presenter_.GetView()->app_list_main_view()->contents_view());
+        }
+
         presenter_.ShowEmbeddedAssistantUI(false);
 
         if (exit_point != AssistantExitPoint::kBackInLauncher) {
@@ -708,6 +723,15 @@
               ->ClearSearchAndDeactivateSearchBox();
         }
       } else if (exit_point != AssistantExitPoint::kBackInLauncher) {
+        base::Optional<
+            app_list::AppListPresenterImpl::ScopedDismissAnimationDisabler>
+            dismiss_animation_disabler;
+        // Similarly, when taking a screenshot by Assistant in clamshell mode,
+        // we do not want to dismiss launcher with animation. Otherwise the
+        // screenshot may have tansient state during the animation.
+        if (exit_point == AssistantExitPoint::kScreenshot)
+          dismiss_animation_disabler.emplace(presenter());
+
         DismissAppList();
       }
 
@@ -1003,7 +1027,6 @@
   }
 
   CloseAssistantUi(AssistantExitPoint::kLauncherClose);
-  model_->SetState(AppListState::kInvalidState);
 
   if (client_)
     client_->ViewClosing();
diff --git a/ash/app_list/views/app_list_view.cc b/ash/app_list/views/app_list_view.cc
index 1de590d..cc3a70d 100644
--- a/ash/app_list/views/app_list_view.cc
+++ b/ash/app_list/views/app_list_view.cc
@@ -1896,6 +1896,15 @@
 void AppListView::OnBoundsAnimationCompleted() {
   const bool was_animation_interrupted =
       GetRemainingBoundsAnimationDistance() != 0;
+
+  // Close embedded Assistant UI if it is open, to reset the
+  // |assistant_page_view| bounds and AppListState.
+  if (app_list_state_ == ash::AppListViewState::kClosed) {
+    auto* contents_view = app_list_main_view()->contents_view();
+    if (contents_view->IsShowingEmbeddedAssistantUI())
+      contents_view->ShowEmbeddedAssistantUI(false);
+  }
+
   // Layout if the animation was completed.
   if (!was_animation_interrupted)
     Layout();
diff --git a/ash/app_list/views/contents_view.cc b/ash/app_list/views/contents_view.cc
index 683af005..7a11403 100644
--- a/ash/app_list/views/contents_view.cc
+++ b/ash/app_list/views/contents_view.cc
@@ -253,10 +253,11 @@
   app_list_pages_[GetActivePageIndex()]->OnWillBeHidden();
 
   // Start animating to the new page.
-  pagination_model_.SelectPage(page_index, animate);
+  const bool should_animate = animate && !set_active_state_without_animation_;
+  pagination_model_.SelectPage(page_index, should_animate);
   ActivePageChanged();
 
-  if (!animate)
+  if (!should_animate)
     Layout();
 }
 
diff --git a/ash/app_list/views/contents_view.h b/ash/app_list/views/contents_view.h
index ed402742..c97a09a 100644
--- a/ash/app_list/views/contents_view.h
+++ b/ash/app_list/views/contents_view.h
@@ -62,6 +62,23 @@
     virtual void OnSearchBoxClearAndDeactivated() = 0;
   };
 
+  // Used to SetActiveState without animations.
+  class ScopedSetActiveStateAnimationDisabler {
+   public:
+    explicit ScopedSetActiveStateAnimationDisabler(ContentsView* contents_view)
+        : contents_view_(contents_view) {
+      contents_view_->set_active_state_without_animation_ = true;
+    }
+    ~ScopedSetActiveStateAnimationDisabler() {
+      contents_view_->set_active_state_without_animation_ = false;
+    }
+
+   private:
+    ContentsView* const contents_view_;
+
+    DISALLOW_COPY_AND_ASSIGN(ScopedSetActiveStateAnimationDisabler);
+  };
+
   explicit ContentsView(AppListView* app_list_view);
   ~ContentsView() override;
 
@@ -293,6 +310,9 @@
   // Manages the pagination for the launcher pages.
   ash::PaginationModel pagination_model_;
 
+  // If true, SetActiveState immediately.
+  bool set_active_state_without_animation_ = false;
+
   base::ObserverList<SearchBoxUpdateObserver> search_box_observers_;
 
   DISALLOW_COPY_AND_ASSIGN(ContentsView);
diff --git a/ash/assistant/assistant_controller.cc b/ash/assistant/assistant_controller.cc
index edf667a..8d5263558 100644
--- a/ash/assistant/assistant_controller.cc
+++ b/ash/assistant/assistant_controller.cc
@@ -168,7 +168,7 @@
     case DeepLinkType::kScreenshot:
       // We close the UI before taking the screenshot as it's probably not the
       // user's intention to include the Assistant in the picture.
-      assistant_ui_controller_.CloseUi(AssistantExitPoint::kUnspecified);
+      assistant_ui_controller_.CloseUi(AssistantExitPoint::kScreenshot);
       Shell::Get()->screenshot_controller()->TakeScreenshotForAllRootWindows();
       break;
     case DeepLinkType::kTaskManager:
diff --git a/ash/assistant/model/assistant_ui_model.h b/ash/assistant/model/assistant_ui_model.h
index 67fba1c..fb0c340 100644
--- a/ash/assistant/model/assistant_ui_model.h
+++ b/ash/assistant/model/assistant_ui_model.h
@@ -49,8 +49,9 @@
   kBackInLauncher = 8,
   kLauncherClose = 9,
   kLauncherOpen = 10,
+  kScreenshot = 11,
   // Special enumerator value used by histogram macros.
-  kMaxValue = kLauncherOpen
+  kMaxValue = kScreenshot
 };
 
 // Enumeration of Assistant UI modes.
diff --git a/ash/drag_drop/drag_drop_controller_unittest.cc b/ash/drag_drop/drag_drop_controller_unittest.cc
index e363e65..bb189893 100644
--- a/ash/drag_drop/drag_drop_controller_unittest.cc
+++ b/ash/drag_drop/drag_drop_controller_unittest.cc
@@ -362,7 +362,7 @@
 };
 
 TEST_F(DragDropControllerTest, DragDropInSingleViewTest) {
-  std::unique_ptr<views::Widget> widget = CreateTestWidget();
+  std::unique_ptr<views::Widget> widget = CreateFramelessWidget();
   DragTestView* drag_view = new DragTestView;
   AddViewToWidgetAndResize(widget.get(), drag_view);
   ui::OSExchangeData data;
@@ -403,7 +403,7 @@
 }
 
 TEST_F(DragDropControllerTest, DragDropWithZeroDragUpdates) {
-  std::unique_ptr<views::Widget> widget = CreateTestWidget();
+  std::unique_ptr<views::Widget> widget = CreateFramelessWidget();
   DragTestView* drag_view = new DragTestView;
   AddViewToWidgetAndResize(widget.get(), drag_view);
   ui::OSExchangeData data;
@@ -556,7 +556,7 @@
 }
 
 TEST_F(DragDropControllerTest, ViewRemovedWhileInDragDropTest) {
-  std::unique_ptr<views::Widget> widget = CreateTestWidget();
+  std::unique_ptr<views::Widget> widget = CreateFramelessWidget();
   std::unique_ptr<DragTestView> drag_view(new DragTestView);
   AddViewToWidgetAndResize(widget.get(), drag_view.get());
   ui::OSExchangeData data;
@@ -619,7 +619,7 @@
   EXPECT_TRUE(cb->IsFormatAvailable(ui::ClipboardFormatType::GetPlainTextType(),
                                     ui::CLIPBOARD_TYPE_COPY_PASTE));
 
-  std::unique_ptr<views::Widget> widget = CreateTestWidget();
+  std::unique_ptr<views::Widget> widget = CreateFramelessWidget();
   DragTestView* drag_view = new DragTestView;
   AddViewToWidgetAndResize(widget.get(), drag_view);
 
@@ -647,7 +647,7 @@
 }
 
 TEST_F(DragDropControllerTest, WindowDestroyedDuringDragDrop) {
-  std::unique_ptr<views::Widget> widget = CreateTestWidget();
+  std::unique_ptr<views::Widget> widget = CreateFramelessWidget();
   DragTestView* drag_view = new DragTestView;
   AddViewToWidgetAndResize(widget.get(), drag_view);
   aura::Window* window = widget->GetNativeView();
@@ -693,7 +693,7 @@
 }
 
 TEST_F(DragDropControllerTest, SyntheticEventsDuringDragDrop) {
-  std::unique_ptr<views::Widget> widget = CreateTestWidget();
+  std::unique_ptr<views::Widget> widget = CreateFramelessWidget();
   DragTestView* drag_view = new DragTestView;
   AddViewToWidgetAndResize(widget.get(), drag_view);
   ui::OSExchangeData data;
@@ -743,7 +743,7 @@
 }
 
 TEST_F(DragDropControllerTest, PressingEscapeCancelsDragDrop) {
-  std::unique_ptr<views::Widget> widget = CreateTestWidget();
+  std::unique_ptr<views::Widget> widget = CreateFramelessWidget();
   DragTestView* drag_view = new DragTestView;
   AddViewToWidgetAndResize(widget.get(), drag_view);
   ui::OSExchangeData data;
@@ -785,7 +785,7 @@
 }
 
 TEST_F(DragDropControllerTest, CaptureLostCancelsDragDrop) {
-  std::unique_ptr<views::Widget> widget = CreateTestWidget();
+  std::unique_ptr<views::Widget> widget = CreateFramelessWidget();
   DragTestView* drag_view = new DragTestView;
   AddViewToWidgetAndResize(widget.get(), drag_view);
   ui::OSExchangeData data;
@@ -897,7 +897,7 @@
 TEST_F(DragDropControllerTest, TouchDragDropCancelsOnLongTap) {
   base::CommandLine::ForCurrentProcess()->AppendSwitch(
       switches::kEnableTouchDragDrop);
-  std::unique_ptr<views::Widget> widget = CreateTestWidget();
+  std::unique_ptr<views::Widget> widget = CreateFramelessWidget();
   DragTestView* drag_view = new DragTestView;
   AddViewToWidgetAndResize(widget.get(), drag_view);
   ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
@@ -923,7 +923,7 @@
 TEST_F(DragDropControllerTest, TouchDragDropLongTapGestureIsForwarded) {
   base::CommandLine::ForCurrentProcess()->AppendSwitch(
       switches::kEnableTouchDragDrop);
-  std::unique_ptr<views::Widget> widget = CreateTestWidget();
+  std::unique_ptr<views::Widget> widget = CreateFramelessWidget();
   DragTestView* drag_view = new DragTestView;
   AddViewToWidgetAndResize(widget.get(), drag_view);
   ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
@@ -974,7 +974,7 @@
   ui::OSExchangeData data;
   data.SetString(base::UTF8ToUTF16("I am being dragged"));
   {
-    std::unique_ptr<views::Widget> widget = CreateTestWidget();
+    std::unique_ptr<views::Widget> widget = CreateFramelessWidget();
     aura::Window* window = widget->GetNativeWindow();
     drag_drop_controller_->StartDragAndDrop(
         data, window->GetRootWindow(), window, gfx::Point(5, 5),
@@ -1005,7 +1005,7 @@
   }
 
   {
-    std::unique_ptr<views::Widget> widget = CreateTestWidget();
+    std::unique_ptr<views::Widget> widget = CreateFramelessWidget();
     aura::Window* window = widget->GetNativeWindow();
     drag_drop_controller_->StartDragAndDrop(
         data, window->GetRootWindow(), window, gfx::Point(405, 405),
@@ -1048,7 +1048,7 @@
 
   ui::OSExchangeData data;
   data.SetString(base::UTF8ToUTF16("I am being dragged"));
-  std::unique_ptr<views::Widget> widget = CreateTestWidget();
+  std::unique_ptr<views::Widget> widget = CreateFramelessWidget();
   aura::Window* window = widget->GetNativeWindow();
   drag_drop_controller_->StartDragAndDrop(
       data, window->GetRootWindow(), window, gfx::Point(5, 5),
@@ -1082,7 +1082,7 @@
       switches::kEnableTouchDragDrop);
   ui::GestureConfiguration::GetInstance()
       ->set_max_touch_move_in_pixels_for_click(1);
-  std::unique_ptr<views::Widget> widget = CreateTestWidget();
+  std::unique_ptr<views::Widget> widget = CreateFramelessWidget();
   DragTestView* drag_view = new DragTestView;
   AddViewToWidgetAndResize(widget.get(), drag_view);
   ui::OSExchangeData data;
@@ -1139,7 +1139,7 @@
   ui::OSExchangeData data;
   data.SetString(base::UTF8ToUTF16("I am being dragged"));
   {
-    std::unique_ptr<views::Widget> widget = CreateTestWidget();
+    std::unique_ptr<views::Widget> widget = CreateFramelessWidget();
     aura::Window* window = widget->GetNativeWindow();
     drag_drop_controller_->StartDragAndDrop(
         data, window->GetRootWindow(), window, gfx::Point(5, 5),
@@ -1166,7 +1166,7 @@
   // Data for the drag.
   ui::OSExchangeData data;
   data.SetString(base::UTF8ToUTF16("I am being dragged"));
-  std::unique_ptr<views::Widget> widget = CreateTestWidget();
+  std::unique_ptr<views::Widget> widget = CreateFramelessWidget();
   aura::Window* window = widget->GetNativeWindow();
 
   // Cannot start a drag when the controller is disabled.
diff --git a/ash/system/message_center/unified_message_center_view_unittest.cc b/ash/system/message_center/unified_message_center_view_unittest.cc
index 1eaaff3..3c17380 100644
--- a/ash/system/message_center/unified_message_center_view_unittest.cc
+++ b/ash/system/message_center/unified_message_center_view_unittest.cc
@@ -244,7 +244,6 @@
   auto* collapse_animation = GetMessageCenterAnimation();
   collapse_animation->SetCurrentValue(0.5);
   message_center_view()->AnimationProgressed(collapse_animation);
-  AnimateMessageListToEnd();
   EXPECT_TRUE(message_center_view()->GetVisible());
 
   // The message center is now hidden after all animations complete.
diff --git a/ash/system/message_center/unified_message_list_view_unittest.cc b/ash/system/message_center/unified_message_list_view_unittest.cc
index ba20b8e..73d47a6 100644
--- a/ash/system/message_center/unified_message_list_view_unittest.cc
+++ b/ash/system/message_center/unified_message_list_view_unittest.cc
@@ -155,7 +155,6 @@
   }
 
   void AnimateToEnd() {
-    EXPECT_TRUE(IsAnimating());
     message_list_view()->animation_->End();
   }
 
@@ -316,10 +315,9 @@
 
   MessageCenter::Get()->RemoveNotification(id1, true /* by_user */);
   FinishSlideOutAnimation();
-  AnimateToMiddle();
+  AnimateToEnd();
   EXPECT_GT(previous_height, message_list_view()->GetPreferredSize().height());
   previous_height = message_list_view()->GetPreferredSize().height();
-  AnimateToEnd();
   // Now it lost separator border.
   bounds1.Inset(gfx::Insets(0, 0, 1, 0));
   EXPECT_EQ(bounds0, GetMessageViewBounds(0));
@@ -327,20 +325,18 @@
 
   MessageCenter::Get()->RemoveNotification(id2, true /* by_user */);
   FinishSlideOutAnimation();
-  AnimateToMiddle();
+  AnimateToEnd();
   EXPECT_GT(previous_height, message_list_view()->GetPreferredSize().height());
   previous_height = message_list_view()->GetPreferredSize().height();
-  AnimateToEnd();
   // Now it lost separator border.
   bounds0.Inset(gfx::Insets(0, 0, 1, 0));
   EXPECT_EQ(bounds0, GetMessageViewBounds(0));
 
   MessageCenter::Get()->RemoveNotification(id0, true /* by_user */);
   FinishSlideOutAnimation();
-  AnimateToMiddle();
+  AnimateToEnd();
   EXPECT_GT(previous_height, message_list_view()->GetPreferredSize().height());
   previous_height = message_list_view()->GetPreferredSize().height();
-  AnimateToEnd();
 
   EXPECT_EQ(0, message_list_view()->GetPreferredSize().height());
 }
diff --git a/ash/wm/desks/desk_mini_view.cc b/ash/wm/desks/desk_mini_view.cc
index 0d8372b..39b82e7 100644
--- a/ash/wm/desks/desk_mini_view.cc
+++ b/ash/wm/desks/desk_mini_view.cc
@@ -85,8 +85,6 @@
   SetInkDropMode(InkDropMode::OFF);
 
   UpdateBorderColor();
-
-  SchedulePaint();
 }
 
 DeskMiniView::~DeskMiniView() {
@@ -149,8 +147,6 @@
       kCloseButtonMargin, kCloseButtonSize.width(), kCloseButtonSize.height());
 
   Button::Layout();
-
-  SchedulePaint();
 }
 
 gfx::Size DeskMiniView::CalculatePreferredSize() const {
diff --git a/base/task/promise/abstract_promise.cc b/base/task/promise/abstract_promise.cc
index 1bafc86..70df142 100644
--- a/base/task/promise/abstract_promise.cc
+++ b/base/task/promise/abstract_promise.cc
@@ -66,6 +66,10 @@
 bool AbstractPromise::InsertDependentOnAnyThread(DependentList::Node* node) {
   scoped_refptr<AbstractPromise>& dependent = node->dependent;
 
+  // Used to ensure no reference to the dependent is kept in case the Promise is
+  // already settled.
+  scoped_refptr<AbstractPromise> dependent_to_release;
+
 #if DCHECK_IS_ON()
   {
     CheckedAutoLock lock(GetCheckedLock());
@@ -80,15 +84,18 @@
       break;
 
     case DependentList::InsertResult::FAIL_PROMISE_RESOLVED:
-      dependent->OnPrerequisiteResolved(this);
+      dependent_to_release = std::move(dependent);
+      dependent_to_release->OnPrerequisiteResolved(this);
       break;
 
     case DependentList::InsertResult::FAIL_PROMISE_REJECTED:
-      dependent->OnPrerequisiteRejected(this);
+      dependent_to_release = std::move(dependent);
+      dependent_to_release->OnPrerequisiteRejected(this);
       break;
 
     case DependentList::InsertResult::FAIL_PROMISE_CANCELED:
-      return dependent->OnPrerequisiteCancelled();
+      dependent_to_release = std::move(dependent);
+      return dependent_to_release->OnPrerequisiteCancelled();
   }
 
   return true;
@@ -444,6 +451,11 @@
   // |dependent_list|. It's sufficient however to simply null our references.
   if (prerequisites_) {
     for (AdjacencyListNode& node : prerequisites_->prerequisite_list) {
+#if DCHECK_IS_ON()
+      // A settled prerequisite should not keep a reference to this.
+      if (node.prerequisite->IsSettled())
+        DCHECK(!node.dependent_node.dependent);
+#endif
       node.prerequisite = nullptr;
     }
   }
@@ -506,6 +518,11 @@
   // |dependent_list|. It's sufficient however to simply null our references.
   if (prerequisites_) {
     for (AdjacencyListNode& node : prerequisites_->prerequisite_list) {
+#if DCHECK_IS_ON()
+      // A settled prerequisite should not keep a reference to this.
+      if (node.prerequisite->IsSettled())
+        DCHECK(!node.dependent_node.dependent);
+#endif
       node.prerequisite = nullptr;
     }
   }
diff --git a/base/task/promise/all_container_executor.h b/base/task/promise/all_container_executor.h
index 9f901d49..786f5b0 100644
--- a/base/task/promise/all_container_executor.h
+++ b/base/task/promise/all_container_executor.h
@@ -24,6 +24,13 @@
     return AbstractPromise::Executor::PrerequisitePolicy::kAll;
   }
 
+  struct VoidResolveType {};
+  struct NonVoidResolveType {};
+
+  using ResolveTypeTag = std::conditional_t<std::is_void<ResolveType>::value,
+                                            VoidResolveType,
+                                            NonVoidResolveType>;
+
   void Execute(AbstractPromise* promise) {
     // All is rejected if any prerequisites are rejected.
     AbstractPromise* first_settled = promise->GetFirstSettledPrerequisite();
@@ -34,22 +41,7 @@
       return;
     }
 
-    const std::vector<AbstractPromise::AdjacencyListNode>* prerequisite_list =
-        promise->prerequisite_list();
-    DCHECK(prerequisite_list);
-    using NonVoidResolveType = ToNonVoidT<ResolveType>;
-    Resolved<std::vector<NonVoidResolveType>> result;
-    result.value.reserve(prerequisite_list->size());
-
-    for (const auto& node : *prerequisite_list) {
-      DCHECK(node.prerequisite->IsResolved());
-      result.value.push_back(
-          ArgMoveSemanticsHelper<
-              NonVoidResolveType,
-              Resolved<NonVoidResolveType>>::Get(node.prerequisite.get()));
-    }
-
-    promise->emplace(std::move(result));
+    ResolveInternal(promise, ResolveTypeTag());
     promise->OnResolved();
   }
 
@@ -70,6 +62,33 @@
 
   bool CanReject() const { return !std::is_same<RejectType, NoReject>::value; }
 #endif
+
+ private:
+  // For containers of Promise<void> there is no point resolving with
+  // std::vector<Void>.
+  void ResolveInternal(AbstractPromise* promise, VoidResolveType) {
+    promise->emplace(Resolved<void>());
+  }
+
+  void ResolveInternal(AbstractPromise* promise, NonVoidResolveType) {
+    using NonVoidResolveType = ToNonVoidT<ResolveType>;
+    Resolved<std::vector<NonVoidResolveType>> result;
+
+    const std::vector<AbstractPromise::AdjacencyListNode>* prerequisite_list =
+        promise->prerequisite_list();
+    DCHECK(prerequisite_list);
+    result.value.reserve(prerequisite_list->size());
+
+    for (const auto& node : *prerequisite_list) {
+      DCHECK(node.prerequisite->IsResolved());
+      result.value.push_back(
+          ArgMoveSemanticsHelper<
+              NonVoidResolveType,
+              Resolved<NonVoidResolveType>>::Get(node.prerequisite.get()));
+    }
+
+    promise->emplace(std::move(result));
+  }
 };
 
 template <typename Container, typename ContainerT>
@@ -78,7 +97,12 @@
 template <typename Container, typename ResolveType, typename RejectType>
 struct AllContainerHelper<Container, Promise<ResolveType, RejectType>> {
   using PromiseResolve = std::vector<ToNonVoidT<ResolveType>>;
-  using PromiseType = Promise<PromiseResolve, RejectType>;
+
+  // As an optimization we don't return std::vector<ResolveType> for void
+  // ResolveType.
+  using PromiseType = std::conditional_t<std::is_void<ResolveType>::value,
+                                         Promise<void, RejectType>,
+                                         Promise<PromiseResolve, RejectType>>;
 
   static PromiseType All(const Location& from_here, const Container& promises) {
     size_t i = 0;
diff --git a/base/task/promise/promise.h b/base/task/promise/promise.h
index 793f605..00d7946 100644
--- a/base/task/promise/promise.h
+++ b/base/task/promise/promise.h
@@ -72,6 +72,16 @@
     return abstract_promise_->IsCanceled();
   }
 
+  bool IsResolvedForTesting() const {
+    DCHECK(abstract_promise_);
+    return abstract_promise_->IsResolved();
+  }
+
+  bool IsRejectedForTesting() const {
+    DCHECK(abstract_promise_);
+    return abstract_promise_->IsRejected();
+  }
+
   // A task to execute |on_reject| is posted on |task_runner| as soon as this
   // promise (or an uncaught ancestor) is rejected. A Promise<> for the return
   // value of |on_reject| is returned.
diff --git a/base/task/promise/promise_unittest.cc b/base/task/promise/promise_unittest.cc
index c7c8b27..21ad2f1 100644
--- a/base/task/promise/promise_unittest.cc
+++ b/base/task/promise/promise_unittest.cc
@@ -1938,17 +1938,20 @@
   promises.push_back(mpr4.promise());
 
   RunLoop run_loop;
-  Promises::All(FROM_HERE, promises)
-      .ThenHere(FROM_HERE, BindLambdaForTesting([&](std::vector<Void> result) {
-                  EXPECT_EQ(4u, result.size());
-                  run_loop.Quit();
-                }));
+  Promise<void> result =
+      Promises::All(FROM_HERE, promises)
+          .ThenHere(FROM_HERE,
+                    BindLambdaForTesting([&]() { run_loop.Quit(); }));
 
   mpr1.Resolve();
   mpr2.Resolve();
   mpr3.Resolve();
+  RunLoop().RunUntilIdle();
+  EXPECT_FALSE(result.IsResolvedForTesting());
+
   mpr4.Resolve();
   run_loop.Run();
+  EXPECT_TRUE(result.IsResolvedForTesting());
 }
 
 TEST_F(PromiseTest, AllVoidIntContainerReject) {
@@ -1965,7 +1968,7 @@
 
   RunLoop run_loop;
   Promises::All(FROM_HERE, promises)
-      .ThenHere(FROM_HERE, BindLambdaForTesting([&](std::vector<Void> result) {
+      .ThenHere(FROM_HERE, BindLambdaForTesting([&]() {
                   FAIL() << "We shouldn't get here, the promise was rejected!";
                   run_loop.Quit();
                 }),
diff --git a/base/task/sequence_manager/task_queue_impl.cc b/base/task/sequence_manager/task_queue_impl.cc
index 50b182428..27402369 100644
--- a/base/task/sequence_manager/task_queue_impl.cc
+++ b/base/task/sequence_manager/task_queue_impl.cc
@@ -28,6 +28,8 @@
       return "control";
     case kHighestPriority:
       return "highest";
+    case kVeryHighPriority:
+      return "very_high";
     case kHighPriority:
       return "high";
     case kNormalPriority:
diff --git a/base/test/android/javatests/src/org/chromium/base/test/BaseJUnit4TestRule.java b/base/test/android/javatests/src/org/chromium/base/test/BaseJUnit4TestRule.java
index 8fb47ad..4e1dbc5 100644
--- a/base/test/android/javatests/src/org/chromium/base/test/BaseJUnit4TestRule.java
+++ b/base/test/android/javatests/src/org/chromium/base/test/BaseJUnit4TestRule.java
@@ -36,12 +36,17 @@
 
                 InMemorySharedPreferencesContext context =
                         BaseChromiumAndroidJUnitRunner.sInMemorySharedPreferencesContext;
-                // Reset Application context in case any tests have replaced it.
-                ContextUtils.initApplicationContextForTests(context);
-                // Ensure all tests start with empty (InMemory)SharedPreferences.
-                context.clearSharedPreferences();
-                // Delete any files that leak state between tests.
-                clearDataDirectory(context);
+                if (context != null) {
+                    // Reset Application context in case any tests have replaced it.
+                    ContextUtils.initApplicationContextForTests(context);
+                    // Ensure all tests start with empty (InMemory)SharedPreferences.
+                    context.clearSharedPreferences();
+                    // Delete any files that leak state between tests.
+                    clearDataDirectory(context);
+                } else {
+                    // Delete any files that leak state between tests.
+                    clearDataDirectory(InstrumentationRegistry.getTargetContext());
+                }
 
                 base.evaluate();
 
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1
index 94c08710..aecd873 100644
--- a/build/fuchsia/linux.sdk.sha1
+++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@
-8911053143154176352
\ No newline at end of file
+8911024139163151344
\ No newline at end of file
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1
index 2c1ae0c..e3b3cce 100644
--- a/build/fuchsia/mac.sdk.sha1
+++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@
-8911052059797671584
\ No newline at end of file
+8911027623584012400
\ No newline at end of file
diff --git a/build/toolchain/toolchain.gni b/build/toolchain/toolchain.gni
index 9a13d296..5101f6e 100644
--- a/build/toolchain/toolchain.gni
+++ b/build/toolchain/toolchain.gni
@@ -18,9 +18,9 @@
   llvm_force_head_revision = false
 
   # Compile with Xcode version of clang instead of hermetic version shipped
-  # with the build. Used on iOS to ship official builds (as they are built
-  # with the version of clang shipped with Xcode).
-  use_xcode_clang = is_ios && is_official_build
+  # with the build. Used to be used iOS for official builds, but is now off by
+  # default for all configurations.
+  use_xcode_clang = false
 
   # Used for binary size analysis.
   generate_linker_map = is_android && is_official_build
diff --git a/cc/BUILD.gn b/cc/BUILD.gn
index 772e7b9..3591777 100644
--- a/cc/BUILD.gn
+++ b/cc/BUILD.gn
@@ -779,7 +779,8 @@
     # TODO(samans): Support more configurations.
     # CFI issue: https://crbug.com/967819
     # x86 issue: https://crbug.com/967831
-    if (use_x11 && target_cpu != "x86" && !is_cfi) {
+    # LSAN issue: https://crbug.com/971325
+    if (use_x11 && target_cpu != "x86" && !is_cfi && !is_lsan) {
       defines = [ "ENABLE_CC_VULKAN_TESTS" ]
     }
   }
diff --git a/cc/layers/layer.cc b/cc/layers/layer.cc
index 24db5b0..591086ec 100644
--- a/cc/layers/layer.cc
+++ b/cc/layers/layer.cc
@@ -24,7 +24,6 @@
 #include "cc/layers/picture_layer.h"
 #include "cc/tiles/frame_viewer_instrumentation.h"
 #include "cc/trees/draw_property_utils.h"
-#include "cc/trees/effect_node.h"
 #include "cc/trees/layer_tree_host.h"
 #include "cc/trees/layer_tree_impl.h"
 #include "cc/trees/mutator_host.h"
@@ -1140,6 +1139,23 @@
   SetNeedsCommit();
 }
 
+RenderSurfaceReason Layer::GetRenderSurfaceReason() const {
+  if (!layer_tree_host_)
+    return RenderSurfaceReason::kNone;
+  PropertyTrees* property_trees = layer_tree_host_->property_trees();
+  DCHECK(!property_trees->needs_rebuild);
+  EffectNode* effect_node =
+      property_trees->effect_tree.Node(this->effect_tree_index());
+
+  // Effect node can also be the effect node of an ancestor layer.
+  // Check if this effect node was created for this layer specifically.
+  if (!effect_node ||
+      (parent_ && this->effect_tree_index() == parent_->effect_tree_index())) {
+    return RenderSurfaceReason::kNone;
+  }
+  return effect_node->render_surface_reason;
+}
+
 void Layer::SetForceRenderSurfaceForTesting(bool force) {
   DCHECK(IsPropertyChangeAllowed());
   if (force_render_surface_for_testing_ == force)
diff --git a/cc/layers/layer.h b/cc/layers/layer.h
index 0474045..daac85f 100644
--- a/cc/layers/layer.h
+++ b/cc/layers/layer.h
@@ -28,6 +28,7 @@
 #include "cc/layers/touch_action_region.h"
 #include "cc/paint/filter_operations.h"
 #include "cc/paint/paint_record.h"
+#include "cc/trees/effect_node.h"
 #include "cc/trees/element_id.h"
 #include "cc/trees/property_tree.h"
 #include "cc/trees/target_property.h"
@@ -508,6 +509,11 @@
   void SetCacheRenderSurface(bool cache_render_surface);
   bool cache_render_surface() const { return cache_render_surface_; }
 
+  // If the layer induces a render surface, this returns the cause for the
+  // render surface. If the layer does not induce a render surface, this returns
+  // kNone.
+  RenderSurfaceReason GetRenderSurfaceReason() const;
+
   // Set or get if the layer and its subtree will be drawn through an
   // intermediate texture, called a RenderSurface. This mimics the need
   // for a RenderSurface that is caused by compositing effects such as masks
diff --git a/cc/trees/layer_tree_host_pixeltest_filters.cc b/cc/trees/layer_tree_host_pixeltest_filters.cc
index d3fd9d03..3e08e35e 100644
--- a/cc/trees/layer_tree_host_pixeltest_filters.cc
+++ b/cc/trees/layer_tree_host_pixeltest_filters.cc
@@ -12,54 +12,6 @@
 #include "cc/test/pixel_comparator.h"
 #include "cc/test/solid_color_content_layer_client.h"
 
-// TODO(crbug.com/971325): Fix memory leaks in tests and re-enable on LSAN.
-#ifdef LEAK_SANITIZER
-#define MAYBE_CroppedFilter DISABLED_CroppedFilter
-#define MAYBE_EnlargedTextureWithAlphaThresholdFilter \
-  DISABLED_EnlargedTextureWithAlphaThresholdFilter
-#define MAYBE_ImageFilterClipped DISABLED_ImageFilterClipped
-#define MAYBE_BlurFilterWithClip DISABLED_BlurFilterWithClip
-#define MAYBE_NullFilter DISABLED_NullFilter
-#define MAYBE_StandardDpi DISABLED_StandardDpi
-#define MAYBE_BackdropFilterBlurOutsets DISABLED_BackdropFilterBlurOutsets
-#define MAYBE_FilterWithGiantCropRect DISABLED_FilterWithGiantCropRect
-#define MAYBE_HiDpi DISABLED_HiDpi
-#define MAYBE_FilterWithGiantCropRectNoClip \
-  DISABLED_FilterWithGiantCropRectNoClip
-#define MAYBE_ImageRenderSurfaceScaled DISABLED_ImageRenderSurfaceScaled
-#define MAYBE_BackdropFilterBlurRect DISABLED_BackdropFilterBlurRect
-#define MAYBE_ImageFilterScaled DISABLED_ImageFilterScaled
-#define MAYBE_StandardDpi DISABLED_StandardDpi
-#define MAYBE_ImageFilterNonZeroOrigin DISABLED_ImageFilterNonZeroOrigin
-#define MAYBE_ZoomFilter DISABLED_ZoomFilter
-#define MAYBE_HiDpi DISABLED_HiDpi
-#define MAYBE_RotatedFilter DISABLED_RotatedFilter
-#define MAYBE_EnlargedTextureWithCropOffsetFilter \
-  DISABLED_EnlargedTextureWithCropOffsetFilter
-#else
-#define MAYBE_CroppedFilter CroppedFilter
-#define MAYBE_EnlargedTextureWithAlphaThresholdFilter \
-  EnlargedTextureWithAlphaThresholdFilter
-#define MAYBE_ImageFilterClipped ImageFilterClipped
-#define MAYBE_BlurFilterWithClip BlurFilterWithClip
-#define MAYBE_NullFilter NullFilter
-#define MAYBE_StandardDpi StandardDpi
-#define MAYBE_BackdropFilterBlurOutsets BackdropFilterBlurOutsets
-#define MAYBE_FilterWithGiantCropRect FilterWithGiantCropRect
-#define MAYBE_HiDpi HiDpi
-#define MAYBE_FilterWithGiantCropRectNoClip FilterWithGiantCropRectNoClip
-#define MAYBE_ImageRenderSurfaceScaled ImageRenderSurfaceScaled
-#define MAYBE_BackdropFilterBlurRect BackdropFilterBlurRect
-#define MAYBE_ImageFilterScaled ImageFilterScaled
-#define MAYBE_StandardDpi StandardDpi
-#define MAYBE_ImageFilterNonZeroOrigin ImageFilterNonZeroOrigin
-#define MAYBE_ZoomFilter ZoomFilter
-#define MAYBE_HiDpi HiDpi
-#define MAYBE_RotatedFilter RotatedFilter
-#define MAYBE_EnlargedTextureWithCropOffsetFilter \
-  EnlargedTextureWithCropOffsetFilter
-#endif
-
 #if !defined(OS_ANDROID)
 
 namespace cc {
@@ -163,7 +115,7 @@
 #endif
                                            ));
 
-TEST_P(LayerTreeHostFiltersPixelTestGPU, MAYBE_BackdropFilterBlurRect) {
+TEST_P(LayerTreeHostFiltersPixelTestGPU, BackdropFilterBlurRect) {
   scoped_refptr<SolidColorLayer> background = CreateSolidColorLayer(
       gfx::Rect(200, 200), SK_ColorWHITE);
 
@@ -245,7 +197,7 @@
       base::FilePath(FILE_PATH_LITERAL("backdrop_filter_blur_rounded.png")));
 }
 
-TEST_P(LayerTreeHostFiltersPixelTestGPU, MAYBE_BackdropFilterBlurOutsets) {
+TEST_P(LayerTreeHostFiltersPixelTestGPU, BackdropFilterBlurOutsets) {
   scoped_refptr<SolidColorLayer> background = CreateSolidColorLayer(
       gfx::Rect(200, 200), SK_ColorWHITE);
 
@@ -446,15 +398,15 @@
 #endif
                                            ));
 
-TEST_P(LayerTreeHostFiltersScaledPixelTest, MAYBE_StandardDpi) {
+TEST_P(LayerTreeHostFiltersScaledPixelTest, StandardDpi) {
   RunPixelTestType(100, 1.f);
 }
 
-TEST_P(LayerTreeHostFiltersScaledPixelTest, MAYBE_HiDpi) {
+TEST_P(LayerTreeHostFiltersScaledPixelTest, HiDpi) {
   RunPixelTestType(50, 2.f);
 }
 
-TEST_P(LayerTreeHostFiltersPixelTest, MAYBE_NullFilter) {
+TEST_P(LayerTreeHostFiltersPixelTest, NullFilter) {
   layer_transforms_should_scale_layer_contents_ = false;
 
   scoped_refptr<SolidColorLayer> foreground =
@@ -468,7 +420,7 @@
                base::FilePath(FILE_PATH_LITERAL("green.png")));
 }
 
-TEST_P(LayerTreeHostFiltersPixelTest, MAYBE_CroppedFilter) {
+TEST_P(LayerTreeHostFiltersPixelTest, CroppedFilter) {
   layer_transforms_should_scale_layer_contents_ = false;
 
   scoped_refptr<SolidColorLayer> foreground =
@@ -487,7 +439,7 @@
                base::FilePath(FILE_PATH_LITERAL("white.png")));
 }
 
-TEST_P(LayerTreeHostFiltersPixelTest, MAYBE_ImageFilterClipped) {
+TEST_P(LayerTreeHostFiltersPixelTest, ImageFilterClipped) {
   scoped_refptr<SolidColorLayer> background =
       CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorYELLOW);
 
@@ -523,7 +475,7 @@
                base::FilePath(FILE_PATH_LITERAL("blue_yellow.png")));
 }
 
-TEST_P(LayerTreeHostFiltersPixelTest, MAYBE_ImageFilterNonZeroOrigin) {
+TEST_P(LayerTreeHostFiltersPixelTest, ImageFilterNonZeroOrigin) {
   scoped_refptr<SolidColorLayer> background =
       CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorYELLOW);
 
@@ -555,7 +507,7 @@
                base::FilePath(FILE_PATH_LITERAL("blue_yellow.png")));
 }
 
-TEST_P(LayerTreeHostFiltersPixelTest, MAYBE_ImageFilterScaled) {
+TEST_P(LayerTreeHostFiltersPixelTest, ImageFilterScaled) {
   scoped_refptr<SolidColorLayer> background =
       CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorWHITE);
 
@@ -682,7 +634,7 @@
                    .InsertBeforeExtensionASCII(GetRendererSuffix()));
 }
 
-TEST_P(LayerTreeHostFiltersPixelTest, MAYBE_ImageRenderSurfaceScaled) {
+TEST_P(LayerTreeHostFiltersPixelTest, ImageRenderSurfaceScaled) {
   // A filter will cause a render surface to be used.  Here we force the
   // render surface on, and scale the result to make sure that we rasterize at
   // the correct resolution.
@@ -733,7 +685,7 @@
           .InsertBeforeExtensionASCII(GetRendererSuffix()));
 }
 
-TEST_P(LayerTreeHostFiltersPixelTest, MAYBE_ZoomFilter) {
+TEST_P(LayerTreeHostFiltersPixelTest, ZoomFilter) {
   scoped_refptr<SolidColorLayer> root =
       CreateSolidColorLayer(gfx::Rect(300, 300), SK_ColorWHITE);
 
@@ -802,7 +754,7 @@
                    .InsertBeforeExtensionASCII(GetRendererSuffix()));
 }
 
-TEST_P(LayerTreeHostFiltersPixelTest, MAYBE_RotatedFilter) {
+TEST_P(LayerTreeHostFiltersPixelTest, RotatedFilter) {
   scoped_refptr<SolidColorLayer> background =
       CreateSolidColorLayer(gfx::Rect(300, 300), SK_ColorWHITE);
 
@@ -935,8 +887,7 @@
       base::FilePath(FILE_PATH_LITERAL("translated_blue_green_alpha.png")));
 }
 
-TEST_P(LayerTreeHostFiltersPixelTest,
-       MAYBE_EnlargedTextureWithAlphaThresholdFilter) {
+TEST_P(LayerTreeHostFiltersPixelTest, EnlargedTextureWithAlphaThresholdFilter) {
   // Rectangles chosen so that if flipped, the test will fail.
   gfx::Rect rect1(10, 10, 10, 15);
   gfx::Rect rect2(20, 25, 70, 65);
@@ -976,8 +927,7 @@
       base::FilePath(FILE_PATH_LITERAL("enlarged_texture_on_threshold.png")));
 }
 
-TEST_P(LayerTreeHostFiltersPixelTest,
-       MAYBE_EnlargedTextureWithCropOffsetFilter) {
+TEST_P(LayerTreeHostFiltersPixelTest, EnlargedTextureWithCropOffsetFilter) {
   // Rectangles chosen so that if flipped, the test will fail.
   gfx::Rect rect1(10, 10, 10, 15);
   gfx::Rect rect2(20, 25, 70, 65);
@@ -1015,7 +965,7 @@
       base::FilePath(FILE_PATH_LITERAL("enlarged_texture_on_crop_offset.png")));
 }
 
-TEST_P(LayerTreeHostFiltersPixelTest, MAYBE_BlurFilterWithClip) {
+TEST_P(LayerTreeHostFiltersPixelTest, BlurFilterWithClip) {
   scoped_refptr<SolidColorLayer> child1 =
       CreateSolidColorLayer(gfx::Rect(200, 200), SK_ColorBLUE);
   scoped_refptr<SolidColorLayer> child2 =
@@ -1068,14 +1018,14 @@
                    .InsertBeforeExtensionASCII(GetRendererSuffix()));
 }
 
-TEST_P(LayerTreeHostFiltersPixelTestGPU, MAYBE_FilterWithGiantCropRect) {
+TEST_P(LayerTreeHostFiltersPixelTestGPU, FilterWithGiantCropRect) {
   scoped_refptr<SolidColorLayer> tree = BuildFilterWithGiantCropRect(true);
   RunPixelTest(
       renderer_type(), tree,
       base::FilePath(FILE_PATH_LITERAL("filter_with_giant_crop_rect.png")));
 }
 
-TEST_P(LayerTreeHostFiltersPixelTestGPU, MAYBE_FilterWithGiantCropRectNoClip) {
+TEST_P(LayerTreeHostFiltersPixelTestGPU, FilterWithGiantCropRectNoClip) {
   scoped_refptr<SolidColorLayer> tree = BuildFilterWithGiantCropRect(false);
   RunPixelTest(
       renderer_type(), tree,
@@ -1132,12 +1082,12 @@
 #endif
                                            ));
 
-TEST_P(BackdropFilterWithDeviceScaleFactorTest, MAYBE_StandardDpi) {
+TEST_P(BackdropFilterWithDeviceScaleFactorTest, StandardDpi) {
   RunPixelTestType(
       1.f, base::FilePath(FILE_PATH_LITERAL("offset_backdrop_filter_1x.png")));
 }
 
-TEST_P(BackdropFilterWithDeviceScaleFactorTest, MAYBE_HiDpi) {
+TEST_P(BackdropFilterWithDeviceScaleFactorTest, HiDpi) {
   RunPixelTestType(
       2.f, base::FilePath(FILE_PATH_LITERAL("offset_backdrop_filter_2x.png")));
 }
diff --git a/chrome/VERSION b/chrome/VERSION
index 66f21e55..a63656e2 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=77
 MINOR=0
-BUILD=3821
+BUILD=3822
 PATCH=0
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni
index 447c1e4..5fcb11a 100644
--- a/chrome/android/chrome_java_sources.gni
+++ b/chrome/android/chrome_java_sources.gni
@@ -62,7 +62,7 @@
   "java/src/org/chromium/chrome/browser/SynchronousInitializationActivity.java",
   "java/src/org/chromium/chrome/browser/TabThemeColorProvider.java",
   "java/src/org/chromium/chrome/browser/ThemeColorProvider.java",
-  "java/src/org/chromium/chrome/browser/UrlConstants.java",
+  "java/src/org/chromium/chrome/browser/util/UrlConstants.java",
   "java/src/org/chromium/chrome/browser/UsbChooserDialog.java",
   "java/src/org/chromium/chrome/browser/WarmupManager.java",
   "java/src/org/chromium/chrome/browser/WebContentsFactory.java",
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/GridTabSwitcherMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/GridTabSwitcherMediator.java
index a7b154ed..94ba7a3 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/GridTabSwitcherMediator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/GridTabSwitcherMediator.java
@@ -22,7 +22,6 @@
 import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeFeatureList;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.compositor.CompositorViewHolder;
 import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager;
 import org.chromium.chrome.browser.fullscreen.FullscreenManager;
@@ -41,6 +40,7 @@
 import org.chromium.chrome.browser.tasks.ReturnToChromeExperimentsUtil;
 import org.chromium.chrome.browser.tasks.tabgroup.TabGroupModelFilter;
 import org.chromium.chrome.browser.util.FeatureUtilities;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.content_public.browser.LoadUrlParams;
 import org.chromium.ui.modelutil.PropertyModel;
 
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediator.java
index b20eed33b..79ad0ba 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediator.java
@@ -8,7 +8,6 @@
 import android.support.annotation.Nullable;
 import android.view.View;
 
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tabmodel.EmptyTabModelObserver;
 import org.chromium.chrome.browser.tabmodel.TabCreatorManager;
@@ -16,6 +15,7 @@
 import org.chromium.chrome.browser.tabmodel.TabModelObserver;
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
 import org.chromium.chrome.browser.tabmodel.TabSelectionType;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.chrome.browser.widget.ScrimView;
 import org.chromium.content_public.browser.LoadUrlParams;
 import org.chromium.ui.modelutil.PropertyModel;
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridSheetMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridSheetMediator.java
index a98353a..183e3e9 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridSheetMediator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridSheetMediator.java
@@ -11,7 +11,6 @@
 import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ThemeColorProvider;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tabmodel.EmptyTabModelObserver;
 import org.chromium.chrome.browser.tabmodel.TabCreatorManager;
@@ -19,6 +18,7 @@
 import org.chromium.chrome.browser.tabmodel.TabModelObserver;
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
 import org.chromium.chrome.browser.tabmodel.TabSelectionType;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.chrome.browser.widget.bottomsheet.BottomSheet.BottomSheetContent;
 import org.chromium.chrome.browser.widget.bottomsheet.BottomSheet.StateChangeReason;
 import org.chromium.chrome.browser.widget.bottomsheet.BottomSheetController;
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediator.java
index 09ad36d..dee69c376 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediator.java
@@ -7,7 +7,6 @@
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.chrome.browser.ThemeColorProvider;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.compositor.layouts.EmptyOverviewModeObserver;
 import org.chromium.chrome.browser.compositor.layouts.OverviewModeBehavior;
 import org.chromium.chrome.browser.tab.Tab;
@@ -22,6 +21,7 @@
 import org.chromium.chrome.browser.tabmodel.TabModelSelectorTabObserver;
 import org.chromium.chrome.browser.tabmodel.TabSelectionType;
 import org.chromium.chrome.browser.toolbar.bottom.BottomControlsCoordinator;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.content_public.browser.LoadUrlParams;
 import org.chromium.ui.modelutil.PropertyModel;
 
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/GridTabSwitcherLayoutPerfTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/GridTabSwitcherLayoutPerfTest.java
index 177934d..c64ba65 100644
--- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/GridTabSwitcherLayoutPerfTest.java
+++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/GridTabSwitcherLayoutPerfTest.java
@@ -8,8 +8,8 @@
 import static org.junit.Assert.assertTrue;
 
 import static org.chromium.base.test.util.CallbackHelper.WAIT_TIMEOUT_SECONDS;
-import static org.chromium.chrome.browser.UrlConstants.NTP_URL;
 import static org.chromium.chrome.browser.tabmodel.TabSelectionType.FROM_USER;
+import static org.chromium.chrome.browser.util.UrlConstants.NTP_URL;
 import static org.chromium.content_public.browser.test.util.CriteriaHelper.DEFAULT_MAX_TIME_TO_POLL;
 import static org.chromium.content_public.browser.test.util.CriteriaHelper.DEFAULT_POLLING_INTERVAL;
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
index 6c4b0d9..ebe13e40 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -152,6 +152,7 @@
 import org.chromium.chrome.browser.util.AccessibilityUtil;
 import org.chromium.chrome.browser.util.FeatureUtilities;
 import org.chromium.chrome.browser.util.IntentUtils;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.chrome.browser.vr.VrModuleProvider;
 import org.chromium.chrome.browser.widget.OverviewListLayout;
 import org.chromium.components.feature_engagement.EventConstants;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java
index 241ec50..0bbb8790 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java
@@ -45,6 +45,7 @@
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tabmodel.TabLaunchType;
 import org.chromium.chrome.browser.util.IntentUtils;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.chrome.browser.util.UrlUtilities;
 import org.chromium.content_public.browser.BrowserStartupController;
 import org.chromium.content_public.browser.LoadUrlParams;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/LaunchIntentDispatcher.java b/chrome/android/java/src/org/chromium/chrome/browser/LaunchIntentDispatcher.java
index 6e84fa6..ca958f6b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/LaunchIntentDispatcher.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/LaunchIntentDispatcher.java
@@ -45,6 +45,7 @@
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.util.FeatureUtilities;
 import org.chromium.chrome.browser.util.IntentUtils;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.chrome.browser.vr.VrModuleProvider;
 import org.chromium.chrome.browser.webapps.ActivityAssigner;
 import org.chromium.chrome.browser.webapps.WebappLauncherActivity;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/NavigationPopup.java b/chrome/android/java/src/org/chromium/chrome/browser/NavigationPopup.java
index cf6d4c9..65fa3a1 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/NavigationPopup.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/NavigationPopup.java
@@ -33,6 +33,7 @@
 import org.chromium.chrome.browser.favicon.FaviconHelper.FaviconImageCallback;
 import org.chromium.chrome.browser.history.HistoryManagerUtils;
 import org.chromium.chrome.browser.profiles.Profile;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.content_public.browser.NavigationController;
 import org.chromium.content_public.browser.NavigationEntry;
 import org.chromium.content_public.browser.NavigationHistory;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/WarmupManager.java b/chrome/android/java/src/org/chromium/chrome/browser/WarmupManager.java
index 185b31b..0d98d1ca 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/WarmupManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/WarmupManager.java
@@ -27,6 +27,7 @@
 import org.chromium.base.task.AsyncTask;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.profiles.Profile;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.chrome.browser.widget.ControlContainer;
 import org.chromium.content_public.browser.WebContents;
 import org.chromium.content_public.browser.WebContentsObserver;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuPropertiesDelegateImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuPropertiesDelegateImpl.java
index a496d1e..8870e3b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuPropertiesDelegateImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuPropertiesDelegateImpl.java
@@ -28,7 +28,6 @@
 import org.chromium.chrome.browser.ChromeFeatureList;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.ShortcutHelper;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.banners.AppBannerManager;
 import org.chromium.chrome.browser.bookmarks.BookmarkBridge;
 import org.chromium.chrome.browser.compositor.layouts.OverviewModeBehavior;
@@ -42,6 +41,7 @@
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
 import org.chromium.chrome.browser.toolbar.ToolbarManager;
 import org.chromium.chrome.browser.translate.TranslateBridge;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.components.dom_distiller.core.DomDistillerUrlUtils;
 import org.chromium.ui.base.DeviceFormFactor;
 import org.chromium.webapk.lib.client.WebApkValidator;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkActivity.java
index a7b6f1b..42902dd0 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkActivity.java
@@ -10,7 +10,7 @@
 
 import org.chromium.base.VisibleForTesting;
 import org.chromium.chrome.browser.SnackbarActivity;
-import org.chromium.chrome.browser.UrlConstants;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.components.bookmarks.BookmarkId;
 
 /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkPage.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkPage.java
index 4fe0ee2..ca3a2fef 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkPage.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkPage.java
@@ -9,10 +9,10 @@
 import org.chromium.base.VisibleForTesting;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeActivity;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.native_page.BasicNativePage;
 import org.chromium.chrome.browser.native_page.NativePageHost;
 import org.chromium.chrome.browser.snackbar.SnackbarManager.SnackbarManageable;
+import org.chromium.chrome.browser.util.UrlConstants;
 
 /**
  * A native page holding a {@link BookmarkManager} on _tablet_.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkUIState.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkUIState.java
index 8d9cb74..c965e4a 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkUIState.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkUIState.java
@@ -7,7 +7,7 @@
 import android.net.Uri;
 import android.text.TextUtils;
 
-import org.chromium.chrome.browser.UrlConstants;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.components.bookmarks.BookmarkId;
 
 /**
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 ea7a96a..434ed25f 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
@@ -23,13 +23,13 @@
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.ChromeTabbedActivity;
 import org.chromium.chrome.browser.IntentHandler;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.document.ChromeLauncherActivity;
 import org.chromium.chrome.browser.snackbar.Snackbar;
 import org.chromium.chrome.browser.snackbar.SnackbarManager;
 import org.chromium.chrome.browser.snackbar.SnackbarManager.SnackbarController;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.util.IntentUtils;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.chrome.browser.widget.TintedDrawable;
 import org.chromium.components.bookmarks.BookmarkId;
 import org.chromium.components.bookmarks.BookmarkType;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/BrowserSessionContentUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/BrowserSessionContentUtils.java
index caedb0b..c582814 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/BrowserSessionContentUtils.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/BrowserSessionContentUtils.java
@@ -25,8 +25,8 @@
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.ChromeApplication;
 import org.chromium.chrome.browser.IntentHandler;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.customtabs.CustomTabsConnection;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.content_public.browser.LoadUrlParams;
 
 /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/Origin.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/Origin.java
index 98f84cb..065057b7 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/Origin.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/Origin.java
@@ -6,7 +6,7 @@
 
 import android.net.Uri;
 
-import org.chromium.chrome.browser.UrlConstants;
+import org.chromium.chrome.browser.util.UrlConstants;
 
 /**
  * A class to canonically represent a web origin in Java. In comparison to
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/OriginVerifier.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/OriginVerifier.java
index a1c031f5..6b2e4e1 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/OriginVerifier.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/OriginVerifier.java
@@ -27,8 +27,8 @@
 import org.chromium.base.task.PostTask;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.IntentHandler;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.profiles.Profile;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.content_public.browser.BrowserStartupController;
 import org.chromium.content_public.browser.UiThreadTaskTraits;
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityClient.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityClient.java
index 9dd3bdb..272d3bd 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityClient.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityClient.java
@@ -24,12 +24,12 @@
 import org.chromium.base.ContextUtils;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeFeatureList;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.browserservices.TrustedWebActivityUmaRecorder.DelegatedNotificationSmallIconFallback;
 import org.chromium.chrome.browser.browserservices.permissiondelegation.NotificationPermissionUpdater;
 import org.chromium.chrome.browser.notifications.NotificationBuilderBase;
 import org.chromium.chrome.browser.notifications.NotificationMetadata;
 import org.chromium.chrome.browser.notifications.NotificationUmaTracker;
+import org.chromium.chrome.browser.util.UrlConstants;
 
 import java.util.List;
 import java.util.Set;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManager.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManager.java
index 37b149f..97a47f8d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManager.java
@@ -17,7 +17,6 @@
 import org.chromium.base.ObserverList;
 import org.chromium.base.TraceEvent;
 import org.chromium.base.VisibleForTesting;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.compositor.LayerTitleCache;
 import org.chromium.chrome.browser.compositor.animation.CompositorAnimationHandler;
 import org.chromium.chrome.browser.compositor.bottombar.OverlayPanelContentViewDelegate;
@@ -55,6 +54,7 @@
 import org.chromium.chrome.browser.tabmodel.TabModelUtils;
 import org.chromium.chrome.browser.tabmodel.TabSelectionType;
 import org.chromium.chrome.browser.util.ColorUtils;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.ui.base.LocalizationUtils;
 import org.chromium.ui.base.SPenSupport;
 import org.chromium.ui.resources.ResourceManager;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ContextMenuParams.java b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ContextMenuParams.java
index 1aef19c..e8522a537 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ContextMenuParams.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ContextMenuParams.java
@@ -9,7 +9,7 @@
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.annotations.JNINamespace;
 import org.chromium.blink_public.web.WebContextMenuMediaType;
-import org.chromium.chrome.browser.UrlConstants;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.content_public.common.Referrer;
 import org.chromium.ui.base.MenuSourceType;
 /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchPolicy.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchPolicy.java
index a2dcdd94..ef23ade 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchPolicy.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchPolicy.java
@@ -15,13 +15,13 @@
 import org.chromium.base.VisibleForTesting;
 import org.chromium.chrome.browser.ChromeFeatureList;
 import org.chromium.chrome.browser.ChromeVersionInfo;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.compositor.bottombar.contextualsearch.ContextualSearchPanel;
 import org.chromium.chrome.browser.contextualsearch.ContextualSearchFieldTrial.ContextualSearchSetting;
 import org.chromium.chrome.browser.contextualsearch.ContextualSearchFieldTrial.ContextualSearchSwitch;
 import org.chromium.chrome.browser.contextualsearch.ContextualSearchSelectionController.SelectionType;
 import org.chromium.chrome.browser.preferences.ChromePreferenceManager;
 import org.chromium.chrome.browser.preferences.PrefServiceBridge;
+import org.chromium.chrome.browser.util.UrlConstants;
 
 import java.net.URL;
 import java.util.HashSet;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabAppMenuPropertiesDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabAppMenuPropertiesDelegate.java
index 300de081..11bc6fa8 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabAppMenuPropertiesDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabAppMenuPropertiesDelegate.java
@@ -20,7 +20,6 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ActivityTabProvider;
 import org.chromium.chrome.browser.DefaultBrowserInfo;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.appmenu.AppMenuPropertiesDelegateImpl;
 import org.chromium.chrome.browser.customtabs.CustomTabIntentDataProvider.CustomTabsUiType;
 import org.chromium.chrome.browser.download.DownloadUtils;
@@ -30,6 +29,7 @@
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
 import org.chromium.chrome.browser.toolbar.ToolbarManager;
+import org.chromium.chrome.browser.util.UrlConstants;
 
 import java.util.HashMap;
 import java.util.List;
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 c18d3d6..f9c287b3 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
@@ -41,13 +41,13 @@
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.ChromeVersionInfo;
 import org.chromium.chrome.browser.IntentHandler;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.browserservices.BrowserSessionDataProvider;
 import org.chromium.chrome.browser.customtabs.dynamicmodule.ModuleMetrics;
 import org.chromium.chrome.browser.externalauth.ExternalAuthUtils;
 import org.chromium.chrome.browser.net.spdyproxy.DataReductionProxySettings;
 import org.chromium.chrome.browser.util.ColorUtils;
 import org.chromium.chrome.browser.util.IntentUtils;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.chrome.browser.widget.TintedDrawable;
 
 import java.lang.annotation.Retention;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java
index 4d8638d..a96711d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java
@@ -52,7 +52,6 @@
 import org.chromium.chrome.browser.ChromeApplication;
 import org.chromium.chrome.browser.ChromeFeatureList;
 import org.chromium.chrome.browser.IntentHandler;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.WarmupManager;
 import org.chromium.chrome.browser.browserservices.BrowserSessionContentUtils;
 import org.chromium.chrome.browser.browserservices.Origin;
@@ -68,6 +67,7 @@
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.util.IntentUtils;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.content_public.browser.BrowserStartupController;
 import org.chromium.content_public.browser.ChildProcessLauncherHelper;
 import org.chromium.content_public.browser.UiThreadTaskTraits;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/DynamicModuleCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/DynamicModuleCoordinator.java
index 032271f..dd0cf78 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/DynamicModuleCoordinator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/DynamicModuleCoordinator.java
@@ -23,7 +23,6 @@
 import org.chromium.base.task.PostTask;
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.ChromeFeatureList;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.browserservices.PostMessageHandler;
 import org.chromium.chrome.browser.customtabs.CloseButtonNavigator;
 import org.chromium.chrome.browser.customtabs.CloseButtonNavigator.PageCriteria;
@@ -43,6 +42,7 @@
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tab.TabObserver;
 import org.chromium.chrome.browser.tab.TabObserverRegistrar;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.chrome.browser.util.UrlUtilities;
 import org.chromium.content_public.browser.NavigationHandle;
 import org.chromium.content_public.browser.UiThreadTaskTraits;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/ChromeDownloadDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/download/ChromeDownloadDelegate.java
index 3d82779..c1bf83fd 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/ChromeDownloadDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/ChromeDownloadDelegate.java
@@ -21,8 +21,8 @@
 import org.chromium.base.UserDataHost;
 import org.chromium.base.VisibleForTesting;
 import org.chromium.base.task.AsyncTask;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.tab.Tab;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.ui.base.PermissionCallback;
 import org.chromium.ui.base.WindowAndroid;
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadActivity.java
index 7ab86f5..5a28fbe3 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadActivity.java
@@ -11,7 +11,6 @@
 import org.chromium.base.VisibleForTesting;
 import org.chromium.chrome.browser.IntentHandler;
 import org.chromium.chrome.browser.SnackbarActivity;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.download.home.DownloadManagerCoordinator;
 import org.chromium.chrome.browser.download.home.DownloadManagerCoordinatorFactory;
 import org.chromium.chrome.browser.download.home.DownloadManagerUiConfig;
@@ -19,6 +18,7 @@
 import org.chromium.chrome.browser.download.ui.DownloadManagerUi;
 import org.chromium.chrome.browser.modaldialog.AppModalPresenter;
 import org.chromium.chrome.browser.util.IntentUtils;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.ui.base.ActivityAndroidPermissionDelegate;
 import org.chromium.ui.base.AndroidPermissionDelegate;
 import org.chromium.ui.modaldialog.ModalDialogManager;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadPage.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadPage.java
index 85d6979..3099090 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadPage.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadPage.java
@@ -12,13 +12,13 @@
 import org.chromium.base.ThreadUtils;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeActivity;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.download.home.DownloadManagerCoordinator;
 import org.chromium.chrome.browser.download.home.DownloadManagerCoordinatorFactory;
 import org.chromium.chrome.browser.download.home.DownloadManagerUiConfig;
 import org.chromium.chrome.browser.native_page.BasicNativePage;
 import org.chromium.chrome.browser.native_page.NativePageHost;
 import org.chromium.chrome.browser.snackbar.SnackbarManager.SnackbarManageable;
+import org.chromium.chrome.browser.util.UrlConstants;
 
 /**
  * Native page for managing downloads handled through Chrome.
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 b9bad859..28cf147 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
@@ -36,7 +36,6 @@
 import org.chromium.chrome.browser.ChromeTabbedActivity;
 import org.chromium.chrome.browser.FileProviderHelper;
 import org.chromium.chrome.browser.IntentHandler;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.download.home.metrics.FileExtensions;
 import org.chromium.chrome.browser.download.items.OfflineContentAggregatorFactory;
 import org.chromium.chrome.browser.download.ui.DownloadFilter;
@@ -56,6 +55,7 @@
 import org.chromium.chrome.browser.tabmodel.document.TabDelegate;
 import org.chromium.chrome.browser.util.ConversionUtils;
 import org.chromium.chrome.browser.util.IntentUtils;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.components.download.DownloadState;
 import org.chromium.components.download.ResumeMode;
 import org.chromium.components.feature_engagement.EventConstants;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/filter/Filters.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/filter/Filters.java
index e97db96..cc7eacd 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/filter/Filters.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/filter/Filters.java
@@ -7,7 +7,7 @@
 import android.support.annotation.IntDef;
 import android.text.TextUtils;
 
-import org.chromium.chrome.browser.UrlConstants;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.components.offline_items_collection.OfflineItem;
 import org.chromium.components.offline_items_collection.OfflineItemFilter;
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadFilter.java b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadFilter.java
index 9ca6e3f..a7cb1f6 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadFilter.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/ui/DownloadFilter.java
@@ -9,7 +9,7 @@
 
 import org.chromium.base.Log;
 import org.chromium.chrome.R;
-import org.chromium.chrome.browser.UrlConstants;
+import org.chromium.chrome.browser.util.UrlConstants;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/explore_sites/ExploreSitesCategory.java b/chrome/android/java/src/org/chromium/chrome/browser/explore_sites/ExploreSitesCategory.java
index 0a120a4..4d5259b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/explore_sites/ExploreSitesCategory.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/explore_sites/ExploreSitesCategory.java
@@ -11,7 +11,7 @@
 import android.support.annotation.IntDef;
 
 import org.chromium.base.annotations.CalledByNative;
-import org.chromium.chrome.browser.UrlConstants;
+import org.chromium.chrome.browser.util.UrlConstants;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/explore_sites/ExploreSitesPage.java b/chrome/android/java/src/org/chromium/chrome/browser/explore_sites/ExploreSitesPage.java
index 53c666a2..95a2fd66 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/explore_sites/ExploreSitesPage.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/explore_sites/ExploreSitesPage.java
@@ -20,7 +20,6 @@
 import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeActivity;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.gesturenav.HistoryNavigationLayout;
 import org.chromium.chrome.browser.native_page.BasicNativePage;
 import org.chromium.chrome.browser.native_page.ContextMenuManager;
@@ -31,6 +30,7 @@
 import org.chromium.chrome.browser.tab.EmptyTabObserver;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tab.TabObserver;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.chrome.browser.widget.RoundedIconGenerator;
 import org.chromium.content_public.browser.NavigationController;
 import org.chromium.content_public.browser.NavigationEntry;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegateImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegateImpl.java
index d120ae1..c0cf588 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegateImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegateImpl.java
@@ -37,7 +37,6 @@
 import org.chromium.chrome.browser.ChromeTabbedActivity2;
 import org.chromium.chrome.browser.IntentHandler;
 import org.chromium.chrome.browser.LaunchIntentDispatcher;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.document.ChromeLauncherActivity;
 import org.chromium.chrome.browser.externalnav.ExternalNavigationHandler.OverrideUrlLoadingResult;
 import org.chromium.chrome.browser.instantapps.AuthenticatedProxyActivity;
@@ -47,6 +46,7 @@
 import org.chromium.chrome.browser.tab.TabObserver;
 import org.chromium.chrome.browser.tab.TabRedirectHandler;
 import org.chromium.chrome.browser.util.IntentUtils;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.chrome.browser.util.UrlUtilities;
 import org.chromium.chrome.browser.webapps.WebappActivity;
 import org.chromium.chrome.browser.webapps.WebappScopePolicy;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationHandler.java
index ac81025..bf59138a 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationHandler.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationHandler.java
@@ -27,12 +27,12 @@
 import org.chromium.chrome.browser.ChromeFeatureList;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.IntentHandler;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.customtabs.CustomTabIntentDataProvider.LaunchSourceType;
 import org.chromium.chrome.browser.instantapps.InstantAppsHandler;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tab.TabRedirectHandler;
 import org.chromium.chrome.browser.util.IntentUtils;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.chrome.browser.util.UrlUtilities;
 import org.chromium.chrome.browser.webapps.WebappScopePolicy;
 import org.chromium.content_public.common.ContentUrlConstants;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunFlowSequencer.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunFlowSequencer.java
index 5b105aa..7e90c12 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunFlowSequencer.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunFlowSequencer.java
@@ -19,7 +19,6 @@
 import org.chromium.chrome.browser.AppHooks;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.IntentHandler;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.locale.LocaleManager;
 import org.chromium.chrome.browser.net.spdyproxy.DataReductionProxySettings;
 import org.chromium.chrome.browser.preferences.PrefServiceBridge;
@@ -28,6 +27,7 @@
 import org.chromium.chrome.browser.signin.SigninManager;
 import org.chromium.chrome.browser.util.FeatureUtilities;
 import org.chromium.chrome.browser.util.IntentUtils;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.chrome.browser.vr.VrModuleProvider;
 import org.chromium.components.signin.AccountManagerFacade;
 import org.chromium.components.signin.ChildAccountStatus;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/gsa/ContextReporter.java b/chrome/android/java/src/org/chromium/chrome/browser/gsa/ContextReporter.java
index 37f154d..e9e78b7 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/gsa/ContextReporter.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/gsa/ContextReporter.java
@@ -10,7 +10,6 @@
 import org.chromium.base.Log;
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.chrome.browser.ChromeActivity;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.contextualsearch.ContextualSearchManager;
 import org.chromium.chrome.browser.sync.ProfileSyncService;
 import org.chromium.chrome.browser.tab.Tab;
@@ -18,6 +17,7 @@
 import org.chromium.chrome.browser.tabmodel.TabModelSelectorTabModelObserver;
 import org.chromium.chrome.browser.tabmodel.TabModelSelectorTabObserver;
 import org.chromium.chrome.browser.tabmodel.TabSelectionType;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.components.sync.ModelType;
 import org.chromium.components.sync.Passphrase;
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/help/HelpAndFeedback.java b/chrome/android/java/src/org/chromium/chrome/browser/help/HelpAndFeedback.java
index 50673d6..68d16fb 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/help/HelpAndFeedback.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/help/HelpAndFeedback.java
@@ -17,9 +17,9 @@
 import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.AppHooks;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.feedback.FeedbackCollector;
 import org.chromium.chrome.browser.profiles.Profile;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.chrome.browser.util.UrlUtilities;
 
 import javax.annotation.Nonnull;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryAdapter.java
index bc63a9a..3772e3a 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryAdapter.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryAdapter.java
@@ -19,11 +19,11 @@
 
 import org.chromium.base.VisibleForTesting;
 import org.chromium.chrome.R;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.favicon.FaviconHelper.DefaultFaviconHelper;
 import org.chromium.chrome.browser.history.HistoryProvider.BrowsingHistoryObserver;
 import org.chromium.chrome.browser.preferences.Pref;
 import org.chromium.chrome.browser.preferences.PrefServiceBridge;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.chrome.browser.widget.DateDividedAdapter;
 import org.chromium.chrome.browser.widget.selection.SelectableItemViewHolder;
 import org.chromium.chrome.browser.widget.selection.SelectionDelegate;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryManagerUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryManagerUtils.java
index 38e1cf3..e081b5f6 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryManagerUtils.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryManagerUtils.java
@@ -10,8 +10,8 @@
 import org.chromium.base.ContextUtils;
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.IntentHandler;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.tab.Tab;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.content_public.browser.LoadUrlParams;
 
 /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryPage.java b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryPage.java
index e08a230..62b2b3b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryPage.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryPage.java
@@ -10,10 +10,10 @@
 import org.chromium.base.VisibleForTesting;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeActivity;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.native_page.BasicNativePage;
 import org.chromium.chrome.browser.native_page.NativePageHost;
 import org.chromium.chrome.browser.snackbar.SnackbarManager.SnackbarManageable;
+import org.chromium.chrome.browser.util.UrlConstants;
 
 /**
  * Native page for managing browsing history.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/DataReductionPromoInfoBar.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/DataReductionPromoInfoBar.java
index 0ec878e..ffe2e2f1 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/DataReductionPromoInfoBar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/DataReductionPromoInfoBar.java
@@ -13,10 +13,10 @@
 import org.chromium.base.CommandLine;
 import org.chromium.base.ThreadUtils;
 import org.chromium.chrome.R;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.datareduction.DataReductionPromoUtils;
 import org.chromium.chrome.browser.omaha.VersionNumberGetter;
 import org.chromium.chrome.browser.preferences.PrefServiceBridge;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.content_public.browser.WebContents;
 import org.chromium.net.GURLUtils;
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/native_page/NativePageFactory.java b/chrome/android/java/src/org/chromium/chrome/browser/native_page/NativePageFactory.java
index 38a9180..09bd533 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/native_page/NativePageFactory.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/native_page/NativePageFactory.java
@@ -11,7 +11,6 @@
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.ChromeFeatureList;
 import org.chromium.chrome.browser.TabLoadStatus;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.bookmarks.BookmarkPage;
 import org.chromium.chrome.browser.download.DownloadPage;
 import org.chromium.chrome.browser.explore_sites.ExploreSitesPage;
@@ -27,6 +26,7 @@
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
 import org.chromium.chrome.browser.touchless.TouchlessDelegate;
 import org.chromium.chrome.browser.util.FeatureUtilities;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.content_public.browser.LoadUrlParams;
 
 import java.lang.annotation.Retention;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/net/spdyproxy/DataReductionProxySettings.java b/chrome/android/java/src/org/chromium/chrome/browser/net/spdyproxy/DataReductionProxySettings.java
index 1dc0f6f..34cb2977 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/net/spdyproxy/DataReductionProxySettings.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/net/spdyproxy/DataReductionProxySettings.java
@@ -11,12 +11,12 @@
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.VisibleForTesting;
 import org.chromium.base.annotations.CalledByNative;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.datareduction.DataReductionPromoUtils;
 import org.chromium.chrome.browser.preferences.datareduction.DataReductionDataUseItem;
 import org.chromium.chrome.browser.preferences.datareduction.DataReductionProxySavingsClearedReason;
 import org.chromium.chrome.browser.preferences.datareduction.DataReductionStatsPreference;
 import org.chromium.chrome.browser.util.ConversionUtils;
+import org.chromium.chrome.browser.util.UrlConstants;
 
 import java.text.NumberFormat;
 import java.util.ArrayList;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/nfc/BeamCallback.java b/chrome/android/java/src/org/chromium/chrome/browser/nfc/BeamCallback.java
index 57c155ab8..eae8e69 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/nfc/BeamCallback.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/nfc/BeamCallback.java
@@ -17,7 +17,7 @@
 import org.chromium.base.ThreadUtils;
 import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.chrome.R;
-import org.chromium.chrome.browser.UrlConstants;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.ui.widget.Toast;
 
 import java.net.MalformedURLException;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/IncognitoNewTabPage.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/IncognitoNewTabPage.java
index d54ef2fd..5273ff0 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/IncognitoNewTabPage.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/IncognitoNewTabPage.java
@@ -16,13 +16,13 @@
 import org.chromium.base.VisibleForTesting;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeActivity;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.compositor.layouts.content.InvalidationAwareThumbnailProvider;
 import org.chromium.chrome.browser.help.HelpAndFeedback;
 import org.chromium.chrome.browser.native_page.BasicNativePage;
 import org.chromium.chrome.browser.native_page.NativePageHost;
 import org.chromium.chrome.browser.ntp.IncognitoNewTabPageView.IncognitoNewTabPageManager;
 import org.chromium.chrome.browser.profiles.Profile;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.chrome.browser.vr.VrModuleProvider;
 
 /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java
index 9ec9648..b6707a3 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java
@@ -27,7 +27,6 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.ChromeApplication;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.compositor.layouts.content.InvalidationAwareThumbnailProvider;
 import org.chromium.chrome.browser.download.DownloadManagerService;
 import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager;
@@ -57,6 +56,7 @@
 import org.chromium.chrome.browser.tab.TabObserver;
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
 import org.chromium.chrome.browser.tabmodel.TabSelectionType;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.chrome.browser.util.UrlUtilities;
 import org.chromium.chrome.browser.vr.VrModuleProvider;
 import org.chromium.content_public.browser.NavigationController;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/RecentTabsPage.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/RecentTabsPage.java
index e53101b8..1b6dc7ea 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/RecentTabsPage.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/RecentTabsPage.java
@@ -21,12 +21,12 @@
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeActivity;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.compositor.layouts.content.InvalidationAwareThumbnailProvider;
 import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager;
 import org.chromium.chrome.browser.gesturenav.HistoryNavigationLayout;
 import org.chromium.chrome.browser.native_page.NativePage;
 import org.chromium.chrome.browser.native_page.NativePageHost;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.chrome.browser.util.ViewUtils;
 import org.chromium.ui.base.DeviceFormFactor;
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtils.java
index ca61c79..8326916 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtils.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtils.java
@@ -24,7 +24,6 @@
 import org.chromium.chrome.browser.ChromeFeatureList;
 import org.chromium.chrome.browser.DeviceConditions;
 import org.chromium.chrome.browser.FileProviderHelper;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.share.ShareParams;
 import org.chromium.chrome.browser.snackbar.Snackbar;
@@ -37,6 +36,7 @@
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
 import org.chromium.chrome.browser.tabmodel.TabModelSelectorTabModelObserver;
 import org.chromium.chrome.browser.util.ChromeFileProvider;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.components.bookmarks.BookmarkId;
 import org.chromium.components.offline_items_collection.LaunchLocation;
 import org.chromium.components.offlinepages.SavePageResult;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/OmniboxUrlEmphasizer.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/OmniboxUrlEmphasizer.java
index 44a53a5..4cbc3b9 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/OmniboxUrlEmphasizer.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/OmniboxUrlEmphasizer.java
@@ -12,8 +12,8 @@
 import org.chromium.base.ApiCompatibilityUtils;
 import org.chromium.base.VisibleForTesting;
 import org.chromium.chrome.R;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.profiles.Profile;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.components.security_state.ConnectionSecurityLevel;
 
 import java.util.Locale;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBarData.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBarData.java
index d3033d8..fd57101 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBarData.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBarData.java
@@ -13,7 +13,7 @@
 import android.text.TextUtils;
 
 import org.chromium.base.CollectionUtil;
-import org.chromium.chrome.browser.UrlConstants;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.content_public.common.ContentUrlConstants;
 
 import java.util.HashSet;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/geo/GeolocationHeader.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/geo/GeolocationHeader.java
index 1145337..aabc1f3 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/geo/GeolocationHeader.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/geo/GeolocationHeader.java
@@ -25,13 +25,13 @@
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.chrome.browser.ContentSettingsType;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.omnibox.geo.VisibleNetworks.VisibleCell;
 import org.chromium.chrome.browser.omnibox.geo.VisibleNetworks.VisibleWifi;
 import org.chromium.chrome.browser.preferences.website.ContentSettingValues;
 import org.chromium.chrome.browser.preferences.website.PermissionInfo;
 import org.chromium.chrome.browser.preferences.website.WebsitePreferenceBridge;
 import org.chromium.chrome.browser.tab.Tab;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.chrome.browser.util.UrlUtilities;
 
 import java.lang.annotation.Retention;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java
index a3d8820..3e4fdaae 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java
@@ -24,7 +24,6 @@
 import org.chromium.chrome.browser.ActivityTabProvider;
 import org.chromium.chrome.browser.ActivityTabProvider.ActivityTabTabObserver;
 import org.chromium.chrome.browser.ChromeFeatureList;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.init.AsyncInitializationActivity;
 import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher;
 import org.chromium.chrome.browser.lifecycle.StartStopWithNativeObserver;
@@ -41,6 +40,7 @@
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.toolbar.ToolbarDataProvider;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.components.omnibox.AnswerType;
 import org.chromium.content_public.browser.WebContents;
 import org.chromium.ui.base.DeviceFormFactor;
@@ -95,13 +95,14 @@
     private final List<Runnable> mDeferredNativeRunnables = new ArrayList<Runnable>();
     private final Handler mHandler;
     private final BasicSuggestionProcessor mBasicSuggestionProcessor;
-    private EditUrlSuggestionProcessor mEditUrlProcessor;
+    private @Nullable EditUrlSuggestionProcessor mEditUrlProcessor;
     private AnswerSuggestionProcessor mAnswerSuggestionProcessor;
     private final EntitySuggestionProcessor mEntitySuggestionProcessor;
 
     private ToolbarDataProvider mDataProvider;
     private boolean mNativeInitialized;
     private AutocompleteController mAutocomplete;
+    private long mUrlFocusTime;
 
     @IntDef({SuggestionVisibilityState.DISALLOWED, SuggestionVisibilityState.PENDING_ALLOW,
             SuggestionVisibilityState.ALLOWED})
@@ -385,6 +386,7 @@
     /** @see org.chromium.chrome.browser.omnibox.UrlFocusChangeListener#onUrlFocusChange(boolean) */
     void onUrlFocusChange(boolean hasFocus) {
         if (hasFocus) {
+            mUrlFocusTime = System.currentTimeMillis();
             mSuggestionVisibilityState = SuggestionVisibilityState.PENDING_ALLOW;
             if (mNativeInitialized) {
                 startZeroSuggest();
@@ -430,7 +432,7 @@
     void setAutocompleteProfile(Profile profile) {
         mAutocomplete.setProfile(profile);
         mBasicSuggestionProcessor.setProfile(profile);
-        mEditUrlProcessor.setProfile(profile);
+        if (mEditUrlProcessor != null) mEditUrlProcessor.setProfile(profile);
     }
 
     /**
@@ -892,6 +894,10 @@
      */
     private void loadUrlFromOmniboxMatch(int matchPosition, OmniboxSuggestion suggestion,
             long inputStart, boolean inVisibleSuggestionList) {
+        final long activationTime = System.currentTimeMillis();
+        RecordHistogram.recordMediumTimesHistogram(
+                "Omnibox.FocusToOpenTimeAnyPopupState3", activationTime - mUrlFocusTime);
+
         String url =
                 updateSuggestionUrlIfNeeded(suggestion, matchPosition, !inVisibleSuggestionList);
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/page_info/SiteSettingsHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/page_info/SiteSettingsHelper.java
index 0cdcc8a..b9c5217 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/page_info/SiteSettingsHelper.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/page_info/SiteSettingsHelper.java
@@ -8,12 +8,12 @@
 import android.content.Intent;
 
 import org.chromium.base.StrictModeContext;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.offlinepages.OfflinePageUtils;
 import org.chromium.chrome.browser.preferences.PreferencesLauncher;
 import org.chromium.chrome.browser.preferences.website.SingleWebsitePreferences;
 import org.chromium.chrome.browser.previews.PreviewsAndroidBridge;
 import org.chromium.chrome.browser.tab.Tab;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.net.GURLUtils;
 
 /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksProviderIterator.java b/chrome/android/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksProviderIterator.java
index 7f79916..b37a345 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksProviderIterator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksProviderIterator.java
@@ -10,7 +10,7 @@
 
 import org.chromium.base.ContextUtils;
 import org.chromium.base.Log;
-import org.chromium.chrome.browser.UrlConstants;
+import org.chromium.chrome.browser.util.UrlConstants;
 
 import java.util.NoSuchElementException;
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/partnercustomizations/HomepageManager.java b/chrome/android/java/src/org/chromium/chrome/browser/partnercustomizations/HomepageManager.java
index 8b44fa1127..deb4b559 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/partnercustomizations/HomepageManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/partnercustomizations/HomepageManager.java
@@ -10,9 +10,9 @@
 import org.chromium.base.ContextUtils;
 import org.chromium.base.ObserverList;
 import org.chromium.base.metrics.RecordHistogram;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.ntp.NewTabPage;
 import org.chromium.chrome.browser.util.FeatureUtilities;
+import org.chromium.chrome.browser.util.UrlConstants;
 
 /**
  * Provides information regarding homepage enabled states and URI.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/partnercustomizations/PartnerBrowserCustomizations.java b/chrome/android/java/src/org/chromium/chrome/browser/partnercustomizations/PartnerBrowserCustomizations.java
index db17acb..0186532 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/partnercustomizations/PartnerBrowserCustomizations.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/partnercustomizations/PartnerBrowserCustomizations.java
@@ -22,9 +22,9 @@
 import org.chromium.chrome.browser.AppHooks;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.ChromeVersionInfo;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.ntp.NewTabPage;
 import org.chromium.chrome.browser.partnerbookmarks.PartnerBookmarksReader;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.chrome.browser.util.UrlUtilities;
 import org.chromium.content_public.browser.UiThreadTaskTraits;
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java
index 48c2518..42f72837 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java
@@ -17,7 +17,6 @@
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.ChromeFeatureList;
 import org.chromium.chrome.browser.ChromeTabbedActivity;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.autofill.PersonalDataManager;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile;
 import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard;
@@ -49,6 +48,7 @@
 import org.chromium.chrome.browser.tabmodel.TabModelSelectorObserver;
 import org.chromium.chrome.browser.tabmodel.TabModelUtils;
 import org.chromium.chrome.browser.tabmodel.TabSelectionType;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.chrome.browser.widget.prefeditor.Completable;
 import org.chromium.chrome.browser.widget.prefeditor.EditableOption;
 import org.chromium.components.payments.CurrencyFormatter;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/UriUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/UriUtils.java
index 05296ad..856b00e3b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/payments/UriUtils.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/UriUtils.java
@@ -6,7 +6,7 @@
 
 import android.support.annotation.Nullable;
 
-import org.chromium.chrome.browser.UrlConstants;
+import org.chromium.chrome.browser.util.UrlConstants;
 
 import java.net.URI;
 import java.net.URISyntaxException;
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 29977f31..7eb8a67a 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
@@ -18,10 +18,10 @@
 
 import org.chromium.base.ApiCompatibilityUtils;
 import org.chromium.chrome.R;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.omnibox.OmniboxUrlEmphasizer;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.util.ColorUtils;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.chrome.browser.widget.TintedDrawable;
 
 /** This class represents a bar to display at the top of the payment request UI. */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/privacy/ClearBrowsingDataPreferencesBasic.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/privacy/ClearBrowsingDataPreferencesBasic.java
index 4b78420..f1b4bb5a 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/privacy/ClearBrowsingDataPreferencesBasic.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/privacy/ClearBrowsingDataPreferencesBasic.java
@@ -9,12 +9,12 @@
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.chrome.R;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.browsing_data.ClearBrowsingDataTab;
 import org.chromium.chrome.browser.preferences.ClearBrowsingDataCheckBoxPreference;
 import org.chromium.chrome.browser.sync.ProfileSyncService;
 import org.chromium.chrome.browser.tabmodel.TabLaunchType;
 import org.chromium.chrome.browser.tabmodel.document.TabDelegate;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.components.signin.ChromeSigninController;
 import org.chromium.components.sync.AndroidSyncSettings;
 import org.chromium.components.sync.ModelType;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/privacy/OtherFormsOfHistoryDialogFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/privacy/OtherFormsOfHistoryDialogFragment.java
index fec6b3a..af266d5 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/privacy/OtherFormsOfHistoryDialogFragment.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/privacy/OtherFormsOfHistoryDialogFragment.java
@@ -20,9 +20,9 @@
 import org.chromium.base.ContextUtils;
 import org.chromium.base.VisibleForTesting;
 import org.chromium.chrome.R;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.tabmodel.TabLaunchType;
 import org.chromium.chrome.browser.tabmodel.document.TabDelegate;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.ui.text.NoUnderlineClickableSpan;
 import org.chromium.ui.text.SpanApplier;
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/WebsiteAddress.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/WebsiteAddress.java
index 4c3851d0..50de65d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/WebsiteAddress.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/WebsiteAddress.java
@@ -7,7 +7,7 @@
 import android.net.Uri;
 import android.support.annotation.Nullable;
 
-import org.chromium.chrome.browser.UrlConstants;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.chrome.browser.util.UrlUtilities;
 import org.chromium.components.url_formatter.UrlFormatter;
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/provider/ChromeBrowserProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/provider/ChromeBrowserProvider.java
index 1404c067..cbde805 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/provider/ChromeBrowserProvider.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/provider/ChromeBrowserProvider.java
@@ -36,10 +36,10 @@
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.task.PostTask;
 import org.chromium.chrome.browser.IntentHandler;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.database.SQLiteCursor;
 import org.chromium.chrome.browser.externalauth.ExternalAuthUtils;
 import org.chromium.chrome.browser.init.ChromeBrowserInitializer;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.content_public.browser.BrowserStartupController;
 import org.chromium.content_public.browser.UiThreadTaskTraits;
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/share/ShareMenuActionHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/share/ShareMenuActionHandler.java
index 61671613..cd3d60d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/share/ShareMenuActionHandler.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/share/ShareMenuActionHandler.java
@@ -12,7 +12,6 @@
 import org.chromium.base.VisibleForTesting;
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.metrics.RecordUserAction;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.feature_engagement.ScreenshotTabObserver;
 import org.chromium.chrome.browser.offlinepages.OfflinePageUtils;
 import org.chromium.chrome.browser.printing.PrintShareActivity;
@@ -20,6 +19,7 @@
 import org.chromium.chrome.browser.tab.SadTab;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.util.ChromeFileProvider;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.components.ui_metrics.CanonicalURLResult;
 import org.chromium.content_public.browser.WebContents;
 import org.chromium.net.GURLUtils;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/GoogleActivityController.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/GoogleActivityController.java
index 7217a29..cc1abd3 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/GoogleActivityController.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/GoogleActivityController.java
@@ -9,7 +9,7 @@
 import android.net.Uri;
 import android.provider.Browser;
 
-import org.chromium.chrome.browser.UrlConstants;
+import org.chromium.chrome.browser.util.UrlConstants;
 
 /**
 * Controls how Google uses Chrome data to personalize Search and other Google services.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/DEPS b/chrome/android/java/src/org/chromium/chrome/browser/tab/DEPS
index e4bb90a5..aea7680 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tab/DEPS
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/DEPS
@@ -7,6 +7,7 @@
     "-chrome",
     "+chrome/android/java/src/org/chromium/chrome/browser/night_mode",
     "+chrome/android/java/src/org/chromium/chrome/browser/tab",
+    "+chrome/android/java/src/org/chromium/chrome/browser/util",
     "-components",
     "+components/embedder_support/android/java/src/org/chromium/components/embedder_support/view",
     "+components/navigation_interception/android/java/src/org/chromium/components/navigation_interception",
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java
index 26b8598a..61ecb52 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java
@@ -34,7 +34,6 @@
 import org.chromium.chrome.browser.ChromeFeatureList;
 import org.chromium.chrome.browser.ChromeVersionInfo;
 import org.chromium.chrome.browser.IntentHandler;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.WarmupManager;
 import org.chromium.chrome.browser.WebContentsFactory;
 import org.chromium.chrome.browser.content.ContentUtils;
@@ -60,6 +59,7 @@
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
 import org.chromium.chrome.browser.tabmodel.TabReparentingParams;
 import org.chromium.chrome.browser.tabmodel.TabSelectionType;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.chrome.browser.vr.VrModuleProvider;
 import org.chromium.components.dom_distiller.core.DomDistillerUrlUtils;
 import org.chromium.components.embedder_support.view.ContentView;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabContextMenuItemDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabContextMenuItemDelegate.java
index c60f254..63a844a 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabContextMenuItemDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabContextMenuItemDelegate.java
@@ -17,7 +17,6 @@
 import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.chrome.browser.DefaultBrowserInfo;
 import org.chromium.chrome.browser.IntentHandler;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.contextmenu.ContextMenuItemDelegate;
 import org.chromium.chrome.browser.document.ChromeLauncherActivity;
 import org.chromium.chrome.browser.download.ChromeDownloadDelegate;
@@ -28,6 +27,7 @@
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
 import org.chromium.chrome.browser.tabmodel.document.TabDelegate;
 import org.chromium.chrome.browser.util.IntentUtils;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.chrome.browser.util.UrlUtilities;
 import org.chromium.content_public.browser.LoadUrlParams;
 import org.chromium.content_public.common.Referrer;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabStateBrowserControlsVisibilityDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabStateBrowserControlsVisibilityDelegate.java
index 8cf44b6..dad01cb 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabStateBrowserControlsVisibilityDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabStateBrowserControlsVisibilityDelegate.java
@@ -9,12 +9,12 @@
 import android.os.Message;
 
 import org.chromium.chrome.browser.ChromeFeatureList;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.device.DeviceClassManager;
 import org.chromium.chrome.browser.fullscreen.FullscreenManager;
 import org.chromium.chrome.browser.modaldialog.TabModalPresenter;
 import org.chromium.chrome.browser.tab.Tab.TabHidingType;
 import org.chromium.chrome.browser.util.AccessibilityUtil;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.components.dom_distiller.core.DomDistillerUrlUtils;
 import org.chromium.components.security_state.ConnectionSecurityLevel;
 import org.chromium.content_public.browser.NavigationHandle;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabCreatorManager.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabCreatorManager.java
index 3ae6f111..478a30c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabCreatorManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabCreatorManager.java
@@ -7,9 +7,9 @@
 import android.support.annotation.Nullable;
 
 import org.chromium.base.TraceEvent;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tab.TabState;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.content_public.browser.LoadUrlParams;
 import org.chromium.content_public.browser.WebContents;
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPersistentStore.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPersistentStore.java
index 093372d8..058e3ec 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPersistentStore.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPersistentStore.java
@@ -31,13 +31,13 @@
 import org.chromium.base.task.SequencedTaskRunner;
 import org.chromium.base.task.TaskRunner;
 import org.chromium.base.task.TaskTraits;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.compositor.layouts.content.TabContentManager;
 import org.chromium.chrome.browser.ntp.NewTabPage;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tab.TabIdManager;
 import org.chromium.chrome.browser.tab.TabState;
 import org.chromium.chrome.browser.util.FeatureUtilities;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.content_public.browser.LoadUrlParams;
 import org.chromium.content_public.browser.UiThreadTaskTraits;
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/LocationBarModel.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/LocationBarModel.java
index df1155d..d94d1e8 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/LocationBarModel.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/LocationBarModel.java
@@ -17,7 +17,6 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeFeatureList;
 import org.chromium.chrome.browser.ChromeTabbedActivity;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.compositor.layouts.OverviewModeBehavior;
 import org.chromium.chrome.browser.dom_distiller.DomDistillerServiceFactory;
 import org.chromium.chrome.browser.dom_distiller.DomDistillerTabUtils;
@@ -31,6 +30,7 @@
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tab.TrustedCdn;
 import org.chromium.chrome.browser.util.ColorUtils;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.chrome.browser.util.UrlUtilities;
 import org.chromium.components.dom_distiller.core.DomDistillerService;
 import org.chromium.components.dom_distiller.core.DomDistillerUrlUtils;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
index 5e06215..80376ec 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
@@ -34,7 +34,6 @@
 import org.chromium.chrome.browser.TabLoadStatus;
 import org.chromium.chrome.browser.ThemeColorProvider;
 import org.chromium.chrome.browser.ThemeColorProvider.ThemeColorObserver;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.WindowDelegate;
 import org.chromium.chrome.browser.appmenu.AppMenuButtonHelper;
 import org.chromium.chrome.browser.appmenu.AppMenuHandler;
@@ -99,6 +98,7 @@
 import org.chromium.chrome.browser.ui.ImmersiveModeManager;
 import org.chromium.chrome.browser.util.ColorUtils;
 import org.chromium.chrome.browser.util.FeatureUtilities;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.chrome.browser.widget.ScrimView;
 import org.chromium.chrome.browser.widget.ScrimView.ScrimObserver;
 import org.chromium.chrome.browser.widget.ScrimView.ScrimParams;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/ShareButton.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/ShareButton.java
index 2e281a8..98e0a07f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/ShareButton.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/ShareButton.java
@@ -17,9 +17,9 @@
 import org.chromium.chrome.browser.ActivityTabProvider.ActivityTabTabObserver;
 import org.chromium.chrome.browser.ThemeColorProvider;
 import org.chromium.chrome.browser.ThemeColorProvider.TintObserver;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.util.FeatureUtilities;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.ui.widget.ChromeImageButton;
 
 /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/util/ChromeFileProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/util/ChromeFileProvider.java
index 1a36a8a..d454428 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/util/ChromeFileProvider.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/util/ChromeFileProvider.java
@@ -12,8 +12,6 @@
 import android.provider.MediaStore;
 import android.support.v4.content.FileProvider;
 
-import org.chromium.chrome.browser.UrlConstants;
-
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.util.Arrays;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/UrlConstants.java b/chrome/android/java/src/org/chromium/chrome/browser/util/UrlConstants.java
similarity index 98%
rename from chrome/android/java/src/org/chromium/chrome/browser/UrlConstants.java
rename to chrome/android/java/src/org/chromium/chrome/browser/util/UrlConstants.java
index 3fb08e1..e3c20de 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/UrlConstants.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/util/UrlConstants.java
@@ -2,7 +2,7 @@
 // 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;
+package org.chromium.chrome.browser.util;
 
 /**
  * Java side version of chrome/common/url_constants.cc
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/util/UrlUtilities.java b/chrome/android/java/src/org/chromium/chrome/browser/util/UrlUtilities.java
index 6bd44d7..25e1a65a 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/util/UrlUtilities.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/util/UrlUtilities.java
@@ -11,7 +11,6 @@
 import org.chromium.base.CollectionUtil;
 import org.chromium.base.Log;
 import org.chromium.base.VisibleForTesting;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.content_public.common.ContentUrlConstants;
 
 import java.io.UnsupportedEncodingException;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/RoundedIconGenerator.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/RoundedIconGenerator.java
index 4897f41..169b5ec5 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/widget/RoundedIconGenerator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/RoundedIconGenerator.java
@@ -17,7 +17,7 @@
 import android.util.Log;
 
 import org.chromium.base.VisibleForTesting;
-import org.chromium.chrome.browser.UrlConstants;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.chrome.browser.util.UrlUtilities;
 
 import java.net.URI;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/CopylessPasteTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/CopylessPasteTest.java
index 1692200..fdc229c 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/CopylessPasteTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/CopylessPasteTest.java
@@ -26,6 +26,7 @@
 import org.chromium.blink.mojom.document_metadata.Values;
 import org.chromium.blink.mojom.document_metadata.WebPage;
 import org.chromium.chrome.browser.firstrun.FirstRunStatus;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.util.ChromeTabUtils;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/IntentHandlerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/IntentHandlerTest.java
index 4b0f7c79..4518f58 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/IntentHandlerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/IntentHandlerTest.java
@@ -30,6 +30,7 @@
 import org.chromium.base.test.util.Feature;
 import org.chromium.chrome.browser.test.ChromeBrowserTestRule;
 import org.chromium.chrome.browser.test.CommandLineInitRule;
+import org.chromium.chrome.browser.util.UrlConstants;
 
 import java.util.ArrayList;
 import java.util.List;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/MainActivityWithURLTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/MainActivityWithURLTest.java
index f010c57..b9bcbea5 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/MainActivityWithURLTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/MainActivityWithURLTest.java
@@ -16,6 +16,7 @@
 import org.chromium.base.test.util.Feature;
 import org.chromium.base.test.util.RetryOnFailure;
 import org.chromium.chrome.browser.tabmodel.TabModel;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.util.ChromeTabUtils;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/TabsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/TabsTest.java
index 603206ba..76fd814d 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/TabsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/TabsTest.java
@@ -66,6 +66,7 @@
 import org.chromium.chrome.browser.tabmodel.TabSelectionType;
 import org.chromium.chrome.browser.tabmodel.TabbedModeTabPersistencePolicy;
 import org.chromium.chrome.browser.toolbar.top.ToggleTabStackButton;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.util.ApplicationTestUtils;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkTest.java
index c1b22bd..13159fe 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkTest.java
@@ -33,9 +33,9 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.ChromeSwitches;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkItem;
 import org.chromium.chrome.browser.partnerbookmarks.PartnerBookmarksShim;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.chrome.browser.widget.selection.SelectableListToolbar;
 import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/download/home/DownloadActivityV2Test.java b/chrome/android/javatests/src/org/chromium/chrome/browser/download/home/DownloadActivityV2Test.java
index 4c10775..c20dcc3d 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/download/home/DownloadActivityV2Test.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/download/home/DownloadActivityV2Test.java
@@ -19,7 +19,6 @@
 
 import org.chromium.base.test.util.Restriction;
 import org.chromium.chrome.browser.ChromeFeatureList;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.download.home.filter.FilterCoordinator;
 import org.chromium.chrome.browser.download.home.list.UiUtils;
 import org.chromium.chrome.browser.download.items.OfflineContentAggregatorFactory;
@@ -27,6 +26,7 @@
 import org.chromium.chrome.browser.feature_engagement.TrackerFactory;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.snackbar.SnackbarManager;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ui.DummyUiActivityTestCase;
 import org.chromium.components.feature_engagement.Tracker;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/explore_sites/ExploreSitesPageTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/explore_sites/ExploreSitesPageTest.java
index 57d6c8e..23333d0 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/explore_sites/ExploreSitesPageTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/explore_sites/ExploreSitesPageTest.java
@@ -33,9 +33,9 @@
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.ChromeFeatureList;
 import org.chromium.chrome.browser.ChromeSwitches;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.util.FeatureUtilities;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.util.RenderTestRule;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/feed/FeedAppLifecycleTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/feed/FeedAppLifecycleTest.java
index 069b680c..6bad1c61 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/feed/FeedAppLifecycleTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/feed/FeedAppLifecycleTest.java
@@ -37,7 +37,6 @@
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.ChromeTabbedActivity;
 import org.chromium.chrome.browser.DeferredStartupHandler;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.feed.FeedAppLifecycle.AppLifecycleEvent;
 import org.chromium.chrome.browser.init.ChromeBrowserInitializer;
 import org.chromium.chrome.browser.multiwindow.MultiWindowTestHelper;
@@ -45,6 +44,7 @@
 import org.chromium.chrome.browser.preferences.Pref;
 import org.chromium.chrome.browser.preferences.PrefServiceBridge;
 import org.chromium.chrome.browser.profiles.Profile;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.util.browser.Features.EnableFeatures;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/feed/FeedNewTabPageTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/feed/FeedNewTabPageTest.java
index 30d29ed..0ef585d3 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/feed/FeedNewTabPageTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/feed/FeedNewTabPageTest.java
@@ -38,7 +38,6 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeFeatureList;
 import org.chromium.chrome.browser.ChromeSwitches;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.ntp.cards.SignInPromo;
 import org.chromium.chrome.browser.ntp.snippets.SectionHeader;
 import org.chromium.chrome.browser.preferences.ChromePreferenceManager;
@@ -46,6 +45,7 @@
 import org.chromium.chrome.browser.preferences.PrefServiceBridge;
 import org.chromium.chrome.browser.suggestions.SiteSuggestion;
 import org.chromium.chrome.browser.tab.Tab;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.util.ChromeTabUtils;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/gesturenav/NavigationHandlerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/gesturenav/NavigationHandlerTest.java
index aec74abe..bfb944d 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/gesturenav/NavigationHandlerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/gesturenav/NavigationHandlerTest.java
@@ -23,8 +23,8 @@
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.RetryOnFailure;
 import org.chromium.chrome.browser.ChromeSwitches;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.tab.Tab;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.util.ChromeTabUtils;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageLoadTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageLoadTest.java
index ae514f1..a3edb257 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageLoadTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageLoadTest.java
@@ -21,12 +21,12 @@
 
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.chrome.browser.ChromeSwitches;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.favicon.IconType;
 import org.chromium.chrome.browser.favicon.LargeIconBridge;
 import org.chromium.chrome.browser.suggestions.tile.Tile;
 import org.chromium.chrome.browser.suggestions.tile.TileVisualType;
 import org.chromium.chrome.browser.tab.Tab;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.util.NewTabPageTestUtils;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageNavigationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageNavigationTest.java
index 6154c9ef..d990354d 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageNavigationTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageNavigationTest.java
@@ -19,8 +19,8 @@
 import org.chromium.base.test.util.Feature;
 import org.chromium.base.test.util.RetryOnFailure;
 import org.chromium.chrome.browser.ChromeSwitches;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.tab.Tab;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.net.test.EmbeddedTestServer;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java
index 345118c..e7e90a4 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java
@@ -49,7 +49,6 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeFeatureList;
 import org.chromium.chrome.browser.ChromeSwitches;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.feed.FeedNewTabPage;
 import org.chromium.chrome.browser.feed.FeedProcessScopeFactory;
 import org.chromium.chrome.browser.feed.TestNetworkClient;
@@ -67,6 +66,7 @@
 import org.chromium.chrome.browser.suggestions.SiteSuggestion;
 import org.chromium.chrome.browser.tab.EmptyTabObserver;
 import org.chromium.chrome.browser.tab.Tab;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.chrome.browser.widget.ScrimView;
 import org.chromium.chrome.test.ChromeJUnit4RunnerDelegate;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageUiCaptureTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageUiCaptureTest.java
index eae99feb..537656b0 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageUiCaptureTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageUiCaptureTest.java
@@ -19,10 +19,10 @@
 import org.chromium.base.test.util.Feature;
 import org.chromium.chrome.browser.ChromeFeatureList;
 import org.chromium.chrome.browser.ChromeSwitches;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.ntp.cards.NewTabPageRecyclerView;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.test.ScreenShooter;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.util.NewTabPageTestUtils;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/RecentTabsPageTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/RecentTabsPageTest.java
index 24ffc3b..1f79feb 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/RecentTabsPageTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/RecentTabsPageTest.java
@@ -19,8 +19,8 @@
 import org.chromium.base.test.util.Feature;
 import org.chromium.base.test.util.RetryOnFailure;
 import org.chromium.chrome.browser.ChromeSwitches;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.tab.Tab;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.content_public.browser.test.util.Criteria;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/cards/NewTabPageRecyclerViewTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/cards/NewTabPageRecyclerViewTest.java
index 086ce3f..da8708d 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/cards/NewTabPageRecyclerViewTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/cards/NewTabPageRecyclerViewTest.java
@@ -28,7 +28,6 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeFeatureList;
 import org.chromium.chrome.browser.ChromeSwitches;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.native_page.ContextMenuManager;
 import org.chromium.chrome.browser.ntp.NewTabPage;
 import org.chromium.chrome.browser.ntp.NewTabPageView;
@@ -39,6 +38,7 @@
 import org.chromium.chrome.browser.ntp.snippets.SnippetArticle;
 import org.chromium.chrome.browser.suggestions.ContentSuggestionsAdditionalAction;
 import org.chromium.chrome.browser.tab.Tab;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.util.ChromeTabUtils;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageAutoFetchTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageAutoFetchTest.java
index 04779a0..a8936fc 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageAutoFetchTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageAutoFetchTest.java
@@ -27,13 +27,13 @@
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.DeviceConditions;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.offlinepages.AutoFetchNotifier.NotificationAction;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tabmodel.TabLaunchType;
 import org.chromium.chrome.browser.tabmodel.TabModel;
 import org.chromium.chrome.browser.tabmodel.TabModelUtils;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.util.ChromeRestriction;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/indicator/OfflineIndicatorControllerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/indicator/OfflineIndicatorControllerTest.java
index ec0932f..9c8cbd5e 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/indicator/OfflineIndicatorControllerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/indicator/OfflineIndicatorControllerTest.java
@@ -20,7 +20,6 @@
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.ChromeFeatureList;
 import org.chromium.chrome.browser.ChromeSwitches;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.download.DownloadActivity;
 import org.chromium.chrome.browser.offlinepages.ClientId;
 import org.chromium.chrome.browser.offlinepages.OfflinePageBridge;
@@ -29,6 +28,7 @@
 import org.chromium.chrome.browser.snackbar.SnackbarManager;
 import org.chromium.chrome.browser.snackbar.SnackbarManager.SnackbarManageable;
 import org.chromium.chrome.browser.tab.Tab;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.util.ActivityUtils;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/prefetch/PrefetchFeedFlowTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/prefetch/PrefetchFeedFlowTest.java
index 34bea1cb..a85497d 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/prefetch/PrefetchFeedFlowTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/prefetch/PrefetchFeedFlowTest.java
@@ -29,7 +29,6 @@
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.ChromeFeatureList;
 import org.chromium.chrome.browser.ChromeSwitches;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.download.items.OfflineContentAggregatorFactory;
 import org.chromium.chrome.browser.feed.FeedProcessScopeFactory;
 import org.chromium.chrome.browser.feed.TestNetworkClient;
@@ -38,6 +37,7 @@
 import org.chromium.chrome.browser.offlinepages.OfflineTestUtil;
 import org.chromium.chrome.browser.preferences.PrefServiceBridge;
 import org.chromium.chrome.browser.profiles.Profile;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.util.ChromeRestriction;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/prefetch/PrefetchFlowTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/prefetch/PrefetchFlowTest.java
index 34a9753c..fa0cdb4 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/prefetch/PrefetchFlowTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/prefetch/PrefetchFlowTest.java
@@ -24,12 +24,12 @@
 import org.chromium.base.test.util.RetryOnFailure;
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.ChromeSwitches;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.offlinepages.OfflinePageBridge;
 import org.chromium.chrome.browser.offlinepages.OfflinePageItem;
 import org.chromium.chrome.browser.offlinepages.OfflineTestUtil;
 import org.chromium.chrome.browser.preferences.PrefServiceBridge;
 import org.chromium.chrome.browser.profiles.Profile;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.util.ChromeRestriction;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omaha/UpdateMenuItemHelperTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omaha/UpdateMenuItemHelperTest.java
index c9f7a13..b9d93bd 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/omaha/UpdateMenuItemHelperTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omaha/UpdateMenuItemHelperTest.java
@@ -20,8 +20,8 @@
 import org.chromium.base.test.util.RetryOnFailure;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeSwitches;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.appmenu.AppMenuTestSupport;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.util.OverviewModeBehaviorWatcher;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/partnercustomizations/PartnerHomepageUnitTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/partnercustomizations/PartnerHomepageUnitTest.java
index 7d9c0c5..1460680 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/partnercustomizations/PartnerHomepageUnitTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/partnercustomizations/PartnerHomepageUnitTest.java
@@ -24,9 +24,9 @@
 import org.chromium.base.test.util.Feature;
 import org.chromium.base.test.util.RetryOnFailure;
 import org.chromium.chrome.browser.ChromeFeatureList;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.preferences.ChromePreferenceManager;
 import org.chromium.chrome.browser.util.FeatureUtilities;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.partnercustomizations.TestPartnerBrowserCustomizationsDelayedProvider;
 import org.chromium.chrome.test.partnercustomizations.TestPartnerBrowserCustomizationsProvider;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/ContentSuggestionsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/ContentSuggestionsTest.java
index 710b39e2..c1f1b95 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/ContentSuggestionsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/ContentSuggestionsTest.java
@@ -17,7 +17,6 @@
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.ChromeFeatureList;
 import org.chromium.chrome.browser.ChromeSwitches;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.ntp.NewTabPage;
 import org.chromium.chrome.browser.ntp.snippets.CategoryInt;
 import org.chromium.chrome.browser.ntp.snippets.KnownCategories;
@@ -25,6 +24,7 @@
 import org.chromium.chrome.browser.ntp.snippets.SuggestionsSource;
 import org.chromium.chrome.browser.preferences.PrefServiceBridge;
 import org.chromium.chrome.browser.tab.Tab;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.util.NewTabPageTestUtils;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/NavigationRecorderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/NavigationRecorderTest.java
index e0fbcdf..9ad60092 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/NavigationRecorderTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/NavigationRecorderTest.java
@@ -21,8 +21,8 @@
 import org.chromium.base.test.util.CallbackHelper;
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.chrome.browser.ChromeSwitches;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.tab.Tab;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.util.ChromeTabUtils;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/tile/TileGridLayoutTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/tile/TileGridLayoutTest.java
index 81ba1615..e3caeb60 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/tile/TileGridLayoutTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/tile/TileGridLayoutTest.java
@@ -38,7 +38,6 @@
 import org.chromium.chrome.browser.ChromeApplication;
 import org.chromium.chrome.browser.ChromeFeatureList;
 import org.chromium.chrome.browser.ChromeSwitches;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.ntp.NewTabPage;
 import org.chromium.chrome.browser.ntp.cards.NewTabPageViewHolder.PartialBindCallback;
 import org.chromium.chrome.browser.offlinepages.OfflinePageItem;
@@ -47,6 +46,7 @@
 import org.chromium.chrome.browser.suggestions.SuggestionsUiDelegate;
 import org.chromium.chrome.browser.suggestions.SuggestionsUiDelegateImpl;
 import org.chromium.chrome.browser.tab.Tab;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.chrome.browser.util.ViewUtils;
 import org.chromium.chrome.browser.widget.displaystyle.UiConfig;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/tile/TileGroupTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/tile/TileGroupTest.java
index 4c4e7fe..8db90f6 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/tile/TileGroupTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/suggestions/tile/TileGroupTest.java
@@ -25,7 +25,6 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.ChromeSwitches;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.explore_sites.ExploreSitesBridge;
 import org.chromium.chrome.browser.explore_sites.ExploreSitesCategory;
 import org.chromium.chrome.browser.native_page.ContextMenuManager;
@@ -33,6 +32,7 @@
 import org.chromium.chrome.browser.snackbar.SnackbarManager;
 import org.chromium.chrome.browser.suggestions.SiteSuggestion;
 import org.chromium.chrome.browser.tab.Tab;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.util.NewTabPageTestUtils;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/LocationBarModelTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/LocationBarModelTest.java
index 88f8cae6..7127f74 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/LocationBarModelTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/LocationBarModelTest.java
@@ -21,11 +21,11 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.ChromeTabbedActivity;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.omnibox.UrlBarData;
 import org.chromium.chrome.browser.tab.MockTab;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.toolbar.top.ToolbarLayout;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.util.ChromeTabUtils;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/ToolbarTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/ToolbarTest.java
index 29e7a14..2d52224 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/ToolbarTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/ToolbarTest.java
@@ -19,9 +19,9 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.ChromeSwitches;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.omnibox.UrlBar;
 import org.chromium.chrome.browser.tab.Tab;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.chrome.browser.widget.findinpage.FindToolbar;
 import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrBrowserControllerInputTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrBrowserControllerInputTest.java
index f0b9bd3..4f8465b91 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrBrowserControllerInputTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrBrowserControllerInputTest.java
@@ -25,8 +25,8 @@
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.Restriction;
 import org.chromium.chrome.browser.ChromeSwitches;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.history.HistoryPage;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.chrome.browser.vr.rules.ChromeTabbedActivityVrTestRule;
 import org.chromium.chrome.browser.vr.util.NativeUiUtils;
 import org.chromium.chrome.browser.vr.util.VrBrowserTransitionUtils;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrBrowserNavigationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrBrowserNavigationTest.java
index 23344fe..c1969efa 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrBrowserNavigationTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrBrowserNavigationTest.java
@@ -26,13 +26,13 @@
 import org.chromium.base.test.util.Feature;
 import org.chromium.base.test.util.Restriction;
 import org.chromium.chrome.browser.ChromeSwitches;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.history.HistoryItemView;
 import org.chromium.chrome.browser.history.HistoryPage;
 import org.chromium.chrome.browser.ntp.NewTabPage;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tabmodel.TabLaunchType;
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.chrome.browser.vr.rules.ChromeTabbedActivityVrTestRule;
 import org.chromium.chrome.browser.vr.util.NativeUiUtils;
 import org.chromium.chrome.browser.vr.util.RenderTestUtils;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrBrowserTransitionTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrBrowserTransitionTest.java
index 43d183c..7f23715 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrBrowserTransitionTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrBrowserTransitionTest.java
@@ -33,11 +33,11 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.ChromeTabbedActivity;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.ntp.IncognitoNewTabPage;
 import org.chromium.chrome.browser.preferences.Preferences;
 import org.chromium.chrome.browser.preferences.PreferencesLauncher;
 import org.chromium.chrome.browser.preferences.website.SingleWebsitePreferences;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.chrome.browser.vr.mock.MockVrDaydreamApi;
 import org.chromium.chrome.browser.vr.rules.ChromeTabbedActivityVrTestRule;
 import org.chromium.chrome.browser.vr.util.NativeUiUtils;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/XrTestFramework.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/XrTestFramework.java
index f39b005..f922dbf 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/XrTestFramework.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/XrTestFramework.java
@@ -11,10 +11,10 @@
 
 import org.chromium.base.Log;
 import org.chromium.base.test.util.UrlUtils;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.tab.SadTab;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tabmodel.TabLaunchType;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.util.ChromeTabUtils;
 import org.chromium.content_public.browser.WebContents;
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/native_page/NativePageFactoryTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/native_page/NativePageFactoryTest.java
index 39bc2bd..c913a5b 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/native_page/NativePageFactoryTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/native_page/NativePageFactoryTest.java
@@ -14,10 +14,10 @@
 
 import org.chromium.base.test.BaseRobolectricTestRunner;
 import org.chromium.chrome.browser.ChromeActivity;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.native_page.NativePageFactory.NativePageType;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
+import org.chromium.chrome.browser.util.UrlConstants;
 
 /**
  * Tests public methods in NativePageFactory.
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/tabmodel/TabPersistentStoreUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/tabmodel/TabPersistentStoreUnitTest.java
index 0bf5ccb..601705c 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/tabmodel/TabPersistentStoreUnitTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/tabmodel/TabPersistentStoreUnitTest.java
@@ -31,12 +31,12 @@
 import org.chromium.base.task.TaskRunner;
 import org.chromium.base.test.BaseRobolectricTestRunner;
 import org.chromium.base.test.util.Feature;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tab.TabState;
 import org.chromium.chrome.browser.tabmodel.TabCreatorManager.TabCreator;
 import org.chromium.chrome.browser.tabmodel.TabPersistentStore.TabPersistentStoreObserver;
 import org.chromium.chrome.browser.tabmodel.TabPersistentStore.TabRestoreDetails;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.content_public.browser.LoadUrlParams;
 
 /**
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/DinoActivity.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/DinoActivity.java
index 79855f8..4ab9a92 100644
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/DinoActivity.java
+++ b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/DinoActivity.java
@@ -10,11 +10,11 @@
 
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.SingleTabActivity;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.compositor.layouts.LayoutManager;
 import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tab.TabState;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.content_public.browser.LoadUrlParams;
 import org.chromium.ui.base.PageTransition;
 
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/NoTouchActivity.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/NoTouchActivity.java
index e0f916e..a7723e9a 100644
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/NoTouchActivity.java
+++ b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/NoTouchActivity.java
@@ -4,7 +4,7 @@
 
 package org.chromium.chrome.browser.touchless;
 
-import static org.chromium.chrome.browser.UrlConstants.NTP_URL;
+import static org.chromium.chrome.browser.util.UrlConstants.NTP_URL;
 
 import android.content.Intent;
 import android.net.Uri;
@@ -20,7 +20,6 @@
 import org.chromium.chrome.browser.IntentHandler.IntentHandlerDelegate;
 import org.chromium.chrome.browser.IntentHandler.TabOpenType;
 import org.chromium.chrome.browser.SingleTabActivity;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.compositor.layouts.LayoutManager;
 import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager;
 import org.chromium.chrome.browser.preferences.ChromePreferenceManager;
@@ -28,6 +27,7 @@
 import org.chromium.chrome.browser.tab.TabRedirectHandler;
 import org.chromium.chrome.browser.tab.TabState;
 import org.chromium.chrome.browser.tabmodel.document.TabDelegate;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.content_public.browser.LoadUrlParams;
 import org.chromium.content_public.common.Referrer;
 import org.chromium.ui.base.PageTransition;
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionModel.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionModel.java
index d8ffa75..969b06b 100644
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionModel.java
+++ b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionModel.java
@@ -25,19 +25,23 @@
             new PropertyModel.ReadableObjectPropertyKey<>();
     static final PropertyModel.WritableObjectPropertyKey<Bitmap> ICON_KEY =
             new PropertyModel.WritableObjectPropertyKey<>();
+    static final PropertyModel.ReadableObjectPropertyKey<Bitmap> DEFAULT_ICON_KEY =
+            new PropertyModel.ReadableObjectPropertyKey<>();
 
-    static PropertyModel getSiteSuggestionModel(SiteSuggestion suggestion) {
+    static PropertyModel getSiteSuggestionModel(SiteSuggestion suggestion, Bitmap defaultIcon) {
         String title = UrlUtilities.getDomainAndRegistry(suggestion.url, false);
         if (TextUtils.isEmpty(title)) {
             // Fallback to title.
             title = suggestion.title;
         }
         return new PropertyModel
-                .Builder(TITLE_KEY, URL_KEY, ICON_KEY, SOURCE_KEY, WHITELIST_ICON_PATH_KEY)
+                .Builder(TITLE_KEY, URL_KEY, ICON_KEY, SOURCE_KEY, WHITELIST_ICON_PATH_KEY,
+                        DEFAULT_ICON_KEY)
                 .with(TITLE_KEY, title)
                 .with(URL_KEY, suggestion.url)
                 .with(SOURCE_KEY, suggestion.source)
                 .with(WHITELIST_ICON_PATH_KEY, suggestion.whitelistIconPath)
+                .with(DEFAULT_ICON_KEY, defaultIcon)
                 .build();
     }
 }
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionsAdapter.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionsAdapter.java
index b2533f4..e90da67 100644
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionsAdapter.java
+++ b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionsAdapter.java
@@ -17,15 +17,13 @@
 import android.support.annotation.IntDef;
 import android.support.annotation.Nullable;
 import android.support.graphics.drawable.VectorDrawableCompat;
-import android.support.v7.widget.RecyclerView;
 import android.view.ContextMenu;
 import android.view.View;
 import android.widget.TextView;
 
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.native_page.ContextMenuManager;
 import org.chromium.chrome.browser.suggestions.SuggestionsNavigationDelegate;
-import org.chromium.chrome.browser.widget.RoundedIconGenerator;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.chrome.touchless.R;
 import org.chromium.ui.modelutil.ForwardingListObservable;
 import org.chromium.ui.modelutil.PropertyKey;
@@ -110,38 +108,34 @@
 
         @Override
         public Bitmap getIconBitmap() {
+            if (mSuggestion.get(SiteSuggestionModel.ICON_KEY) == null) {
+                return mSuggestion.get(SiteSuggestionModel.DEFAULT_ICON_KEY);
+            }
             return mSuggestion.get(SiteSuggestionModel.ICON_KEY);
         }
     }
 
     private PropertyModel mModel;
-    private RoundedIconGenerator mIconGenerator;
     private SuggestionsNavigationDelegate mNavDelegate;
     private ContextMenuManager mContextMenuManager;
     private SiteSuggestionsLayoutManager mLayoutManager;
     private TextView mTitleView;
 
-    private final RecyclerView mRecyclerView;
-
     /**
      * @param model the main property model coming from {@link SiteSuggestionsCoordinator}.
-     * @param iconGenerator an icon generator for creating icons.
      * @param navigationDelegate delegate for navigation controls
      * @param contextMenuManager handles context menu creation
      * @param layoutManager the layout manager controlling this recyclerview and adapter
      * @param titleView the view to update site title when focus changes.
      */
-    SiteSuggestionsAdapter(PropertyModel model, RoundedIconGenerator iconGenerator,
-            SuggestionsNavigationDelegate navigationDelegate, ContextMenuManager contextMenuManager,
-            SiteSuggestionsLayoutManager layoutManager, TextView titleView,
-            RecyclerView recyclerView) {
+    SiteSuggestionsAdapter(PropertyModel model, SuggestionsNavigationDelegate navigationDelegate,
+            ContextMenuManager contextMenuManager, SiteSuggestionsLayoutManager layoutManager,
+            TextView titleView) {
         mModel = model;
-        mIconGenerator = iconGenerator;
         mNavDelegate = navigationDelegate;
         mContextMenuManager = contextMenuManager;
         mLayoutManager = layoutManager;
         mTitleView = titleView;
-        mRecyclerView = recyclerView;
 
         mModel.get(SUGGESTIONS_KEY).addObserver(this);
         mModel.addObserver(this);
@@ -195,11 +189,10 @@
             // Only update the icon for icon updates.
             if (payload == SiteSuggestionModel.ICON_KEY) {
                 tile.updateIcon(item.get(SiteSuggestionModel.ICON_KEY),
-                        item.get(SiteSuggestionModel.TITLE_KEY));
+                        item.get(SiteSuggestionModel.DEFAULT_ICON_KEY));
             } else {
-                tile.initialize(mIconGenerator);
                 tile.updateIcon(item.get(SiteSuggestionModel.ICON_KEY),
-                        item.get(SiteSuggestionModel.TITLE_KEY));
+                        item.get(SiteSuggestionModel.DEFAULT_ICON_KEY));
 
                 SiteSuggestionInteractionDelegate interactionDelegate =
                         new SiteSuggestionInteractionDelegate(item);
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionsCoordinator.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionsCoordinator.java
index 57cb334f..f8d835cd 100644
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionsCoordinator.java
+++ b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionsCoordinator.java
@@ -73,9 +73,9 @@
 
         RecyclerView recyclerView =
                 suggestionsView.findViewById(R.id.most_likely_launcher_recycler);
-        SiteSuggestionsAdapter adapterDelegate = new SiteSuggestionsAdapter(model, iconGenerator,
+        SiteSuggestionsAdapter adapterDelegate = new SiteSuggestionsAdapter(model,
                 navigationDelegate, contextMenuManager, layoutManager,
-                suggestionsView.findViewById(R.id.most_likely_web_title_text), recyclerView);
+                suggestionsView.findViewById(R.id.most_likely_web_title_text));
 
         RecyclerViewAdapter<SiteSuggestionsViewHolderFactory.SiteSuggestionsViewHolder, PropertyKey>
                 adapter = new RecyclerViewAdapter<>(
@@ -98,7 +98,8 @@
         recyclerView.setLayoutManager(layoutManager);
         recyclerView.setAdapter(adapter);
 
-        mMediator = new SiteSuggestionsMediator(model, profile, imageFetcher, iconSize);
+        mMediator =
+                new SiteSuggestionsMediator(model, profile, imageFetcher, iconGenerator, iconSize);
     }
 
     public void destroy() {
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionsMediator.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionsMediator.java
index e19bb5a..6ea02845 100644
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionsMediator.java
+++ b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionsMediator.java
@@ -19,6 +19,7 @@
 import org.chromium.chrome.browser.suggestions.SiteSuggestion;
 import org.chromium.chrome.browser.suggestions.SuggestionsDependencyFactory;
 import org.chromium.chrome.browser.suggestions.mostvisited.MostVisitedSites;
+import org.chromium.chrome.browser.widget.RoundedIconGenerator;
 import org.chromium.chrome.touchless.R;
 import org.chromium.ui.modelutil.PropertyKey;
 import org.chromium.ui.modelutil.PropertyModel;
@@ -49,6 +50,7 @@
     private ImageFetcher mImageFetcher;
     private MostVisitedSites mMostVisitedSites;
     private Profile mProfile;
+    private RoundedIconGenerator mDefaultIconGenerator;
     private int mIconSize;
 
     // Whether we should set focus to the data. Used to delay focus-setting until after loading
@@ -57,12 +59,13 @@
     // Whether we have pending requests for suggestions.
     private boolean mHasPendingRequests;
 
-    SiteSuggestionsMediator(
-            PropertyModel model, Profile profile, ImageFetcher imageFetcher, int minIconSize) {
+    SiteSuggestionsMediator(PropertyModel model, Profile profile, ImageFetcher imageFetcher,
+            RoundedIconGenerator iconGenerator, int minIconSize) {
         mModel = model;
         mImageFetcher = imageFetcher;
         mIconSize = minIconSize;
         mProfile = profile;
+        mDefaultIconGenerator = iconGenerator;
 
         mHasPendingRequests = true;
         mMostVisitedSites =
@@ -89,7 +92,8 @@
             // Do not put duplicates.
             if (urls.contains(suggestion.url)) continue;
 
-            PropertyModel siteSuggestion = SiteSuggestionModel.getSiteSuggestionModel(suggestion);
+            PropertyModel siteSuggestion = SiteSuggestionModel.getSiteSuggestionModel(
+                    suggestion, mDefaultIconGenerator.generateIconForText(suggestion.title));
             modelList.add(siteSuggestion);
             if (suggestion.whitelistIconPath.isEmpty()) {
                 makeIconRequest(siteSuggestion);
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionsTileView.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionsTileView.java
index cdf1316..42519ff 100644
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionsTileView.java
+++ b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/SiteSuggestionsTileView.java
@@ -11,7 +11,6 @@
 import android.util.AttributeSet;
 
 import org.chromium.chrome.browser.util.ViewUtils;
-import org.chromium.chrome.browser.widget.RoundedIconGenerator;
 import org.chromium.chrome.browser.widget.tile.TileView;
 import org.chromium.chrome.touchless.R;
 
@@ -21,8 +20,6 @@
 public class SiteSuggestionsTileView extends TileView {
     private final int mIconSizePx;
 
-    // Used to generate textual icons.
-    private RoundedIconGenerator mIconGenerator;
 
     public SiteSuggestionsTileView(Context ctx, AttributeSet attrs) {
         super(ctx, attrs);
@@ -30,33 +27,25 @@
     }
 
     /**
-     * Initializes the icon generator and clears the model processor attached to this view.
-     * @param generator The generator for icons.
-     */
-    public void initialize(RoundedIconGenerator generator) {
-        mIconGenerator = generator;
-    }
-
-    /**
      * Updates the icon in the tile.
      *
      * @param iconImage Bitmap icon to update.
-     * @param text Text to generate scrabble text from.
+     * @param defaultIcon Default icon for the tile.
      */
-    public void updateIcon(Bitmap iconImage, String text) {
-        setIconDrawable(getDrawableForBitmap(iconImage, text));
+    public void updateIcon(Bitmap iconImage, Bitmap defaultIcon) {
+        setIconDrawable(getDrawableForBitmap(iconImage, defaultIcon));
     }
 
     /**
      * Generates a Drawable from the Bitmap version of an icon.
      *
      * @param image The Bitmap image. Can be null.
-     * @param text The text to generate a scrabble text from if the bitmap is null.
+     * @param defaultIcon Default icon for the tile.
      * @return Drawable encapsulating either the scrabble tile or the bitmap.
      */
-    public Drawable getDrawableForBitmap(Bitmap image, String text) {
+    public Drawable getDrawableForBitmap(Bitmap image, Bitmap defaultIcon) {
         if (image == null) {
-            return new BitmapDrawable(getResources(), mIconGenerator.generateIconForText(text));
+            return new BitmapDrawable(getResources(), defaultIcon);
         }
         return ViewUtils.createRoundedBitmapDrawable(
                 Bitmap.createScaledBitmap(image, mIconSizePx, mIconSizePx, false),
diff --git a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessNewTabPage.java b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessNewTabPage.java
index 03ad3258..98c94140 100644
--- a/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessNewTabPage.java
+++ b/chrome/android/touchless/java/src/org/chromium/chrome/browser/touchless/TouchlessNewTabPage.java
@@ -12,7 +12,6 @@
 import org.chromium.base.ApiCompatibilityUtils;
 import org.chromium.base.TraceEvent;
 import org.chromium.chrome.browser.ChromeActivity;
-import org.chromium.chrome.browser.UrlConstants;
 import org.chromium.chrome.browser.native_page.BasicNativePage;
 import org.chromium.chrome.browser.native_page.ContextMenuManager;
 import org.chromium.chrome.browser.native_page.NativePageHost;
@@ -28,6 +27,7 @@
 import org.chromium.chrome.browser.suggestions.SuggestionsUiDelegateImpl;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
+import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.chrome.browser.widget.displaystyle.UiConfig;
 import org.chromium.chrome.touchless.R;
 import org.chromium.ui.modaldialog.ModalDialogManager;
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 9a7638c..d43a3efc 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -115,12 +115,12 @@
     "autocomplete/chrome_autocomplete_provider_client.h",
     "autocomplete/chrome_autocomplete_scheme_classifier.cc",
     "autocomplete/chrome_autocomplete_scheme_classifier.h",
-    "autocomplete/contextual_suggestions_service_factory.cc",
-    "autocomplete/contextual_suggestions_service_factory.h",
     "autocomplete/document_suggestions_service_factory.cc",
     "autocomplete/document_suggestions_service_factory.h",
     "autocomplete/in_memory_url_index_factory.cc",
     "autocomplete/in_memory_url_index_factory.h",
+    "autocomplete/remote_suggestions_service_factory.cc",
+    "autocomplete/remote_suggestions_service_factory.h",
     "autocomplete/shortcuts_backend_factory.cc",
     "autocomplete/shortcuts_backend_factory.h",
     "autofill/address_normalizer_factory.cc",
@@ -2567,7 +2567,6 @@
       "android/thumbnail/thumbnail_cache.h",
       "android/trusted_cdn.cc",
       "android/trusted_cdn.h",
-      "android/url_utilities.cc",
       "android/usage_stats/notification_suspender.cc",
       "android/usage_stats/usage_stats_bridge.cc",
       "android/usage_stats/usage_stats_bridge.h",
@@ -2575,6 +2574,7 @@
       "android/usage_stats/usage_stats_database.h",
       "android/usb/web_usb_chooser_android.cc",
       "android/usb/web_usb_chooser_android.h",
+      "android/util/url_utilities.cc",
       "android/warmup_manager.cc",
       "android/web_contents_factory.cc",
       "android/webapk/chrome_webapk_host.cc",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index a39580c..3637d9f24 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -3908,6 +3908,7 @@
      flag_descriptions::kEnableAutofillCreditCardUploadFeedbackDescription,
      kOsWin | kOsMac | kOsLinux,
      FEATURE_VALUE_TYPE(autofill::features::kAutofillCreditCardUploadFeedback)},
+
     {"periodic-background-sync", flag_descriptions::kPeriodicBackgroundSyncName,
      flag_descriptions::kPeriodicBackgroundSyncDescription, kOsAll,
      FEATURE_VALUE_TYPE(features::kPeriodicBackgroundSync)},
diff --git a/chrome/browser/android/url_utilities.cc b/chrome/browser/android/util/url_utilities.cc
similarity index 91%
rename from chrome/browser/android/url_utilities.cc
rename to chrome/browser/android/util/url_utilities.cc
index b4fc8cb6..aa9be11 100644
--- a/chrome/browser/android/url_utilities.cc
+++ b/chrome/browser/android/util/url_utilities.cc
@@ -18,23 +18,22 @@
 
 namespace {
 
-static const char* const g_supported_schemes[] = { "about", "data", "file",
-    "http", "https", "inline", "javascript", nullptr };
+static const char* const g_supported_schemes[] = {
+    "about", "data", "file", "http", "https", "inline", "javascript", nullptr};
 
 static const char* const g_downloadable_schemes[] = {
-    "data", "blob", "file", "filesystem", "http", "https", nullptr };
+    "data", "blob", "file", "filesystem", "http", "https", nullptr};
 
-static const char* const g_fallback_valid_schemes[] = {
-    "http", "https", nullptr };
+static const char* const g_fallback_valid_schemes[] = {"http", "https",
+                                                       nullptr};
 
 GURL JNI_UrlUtilities_ConvertJavaStringToGURL(JNIEnv* env, jstring url) {
   return url ? GURL(ConvertJavaStringToUTF8(env, url)) : GURL();
 }
 
-bool CheckSchemeBelongsToList(
-    JNIEnv* env,
-    const JavaParamRef<jstring>& url,
-    const char* const* scheme_list) {
+bool CheckSchemeBelongsToList(JNIEnv* env,
+                              const JavaParamRef<jstring>& url,
+                              const char* const* scheme_list) {
   GURL gurl = JNI_UrlUtilities_ConvertJavaStringToGURL(env, url);
   if (gurl.is_valid()) {
     for (size_t i = 0; scheme_list[i]; i++) {
@@ -49,8 +48,8 @@
 net::registry_controlled_domains::PrivateRegistryFilter GetRegistryFilter(
     jboolean include_private) {
   return include_private
-      ? net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES
-      : net::registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES;
+             ? net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES
+             : net::registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES;
 }
 
 }  // namespace
@@ -68,8 +67,7 @@
   net::registry_controlled_domains::PrivateRegistryFilter filter =
       GetRegistryFilter(include_private);
 
-  return net::registry_controlled_domains::SameDomainOrHost(url_1,
-                                                            url_2,
+  return net::registry_controlled_domains::SameDomainOrHost(url_1, url_2,
                                                             filter);
 }
 
diff --git a/chrome/browser/autocomplete/autocomplete_classifier_factory.cc b/chrome/browser/autocomplete/autocomplete_classifier_factory.cc
index e315914..7f4dd5ff 100644
--- a/chrome/browser/autocomplete/autocomplete_classifier_factory.cc
+++ b/chrome/browser/autocomplete/autocomplete_classifier_factory.cc
@@ -8,8 +8,8 @@
 
 #include "chrome/browser/autocomplete/chrome_autocomplete_provider_client.h"
 #include "chrome/browser/autocomplete/chrome_autocomplete_scheme_classifier.h"
-#include "chrome/browser/autocomplete/contextual_suggestions_service_factory.h"
 #include "chrome/browser/autocomplete/in_memory_url_index_factory.h"
+#include "chrome/browser/autocomplete/remote_suggestions_service_factory.h"
 #include "chrome/browser/autocomplete/shortcuts_backend_factory.h"
 #include "chrome/browser/profiles/incognito_helpers.h"
 #include "chrome/browser/profiles/profile.h"
@@ -60,7 +60,7 @@
   //   DependsOn(PrefServiceFactory::GetInstance());
   DependsOn(ShortcutsBackendFactory::GetInstance());
   DependsOn(InMemoryURLIndexFactory::GetInstance());
-  DependsOn(ContextualSuggestionsServiceFactory::GetInstance());
+  DependsOn(RemoteSuggestionsServiceFactory::GetInstance());
 }
 
 AutocompleteClassifierFactory::~AutocompleteClassifierFactory() {
diff --git a/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc b/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc
index fbc5c4e..e73e4ea 100644
--- a/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc
+++ b/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc
@@ -12,9 +12,9 @@
 #include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
 #include "chrome/browser/autocomplete/autocomplete_classifier_factory.h"
-#include "chrome/browser/autocomplete/contextual_suggestions_service_factory.h"
 #include "chrome/browser/autocomplete/document_suggestions_service_factory.h"
 #include "chrome/browser/autocomplete/in_memory_url_index_factory.h"
+#include "chrome/browser/autocomplete/remote_suggestions_service_factory.h"
 #include "chrome/browser/autocomplete/shortcuts_backend_factory.h"
 #include "chrome/browser/bitmap_fetcher/bitmap_fetcher_service.h"
 #include "chrome/browser/bitmap_fetcher/bitmap_fetcher_service_factory.h"
@@ -154,11 +154,11 @@
   return TemplateURLServiceFactory::GetForProfile(profile_);
 }
 
-ContextualSuggestionsService*
-ChromeAutocompleteProviderClient::GetContextualSuggestionsService(
+RemoteSuggestionsService*
+ChromeAutocompleteProviderClient::GetRemoteSuggestionsService(
     bool create_if_necessary) const {
-  return ContextualSuggestionsServiceFactory::GetForProfile(
-      profile_, create_if_necessary);
+  return RemoteSuggestionsServiceFactory::GetForProfile(profile_,
+                                                        create_if_necessary);
 }
 
 DocumentSuggestionsService*
diff --git a/chrome/browser/autocomplete/chrome_autocomplete_provider_client.h b/chrome/browser/autocomplete/chrome_autocomplete_provider_client.h
index 8fe0230..2aee567 100644
--- a/chrome/browser/autocomplete/chrome_autocomplete_provider_client.h
+++ b/chrome/browser/autocomplete/chrome_autocomplete_provider_client.h
@@ -36,7 +36,7 @@
   InMemoryURLIndex* GetInMemoryURLIndex() override;
   TemplateURLService* GetTemplateURLService() override;
   const TemplateURLService* GetTemplateURLService() const override;
-  ContextualSuggestionsService* GetContextualSuggestionsService(
+  RemoteSuggestionsService* GetRemoteSuggestionsService(
       bool create_if_necessary) const override;
   DocumentSuggestionsService* GetDocumentSuggestionsService(
       bool create_if_necessary) const override;
diff --git a/chrome/browser/autocomplete/contextual_suggestions_service_factory.cc b/chrome/browser/autocomplete/contextual_suggestions_service_factory.cc
deleted file mode 100644
index 4c38783..0000000
--- a/chrome/browser/autocomplete/contextual_suggestions_service_factory.cc
+++ /dev/null
@@ -1,46 +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 "chrome/browser/autocomplete/contextual_suggestions_service_factory.h"
-
-#include "base/memory/singleton.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/signin/identity_manager_factory.h"
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
-#include "components/omnibox/browser/contextual_suggestions_service.h"
-#include "content/public/browser/storage_partition.h"
-
-// static
-ContextualSuggestionsService*
-ContextualSuggestionsServiceFactory::GetForProfile(Profile* profile,
-                                                   bool create_if_necessary) {
-  return static_cast<ContextualSuggestionsService*>(
-      GetInstance()->GetServiceForBrowserContext(profile, create_if_necessary));
-}
-
-// static
-ContextualSuggestionsServiceFactory*
-ContextualSuggestionsServiceFactory::GetInstance() {
-  return base::Singleton<ContextualSuggestionsServiceFactory>::get();
-}
-
-KeyedService* ContextualSuggestionsServiceFactory::BuildServiceInstanceFor(
-    content::BrowserContext* context) const {
-  Profile* profile = Profile::FromBrowserContext(context);
-  identity::IdentityManager* identity_manager =
-      IdentityManagerFactory::GetForProfile(profile);
-  return new ContextualSuggestionsService(
-      identity_manager,
-      content::BrowserContext::GetDefaultStoragePartition(profile)
-          ->GetURLLoaderFactoryForBrowserProcess());
-}
-
-ContextualSuggestionsServiceFactory::ContextualSuggestionsServiceFactory()
-    : BrowserContextKeyedServiceFactory(
-          "ContextualSuggestionsService",
-          BrowserContextDependencyManager::GetInstance()) {
-  DependsOn(IdentityManagerFactory::GetInstance());
-}
-
-ContextualSuggestionsServiceFactory::~ContextualSuggestionsServiceFactory() {}
diff --git a/chrome/browser/autocomplete/contextual_suggestions_service_factory.h b/chrome/browser/autocomplete/contextual_suggestions_service_factory.h
deleted file mode 100644
index ccd6a1d..0000000
--- a/chrome/browser/autocomplete/contextual_suggestions_service_factory.h
+++ /dev/null
@@ -1,36 +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 CHROME_BROWSER_AUTOCOMPLETE_CONTEXTUAL_SUGGESTIONS_SERVICE_FACTORY_H_
-#define CHROME_BROWSER_AUTOCOMPLETE_CONTEXTUAL_SUGGESTIONS_SERVICE_FACTORY_H_
-
-#include "base/macros.h"
-#include "base/memory/singleton.h"
-#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
-
-class ContextualSuggestionsService;
-class Profile;
-
-class ContextualSuggestionsServiceFactory
-    : public BrowserContextKeyedServiceFactory {
- public:
-  static ContextualSuggestionsService* GetForProfile(Profile* profile,
-                                                     bool create_if_necessary);
-  static ContextualSuggestionsServiceFactory* GetInstance();
-
- private:
-  friend struct base::DefaultSingletonTraits<
-      ContextualSuggestionsServiceFactory>;
-
-  ContextualSuggestionsServiceFactory();
-  ~ContextualSuggestionsServiceFactory() override;
-
-  // Overrides from BrowserContextKeyedServiceFactory:
-  KeyedService* BuildServiceInstanceFor(
-      content::BrowserContext* context) const override;
-
-  DISALLOW_COPY_AND_ASSIGN(ContextualSuggestionsServiceFactory);
-};
-
-#endif  // CHROME_BROWSER_AUTOCOMPLETE_CONTEXTUAL_SUGGESTIONS_SERVICE_FACTORY_H_
diff --git a/chrome/browser/autocomplete/remote_suggestions_service_factory.cc b/chrome/browser/autocomplete/remote_suggestions_service_factory.cc
new file mode 100644
index 0000000..8884ab1
--- /dev/null
+++ b/chrome/browser/autocomplete/remote_suggestions_service_factory.cc
@@ -0,0 +1,46 @@
+// 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 "chrome/browser/autocomplete/remote_suggestions_service_factory.h"
+
+#include "base/memory/singleton.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/signin/identity_manager_factory.h"
+#include "components/keyed_service/content/browser_context_dependency_manager.h"
+#include "components/omnibox/browser/remote_suggestions_service.h"
+#include "content/public/browser/storage_partition.h"
+
+// static
+RemoteSuggestionsService* RemoteSuggestionsServiceFactory::GetForProfile(
+    Profile* profile,
+    bool create_if_necessary) {
+  return static_cast<RemoteSuggestionsService*>(
+      GetInstance()->GetServiceForBrowserContext(profile, create_if_necessary));
+}
+
+// static
+RemoteSuggestionsServiceFactory*
+RemoteSuggestionsServiceFactory::GetInstance() {
+  return base::Singleton<RemoteSuggestionsServiceFactory>::get();
+}
+
+KeyedService* RemoteSuggestionsServiceFactory::BuildServiceInstanceFor(
+    content::BrowserContext* context) const {
+  Profile* profile = Profile::FromBrowserContext(context);
+  identity::IdentityManager* identity_manager =
+      IdentityManagerFactory::GetForProfile(profile);
+  return new RemoteSuggestionsService(
+      identity_manager,
+      content::BrowserContext::GetDefaultStoragePartition(profile)
+          ->GetURLLoaderFactoryForBrowserProcess());
+}
+
+RemoteSuggestionsServiceFactory::RemoteSuggestionsServiceFactory()
+    : BrowserContextKeyedServiceFactory(
+          "RemoteSuggestionsService",
+          BrowserContextDependencyManager::GetInstance()) {
+  DependsOn(IdentityManagerFactory::GetInstance());
+}
+
+RemoteSuggestionsServiceFactory::~RemoteSuggestionsServiceFactory() {}
diff --git a/chrome/browser/autocomplete/remote_suggestions_service_factory.h b/chrome/browser/autocomplete/remote_suggestions_service_factory.h
new file mode 100644
index 0000000..fc3b989
--- /dev/null
+++ b/chrome/browser/autocomplete/remote_suggestions_service_factory.h
@@ -0,0 +1,35 @@
+// 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 CHROME_BROWSER_AUTOCOMPLETE_REMOTE_SUGGESTIONS_SERVICE_FACTORY_H_
+#define CHROME_BROWSER_AUTOCOMPLETE_REMOTE_SUGGESTIONS_SERVICE_FACTORY_H_
+
+#include "base/macros.h"
+#include "base/memory/singleton.h"
+#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+
+class RemoteSuggestionsService;
+class Profile;
+
+class RemoteSuggestionsServiceFactory
+    : public BrowserContextKeyedServiceFactory {
+ public:
+  static RemoteSuggestionsService* GetForProfile(Profile* profile,
+                                                 bool create_if_necessary);
+  static RemoteSuggestionsServiceFactory* GetInstance();
+
+ private:
+  friend struct base::DefaultSingletonTraits<RemoteSuggestionsServiceFactory>;
+
+  RemoteSuggestionsServiceFactory();
+  ~RemoteSuggestionsServiceFactory() override;
+
+  // Overrides from BrowserContextKeyedServiceFactory:
+  KeyedService* BuildServiceInstanceFor(
+      content::BrowserContext* context) const override;
+
+  DISALLOW_COPY_AND_ASSIGN(RemoteSuggestionsServiceFactory);
+};
+
+#endif  // CHROME_BROWSER_AUTOCOMPLETE_REMOTE_SUGGESTIONS_SERVICE_FACTORY_H_
diff --git a/chrome/browser/chromeos/arc/bluetooth/arc_bluetooth_bridge_unittest.cc b/chrome/browser/chromeos/arc/bluetooth/arc_bluetooth_bridge_unittest.cc
index e44a05d..c2001ede 100644
--- a/chrome/browser/chromeos/arc/bluetooth/arc_bluetooth_bridge_unittest.cc
+++ b/chrome/browser/chromeos/arc/bluetooth/arc_bluetooth_bridge_unittest.cc
@@ -10,10 +10,10 @@
 #include <vector>
 
 #include "base/bind.h"
-#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/strings/stringprintf.h"
 #include "base/system/sys_info.h"
+#include "base/test/scoped_task_environment.h"
 #include "components/arc/bluetooth/bluetooth_type_converters.h"
 #include "components/arc/common/bluetooth.mojom.h"
 #include "components/arc/session/arc_bridge_service.h"
@@ -209,7 +209,7 @@
   std::unique_ptr<FakeBluetoothInstance> fake_bluetooth_instance_;
   std::unique_ptr<ArcBluetoothBridge> arc_bluetooth_bridge_;
   scoped_refptr<device::BluetoothAdapter> adapter_;
-  base::MessageLoop message_loop_;
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
   base::RunLoop get_adapter_run_loop_;
 };
 
diff --git a/chrome/browser/chromeos/extensions/wallpaper_private_api_unittest.cc b/chrome/browser/chromeos/extensions/wallpaper_private_api_unittest.cc
index 4f64fe0..3ed416f4 100644
--- a/chrome/browser/chromeos/extensions/wallpaper_private_api_unittest.cc
+++ b/chrome/browser/chromeos/extensions/wallpaper_private_api_unittest.cc
@@ -69,8 +69,8 @@
       chromeos::SystemSaltGetter::RawSalt({1, 2, 3, 4, 5, 6, 7, 8}));
 
   ScopedTestingLocalState local_state(TestingBrowserProcess::GetGlobal());
-  WallpaperControllerClient client;
   TestWallpaperController test_controller;
+  WallpaperControllerClient client;
   client.InitForTesting(&test_controller);
   fake_user_manager()->AddUser(AccountId::FromUserEmail(kTestAccount));
 
diff --git a/chrome/browser/chromeos/policy/network_policy_application_browsertest.cc b/chrome/browser/chromeos/policy/network_policy_application_browsertest.cc
index a7b98ef..7cdfcc4 100644
--- a/chrome/browser/chromeos/policy/network_policy_application_browsertest.cc
+++ b/chrome/browser/chromeos/policy/network_policy_application_browsertest.cc
@@ -418,4 +418,94 @@
   }
 }
 
+// Checks the edge case where a policy with GUID {same_guid} applies to network
+// with SSID "WifiTwo", and subsequently the policy changes, the new
+// NetworkConfiguration with GUID {same_guid} now applying to SSID "WifiOne".
+// For this to work correctly, PolicyApplicator must first clear the "WifiTwo"
+// settings so it is not matched by GUID, and then write the new policy to
+// shill.
+IN_PROC_BROWSER_TEST_F(NetworkPolicyApplicationTest,
+                       PolicyWithSameGUIDAppliesToOtherSSID) {
+  // Set up two services.
+  shill_service_client_test_->AddService(
+      kServiceWifi1, "wifi_orig_guid_1", "WifiOne", shill::kTypeWifi,
+      shill::kStateOnline, true /* add_to_visible */);
+  shill_service_client_test_->SetServiceProperty(
+      kServiceWifi1, shill::kSSIDProperty, base::Value("WifiOne"));
+  shill_service_client_test_->SetServiceProperty(
+      kServiceWifi1, shill::kSecurityClassProperty,
+      base::Value(shill::kSecurityPsk));
+
+  shill_service_client_test_->AddService(
+      kServiceWifi2, "wifi_orig_guid_2", "WifiTwo", shill::kTypeWifi,
+      shill::kStateOnline, true /* add_to_visible */);
+  shill_service_client_test_->SetServiceProperty(
+      kServiceWifi2, shill::kSSIDProperty, base::Value("WifiTwo"));
+  shill_service_client_test_->SetServiceProperty(
+      kServiceWifi2, shill::kSecurityClassProperty,
+      base::Value(shill::kSecurityPsk));
+
+  const char kDeviceONC1[] = R"(
+    {
+      "NetworkConfigurations": [
+        {
+          "GUID": "{same_guid}",
+          "Name": "X",
+          "Type": "WiFi",
+          "WiFi": {
+             "AutoConnect": false,
+             "HiddenSSID": false,
+             "Passphrase": "Passphrase",
+             "SSID": "WifiTwo",
+             "Security": "WPA-PSK"
+          }
+        }
+      ]
+    })";
+  SetDeviceOpenNetworkConfiguration(kDeviceONC1);
+
+  {
+    const base::Value* wifi_service_properties =
+        shill_service_client_test_->GetServiceProperties(kServiceWifi2);
+    ASSERT_TRUE(wifi_service_properties);
+    EXPECT_THAT(
+        *wifi_service_properties,
+        DictionaryHasValue(shill::kGuidProperty, base::Value("{same_guid}")));
+  }
+
+  // Same GUID for a different SSID.
+  const char kDeviceONC2[] = R"(
+    {
+      "NetworkConfigurations": [
+        {
+          "GUID": "{same_guid}",
+          "Name": "X",
+          "Type": "WiFi",
+          "WiFi": {
+             "AutoConnect": false,
+             "HiddenSSID": false,
+             "Passphrase": "SomePassphrase",
+             "SSID": "WifiOne",
+             "Security": "WPA-PSK"
+          }
+        }
+      ]
+    })";
+  SetDeviceOpenNetworkConfiguration(kDeviceONC2);
+  {
+    const base::Value* wifi_service_properties =
+        shill_service_client_test_->GetServiceProperties(kServiceWifi2);
+    ASSERT_TRUE(wifi_service_properties);
+    EXPECT_FALSE(wifi_service_properties->FindKey(shill::kGuidProperty));
+  }
+  {
+    const base::Value* wifi_service_properties =
+        shill_service_client_test_->GetServiceProperties(kServiceWifi1);
+    ASSERT_TRUE(wifi_service_properties);
+    EXPECT_THAT(
+        *wifi_service_properties,
+        DictionaryHasValue(shill::kGuidProperty, base::Value("{same_guid}")));
+  }
+}
+
 }  // namespace chromeos
diff --git a/chrome/browser/component_updater/optimization_hints_component_installer_unittest.cc b/chrome/browser/component_updater/optimization_hints_component_installer_unittest.cc
index 5cc09d7..0dabb1f 100644
--- a/chrome/browser/component_updater/optimization_hints_component_installer_unittest.cc
+++ b/chrome/browser/component_updater/optimization_hints_component_installer_unittest.cc
@@ -91,6 +91,7 @@
         data_reduction_proxy::DataReductionProxyTestContext::Builder()
             .WithMockConfig()
             .Build();
+    drp_test_context_->DisableWarmupURLFetch();
   }
 
   void TearDown() override {
diff --git a/chrome/browser/download/chrome_download_manager_delegate.cc b/chrome/browser/download/chrome_download_manager_delegate.cc
index 98e20781b63..858f432 100644
--- a/chrome/browser/download/chrome_download_manager_delegate.cc
+++ b/chrome/browser/download/chrome_download_manager_delegate.cc
@@ -658,6 +658,8 @@
   if (!download->CanOpenDownload())
     return;
 
+  if (!IsMostRecentDownloadItemAtFilePath(download))
+    return;
   MaybeSendDangerousDownloadOpenedReport(download,
                                          false /* show_download_in_folder */);
 
diff --git a/chrome/browser/extensions/api/feedback_private/feedback_browsertest.cc b/chrome/browser/extensions/api/feedback_private/feedback_browsertest.cc
index 5556209..d5d37cb 100644
--- a/chrome/browser/extensions/api/feedback_private/feedback_browsertest.cc
+++ b/chrome/browser/extensions/api/feedback_private/feedback_browsertest.cc
@@ -108,14 +108,7 @@
   base::RunLoop* quit_on_dispatch_;
 };
 
-// Disabled for ASan due to flakiness on Mac ASan 64 Tests (1).
-// See crbug.com/757243.
-#if defined(ADDRESS_SANITIZER)
-#define MAYBE_ShowFeedback DISABLED_ShowFeedback
-#else
-#define MAYBE_ShowFeedback ShowFeedback
-#endif
-IN_PROC_BROWSER_TEST_F(FeedbackTest, MAYBE_ShowFeedback) {
+IN_PROC_BROWSER_TEST_F(FeedbackTest, ShowFeedback) {
   WaitForExtensionViewsToLoad();
 
   ASSERT_TRUE(IsFeedbackAppAvailable());
@@ -123,14 +116,7 @@
   VerifyFeedbackAppLaunch();
 }
 
-// Disabled for ASan due to flakiness on Mac ASan 64 Tests (1).
-// See crbug.com/757243.
-#if defined(ADDRESS_SANITIZER)
-#define MAYBE_ShowLoginFeedback DISABLED_ShowLoginFeedback
-#else
-#define MAYBE_ShowLoginFeedback ShowLoginFeedback
-#endif
-IN_PROC_BROWSER_TEST_F(FeedbackTest, MAYBE_ShowLoginFeedback) {
+IN_PROC_BROWSER_TEST_F(FeedbackTest, ShowLoginFeedback) {
   WaitForExtensionViewsToLoad();
 
   ASSERT_TRUE(IsFeedbackAppAvailable());
@@ -152,16 +138,9 @@
   EXPECT_TRUE(bool_result);
 }
 
-// Disabled for ASan due to flakiness on Mac ASan 64 Tests (1).
-// See crbug.com/757243.
-#if defined(ADDRESS_SANITIZER)
-#define MAYBE_AnonymousUser DISABLED_AnonymousUser
-#else
-#define MAYBE_AnonymousUser AnonymousUser
-#endif
 // Tests that there's an option in the email drop down box with a value
 // 'anonymous_user'.
-IN_PROC_BROWSER_TEST_F(FeedbackTest, MAYBE_AnonymousUser) {
+IN_PROC_BROWSER_TEST_F(FeedbackTest, AnonymousUser) {
   WaitForExtensionViewsToLoad();
 
   ASSERT_TRUE(IsFeedbackAppAvailable());
@@ -190,16 +169,9 @@
   EXPECT_TRUE(bool_result);
 }
 
-// Disabled for ASan due to flakiness on Mac ASan 64 Tests (1).
-// See crbug.com/757243.
-#if defined(ADDRESS_SANITIZER)
-#define MAYBE_ExtraDiagnostics DISABLED_ExtraDiagnostics
-#else
-#define MAYBE_ExtraDiagnostics ExtraDiagnostics
-#endif
 // Ensures that when extra diagnostics are provided with feedback, they are
 // injected properly in the system information.
-IN_PROC_BROWSER_TEST_F(FeedbackTest, MAYBE_ExtraDiagnostics) {
+IN_PROC_BROWSER_TEST_F(FeedbackTest, ExtraDiagnostics) {
   WaitForExtensionViewsToLoad();
 
   ASSERT_TRUE(IsFeedbackAppAvailable());
@@ -230,16 +202,9 @@
   EXPECT_TRUE(bool_result);
 }
 
-// Disabled for ASan due to flakiness on Mac ASan 64 Tests (1).
-// See crbug.com/757243.
-#if defined(ADDRESS_SANITIZER)
-#define MAYBE_ShowFeedbackFromAssistant DISABLED_ShowFeedbackFromAssistant
-#else
-#define MAYBE_ShowFeedbackFromAssistant ShowFeedbackFromAssistant
-#endif
 // Ensures that when triggered from Assistant with Google account, Assistant
 // checkbox are not hidden.
-IN_PROC_BROWSER_TEST_F(FeedbackTest, MAYBE_ShowFeedbackFromAssistant) {
+IN_PROC_BROWSER_TEST_F(FeedbackTest, ShowFeedbackFromAssistant) {
   WaitForExtensionViewsToLoad();
 
   ASSERT_TRUE(IsFeedbackAppAvailable());
diff --git a/chrome/browser/extensions/service_worker_apitest.cc b/chrome/browser/extensions/service_worker_apitest.cc
index 8cfbf09..d83a871 100644
--- a/chrome/browser/extensions/service_worker_apitest.cc
+++ b/chrome/browser/extensions/service_worker_apitest.cc
@@ -1351,64 +1351,6 @@
   ASSERT_EQ("chrome.tabs.onUpdated callback", result);
 }
 
-// Tests that events to service worker arrives correctly event if the owner
-// extension of the worker is not running.
-IN_PROC_BROWSER_TEST_F(ServiceWorkerLazyBackgroundTest,
-                       EventsToStoppedExtension) {
-  LazyBackgroundObserver lazy_observer;
-  ResultCatcher catcher;
-  const Extension* extension = LoadExtensionWithFlags(
-      test_data_dir_.AppendASCII("service_worker/events_to_stopped_extension"),
-      kFlagNone);
-  ASSERT_TRUE(extension);
-  EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
-
-  ProcessManager* pm = ProcessManager::Get(browser()->profile());
-  EXPECT_GT(pm->GetLazyKeepaliveCount(extension), 0);
-  EXPECT_FALSE(pm->GetLazyKeepaliveActivities(extension).empty());
-
-  // |extension|'s background page opens a tab to its resource.
-  content::WebContents* extension_web_contents =
-      browser()->tab_strip_model()->GetActiveWebContents();
-  EXPECT_TRUE(content::WaitForLoadStop(extension_web_contents));
-  EXPECT_EQ(extension->GetResourceURL("page.html").spec(),
-            extension_web_contents->GetURL().spec());
-  {
-    // Let the service worker start and register a listener to
-    // chrome.tabs.onCreated event.
-    ExtensionTestMessageListener add_listener_done("listener-added", false);
-    content::ExecuteScriptAsync(extension_web_contents,
-                                "window.runServiceWorkerAsync()");
-    EXPECT_TRUE(add_listener_done.WaitUntilSatisfied());
-
-    base::RunLoop run_loop;
-    content::StoragePartition* storage_partition =
-        content::BrowserContext::GetDefaultStoragePartition(
-            browser()->profile());
-    content::StopServiceWorkerForScope(
-        storage_partition->GetServiceWorkerContext(),
-        // The service worker is registered at the top level scope.
-        extension->url(), run_loop.QuitClosure());
-    run_loop.Run();
-  }
-
-  // Close the tab to |extension|'s resource. This will also close the
-  // extension's event page.
-  browser()->tab_strip_model()->CloseWebContentsAt(
-      browser()->tab_strip_model()->active_index(), TabStripModel::CLOSE_NONE);
-  lazy_observer.Wait();
-
-  // At this point both the extension worker and extension event page is not
-  // running. Since the worker registered a listener for tabs.onCreated, it
-  // will be started to dispatch the event once we create a tab.
-  ExtensionTestMessageListener newtab_listener("hello-newtab", false);
-  newtab_listener.set_failure_message("WRONG_NEWTAB");
-  content::WebContents* new_web_contents =
-      AddTab(browser(), GURL(url::kAboutBlankURL));
-  EXPECT_TRUE(new_web_contents);
-  EXPECT_TRUE(newtab_listener.WaitUntilSatisfied());
-}
-
 // Tests that worker ref count increments while extension API function is
 // active.
 IN_PROC_BROWSER_TEST_F(ServiceWorkerTest, WorkerRefCount) {
diff --git a/chrome/browser/notifications/scheduler/internal/background_task_coordinator_unittest.cc b/chrome/browser/notifications/scheduler/internal/background_task_coordinator_unittest.cc
index 28d15a3d..8fdd17d4 100644
--- a/chrome/browser/notifications/scheduler/internal/background_task_coordinator_unittest.cc
+++ b/chrome/browser/notifications/scheduler/internal/background_task_coordinator_unittest.cc
@@ -10,10 +10,10 @@
 #include <vector>
 
 #include "base/test/scoped_task_environment.h"
-#include "base/time/clock.h"
 #include "chrome/browser/notifications/scheduler/internal/notification_entry.h"
 #include "chrome/browser/notifications/scheduler/internal/scheduler_config.h"
 #include "chrome/browser/notifications/scheduler/public/notification_background_task_scheduler.h"
+#include "chrome/browser/notifications/scheduler/test/fake_clock.h"
 #include "chrome/browser/notifications/scheduler/test/test_utils.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -58,22 +58,6 @@
   DISALLOW_COPY_AND_ASSIGN(MockNotificationBackgroundTaskScheduler);
 };
 
-// Clock to mock Clock::Now() to get a fixed time in the test.
-class FakeClock : public base::Clock {
- public:
-  FakeClock() = default;
-  ~FakeClock() override = default;
-
-  void SetTime(const base::Time& time) { time_ = time; }
-
- private:
-  // base::Clock implementation.
-  base::Time Now() const override { return time_; }
-
-  base::Time time_;
-  DISALLOW_COPY_AND_ASSIGN(FakeClock);
-};
-
 struct TestData {
   // Impression data as the input.
   std::vector<test::ImpressionTestData> impression_test_data;
@@ -112,16 +96,10 @@
 
   SchedulerConfig* config() { return &config_; }
 
-  void SetNow(const char* now_str) {
-    base::Time now = GetTime(now_str);
-    clock_.SetTime(now);
-  }
+  void SetNow(const char* now_str) { clock_.SetNow(now_str); }
 
   base::Time GetTime(const char* time_str) {
-    base::Time time;
-    bool success = base::Time::FromString(time_str, &time);
-    DCHECK(success);
-    return time;
+    return test::FakeClock::GetTime(time_str);
   }
 
   void ScheduleTask(const TestData& test_data) {
@@ -144,7 +122,7 @@
 
  private:
   base::test::ScopedTaskEnvironment scoped_task_environment_;
-  FakeClock clock_;
+  test::FakeClock clock_;
   SchedulerConfig config_;
   std::unique_ptr<BackgroundTaskCoordinator> coordinator_;
   MockNotificationBackgroundTaskScheduler* background_task_;
diff --git a/chrome/browser/notifications/scheduler/internal/impression_history_tracker.cc b/chrome/browser/notifications/scheduler/internal/impression_history_tracker.cc
index 679c26ab..154b22df 100644
--- a/chrome/browser/notifications/scheduler/internal/impression_history_tracker.cc
+++ b/chrome/browser/notifications/scheduler/internal/impression_history_tracker.cc
@@ -39,26 +39,43 @@
 ImpressionHistoryTrackerImpl::ImpressionHistoryTrackerImpl(
     const SchedulerConfig& config,
     std::vector<SchedulerClientType> registered_clients,
-    std::unique_ptr<CollectionStore<ClientState>> store)
+    std::unique_ptr<CollectionStore<ClientState>> store,
+    base::Clock* clock)
     : store_(std::move(store)),
       config_(config),
       registered_clients_(std::move(registered_clients)),
       initialized_(false),
       delegate_(nullptr),
+      clock_(clock),
       weak_ptr_factory_(this) {}
 
 ImpressionHistoryTrackerImpl::~ImpressionHistoryTrackerImpl() = default;
 
 void ImpressionHistoryTrackerImpl::Init(Delegate* delegate,
                                         InitCallback callback) {
-  DCHECK(!delegate_ && delegate);
+  DCHECK(!delegate_ && delegate && !initialized_);
   delegate_ = delegate;
   store_->InitAndLoad(
       base::BindOnce(&ImpressionHistoryTrackerImpl::OnStoreInitialized,
                      weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
 }
 
+void ImpressionHistoryTrackerImpl::AddImpression(SchedulerClientType type,
+                                                 const std::string& guid) {
+  DCHECK(initialized_);
+  auto it = client_states_.find(type);
+  if (it == client_states_.end())
+    return;
+
+  it->second->impressions.emplace_back(Impression(type, guid, clock_->Now()));
+  impression_map_.emplace(guid, &it->second->impressions.back());
+  SetNeedsUpdate(type, true /*needs_update*/);
+  MaybeUpdateDb(type);
+  NotifyImpressionUpdate();
+}
+
 void ImpressionHistoryTrackerImpl::AnalyzeImpressionHistory() {
+  DCHECK(initialized_);
   for (auto& client_state : client_states_)
     AnalyzeImpressionHistory(client_state.second.get());
   if (MaybeUpdateAllDb())
@@ -67,6 +84,7 @@
 
 void ImpressionHistoryTrackerImpl::GetClientStates(
     std::map<SchedulerClientType, const ClientState*>* client_states) const {
+  DCHECK(initialized_);
   DCHECK(client_states);
   client_states->clear();
   for (const auto& pair : client_states_) {
@@ -149,7 +167,7 @@
     ClientState* client_state) {
   DCHECK(client_state);
   std::deque<Impression*> dismisses;
-  base::Time now = base::Time::Now();
+  base::Time now = clock_->Now();
 
   for (auto it = client_state->impressions.begin();
        it != client_state->impressions.end();) {
@@ -277,8 +295,7 @@
 
   // Suppress the notification, the user will not see this type of notification
   // for a while.
-  SuppressionInfo supression_info(base::Time::Now(),
-                                  config_.suppression_duration);
+  SuppressionInfo supression_info(clock_->Now(), config_.suppression_duration);
   client_state->suppression_info = std::move(supression_info);
   client_state->current_max_daily_show = 0;
 }
@@ -290,7 +307,7 @@
     return;
 
   SuppressionInfo& suppression = client_state->suppression_info.value();
-  base::Time now = base::Time::Now();
+  base::Time now = clock_->Now();
 
   // Still in the suppression time window.
   if (now - suppression.last_trigger_time < suppression.duration)
diff --git a/chrome/browser/notifications/scheduler/internal/impression_history_tracker.h b/chrome/browser/notifications/scheduler/internal/impression_history_tracker.h
index 2e534794..a89104f2 100644
--- a/chrome/browser/notifications/scheduler/internal/impression_history_tracker.h
+++ b/chrome/browser/notifications/scheduler/internal/impression_history_tracker.h
@@ -14,6 +14,7 @@
 #include "base/callback.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
+#include "base/time/clock.h"
 #include "base/time/time.h"
 #include "chrome/browser/notifications/scheduler/internal/collection_store.h"
 #include "chrome/browser/notifications/scheduler/internal/impression_types.h"
@@ -45,6 +46,10 @@
   // Initializes the impression tracker.
   virtual void Init(Delegate* delegate, InitCallback callback) = 0;
 
+  // Add a new impression, called after the notification is shown.
+  virtual void AddImpression(SchedulerClientType type,
+                             const std::string& guid) = 0;
+
   // Analyzes the impression history for all notification clients, and adjusts
   // the |current_max_daily_show|.
   virtual void AnalyzeImpressionHistory() = 0;
@@ -69,12 +74,15 @@
   explicit ImpressionHistoryTrackerImpl(
       const SchedulerConfig& config,
       std::vector<SchedulerClientType> registered_clients,
-      std::unique_ptr<CollectionStore<ClientState>> store);
+      std::unique_ptr<CollectionStore<ClientState>> store,
+      base::Clock* clock);
   ~ImpressionHistoryTrackerImpl() override;
 
  private:
   // ImpressionHistoryTracker implementation.
   void Init(Delegate* delegate, InitCallback callback) override;
+  void AddImpression(SchedulerClientType type,
+                     const std::string& guid) override;
   void AnalyzeImpressionHistory() override;
   void GetClientStates(std::map<SchedulerClientType, const ClientState*>*
                            client_states) const override;
@@ -162,6 +170,9 @@
 
   Delegate* delegate_;
 
+  // The clock to provide the current timestamp.
+  base::Clock* clock_;
+
   base::WeakPtrFactory<ImpressionHistoryTrackerImpl> weak_ptr_factory_;
   DISALLOW_COPY_AND_ASSIGN(ImpressionHistoryTrackerImpl);
 };
diff --git a/chrome/browser/notifications/scheduler/internal/impression_history_tracker_unittest.cc b/chrome/browser/notifications/scheduler/internal/impression_history_tracker_unittest.cc
index f8c5882..7948d7c 100644
--- a/chrome/browser/notifications/scheduler/internal/impression_history_tracker_unittest.cc
+++ b/chrome/browser/notifications/scheduler/internal/impression_history_tracker_unittest.cc
@@ -10,6 +10,7 @@
 #include "base/run_loop.h"
 #include "base/test/scoped_task_environment.h"
 #include "chrome/browser/notifications/scheduler/internal/impression_history_tracker.h"
+#include "chrome/browser/notifications/scheduler/test/fake_clock.h"
 #include "chrome/browser/notifications/scheduler/test/test_utils.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -36,13 +37,9 @@
 
 Impression CreateImpression(const base::Time& create_time,
                             const std::string& guid) {
-  return {create_time,
-          UserFeedback::kNoFeedback,
-          ImpressionResult::kInvalid,
-          false /* integrated */,
-          SchedulerTaskTime::kMorning,
-          guid,
-          SchedulerClientType::kTest1};
+  Impression impression(SchedulerClientType::kTest1, guid, create_time);
+  impression.task_start_time = SchedulerTaskTime::kMorning;
+  return impression;
 }
 
 TestCase CreateDefaultTestCase() {
@@ -106,7 +103,7 @@
     delegate_ = std::make_unique<MockDelegate>();
 
     impression_trakcer_ = std::make_unique<ImpressionHistoryTrackerImpl>(
-        config_, test_case.registered_clients, std::move(store));
+        config_, test_case.registered_clients, std::move(store), &clock_);
   }
 
   // Initializes the tracker with data defined in the |test_case|.
@@ -151,13 +148,17 @@
     }
   }
 
+  void SetNow(const char* now_str) { clock_.SetNow(now_str); }
+
   const SchedulerConfig& config() const { return config_; }
   MockImpressionStore* store() { return store_; }
   MockDelegate* delegate() { return delegate_.get(); }
   ImpressionHistoryTracker* tracker() { return impression_trakcer_.get(); }
+  test::FakeClock* clock() { return &clock_; }
 
  private:
   base::test::ScopedTaskEnvironment scoped_task_environment_;
+  test::FakeClock clock_;
   SchedulerConfig config_;
   std::unique_ptr<ImpressionHistoryTracker> impression_trakcer_;
   MockImpressionStore* store_;
@@ -197,21 +198,13 @@
 // Verifies expired impression will be deleted.
 TEST_F(ImpressionHistoryTrackerTest, DeleteExpiredImpression) {
   TestCase test_case = CreateDefaultTestCase();
-  auto expired_create_time = base::Time::Now() - base::TimeDelta::FromDays(1) -
+  auto expired_create_time = clock()->Now() - base::TimeDelta::FromDays(1) -
                              config().impression_expiration;
-  auto not_expired_time = base::Time::Now() + base::TimeDelta::FromDays(1) -
+  auto not_expired_time = clock()->Now() + base::TimeDelta::FromDays(1) -
                           config().impression_expiration;
-  Impression expired{expired_create_time,         UserFeedback::kNoFeedback,
-                     ImpressionResult::kInvalid,  false /* integrated */,
-                     SchedulerTaskTime::kMorning, "guid1",
-                     SchedulerClientType::kTest1};
-  Impression not_expired{not_expired_time,
-                         UserFeedback::kNoFeedback,
-                         ImpressionResult::kInvalid,
-                         false /* integrated */,
-                         SchedulerTaskTime::kMorning,
-                         "guid2",
-                         SchedulerClientType::kTest1};
+
+  Impression expired = CreateImpression(expired_create_time, "guid1");
+  Impression not_expired = CreateImpression(not_expired_time, "guid2");
 
   // The impressions in the input should be sorted by creation time when gets
   // loaded to memory.
@@ -230,6 +223,26 @@
   VerifyClientStates(test_case);
 }
 
+// Verifies the state of new impression added to the tracker.
+TEST_F(ImpressionHistoryTrackerTest, AddImpression) {
+  TestCase test_case = CreateDefaultTestCase();
+  CreateTracker(test_case);
+  InitTrackerWithData(test_case);
+
+  // No-op for unregistered client.
+  tracker()->AddImpression(SchedulerClientType::kTest2, kGuid1);
+  VerifyClientStates(test_case);
+
+  SetNow("04/25/20 01:00:00 AM");
+
+  EXPECT_CALL(*store(), Update(_, _, _));
+  EXPECT_CALL(*delegate(), OnImpressionUpdated());
+  tracker()->AddImpression(SchedulerClientType::kTest1, kGuid1);
+  test_case.expected.back().impressions.emplace_back(
+      Impression(SchedulerClientType::kTest1, kGuid1, clock()->Now()));
+  VerifyClientStates(test_case);
+}
+
 // If impression has been deleted, click should have no result.
 TEST_F(ImpressionHistoryTrackerTest, ClickNoImpression) {
   TestCase test_case = CreateDefaultTestCase();
@@ -260,8 +273,7 @@
   DISALLOW_COPY_AND_ASSIGN(ImpressionHistoryTrackerUserActionTest);
 };
 
-// TODO(xingliu): Add test for unhelpful/dismiss, need to use base::Clock to
-// mock base::Time::Now().
+// TODO(xingliu): Add test for unhelpful/dismiss.
 const UserActionTestParam kUserActionTestParams[] = {
     {ImpressionResult::kPositive, UserFeedback::kClick, 3, base::nullopt,
      base::nullopt},
diff --git a/chrome/browser/notifications/scheduler/internal/impression_types.cc b/chrome/browser/notifications/scheduler/internal/impression_types.cc
index 899a8d82..148e385a 100644
--- a/chrome/browser/notifications/scheduler/internal/impression_types.cc
+++ b/chrome/browser/notifications/scheduler/internal/impression_types.cc
@@ -6,6 +6,13 @@
 
 namespace notifications {
 
+Impression::Impression() = default;
+
+Impression::Impression(SchedulerClientType type,
+                       const std::string& guid,
+                       const base::Time& create_time)
+    : create_time(create_time), guid(guid), type(type) {}
+
 bool Impression::operator==(const Impression& other) const {
   return create_time == other.create_time && feedback == other.feedback &&
          impression == other.impression && integrated == other.integrated &&
diff --git a/chrome/browser/notifications/scheduler/internal/impression_types.h b/chrome/browser/notifications/scheduler/internal/impression_types.h
index 3c91f55..876ada57 100644
--- a/chrome/browser/notifications/scheduler/internal/impression_types.h
+++ b/chrome/browser/notifications/scheduler/internal/impression_types.h
@@ -25,6 +25,11 @@
 // an impression result, which may affect notification exposure.
 // 4. The impression is deleted after it expires.
 struct Impression {
+  Impression();
+  Impression(SchedulerClientType type,
+             const std::string& guid,
+             const base::Time& create_time);
+
   bool operator==(const Impression& other) const;
 
   // Creation timestamp.
diff --git a/chrome/browser/notifications/scheduler/internal/notification_scheduler.cc b/chrome/browser/notifications/scheduler/internal/notification_scheduler.cc
index 48353b4..731b864 100644
--- a/chrome/browser/notifications/scheduler/internal/notification_scheduler.cc
+++ b/chrome/browser/notifications/scheduler/internal/notification_scheduler.cc
@@ -156,7 +156,8 @@
   void DisplayNotification(
       std::unique_ptr<NotificationEntry> notification) override {
     // TODO(xingliu): Inform the clients and show the notification.
-    NOTIMPLEMENTED();
+    context_->impression_tracker()->AddImpression(notification->type,
+                                                  notification->guid);
   }
 
   // ImpressionHistoryTracker::Delegate implementation.
diff --git a/chrome/browser/notifications/scheduler/internal/proto_conversion_unittest.cc b/chrome/browser/notifications/scheduler/internal/proto_conversion_unittest.cc
index 59b1eaf..53a5e56 100644
--- a/chrome/browser/notifications/scheduler/internal/proto_conversion_unittest.cc
+++ b/chrome/browser/notifications/scheduler/internal/proto_conversion_unittest.cc
@@ -101,13 +101,11 @@
   base::Time create_time;
   bool success = base::Time::FromString("03/25/19 00:00:00 AM", &create_time);
   DCHECK(success);
-  Impression impression{create_time,
-                        UserFeedback::kHelpful,
-                        ImpressionResult::kPositive,
-                        true /*integrated*/,
-                        SchedulerTaskTime::kMorning,
-                        kGuid,
-                        SchedulerClientType::kTest1};
+
+  Impression impression = test::CreateImpression(
+      create_time, UserFeedback::kHelpful, ImpressionResult::kPositive,
+      true /*integrated*/, SchedulerTaskTime::kMorning, kGuid,
+      SchedulerClientType::kTest1);
   client_state.impressions.emplace_back(impression);
   TestClientStateConversion(&client_state);
 
@@ -149,12 +147,14 @@
   bool success = base::Time::FromString("04/25/20 01:00:00 AM", &create_time);
   DCHECK(success);
 
-  Impression impression{create_time, UserFeedback::kHelpful,
-                        ImpressionResult::kPositive, true,
-                        SchedulerTaskTime::kMorning};
-  Impression other_impression{create_time, UserFeedback::kNoFeedback,
-                              ImpressionResult::kNegative, false,
-                              SchedulerTaskTime::kEvening};
+  Impression impression = test::CreateImpression(
+      create_time, UserFeedback::kHelpful, ImpressionResult::kPositive,
+      true /*integrated*/, SchedulerTaskTime::kMorning, "guid1",
+      SchedulerClientType::kUnknown);
+  Impression other_impression = test::CreateImpression(
+      create_time, UserFeedback::kNoFeedback, ImpressionResult::kNegative,
+      false /*integrated*/, SchedulerTaskTime::kEvening, "guid2",
+      SchedulerClientType::kUnknown);
   client_state.impressions.emplace_back(std::move(impression));
   client_state.impressions.emplace_back(std::move(other_impression));
   TestClientStateConversion(&client_state);
diff --git a/chrome/browser/notifications/scheduler/schedule_service_factory_helper.cc b/chrome/browser/notifications/scheduler/schedule_service_factory_helper.cc
index e60d55c..02447c1 100644
--- a/chrome/browser/notifications/scheduler/schedule_service_factory_helper.cc
+++ b/chrome/browser/notifications/scheduler/schedule_service_factory_helper.cc
@@ -9,6 +9,7 @@
 
 #include "base/sequenced_task_runner.h"
 #include "base/task/post_task.h"
+#include "base/time/default_clock.h"
 #include "chrome/browser/notifications/scheduler/internal/display_decider.h"
 #include "chrome/browser/notifications/scheduler/internal/icon_store.h"
 #include "chrome/browser/notifications/scheduler/internal/impression_history_tracker.h"
@@ -60,8 +61,8 @@
   std::vector<SchedulerClientType> registered_clients;
   client_registrar->GetRegisteredClients(&registered_clients);
   auto impression_tracker = std::make_unique<ImpressionHistoryTrackerImpl>(
-      *config.get(), std::move(registered_clients),
-      std::move(impression_store));
+      *config.get(), std::move(registered_clients), std::move(impression_store),
+      base::DefaultClock::GetInstance());
 
   // Build scheduled notification manager.
   base::FilePath notification_store_dir =
diff --git a/chrome/browser/notifications/scheduler/test/BUILD.gn b/chrome/browser/notifications/scheduler/test/BUILD.gn
index 27f61b4..38c2aaf 100644
--- a/chrome/browser/notifications/scheduler/test/BUILD.gn
+++ b/chrome/browser/notifications/scheduler/test/BUILD.gn
@@ -13,6 +13,8 @@
       [ "//chrome/browser/notifications/scheduler/internal:unit_tests" ]
 
   sources = [
+    "fake_clock.cc",
+    "fake_clock.h",
     "test_utils.cc",
     "test_utils.h",
   ]
diff --git a/chrome/browser/notifications/scheduler/test/fake_clock.cc b/chrome/browser/notifications/scheduler/test/fake_clock.cc
new file mode 100644
index 0000000..5b60f72e
--- /dev/null
+++ b/chrome/browser/notifications/scheduler/test/fake_clock.cc
@@ -0,0 +1,41 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/notifications/scheduler/test/fake_clock.h"
+
+namespace notifications {
+namespace test {
+
+// static
+base::Time FakeClock::GetTime(const char* time_str) {
+  base::Time time;
+  bool success = base::Time::FromString(time_str, &time);
+  DCHECK(success);
+  return time;
+}
+
+FakeClock::FakeClock() : time_mocked_(false) {}
+
+FakeClock::~FakeClock() = default;
+
+void FakeClock::SetNow(const char* time_str) {
+  base::Time now = GetTime(time_str);
+  SetNow(now);
+}
+
+void FakeClock::SetNow(const base::Time& time) {
+  time_ = time;
+  time_mocked_ = true;
+}
+
+void FakeClock::Reset() {
+  time_mocked_ = false;
+}
+
+base::Time FakeClock::Now() const {
+  return time_mocked_ ? time_ : base::Time::Now();
+}
+
+}  // namespace test
+}  // namespace notifications
diff --git a/chrome/browser/notifications/scheduler/test/fake_clock.h b/chrome/browser/notifications/scheduler/test/fake_clock.h
new file mode 100644
index 0000000..980dedd
--- /dev/null
+++ b/chrome/browser/notifications/scheduler/test/fake_clock.h
@@ -0,0 +1,46 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_NOTIFICATIONS_SCHEDULER_TEST_FAKE_CLOCK_H_
+#define CHROME_BROWSER_NOTIFICATIONS_SCHEDULER_TEST_FAKE_CLOCK_H_
+
+#include "base/time/clock.h"
+#include "base/time/time.h"
+
+namespace notifications {
+namespace test {
+
+// Clock to mock Clock::Now() to get a fixed time in the test.
+class FakeClock : public base::Clock {
+ public:
+  // Helper function to convert a string to a time object.
+  static base::Time GetTime(const char* time_str);
+
+  FakeClock();
+  ~FakeClock() override;
+
+  // Helper functions to set the current timestamp.
+  void SetNow(const char* time_str);
+  void SetNow(const base::Time& time);
+
+  // Resets to use base::Time::Now().
+  void Reset();
+
+  // base::Clock implementation.
+  base::Time Now() const override;
+
+ private:
+  // Mocked time.
+  base::Time time_;
+
+  // Whether Now() should return mocked time.
+  bool time_mocked_;
+
+  DISALLOW_COPY_AND_ASSIGN(FakeClock);
+};
+
+}  // namespace test
+}  // namespace notifications
+
+#endif  // CHROME_BROWSER_NOTIFICATIONS_SCHEDULER_TEST_FAKE_CLOCK_H_
diff --git a/chrome/browser/notifications/scheduler/test/test_utils.cc b/chrome/browser/notifications/scheduler/test/test_utils.cc
index de7cc02..d28fbd8 100644
--- a/chrome/browser/notifications/scheduler/test/test_utils.cc
+++ b/chrome/browser/notifications/scheduler/test/test_utils.cc
@@ -63,6 +63,21 @@
   }
 }
 
+Impression CreateImpression(const base::Time& create_time,
+                            UserFeedback feedback,
+                            ImpressionResult impression_result,
+                            bool integrated,
+                            SchedulerTaskTime task_start_time,
+                            const std::string& guid,
+                            SchedulerClientType type) {
+  Impression impression(type, guid, create_time);
+  impression.feedback = feedback;
+  impression.impression = impression_result;
+  impression.integrated = integrated;
+  impression.task_start_time = task_start_time;
+  return impression;
+}
+
 std::string DebugString(const NotificationData* data) {
   DCHECK(data);
   std::ostringstream stream;
diff --git a/chrome/browser/notifications/scheduler/test/test_utils.h b/chrome/browser/notifications/scheduler/test/test_utils.h
index 8492701..ed3982b6 100644
--- a/chrome/browser/notifications/scheduler/test/test_utils.h
+++ b/chrome/browser/notifications/scheduler/test/test_utils.h
@@ -50,6 +50,15 @@
     const std::vector<ImpressionTestData>& test_data,
     std::vector<std::unique_ptr<ClientState>>* client_states);
 
+// Creates an impression.
+Impression CreateImpression(const base::Time& create_time,
+                            UserFeedback feedback,
+                            ImpressionResult impression,
+                            bool integrated,
+                            SchedulerTaskTime task_time,
+                            const std::string& guid,
+                            SchedulerClientType type);
+
 // Generates a debug string to print details of |data|.
 std::string DebugString(const NotificationData* data);
 
diff --git a/chrome/browser/printing/print_preview_dialog_controller.cc b/chrome/browser/printing/print_preview_dialog_controller.cc
index c26ddaa..cedaf48 100644
--- a/chrome/browser/printing/print_preview_dialog_controller.cc
+++ b/chrome/browser/printing/print_preview_dialog_controller.cc
@@ -7,7 +7,6 @@
 #include <stddef.h>
 
 #include <algorithm>
-#include <memory>
 #include <string>
 #include <vector>
 
@@ -17,7 +16,6 @@
 #include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
 #include "chrome/browser/browser_process.h"
-#include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/extensions/chrome_extension_web_contents_observer.h"
 #include "chrome/browser/printing/print_view_manager.h"
 #include "chrome/browser/task_manager/web_contents_tags.h"
@@ -37,8 +35,6 @@
 #include "content/public/browser/navigation_controller.h"
 #include "content/public/browser/navigation_details.h"
 #include "content/public/browser/navigation_entry.h"
-#include "content/public/browser/notification_details.h"
-#include "content/public/browser/notification_source.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_contents_delegate.h"
@@ -187,6 +183,53 @@
 
 }  // namespace
 
+// PrintPreviewDialogController::WebContentsObserver ---------------------------
+
+class PrintPreviewDialogController::WebContentsObserver
+    : public content::WebContentsObserver {
+ public:
+  WebContentsObserver(PrintPreviewDialogController* controller,
+                      content::WebContents* web_contents);
+  ~WebContentsObserver() override;
+
+  // content::WebContentsObserver:
+  void RenderProcessGone(base::TerminationStatus status) override;
+  void NavigationEntryCommitted(
+      const content::LoadCommittedDetails& load_details) override;
+  void WebContentsDestroyed() override;
+
+ private:
+  PrintPreviewDialogController* const controller_;
+
+  DISALLOW_COPY_AND_ASSIGN(WebContentsObserver);
+};
+
+PrintPreviewDialogController::WebContentsObserver::WebContentsObserver(
+    PrintPreviewDialogController* controller,
+    content::WebContents* web_contents)
+    : content::WebContentsObserver(web_contents), controller_(controller) {}
+
+PrintPreviewDialogController::WebContentsObserver::~WebContentsObserver() =
+    default;
+
+void PrintPreviewDialogController::WebContentsObserver::RenderProcessGone(
+    base::TerminationStatus status) {
+  controller_->OnRendererProcessClosed(
+      web_contents()->GetMainFrame()->GetProcess());
+}
+
+void PrintPreviewDialogController::WebContentsObserver::
+    NavigationEntryCommitted(
+        const content::LoadCommittedDetails& load_details) {
+  controller_->OnNavEntryCommitted(web_contents(), load_details);
+}
+
+void PrintPreviewDialogController::WebContentsObserver::WebContentsDestroyed() {
+  controller_->OnWebContentsDestroyed(web_contents());
+}
+
+// PrintPreviewDialogController ------------------------------------------------
+
 PrintPreviewDialogController::PrintPreviewDialogController() = default;
 
 // static
@@ -256,25 +299,6 @@
   return (it != preview_dialog_map_.end()) ? it->second : nullptr;
 }
 
-void PrintPreviewDialogController::Observe(
-    int type,
-    const content::NotificationSource& source,
-    const content::NotificationDetails& details) {
-  if (type == content::NOTIFICATION_RENDERER_PROCESS_CLOSED) {
-    OnRendererProcessClosed(
-        content::Source<content::RenderProcessHost>(source).ptr());
-  } else if (type == content::NOTIFICATION_WEB_CONTENTS_DESTROYED) {
-    OnWebContentsDestroyed(content::Source<WebContents>(source).ptr());
-  } else {
-    DCHECK_EQ(content::NOTIFICATION_NAV_ENTRY_COMMITTED, type);
-    WebContents* contents =
-        content::Source<NavigationController>(source)->GetWebContents();
-    OnNavEntryCommitted(
-        contents,
-        content::Details<content::LoadCommittedDetails>(details).ptr());
-  }
-}
-
 void PrintPreviewDialogController::ForEachPreviewDialog(
     base::Callback<void(content::WebContents*)> callback) {
   for (const auto& it : preview_dialog_map_)
@@ -293,7 +317,7 @@
   if (it == preview_dialog_map_.end())
     return;
 
-  RemoveObservers(it->second);
+  RemoveObserver(it->second);
   preview_dialog_map_[preview_dialog] = nullptr;
 }
 
@@ -341,7 +365,7 @@
 
 void PrintPreviewDialogController::OnNavEntryCommitted(
     WebContents* contents,
-    const content::LoadCommittedDetails* details) {
+    const content::LoadCommittedDetails& details) {
   WebContents* preview_dialog = GetPrintPreviewForContents(contents);
   if (!preview_dialog) {
     NOTREACHED();
@@ -356,19 +380,17 @@
 
 void PrintPreviewDialogController::OnInitiatorNavigated(
     WebContents* initiator,
-    const content::LoadCommittedDetails* details) {
-  if (details) {
-    if (details->type == content::NAVIGATION_TYPE_EXISTING_PAGE) {
-      static const ui::PageTransition kTransitions[] = {
-          ui::PageTransitionFromInt(ui::PAGE_TRANSITION_TYPED |
-                                    ui::PAGE_TRANSITION_FROM_ADDRESS_BAR),
-          ui::PAGE_TRANSITION_LINK,
-      };
-      ui::PageTransition type = details->entry->GetTransitionType();
-      for (ui::PageTransition transition : kTransitions) {
-        if (ui::PageTransitionTypeIncludingQualifiersIs(type, transition))
-          return;
-      }
+    const content::LoadCommittedDetails& details) {
+  if (details.type == content::NAVIGATION_TYPE_EXISTING_PAGE) {
+    static const ui::PageTransition kTransitions[] = {
+        ui::PageTransitionFromInt(ui::PAGE_TRANSITION_TYPED |
+                                  ui::PAGE_TRANSITION_FROM_ADDRESS_BAR),
+        ui::PAGE_TRANSITION_LINK,
+    };
+    ui::PageTransition type = details.entry->GetTransitionType();
+    for (ui::PageTransition transition : kTransitions) {
+      if (ui::PageTransitionTypeIncludingQualifiersIs(type, transition))
+        return;
     }
   }
 
@@ -377,26 +399,24 @@
 
 void PrintPreviewDialogController::OnPreviewDialogNavigated(
     WebContents* preview_dialog,
-    const content::LoadCommittedDetails* details) {
-  if (details) {
-    ui::PageTransition type = details->entry->GetTransitionType();
+    const content::LoadCommittedDetails& details) {
+  ui::PageTransition type = details.entry->GetTransitionType();
 
-    // New |preview_dialog| is created. Don't update/erase map entry.
-    if (waiting_for_new_preview_page_ &&
-        ui::PageTransitionCoreTypeIs(type, ui::PAGE_TRANSITION_AUTO_TOPLEVEL) &&
-        details->type == content::NAVIGATION_TYPE_NEW_PAGE) {
-      waiting_for_new_preview_page_ = false;
-      SaveInitiatorTitle(preview_dialog);
-      return;
-    }
+  // New |preview_dialog| is created. Don't update/erase map entry.
+  if (waiting_for_new_preview_page_ &&
+      ui::PageTransitionCoreTypeIs(type, ui::PAGE_TRANSITION_AUTO_TOPLEVEL) &&
+      details.type == content::NAVIGATION_TYPE_NEW_PAGE) {
+    waiting_for_new_preview_page_ = false;
+    SaveInitiatorTitle(preview_dialog);
+    return;
+  }
 
-    // Cloud print sign-in causes a reload.
-    if (!waiting_for_new_preview_page_ &&
-        ui::PageTransitionCoreTypeIs(type, ui::PAGE_TRANSITION_RELOAD) &&
-        details->type == content::NAVIGATION_TYPE_EXISTING_PAGE &&
-        IsPrintPreviewURL(details->previous_url)) {
-      return;
-    }
+  // Cloud print sign-in causes a reload.
+  if (!waiting_for_new_preview_page_ &&
+      ui::PageTransitionCoreTypeIs(type, ui::PAGE_TRANSITION_RELOAD) &&
+      details.type == content::NAVIGATION_TYPE_EXISTING_PAGE &&
+      IsPrintPreviewURL(details.previous_url)) {
+    return;
   }
 
   NOTREACHED();
@@ -430,8 +450,8 @@
   // Make the print preview WebContents show up in the task manager.
   task_manager::WebContentsTags::CreateForPrintingContents(preview_dialog);
 
-  AddObservers(initiator);
-  AddObservers(preview_dialog);
+  AddObserver(initiator);
+  AddObserver(preview_dialog);
 
   return preview_dialog;
 }
@@ -450,55 +470,16 @@
       PrintViewManager::FromWebContents(initiator)->RenderSourceName());
 }
 
-void PrintPreviewDialogController::AddObservers(WebContents* contents) {
-  registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
-                 content::Source<WebContents>(contents));
-  registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED,
-      content::Source<NavigationController>(&contents->GetController()));
-
-  // Multiple sites may share the same RenderProcessHost, so check if this
-  // notification has already been added.
-  content::Source<content::RenderProcessHost> rph_source(
-      contents->GetMainFrame()->GetProcess());
-  if (!registrar_.IsRegistered(this,
-      content::NOTIFICATION_RENDERER_PROCESS_CLOSED, rph_source)) {
-    // Not registered for this host yet, so add the notification and add the
-    // host to the count map with a count of 1.
-    registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED,
-                   rph_source);
-    host_contents_count_map_[contents->GetMainFrame()->GetProcess()] = 1;
-  } else {
-    // This host's notification is already registered. Increment its count in
-    // the map so that the notification will not be removed from the registry
-    // until all web contents that use it are destroyed.
-    ++host_contents_count_map_[contents->GetMainFrame()->GetProcess()];
-  }
+void PrintPreviewDialogController::AddObserver(WebContents* contents) {
+  auto emplace_result = web_contents_observers_.emplace(
+      std::piecewise_construct, std::forward_as_tuple(contents),
+      std::forward_as_tuple(
+          std::make_unique<WebContentsObserver>(this, contents)));
+  DCHECK(emplace_result.second);
 }
 
-void PrintPreviewDialogController::RemoveObservers(WebContents* contents) {
-  registrar_.Remove(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
-                    content::Source<WebContents>(contents));
-  registrar_.Remove(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED,
-      content::Source<NavigationController>(&contents->GetController()));
-
-  // Multiple sites may share the same RenderProcessHost, so check if this
-  // notification has already been added.
-  content::Source<content::RenderProcessHost> rph_source(
-      contents->GetMainFrame()->GetProcess());
-  if (registrar_.IsRegistered(this,
-      content::NOTIFICATION_RENDERER_PROCESS_CLOSED, rph_source)) {
-    if (host_contents_count_map_[contents->GetMainFrame()->GetProcess()] == 1) {
-      // This is the last contents that has this render process host, so we can
-      // remove the notification.
-      registrar_.Remove(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED,
-                        rph_source);
-      host_contents_count_map_.erase(contents->GetMainFrame()->GetProcess());
-    } else {
-      // Other initializers and/or dialogs are still connected to the host, so
-      // we can't remove the notification. Decrement the count in the map.
-      --host_contents_count_map_[contents->GetMainFrame()->GetProcess()];
-    }
-  }
+void PrintPreviewDialogController::RemoveObserver(WebContents* contents) {
+  web_contents_observers_.erase(contents);
 }
 
 void PrintPreviewDialogController::RemoveInitiator(
@@ -509,7 +490,7 @@
   // and reaches RemovePreviewDialog(), it does not attempt to also remove the
   // initiator's observers.
   preview_dialog_map_[preview_dialog] = nullptr;
-  RemoveObservers(initiator);
+  RemoveObserver(initiator);
 
   PrintViewManager::FromWebContents(initiator)->PrintPreviewDone();
 
@@ -524,12 +505,12 @@
   // Remove the initiator's observers before erasing the mapping.
   WebContents* initiator = GetInitiator(preview_dialog);
   if (initiator) {
-    RemoveObservers(initiator);
+    RemoveObserver(initiator);
     PrintViewManager::FromWebContents(initiator)->PrintPreviewDone();
   }
 
   preview_dialog_map_.erase(preview_dialog);
-  RemoveObservers(preview_dialog);
+  RemoveObserver(preview_dialog);
 }
 
 }  // namespace printing
diff --git a/chrome/browser/printing/print_preview_dialog_controller.h b/chrome/browser/printing/print_preview_dialog_controller.h
index fefafc870..d4646e3 100644
--- a/chrome/browser/printing/print_preview_dialog_controller.h
+++ b/chrome/browser/printing/print_preview_dialog_controller.h
@@ -6,13 +6,12 @@
 #define CHROME_BROWSER_PRINTING_PRINT_PREVIEW_DIALOG_CONTROLLER_H_
 
 #include <map>
+#include <memory>
 
 #include "base/callback.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "components/sessions/core/session_id.h"
-#include "content/public/browser/notification_observer.h"
-#include "content/public/browser/notification_registrar.h"
 
 class GURL;
 
@@ -31,9 +30,10 @@
 // track of the 1:1 relationship between initiator tabs and print preview
 // dialogs.
 class PrintPreviewDialogController
-    : public base::RefCounted<PrintPreviewDialogController>,
-      public content::NotificationObserver {
+    : public base::RefCounted<PrintPreviewDialogController> {
  public:
+  class WebContentsObserver;
+
   PrintPreviewDialogController();
 
   static PrintPreviewDialogController* GetInstance();
@@ -64,11 +64,6 @@
   void ForEachPreviewDialog(
       base::Callback<void(content::WebContents*)> callback);
 
-  // content::NotificationObserver implementation.
-  void Observe(int type,
-               const content::NotificationSource& source,
-               const content::NotificationDetails& details) override;
-
   // Erase the initiator info associated with |preview_dialog|.
   void EraseInitiatorInfo(content::WebContents* preview_dialog);
 
@@ -85,26 +80,26 @@
   using PrintPreviewDialogMap =
       std::map<content::WebContents*, content::WebContents*>;
 
-  ~PrintPreviewDialogController() override;
+  ~PrintPreviewDialogController();
 
-  // Handler for the RENDERER_PROCESS_CLOSED notification. This is observed when
-  // the initiator renderer crashed.
+  // Handles the closing of the RenderProcessHost. This is observed when the
+  // initiator renderer crashes.
   void OnRendererProcessClosed(content::RenderProcessHost* rph);
 
-  // Handler for the WEB_CONTENTS_DESTROYED notification. This is observed when
-  // either WebContents is closed.
+  // Handles the destruction of |contents|. This is observed when either
+  // the initiator or preview WebContents is closed.
   void OnWebContentsDestroyed(content::WebContents* contents);
 
-  // Handler for the NAV_ENTRY_COMMITTED notification. This is observed when the
-  // renderer is navigated to a different page.
+  // Handles the commit of a navigation entry for |contents|. This is observed
+  // when the renderer for either WebContents is navigated to a different page.
   void OnNavEntryCommitted(content::WebContents* contents,
-                           const content::LoadCommittedDetails* details);
+                           const content::LoadCommittedDetails& details);
 
   // Helpers for OnNavEntryCommitted().
   void OnInitiatorNavigated(content::WebContents* initiator,
-                            const content::LoadCommittedDetails* details);
+                            const content::LoadCommittedDetails& details);
   void OnPreviewDialogNavigated(content::WebContents* preview_dialog,
-                                const content::LoadCommittedDetails* details);
+                                const content::LoadCommittedDetails& details);
 
   // Creates a new print preview dialog.
   content::WebContents* CreatePrintPreviewDialog(
@@ -114,9 +109,9 @@
   // |preview_dialog| in |preview_dialog|'s PrintPreviewUI.
   void SaveInitiatorTitle(content::WebContents* preview_dialog);
 
-  // Adds/Removes observers for notifications from |contents|.
-  void AddObservers(content::WebContents* contents);
-  void RemoveObservers(content::WebContents* contents);
+  // Adds/Removes the WebContentsObserver for |contents|.
+  void AddObserver(content::WebContents* contents);
+  void RemoveObserver(content::WebContents* contents);
 
   // Removes WebContents when they close/crash/navigate.
   void RemoveInitiator(content::WebContents* initiator);
@@ -125,9 +120,6 @@
   // Mapping between print preview dialog and the corresponding initiator.
   PrintPreviewDialogMap preview_dialog_map_;
 
-  // A registrar for listening to notifications.
-  content::NotificationRegistrar registrar_;
-
   // True if the controller is waiting for a new preview dialog via
   // content::NAVIGATION_TYPE_NEW_PAGE.
   bool waiting_for_new_preview_page_ = false;
@@ -136,11 +128,8 @@
   // print preview dialog.
   bool is_creating_print_preview_dialog_ = false;
 
-  // How many web contents (dialogs and initiators) are watching a given render
-  // process host. Used to determine when a render process host's
-  // NOTIFICATION_RENDERER_PROCESS_CLOSED notification should be removed from
-  // the registrar.
-  std::map<content::RenderProcessHost*, int> host_contents_count_map_;
+  std::map<content::WebContents*, std::unique_ptr<WebContentsObserver>>
+      web_contents_observers_;
 
   DISALLOW_COPY_AND_ASSIGN(PrintPreviewDialogController);
 };
diff --git a/chrome/browser/ui/ash/wallpaper_controller_client_unittest.cc b/chrome/browser/ui/ash/wallpaper_controller_client_unittest.cc
index 4cfa016..cbaadeb 100644
--- a/chrome/browser/ui/ash/wallpaper_controller_client_unittest.cc
+++ b/chrome/browser/ui/ash/wallpaper_controller_client_unittest.cc
@@ -28,8 +28,8 @@
 };
 
 TEST_F(WallpaperControllerClientTest, Construction) {
-  WallpaperControllerClient client;
   TestWallpaperController controller;
+  WallpaperControllerClient client;
   client.InitForTesting(&controller);
 
   // Singleton was initialized.
diff --git a/chrome/browser/ui/autofill/chrome_autofill_client.cc b/chrome/browser/ui/autofill/chrome_autofill_client.cc
index 3a98d1a..9b106e4 100644
--- a/chrome/browser/ui/autofill/chrome_autofill_client.cc
+++ b/chrome/browser/ui/autofill/chrome_autofill_client.cc
@@ -42,6 +42,7 @@
 #include "components/autofill/core/browser/ui/payments/card_unmask_prompt_view.h"
 #include "components/autofill/core/browser/ui/popup_item_ids.h"
 #include "components/autofill/core/common/autofill_features.h"
+#include "components/autofill/core/common/autofill_payments_features.h"
 #include "components/autofill/core/common/autofill_prefs.h"
 #include "components/autofill/core/common/autofill_switches.h"
 #include "components/password_manager/content/browser/content_password_manager_driver.h"
@@ -365,6 +366,23 @@
 #endif
 }
 
+void ChromeAutofillClient::CreditCardUploadCompleted() {
+#if defined(OS_ANDROID)
+  // TODO(hozhng@): Placeholder for Clank Notification.
+#else
+  if (!base::FeatureList::IsEnabled(
+          features::kAutofillCreditCardUploadFeedback)) {
+    return;
+  }
+
+  // Do lazy initialization of SaveCardBubbleControllerImpl.
+  // TODO(crbug.com/964127): Add success branch.
+  autofill::SaveCardBubbleControllerImpl::CreateForWebContents(web_contents());
+  autofill::SaveCardBubbleControllerImpl::FromWebContents(web_contents())
+      ->UpdateIconForSaveCardFailure();
+#endif
+}
+
 void ChromeAutofillClient::ConfirmCreditCardFillAssist(
     const CreditCard& card,
     base::OnceClosure callback) {
diff --git a/chrome/browser/ui/autofill/chrome_autofill_client.h b/chrome/browser/ui/autofill/chrome_autofill_client.h
index bb82042..77d3013 100644
--- a/chrome/browser/ui/autofill/chrome_autofill_client.h
+++ b/chrome/browser/ui/autofill/chrome_autofill_client.h
@@ -100,6 +100,7 @@
       std::unique_ptr<base::DictionaryValue> legal_message,
       SaveCreditCardOptions options,
       UploadSaveCardPromptCallback callback) override;
+  void CreditCardUploadCompleted() override;
   void ConfirmCreditCardFillAssist(const CreditCard& card,
                                    base::OnceClosure callback) override;
   bool HasCreditCardScanFeature() override;
diff --git a/chrome/browser/ui/autofill/payments/save_card_bubble_controller_impl.cc b/chrome/browser/ui/autofill/payments/save_card_bubble_controller_impl.cc
index e576d1a..796f1e16 100644
--- a/chrome/browser/ui/autofill/payments/save_card_bubble_controller_impl.cc
+++ b/chrome/browser/ui/autofill/payments/save_card_bubble_controller_impl.cc
@@ -164,6 +164,11 @@
   ShowBubble();
 }
 
+void SaveCardBubbleControllerImpl::UpdateIconForSaveCardFailure() {
+  current_bubble_type_ = BubbleType::FAILURE;
+  ShowIconOnly();
+}
+
 void SaveCardBubbleControllerImpl::ShowBubbleForSaveCardFailureForTesting() {
   current_bubble_type_ = BubbleType::FAILURE;
   ShowBubble();
diff --git a/chrome/browser/ui/autofill/payments/save_card_bubble_controller_impl.h b/chrome/browser/ui/autofill/payments/save_card_bubble_controller_impl.h
index 14da125a..1d95530 100644
--- a/chrome/browser/ui/autofill/payments/save_card_bubble_controller_impl.h
+++ b/chrome/browser/ui/autofill/payments/save_card_bubble_controller_impl.h
@@ -85,6 +85,11 @@
   // just saved and links the user to manage their other cards.
   void ShowBubbleForManageCardsForTesting(const CreditCard& card);
 
+  // Updates the save card icon when credit card upload failed. This will only
+  // update the icon image and stop icon from animating. The actual bubble will
+  // be shown when users click on the icon.
+  void UpdateIconForSaveCardFailure();
+
   // For testing. Sets up the controller for showing the
   // save card failure bubble.
   void ShowBubbleForSaveCardFailureForTesting();
diff --git a/chrome/browser/ui/startup/startup_browser_creator_impl.cc b/chrome/browser/ui/startup/startup_browser_creator_impl.cc
index 9efee7b..619e3f1 100644
--- a/chrome/browser/ui/startup/startup_browser_creator_impl.cc
+++ b/chrome/browser/ui/startup/startup_browser_creator_impl.cc
@@ -713,6 +713,9 @@
   // may be shown alongside command-line tabs.
   StartupTabs tabs = provider.GetResetTriggerTabs(profile_);
 
+  // Maybe add any tabs which the user has previously pinned.
+  AppendTabs(provider.GetPinnedTabs(command_line_, profile_), &tabs);
+
   // URLs passed on the command line supersede all others.
   AppendTabs(cmd_line_tabs, &tabs);
   if (!cmd_line_tabs.empty())
@@ -754,9 +757,6 @@
   if (onboarding_tabs.empty() && prefs_tabs.empty())
     AppendTabs(provider.GetNewTabPageTabs(command_line_, profile_), &tabs);
 
-  // Maybe add any tabs which the user has previously pinned.
-  AppendTabs(provider.GetPinnedTabs(command_line_, profile_), &tabs);
-
   return tabs;
 }
 
diff --git a/chrome/browser/ui/startup/startup_browser_creator_impl_unittest.cc b/chrome/browser/ui/startup/startup_browser_creator_impl_unittest.cc
index 36a67d7ae..30d8b72 100644
--- a/chrome/browser/ui/startup/startup_browser_creator_impl_unittest.cc
+++ b/chrome/browser/ui/startup/startup_browser_creator_impl_unittest.cc
@@ -113,17 +113,17 @@
                                                  false, false, false, true);
   ASSERT_EQ(4U, output.size());
   EXPECT_EQ("reset-trigger", output[0].url.host());
-  EXPECT_EQ("onboarding", output[1].url.host());
-  EXPECT_EQ("prefs", output[2].url.host());
-  EXPECT_EQ("pinned", output[3].url.host());
+  EXPECT_EQ("pinned", output[1].url.host());
+  EXPECT_EQ("onboarding", output[2].url.host());
+  EXPECT_EQ("prefs", output[3].url.host());
 
   // No extra onboarding content for managed starts.
   output = impl.DetermineStartupTabs(provider, StartupTabs(), true, false,
                                      false, false, false);
   ASSERT_EQ(3U, output.size());
   EXPECT_EQ("reset-trigger", output[0].url.host());
-  EXPECT_EQ("prefs", output[1].url.host());
-  EXPECT_EQ("pinned", output[2].url.host());
+  EXPECT_EQ("pinned", output[1].url.host());
+  EXPECT_EQ("prefs", output[2].url.host());
 }
 
 // Only the New Tab Page should appear in Incognito mode, skipping all the usual
@@ -201,9 +201,10 @@
 
   StartupTabs output = impl.DetermineStartupTabs(provider, cmd_line_tabs, true,
                                                  false, false, false, true);
-  ASSERT_EQ(2U, output.size());
+  ASSERT_EQ(3U, output.size());
   EXPECT_EQ("reset-trigger", output[0].url.host());
-  EXPECT_EQ("cmd-line", output[1].url.host());
+  EXPECT_EQ("pinned", output[1].url.host());
+  EXPECT_EQ("cmd-line", output[2].url.host());
 
   // Also test that both incognito and crash recovery don't interfere with
   // command line tabs.
@@ -240,8 +241,8 @@
       provider_allows_ntp, StartupTabs(), true, false, false, false, true);
   ASSERT_EQ(3U, output.size());
   EXPECT_EQ("reset-trigger", output[0].url.host());
-  EXPECT_EQ("new-tab", output[1].url.host());
-  EXPECT_EQ("pinned", output[2].url.host());
+  EXPECT_EQ("pinned", output[1].url.host());
+  EXPECT_EQ("new-tab", output[2].url.host());
 }
 
 // The welcome back page should appear before any other session restore tabs.
@@ -255,23 +256,23 @@
   StartupTabs output = impl.DetermineStartupTabs(
       provider_allows_ntp, StartupTabs(), true, false, false, false, true);
   ASSERT_EQ(3U, output.size());
-  EXPECT_EQ("welcome-back", output[0].url.host());
-  EXPECT_EQ("prefs", output[1].url.host());
-  EXPECT_EQ("pinned", output[2].url.host());
+  EXPECT_EQ("pinned", output[0].url.host());
+  EXPECT_EQ("welcome-back", output[1].url.host());
+  EXPECT_EQ("prefs", output[2].url.host());
 
   // No welcome back for non-startup opens.
   output = impl.DetermineStartupTabs(provider_allows_ntp, StartupTabs(), false,
                                      false, false, false, true);
   ASSERT_EQ(2U, output.size());
-  EXPECT_EQ("prefs", output[0].url.host());
-  EXPECT_EQ("pinned", output[1].url.host());
+  EXPECT_EQ("pinned", output[0].url.host());
+  EXPECT_EQ("prefs", output[1].url.host());
 
   // No welcome back for managed starts even if first run.
   output = impl.DetermineStartupTabs(provider_allows_ntp, StartupTabs(), true,
                                      false, false, false, false);
   ASSERT_EQ(2U, output.size());
-  EXPECT_EQ("prefs", output[0].url.host());
-  EXPECT_EQ("pinned", output[1].url.host());
+  EXPECT_EQ("pinned", output[0].url.host());
+  EXPECT_EQ("prefs", output[1].url.host());
 }
 
 TEST(StartupBrowserCreatorImplTest, DetermineBrowserOpenBehavior_Startup) {
diff --git a/chrome/browser/ui/toolbar/app_menu_model.cc b/chrome/browser/ui/toolbar/app_menu_model.cc
index 0abc4d7..a8864bc 100644
--- a/chrome/browser/ui/toolbar/app_menu_model.cc
+++ b/chrome/browser/ui/toolbar/app_menu_model.cc
@@ -61,9 +61,6 @@
 #include "components/zoom/zoom_event_manager.h"
 #include "content/public/browser/host_zoom_map.h"
 #include "content/public/browser/navigation_entry.h"
-#include "content/public/browser/notification_service.h"
-#include "content/public/browser/notification_source.h"
-#include "content/public/browser/notification_types.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/profiling.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -251,17 +248,16 @@
 
 void AppMenuModel::Init() {
   Build();
-  UpdateZoomControls();
 
   browser_zoom_subscription_ =
       zoom::ZoomEventManager::GetForBrowserContext(browser_->profile())
           ->AddZoomLevelChangedCallback(base::Bind(
               &AppMenuModel::OnZoomLevelChanged, base::Unretained(this)));
 
-  browser_->tab_strip_model()->AddObserver(this);
-
-  registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED,
-                 content::NotificationService::AllSources());
+  TabStripModel* tab_strip_model = browser_->tab_strip_model();
+  tab_strip_model->AddObserver(this);
+  Observe(tab_strip_model->GetActiveWebContents());
+  UpdateZoomControls();
 }
 
 bool AppMenuModel::DoesCommandIdDismissMenu(int command_id) const {
@@ -698,14 +694,13 @@
   if (selection.active_tab_changed()) {
     // The user has switched between tabs and the new tab may have a different
     // zoom setting. Or web contents for a tab has been replaced.
+    Observe(selection.new_contents);
     UpdateZoomControls();
   }
 }
 
-void AppMenuModel::Observe(int type,
-                           const content::NotificationSource& source,
-                           const content::NotificationDetails& details) {
-  DCHECK_EQ(content::NOTIFICATION_NAV_ENTRY_COMMITTED, type);
+void AppMenuModel::NavigationEntryCommitted(
+    const content::LoadCommittedDetails& load_details) {
   UpdateZoomControls();
 }
 
@@ -891,11 +886,12 @@
 }
 
 void AppMenuModel::UpdateZoomControls() {
-  WebContents* contents = browser_->tab_strip_model()->GetActiveWebContents();
-  zoom_label_ = base::FormatPercent(
-      contents
-          ? zoom::ZoomController::FromWebContents(contents)->GetZoomPercent()
-          : 100);
+  int zoom_percent = 100;  // Defaults to 100% zoom.
+  if (web_contents()) {
+    zoom_percent =
+        zoom::ZoomController::FromWebContents(web_contents())->GetZoomPercent();
+  }
+  zoom_label_ = base::FormatPercent(zoom_percent);
 }
 
 bool AppMenuModel::ShouldShowNewIncognitoWindowMenuItem() {
diff --git a/chrome/browser/ui/toolbar/app_menu_model.h b/chrome/browser/ui/toolbar/app_menu_model.h
index 6d06271..908714a7 100644
--- a/chrome/browser/ui/toolbar/app_menu_model.h
+++ b/chrome/browser/ui/toolbar/app_menu_model.h
@@ -13,8 +13,7 @@
 #include "base/timer/elapsed_timer.h"
 #include "chrome/browser/ui/tabs/tab_strip_model_observer.h"
 #include "content/public/browser/host_zoom_map.h"
-#include "content/public/browser/notification_observer.h"
-#include "content/public/browser/notification_registrar.h"
+#include "content/public/browser/web_contents_observer.h"
 #include "ui/base/accelerators/accelerator.h"
 #include "ui/base/models/button_menu_item_model.h"
 #include "ui/base/models/simple_menu_model.h"
@@ -108,7 +107,7 @@
                      public ui::SimpleMenuModel::Delegate,
                      public ui::ButtonMenuItemModel::Delegate,
                      public TabStripModelObserver,
-                     public content::NotificationObserver {
+                     public content::WebContentsObserver {
  public:
   // Range of command IDs to use for the items in the recent tabs submenu.
   static const int kMinRecentTabsCommandId = 1001;
@@ -146,10 +145,9 @@
       const TabStripModelChange& change,
       const TabStripSelectionChange& selection) override;
 
-  // Overridden from content::NotificationObserver:
-  void Observe(int type,
-               const content::NotificationSource& source,
-               const content::NotificationDetails& details) override;
+  // content::WebContentsObserver:
+  void NavigationEntryCommitted(
+      const content::LoadCommittedDetails& load_details) override;
 
   // Getters.
   Browser* browser() const { return browser_; }
@@ -233,7 +231,6 @@
 
   std::unique_ptr<content::HostZoomMap::Subscription>
       browser_zoom_subscription_;
-  content::NotificationRegistrar registrar_;
 
   DISALLOW_COPY_AND_ASSIGN(AppMenuModel);
 };
diff --git a/chrome/browser/ui/views/extensions/extensions_menu_button.cc b/chrome/browser/ui/views/extensions/extensions_menu_button.cc
index d4e06e5..5fe5c1d 100644
--- a/chrome/browser/ui/views/extensions/extensions_menu_button.cc
+++ b/chrome/browser/ui/views/extensions/extensions_menu_button.cc
@@ -42,7 +42,6 @@
       controller_(std::move(controller)) {
   ConfigureSecondaryView();
   set_auto_compute_tooltip(false);
-  set_context_menu_controller(this);
   controller_->SetDelegate(this);
   UpdateState();
 }
@@ -56,7 +55,7 @@
 void ExtensionsMenuButton::ButtonPressed(Button* sender,
                                          const ui::Event& event) {
   if (sender->GetID() == EXTENSION_CONTEXT_MENU) {
-    ShowContextMenu(gfx::Point(), ui::MENU_SOURCE_MOUSE);
+    RunExtensionContextMenu(ui::MENU_SOURCE_MOUSE);
     return;
   }
   DCHECK_EQ(this, sender);
@@ -99,10 +98,7 @@
   return menu_runner_ && menu_runner_->IsRunning();
 }
 
-// views::ContextMenuController:
-void ExtensionsMenuButton::ShowContextMenuForViewImpl(
-    views::View* source,
-    const gfx::Point& point,
+void ExtensionsMenuButton::RunExtensionContextMenu(
     ui::MenuSourceType source_type) {
   ui::MenuModel* model = controller_->GetContextMenu();
   if (!model)
diff --git a/chrome/browser/ui/views/extensions/extensions_menu_button.h b/chrome/browser/ui/views/extensions/extensions_menu_button.h
index f0087fb..a2d813f1 100644
--- a/chrome/browser/ui/views/extensions/extensions_menu_button.h
+++ b/chrome/browser/ui/views/extensions/extensions_menu_button.h
@@ -22,8 +22,7 @@
 
 class ExtensionsMenuButton : public HoverButton,
                              public views::ButtonListener,
-                             public ToolbarActionViewDelegateViews,
-                             public views::ContextMenuController {
+                             public ToolbarActionViewDelegateViews {
  public:
   ExtensionsMenuButton(Browser* browser,
                        std::unique_ptr<ToolbarActionViewController> controller);
@@ -44,10 +43,7 @@
   void UpdateState() override;
   bool IsMenuRunning() const override;
 
-  // views::ContextMenuController:
-  void ShowContextMenuForViewImpl(views::View* source,
-                                  const gfx::Point& point,
-                                  ui::MenuSourceType source_type) override;
+  void RunExtensionContextMenu(ui::MenuSourceType source_type);
 
   // Callback for MenuModelAdapter.
   void OnMenuClosed();
diff --git a/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc b/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc
index 218e5bb7..60c15ce 100644
--- a/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc
@@ -1024,16 +1024,18 @@
     PRINTER_LOG(ERROR) << "Discovered printer disappeared";
     // Printer disappeared, so we don't have information about it anymore and
     // can't really do much. Fail the add.
-    FireWebUIListener("on-add-or-edit-cups-printer", base::Value(false),
-                      base::Value(printer_id));
+    FireWebUIListener("on-add-or-edit-cups-printer",
+                      base::Value(PrinterSetupResult::kPrinterUnreachable),
+                      base::Value(""));
     return;
   }
 
   if (!printer->GetUriComponents().has_value()) {
     PRINTER_LOG(DEBUG) << "Could not parse uri";
     // The printer uri was not parsed successfully. Fail the add.
-    FireWebUIListener("on-add-or-edit-cups-printer", base::Value(false),
-                      base::Value(printer_id));
+    FireWebUIListener("on-add-or-edit-cups-printer",
+                      base::Value(PrinterSetupResult::kPrinterUnreachable),
+                      base::Value(""));
     return;
   }
 
diff --git a/chrome/test/chromedriver/commands.cc b/chrome/test/chromedriver/commands.cc
index dc45e2a4..5cb100e5 100644
--- a/chrome/test/chromedriver/commands.cc
+++ b/chrome/test/chromedriver/commands.cc
@@ -28,6 +28,7 @@
 #include "chrome/test/chromedriver/chrome/status.h"
 #include "chrome/test/chromedriver/logging.h"
 #include "chrome/test/chromedriver/session.h"
+#include "chrome/test/chromedriver/session_commands.h"
 #include "chrome/test/chromedriver/session_thread_map.h"
 #include "chrome/test/chromedriver/util.h"
 #include "chrome/test/chromedriver/version.h"
@@ -68,8 +69,9 @@
   if (new_id.empty())
     new_id = GenerateId();
   std::unique_ptr<Session> session = std::make_unique<Session>(new_id);
-  std::unique_ptr<base::Thread> thread = std::make_unique<base::Thread>(new_id);
-  if (!thread->Start()) {
+  std::unique_ptr<SessionThreadInfo> threadInfo =
+      std::make_unique<SessionThreadInfo>(new_id, GetW3CSetting(params));
+  if (!threadInfo->thread()->Start()) {
     callback.Run(
         Status(kUnknownError, "failed to start a thread for the new session"),
         std::unique_ptr<base::Value>(), std::string(),
@@ -77,9 +79,9 @@
     return;
   }
 
-  thread->task_runner()->PostTask(
+  threadInfo->thread()->task_runner()->PostTask(
       FROM_HERE, base::BindOnce(&SetThreadLocalSession, std::move(session)));
-  session_thread_map->insert(std::make_pair(new_id, std::move(thread)));
+  session_thread_map->insert(std::make_pair(new_id, std::move(threadInfo)));
   init_session_cmd.Run(params, new_id, callback);
 }
 
@@ -335,7 +337,7 @@
     callback.Run(status, std::unique_ptr<base::Value>(), session_id,
                  kW3CDefault);
   } else {
-    iter->second->task_runner()->PostTask(
+    iter->second->thread()->task_runner()->PostTask(
         FROM_HERE,
         base::BindOnce(&ExecuteSessionCommandOnSessionThread, command_name,
                        command, w3c_standard_command, return_ok_without_session,
diff --git a/chrome/test/chromedriver/commands_unittest.cc b/chrome/test/chromedriver/commands_unittest.cc
index 99f6524..752d1a6 100644
--- a/chrome/test/chromedriver/commands_unittest.cc
+++ b/chrome/test/chromedriver/commands_unittest.cc
@@ -141,8 +141,8 @@
   SessionThreadMap map;
   Session session("id");
   Session session2("id2");
-  map[session.id] = std::make_unique<base::Thread>("1");
-  map[session2.id] = std::make_unique<base::Thread>("2");
+  map[session.id] = std::make_unique<SessionThreadInfo>("1", true);
+  map[session2.id] = std::make_unique<SessionThreadInfo>("2", true);
 
   int count = 0;
 
@@ -186,8 +186,8 @@
   SessionThreadMap map;
   Session session("id");
   Session session2("id2");
-  map[session.id] = std::make_unique<base::Thread>("1");
-  map[session2.id] = std::make_unique<base::Thread>("2");
+  map[session.id] = std::make_unique<SessionThreadInfo>("1", true);
+  map[session2.id] = std::make_unique<SessionThreadInfo>("2", true);
 
   int count = 0;
   Command cmd = base::Bind(&ExecuteStubQuit, &count);
@@ -229,13 +229,14 @@
 
 TEST(CommandsTest, ExecuteSessionCommand) {
   SessionThreadMap map;
-  auto thread = std::make_unique<base::Thread>("1");
+  auto threadInfo = std::make_unique<SessionThreadInfo>("1", true);
+  base::Thread* thread = threadInfo->thread();
   ASSERT_TRUE(thread->Start());
   std::string id("id");
   thread->task_runner()->PostTask(
       FROM_HERE,
       base::BindOnce(&internal::CreateSessionOnSessionThreadForTesting, id));
-  map[id] = std::move(thread);
+  map[id] = std::move(threadInfo);
 
   base::DictionaryValue params;
   params.SetInteger("param", 5);
@@ -310,10 +311,10 @@
 
 TEST(CommandsTest, ExecuteSessionCommandOnJustDeletedSession) {
   SessionThreadMap map;
-  auto thread = std::make_unique<base::Thread>("1");
-  ASSERT_TRUE(thread->Start());
+  auto threadInfo = std::make_unique<SessionThreadInfo>("1", true);
+  ASSERT_TRUE(threadInfo->thread()->Start());
   std::string id("id");
-  map[id] = std::move(thread);
+  map[id] = std::move(threadInfo);
 
   base::test::ScopedTaskEnvironment scoped_task_environment;
   base::RunLoop run_loop;
@@ -701,14 +702,15 @@
 
 TEST(CommandsTest, SuccessNotifyingCommandListeners) {
   SessionThreadMap map;
-  auto thread = std::make_unique<base::Thread>("1");
+  auto threadInfo = std::make_unique<SessionThreadInfo>("1", true);
+  base::Thread* thread = threadInfo->thread();
   ASSERT_TRUE(thread->Start());
   std::string id("id");
   thread->task_runner()->PostTask(
       FROM_HERE,
       base::BindOnce(&internal::CreateSessionOnSessionThreadForTesting, id));
 
-  map[id] = std::move(thread);
+  map[id] = std::move(threadInfo);
 
   base::DictionaryValue params;
   auto listener = std::make_unique<MockCommandListener>();
@@ -782,20 +784,20 @@
 
 TEST(CommandsTest, ErrorNotifyingCommandListeners) {
   SessionThreadMap map;
-  auto thread = std::make_unique<base::Thread>("1");
-  base::Thread* thread_ptr = thread.get();
+  auto threadInfo = std::make_unique<SessionThreadInfo>("1", true);
+  base::Thread* thread = threadInfo->thread();
   ASSERT_TRUE(thread->Start());
   std::string id("id");
   thread->task_runner()->PostTask(
       FROM_HERE,
       base::BindOnce(&internal::CreateSessionOnSessionThreadForTesting, id));
-  map[id] = std::move(thread);
+  map[id] = std::move(threadInfo);
 
   // In SuccessNotifyingCommandListenersBeforeCommand, we verified BeforeCommand
   // was called before (as opposed to after) command execution. We don't need to
   // verify this again, so we can just add |listener| with PostTask.
   auto listener = std::make_unique<FailingCommandListener>();
-  thread_ptr->task_runner()->PostTask(
+  thread->task_runner()->PostTask(
       FROM_HERE, base::BindOnce(&AddListenerToSessionIfSessionExists,
                                 std::move(listener)));
 
@@ -810,6 +812,6 @@
       base::Bind(&OnFailBecauseErrorNotifyingListeners, &run_loop));
   run_loop.Run();
 
-  thread_ptr->task_runner()->PostTask(FROM_HERE,
-                                      base::BindOnce(&VerifySessionWasDeleted));
+  thread->task_runner()->PostTask(FROM_HERE,
+                                  base::BindOnce(&VerifySessionWasDeleted));
 }
diff --git a/chrome/test/chromedriver/element_commands.cc b/chrome/test/chromedriver/element_commands.cc
index fba128f..6196b16b 100644
--- a/chrome/test/chromedriver/element_commands.cc
+++ b/chrome/test/chromedriver/element_commands.cc
@@ -15,6 +15,7 @@
 #include "base/files/file_util.h"
 #include "base/logging.h"
 #include "base/strings/string_split.h"
+#include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/threading/platform_thread.h"
 #include "base/time/time.h"
@@ -31,6 +32,8 @@
 #include "third_party/webdriver/atoms.h"
 
 const int kFlickTouchEventsPerSecond = 30;
+const std::set<std::string> textControlTypes = {"text", "search", "tel",
+                                                "url",  "email",  "password"};
 
 namespace {
 
@@ -81,14 +84,27 @@
   return Status(kOk);
 }
 
-Status SendKeysToElement(
-    Session* session,
-    WebView* web_view,
-    const std::string& element_id,
-    const base::ListValue* key_list) {
+Status SendKeysToElement(Session* session,
+                         WebView* web_view,
+                         const std::string& element_id,
+                         const bool is_text,
+                         const base::ListValue* key_list) {
   Status status = FocusToElement(session, web_view, element_id);
   if (status.IsError())
         return Status(kElementNotInteractable);
+  // Move cursor/caret to append the input keys if element's type is
+  // text-related
+  if (is_text) {
+    base::ListValue args;
+    args.Append(CreateElement(element_id));
+    std::unique_ptr<base::Value> result;
+    status = web_view->CallFunction(
+        session->GetCurrentFrameId(),
+        "elem => elem.setSelectionRange(elem.value.length, elem.value.length)",
+        args, &result);
+    if (status.IsError())
+      return status;
+  }
   return SendKeysOnWindow(web_view, key_list, true, &session->sticky_modifiers);
 }
 
@@ -360,15 +376,20 @@
   }
 
   bool is_input = false;
-  status = IsElementAttributeEqualToIgnoreCase(
-      session, web_view, element_id, "tagName", "input", &is_input);
+  status = IsElementAttributeEqualToIgnoreCase(session, web_view, element_id,
+                                               "tagName", "input", &is_input);
   if (status.IsError())
     return status;
-  bool is_file = false;
-  status = IsElementAttributeEqualToIgnoreCase(
-      session, web_view, element_id, "type", "file", &is_file);
+  std::unique_ptr<base::Value> get_element_type;
+  status = GetElementAttribute(session, web_view, element_id, "type",
+                               &get_element_type);
   if (status.IsError())
     return status;
+  std::string element_type;
+  if (get_element_type->GetAsString(&element_type))
+    element_type = base::ToLowerASCII(element_type);
+  bool is_file = element_type == "file";
+
   if (is_input && is_file) {
     if (session->strict_file_interactability) {
       status = FocusToElement(session, web_view,element_id);
@@ -420,7 +441,10 @@
     return web_view->SetFileInputFiles(session->GetCurrentFrameId(), *element,
                                        paths, multiple);
   } else {
-    return SendKeysToElement(session, web_view, element_id, key_list);
+    // If element_type is in textControlTypes, sendKeys should append
+    bool is_text = is_input && textControlTypes.find(element_type) !=
+                                   textControlTypes.end();
+    return SendKeysToElement(session, web_view, element_id, is_text, key_list);
   }
 }
 
@@ -761,16 +785,23 @@
   // document.body, depending on document compatibility mode. The parentheses
   // around the JavaScript code below is needed because JavaScript syntax
   // doesn't allow a statement to start with an object literal.
-  std::unique_ptr<base::Value> scroll;
+  // document.documentElement.clientHeight and Width provide viewport height
+  // and width to crop screenshot if necessary.
+  std::unique_ptr<base::Value> browser_info;
   status = web_view->EvaluateScript(
       std::string(),
       "({x: document.documentElement.scrollLeft || document.body.scrollLeft,"
-      "  y: document.documentElement.scrollTop || document.body.scrollTop})",
-      &scroll);
+      "  y: document.documentElement.scrollTop || document.body.scrollTop,"
+      "  height: document.documentElement.clientHeight,"
+      "  width: document.documentElement.clientWidth})",
+      &browser_info);
   if (status.IsError())
     return status;
-  int scroll_left = scroll->FindKey("x")->GetInt();
-  int scroll_top = scroll->FindKey("y")->GetInt();
+
+  int scroll_left = browser_info->FindKey("x")->GetInt();
+  int scroll_top = browser_info->FindKey("y")->GetInt();
+  double viewport_height = browser_info->FindKey("height")->GetDouble();
+  double viewport_width = browser_info->FindKey("width")->GetDouble();
 
   std::unique_ptr<base::DictionaryValue> clip_dict =
       base::DictionaryValue::From(std::move(clip));
@@ -783,6 +814,13 @@
   clip_dict->SetInteger("x", location.x + scroll_left);
   clip_dict->SetInteger("y", location.y + scroll_top);
   clip_dict->SetDouble("scale", 1.0);
+  // Crop screenshot by viewport if element is larger than viewport
+  clip_dict->SetInteger(
+      "height",
+      std::min(viewport_height, clip_dict->FindKey("height")->GetDouble()));
+  clip_dict->SetInteger(
+      "width",
+      std::min(viewport_width, clip_dict->FindKey("width")->GetDouble()));
   base::DictionaryValue screenshot_params;
   screenshot_params.SetDictionary("clip", std::move(clip_dict));
 
diff --git a/chrome/test/chromedriver/server/http_handler.cc b/chrome/test/chromedriver/server/http_handler.cc
index b9cb1230..578f3ab 100644
--- a/chrome/test/chromedriver/server/http_handler.cc
+++ b/chrome/test/chromedriver/server/http_handler.cc
@@ -50,6 +50,13 @@
 const char kSessionStorage[] = "sessionStorage";
 const char kShutdownPath[] = "shutdown";
 
+bool w3cMode(const std::string& session_id,
+             const SessionThreadMap& session_thread_map) {
+  if (session_id.length() > 0 && session_thread_map.count(session_id) > 0)
+    return session_thread_map.at(session_id)->w3cMode();
+  return kW3CDefault;
+}
+
 }  // namespace
 
 // WrapperURLLoaderFactory subclasses mojom::URLLoaderFactory as non-mojo, cross
@@ -914,11 +921,11 @@
   CommandMap::const_iterator iter = command_map_->begin();
   while (true) {
     if (iter == command_map_->end()) {
-      if (kW3CDefault) {
+      if (w3cMode(session_id, session_thread_map_)) {
         PrepareResponse(
             trimmed_path, send_response_func,
             Status(kUnknownCommand, "unknown command: " + trimmed_path),
-            nullptr, session_id, kW3CDefault);
+            nullptr, session_id, true);
       } else {
         std::unique_ptr<net::HttpServerResponseInfo> response(
             new net::HttpServerResponseInfo(net::HTTP_NOT_FOUND));
@@ -939,10 +946,10 @@
     std::unique_ptr<base::Value> parsed_body =
         base::JSONReader::ReadDeprecated(request.data);
     if (!parsed_body || !parsed_body->GetAsDictionary(&body_params)) {
-      if (kW3CDefault) {
+      if (w3cMode(session_id, session_thread_map_)) {
         PrepareResponse(trimmed_path, send_response_func,
                         Status(kInvalidArgument, "missing command parameters"),
-                        nullptr, session_id, kW3CDefault);
+                        nullptr, session_id, true);
       } else {
         std::unique_ptr<net::HttpServerResponseInfo> response(
             new net::HttpServerResponseInfo(net::HTTP_BAD_REQUEST));
@@ -952,12 +959,13 @@
       return;
     }
     params.MergeDictionary(body_params);
-  } else if (kW3CDefault && iter->method == kPost) {
+  } else if (iter->method == kPost &&
+             w3cMode(session_id, session_thread_map_)) {
     // Data in JSON format is required for POST requests. See step 5 of
     // https://www.w3.org/TR/2018/REC-webdriver1-20180605/#processing-model.
     PrepareResponse(trimmed_path, send_response_func,
                     Status(kInvalidArgument, "missing command parameters"),
-                    nullptr, session_id, kW3CDefault);
+                    nullptr, session_id, true);
     return;
   }
 
diff --git a/chrome/test/chromedriver/session_commands.cc b/chrome/test/chromedriver/session_commands.cc
index edff019..b910f107 100644
--- a/chrome/test/chromedriver/session_commands.cc
+++ b/chrome/test/chromedriver/session_commands.cc
@@ -82,6 +82,41 @@
 
 InitSessionParams::~InitSessionParams() {}
 
+// Look for W3C mode setting in InitSession command parameters.
+bool GetW3CSetting(const base::DictionaryValue& params) {
+  bool w3c;
+  const base::ListValue* list;
+  const base::DictionaryValue* dict;
+
+  if (params.GetDictionary("capabilities.alwaysMatch", &dict)) {
+    if (dict->GetBoolean("goog:chromeOptions.w3c", &w3c) ||
+        dict->GetBoolean("chromeOptions.w3c", &w3c)) {
+      return w3c;
+    }
+  }
+
+  if (params.GetList("capabilities.firstMatch", &list) &&
+      list->GetDictionary(0, &dict)) {
+    if (dict->GetBoolean("goog:chromeOptions.w3c", &w3c) ||
+        dict->GetBoolean("chromeOptions.w3c", &w3c)) {
+      return w3c;
+    }
+  }
+
+  if (params.GetDictionary("desiredCapabilities", &dict)) {
+    if (dict->GetBoolean("goog:chromeOptions.w3c", &w3c) ||
+        dict->GetBoolean("chromeOptions.w3c", &w3c)) {
+      return w3c;
+    }
+  }
+
+  if (!params.HasKey("capabilities")) {
+    return false;
+  }
+
+  return kW3CDefault;
+}
+
 namespace {
 
 // Creates a JSON object (represented by base::DictionaryValue) that contains
@@ -195,41 +230,6 @@
   return Status(kOk);
 }
 
-// Look for W3C mode setting in InitSession command parameters.
-bool GetW3CSetting(const base::DictionaryValue& params) {
-  bool w3c;
-  const base::ListValue* list;
-  const base::DictionaryValue* dict;
-
-  if (params.GetDictionary("capabilities.alwaysMatch", &dict)) {
-    if (dict->GetBoolean("goog:chromeOptions.w3c", &w3c) ||
-        dict->GetBoolean("chromeOptions.w3c", &w3c)) {
-      return w3c;
-    }
-  }
-
-  if (params.GetList("capabilities.firstMatch", &list) &&
-      list->GetDictionary(0, &dict)) {
-    if (dict->GetBoolean("goog:chromeOptions.w3c", &w3c) ||
-        dict->GetBoolean("chromeOptions.w3c", &w3c)) {
-      return w3c;
-    }
-  }
-
-  if (params.GetDictionary("desiredCapabilities", &dict)) {
-    if (dict->GetBoolean("goog:chromeOptions.w3c", &w3c) ||
-        dict->GetBoolean("chromeOptions.w3c", &w3c)) {
-      return w3c;
-    }
-  }
-
-  if (!params.HasKey("capabilities")) {
-    return false;
-  }
-
-  return kW3CDefault;
-}
-
 Status InitSessionHelper(const InitSessionParams& bound_params,
                          Session* session,
                          const base::DictionaryValue& params,
diff --git a/chrome/test/chromedriver/session_commands.h b/chrome/test/chromedriver/session_commands.h
index 81c6db190..2fcef40 100644
--- a/chrome/test/chromedriver/session_commands.h
+++ b/chrome/test/chromedriver/session_commands.h
@@ -34,6 +34,8 @@
   DeviceManager* device_manager;
 };
 
+bool GetW3CSetting(const base::DictionaryValue& params);
+
 bool MergeCapabilities(const base::DictionaryValue* always_match,
                        const base::DictionaryValue* first_match,
                        base::DictionaryValue* merged);
diff --git a/chrome/test/chromedriver/session_thread_map.h b/chrome/test/chromedriver/session_thread_map.h
index c0bdaab..972b069d 100644
--- a/chrome/test/chromedriver/session_thread_map.h
+++ b/chrome/test/chromedriver/session_thread_map.h
@@ -11,6 +11,21 @@
 
 #include "base/threading/thread.h"
 
-using SessionThreadMap = std::map<std::string, std::unique_ptr<base::Thread>>;
+// Info related to session threads, one instance per session. This object should
+// only be accessed on the main thread.
+class SessionThreadInfo {
+ public:
+  SessionThreadInfo(const std::string& name, bool w3c_mode)
+      : thread_(name), w3c_mode_(w3c_mode) {}
+  base::Thread* thread() { return &thread_; }
+  bool w3cMode() const { return w3c_mode_; }
+
+ private:
+  base::Thread thread_;
+  bool w3c_mode_;
+};
+
+using SessionThreadMap =
+    std::map<std::string, std::unique_ptr<SessionThreadInfo>>;
 
 #endif  // CHROME_TEST_CHROMEDRIVER_SESSION_THREAD_MAP_H_
diff --git a/chrome/test/chromedriver/test/run_py_tests.py b/chrome/test/chromedriver/test/run_py_tests.py
index 36fa18c..7692a95 100755
--- a/chrome/test/chromedriver/test/run_py_tests.py
+++ b/chrome/test/chromedriver/test/run_py_tests.py
@@ -1919,6 +1919,17 @@
         ChromeDriverTest.MakeRedImageTestScript(elementScreenshotPNGBase64))
     self.assertEquals('PASS', analysisResult)
 
+  def testTakeLargeElementScreenshot(self):
+    self._driver.Load(self.GetHttpUrlForFile(
+        '/chromedriver/large_element.html'))
+    self._driver.SetWindowRect(500, 500, 0, 0)
+    elementScreenshotPNGBase64 = self._driver.FindElement(
+        'css selector','#A').TakeElementScreenshot()
+    self.assertIsNotNone(elementScreenshotPNGBase64)
+    analysisResult = self._driver.ExecuteAsyncScript(
+        ChromeDriverTest.MakeRedImageTestScript(elementScreenshotPNGBase64))
+    self.assertEquals('PASS', analysisResult)
+
   def testGenerateTestReport(self):
     self._driver.Load(self.GetHttpUrlForFile(
                       '/chromedriver/reporting_observer.html'))
@@ -1951,6 +1962,20 @@
     value = self._driver.ExecuteScript('return arguments[0].value;', text)
     self.assertEquals('0123456789+-*/ Hi, there!', value)
 
+  def testSendKeysToElementAppend(self):
+      self._driver.Load(self.GetHttpUrlForFile(
+          '/chromedriver/empty.html'))
+      element = self._driver.ExecuteScript(
+          'document.body.innerHTML = '
+          '\'<input type="text" value="send_this_value">\';'
+          'var input = document.getElementsByTagName("input")[0];'
+          'input.focus();'
+          'input.setSelectionRange(0,0);'
+          'return input;')
+      element.SendKeys('hello')
+      value = self._driver.ExecuteScript('return arguments[0].value;', element)
+      self.assertEquals('send_this_valuehello', value)
+
   def testUnexpectedAlertOpenExceptionMessage(self):
     self._driver.Load(self.GetHttpUrlForFile('/chromedriver/empty.html'))
     self._driver.ExecuteScript('window.alert("Hi");')
diff --git a/chrome/test/data/chromedriver/large_element.html b/chrome/test/data/chromedriver/large_element.html
new file mode 100644
index 0000000..1261ca7
--- /dev/null
+++ b/chrome/test/data/chromedriver/large_element.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+  <body>
+    <div id="A" style="background-color: blue; height:5000px; width:5000px;">
+      <div id="B" style="background-color: red; height: 3500px; width:3500px;">
+      </div>
+    </div>
+  </body>
+</html>
diff --git a/chrome/test/data/extensions/api_test/networking_private/chromeos/test.js b/chrome/test/data/extensions/api_test/networking_private/chromeos/test.js
index 22784f4..dba9dc4 100644
--- a/chrome/test/data/extensions/api_test/networking_private/chromeos/test.js
+++ b/chrome/test/data/extensions/api_test/networking_private/chromeos/test.js
@@ -642,7 +642,6 @@
       'stub_wifi2',
       callbackPass(function(result) {
         assertEq({
-          Connectable: true,
           ConnectionState: ConnectionStateType.NOT_CONNECTED,
           GUID: 'stub_wifi2',
           Name: {
@@ -662,7 +661,6 @@
           Type: NetworkType.WI_FI,
           WiFi: {
             AutoConnect: {
-              Active: false,
               UserEditable: true
             },
             HexSSID: {
diff --git a/chrome/test/data/extensions/api_test/service_worker/events_to_stopped_extension/background.js b/chrome/test/data/extensions/api_test/service_worker/events_to_stopped_extension/background.js
deleted file mode 100644
index a9c1830..0000000
--- a/chrome/test/data/extensions/api_test/service_worker/events_to_stopped_extension/background.js
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-chrome.runtime.onInstalled.addListener(function() {
-  chrome.tabs.create({url: 'page.html'}, chrome.test.callbackPass());
-});
diff --git a/chrome/test/data/extensions/api_test/service_worker/events_to_stopped_extension/manifest.json b/chrome/test/data/extensions/api_test/service_worker/events_to_stopped_extension/manifest.json
deleted file mode 100644
index a8cffded..0000000
--- a/chrome/test/data/extensions/api_test/service_worker/events_to_stopped_extension/manifest.json
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-  "name": "Service worker with chrome.tabs.onCreated event",
-  "description": "Tests that dispatching events to worker works when extension is not running",
-  "version": "1.0",
-  "manifest_version": 2,
-  "permissions": ["tabs"],
-  "background": {
-    "scripts": ["background.js"],
-    "persistent": false
-  }
-}
diff --git a/chrome/test/data/extensions/api_test/service_worker/events_to_stopped_extension/page.html b/chrome/test/data/extensions/api_test/service_worker/events_to_stopped_extension/page.html
deleted file mode 100644
index f6e2de85..0000000
--- a/chrome/test/data/extensions/api_test/service_worker/events_to_stopped_extension/page.html
+++ /dev/null
@@ -1 +0,0 @@
-<script src="page.js"></script>
diff --git a/chrome/test/data/extensions/api_test/service_worker/events_to_stopped_extension/page.js b/chrome/test/data/extensions/api_test/service_worker/events_to_stopped_extension/page.js
deleted file mode 100644
index da41d97..0000000
--- a/chrome/test/data/extensions/api_test/service_worker/events_to_stopped_extension/page.js
+++ /dev/null
@@ -1,24 +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.
-
-var getReadyPromise = function() {
-  return new Promise(function(resolve, reject) {
-    navigator.serviceWorker.register('sw.js').then(function() {
-      return navigator.serviceWorker.ready;
-    }).then(function(registration) {
-      resolve('ready');
-    }).catch(function(err) {
-      reject(err);
-    });
-  });
-};
-
-window.runServiceWorkerAsync = function() {
-  chrome.test.log('runServiceWorkerAsync');
-  getReadyPromise().then(function(message) {
-    chrome.test.sendMessage('listener-added');
-  }).catch(function(err) {
-    chrome.test.sendMessage('FAILURE');
-  });
-};
diff --git a/chrome/test/data/extensions/api_test/service_worker/events_to_stopped_extension/sw.js b/chrome/test/data/extensions/api_test/service_worker/events_to_stopped_extension/sw.js
deleted file mode 100644
index ad924e0..0000000
--- a/chrome/test/data/extensions/api_test/service_worker/events_to_stopped_extension/sw.js
+++ /dev/null
@@ -1,8 +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.
-
-chrome.tabs.onCreated.addListener(function(tab) {
-  chrome.test.sendMessage(tab.url == 'about:blank' ?
-      'hello-newtab' : 'WRONG_NEWTAB');
-});
diff --git a/chrome/test/data/webui/test_api.js b/chrome/test/data/webui/test_api.js
index fb056a6f..4eb227b7 100644
--- a/chrome/test/data/webui/test_api.js
+++ b/chrome/test/data/webui/test_api.js
@@ -1512,29 +1512,6 @@
 }
 
 /**
- * Syntactic sugar for use with will() on a Mock4JS.Mock.
- * Creates an action for will() that invokes a callback that the tested code
- * passes to a mocked function.
- * @param {SaveMockArguments} savedArgs Arguments that will contain the
- *     callback once the mocked function is called.
- * @param {number} callbackParameter Index of the callback parameter in
- *     |savedArgs|.
- * @param {...Object} var_args Arguments to pass to the callback.
- * @return {CallFunctionAction} Action for use in will().
- */
-function invokeCallback(savedArgs, callbackParameter, var_args) {
-  var callbackArguments = Array.prototype.slice.call(arguments, 2);
-  return callFunction(function() {
-    savedArgs.arguments[callbackParameter].apply(null, callbackArguments);
-
-    // Mock4JS does not clear the saved args after invocation.
-    // To allow reuse of the same SaveMockArguments for multiple
-    // invocations with similar arguments, clear them here.
-    savedArgs.arguments.splice(0, savedArgs.arguments.length);
-  });
-}
-
-/**
  * Mock4JS matcher object that matches the actual argument and the expected
  * value iff their JSON representations are same.
  * @param {Object} expectedValue
@@ -1575,46 +1552,6 @@
 }
 
 /**
- * Mock4JS matcher object that matches the actual argument and the expected
- * value iff the the string representation of the actual argument is equal to
- * the expected value.
- * @param {string} expectedValue
- * @constructor
- */
-function MatchToString(expectedValue) {
-  this.expectedValue_ = expectedValue;
-}
-
-MatchToString.prototype = {
-  /**
-   * Checks that the the string representation of the actual argument matches
-   * the expected value.
-   * @param {*} actualArgument The argument to match.
-   * @return {boolean} Result of the comparison.
-   */
-  argumentMatches: function(actualArgument) {
-    return this.expectedValue_ === String(actualArgument);
-  },
-
-  /**
-   * Describes the matcher.
-   * @return {string} Description of this Mock4JS matcher.
-   */
-  describe: function() {
-    return 'eqToString("' + this.expectedValue_ + '")';
-  },
-};
-
-/**
- * Builds a MatchToString argument matcher for a given expected value.
- * @param {Object} expectedValue
- * @return {MatchToString} Resulting Mock4JS matcher.
- */
-function eqToString(expectedValue) {
-  return new MatchToString(expectedValue);
-}
-
-/**
  * Exports assertion methods. All assertion methods delegate to the chai.js
  * assertion library.
  */
@@ -1658,8 +1595,6 @@
   exports.callFunction = callFunction;
   exports.callFunctionWithSavedArgs = callFunctionWithSavedArgs;
   exports.eqJSON = eqJSON;
-  exports.eqToString = eqToString;
-  exports.invokeCallback = invokeCallback;
   exports.SaveMockArguments = SaveMockArguments;
 
   // Import the Mock4JS helpers.
diff --git a/chrome/test/pixel/skia_gold_pixel_diff.cc b/chrome/test/pixel/skia_gold_pixel_diff.cc
index 794edd2b..1d5b876 100644
--- a/chrome/test/pixel/skia_gold_pixel_diff.cc
+++ b/chrome/test/pixel/skia_gold_pixel_diff.cc
@@ -41,6 +41,11 @@
 
 std::string kBuildRevisionKey = "build-revision";
 
+// The switch keys for tryjob.
+std::string kIssueKey = "issue";
+std::string kPatchSetKey = "patchset";
+std::string kJobIdKey = "jobid";
+
 std::string kNoLuciAuth = "no-luci-auth";
 
 SkiaGoldPixelDiff::SkiaGoldPixelDiff() = default;
@@ -151,6 +156,11 @@
   cmd.AppendSwitchPath("failure-file", failure_temp_file);
   cmd.AppendSwitch("passfail");
   cmd.AppendSwitchASCII("commit", build_revision_);
+  if (issue_.length()) {
+    cmd.AppendSwitchASCII("issue", issue_);
+    cmd.AppendSwitchASCII("patchset", patchset_);
+    cmd.AppendSwitchASCII("jobid", job_id_);
+  }
   AppendArgsJustAfterProgram(cmd, {FILE_PATH_LITERAL("imgtest"), FILE_PATH_LITERAL("init")});
   cmd_str = cmd.GetCommandLineString();
   LOG(INFO) << "Skia Gold imgtest init Commandline: " << cmd_str;
@@ -163,7 +173,21 @@
   auto* cmd_line = base::CommandLine::ForCurrentProcess();
   ASSERT_TRUE(cmd_line->HasSwitch(kBuildRevisionKey))
       << "Missing switch " << kBuildRevisionKey;
+  ASSERT_TRUE(cmd_line->HasSwitch(kIssueKey) &&
+      cmd_line->HasSwitch(kPatchSetKey) &&
+      cmd_line->HasSwitch(kJobIdKey) ||
+      !cmd_line->HasSwitch(kIssueKey) &&
+      !cmd_line->HasSwitch(kPatchSetKey) &&
+      !cmd_line->HasSwitch(kJobIdKey))
+      << "Missing switch. If it's running for tryjob, you should pass --"
+      << kIssueKey << " --" << kPatchSetKey << " --" << kJobIdKey
+      << ". Otherwise, do not pass any one of them.";
   build_revision_ = cmd_line->GetSwitchValueASCII(kBuildRevisionKey);
+  if (cmd_line->HasSwitch(kIssueKey)) {
+    issue_ = cmd_line->GetSwitchValueASCII(kIssueKey);
+    patchset_ = cmd_line->GetSwitchValueASCII(kPatchSetKey);
+    job_id_ = cmd_line->GetSwitchValueASCII(kJobIdKey);
+  }
   if (cmd_line->HasSwitch(kNoLuciAuth)) {
     luci_auth_ = false;
   }
diff --git a/chrome/test/pixel/skia_gold_pixel_diff.h b/chrome/test/pixel/skia_gold_pixel_diff.h
index d85d6081..ead3b071 100644
--- a/chrome/test/pixel/skia_gold_pixel_diff.h
+++ b/chrome/test/pixel/skia_gold_pixel_diff.h
@@ -76,6 +76,9 @@
   // Use luci auth on bots. Don't use luci auth for local development.
   bool luci_auth_ = true;
   std::string build_revision_;
+  std::string issue_;
+  std::string patchset_;
+  std::string job_id_;
   // The working dir for goldctl. It's the dir for storing temporary files.
   base::FilePath working_dir_;
 };
diff --git a/chromecast/media/cma/backend/android/java/src/org/chromium/chromecast/cma/backend/android/VolumeControl.java b/chromecast/media/cma/backend/android/java/src/org/chromium/chromecast/cma/backend/android/VolumeControl.java
index 49535eb6..05d731a 100644
--- a/chromecast/media/cma/backend/android/java/src/org/chromium/chromecast/cma/backend/android/VolumeControl.java
+++ b/chromecast/media/cma/backend/android/java/src/org/chromium/chromecast/cma/backend/android/VolumeControl.java
@@ -89,9 +89,13 @@
         /** Sets the given mute state in AudioManager. */
         void setMuted(boolean muted) {
             if (DEBUG_LEVEL >= 1) Log.i(TAG, "setMuted: muted=" + muted);
-            int direction = muted ? AudioManager.ADJUST_MUTE : AudioManager.ADJUST_UNMUTE;
-            int flag = 0;
-            mAudioManager.adjustStreamVolume(mStreamType, direction, flag);
+            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+                int direction = muted ? AudioManager.ADJUST_MUTE : AudioManager.ADJUST_UNMUTE;
+                int flag = 0;
+                mAudioManager.adjustStreamVolume(mStreamType, direction, flag);
+            } else {
+                mAudioManager.setStreamMute(mStreamType, muted);
+            }
         }
 
         /** Refreshes the stored mute state by reading it from AudioManager.
diff --git a/chromecast/media/cma/backend/android/java/src/org/chromium/chromecast/cma/backend/android/VolumeMap.java b/chromecast/media/cma/backend/android/java/src/org/chromium/chromecast/cma/backend/android/VolumeMap.java
index af3c33f8..1f1987d 100644
--- a/chromecast/media/cma/backend/android/java/src/org/chromium/chromecast/cma/backend/android/VolumeMap.java
+++ b/chromecast/media/cma/backend/android/java/src/org/chromium/chromecast/cma/backend/android/VolumeMap.java
@@ -55,14 +55,21 @@
 
     private static final SparseIntArray MIN_VOLUME_INDEX = new SparseIntArray(4) {
         {
-            append(AudioManager.STREAM_MUSIC,
-                    getAudioManager().getStreamMinVolume(AudioManager.STREAM_MUSIC));
-            append(AudioManager.STREAM_ALARM,
-                    getAudioManager().getStreamMinVolume(AudioManager.STREAM_ALARM));
-            append(AudioManager.STREAM_SYSTEM,
-                    getAudioManager().getStreamMinVolume(AudioManager.STREAM_SYSTEM));
-            append(AudioManager.STREAM_VOICE_CALL,
-                    getAudioManager().getStreamMinVolume(AudioManager.STREAM_VOICE_CALL));
+            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
+                append(AudioManager.STREAM_MUSIC,
+                        getAudioManager().getStreamMinVolume(AudioManager.STREAM_MUSIC));
+                append(AudioManager.STREAM_ALARM,
+                        getAudioManager().getStreamMinVolume(AudioManager.STREAM_ALARM));
+                append(AudioManager.STREAM_SYSTEM,
+                        getAudioManager().getStreamMinVolume(AudioManager.STREAM_SYSTEM));
+                append(AudioManager.STREAM_VOICE_CALL,
+                        getAudioManager().getStreamMinVolume(AudioManager.STREAM_VOICE_CALL));
+            } else {
+                append(AudioManager.STREAM_MUSIC, 0);
+                append(AudioManager.STREAM_ALARM, 0);
+                append(AudioManager.STREAM_SYSTEM, 0);
+                append(AudioManager.STREAM_VOICE_CALL, 0);
+            }
         }
     };
 
diff --git a/chromecast/public/reboot_shlib.h b/chromecast/public/reboot_shlib.h
index 7a6a2e3f..09b66b0 100644
--- a/chromecast/public/reboot_shlib.h
+++ b/chromecast/public/reboot_shlib.h
@@ -68,6 +68,10 @@
 
     // A reboot caused by overheat.
     OVERHEAT = 11,
+
+    // The device got into a state such that it needs to regenerate the cloud
+    // device id.
+    REGENERATE_CLOUD_ID = 12,
   };
 
   // Initializes any platform-specific reboot systems.
diff --git a/chromecast/system/reboot/BUILD.gn b/chromecast/system/reboot/BUILD.gn
index 1dd9762b..596a6fb 100644
--- a/chromecast/system/reboot/BUILD.gn
+++ b/chromecast/system/reboot/BUILD.gn
@@ -21,14 +21,11 @@
     sources += [ "reboot_util_dummy.cc" ]
   }
 
-  if (is_android_things && chromecast_branding != "public") {
+  if (is_android && chromecast_branding != "public") {
     deps += [
-      "//chromecast/internal/system/reboot/android:reboot_android_things",
+      "//chromecast/internal/system/reboot/android:reboot_shlib_impl",
       "//chromecast/public",
     ]
-  } else if (is_android) {
-    sources += [ "reboot_dummy.cc" ]
-    deps += [ "//chromecast/public" ]
   } else {
     deps += [ ":libcast_reboot_1.0" ]
   }
diff --git a/chromecast/system/reboot/reboot_util_core.cc b/chromecast/system/reboot/reboot_util_core.cc
index c10bb4fa..0a0258e6 100644
--- a/chromecast/system/reboot/reboot_util_core.cc
+++ b/chromecast/system/reboot/reboot_util_core.cc
@@ -40,6 +40,7 @@
     case RebootShlib::RebootSource::HW_WATCHDOG:
     case RebootShlib::RebootSource::SW_OTHER:
     case RebootShlib::RebootSource::OVERHEAT:
+    case RebootShlib::RebootSource::REGENERATE_CLOUD_ID:
       return true;
     default:
       return false;
diff --git a/chromeos/dbus/shill/fake_shill_profile_client.cc b/chromeos/dbus/shill/fake_shill_profile_client.cc
index f91ccee..d4a8886 100644
--- a/chromeos/dbus/shill/fake_shill_profile_client.cc
+++ b/chromeos/dbus/shill/fake_shill_profile_client.cc
@@ -112,9 +112,9 @@
     return;
   }
 
-  base::Value profile_path_value("");
-  ShillServiceClient::Get()->GetTestInterface()->SetServiceProperty(
-      entry_path, shill::kProfileProperty, profile_path_value);
+  ShillServiceClient::Get()
+      ->GetTestInterface()
+      ->ClearConfiguredServiceProperties(entry_path);
 
   base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, callback);
 }
diff --git a/chromeos/dbus/shill/fake_shill_service_client.cc b/chromeos/dbus/shill/fake_shill_service_client.cc
index 0944ecb..18d02e2 100644
--- a/chromeos/dbus/shill/fake_shill_service_client.cc
+++ b/chromeos/dbus/shill/fake_shill_service_client.cc
@@ -120,6 +120,29 @@
   return false;
 }
 
+// Properties that should be retained when a visible service is deleted from a
+// profile, i.e. when all its configured properties are removed. This should
+// contain properties which can be "observed", e.g. a SSID.
+// For simplicity, these are not distinguished by service type.
+constexpr const char* kIntrinsicServiceProperties[] = {
+    shill::kTypeProperty,
+    shill::kDeviceProperty,
+    shill::kVisibleProperty,
+    shill::kStateProperty,
+    shill::kSSIDProperty,
+    shill::kWifiHexSsid,
+    shill::kSignalStrengthProperty,
+    shill::kWifiFrequency,
+    shill::kWifiFrequencyListProperty,
+    shill::kWifiHexSsid,
+    shill::kModeProperty,
+    shill::kSecurityProperty,
+    shill::kSecurityClassProperty,
+    shill::kNetworkTechnologyProperty,
+    shill::kNameProperty,
+    shill::kProviderProperty,
+    shill::kTetheringProperty};
+
 }  // namespace
 
 FakeShillServiceClient::FakeShillServiceClient() : weak_ptr_factory_(this) {}
@@ -560,6 +583,40 @@
   return properties;
 }
 
+bool FakeShillServiceClient::ClearConfiguredServiceProperties(
+    const std::string& service_path) {
+  base::Value* service_dict = GetModifiableServiceProperties(
+      service_path, false /* create_if_missing */);
+  if (!service_dict)
+    return false;
+
+  const base::Value* visible_property = service_dict->FindKeyOfType(
+      shill::kVisibleProperty, base::Value::Type::BOOLEAN);
+  if (!visible_property || !visible_property->GetBool()) {
+    stub_services_.RemoveKey(service_path);
+    RemoveService(service_path);
+    return true;
+  }
+
+  base::DictionaryValue properties_after_delete_entry;
+
+  // Explicitly clear the profile property using SetServiceProperty so a
+  // notification is sent about that.
+  SetServiceProperty(service_path, shill::kProfileProperty,
+                     base::Value(std::string()));
+  properties_after_delete_entry.SetKey(shill::kProfileProperty,
+                                       base::Value(std::string()));
+
+  for (const std::string& property_to_retain : kIntrinsicServiceProperties) {
+    const base::Value* value = service_dict->FindKey(property_to_retain);
+    if (!value)
+      continue;
+    properties_after_delete_entry.SetKey(property_to_retain, value->Clone());
+  }
+  stub_services_.SetKey(service_path, std::move(properties_after_delete_entry));
+  return true;
+}
+
 std::string FakeShillServiceClient::FindServiceMatchingGUID(
     const std::string& guid) {
   for (const auto& service_pair : stub_services_.DictItems()) {
diff --git a/chromeos/dbus/shill/fake_shill_service_client.h b/chromeos/dbus/shill/fake_shill_service_client.h
index fd8b858..7bcf14d 100644
--- a/chromeos/dbus/shill/fake_shill_service_client.h
+++ b/chromeos/dbus/shill/fake_shill_service_client.h
@@ -100,6 +100,8 @@
                           const base::Value& value) override;
   const base::DictionaryValue* GetServiceProperties(
       const std::string& service_path) const override;
+  bool ClearConfiguredServiceProperties(
+      const std::string& service_path) override;
   std::string FindServiceMatchingGUID(const std::string& guid) override;
   std::string FindSimilarService(
       const base::Value& template_service_properties) override;
diff --git a/chromeos/dbus/shill/modem_messaging_client_unittest.cc b/chromeos/dbus/shill/modem_messaging_client_unittest.cc
index 0444546..3e0bc3c 100644
--- a/chromeos/dbus/shill/modem_messaging_client_unittest.cc
+++ b/chromeos/dbus/shill/modem_messaging_client_unittest.cc
@@ -9,10 +9,10 @@
 
 #include "base/bind.h"
 #include "base/location.h"
-#include "base/message_loop/message_loop.h"
 #include "base/optional.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
+#include "base/test/scoped_task_environment.h"
 #include "base/values.h"
 #include "dbus/message.h"
 #include "dbus/mock_bus.h"
@@ -99,7 +99,7 @@
     EXPECT_EQ(expected_sms_path_, sms_path);
     EXPECT_FALSE(reader.HasMoreData());
 
-    message_loop_.task_runner()->PostTask(
+    scoped_task_environment_.GetMainThreadTaskRunner()->PostTask(
         FROM_HERE, base::BindOnce(std::move(*callback), response_));
   }
 
@@ -113,14 +113,14 @@
     dbus::MessageReader reader(method_call);
     EXPECT_FALSE(reader.HasMoreData());
 
-    message_loop_.task_runner()->PostTask(
+    scoped_task_environment_.GetMainThreadTaskRunner()->PostTask(
         FROM_HERE, base::BindOnce(std::move(*callback), response_));
   }
 
  protected:
   ModemMessagingClient* client_ = nullptr;  // Unowned convenience pointer.
   // A message loop to emulate asynchronous behavior.
-  base::MessageLoop message_loop_;
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
   // The mock bus.
   scoped_refptr<dbus::MockBus> mock_bus_;
   // The mock object proxy.
@@ -141,7 +141,7 @@
       dbus::ObjectProxy::OnConnectedCallback* on_connected_callback) {
     sms_received_callback_ = signal_callback;
     const bool success = true;
-    message_loop_.task_runner()->PostTask(
+    scoped_task_environment_.GetMainThreadTaskRunner()->PostTask(
         FROM_HERE, base::BindOnce(std::move(*on_connected_callback),
                                   interface_name, signal_name, success));
   }
diff --git a/chromeos/dbus/shill/shill_client_unittest_base.cc b/chromeos/dbus/shill/shill_client_unittest_base.cc
index 9b95990..596e2d21 100644
--- a/chromeos/dbus/shill/shill_client_unittest_base.cc
+++ b/chromeos/dbus/shill/shill_client_unittest_base.cc
@@ -139,7 +139,8 @@
   // Set an expectation so mock_bus's GetDBusTaskRunner will return the current
   // task runner.
   EXPECT_CALL(*mock_bus_.get(), GetDBusTaskRunner())
-      .WillRepeatedly(Return(message_loop_.task_runner().get()));
+      .WillRepeatedly(
+          Return(scoped_task_environment_.GetMainThreadTaskRunner().get()));
 
   // ShutdownAndBlock() will be called in TearDown().
   EXPECT_CALL(*mock_bus_.get(), ShutdownAndBlock()).WillOnce(Return());
@@ -380,7 +381,7 @@
     dbus::ObjectProxy::OnConnectedCallback* on_connected_callback) {
   platform_message_handler_ = signal_callback;
   const bool success = true;
-  message_loop_.task_runner()->PostTask(
+  scoped_task_environment_.GetMainThreadTaskRunner()->PostTask(
       FROM_HERE, base::BindOnce(std::move(*on_connected_callback),
                                 interface_name, signal_name, success));
 }
@@ -392,7 +393,7 @@
     dbus::ObjectProxy::OnConnectedCallback* on_connected_callback) {
   packet_receieved__handler_ = signal_callback;
   const bool success = true;
-  message_loop_.task_runner()->PostTask(
+  scoped_task_environment_.GetMainThreadTaskRunner()->PostTask(
       FROM_HERE, base::BindOnce(std::move(*on_connected_callback),
                                 interface_name, signal_name, success));
 }
@@ -404,7 +405,7 @@
     dbus::ObjectProxy::OnConnectedCallback* on_connected_callback) {
   property_changed_handler_ = signal_callback;
   const bool success = true;
-  message_loop_.task_runner()->PostTask(
+  scoped_task_environment_.GetMainThreadTaskRunner()->PostTask(
       FROM_HERE, base::BindOnce(std::move(*on_connected_callback),
                                 interface_name, signal_name, success));
 }
@@ -417,7 +418,7 @@
   EXPECT_EQ(expected_method_name_, method_call->GetMember());
   dbus::MessageReader reader(method_call);
   argument_checker_.Run(&reader);
-  message_loop_.task_runner()->PostTask(
+  scoped_task_environment_.GetMainThreadTaskRunner()->PostTask(
       FROM_HERE, base::BindOnce(std::move(*response_callback), response_));
 }
 
diff --git a/chromeos/dbus/shill/shill_client_unittest_base.h b/chromeos/dbus/shill/shill_client_unittest_base.h
index 23b9c4eb..a555db3 100644
--- a/chromeos/dbus/shill/shill_client_unittest_base.h
+++ b/chromeos/dbus/shill/shill_client_unittest_base.h
@@ -12,7 +12,7 @@
 #include <vector>
 
 #include "base/memory/ref_counted.h"
-#include "base/message_loop/message_loop.h"
+#include "base/test/scoped_task_environment.h"
 #include "chromeos/dbus/dbus_method_call_status.h"
 #include "chromeos/dbus/shill/shill_client_helper.h"
 #include "chromeos/dbus/shill/shill_property_changed_observer.h"
@@ -173,7 +173,7 @@
       const base::DictionaryValue& result);
 
   // A message loop to emulate asynchronous behavior.
-  base::MessageLoop message_loop_;
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
   // The mock bus.
   scoped_refptr<dbus::MockBus> mock_bus_;
 
diff --git a/chromeos/dbus/shill/shill_service_client.h b/chromeos/dbus/shill/shill_service_client.h
index 2974376..d8c2c0a 100644
--- a/chromeos/dbus/shill/shill_service_client.h
+++ b/chromeos/dbus/shill/shill_service_client.h
@@ -76,6 +76,16 @@
     virtual const base::DictionaryValue* GetServiceProperties(
         const std::string& service_path) const = 0;
 
+    // If the service referenced by |service_path| is not visible (according to
+    // its |shill::kVisibleProperty|, it is removed completely. If the service
+    // referenced by |service_path| is visible, keeps only its "intrinsic"
+    // properties and removes all other properties. Intrinsic properties are
+    // properties that describe the identity or the state of  the service and
+    // are not configurable, such as SSID (for wifi), signal strength (for wifi)
+    // or provider (for VPN). All other properties are removed.
+    virtual bool ClearConfiguredServiceProperties(
+        const std::string& service_path) = 0;
+
     // Returns the service path for the service which has the GUID property set
     // to |guid|. If no such service exists, returns the empty string.
     virtual std::string FindServiceMatchingGUID(const std::string& guid) = 0;
diff --git a/chromeos/geolocation/BUILD.gn b/chromeos/geolocation/BUILD.gn
index 4bc2e9df..acbb141f 100644
--- a/chromeos/geolocation/BUILD.gn
+++ b/chromeos/geolocation/BUILD.gn
@@ -32,6 +32,7 @@
   deps = [
     ":geolocation",
     "//base",
+    "//base/test:test_support",
     "//chromeos/dbus/shill",
     "//chromeos/network:test_support",
     "//net",
diff --git a/chromeos/geolocation/simple_geolocation_unittest.cc b/chromeos/geolocation/simple_geolocation_unittest.cc
index 81ef9ca6..86923d1a 100644
--- a/chromeos/geolocation/simple_geolocation_unittest.cc
+++ b/chromeos/geolocation/simple_geolocation_unittest.cc
@@ -6,10 +6,10 @@
 
 #include "base/bind.h"
 #include "base/macros.h"
-#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
+#include "base/test/scoped_task_environment.h"
 #include "chromeos/dbus/shill/shill_clients.h"
 #include "chromeos/dbus/shill/shill_manager_client.h"
 #include "chromeos/geolocation/simple_geolocation_provider.h"
@@ -182,7 +182,7 @@
 
 class SimpleGeolocationTest : public testing::Test {
  private:
-  base::MessageLoop message_loop_;
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
 };
 
 TEST_F(SimpleGeolocationTest, ResponseOK) {
diff --git a/chromeos/timezone/BUILD.gn b/chromeos/timezone/BUILD.gn
index 4a84d48..4a75140 100644
--- a/chromeos/timezone/BUILD.gn
+++ b/chromeos/timezone/BUILD.gn
@@ -31,6 +31,7 @@
   deps = [
     ":timezone",
     "//base",
+    "//base/test:test_support",
     "//chromeos/geolocation",
     "//net",
     "//services/network:test_support",
diff --git a/chromeos/timezone/timezone_unittest.cc b/chromeos/timezone/timezone_unittest.cc
index 15a5e33..26d58d8 100644
--- a/chromeos/timezone/timezone_unittest.cc
+++ b/chromeos/timezone/timezone_unittest.cc
@@ -7,8 +7,8 @@
 
 #include "base/bind.h"
 #include "base/macros.h"
-#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
+#include "base/test/scoped_task_environment.h"
 #include "chromeos/geolocation/geoposition.h"
 #include "chromeos/timezone/timezone_provider.h"
 #include "chromeos/timezone/timezone_resolver.h"
@@ -159,7 +159,7 @@
 
 class TimeZoneTest : public testing::Test {
  private:
-  base::MessageLoop message_loop_;
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
 };
 
 TEST_F(TimeZoneTest, ResponseOK) {
diff --git a/components/autofill/content/browser/content_autofill_driver_unittest.cc b/components/autofill/content/browser/content_autofill_driver_unittest.cc
index c0dc02d..3084327 100644
--- a/components/autofill/content/browser/content_autofill_driver_unittest.cc
+++ b/components/autofill/content/browser/content_autofill_driver_unittest.cc
@@ -317,15 +317,6 @@
   FakeAutofillAgent fake_agent_;
 };
 
-TEST_F(ContentAutofillDriverTest, GetURLRequestContext) {
-  net::URLRequestContextGetter* request_context =
-      driver_->GetURLRequestContext();
-  net::URLRequestContextGetter* expected_request_context =
-      content::BrowserContext::GetDefaultStoragePartition(
-          web_contents()->GetBrowserContext())->GetURLRequestContext();
-  EXPECT_EQ(request_context, expected_request_context);
-}
-
 TEST_F(ContentAutofillDriverTest, NavigatedMainFrameDifferentDocument) {
   EXPECT_CALL(*driver_->mock_autofill_manager(), Reset());
   Navigate(/*same_document=*/false);
diff --git a/components/autofill/core/browser/autofill_client.h b/components/autofill/core/browser/autofill_client.h
index a363a2b7..11f094d 100644
--- a/components/autofill/core/browser/autofill_client.h
+++ b/components/autofill/core/browser/autofill_client.h
@@ -317,6 +317,12 @@
       SaveCreditCardOptions options,
       UploadSaveCardPromptCallback callback) = 0;
 
+  // Called after credit card upload is finished. Will show upload result to
+  // users.
+  // TODO(crbug.com/964127): It handles only failure branch now. Success branch
+  // will be added later.
+  virtual void CreditCardUploadCompleted() = 0;
+
   // Will show an infobar to get user consent for Credit Card assistive filling.
   // Will run |callback| on success.
   virtual void ConfirmCreditCardFillAssist(const CreditCard& card,
diff --git a/components/autofill/core/browser/payments/credit_card_save_manager.cc b/components/autofill/core/browser/payments/credit_card_save_manager.cc
index c130c2e7..a7165ca 100644
--- a/components/autofill/core/browser/payments/credit_card_save_manager.cc
+++ b/components/autofill/core/browser/payments/credit_card_save_manager.cc
@@ -319,6 +319,9 @@
       // Notify the browsertests that a strike was added.
       OnStrikeChangeComplete(nth_strike_added);
     }
+
+    // Show credit card upload feedback.
+    client_->CreditCardUploadCompleted();
   }
 }
 
diff --git a/components/autofill/core/browser/test_autofill_client.cc b/components/autofill/core/browser/test_autofill_client.cc
index b68754f62..c0eba6c 100644
--- a/components/autofill/core/browser/test_autofill_client.cc
+++ b/components/autofill/core/browser/test_autofill_client.cc
@@ -152,6 +152,8 @@
   std::move(callback).Run(AutofillClient::ACCEPTED, {});
 }
 
+void TestAutofillClient::CreditCardUploadCompleted() {}
+
 void TestAutofillClient::ConfirmCreditCardFillAssist(
     const CreditCard& card,
     base::OnceClosure callback) {
diff --git a/components/autofill/core/browser/test_autofill_client.h b/components/autofill/core/browser/test_autofill_client.h
index 3b3b739..b4a3eb4 100644
--- a/components/autofill/core/browser/test_autofill_client.h
+++ b/components/autofill/core/browser/test_autofill_client.h
@@ -82,6 +82,7 @@
       std::unique_ptr<base::DictionaryValue> legal_message,
       SaveCreditCardOptions options,
       UploadSaveCardPromptCallback callback) override;
+  void CreditCardUploadCompleted() override;
   void ConfirmCreditCardFillAssist(const CreditCard& card,
                                    base::OnceClosure callback) override;
   bool HasCreditCardScanFeature() override;
diff --git a/components/cronet/tools/cr_cronet.py b/components/cronet/tools/cr_cronet.py
index 5c58e2d..8a94a0a 100755
--- a/components/cronet/tools/cr_cronet.py
+++ b/components/cronet/tools/cr_cronet.py
@@ -114,7 +114,7 @@
 def get_ios_gn_args(is_release, target_cpu):
   return get_mobile_gn_args('ios', is_release) + \
       'is_cronet_build=true  ' + \
-      'use_xcode_clang=true ' + \
+      'use_xcode_clang=false ' + \
       'ios_deployment_target="9.0" ' + \
       'enable_dsyms=true ' + \
       'target_cpu="%s" ' % target_cpu
diff --git a/components/data_reduction_proxy/core/browser/BUILD.gn b/components/data_reduction_proxy/core/browser/BUILD.gn
index 2e8cfccb..c00b6b4 100644
--- a/components/data_reduction_proxy/core/browser/BUILD.gn
+++ b/components/data_reduction_proxy/core/browser/BUILD.gn
@@ -201,6 +201,7 @@
     "//components/previews/core:test_support",
     "//components/variations",
     "//content/public/browser",
+    "//content/test:test_support",
     "//net:test_support",
     "//services/network:network_service",
     "//services/network:test_support",
diff --git a/components/data_reduction_proxy/core/browser/DEPS b/components/data_reduction_proxy/core/browser/DEPS
index 3fe2155..63e2976 100644
--- a/components/data_reduction_proxy/core/browser/DEPS
+++ b/components/data_reduction_proxy/core/browser/DEPS
@@ -5,4 +5,5 @@
   "+services/network/test",
   "+third_party/leveldatabase",
   "+content/public/browser",
+  "+content/public/test",
 ]
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 2f4e2d84..f460124a 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
@@ -217,7 +217,7 @@
 
   secure_proxy_checker_.reset(new SecureProxyChecker(url_loader_factory));
   warmup_url_fetcher_.reset(new WarmupURLFetcher(
-      url_loader_factory, create_custom_proxy_config_callback,
+      create_custom_proxy_config_callback,
       base::BindRepeating(
           &DataReductionProxyConfig::HandleWarmupFetcherResponse,
           base::Unretained(this)),
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_unittest.cc
index cb5ea98..b80e6d3 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_unittest.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_unittest.cc
@@ -27,7 +27,6 @@
 #include "base/strings/string_util.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/scoped_feature_list.h"
-#include "base/test/scoped_task_environment.h"
 #include "base/test/simple_test_tick_clock.h"
 #include "base/threading/platform_thread.h"
 #include "base/time/default_clock.h"
@@ -45,6 +44,7 @@
 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_type_info.h"
 #include "components/data_reduction_proxy/proto/client_config.pb.h"
 #include "components/variations/variations_associated_data.h"
+#include "content/public/test/test_browser_thread_bundle.h"
 #include "net/base/load_flags.h"
 #include "net/base/net_errors.h"
 #include "net/base/network_change_notifier.h"
@@ -205,7 +205,7 @@
     return test_context_->GetConfiguredProxiesForHttp();
   }
 
-  base::test::ScopedTaskEnvironment task_environment_{
+  content::TestBrowserThreadBundle task_environment_{
       base::test::ScopedTaskEnvironment::MainThreadType::IO};
 
   std::unique_ptr<DataReductionProxyTestContext> test_context_;
@@ -414,7 +414,6 @@
     base::FieldTrialList::CreateFieldTrial(params::GetQuicFieldTrialName(),
                                            "Enabled");
 
-    base::CommandLine::ForCurrentProcess()->InitFromArgv(0, nullptr);
     TestDataReductionProxyConfig config(task_runner(), task_runner(),
                                         configurator());
 
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data_unittest.cc
index 426080a..4b72a73 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data_unittest.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data_unittest.cc
@@ -12,7 +12,6 @@
 #include "base/metrics/field_trial.h"
 #include "base/run_loop.h"
 #include "base/strings/string_number_conversions.h"
-#include "base/test/scoped_task_environment.h"
 #include "base/time/default_clock.h"
 #include "base/time/time.h"
 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_config.h"
@@ -31,6 +30,7 @@
 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_switches.h"
 #include "components/prefs/pref_service.h"
 #include "components/prefs/testing_pref_service.h"
+#include "content/public/test/test_browser_thread_bundle.h"
 #include "mojo/public/cpp/bindings/strong_binding.h"
 #include "net/proxy_resolution/proxy_info.h"
 #include "net/proxy_resolution/proxy_resolution_service.h"
@@ -77,7 +77,7 @@
   }
 
  protected:
-  base::test::ScopedTaskEnvironment scoped_task_environment_;
+  content::TestBrowserThreadBundle scoped_task_environment_;
 
  private:
   TestingPrefServiceSimple prefs_;
diff --git a/components/data_reduction_proxy/core/browser/warmup_url_fetcher.cc b/components/data_reduction_proxy/core/browser/warmup_url_fetcher.cc
index 273eadb..a200849c 100644
--- a/components/data_reduction_proxy/core/browser/warmup_url_fetcher.cc
+++ b/components/data_reduction_proxy/core/browser/warmup_url_fetcher.cc
@@ -43,8 +43,6 @@
 }
 
 WarmupURLFetcher::WarmupURLFetcher(
-    scoped_refptr<network::SharedURLLoaderFactory>
-        non_network_service_url_loader_factory,
     CreateCustomProxyConfigCallback create_custom_proxy_config_callback,
     WarmupURLFetcherCallback callback,
     GetHttpRttCallback get_http_rtt_callback,
@@ -52,14 +50,11 @@
     const std::string& user_agent)
     : is_fetch_in_flight_(false),
       previous_attempt_counts_(0),
-      non_network_service_url_loader_factory_(
-          std::move(non_network_service_url_loader_factory)),
       create_custom_proxy_config_callback_(create_custom_proxy_config_callback),
       callback_(callback),
       get_http_rtt_callback_(get_http_rtt_callback),
       user_agent_(user_agent),
       ui_task_runner_(ui_task_runner) {
-  DCHECK(non_network_service_url_loader_factory_);
   DCHECK(create_custom_proxy_config_callback);
 }
 
@@ -162,15 +157,11 @@
       &WarmupURLFetcher::OnURLLoadResponseStarted, base::Unretained(this)));
   url_loader_->SetOnRedirectCallback(base::BindRepeating(
       &WarmupURLFetcher::OnURLLoaderRedirect, base::Unretained(this)));
-  network::mojom::URLLoaderFactory* factory = nullptr;
-  if (params::IsEnabledWithNetworkService())
-    factory = GetNetworkServiceURLLoaderFactory(proxy_server);
-  else
-    factory = non_network_service_url_loader_factory_.get();
 
   url_loader_->DownloadToStringOfUnboundedSizeUntilCrashAndDie(
-      factory, base::BindOnce(&WarmupURLFetcher::OnURLLoadComplete,
-                              base::Unretained(this)));
+      GetNetworkServiceURLLoaderFactory(proxy_server),
+      base::BindOnce(&WarmupURLFetcher::OnURLLoadComplete,
+                     base::Unretained(this)));
 }
 
 network::mojom::URLLoaderFactory*
diff --git a/components/data_reduction_proxy/core/browser/warmup_url_fetcher.h b/components/data_reduction_proxy/core/browser/warmup_url_fetcher.h
index 578b8680..fe60789 100644
--- a/components/data_reduction_proxy/core/browser/warmup_url_fetcher.h
+++ b/components/data_reduction_proxy/core/browser/warmup_url_fetcher.h
@@ -24,7 +24,6 @@
 
 namespace network {
 struct ResourceResponseHead;
-class SharedURLLoaderFactory;
 class SimpleURLLoader;
 }  // namespace network
 
@@ -50,7 +49,6 @@
           const std::vector<DataReductionProxyServer>&)>;
 
   WarmupURLFetcher(
-      scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
       CreateCustomProxyConfigCallback create_custom_proxy_config_callback,
       WarmupURLFetcherCallback callback,
       GetHttpRttCallback get_http_rtt_callback,
@@ -124,15 +122,13 @@
 
   // Gets a URLLoaderFactory which will only attempt to use |proxy_server| as a
   // proxy.
-  network::mojom::URLLoaderFactory* GetNetworkServiceURLLoaderFactory(
+  virtual network::mojom::URLLoaderFactory* GetNetworkServiceURLLoaderFactory(
       const DataReductionProxyServer& proxy_server);
 
   // Count of fetch attempts that have been made to the proxy which is being
   // probed.
   size_t previous_attempt_counts_;
 
-  scoped_refptr<network::SharedURLLoaderFactory>
-      non_network_service_url_loader_factory_;
   CreateCustomProxyConfigCallback create_custom_proxy_config_callback_;
   network::mojom::URLLoaderFactoryPtr url_loader_factory_;
   network::mojom::NetworkContextPtr context_;
diff --git a/components/data_reduction_proxy/core/browser/warmup_url_fetcher_unittest.cc b/components/data_reduction_proxy/core/browser/warmup_url_fetcher_unittest.cc
index 5b1d460..a1a7a0e 100644
--- a/components/data_reduction_proxy/core/browser/warmup_url_fetcher_unittest.cc
+++ b/components/data_reduction_proxy/core/browser/warmup_url_fetcher_unittest.cc
@@ -38,10 +38,8 @@
 
 class WarmupURLFetcherTest : public WarmupURLFetcher {
  public:
-  WarmupURLFetcherTest(
-      scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory)
+  WarmupURLFetcherTest(network::mojom::URLLoaderFactory* url_loader_factory)
       : WarmupURLFetcher(
-            std::move(url_loader_factory),
             base::BindRepeating(
                 [](const std::vector<DataReductionProxyServer>&) {
                   return network::mojom::CustomProxyConfig::New();
@@ -52,7 +50,8 @@
             base::BindRepeating(&WarmupURLFetcherTest::GetHttpRttEstimate,
                                 base::Unretained(this)),
             base::ThreadTaskRunnerHandle::Get(),
-            std::string() /*user_agent*/) {}
+            std::string() /*user_agent*/),
+        url_loader_factory_(url_loader_factory) {}
   ~WarmupURLFetcherTest() override {}
 
   size_t callback_received_count() const { return callback_received_count_; }
@@ -98,6 +97,11 @@
     http_rtt_override_ = http_rtt;
   }
 
+  network::mojom::URLLoaderFactory* GetNetworkServiceURLLoaderFactory(
+      const DataReductionProxyServer& proxy_server) override {
+    return url_loader_factory_;
+  }
+
  private:
   base::Optional<base::TimeDelta> GetHttpRttEstimate() const {
     if (http_rtt_override_)
@@ -117,6 +121,7 @@
   FetchResult success_response_last_ = FetchResult::kFailed;
   base::Optional<base::TimeDelta> fetch_timeout_;
   base::Optional<base::TimeDelta> http_rtt_override_;
+  network::mojom::URLLoaderFactory* url_loader_factory_;
   DISALLOW_COPY_AND_ASSIGN(WarmupURLFetcherTest);
 };
 
@@ -124,11 +129,7 @@
 TEST(WarmupURLFetcherTest, TestGetWarmupURLWithQueryParam) {
   base::test::ScopedTaskEnvironment scoped_task_environment;
   network::TestURLLoaderFactory test_url_loader_factory;
-  auto test_shared_url_loader_factory =
-      base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
-          &test_url_loader_factory);
-
-  WarmupURLFetcherTest warmup_url_fetcher(test_shared_url_loader_factory);
+  WarmupURLFetcherTest warmup_url_fetcher(&test_url_loader_factory);
 
   GURL gurl_original;
   warmup_url_fetcher.GetWarmupURLWithQueryParam(&gurl_original);
@@ -159,14 +160,11 @@
 TEST(WarmupURLFetcherTest, TestSuccessfulFetchWarmupURLNoViaHeader) {
   base::test::ScopedTaskEnvironment scoped_task_environment;
   network::TestURLLoaderFactory test_url_loader_factory;
-  auto test_shared_url_loader_factory =
-      base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
-          &test_url_loader_factory);
 
   base::HistogramTester histogram_tester;
 
   auto proxy_server = net::ProxyServer::Direct();
-  WarmupURLFetcherTest warmup_url_fetcher(test_shared_url_loader_factory);
+  WarmupURLFetcherTest warmup_url_fetcher(&test_url_loader_factory);
   EXPECT_FALSE(warmup_url_fetcher.IsFetchInFlight());
   warmup_url_fetcher.FetchWarmupURL(0, DataReductionProxyServer(proxy_server));
   EXPECT_TRUE(warmup_url_fetcher.IsFetchInFlight());
@@ -208,14 +206,11 @@
 TEST(WarmupURLFetcherTest, TestSuccessfulFetchWarmupURLWithViaHeader) {
   base::test::ScopedTaskEnvironment scoped_task_environment;
   network::TestURLLoaderFactory test_url_loader_factory;
-  auto test_shared_url_loader_factory =
-      base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
-          &test_url_loader_factory);
 
   base::HistogramTester histogram_tester;
 
   auto proxy_server = net::ProxyServer::Direct();
-  WarmupURLFetcherTest warmup_url_fetcher(test_shared_url_loader_factory);
+  WarmupURLFetcherTest warmup_url_fetcher(&test_url_loader_factory);
   EXPECT_FALSE(warmup_url_fetcher.IsFetchInFlight());
   warmup_url_fetcher.FetchWarmupURL(0, DataReductionProxyServer(proxy_server));
   EXPECT_TRUE(warmup_url_fetcher.IsFetchInFlight());
@@ -263,14 +258,11 @@
      TestSuccessfulFetchWarmupURLWithViaHeaderExperimentNotEnabled) {
   base::test::ScopedTaskEnvironment scoped_task_environment;
   network::TestURLLoaderFactory test_url_loader_factory;
-  auto test_shared_url_loader_factory =
-      base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
-          &test_url_loader_factory);
 
   base::HistogramTester histogram_tester;
 
   auto proxy_server = net::ProxyServer::Direct();
-  WarmupURLFetcherTest warmup_url_fetcher(test_shared_url_loader_factory);
+  WarmupURLFetcherTest warmup_url_fetcher(&test_url_loader_factory);
   warmup_url_fetcher.FetchWarmupURL(0, DataReductionProxyServer(proxy_server));
   base::RunLoop().RunUntilIdle();
 
@@ -306,13 +298,10 @@
 TEST(WarmupURLFetcherTest, TestConnectionResetFetchWarmupURL) {
   base::test::ScopedTaskEnvironment scoped_task_environment;
   network::TestURLLoaderFactory test_url_loader_factory;
-  auto test_shared_url_loader_factory =
-      base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
-          &test_url_loader_factory);
 
   base::HistogramTester histogram_tester;
 
-  WarmupURLFetcherTest warmup_url_fetcher(test_shared_url_loader_factory);
+  WarmupURLFetcherTest warmup_url_fetcher(&test_url_loader_factory);
   EXPECT_FALSE(warmup_url_fetcher.IsFetchInFlight());
   warmup_url_fetcher.FetchWarmupURL(
       0, DataReductionProxyServer(net::ProxyServer::Direct()));
@@ -351,13 +340,10 @@
 TEST(WarmupURLFetcherTest, TestFetchTimesout) {
   base::test::ScopedTaskEnvironment scoped_task_environment;
   network::TestURLLoaderFactory test_url_loader_factory;
-  auto test_shared_url_loader_factory =
-      base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
-          &test_url_loader_factory);
 
   base::HistogramTester histogram_tester;
 
-  WarmupURLFetcherTest warmup_url_fetcher(test_shared_url_loader_factory);
+  WarmupURLFetcherTest warmup_url_fetcher(&test_url_loader_factory);
   // Set the timeout to a very low value. This should cause warmup URL fetcher
   // to run the callback with appropriate error code.
   warmup_url_fetcher.SetFetchTimeout(base::TimeDelta::FromSeconds(0));
@@ -390,14 +376,11 @@
   base::test::ScopedTaskEnvironment scoped_task_environment(
       base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME);
   network::TestURLLoaderFactory test_url_loader_factory;
-  auto test_shared_url_loader_factory =
-      base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
-          &test_url_loader_factory);
 
   base::HistogramTester histogram_tester;
 
   auto proxy_server = net::ProxyServer::Direct();
-  WarmupURLFetcherTest warmup_url_fetcher(test_shared_url_loader_factory);
+  WarmupURLFetcherTest warmup_url_fetcher(&test_url_loader_factory);
   EXPECT_FALSE(warmup_url_fetcher.IsFetchInFlight());
   warmup_url_fetcher.SetFetchWaitTime(base::TimeDelta::FromMilliseconds(1));
   warmup_url_fetcher.FetchWarmupURL(1, DataReductionProxyServer(proxy_server));
@@ -450,12 +433,9 @@
 
   base::test::ScopedTaskEnvironment scoped_task_environment;
   network::TestURLLoaderFactory test_url_loader_factory;
-  auto test_shared_url_loader_factory =
-      base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
-          &test_url_loader_factory);
 
   DataReductionProxyServer proxy_server(net::ProxyServer::Direct());
-  WarmupURLFetcherTest warmup_url_fetcher(test_shared_url_loader_factory);
+  WarmupURLFetcherTest warmup_url_fetcher(&test_url_loader_factory);
   EXPECT_FALSE(warmup_url_fetcher.IsFetchInFlight());
 
   EXPECT_EQ(kMinTimeout, warmup_url_fetcher.GetFetchTimeout());
@@ -483,12 +463,9 @@
 
   base::test::ScopedTaskEnvironment scoped_task_environment;
   network::TestURLLoaderFactory test_url_loader_factory;
-  auto test_shared_url_loader_factory =
-      base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
-          &test_url_loader_factory);
 
   DataReductionProxyServer proxy_server(net::ProxyServer::Direct());
-  WarmupURLFetcherTest warmup_url_fetcher(test_shared_url_loader_factory);
+  WarmupURLFetcherTest warmup_url_fetcher(&test_url_loader_factory);
   EXPECT_FALSE(warmup_url_fetcher.IsFetchInFlight());
 
   warmup_url_fetcher.FetchWarmupURL(1, proxy_server);
diff --git a/components/data_reduction_proxy/core/common/data_reduction_proxy_features.cc b/components/data_reduction_proxy/core/common/data_reduction_proxy_features.cc
index 04781d8..4946a8c 100644
--- a/components/data_reduction_proxy/core/common/data_reduction_proxy_features.cc
+++ b/components/data_reduction_proxy/core/common/data_reduction_proxy_features.cc
@@ -40,11 +40,7 @@
 // Enables data reduction proxy when network service is enabled.
 const base::Feature kDataReductionProxyEnabledWithNetworkService{
   "DataReductionProxyEnabledWithNetworkService",
-#if defined(OS_ANDROID)
       base::FEATURE_ENABLED_BY_DEFAULT
-#else
-      base::FEATURE_DISABLED_BY_DEFAULT
-#endif
 };
 
 // Enables block action of all proxies when 502 is received with no
diff --git a/components/download/internal/common/download_item_impl.cc b/components/download/internal/common/download_item_impl.cc
index cfb832a..4d20fcc 100644
--- a/components/download/internal/common/download_item_impl.cc
+++ b/components/download/internal/common/download_item_impl.cc
@@ -997,8 +997,7 @@
   // they aren't owned by the download system.
   const bool is_complete = GetState() == DownloadItem::COMPLETE;
   return (!IsDone() || is_complete) && !IsTemporary() &&
-         !file_externally_removed_ &&
-         delegate_->IsMostRecentDownloadItemAtFilePath(this);
+         !file_externally_removed_;
 }
 
 bool DownloadItemImpl::ShouldOpenFileBasedOnExtension() {
diff --git a/components/language/core/common/language_experiments.cc b/components/language/core/common/language_experiments.cc
index e7cec35..df4c1f7 100644
--- a/components/language/core/common/language_experiments.cc
+++ b/components/language/core/common/language_experiments.cc
@@ -24,7 +24,7 @@
 const base::Feature kUseFluentLanguageModel{"UseFluentLanguageModel",
                                             base::FEATURE_DISABLED_BY_DEFAULT};
 const base::Feature kNotifySyncOnLanguageDetermined{
-    "NotifySyncOnLanguageDetermined", base::FEATURE_DISABLED_BY_DEFAULT};
+    "NotifySyncOnLanguageDetermined", base::FEATURE_ENABLED_BY_DEFAULT};
 
 // Base feature for Translate desktop UI experiment
 const base::Feature kUseButtonTranslateBubbleUi{
diff --git a/components/omnibox/browser/BUILD.gn b/components/omnibox/browser/BUILD.gn
index ce2b6d6..c05a311 100644
--- a/components/omnibox/browser/BUILD.gn
+++ b/components/omnibox/browser/BUILD.gn
@@ -105,8 +105,6 @@
     "builtin_provider.h",
     "clipboard_provider.cc",
     "clipboard_provider.h",
-    "contextual_suggestions_service.cc",
-    "contextual_suggestions_service.h",
     "document_provider.cc",
     "document_provider.h",
     "document_suggestions_service.cc",
@@ -172,6 +170,8 @@
     "on_device_head_provider.h",
     "on_device_head_serving.cc",
     "on_device_head_serving.h",
+    "remote_suggestions_service.cc",
+    "remote_suggestions_service.h",
     "scored_history_match.cc",
     "scored_history_match.h",
     "search_provider.cc",
@@ -384,7 +384,6 @@
     "bookmark_provider_unittest.cc",
     "builtin_provider_unittest.cc",
     "clipboard_provider_unittest.cc",
-    "contextual_suggestions_service_unittest.cc",
     "document_provider_unittest.cc",
     "favicon_cache_unittest.cc",
     "history_provider_unittest.cc",
@@ -404,6 +403,7 @@
     "omnibox_view_unittest.cc",
     "on_device_head_provider_unittest.cc",
     "on_device_head_serving_unittest.cc",
+    "remote_suggestions_service_unittest.cc",
     "scored_history_match_unittest.cc",
     "search_suggestion_parser_unittest.cc",
     "shortcuts_backend_unittest.cc",
diff --git a/components/omnibox/browser/autocomplete_provider_client.h b/components/omnibox/browser/autocomplete_provider_client.h
index d340d55..af00181b 100644
--- a/components/omnibox/browser/autocomplete_provider_client.h
+++ b/components/omnibox/browser/autocomplete_provider_client.h
@@ -21,7 +21,7 @@
 struct AutocompleteMatch;
 class AutocompleteClassifier;
 class AutocompleteSchemeClassifier;
-class ContextualSuggestionsService;
+class RemoteSuggestionsService;
 class DocumentSuggestionsService;
 class GURL;
 class InMemoryURLIndex;
@@ -61,7 +61,7 @@
   virtual InMemoryURLIndex* GetInMemoryURLIndex() = 0;
   virtual TemplateURLService* GetTemplateURLService() = 0;
   virtual const TemplateURLService* GetTemplateURLService() const = 0;
-  virtual ContextualSuggestionsService* GetContextualSuggestionsService(
+  virtual RemoteSuggestionsService* GetRemoteSuggestionsService(
       bool create_if_necessary) const = 0;
   virtual DocumentSuggestionsService* GetDocumentSuggestionsService(
       bool create_if_necessary) const = 0;
diff --git a/components/omnibox/browser/mock_autocomplete_provider_client.cc b/components/omnibox/browser/mock_autocomplete_provider_client.cc
index 4333cc8..19d816d8 100644
--- a/components/omnibox/browser/mock_autocomplete_provider_client.cc
+++ b/components/omnibox/browser/mock_autocomplete_provider_client.cc
@@ -11,9 +11,8 @@
       base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
           &test_url_loader_factory_);
 
-  contextual_suggestions_service_ =
-      std::make_unique<ContextualSuggestionsService>(
-          /*identity_manager=*/nullptr, GetURLLoaderFactory());
+  remote_suggestions_service_ = std::make_unique<RemoteSuggestionsService>(
+      /*identity_manager=*/nullptr, GetURLLoaderFactory());
   document_suggestions_service_ = std::make_unique<DocumentSuggestionsService>(
       /*identity_manager=*/nullptr, GetURLLoaderFactory());
   pedal_provider_ = std::make_unique<OmniboxPedalProvider>(*this);
diff --git a/components/omnibox/browser/mock_autocomplete_provider_client.h b/components/omnibox/browser/mock_autocomplete_provider_client.h
index f182c9a..970fd1b 100644
--- a/components/omnibox/browser/mock_autocomplete_provider_client.h
+++ b/components/omnibox/browser/mock_autocomplete_provider_client.h
@@ -13,9 +13,9 @@
 #include "base/macros.h"
 #include "components/omnibox/browser/autocomplete_provider_client.h"
 #include "components/omnibox/browser/autocomplete_scheme_classifier.h"
-#include "components/omnibox/browser/contextual_suggestions_service.h"
 #include "components/omnibox/browser/document_suggestions_service.h"
 #include "components/omnibox/browser/omnibox_pedal_provider.h"
+#include "components/omnibox/browser/remote_suggestions_service.h"
 #include "components/search_engines/template_url_service.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 #include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
@@ -53,9 +53,9 @@
   const TemplateURLService* GetTemplateURLService() const override {
     return template_url_service_.get();
   }
-  ContextualSuggestionsService* GetContextualSuggestionsService(
+  RemoteSuggestionsService* GetRemoteSuggestionsService(
       bool create_if_necessary) const override {
-    return contextual_suggestions_service_.get();
+    return remote_suggestions_service_.get();
   }
   DocumentSuggestionsService* GetDocumentSuggestionsService(
       bool create_if_necessary) const override {
@@ -125,7 +125,7 @@
   network::TestURLLoaderFactory test_url_loader_factory_;
   scoped_refptr<network::SharedURLLoaderFactory> shared_factory_;
 
-  std::unique_ptr<ContextualSuggestionsService> contextual_suggestions_service_;
+  std::unique_ptr<RemoteSuggestionsService> remote_suggestions_service_;
   std::unique_ptr<DocumentSuggestionsService> document_suggestions_service_;
   std::unique_ptr<OmniboxPedalProvider> pedal_provider_;
   std::unique_ptr<TemplateURLService> template_url_service_;
diff --git a/components/omnibox/browser/contextual_suggestions_service.cc b/components/omnibox/browser/remote_suggestions_service.cc
similarity index 91%
rename from components/omnibox/browser/contextual_suggestions_service.cc
rename to components/omnibox/browser/remote_suggestions_service.cc
index a07b839..46324b2 100644
--- a/components/omnibox/browser/contextual_suggestions_service.cc
+++ b/components/omnibox/browser/remote_suggestions_service.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/omnibox/browser/contextual_suggestions_service.h"
+#include "components/omnibox/browser/remote_suggestions_service.h"
 
 #include <memory>
 #include <utility>
@@ -11,6 +11,7 @@
 #include "base/feature_list.h"
 #include "base/json/json_writer.h"
 #include "base/metrics/field_trial_params.h"
+#include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
 #include "base/values.h"
 #include "components/omnibox/browser/base_search_provider.h"
@@ -35,7 +36,7 @@
   // Add Chrome experiment state to the request headers.
   //
   // Note: It's OK to pass InIncognito::kNo since we are expected to be in
-  // non-incognito state here (i.e. contextual sugestions are not served in
+  // non-incognito state here (i.e. remote sugestions are not served in
   // incognito mode).
   variations::AppendVariationsHeaderUnknownSignedIn(
       request->url, variations::InIncognito::kNo, request);
@@ -68,7 +69,8 @@
   url_entry->SetString("url", current_url);
   url_entry->SetString(
       "timestamp_usec",
-      std::to_string((visit_time - base::Time::UnixEpoch()).InMicroseconds()));
+      base::NumberToString(
+          (visit_time - base::Time::UnixEpoch()).InMicroseconds()));
   url_list->Append(std::move(url_entry));
   request->Set("urls", std::move(url_list));
   // stream_type = 1 corresponds to zero suggest suggestions.
@@ -84,7 +86,7 @@
 
 }  // namespace
 
-ContextualSuggestionsService::ContextualSuggestionsService(
+RemoteSuggestionsService::RemoteSuggestionsService(
     identity::IdentityManager* identity_manager,
     scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory)
     : url_loader_factory_(url_loader_factory),
@@ -93,9 +95,9 @@
   DCHECK(url_loader_factory);
 }
 
-ContextualSuggestionsService::~ContextualSuggestionsService() {}
+RemoteSuggestionsService::~RemoteSuggestionsService() {}
 
-void ContextualSuggestionsService::CreateContextualSuggestionsRequest(
+void RemoteSuggestionsService::CreateSuggestionsRequest(
     const std::string& current_url,
     const base::Time& visit_time,
     const AutocompleteInput& input,
@@ -103,7 +105,7 @@
     StartCallback start_callback,
     CompletionCallback completion_callback) {
   const GURL experimental_suggest_url =
-      ExperimentalContextualSuggestionsUrl(current_url, template_url_service);
+      ExperimentalEndpointUrl(current_url, template_url_service);
   if (experimental_suggest_url.is_valid())
     CreateExperimentalRequest(current_url, visit_time, experimental_suggest_url,
                               std::move(start_callback),
@@ -114,13 +116,13 @@
                          std::move(completion_callback));
 }
 
-void ContextualSuggestionsService::StopCreatingContextualSuggestionsRequest() {
+void RemoteSuggestionsService::StopCreatingSuggestionsRequest() {
   std::unique_ptr<identity::PrimaryAccountAccessTokenFetcher>
       token_fetcher_deleter(std::move(token_fetcher_));
 }
 
 // static
-GURL ContextualSuggestionsService::ContextualSuggestionsUrl(
+GURL RemoteSuggestionsService::EndpointUrl(
     const std::string& current_url,
     const AutocompleteInput& input,
     const TemplateURLService* template_url_service) {
@@ -154,7 +156,7 @@
                                                     search_terms_data));
 }
 
-GURL ContextualSuggestionsService::ExperimentalContextualSuggestionsUrl(
+GURL RemoteSuggestionsService::ExperimentalEndpointUrl(
     const std::string& current_url,
     const TemplateURLService* template_url_service) const {
   if (current_url.empty() || template_url_service == nullptr) {
@@ -192,14 +194,14 @@
   return suggest_url;
 }
 
-void ContextualSuggestionsService::CreateDefaultRequest(
+void RemoteSuggestionsService::CreateDefaultRequest(
     const std::string& current_url,
     const AutocompleteInput& input,
     const TemplateURLService* template_url_service,
     StartCallback start_callback,
     CompletionCallback completion_callback) {
   const GURL suggest_url =
-      ContextualSuggestionsUrl(current_url, input, template_url_service);
+      EndpointUrl(current_url, input, template_url_service);
   DCHECK(suggest_url.is_valid());
 
   net::NetworkTrafficAnnotationTag traffic_annotation =
@@ -244,7 +246,7 @@
                                  std::move(completion_callback));
 }
 
-void ContextualSuggestionsService::CreateExperimentalRequest(
+void RemoteSuggestionsService::CreateExperimentalRequest(
     const std::string& current_url,
     const base::Time& visit_time,
     const GURL& suggest_url,
@@ -294,7 +296,7 @@
   request->allow_credentials = false;
 
   // If authentication services are unavailable or if this request is still
-  // waiting for an oauth2 token, run the contextual service without access
+  // waiting for an oauth2 token, run the remote service without access
   // tokens.
   if ((identity_manager_ == nullptr) || (token_fetcher_ != nullptr)) {
     StartDownloadAndTransferLoader(
@@ -307,15 +309,15 @@
   const identity::ScopeSet scopes{
       "https://www.googleapis.com/auth/cusco-chrome-extension"};
   token_fetcher_ = std::make_unique<identity::PrimaryAccountAccessTokenFetcher>(
-      "contextual_suggestions_service", identity_manager_, scopes,
-      base::BindOnce(&ContextualSuggestionsService::AccessTokenAvailable,
+      "remote_suggestions_service", identity_manager_, scopes,
+      base::BindOnce(&RemoteSuggestionsService::AccessTokenAvailable,
                      base::Unretained(this), std::move(request),
                      std::move(request_body), traffic_annotation,
                      std::move(start_callback), std::move(completion_callback)),
       identity::PrimaryAccountAccessTokenFetcher::Mode::kWaitUntilAvailable);
 }
 
-void ContextualSuggestionsService::AccessTokenAvailable(
+void RemoteSuggestionsService::AccessTokenAvailable(
     std::unique_ptr<network::ResourceRequest> request,
     std::string request_body,
     net::NetworkTrafficAnnotationTag traffic_annotation,
@@ -340,7 +342,7 @@
                                  std::move(completion_callback));
 }
 
-void ContextualSuggestionsService::StartDownloadAndTransferLoader(
+void RemoteSuggestionsService::StartDownloadAndTransferLoader(
     std::unique_ptr<network::ResourceRequest> request,
     std::string request_body,
     net::NetworkTrafficAnnotationTag traffic_annotation,
diff --git a/components/omnibox/browser/contextual_suggestions_service.h b/components/omnibox/browser/remote_suggestions_service.h
similarity index 84%
rename from components/omnibox/browser/contextual_suggestions_service.h
rename to components/omnibox/browser/remote_suggestions_service.h
index eaab5ee..e669a426 100644
--- a/components/omnibox/browser/contextual_suggestions_service.h
+++ b/components/omnibox/browser/remote_suggestions_service.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_OMNIBOX_BROWSER_CONTEXTUAL_SUGGESTIONS_SERVICE_H_
-#define COMPONENTS_OMNIBOX_BROWSER_CONTEXTUAL_SUGGESTIONS_SERVICE_H_
+#ifndef COMPONENTS_OMNIBOX_BROWSER_REMOTE_SUGGESTIONS_SERVICE_H_
+#define COMPONENTS_OMNIBOX_BROWSER_REMOTE_SUGGESTIONS_SERVICE_H_
 
 #include <memory>
 #include <string>
@@ -38,18 +38,15 @@
 // This service is always sent the user's authentication state, so the
 // suggestions always can be personalized. This service is also sometimes sent
 // the user's current URL, so the suggestions are sometimes also contextual.
-//
-// TODO(tommycli): Probably we should just rename this RemoteSuggestionsService,
-// as the suggestions are not always contextual.
-class ContextualSuggestionsService : public KeyedService {
+class RemoteSuggestionsService : public KeyedService {
  public:
   // |identity_manager| may be null but only unauthenticated requests will
   // issued.
-  ContextualSuggestionsService(
+  RemoteSuggestionsService(
       identity::IdentityManager* identity_manager,
       scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory);
 
-  ~ContextualSuggestionsService() override;
+  ~RemoteSuggestionsService() override;
 
   using StartCallback = base::OnceCallback<void(
       std::unique_ptr<network::SimpleURLLoader> loader)>;
@@ -58,7 +55,7 @@
       base::OnceCallback<void(const network::SimpleURLLoader* source,
                               std::unique_ptr<std::string> response_body)>;
 
-  // Creates a loader for contextual suggestions for |current_url| and passes
+  // Creates a loader for remote suggestions for |current_url| and passes
   // the loader to |start_callback|. It uses a number of signals to create the
   // loader, including field trial / experimental parameters, and it may
   // pass a nullptr to |start_callback| (see below for details).
@@ -85,16 +82,15 @@
   //
   // This method sends a request for an OAuth2 token and temporarily
   // instantiates |token_fetcher_|.
-  void CreateContextualSuggestionsRequest(
-      const std::string& current_url,
-      const base::Time& visit_time,
-      const AutocompleteInput& input,
-      const TemplateURLService* template_url_service,
-      StartCallback start_callback,
-      CompletionCallback completion_callback);
+  void CreateSuggestionsRequest(const std::string& current_url,
+                                const base::Time& visit_time,
+                                const AutocompleteInput& input,
+                                const TemplateURLService* template_url_service,
+                                StartCallback start_callback,
+                                CompletionCallback completion_callback);
 
   // Advises the service to stop any process that creates a suggestion request.
-  void StopCreatingContextualSuggestionsRequest();
+  void StopCreatingSuggestionsRequest();
 
   // Returns a URL representing the address of the server where the zero suggest
   // request is being sent. Does not take into account whether sending this
@@ -109,10 +105,9 @@
   //
   // Note that this method is public and is also used by ZeroSuggestProvider for
   // suggestions that do not take |current_url| into consideration.
-  static GURL ContextualSuggestionsUrl(
-      const std::string& current_url,
-      const AutocompleteInput& input,
-      const TemplateURLService* template_url_service);
+  static GURL EndpointUrl(const std::string& current_url,
+                          const AutocompleteInput& input,
+                          const TemplateURLService* template_url_service);
 
  private:
   // Returns a URL representing the address of the server where the zero suggest
@@ -127,16 +122,16 @@
   // * The suggest request is over HTTPS. This avoids leaking the current page
   //   URL or personal data in unencrypted network traffic.
   // Note: these checks are in addition to CanSendUrl() on the default
-  // contextual suggestion URL.
-  GURL ExperimentalContextualSuggestionsUrl(
+  // remote suggestion URL.
+  GURL ExperimentalEndpointUrl(
       const std::string& current_url,
       const TemplateURLService* template_url_service) const;
 
-  // Upon succesful creation of an HTTP GET request for default contextual
+  // Upon succesful creation of an HTTP GET request for default remote
   // suggestions, the |callback| function is run with the HTTP GET request as a
   // parameter.
   //
-  // This function is called by CreateContextualSuggestionsRequest. See its
+  // This function is called by CreateSuggestionsRequest. See its
   // function definition for details on the parameters.
   void CreateDefaultRequest(const std::string& current_url,
                             const AutocompleteInput& input,
@@ -144,11 +139,11 @@
                             StartCallback start_callback,
                             CompletionCallback completion_callback);
 
-  // Upon succesful creation of an HTTP POST request for experimental contextual
+  // Upon succesful creation of an HTTP POST request for experimental remote
   // suggestions, the |callback| function is run with the HTTP POST request as a
   // parameter.
   //
-  // This function is called by CreateContextualSuggestionsRequest. See its
+  // This function is called by CreateSuggestionsRequest. See its
   // function definition for details on the parameters.
   void CreateExperimentalRequest(const std::string& current_url,
                                  const base::Time& visit_time,
@@ -168,7 +163,7 @@
   // request to load the suggestions.
   //
   // |start_callback|, |completion_callback| are the same as passed to
-  // CreateContextualSuggestionsRequest()
+  // CreateSuggestionsRequest()
   //
   // |error| and |access_token| are the results of token request.
   void AccessTokenAvailable(std::unique_ptr<network::ResourceRequest> request,
@@ -196,7 +191,7 @@
   // token request is currently in progress.
   std::unique_ptr<identity::PrimaryAccountAccessTokenFetcher> token_fetcher_;
 
-  DISALLOW_COPY_AND_ASSIGN(ContextualSuggestionsService);
+  DISALLOW_COPY_AND_ASSIGN(RemoteSuggestionsService);
 };
 
-#endif  // COMPONENTS_OMNIBOX_BROWSER_CONTEXTUAL_SUGGESTIONS_SERVICE_H_
+#endif  // COMPONENTS_OMNIBOX_BROWSER_REMOTE_SUGGESTIONS_SERVICE_H_
diff --git a/components/omnibox/browser/contextual_suggestions_service_unittest.cc b/components/omnibox/browser/remote_suggestions_service_unittest.cc
similarity index 82%
rename from components/omnibox/browser/contextual_suggestions_service_unittest.cc
rename to components/omnibox/browser/remote_suggestions_service_unittest.cc
index a7fd19c..ecc6e33 100644
--- a/components/omnibox/browser/contextual_suggestions_service_unittest.cc
+++ b/components/omnibox/browser/remote_suggestions_service_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/omnibox/browser/contextual_suggestions_service.h"
+#include "components/omnibox/browser/remote_suggestions_service.h"
 
 #include <memory>
 #include <string>
@@ -22,9 +22,9 @@
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-class ContextualSuggestionsServiceTest : public testing::Test {
+class RemoteSuggestionsServiceTest : public testing::Test {
  public:
-  ContextualSuggestionsServiceTest()
+  RemoteSuggestionsServiceTest()
       : mock_task_runner_(new base::TestMockTimeTaskRunner(
             base::TestMockTimeTaskRunner::Type::kBoundToThread)) {}
 
@@ -45,23 +45,23 @@
   network::TestURLLoaderFactory test_url_loader_factory_;
 };
 
-TEST_F(ContextualSuggestionsServiceTest, EnsureAttachCookies) {
+TEST_F(RemoteSuggestionsServiceTest, EnsureAttachCookies) {
   network::ResourceRequest resource_request;
   test_url_loader_factory_.SetInterceptor(
       base::BindLambdaForTesting([&](const network::ResourceRequest& request) {
         resource_request = request;
       }));
 
-  ContextualSuggestionsService service(nullptr /* identity_manager */,
-                                       GetUrlLoaderFactory());
+  RemoteSuggestionsService service(nullptr /* identity_manager */,
+                                   GetUrlLoaderFactory());
   AutocompleteInput input;
   base::Time visit_time;
   TemplateURLService template_url_service(nullptr, 0);
-  service.CreateContextualSuggestionsRequest(
+  service.CreateSuggestionsRequest(
       "https://www.google.com/", visit_time, input, &template_url_service,
-      base::BindOnce(&ContextualSuggestionsServiceTest::OnRequestStart,
+      base::BindOnce(&RemoteSuggestionsServiceTest::OnRequestStart,
                      base::Unretained(this)),
-      base::BindOnce(&ContextualSuggestionsServiceTest::OnRequestComplete,
+      base::BindOnce(&RemoteSuggestionsServiceTest::OnRequestComplete,
                      base::Unretained(this)));
 
   RunAndWait();
diff --git a/components/omnibox/browser/zero_suggest_provider.cc b/components/omnibox/browser/zero_suggest_provider.cc
index 0a339cf..8f6468ef6 100644
--- a/components/omnibox/browser/zero_suggest_provider.cc
+++ b/components/omnibox/browser/zero_suggest_provider.cc
@@ -28,9 +28,9 @@
 #include "components/omnibox/browser/autocomplete_match.h"
 #include "components/omnibox/browser/autocomplete_match_classification.h"
 #include "components/omnibox/browser/autocomplete_provider_listener.h"
-#include "components/omnibox/browser/contextual_suggestions_service.h"
 #include "components/omnibox/browser/history_url_provider.h"
 #include "components/omnibox/browser/omnibox_pref_names.h"
+#include "components/omnibox/browser/remote_suggestions_service.h"
 #include "components/omnibox/browser/search_provider.h"
 #include "components/omnibox/browser/verbatim_match.h"
 #include "components/omnibox/common/omnibox_features.h"
@@ -154,7 +154,7 @@
   current_page_classification_ = input.current_page_classification();
   current_url_match_ = MatchForCurrentURL();
 
-  GURL suggest_url = ContextualSuggestionsService::ContextualSuggestionsUrl(
+  GURL suggest_url = RemoteSuggestionsService::EndpointUrl(
       /*current_url=*/"", input, client()->GetTemplateURLService());
   if (!suggest_url.is_valid())
     return;
@@ -185,14 +185,14 @@
   const std::string current_url =
       result_type_running_ == REMOTE_SEND_URL ? current_query_ : std::string();
   // Create a request for suggestions, routing completion to
-  // OnContextualSuggestionsLoaderAvailable.
+  // OnRemoteSuggestionsLoaderAvailable.
   client()
-      ->GetContextualSuggestionsService(/*create_if_necessary=*/true)
-      ->CreateContextualSuggestionsRequest(
+      ->GetRemoteSuggestionsService(/*create_if_necessary=*/true)
+      ->CreateSuggestionsRequest(
           current_url, client()->GetCurrentVisitTimestamp(), input,
           client()->GetTemplateURLService(),
           base::BindOnce(
-              &ZeroSuggestProvider::OnContextualSuggestionsLoaderAvailable,
+              &ZeroSuggestProvider::OnRemoteSuggestionsLoaderAvailable,
               weak_ptr_factory_.GetWeakPtr()),
           base::BindOnce(
               &ZeroSuggestProvider::OnURLLoadComplete,
@@ -204,11 +204,11 @@
   if (loader_)
     LogOmniboxZeroSuggestRequest(ZERO_SUGGEST_REQUEST_INVALIDATED);
   loader_.reset();
-  auto* contextual_suggestions_service =
-      client()->GetContextualSuggestionsService(/*create_if_necessary=*/false);
-  // contextual_suggestions_service can be null if in incognito mode.
-  if (contextual_suggestions_service != nullptr) {
-    contextual_suggestions_service->StopCreatingContextualSuggestionsRequest();
+  auto* remote_suggestions_service =
+      client()->GetRemoteSuggestionsService(/*create_if_necessary=*/false);
+  // remote_suggestions_service can be null if in incognito mode.
+  if (remote_suggestions_service != nullptr) {
+    remote_suggestions_service->StopCreatingSuggestionsRequest();
   }
   // TODO(krb): It would allow us to remove some guards if we could also cancel
   // the TopSites::GetMostVisitedURLs request.
@@ -264,13 +264,13 @@
       listener_(listener),
       result_type_running_(NONE),
       weak_ptr_factory_(this) {
-  // Record whether contextual zero suggest is possible for this user / profile.
+  // Record whether remote zero suggest is possible for this user / profile.
   const TemplateURLService* template_url_service =
       client->GetTemplateURLService();
   // Template URL service can be null in tests.
   if (template_url_service != nullptr) {
     AutocompleteInput empty_input;
-    GURL suggest_url = ContextualSuggestionsService::ContextualSuggestionsUrl(
+    GURL suggest_url = RemoteSuggestionsService::EndpointUrl(
         /*current_url=*/"", /*empty input*/ empty_input, template_url_service);
     // To check whether this is allowed, use an arbitrary insecure (http) URL
     // as the URL we'd want suggestions for.  The value of OTHER as the current
@@ -423,9 +423,9 @@
   listener_->OnProviderUpdate(true);
 }
 
-void ZeroSuggestProvider::OnContextualSuggestionsLoaderAvailable(
+void ZeroSuggestProvider::OnRemoteSuggestionsLoaderAvailable(
     std::unique_ptr<network::SimpleURLLoader> loader) {
-  // ContextualSuggestionsService has already started |loader|, so here it's
+  // RemoteSuggestionsService has already started |loader|, so here it's
   // only neccessary to grab its ownership until results come in to
   // OnURLLoadComplete().
   loader_ = std::move(loader);
@@ -546,7 +546,7 @@
   // pages with URLs the user will recognize.
   //
   // This list intentionally does not include items such as ftp: and file:
-  // because (a) these do not work on Android and iOS, where non-contextual
+  // because (a) these do not work on Android and iOS, where most visited
   // zero suggest is launched and (b) on desktop, where contextual zero suggest
   // is running, these types of schemes aren't eligible to be sent to the
   // server to ask for suggestions (and thus in practice we won't display zero
diff --git a/components/omnibox/browser/zero_suggest_provider.h b/components/omnibox/browser/zero_suggest_provider.h
index 8574960..27f3544 100644
--- a/components/omnibox/browser/zero_suggest_provider.h
+++ b/components/omnibox/browser/zero_suggest_provider.h
@@ -142,11 +142,11 @@
   void OnMostVisitedUrlsAvailable(size_t request_num,
                                   const history::MostVisitedURLList& urls);
 
-  // When the user is in the contextual omnibox suggestions field trial, we ask
-  // the ContextualSuggestionsService for a loader to retrieve recommendations.
-  // When the loader has started, the contextual suggestion service then calls
+  // When the user is in the remote omnibox suggestions field trial, we ask
+  // the RemoteSuggestionsService for a loader to retrieve recommendations.
+  // When the loader has started, the remote suggestion service then calls
   // back to this function with the |loader| to pass its ownership to |this|.
-  void OnContextualSuggestionsLoaderAvailable(
+  void OnRemoteSuggestionsLoaderAvailable(
       std::unique_ptr<network::SimpleURLLoader> loader);
 
   // Whether zero suggest suggestions are allowed in the given context.
diff --git a/components/omnibox/browser/zero_suggest_provider_unittest.cc b/components/omnibox/browser/zero_suggest_provider_unittest.cc
index 94f2f39..644f083d 100644
--- a/components/omnibox/browser/zero_suggest_provider_unittest.cc
+++ b/components/omnibox/browser/zero_suggest_provider_unittest.cc
@@ -497,7 +497,7 @@
 
 TEST_F(ZeroSuggestProviderTest, CustomEndpoint) {
   // Coverage for the URL-specific page. (Regression test for a DCHECK).
-  // This is exercising ContextualSuggestionsService::CreateExperimentalRequest,
+  // This is exercising RemoteSuggestionsService::CreateExperimentalRequest,
   // and to do that, ZeroSuggestProvider needs to be looking for
   // DEFAULT_SERP_FOR_URL results (which needs various personalization
   // experiments off, IsPersonalizedUrlDataCollectionActive true), and the
diff --git a/components/test/components_test_suite.cc b/components/test/components_test_suite.cc
index 15d451e5..5206ea6c 100644
--- a/components/test/components_test_suite.cc
+++ b/components/test/components_test_suite.cc
@@ -143,11 +143,8 @@
 
 base::RunTestSuiteCallback GetLaunchCallback(int argc, char** argv) {
 #if !defined(OS_IOS)
-  // components_unittests don't currently work with the Network Service enabled.
-  // https://crbug.com/966633.
   auto test_suite = std::make_unique<content::UnitTestTestSuite>(
-      new ComponentsTestSuite(argc, argv),
-      network::features::kNetworkServiceFeatureName);
+      new ComponentsTestSuite(argc, argv));
 #else
   auto test_suite = std::make_unique<ComponentsTestSuite>(argc, argv);
 #endif
diff --git a/components/translate/content/browser/content_translate_driver.cc b/components/translate/content/browser/content_translate_driver.cc
index 60f54353..21ffaf3 100644
--- a/components/translate/content/browser/content_translate_driver.cc
+++ b/components/translate/content/browser/content_translate_driver.cc
@@ -9,6 +9,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/feature_list.h"
 #include "base/location.h"
 #include "base/logging.h"
 #include "base/single_thread_task_runner.h"
@@ -45,6 +46,12 @@
 // loading before giving up the translation
 const int kMaxTranslateLoadCheckAttempts = 20;
 
+// Overrides the hrefTranslate logic to auto-translate when the navigation is
+// from any origin rather than only Google origins. Used for manual testing
+// where the test page may reside on a test domain.
+const base::Feature kAutoHrefTranslateAllOrigins{
+    "AutoHrefTranslateAllOrigins", base::FEATURE_DISABLED_BY_DEFAULT};
+
 }  // namespace
 
 ContentTranslateDriver::ContentTranslateDriver(
@@ -262,9 +269,10 @@
 
   bool navigation_from_google =
       initiator_origin.has_value() &&
-      google_util::IsGoogleDomainUrl(initiator_origin->GetURL(),
-                                     google_util::DISALLOW_SUBDOMAIN,
-                                     google_util::ALLOW_NON_STANDARD_PORTS);
+      (google_util::IsGoogleDomainUrl(initiator_origin->GetURL(),
+                                      google_util::DISALLOW_SUBDOMAIN,
+                                      google_util::ALLOW_NON_STANDARD_PORTS) ||
+       base::FeatureList::IsEnabled(kAutoHrefTranslateAllOrigins));
 
   translate_manager_->GetLanguageState().DidNavigate(
       navigation_handle->IsSameDocument(), navigation_handle->IsInMainFrame(),
diff --git a/components/ui_devtools/views/BUILD.gn b/components/ui_devtools/views/BUILD.gn
index 99833f92..e364dad 100644
--- a/components/ui_devtools/views/BUILD.gn
+++ b/components/ui_devtools/views/BUILD.gn
@@ -15,6 +15,8 @@
     "devtools_server_util.h",
     "dom_agent_views.cc",
     "dom_agent_views.h",
+    "element_utility.cc",
+    "element_utility.h",
     "overlay_agent_views.cc",
     "overlay_agent_views.h",
     "view_element.cc",
diff --git a/components/ui_devtools/views/element_utility.cc b/components/ui_devtools/views/element_utility.cc
new file mode 100644
index 0000000..d61e5c5
--- /dev/null
+++ b/components/ui_devtools/views/element_utility.cc
@@ -0,0 +1,26 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/ui_devtools/views/element_utility.h"
+#include "ui/compositor/layer_owner.h"
+
+namespace ui_devtools {
+
+void AppendLayerProperties(
+    const ui::Layer* layer,
+    std::vector<std::pair<std::string, std::string>>* ret) {
+  ret->emplace_back("layer-type", LayerTypeToString(layer->type()));
+  ret->emplace_back("has-layer-mask",
+                    layer->layer_mask_layer() ? "true" : "false");
+  const cc::Layer* cc_layer = layer->cc_layer_for_testing();
+  if (cc_layer) {
+    cc::RenderSurfaceReason render_surface = cc_layer->GetRenderSurfaceReason();
+    if (render_surface != cc::RenderSurfaceReason::kNone) {
+      ret->emplace_back("render-surface-reason",
+                        cc::RenderSurfaceReasonToString(render_surface));
+    }
+  }
+}
+
+}  // namespace ui_devtools
diff --git a/components/ui_devtools/views/element_utility.h b/components/ui_devtools/views/element_utility.h
new file mode 100644
index 0000000..d6697d4
--- /dev/null
+++ b/components/ui_devtools/views/element_utility.h
@@ -0,0 +1,28 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_UI_DEVTOOLS_VIEWS_ELEMENT_UTILITY_H_
+#define COMPONENTS_UI_DEVTOOLS_VIEWS_ELEMENT_UTILITY_H_
+
+#include <string>
+#include <vector>
+
+namespace ui {
+class Layer;
+}
+
+namespace ui_devtools {
+
+// TODO(https://crbug.com/757283): Remove this file when LayerElement exists
+
+// Appends Layer properties to ret (ex: layer-type, layer-mask, etc).
+// This is used to display information about the layer on devtools.
+// Note that ret may not be empty when it's passed in.
+void AppendLayerProperties(
+    const ui::Layer* layer,
+    std::vector<std::pair<std::string, std::string>>* ret);
+
+}  // namespace ui_devtools
+
+#endif  // COMPONENTS_UI_DEVTOOLS_VIEWS_ELEMENT_UTILITY_H_
diff --git a/components/ui_devtools/views/view_element.cc b/components/ui_devtools/views/view_element.cc
index 764b52b..2133320 100644
--- a/components/ui_devtools/views/view_element.cc
+++ b/components/ui_devtools/views/view_element.cc
@@ -8,6 +8,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "components/ui_devtools/Protocol.h"
 #include "components/ui_devtools/ui_element_delegate.h"
+#include "components/ui_devtools/views/element_utility.h"
 #include "ui/views/widget/widget.h"
 
 namespace ui_devtools {
@@ -68,6 +69,13 @@
                      base::UTF16ToUTF8(member->GetValueAsString(view_)));
   }
 
+  ret.emplace_back("is-drawn", view_->IsDrawn() ? "true" : "false");
+  ui::Layer* layer = view_->layer();
+  if (layer) {
+    ret.emplace_back("layer", layer->name());
+    AppendLayerProperties(layer, &ret);
+  }
+
   base::string16 description = view_->GetTooltipText(gfx::Point());
   if (!description.empty())
     ret.emplace_back("tooltip", base::UTF16ToUTF8(description));
diff --git a/components/ui_devtools/views/window_element.cc b/components/ui_devtools/views/window_element.cc
index 0378b7629..eb8aa28 100644
--- a/components/ui_devtools/views/window_element.cc
+++ b/components/ui_devtools/views/window_element.cc
@@ -6,6 +6,7 @@
 
 #include "components/ui_devtools/Protocol.h"
 #include "components/ui_devtools/ui_element_delegate.h"
+#include "components/ui_devtools/views/element_utility.h"
 #include "ui/aura/window.h"
 #include "ui/wm/core/window_util.h"
 
@@ -67,7 +68,23 @@
 
 std::vector<std::pair<std::string, std::string>>
 WindowElement::GetCustomProperties() const {
-  return {};
+  std::vector<std::pair<std::string, std::string>> ret;
+
+  std::string state_str =
+      aura::Window::OcclusionStateToString(window_->occlusion_state());
+  // change OcclusionState::UNKNOWN to UNKNOWN
+  state_str = state_str.substr(state_str.find("::") + 2);
+  ret.emplace_back("occlusion-state", state_str);
+  ret.emplace_back("surface", window_->GetSurfaceId().is_valid()
+                                  ? window_->GetSurfaceId().ToString()
+                                  : "none");
+  ret.emplace_back("capture", window_->HasCapture() ? "true" : "false");
+  ret.emplace_back("is-activatable",
+                   wm::CanActivateWindow(window_) ? "true" : "false");
+  ui::Layer* layer = window_->layer();
+  if (layer)
+    AppendLayerProperties(layer, &ret);
+  return ret;
 }
 
 void WindowElement::GetBounds(gfx::Rect* bounds) const {
diff --git a/components/version_ui/resources/about_version.html b/components/version_ui/resources/about_version.html
index c44532d..3cab5c3e 100644
--- a/components/version_ui/resources/about_version.html
+++ b/components/version_ui/resources/about_version.html
@@ -147,6 +147,12 @@
           <td class="label">Sanitizer</td>
           <td class="version" id="sanitizer">$i18n{sanitizer}</td>
         </tr>
+<if expr="is_ios">
+        <tr id="compiler-section">
+          <td class="label">Compiler</td>
+          <td class="version" id="compiler">$i18n{compiler}</td>
+        </tr>
+</if>
       </table>
     </div>
   </body>
diff --git a/components/version_ui/version_ui_constants.cc b/components/version_ui/version_ui_constants.cc
index 28238dc0..6ad2a1e 100644
--- a/components/version_ui/version_ui_constants.cc
+++ b/components/version_ui/version_ui_constants.cc
@@ -26,6 +26,9 @@
 const char kCommandLine[] = "command_line";
 const char kCommandLineName[] = "command_line_name";
 const char kCompany[] = "company";
+#if defined(OS_IOS)
+const char kCompiler[] = "compiler";
+#endif
 #if defined(OS_WIN)
 const char kUpdateCohortName[] = "update_cohort_name";
 #endif
diff --git a/components/version_ui/version_ui_constants.h b/components/version_ui/version_ui_constants.h
index d87c2cd..ebc50865 100644
--- a/components/version_ui/version_ui_constants.h
+++ b/components/version_ui/version_ui_constants.h
@@ -32,6 +32,9 @@
 extern const char kCommandLine[];
 extern const char kCommandLineName[];
 extern const char kCompany[];
+#if defined(OS_IOS)
+extern const char kCompiler[];
+#endif
 #if defined(OS_WIN)
 extern const char kUpdateCohortName[];
 #endif
diff --git a/components/viz/demo/BUILD.gn b/components/viz/demo/BUILD.gn
index ad446765..55981f9 100644
--- a/components/viz/demo/BUILD.gn
+++ b/components/viz/demo/BUILD.gn
@@ -75,6 +75,7 @@
       "//ui/events/platform/x11",
       "//ui/platform_window/x11",
     ]
+    configs += [ "//build/config/linux:x11" ]
   }
 
   if (is_win) {
diff --git a/components/viz/service/BUILD.gn b/components/viz/service/BUILD.gn
index 39874b7..4c5137a 100644
--- a/components/viz/service/BUILD.gn
+++ b/components/viz/service/BUILD.gn
@@ -491,7 +491,8 @@
     # TODO(samans): Support more configurations.
     # CFI issue: https://crbug.com/967819
     # x86 issue: https://crbug.com/967831
-    if (use_x11 && target_cpu != "x86" && !is_cfi) {
+    # LSAN issue: https://crbug.com/971357
+    if (use_x11 && target_cpu != "x86" && !is_cfi && !is_lsan) {
       defines = [ "ENABLE_VIZ_VULKAN_TESTS" ]
     }
   }
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index e8b16453..e336736 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -2419,6 +2419,8 @@
       "frame_host/render_frame_host_android.h",
       "media/capture/screen_capture_device_android.cc",
       "media/capture/screen_capture_device_android.h",
+      "renderer_host/compositor_dependencies_android.cc",
+      "renderer_host/compositor_dependencies_android.h",
       "renderer_host/compositor_impl_android.cc",
       "renderer_host/compositor_impl_android.h",
       "renderer_host/delegated_frame_host_client_android.cc",
diff --git a/content/browser/compositor/surface_utils.cc b/content/browser/compositor/surface_utils.cc
index e7033f4b..6e928608 100644
--- a/content/browser/compositor/surface_utils.cc
+++ b/content/browser/compositor/surface_utils.cc
@@ -9,7 +9,7 @@
 #include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
 
 #if defined(OS_ANDROID)
-#include "content/browser/renderer_host/compositor_impl_android.h"
+#include "content/browser/renderer_host/compositor_dependencies_android.h"
 #else
 #include "content/browser/compositor/image_transport_factory.h"
 #include "ui/compositor/compositor.h"  // nogncheck
@@ -19,7 +19,7 @@
 
 viz::FrameSinkId AllocateFrameSinkId() {
 #if defined(OS_ANDROID)
-  return CompositorImpl::AllocateFrameSinkId();
+  return CompositorDependencies::Get().AllocateFrameSinkId();
 #else
   ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
   return factory->GetContextFactoryPrivate()->AllocateFrameSinkId();
@@ -28,7 +28,7 @@
 
 viz::FrameSinkManagerImpl* GetFrameSinkManager() {
 #if defined(OS_ANDROID)
-  return CompositorImpl::GetFrameSinkManager();
+  return CompositorDependencies::Get().frame_sink_manager_impl();
 #else
   ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
   if (!factory)
@@ -39,7 +39,7 @@
 
 viz::HostFrameSinkManager* GetHostFrameSinkManager() {
 #if defined(OS_ANDROID)
-  return CompositorImpl::GetHostFrameSinkManager();
+  return CompositorDependencies::Get().host_frame_sink_manager();
 #else
   ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
   if (!factory)
diff --git a/content/browser/download/download_manager_impl.cc b/content/browser/download/download_manager_impl.cc
index cd50e7fd..ef9e5d6 100644
--- a/content/browser/download/download_manager_impl.cc
+++ b/content/browser/download/download_manager_impl.cc
@@ -1141,8 +1141,9 @@
 }
 
 void DownloadManagerImpl::ImportInProgressDownloads(uint32_t id) {
-  for (auto& download : in_progress_downloads_) {
-    auto item = std::move(download);
+  auto download = in_progress_downloads_.begin();
+  while (download != in_progress_downloads_.end()) {
+    auto item = std::move(*download);
     // If the in-progress download doesn't have an ID, generate new IDs for it.
     if (item->GetId() == download::DownloadItem::kInvalidId) {
       item->SetDownloadId(id++);
@@ -1152,10 +1153,9 @@
     }
     item->SetDelegate(this);
     DownloadItemUtils::AttachInfo(item.get(), GetBrowserContext(), nullptr);
+    download = in_progress_downloads_.erase(download);
     OnDownloadCreated(std::move(item));
   }
-  in_progress_downloads_.clear();
-
   OnDownloadManagerInitialized();
 }
 
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc
index 98ac2696..094ac652 100644
--- a/content/browser/frame_host/render_frame_host_impl.cc
+++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -1271,7 +1271,8 @@
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   CHECK(CanExecuteJavaScript());
 
-  GetNavigationControl()->JavaScriptExecuteRequest(javascript,
+  const bool wants_result = !callback.is_null();
+  GetNavigationControl()->JavaScriptExecuteRequest(javascript, wants_result,
                                                    std::move(callback));
 }
 
@@ -1283,8 +1284,9 @@
   DCHECK_GT(world_id, ISOLATED_WORLD_ID_GLOBAL);
   DCHECK_LE(world_id, ISOLATED_WORLD_ID_MAX);
 
+  const bool wants_result = !callback.is_null();
   GetNavigationControl()->JavaScriptExecuteRequestInIsolatedWorld(
-      javascript, world_id, std::move(callback));
+      javascript, wants_result, world_id, std::move(callback));
 }
 
 void RenderFrameHostImpl::ExecuteJavaScriptForTests(
@@ -1293,8 +1295,9 @@
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   const bool has_user_gesture = false;
+  const bool wants_result = !callback.is_null();
   GetNavigationControl()->JavaScriptExecuteRequestForTests(
-      javascript, has_user_gesture, std::move(callback));
+      javascript, wants_result, has_user_gesture, std::move(callback));
 }
 
 void RenderFrameHostImpl::ExecuteJavaScriptWithUserGestureForTests(
@@ -1303,7 +1306,7 @@
 
   const bool has_user_gesture = true;
   GetNavigationControl()->JavaScriptExecuteRequestForTests(
-      javascript, has_user_gesture, base::NullCallback());
+      javascript, false, has_user_gesture, base::NullCallback());
 }
 
 void RenderFrameHostImpl::CopyImageAt(int x, int y) {
diff --git a/content/browser/renderer_host/compositor_dependencies_android.cc b/content/browser/renderer_host/compositor_dependencies_android.cc
new file mode 100644
index 0000000..4cb2f96
--- /dev/null
+++ b/content/browser/renderer_host/compositor_dependencies_android.cc
@@ -0,0 +1,213 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/compositor_dependencies_android.h"
+
+#include "base/bind.h"
+#include "base/system/sys_info.h"
+#include "base/task/post_task.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "base/time/time.h"
+#include "cc/raster/single_thread_task_graph_runner.h"
+#include "components/viz/client/frame_eviction_manager.h"
+#include "components/viz/common/features.h"
+#include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
+#include "content/browser/browser_main_loop.h"
+#include "content/browser/compositor/surface_utils.h"
+#include "content/browser/gpu/browser_gpu_channel_host_factory.h"
+#include "content/browser/gpu/gpu_data_manager_impl.h"
+#include "content/browser/gpu/gpu_process_host.h"
+#include "content/public/browser/browser_task_traits.h"
+#include "content/public/browser/browser_thread.h"
+
+namespace content {
+
+namespace {
+
+// The client_id used here should not conflict with the client_id generated
+// from RenderWidgetHostImpl.
+constexpr uint32_t kDefaultClientId = 0u;
+
+void BrowserGpuChannelHostFactorySetApplicationVisible(bool is_visible) {
+  // This code relies on the browser's GpuChannelEstablishFactory being the
+  // BrowserGpuChannelHostFactory.
+  DCHECK_EQ(BrowserMainLoop::GetInstance()->gpu_channel_establish_factory(),
+            BrowserGpuChannelHostFactory::instance());
+  BrowserGpuChannelHostFactory::instance()->SetApplicationVisible(is_visible);
+}
+
+// These functions are called based on application visibility status.
+void SendOnBackgroundedToGpuService() {
+  content::GpuProcessHost::CallOnIO(
+      content::GPU_PROCESS_KIND_SANDBOXED, false /* force_create */,
+      base::BindRepeating([](content::GpuProcessHost* host) {
+        if (host) {
+          host->gpu_service()->OnBackgrounded();
+        }
+      }));
+}
+
+void SendOnForegroundedToGpuService() {
+  content::GpuProcessHost::CallOnIO(
+      content::GPU_PROCESS_KIND_SANDBOXED, false /* force_create */,
+      base::BindRepeating([](content::GpuProcessHost* host) {
+        if (host) {
+          host->gpu_service()->OnForegrounded();
+        }
+      }));
+}
+
+class SingleThreadTaskGraphRunner : public cc::SingleThreadTaskGraphRunner {
+ public:
+  SingleThreadTaskGraphRunner() {
+    Start("CompositorTileWorker1", base::SimpleThread::Options());
+  }
+
+  ~SingleThreadTaskGraphRunner() override { Shutdown(); }
+};
+
+}  // namespace
+
+// static
+CompositorDependencies& CompositorDependencies::Get() {
+  static base::NoDestructor<CompositorDependencies> instance;
+  return *instance;
+}
+
+CompositorDependencies::CompositorDependencies()
+    : frame_sink_id_allocator_(kDefaultClientId) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+  bool enable_viz = features::IsVizDisplayCompositorEnabled();
+  if (!enable_viz) {
+    // The SharedBitmapManager can be null as software compositing is not
+    // supported or used on Android.
+    frame_sink_manager_impl_ = std::make_unique<viz::FrameSinkManagerImpl>(
+        /*shared_bitmap_manager=*/nullptr);
+    surface_utils::ConnectWithLocalFrameSinkManager(
+        &host_frame_sink_manager_, frame_sink_manager_impl_.get());
+  } else {
+    CreateVizFrameSinkManager();
+  }
+}
+
+CompositorDependencies::~CompositorDependencies() = default;
+
+void CompositorDependencies::CreateVizFrameSinkManager() {
+  viz::mojom::FrameSinkManagerPtr frame_sink_manager;
+  viz::mojom::FrameSinkManagerRequest frame_sink_manager_request =
+      mojo::MakeRequest(&frame_sink_manager);
+  viz::mojom::FrameSinkManagerClientPtr frame_sink_manager_client;
+  viz::mojom::FrameSinkManagerClientRequest frame_sink_manager_client_request =
+      mojo::MakeRequest(&frame_sink_manager_client);
+
+  // Setup HostFrameSinkManager with interface endpoints.
+  host_frame_sink_manager_.BindAndSetManager(
+      std::move(frame_sink_manager_client_request),
+      base::ThreadTaskRunnerHandle::Get(), std::move(frame_sink_manager));
+
+  // Set up a callback to automatically re-connect if we lose our
+  // connection.
+  host_frame_sink_manager_.SetConnectionLostCallback(base::BindRepeating(
+      []() { CompositorDependencies::Get().CreateVizFrameSinkManager(); }));
+
+  // Set up a pending request which will be run once we've successfully
+  // connected to the GPU process.
+  pending_connect_viz_on_io_thread_ = base::BindOnce(
+      &CompositorDependencies::ConnectVizFrameSinkManagerOnIOThread,
+      std::move(frame_sink_manager_request),
+      frame_sink_manager_client.PassInterface());
+}
+
+cc::TaskGraphRunner* CompositorDependencies::GetTaskGraphRunner() {
+  if (!task_graph_runner_)
+    task_graph_runner_ = std::make_unique<SingleThreadTaskGraphRunner>();
+  return task_graph_runner_.get();
+}
+
+viz::FrameSinkId CompositorDependencies::AllocateFrameSinkId() {
+  return frame_sink_id_allocator_.NextFrameSinkId();
+}
+
+void CompositorDependencies::TryEstablishVizConnectionIfNeeded() {
+  if (!pending_connect_viz_on_io_thread_)
+    return;
+  base::PostTaskWithTraits(FROM_HERE, {BrowserThread::IO},
+                           std::move(pending_connect_viz_on_io_thread_));
+}
+
+// Called on IO thread, after a GPU connection has already been established.
+// |gpu_process_host| should only be invalid if a channel has been
+// established and lost. In this case the ConnectionLost callback will be
+// re-run when the request is deleted (goes out of scope).
+// static
+void CompositorDependencies::ConnectVizFrameSinkManagerOnIOThread(
+    viz::mojom::FrameSinkManagerRequest request,
+    viz::mojom::FrameSinkManagerClientPtrInfo client) {
+  auto* gpu_process_host = GpuProcessHost::Get();
+  if (!gpu_process_host)
+    return;
+  gpu_process_host->gpu_host()->ConnectFrameSinkManager(std::move(request),
+                                                        std::move(client));
+}
+
+void CompositorDependencies::EnqueueLowEndBackgroundCleanup() {
+  if (base::SysInfo::IsLowEndDevice()) {
+    low_end_background_cleanup_task_.Reset(
+        base::BindOnce(&CompositorDependencies::DoLowEndBackgroundCleanup,
+                       base::Unretained(this)));
+    base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+        FROM_HERE, low_end_background_cleanup_task_.callback(),
+        base::TimeDelta::FromSeconds(5));
+  }
+}
+
+void CompositorDependencies::DoLowEndBackgroundCleanup() {
+  // When we become visible, we immediately cancel the callback that runs this
+  // code. First, evict all unlocked frames, allowing resources to be
+  // reclaimed.
+  viz::FrameEvictionManager::GetInstance()->PurgeAllUnlockedFrames();
+
+  // Next, notify the GPU process to do background processing, which will
+  // lose all renderer contexts.
+  content::GpuProcessHost::CallOnIO(
+      content::GPU_PROCESS_KIND_SANDBOXED, false /* force_create */,
+      base::BindRepeating([](content::GpuProcessHost* host) {
+        if (host) {
+          host->gpu_service()->OnBackgroundCleanup();
+        }
+      }));
+}
+
+void CompositorDependencies::OnCompositorVisible(CompositorImpl* compositor) {
+  bool element_inserted = visible_compositors_.insert(compositor).second;
+  DCHECK(element_inserted);
+  if (visible_compositors_.size() == 1)
+    OnVisibilityChanged();
+}
+
+void CompositorDependencies::OnCompositorHidden(CompositorImpl* compositor) {
+  size_t elements_removed = visible_compositors_.erase(compositor);
+  DCHECK_EQ(1u, elements_removed);
+  if (visible_compositors_.size() == 0)
+    OnVisibilityChanged();
+}
+
+// This function runs when our first CompositorImpl becomes visible or when
+// our last Compositormpl is hidden.
+void CompositorDependencies::OnVisibilityChanged() {
+  if (visible_compositors_.size() > 0) {
+    GpuDataManagerImpl::GetInstance()->SetApplicationVisible(true);
+    BrowserGpuChannelHostFactorySetApplicationVisible(true);
+    SendOnForegroundedToGpuService();
+    low_end_background_cleanup_task_.Cancel();
+  } else {
+    GpuDataManagerImpl::GetInstance()->SetApplicationVisible(false);
+    BrowserGpuChannelHostFactorySetApplicationVisible(false);
+    SendOnBackgroundedToGpuService();
+    EnqueueLowEndBackgroundCleanup();
+  }
+}
+
+}  // namespace content
diff --git a/content/browser/renderer_host/compositor_dependencies_android.h b/content/browser/renderer_host/compositor_dependencies_android.h
new file mode 100644
index 0000000..dc131a2
--- /dev/null
+++ b/content/browser/renderer_host/compositor_dependencies_android.h
@@ -0,0 +1,92 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_RENDERER_HOST_COMPOSITOR_DEPENDENCIES_ANDROID_H_
+#define CONTENT_BROWSER_RENDERER_HOST_COMPOSITOR_DEPENDENCIES_ANDROID_H_
+
+#include <memory>
+
+#include "base/callback.h"
+#include "base/cancelable_callback.h"
+#include "base/containers/flat_set.h"
+#include "base/no_destructor.h"
+#include "components/viz/common/surfaces/frame_sink_id_allocator.h"
+#include "components/viz/host/host_frame_sink_manager.h"
+#include "services/viz/privileged/interfaces/compositing/frame_sink_manager.mojom.h"
+
+namespace cc {
+class TaskGraphRunner;
+}  // namespace cc
+
+namespace viz {
+class FrameSinkManagerImpl;
+}  // namespace viz
+
+namespace content {
+
+class CompositorImpl;
+
+class CompositorDependencies {
+ public:
+  static CompositorDependencies& Get();
+
+  cc::TaskGraphRunner* GetTaskGraphRunner();
+
+  viz::HostFrameSinkManager* host_frame_sink_manager() {
+    return &host_frame_sink_manager_;
+  }
+
+  viz::FrameSinkManagerImpl* frame_sink_manager_impl() {
+    return frame_sink_manager_impl_.get();
+  }
+
+  viz::FrameSinkId AllocateFrameSinkId();
+  void TryEstablishVizConnectionIfNeeded();
+  void OnCompositorVisible(CompositorImpl* compositor);
+  void OnCompositorHidden(CompositorImpl* compositor);
+
+ private:
+  friend class base::NoDestructor<CompositorDependencies>;
+
+  static void ConnectVizFrameSinkManagerOnIOThread(
+      viz::mojom::FrameSinkManagerRequest request,
+      viz::mojom::FrameSinkManagerClientPtrInfo client);
+
+  CompositorDependencies();
+  ~CompositorDependencies();
+
+  void CreateVizFrameSinkManager();
+  void EnqueueLowEndBackgroundCleanup();
+  void DoLowEndBackgroundCleanup();
+  void OnVisibilityChanged();
+
+  viz::HostFrameSinkManager host_frame_sink_manager_;
+  viz::FrameSinkIdAllocator frame_sink_id_allocator_;
+
+  // Non-viz members:
+  // This is owned here so that SurfaceManager will be accessible in process
+  // when display is in the same process. Other than using SurfaceManager,
+  // access to |in_process_frame_sink_manager_| should happen via
+  // |host_frame_sink_manager_| instead which uses Mojo. See
+  // http://crbug.com/657959.
+  std::unique_ptr<viz::FrameSinkManagerImpl> frame_sink_manager_impl_;
+
+  // A task which runs cleanup tasks on low-end Android after a delay. Enqueued
+  // when we hide, canceled when we're shown.
+  base::CancelableOnceClosure low_end_background_cleanup_task_;
+
+  // A callback which connects to the viz service on the IO thread.
+  base::OnceClosure pending_connect_viz_on_io_thread_;
+
+  // The set of visible CompositorImpls.
+  base::flat_set<CompositorImpl*> visible_compositors_;
+
+  std::unique_ptr<cc::TaskGraphRunner> task_graph_runner_;
+
+  DISALLOW_COPY_AND_ASSIGN(CompositorDependencies);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_RENDERER_HOST_COMPOSITOR_DEPENDENCIES_ANDROID_H_
diff --git a/content/browser/renderer_host/compositor_impl_android.cc b/content/browser/renderer_host/compositor_impl_android.cc
index a0c7d6e..69e1a82 100644
--- a/content/browser/renderer_host/compositor_impl_android.cc
+++ b/content/browser/renderer_host/compositor_impl_android.cc
@@ -23,11 +23,8 @@
 #include "base/logging.h"
 #include "base/memory/weak_ptr.h"
 #include "base/metrics/histogram_macros.h"
-#include "base/no_destructor.h"
 #include "base/single_thread_task_runner.h"
 #include "base/synchronization/lock.h"
-#include "base/system/sys_info.h"
-#include "base/task/post_task.h"
 #include "base/threading/simple_thread.h"
 #include "base/threading/thread.h"
 #include "base/threading/thread_checker.h"
@@ -37,21 +34,17 @@
 #include "cc/input/input_handler.h"
 #include "cc/layers/layer.h"
 #include "cc/mojo_embedder/async_layer_tree_frame_sink.h"
-#include "cc/raster/single_thread_task_graph_runner.h"
 #include "cc/resources/ui_resource_manager.h"
 #include "cc/trees/layer_tree_host.h"
 #include "cc/trees/layer_tree_settings.h"
-#include "components/viz/client/frame_eviction_manager.h"
 #include "components/viz/client/hit_test_data_provider_draw_quad.h"
 #include "components/viz/client/local_surface_id_provider.h"
 #include "components/viz/common/features.h"
 #include "components/viz/common/gpu/context_provider.h"
 #include "components/viz/common/quads/compositor_frame.h"
-#include "components/viz/common/surfaces/frame_sink_id_allocator.h"
 #include "components/viz/common/surfaces/local_surface_id_allocation.h"
 #include "components/viz/common/viz_utils.h"
 #include "components/viz/host/host_display_client.h"
-#include "components/viz/host/host_frame_sink_manager.h"
 #include "components/viz/service/display/display.h"
 #include "components/viz/service/display/display_scheduler.h"
 #include "components/viz/service/display/output_surface.h"
@@ -63,14 +56,12 @@
 #include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
 #include "content/browser/browser_main_loop.h"
 #include "content/browser/compositor/surface_utils.h"
-#include "content/browser/gpu/browser_gpu_channel_host_factory.h"
 #include "content/browser/gpu/compositor_util.h"
-#include "content/browser/gpu/gpu_data_manager_impl.h"
 #include "content/browser/gpu/gpu_process_host.h"
+#include "content/browser/renderer_host/compositor_dependencies_android.h"
 #include "content/browser/renderer_host/render_widget_host_impl.h"
 #include "content/public/browser/android/compositor.h"
 #include "content/public/browser/android/compositor_client.h"
-#include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/common/content_features.h"
 #include "content/public/common/content_switches.h"
@@ -82,7 +73,6 @@
 #include "gpu/ipc/client/command_buffer_proxy_impl.h"
 #include "gpu/ipc/client/gpu_channel_host.h"
 #include "gpu/ipc/common/gpu_surface_tracker.h"
-#include "services/viz/privileged/interfaces/compositing/frame_sink_manager.mojom.h"
 #include "services/viz/public/interfaces/compositing/compositor_frame_sink.mojom.h"
 #include "services/ws/public/cpp/gpu/context_provider_command_buffer.h"
 #include "third_party/khronos/GLES2/gl2.h"
@@ -130,203 +120,6 @@
   return gfx::OVERLAY_TRANSFORM_NONE;
 }
 
-// These functions are called based on application visibility status.
-void SendOnBackgroundedToGpuService() {
-  content::GpuProcessHost::CallOnIO(
-      content::GPU_PROCESS_KIND_SANDBOXED, false /* force_create */,
-      base::BindRepeating([](content::GpuProcessHost* host) {
-        if (host) {
-          host->gpu_service()->OnBackgrounded();
-        }
-      }));
-}
-
-void SendOnForegroundedToGpuService() {
-  content::GpuProcessHost::CallOnIO(
-      content::GPU_PROCESS_KIND_SANDBOXED, false /* force_create */,
-      base::BindRepeating([](content::GpuProcessHost* host) {
-        if (host) {
-          host->gpu_service()->OnForegrounded();
-        }
-      }));
-}
-
-void BrowserGpuChannelHostFactorySetApplicationVisible(bool is_visible) {
-  // This code relies on the browser's GpuChannelEstablishFactory being the
-  // BrowserGpuChannelHostFactory.
-  DCHECK_EQ(BrowserMainLoop::GetInstance()->gpu_channel_establish_factory(),
-            BrowserGpuChannelHostFactory::instance());
-  BrowserGpuChannelHostFactory::instance()->SetApplicationVisible(is_visible);
-}
-
-// The client_id used here should not conflict with the client_id generated
-// from RenderWidgetHostImpl.
-constexpr uint32_t kDefaultClientId = 0u;
-
-class SingleThreadTaskGraphRunner : public cc::SingleThreadTaskGraphRunner {
- public:
-  SingleThreadTaskGraphRunner() {
-    Start("CompositorTileWorker1", base::SimpleThread::Options());
-  }
-
-  ~SingleThreadTaskGraphRunner() override { Shutdown(); }
-};
-
-class CompositorDependencies {
- public:
-  static CompositorDependencies& Get() {
-    static base::NoDestructor<CompositorDependencies> instance;
-    return *instance;
-  }
-
-  void CreateVizFrameSinkManager() {
-    viz::mojom::FrameSinkManagerPtr frame_sink_manager;
-    viz::mojom::FrameSinkManagerRequest frame_sink_manager_request =
-        mojo::MakeRequest(&frame_sink_manager);
-    viz::mojom::FrameSinkManagerClientPtr frame_sink_manager_client;
-    viz::mojom::FrameSinkManagerClientRequest
-        frame_sink_manager_client_request =
-            mojo::MakeRequest(&frame_sink_manager_client);
-
-    // Setup HostFrameSinkManager with interface endpoints.
-    host_frame_sink_manager.BindAndSetManager(
-        std::move(frame_sink_manager_client_request),
-        base::ThreadTaskRunnerHandle::Get(), std::move(frame_sink_manager));
-
-    // Set up a callback to automatically re-connect if we lose our
-    // connection.
-    host_frame_sink_manager.SetConnectionLostCallback(base::BindRepeating(
-        []() { CompositorDependencies::Get().CreateVizFrameSinkManager(); }));
-
-    // Set up a pending request which will be run once we've successfully
-    // connected to the GPU process.
-    pending_connect_viz_on_io_thread_ = base::BindOnce(
-        &CompositorDependencies::ConnectVizFrameSinkManagerOnIOThread,
-        std::move(frame_sink_manager_request),
-        frame_sink_manager_client.PassInterface());
-  }
-
-  void TryEstablishVizConnectionIfNeeded() {
-    if (!pending_connect_viz_on_io_thread_)
-      return;
-    base::PostTaskWithTraits(FROM_HERE, {BrowserThread::IO},
-                             std::move(pending_connect_viz_on_io_thread_));
-  }
-
-  void OnCompositorVisible(CompositorImpl* compositor) {
-    bool element_inserted = visible_compositors_.insert(compositor).second;
-    DCHECK(element_inserted);
-    if (visible_compositors_.size() == 1)
-      OnVisibilityChanged();
-  }
-
-  void OnCompositorHidden(CompositorImpl* compositor) {
-    size_t elements_removed = visible_compositors_.erase(compositor);
-    DCHECK_EQ(1u, elements_removed);
-    if (visible_compositors_.size() == 0)
-      OnVisibilityChanged();
-  }
-
-  SingleThreadTaskGraphRunner task_graph_runner;
-  viz::HostFrameSinkManager host_frame_sink_manager;
-  viz::FrameSinkIdAllocator frame_sink_id_allocator;
-
-  // Non-viz members:
-  // This is owned here so that SurfaceManager will be accessible in process
-  // when display is in the same process. Other than using SurfaceManager,
-  // access to |in_process_frame_sink_manager_| should happen via
-  // |host_frame_sink_manager_| instead which uses Mojo. See
-  // http://crbug.com/657959.
-  std::unique_ptr<viz::FrameSinkManagerImpl> frame_sink_manager_impl;
-
- private:
-  friend class base::NoDestructor<CompositorDependencies>;
-
-  CompositorDependencies() : frame_sink_id_allocator(kDefaultClientId) {
-    DCHECK_CURRENTLY_ON(BrowserThread::UI);
-
-    bool enable_viz = features::IsVizDisplayCompositorEnabled();
-    if (!enable_viz) {
-      // The SharedBitmapManager can be null as software compositing is not
-      // supported or used on Android.
-      frame_sink_manager_impl = std::make_unique<viz::FrameSinkManagerImpl>(
-          /*shared_bitmap_manager=*/nullptr);
-      surface_utils::ConnectWithLocalFrameSinkManager(
-          &host_frame_sink_manager, frame_sink_manager_impl.get());
-    } else {
-      CreateVizFrameSinkManager();
-    }
-  }
-
-  // Called on IO thread, after a GPU connection has already been established.
-  // |gpu_process_host| should only be invalid if a channel has been
-  // established and lost. In this case the ConnectionLost callback will be
-  // re-run when the request is deleted (goes out of scope).
-  static void ConnectVizFrameSinkManagerOnIOThread(
-      viz::mojom::FrameSinkManagerRequest request,
-      viz::mojom::FrameSinkManagerClientPtrInfo client) {
-    auto* gpu_process_host = GpuProcessHost::Get();
-    if (!gpu_process_host)
-      return;
-    gpu_process_host->gpu_host()->ConnectFrameSinkManager(std::move(request),
-                                                          std::move(client));
-  }
-
-  void EnqueueLowEndBackgroundCleanup() {
-    if (base::SysInfo::IsLowEndDevice()) {
-      low_end_background_cleanup_task_.Reset(
-          base::BindOnce(&CompositorDependencies::DoLowEndBackgroundCleanup,
-                         base::Unretained(this)));
-      base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
-          FROM_HERE, low_end_background_cleanup_task_.callback(),
-          base::TimeDelta::FromSeconds(5));
-    }
-  }
-
-  void DoLowEndBackgroundCleanup() {
-    // When we become visible, we immediately cancel the callback that runs this
-    // code. First, evict all unlocked frames, allowing resources to be
-    // reclaimed.
-    viz::FrameEvictionManager::GetInstance()->PurgeAllUnlockedFrames();
-
-    // Next, notify the GPU process to do background processing, which will
-    // lose all renderer contexts.
-    content::GpuProcessHost::CallOnIO(
-        content::GPU_PROCESS_KIND_SANDBOXED, false /* force_create */,
-        base::BindRepeating([](content::GpuProcessHost* host) {
-          if (host) {
-            host->gpu_service()->OnBackgroundCleanup();
-          }
-        }));
-  }
-
-  // This function runs when our first CompositorImpl becomes visible or when
-  // our last Compositormpl is hidden.
-  void OnVisibilityChanged() {
-    if (visible_compositors_.size() > 0) {
-      GpuDataManagerImpl::GetInstance()->SetApplicationVisible(true);
-      BrowserGpuChannelHostFactorySetApplicationVisible(true);
-      SendOnForegroundedToGpuService();
-      low_end_background_cleanup_task_.Cancel();
-    } else {
-      GpuDataManagerImpl::GetInstance()->SetApplicationVisible(false);
-      BrowserGpuChannelHostFactorySetApplicationVisible(false);
-      SendOnBackgroundedToGpuService();
-      EnqueueLowEndBackgroundCleanup();
-    }
-  }
-
-  // A task which runs cleanup tasks on low-end Android after a delay. Enqueued
-  // when we hide, canceled when we're shown.
-  base::CancelableOnceClosure low_end_background_cleanup_task_;
-
-  // A callback which connects to the viz service on the IO thread.
-  base::OnceClosure pending_connect_viz_on_io_thread_;
-
-  // The set of visible CompositorImpls.
-  base::flat_set<CompositorImpl*> visible_compositors_;
-};
-
 const unsigned int kMaxDisplaySwapBuffers = 1U;
 
 gpu::SharedMemoryLimits GetCompositorContextSharedMemoryLimits(
@@ -612,22 +405,6 @@
 }
 
 // static
-viz::FrameSinkManagerImpl* CompositorImpl::GetFrameSinkManager() {
-  return CompositorDependencies::Get().frame_sink_manager_impl.get();
-}
-
-// static
-viz::HostFrameSinkManager* CompositorImpl::GetHostFrameSinkManager() {
-  return &CompositorDependencies::Get().host_frame_sink_manager;
-}
-
-// static
-viz::FrameSinkId CompositorImpl::AllocateFrameSinkId() {
-  return CompositorDependencies::Get()
-      .frame_sink_id_allocator.NextFrameSinkId();
-}
-
-// static
 bool CompositorImpl::IsInitialized() {
   return g_initialized;
 }
@@ -794,7 +571,7 @@
 
   cc::LayerTreeHost::InitParams params;
   params.client = this;
-  params.task_graph_runner = &CompositorDependencies::Get().task_graph_runner;
+  params.task_graph_runner = CompositorDependencies::Get().GetTaskGraphRunner();
   params.main_task_runner = base::ThreadTaskRunnerHandle::Get();
   params.settings = &settings;
   params.mutator_host = animation_host_.get();
diff --git a/content/browser/renderer_host/compositor_impl_android.h b/content/browser/renderer_host/compositor_impl_android.h
index 61b97e38..765c73f 100644
--- a/content/browser/renderer_host/compositor_impl_android.h
+++ b/content/browser/renderer_host/compositor_impl_android.h
@@ -55,7 +55,6 @@
 namespace viz {
 class Display;
 class FrameSinkId;
-class FrameSinkManagerImpl;
 class HostDisplayClient;
 class OutputSurface;
 }
@@ -80,10 +79,6 @@
 
   static bool IsInitialized();
 
-  static viz::FrameSinkManagerImpl* GetFrameSinkManager();
-  static viz::HostFrameSinkManager* GetHostFrameSinkManager();
-  static viz::FrameSinkId AllocateFrameSinkId();
-
   // ui::ResourceProvider implementation.
   cc::UIResourceId CreateUIResource(cc::UIResourceClient* client) override;
   void DeleteUIResource(cc::UIResourceId resource_id) override;
diff --git a/content/browser/renderer_host/delegated_frame_host.cc b/content/browser/renderer_host/delegated_frame_host.cc
index cd3f355..3a5efa97 100644
--- a/content/browser/renderer_host/delegated_frame_host.cc
+++ b/content/browser/renderer_host/delegated_frame_host.cc
@@ -282,7 +282,10 @@
   if (seen_first_activation_)
     frame_evictor_->OnNewSurfaceEmbedded();
 #else
-  frame_evictor_->OnNewSurfaceEmbedded();
+  // Ignore empty frames. Extensions often create empty background page frames
+  // which shouldn't count against the saved frames.
+  if (!new_dip_size.IsEmpty())
+    frame_evictor_->OnNewSurfaceEmbedded();
 #endif
 
   if (!primary_surface_id ||
diff --git a/content/browser/renderer_host/input/input_router_impl.cc b/content/browser/renderer_host/input/input_router_impl.cc
index 0e28047e..0eaa9de 100644
--- a/content/browser/renderer_host/input/input_router_impl.cc
+++ b/content/browser/renderer_host/input/input_router_impl.cc
@@ -621,10 +621,8 @@
     }
   }
 
-  bool should_stop_timeout_monitor =
-      !compositor_touch_action_enabled_ ||
-      (compositor_touch_action_enabled_ &&
-       touch_action_filter_.allowed_touch_action().has_value());
+  // TODO(crbug.com/953547): find a proper way to stop the timeout monitor.
+  bool should_stop_timeout_monitor = true;
   // |touch_event_queue_| will forward to OnTouchEventAck when appropriate.
   touch_event_queue_.ProcessTouchAck(source, state, latency,
                                      touch_event.event.unique_touch_event_id,
diff --git a/content/browser/renderer_host/input/input_router_impl_unittest.cc b/content/browser/renderer_host/input/input_router_impl_unittest.cc
index b1ecd6e..f19d1ed 100644
--- a/content/browser/renderer_host/input/input_router_impl_unittest.cc
+++ b/content/browser/renderer_host/input/input_router_impl_unittest.cc
@@ -2126,6 +2126,9 @@
 }
 
 TEST_P(InputRouterImplTest, TimeoutMonitorStopWithMainThreadTouchAction) {
+  // TODO(crbug.com/953547): enable this when the bug is fixed.
+  if (compositor_touch_action_enabled_)
+    return;
   SetUpForTouchAckTimeoutTest(1, 1);
   OnHasTouchEventHandlers(true);
 
diff --git a/content/browser/renderer_host/render_widget_host_input_event_router.cc b/content/browser/renderer_host/render_widget_host_input_event_router.cc
index 81f81bc..e7dee485 100644
--- a/content/browser/renderer_host/render_widget_host_input_event_router.cc
+++ b/content/browser/renderer_host/render_widget_host_input_event_router.cc
@@ -1389,13 +1389,6 @@
           .view->GetRenderWidgetHost());
 }
 
-void RenderWidgetHostInputEventRouter::GetRenderWidgetHostAtPointAsynchronously(
-    RenderWidgetHostViewBase* root_view,
-    const gfx::PointF& point,
-    RenderWidgetTargeter::RenderWidgetHostAtPointCallback callback) {
-  event_targeter_->FindTargetAndCallback(root_view, point, std::move(callback));
-}
-
 RenderWidgetTargetResult
 RenderWidgetHostInputEventRouter::FindTouchscreenGestureEventTarget(
     RenderWidgetHostViewBase* root_view,
@@ -1778,15 +1771,6 @@
 }
 
 RenderWidgetTargetResult
-RenderWidgetHostInputEventRouter::FindTargetSynchronouslyAtLocation(
-    RenderWidgetHostViewBase* root_view,
-    const gfx::PointF& location) {
-  gfx::PointF transformed_pt;  // This is already in the result
-  return FindViewAtLocation(root_view, location, gfx::PointF() /* not used */,
-                            viz::EventSource::MOUSE, &transformed_pt);
-}
-
-RenderWidgetTargetResult
 RenderWidgetHostInputEventRouter::FindTargetSynchronously(
     RenderWidgetHostViewBase* root_view,
     const blink::WebInputEvent& event) {
diff --git a/content/browser/renderer_host/render_widget_host_input_event_router.h b/content/browser/renderer_host/render_widget_host_input_event_router.h
index 748e0c5..e46df79 100644
--- a/content/browser/renderer_host/render_widget_host_input_event_router.h
+++ b/content/browser/renderer_host/render_widget_host_input_event_router.h
@@ -135,17 +135,6 @@
       const gfx::PointF& point,
       gfx::PointF* transformed_point);
 
-  // Finds the RenderWidgetHostImpl inside the |root_view| at |point| where
-  // |point| is with respect to |root_view|'s coordinates. If a RWHI is found,
-  // it is passed along with the coordinate of the point with
-  // respect to the RWHI's coordinates to the callback function. If
-  // |root_view| is nullptr or RWHI is not found, the callback is called with
-  // nullptr and no location.
-  void GetRenderWidgetHostAtPointAsynchronously(
-      RenderWidgetHostViewBase* root_view,
-      const gfx::PointF& point,
-      RenderWidgetTargeter::RenderWidgetHostAtPointCallback callback);
-
   // RenderWidgetTargeter::Delegate:
   RenderWidgetHostViewBase* FindViewFromFrameSinkId(
       const viz::FrameSinkId& frame_sink_id) const override;
@@ -323,10 +312,6 @@
                                       const RenderWidgetHostViewBase* view);
 
   // RenderWidgetTargeter::Delegate:
-  RenderWidgetTargetResult FindTargetSynchronouslyAtLocation(
-      RenderWidgetHostViewBase* root_view,
-      const gfx::PointF& location) override;
-
   RenderWidgetTargetResult FindTargetSynchronously(
       RenderWidgetHostViewBase* root_view,
       const blink::WebInputEvent& event) override;
diff --git a/content/browser/renderer_host/render_widget_host_view_android.cc b/content/browser/renderer_host/render_widget_host_view_android.cc
index 297957c..212a792 100644
--- a/content/browser/renderer_host/render_widget_host_view_android.cc
+++ b/content/browser/renderer_host/render_widget_host_view_android.cc
@@ -205,9 +205,8 @@
     delegated_frame_host_client_ =
         std::make_unique<DelegatedFrameHostClientAndroid>(this);
     delegated_frame_host_ = std::make_unique<ui::DelegatedFrameHostAndroid>(
-        &view_, CompositorImpl::GetHostFrameSinkManager(),
-        delegated_frame_host_client_.get(), host()->GetFrameSinkId(),
-        features::IsSurfaceSynchronizationEnabled());
+        &view_, GetHostFrameSinkManager(), delegated_frame_host_client_.get(),
+        host()->GetFrameSinkId(), features::IsSurfaceSynchronizationEnabled());
     if (is_showing_) {
       delegated_frame_host_->WasShown(
           local_surface_id_allocator_.GetCurrentLocalSurfaceIdAllocation()
@@ -226,7 +225,7 @@
   host()->SetView(this);
   touch_selection_controller_client_manager_ =
       std::make_unique<TouchSelectionControllerClientManagerAndroid>(
-          this, CompositorImpl::GetHostFrameSinkManager());
+          this, GetHostFrameSinkManager());
 
   UpdateNativeViewTree(parent_native_view);
   // This RWHVA may have been created speculatively. We should give any
diff --git a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
index 9e8e7a40..1d12735e 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
+++ b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
@@ -5740,6 +5740,8 @@
 TEST_F(RenderWidgetHostViewAuraSurfaceSynchronizationTest,
        AllocateLocalSurfaceIdOnEviction) {
   view_->InitAsChild(nullptr);
+  // View has to not be empty in order for frame eviction to be invoked.
+  view_->SetSize(gfx::Size(54, 32));
   aura::client::ParentWindowWithContext(
       view_->GetNativeView(), parent_view_->GetNativeView()->GetRootWindow(),
       gfx::Rect());
diff --git a/content/browser/renderer_host/render_widget_targeter.cc b/content/browser/renderer_host/render_widget_targeter.cc
index 83ee7d4..2f540fb 100644
--- a/content/browser/renderer_host/render_widget_targeter.cc
+++ b/content/browser/renderer_host/render_widget_targeter.cc
@@ -22,6 +22,17 @@
 
 namespace {
 
+bool MergeEventIfPossible(const blink::WebInputEvent& event,
+                          ui::WebScopedInputEvent* blink_event) {
+  if (!blink::WebInputEvent::IsTouchEventType(event.GetType()) &&
+      !blink::WebInputEvent::IsGestureEventType(event.GetType()) &&
+      ui::CanCoalesce(event, **blink_event)) {
+    ui::Coalesce(event, blink_event->get());
+    return true;
+  }
+  return false;
+}
+
 gfx::PointF ComputeEventLocation(const blink::WebInputEvent& event) {
   if (blink::WebInputEvent::IsMouseEventType(event.GetType()) ||
       event.GetType() == blink::WebInputEvent::kMouseWheel) {
@@ -107,24 +118,7 @@
 
 RenderWidgetTargetResult::~RenderWidgetTargetResult() = default;
 
-RenderWidgetTargeter::TargetingRequest::TargetingRequest(
-    base::WeakPtr<RenderWidgetHostViewBase> root_view,
-    const blink::WebInputEvent& event,
-    const ui::LatencyInfo& latency) {
-  this->root_view = std::move(root_view);
-  this->location = ComputeEventLocation(event);
-  this->event = ui::WebInputEventTraits::Clone(event);
-  this->latency = latency;
-}
-
-RenderWidgetTargeter::TargetingRequest::TargetingRequest(
-    base::WeakPtr<RenderWidgetHostViewBase> root_view,
-    const gfx::PointF& location,
-    RenderWidgetHostAtPointCallback callback) {
-  this->root_view = std::move(root_view);
-  this->location = location;
-  this->callback = std::move(callback);
-}
+RenderWidgetTargeter::TargetingRequest::TargetingRequest() = default;
 
 RenderWidgetTargeter::TargetingRequest::TargetingRequest(
     TargetingRequest&& request) = default;
@@ -134,68 +128,6 @@
 
 RenderWidgetTargeter::TargetingRequest::~TargetingRequest() = default;
 
-void RenderWidgetTargeter::TargetingRequest::RunCallback(
-    RenderWidgetHostViewBase* target,
-    base::Optional<gfx::PointF> point) {
-  if (!callback.is_null()) {
-    std::move(callback).Run(target ? target->GetWeakPtr() : nullptr, point);
-  }
-}
-
-bool RenderWidgetTargeter::TargetingRequest::MergeEventIfPossible(
-    const blink::WebInputEvent& new_event) {
-  if (event && !blink::WebInputEvent::IsTouchEventType(new_event.GetType()) &&
-      !blink::WebInputEvent::IsGestureEventType(new_event.GetType()) &&
-      ui::CanCoalesce(new_event, *event.get())) {
-    ui::Coalesce(new_event, event.get());
-    return true;
-  }
-  return false;
-}
-
-void RenderWidgetTargeter::TargetingRequest::StartQueueingTimeTracker() {
-  tracker =
-      std::make_unique<TracingUmaTracker>("Event.AsyncTargeting.TimeInQueue");
-}
-
-void RenderWidgetTargeter::TargetingRequest::StopQueueingTimeTracker() {
-  if (tracker)
-    tracker->Stop();
-}
-
-bool RenderWidgetTargeter::TargetingRequest::IsWebInputEventRequest() const {
-  return !!event;
-}
-
-const blink::WebInputEvent& RenderWidgetTargeter::TargetingRequest::GetEvent()
-    const {
-  return *event.get();
-}
-
-RenderWidgetHostViewBase* RenderWidgetTargeter::TargetingRequest::GetRootView()
-    const {
-  return root_view.get();
-}
-
-gfx::PointF RenderWidgetTargeter::TargetingRequest::GetLocation() const {
-  return location;
-}
-
-viz::FrameSinkId
-RenderWidgetTargeter::TargetingRequest::GetExpectedFrameSinkId() const {
-  return expected_frame_sink_id;
-}
-
-void RenderWidgetTargeter::TargetingRequest::SetExpectedFrameSinkId(
-    const viz::FrameSinkId& id) {
-  expected_frame_sink_id = id;
-}
-
-const ui::LatencyInfo& RenderWidgetTargeter::TargetingRequest::GetLatency()
-    const {
-  return latency;
-}
-
 RenderWidgetTargeter::RenderWidgetTargeter(Delegate* delegate)
     : trace_id_(base::RandUint64()),
       is_viz_hit_testing_debug_enabled_(
@@ -220,48 +152,35 @@
            static_cast<const blink::WebGestureEvent&>(event).SourceDevice() ==
                blink::WebGestureDevice::kTouchpad)));
 
-  if (!requests_.empty()) {
-    auto& request = requests_.back();
-    if (request.MergeEventIfPossible(event))
-      return;
-  }
-
-  TargetingRequest request(root_view->GetWeakPtr(), event, latency);
-
-  ResolveTargetingRequest(std::move(request));
-}
-
-void RenderWidgetTargeter::FindTargetAndCallback(
-    RenderWidgetHostViewBase* root_view,
-    const gfx::PointF& point,
-    RenderWidgetHostAtPointCallback callback) {
-  TargetingRequest request(root_view->GetWeakPtr(), point, std::move(callback));
-
-  ResolveTargetingRequest(std::move(request));
-}
-
-void RenderWidgetTargeter::ResolveTargetingRequest(TargetingRequest request) {
   if (request_in_flight_) {
-    request.StartQueueingTimeTracker();
+    if (!requests_.empty()) {
+      auto& request = requests_.back();
+      if (MergeEventIfPossible(event, &request.event))
+        return;
+    }
+    TargetingRequest request;
+    request.root_view = root_view->GetWeakPtr();
+    request.event = ui::WebInputEventTraits::Clone(event);
+    request.latency = latency;
+    request.tracker =
+        std::make_unique<TracingUmaTracker>("Event.AsyncTargeting.TimeInQueue");
     requests_.push(std::move(request));
     return;
   }
 
-  RenderWidgetTargetResult result;
-  if (request.IsWebInputEventRequest()) {
-    result = delegate_->FindTargetSynchronously(request.GetRootView(),
-                                                request.GetEvent());
-  } else {
-    result = delegate_->FindTargetSynchronouslyAtLocation(
-        request.GetRootView(), request.GetLocation());
-  }
+  RenderWidgetTargetResult result =
+      delegate_->FindTargetSynchronously(root_view, event);
+
+  const gfx::PointF event_location = ComputeEventLocation(event);
+
   RenderWidgetHostViewBase* target = result.view;
+  auto* event_ptr = &event;
   async_depth_ = 0;
   if (result.should_query_view) {
     TRACE_EVENT_WITH_FLOW2(
         "viz,benchmark", "Event.Pipeline", TRACE_ID_GLOBAL(trace_id_),
         TRACE_EVENT_FLAG_FLOW_OUT, "step", "QueryClient(Start)",
-        "event_location", request.GetLocation().ToString());
+        "event_location", event_location.ToString());
 
     // TODO(kenrb, sadrul): When all event types support asynchronous hit
     // testing, we should be able to have FindTargetSynchronously return the
@@ -271,15 +190,17 @@
     // root_view and the original event location for the initial query.
     // Do not compare hit test results if we are forced to do async hit testing
     // by HitTestQuery.
-    QueryClient(std::move(request));
+    QueryClient(root_view, root_view, *event_ptr, latency, event_location,
+                nullptr, gfx::PointF());
   } else {
-    FoundTarget(target, result.target_location, result.latched_target,
-                &request);
+    FoundTarget(root_view, target, *event_ptr, latency, result.target_location,
+                result.latched_target, viz::FrameSinkId());
     // Verify the event targeting results from surface layer viz hit testing if
     // --use-viz-hit-test-surface-layer is enabled.
     if (result.should_verify_result && !target->IsRenderWidgetHostViewGuest()) {
-      request.SetExpectedFrameSinkId(target->GetFrameSinkId());
-      QueryAndVerifyClient(std::move(request));
+      QueryAndVerifyClient(root_view, root_view, *event_ptr, latency,
+                           event_location, nullptr, gfx::PointF(),
+                           target->GetFrameSinkId());
     }
   }
 }
@@ -293,14 +214,17 @@
 }
 
 void RenderWidgetTargeter::QueryClientInternal(
+    RenderWidgetHostViewBase* root_view,
     RenderWidgetHostViewBase* target,
+    const blink::WebInputEvent& event,
+    const ui::LatencyInfo& latency,
     const gfx::PointF& target_location,
     RenderWidgetHostViewBase* last_request_target,
     const gfx::PointF& last_target_location,
-    TargetingRequest request) {
+    const viz::FrameSinkId& expected_frame_sink_id) {
   // Async event targeting and verifying use two different queues, so they don't
   // block each other.
-  bool is_verifying = request.GetExpectedFrameSinkId().is_valid();
+  bool is_verifying = expected_frame_sink_id.is_valid();
   DCHECK((!is_verifying && !request_in_flight_) ||
          (is_verifying && !verify_request_in_flight_));
 
@@ -309,14 +233,15 @@
   // understand why this happens. https://crbug.com/859492.
   // We do not verify hit testing result under this circumstance.
   if (!target_client) {
-    FoundTarget(target, target_location, false, &request);
+    FoundTarget(root_view, target, event, latency, target_location, false,
+                viz::FrameSinkId());
     return;
   }
 
   if (is_verifying) {
-    verify_request_in_flight_ = std::move(request);
+    verify_request_in_flight_ = true;
   } else {
-    request_in_flight_ = std::move(request);
+    request_in_flight_ = true;
     async_depth_++;
   }
   TracingUmaTracker tracker("Event.AsyncTargeting.ResponseTime");
@@ -325,46 +250,67 @@
   hit_test_timeout.reset(new OneShotTimeoutMonitor(
       base::BindOnce(
           &RenderWidgetTargeter::AsyncHitTestTimedOut,
-          weak_ptr_factory_.GetWeakPtr(), target->GetWeakPtr(), target_location,
+          weak_ptr_factory_.GetWeakPtr(), root_view->GetWeakPtr(),
+          target->GetWeakPtr(), target_location,
           last_request_target ? last_request_target->GetWeakPtr() : nullptr,
-          last_target_location, is_verifying),
+          last_target_location, ui::WebInputEventTraits::Clone(event), latency,
+          expected_frame_sink_id),
       async_hit_test_timeout_delay_));
 
   TRACE_EVENT_WITH_FLOW2(
       "viz,benchmark", "Event.Pipeline", TRACE_ID_GLOBAL(trace_id_),
       TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT, "step",
-      "QueryClient", "event_location", request.GetLocation().ToString());
+      "QueryClient", "event", blink::WebInputEvent::GetName(event.GetType()));
 
   target_client->FrameSinkIdAt(
       target_location, trace_id_,
       base::BindOnce(
           &RenderWidgetTargeter::FoundFrameSinkId,
-          weak_ptr_factory_.GetWeakPtr(), target->GetWeakPtr(),
+          weak_ptr_factory_.GetWeakPtr(), root_view->GetWeakPtr(),
+          target->GetWeakPtr(), ui::WebInputEventTraits::Clone(event), latency,
           is_verifying ? ++last_verify_request_id_ : ++last_request_id_,
-          target_location, std::move(tracker), is_verifying));
+          target_location, std::move(tracker), expected_frame_sink_id));
 }
 
-void RenderWidgetTargeter::QueryClient(TargetingRequest request) {
-  auto* target = request.GetRootView();
-  auto target_location = request.GetLocation();
-  QueryClientInternal(target, target_location, nullptr, gfx::PointF(),
-                      std::move(request));
+void RenderWidgetTargeter::QueryClient(
+    RenderWidgetHostViewBase* root_view,
+    RenderWidgetHostViewBase* target,
+    const blink::WebInputEvent& event,
+    const ui::LatencyInfo& latency,
+    const gfx::PointF& target_location,
+    RenderWidgetHostViewBase* last_request_target,
+    const gfx::PointF& last_target_location) {
+  QueryClientInternal(root_view, target, event, latency, target_location,
+                      last_request_target, last_target_location,
+                      viz::FrameSinkId());
 }
 
-void RenderWidgetTargeter::QueryAndVerifyClient(TargetingRequest request) {
+void RenderWidgetTargeter::QueryAndVerifyClient(
+    RenderWidgetHostViewBase* root_view,
+    RenderWidgetHostViewBase* target,
+    const blink::WebInputEvent& event,
+    const ui::LatencyInfo& latency,
+    const gfx::PointF& target_location,
+    RenderWidgetHostViewBase* last_request_target,
+    const gfx::PointF& last_target_location,
+    const viz::FrameSinkId& expected_frame_sink_id) {
   if (verify_request_in_flight_) {
+    TargetingRequest request;
+    request.root_view = root_view->GetWeakPtr();
+    request.event = ui::WebInputEventTraits::Clone(event);
+    request.latency = latency;
+    request.expected_frame_sink_id = expected_frame_sink_id;
     verify_requests_.push(std::move(request));
     return;
   }
-  auto* target = request.GetRootView();
-  auto target_location = request.GetLocation();
-  QueryClientInternal(target, target_location, nullptr, gfx::PointF(),
-                      std::move(request));
+  QueryClientInternal(root_view, target, event, latency, target_location,
+                      last_request_target, last_target_location,
+                      expected_frame_sink_id);
 }
 
 void RenderWidgetTargeter::FlushEventQueue(bool is_verifying) {
   bool events_being_flushed = false;
-  base::Optional<TargetingRequest>& request_in_flight =
+  bool& request_in_flight =
       is_verifying ? verify_request_in_flight_ : request_in_flight_;
   auto* requests = is_verifying ? &verify_requests_ : &requests_;
   while (!request_in_flight && !requests->empty()) {
@@ -372,10 +318,11 @@
     requests->pop();
     // The root-view has gone away. Ignore this event, and try to process the
     // next event.
-    if (!request.GetRootView()) {
+    if (!request.root_view) {
       continue;
     }
-    request.StopQueueingTimeTracker();
+    if (request.tracker)
+      request.tracker->Stop();
     // Only notify the delegate once that the current event queue is being
     // flushed. Once all the events are flushed, notify the delegate again.
     if (!is_verifying && !events_being_flushed) {
@@ -383,9 +330,13 @@
       events_being_flushed = true;
     }
     if (is_verifying) {
-      QueryAndVerifyClient(std::move(request));
+      QueryAndVerifyClient(request.root_view.get(), request.root_view.get(),
+                           *request.event, request.latency,
+                           ComputeEventLocation(*request.event), nullptr,
+                           gfx::PointF(), request.expected_frame_sink_id);
     } else {
-      ResolveTargetingRequest(std::move(request));
+      FindTargetAndDispatch(request.root_view.get(), *request.event,
+                            request.latency);
     }
   }
   if (!is_verifying)
@@ -393,24 +344,25 @@
 }
 
 void RenderWidgetTargeter::FoundFrameSinkId(
+    base::WeakPtr<RenderWidgetHostViewBase> root_view,
     base::WeakPtr<RenderWidgetHostViewBase> target,
+    ui::WebScopedInputEvent event,
+    const ui::LatencyInfo& latency,
     uint32_t request_id,
     const gfx::PointF& target_location,
     TracingUmaTracker tracker,
-    const bool is_verification_request,
+    const viz::FrameSinkId& expected_frame_sink_id,
     const viz::FrameSinkId& frame_sink_id,
     const gfx::PointF& transformed_location) {
-  if (is_verification_request) {
+  if (expected_frame_sink_id.is_valid()) {
     tracker.Stop();
   } else {
     tracker.StopAndRecord();
   }
-
-  uint32_t last_id =
-      is_verification_request ? last_verify_request_id_ : last_request_id_;
-  bool in_flight = is_verification_request
-                       ? verify_request_in_flight_.has_value()
-                       : request_in_flight_.has_value();
+  uint32_t last_id = expected_frame_sink_id.is_valid() ? last_verify_request_id_
+                                                       : last_request_id_;
+  bool in_flight = expected_frame_sink_id.is_valid() ? verify_request_in_flight_
+                                                     : request_in_flight_;
   if (request_id != last_id || !in_flight) {
     // This is a response to a request that already timed out, so the event
     // should have already been dispatched. Mark the renderer as responsive
@@ -419,20 +371,15 @@
     return;
   }
 
-  TargetingRequest request = is_verification_request
-                                 ? std::move(verify_request_in_flight_.value())
-                                 : std::move(request_in_flight_.value());
-
-  if (request.GetExpectedFrameSinkId().is_valid()) {
-    verify_request_in_flight_.reset();
+  if (expected_frame_sink_id.is_valid()) {
+    verify_request_in_flight_ = false;
     async_verify_hit_test_timeout_.reset(nullptr);
   } else {
-    request_in_flight_.reset();
+    request_in_flight_ = false;
     async_hit_test_timeout_.reset(nullptr);
 
-    if (is_viz_hit_testing_debug_enabled_ && request.IsWebInputEventRequest() &&
-        request.GetEvent().GetType() ==
-            blink::WebInputEvent::Type::kMouseDown) {
+    if (is_viz_hit_testing_debug_enabled_ &&
+        event->GetType() == blink::WebInputEvent::Type::kMouseDown) {
       hit_test_async_queried_debug_queue_.push_back(target->GetFrameSinkId());
     }
   }
@@ -453,45 +400,46 @@
                              TRACE_EVENT_FLAG_FLOW_IN, "step", "FoundTarget");
     }
 
-    FoundTarget(view, transformed_location, false, &request);
+    FoundTarget(root_view.get(), view, *event, latency, transformed_location,
+                false, expected_frame_sink_id);
   } else {
-    QueryClientInternal(view, transformed_location, target.get(),
-                        target_location, std::move(request));
+    QueryClientInternal(root_view.get(), view, *event, latency,
+                        transformed_location, target.get(), target_location,
+                        expected_frame_sink_id);
   }
 }
 
 void RenderWidgetTargeter::FoundTarget(
+    RenderWidgetHostViewBase* root_view,
     RenderWidgetHostViewBase* target,
+    const blink::WebInputEvent& event,
+    const ui::LatencyInfo& latency,
     const base::Optional<gfx::PointF>& target_location,
     bool latched_target,
-    TargetingRequest* request) {
-  DCHECK(request);
-
+    const viz::FrameSinkId& expected_frame_sink_id) {
   if (SiteIsolationPolicy::UseDedicatedProcessesForAllSites() &&
-      !latched_target && !request->GetExpectedFrameSinkId().is_valid()) {
+      !latched_target && !expected_frame_sink_id.is_valid()) {
     UMA_HISTOGRAM_COUNTS_100("Event.AsyncTargeting.AsyncClientDepth",
                              async_depth_);
   }
 
   // RenderWidgetHostViewMac can be deleted asynchronously, in which case the
   // View will be valid but there will no longer be a RenderWidgetHostImpl.
-  if (!request->GetRootView() || !request->GetRootView()->GetRenderWidgetHost())
+  if (!root_view || !root_view->GetRenderWidgetHost())
     return;
 
   if (is_viz_hit_testing_debug_enabled_ &&
       !hit_test_async_queried_debug_queue_.empty()) {
     GetHostFrameSinkManager()->SetHitTestAsyncQueriedDebugRegions(
-        request->GetRootView()->GetRootFrameSinkId(),
-        hit_test_async_queried_debug_queue_);
+        root_view->GetRootFrameSinkId(), hit_test_async_queried_debug_queue_);
     hit_test_async_queried_debug_queue_.clear();
   }
 
   if (features::IsVizHitTestingSurfaceLayerEnabled() &&
-      request->GetExpectedFrameSinkId().is_valid()) {
+      expected_frame_sink_id.is_valid()) {
     static const char* kResultsMatchHistogramName =
         "Event.VizHitTestSurfaceLayer.ResultsMatch";
-    bool results_match =
-        target->GetFrameSinkId() == request->GetExpectedFrameSinkId();
+    bool results_match = target->GetFrameSinkId() == expected_frame_sink_id;
     HitTestResultsMatch match_result =
         HitTestResultsMatch::kHitTestResultChanged;
     if (results_match) {
@@ -500,17 +448,10 @@
       // If the results do not match, it is possible that the hit test data
       // changed during verification. We do synchronous hit test again to make
       // sure the result is reliable.
-      RenderWidgetTargetResult result;
-      if (request->IsWebInputEventRequest()) {
-        result = delegate_->FindTargetSynchronously(request->GetRootView(),
-                                                    request->GetEvent());
-      } else {
-        result = delegate_->FindTargetSynchronouslyAtLocation(
-            request->GetRootView(), request->GetLocation());
-      }
-
+      RenderWidgetTargetResult result =
+          delegate_->FindTargetSynchronously(root_view, event);
       if (!result.should_query_view && result.view &&
-          request->GetExpectedFrameSinkId() == result.view->GetFrameSinkId()) {
+          expected_frame_sink_id == result.view->GetFrameSinkId()) {
         // If the result did not change, it is likely that viz hit test finds
         // the wrong target.
         match_result = HitTestResultsMatch::kDoNotMatch;
@@ -524,53 +465,48 @@
     FlushEventQueue(true);
     return;
   }
-  if (request->IsWebInputEventRequest()) {
-    delegate_->DispatchEventToTarget(request->GetRootView(), target,
-                                     request->GetEvent(), request->GetLatency(),
-                                     target_location);
-  } else {
-    request->RunCallback(target, target_location);
-  }
+  delegate_->DispatchEventToTarget(root_view, target, event, latency,
+                                   target_location);
   FlushEventQueue(false);
 }
 
 void RenderWidgetTargeter::AsyncHitTestTimedOut(
+    base::WeakPtr<RenderWidgetHostViewBase> current_request_root_view,
     base::WeakPtr<RenderWidgetHostViewBase> current_request_target,
     const gfx::PointF& current_target_location,
     base::WeakPtr<RenderWidgetHostViewBase> last_request_target,
     const gfx::PointF& last_target_location,
-    const bool is_verification_request) {
+    ui::WebScopedInputEvent event,
+    const ui::LatencyInfo& latency,
+    const viz::FrameSinkId& expected_frame_sink_id) {
   DCHECK(request_in_flight_ || verify_request_in_flight_);
-
-  TargetingRequest request = is_verification_request
-                                 ? std::move(verify_request_in_flight_.value())
-                                 : std::move(request_in_flight_.value());
-
   // If we time out during a verification, we early out to avoid dispatching
   // event to root frame.
-  if (request.GetExpectedFrameSinkId().is_valid()) {
-    verify_request_in_flight_.reset();
+  if (expected_frame_sink_id.is_valid()) {
+    verify_request_in_flight_ = false;
     return;
   } else {
-    request_in_flight_.reset();
+    request_in_flight_ = false;
   }
 
-  if (!request.GetRootView())
+  if (!current_request_root_view)
     return;
 
   // Mark view as unresponsive so further events will not be sent to it.
   if (current_request_target)
     unresponsive_views_.insert(current_request_target.get());
 
-  if (request.GetRootView() == current_request_target.get()) {
+  if (current_request_root_view.get() == current_request_target.get()) {
     // When a request to the top-level frame times out then the event gets
     // sent there anyway. It will trigger the hung renderer dialog if the
     // renderer fails to process it.
-    FoundTarget(current_request_target.get(), current_target_location, false,
-                &request);
+    FoundTarget(current_request_root_view.get(),
+                current_request_root_view.get(), *event, latency,
+                current_target_location, false, viz::FrameSinkId());
   } else {
-    FoundTarget(last_request_target.get(), last_target_location, false,
-                &request);
+    FoundTarget(current_request_root_view.get(), last_request_target.get(),
+                *event, latency, last_target_location, false,
+                viz::FrameSinkId());
   }
 }
 
diff --git a/content/browser/renderer_host/render_widget_targeter.h b/content/browser/renderer_host/render_widget_targeter.h
index 866dd3f1..d6b9834 100644
--- a/content/browser/renderer_host/render_widget_targeter.h
+++ b/content/browser/renderer_host/render_widget_targeter.h
@@ -6,12 +6,12 @@
 #define CONTENT_BROWSER_RENDERER_HOST_RENDER_WIDGET_TARGETER_H_
 
 #include <queue>
+#include <unordered_set>
 
 #include "base/memory/weak_ptr.h"
 #include "base/optional.h"
 #include "base/time/time.h"
 #include "components/viz/common/surfaces/frame_sink_id.h"
-#include "content/browser/renderer_host/render_widget_host_view_base.h"
 #include "content/common/content_constants_internal.h"
 #include "content/common/content_export.h"
 #include "ui/events/blink/web_input_event_traits.h"
@@ -60,18 +60,10 @@
 
 class RenderWidgetTargeter {
  public:
-  using RenderWidgetHostAtPointCallback =
-      base::OnceCallback<void(base::WeakPtr<RenderWidgetHostViewBase>,
-                              base::Optional<gfx::PointF>)>;
-
   class Delegate {
    public:
     virtual ~Delegate() {}
 
-    virtual RenderWidgetTargetResult FindTargetSynchronouslyAtLocation(
-        RenderWidgetHostViewBase* root_view,
-        const gfx::PointF& location) = 0;
-
     virtual RenderWidgetTargetResult FindTargetSynchronously(
         RenderWidgetHostViewBase* root_view,
         const blink::WebInputEvent& event) = 0;
@@ -105,13 +97,6 @@
                              const blink::WebInputEvent& event,
                              const ui::LatencyInfo& latency);
 
-  // Finds the appropriate target inside |root_view| for |point|, and passes the
-  // target along with the transformed coordinates of the point with respect to
-  // the target's coordinates.
-  void FindTargetAndCallback(RenderWidgetHostViewBase* root_view,
-                             const gfx::PointF& point,
-                             RenderWidgetHostAtPointCallback callback);
-
   void ViewWillBeDestroyed(RenderWidgetHostViewBase* view);
 
   bool HasEventsPendingDispatch() const;
@@ -122,65 +107,9 @@
   }
 
   size_t num_requests_in_queue_for_testing() { return requests_.size(); }
-  bool is_request_in_flight_for_testing() {
-    return request_in_flight_.has_value();
-  }
+  bool is_request_in_flight_for_testing() { return request_in_flight_; }
 
  private:
-  class TargetingRequest {
-   public:
-    TargetingRequest(base::WeakPtr<RenderWidgetHostViewBase>,
-                     const blink::WebInputEvent&,
-                     const ui::LatencyInfo&);
-    TargetingRequest(base::WeakPtr<RenderWidgetHostViewBase>,
-                     const gfx::PointF&,
-                     RenderWidgetHostAtPointCallback);
-    TargetingRequest(TargetingRequest&& request);
-    TargetingRequest& operator=(TargetingRequest&& other);
-    ~TargetingRequest();
-
-    void RunCallback(RenderWidgetHostViewBase* target,
-                     base::Optional<gfx::PointF> point);
-
-    bool MergeEventIfPossible(const blink::WebInputEvent& event);
-    bool IsWebInputEventRequest() const;
-    const blink::WebInputEvent& GetEvent() const;
-    RenderWidgetHostViewBase* GetRootView() const;
-    gfx::PointF GetLocation() const;
-    const ui::LatencyInfo& GetLatency() const;
-
-    // Queued TragetingRequest
-    void StartQueueingTimeTracker();
-    void StopQueueingTimeTracker();
-
-    // Verification TargetingRequest
-    viz::FrameSinkId GetExpectedFrameSinkId() const;
-    void SetExpectedFrameSinkId(const viz::FrameSinkId& id);
-
-   private:
-    base::WeakPtr<RenderWidgetHostViewBase> root_view;
-
-    RenderWidgetHostAtPointCallback callback;
-
-    // |location| is in the coordinate space of |root_view| which is
-    // either set directly when event is null or calculated from the event.
-    gfx::PointF location;
-    // |event| if set is in the coordinate space of |root_view|.
-    ui::WebScopedInputEvent event;
-    ui::LatencyInfo latency;
-
-    // |expected_frame_sink_id| is only valid if the request is for
-    // verification.
-    viz::FrameSinkId expected_frame_sink_id;
-
-    // To track how long the request has been queued.
-    std::unique_ptr<TracingUmaTracker> tracker;
-
-    DISALLOW_COPY_AND_ASSIGN(TargetingRequest);
-  };
-
-  void ResolveTargetingRequest(TargetingRequest);
-
   // Attempts to target and dispatch all events in the queue. It stops if it has
   // to query a client, or if the queue becomes empty.
   void FlushEventQueue(bool is_verifying);
@@ -198,17 +127,33 @@
   // correctly.
   // TODO(sunxd): Remove |expected_frame_sink_id| after verifying synchronous
   // hit testing correctness. See https://crbug.com/871996.
-  void QueryClientInternal(RenderWidgetHostViewBase* target,
+  void QueryClientInternal(RenderWidgetHostViewBase* root_view,
+                           RenderWidgetHostViewBase* target,
+                           const blink::WebInputEvent& event,
+                           const ui::LatencyInfo& latency,
                            const gfx::PointF& target_location,
                            RenderWidgetHostViewBase* last_request_target,
                            const gfx::PointF& last_target_location,
-                           TargetingRequest request);
+                           const viz::FrameSinkId& expected_frame_sink_id);
 
-  void QueryClient(TargetingRequest request);
+  void QueryClient(RenderWidgetHostViewBase* root_view,
+                   RenderWidgetHostViewBase* target,
+                   const blink::WebInputEvent& event,
+                   const ui::LatencyInfo& latency,
+                   const gfx::PointF& target_location,
+                   RenderWidgetHostViewBase* last_request_target,
+                   const gfx::PointF& last_target_location);
 
-  void QueryAndVerifyClient(TargetingRequest request);
+  void QueryAndVerifyClient(RenderWidgetHostViewBase* root_view,
+                            RenderWidgetHostViewBase* target,
+                            const blink::WebInputEvent& event,
+                            const ui::LatencyInfo& latency,
+                            const gfx::PointF& target_location,
+                            RenderWidgetHostViewBase* last_request_target,
+                            const gfx::PointF& last_target_location,
+                            const viz::FrameSinkId& expected_frame_sink_id);
 
-  // |target_location|, if
+  // |event| is in the coordinate space of |root_view|. |target_location|, if
   // set, is the location in |target|'s coordinate space.
   // |target| is the current target that will be queried using its
   // InputTargetClient interface.
@@ -217,44 +162,66 @@
   // that new target's coordinate space.
   // |expected_frame_sink_id| is the expected hit test result based on
   // synchronous event targeting with cc generated data.
-  void FoundFrameSinkId(base::WeakPtr<RenderWidgetHostViewBase> target,
+  void FoundFrameSinkId(base::WeakPtr<RenderWidgetHostViewBase> root_view,
+                        base::WeakPtr<RenderWidgetHostViewBase> target,
+                        ui::WebScopedInputEvent event,
+                        const ui::LatencyInfo& latency,
                         uint32_t request_id,
                         const gfx::PointF& target_location,
                         TracingUmaTracker tracker,
-                        const bool is_verification_request,
+                        const viz::FrameSinkId& expected_frame_sink_id,
                         const viz::FrameSinkId& frame_sink_id,
                         const gfx::PointF& transformed_location);
 
-  // |target_location|, if
+  // |event| is in the coordinate space of |root_view|. |target_location|, if
   // set, is the location in |target|'s coordinate space. If |latched_target| is
   // false, we explicitly did hit-testing for this event, instead of using a
   // known target.
-  void FoundTarget(RenderWidgetHostViewBase* target,
+  void FoundTarget(RenderWidgetHostViewBase* root_view,
+                   RenderWidgetHostViewBase* target,
+                   const blink::WebInputEvent& event,
+                   const ui::LatencyInfo& latency,
                    const base::Optional<gfx::PointF>& target_location,
                    bool latched_target,
-                   TargetingRequest* request);
+                   const viz::FrameSinkId& expected_frame_sink_id);
 
   // Callback when the hit testing timer fires, to resume event processing
   // without further waiting for a response to the last targeting request.
   void AsyncHitTestTimedOut(
+      base::WeakPtr<RenderWidgetHostViewBase> current_request_root_view,
       base::WeakPtr<RenderWidgetHostViewBase> current_request_target,
       const gfx::PointF& current_target_location,
       base::WeakPtr<RenderWidgetHostViewBase> last_request_target,
       const gfx::PointF& last_target_location,
-      const bool is_verification_request);
+      ui::WebScopedInputEvent event,
+      const ui::LatencyInfo& latency,
+      const viz::FrameSinkId& expected_frame_sink_id);
 
   base::TimeDelta async_hit_test_timeout_delay() {
     return async_hit_test_timeout_delay_;
   }
 
-  base::Optional<TargetingRequest> request_in_flight_;
+  struct TargetingRequest {
+    TargetingRequest();
+    TargetingRequest(TargetingRequest&& request);
+    TargetingRequest& operator=(TargetingRequest&& other);
+    ~TargetingRequest();
+
+    base::WeakPtr<RenderWidgetHostViewBase> root_view;
+    ui::WebScopedInputEvent event;
+    ui::LatencyInfo latency;
+    viz::FrameSinkId expected_frame_sink_id;
+    std::unique_ptr<TracingUmaTracker> tracker;
+  };
+
+  bool request_in_flight_ = false;
   uint32_t last_request_id_ = 0;
   std::queue<TargetingRequest> requests_;
 
   // With viz-hit-testing-surface-layer being enabled, we do async hit testing
   // for already dispatched events for verification. These verification requests
   // should not block normal hit testing requests.
-  base::Optional<TargetingRequest> verify_request_in_flight_;
+  bool verify_request_in_flight_ = false;
   uint32_t last_verify_request_id_ = 0;
   std::queue<TargetingRequest> verify_requests_;
 
diff --git a/content/browser/web_contents/web_contents_view_aura.cc b/content/browser/web_contents/web_contents_view_aura.cc
index 49efaee4..ee5760e 100644
--- a/content/browser/web_contents/web_contents_view_aura.cc
+++ b/content/browser/web_contents/web_contents_view_aura.cc
@@ -1232,22 +1232,25 @@
 ////////////////////////////////////////////////////////////////////////////////
 // WebContentsViewAura, aura::client::DragDropDelegate implementation:
 
-void WebContentsViewAura::DragEnteredCallback(
-    const ui::DropTargetEvent& event,
-    std::unique_ptr<DropData> drop_data,
-    base::WeakPtr<RenderWidgetHostViewBase> target,
-    base::Optional<gfx::PointF> transformed_pt) {
-  if (!target)
-    return;
+void WebContentsViewAura::OnDragEntered(const ui::DropTargetEvent& event) {
+#if defined(OS_WIN)
+  async_drop_navigation_observer_.reset();
+#endif
+
+  gfx::PointF transformed_pt;
   RenderWidgetHostImpl* target_rwh =
-      RenderWidgetHostImpl::From(target->GetRenderWidgetHost());
+      web_contents_->GetInputEventRouter()->GetRenderWidgetHostAtPoint(
+          web_contents_->GetRenderViewHost()->GetWidget()->GetView(),
+          event.location_f(), &transformed_pt);
+
   if (!IsValidDragTarget(target_rwh))
     return;
 
   current_rwh_for_drag_ = target_rwh->GetWeakPtr();
   current_rvh_for_drag_ =
       GetRenderViewHostID(web_contents_->GetRenderViewHost());
-  current_drop_data_.reset(drop_data.release());
+  current_drop_data_.reset(new DropData());
+  PrepareDropData(current_drop_data_.get(), event.data());
   current_rwh_for_drag_->FilterDropData(current_drop_data_.get());
 
   blink::WebDragOperationsMask op = ConvertToWeb(event.source_operations());
@@ -1263,50 +1266,26 @@
   if (drag_dest_delegate_)
     drag_dest_delegate_->DragInitialize(web_contents_);
 
-  DCHECK(transformed_pt.has_value());
   gfx::PointF screen_pt(display::Screen::GetScreen()->GetCursorScreenPoint());
   current_rwh_for_drag_->DragTargetDragEnter(
-      *current_drop_data_, transformed_pt.value(), screen_pt, op,
+      *current_drop_data_, transformed_pt, screen_pt, op,
       ui::EventFlagsToWebEventModifiers(event.flags()));
 
   if (drag_dest_delegate_) {
+    drag_dest_delegate_->OnReceiveDragData(event.data());
     drag_dest_delegate_->OnDragEnter();
   }
 }
 
-void WebContentsViewAura::OnDragEntered(const ui::DropTargetEvent& event) {
-#if defined(OS_WIN)
-  async_drop_navigation_observer_.reset();
-#endif
-
-  std::unique_ptr<DropData> drop_data = std::make_unique<DropData>();
-  // Calling this here as event.data might become invalid inside the callback.
-  PrepareDropData(drop_data.get(), event.data());
-
-  if (drag_dest_delegate_) {
-    drag_dest_delegate_->OnReceiveDragData(event.data());
-  }
-
-  web_contents_->GetInputEventRouter()
-      ->GetRenderWidgetHostAtPointAsynchronously(
-          web_contents_->GetRenderViewHost()->GetWidget()->GetView(),
-          event.location_f(),
-          base::BindOnce(&WebContentsViewAura::DragEnteredCallback,
-                         weak_ptr_factory_.GetWeakPtr(), event,
-                         std::move(drop_data)));
-}
-
-void WebContentsViewAura::DragUpdatedCallback(
-    const ui::DropTargetEvent& event,
-    std::unique_ptr<DropData> drop_data,
-    base::WeakPtr<RenderWidgetHostViewBase> target,
-    base::Optional<gfx::PointF> transformed_pt) {
-  if (!target)
-    return;
+int WebContentsViewAura::OnDragUpdated(const ui::DropTargetEvent& event) {
+  gfx::PointF transformed_pt;
   RenderWidgetHostImpl* target_rwh =
-      RenderWidgetHostImpl::From(target->GetRenderWidgetHost());
+      web_contents_->GetInputEventRouter()->GetRenderWidgetHostAtPoint(
+          web_contents_->GetRenderViewHost()->GetWidget()->GetView(),
+          event.location_f(), &transformed_pt);
+
   if (!IsValidDragTarget(target_rwh))
-    return;
+    return ui::DragDropTypes::DRAG_NONE;
 
   aura::Window* root_window = GetNativeView()->GetRootWindow();
   aura::client::ScreenPositionClient* screen_position_client =
@@ -1328,35 +1307,20 @@
       current_rwh_for_drag_->DragTargetDragLeave(transformed_leave_point,
                                                  screen_pt);
     }
-    DragEnteredCallback(event, std::move(drop_data), target, transformed_pt);
+    OnDragEntered(event);
   }
 
-  if (!current_drop_data_) {
-    return;
-  }
+  if (!current_drop_data_)
+    return ui::DragDropTypes::DRAG_NONE;
 
-  DCHECK(transformed_pt.has_value());
   blink::WebDragOperationsMask op = ConvertToWeb(event.source_operations());
   target_rwh->DragTargetDragOver(
-      transformed_pt.value(), screen_pt, op,
+      transformed_pt, screen_pt, op,
       ui::EventFlagsToWebEventModifiers(event.flags()));
 
   if (drag_dest_delegate_)
     drag_dest_delegate_->OnDragOver();
-}
 
-int WebContentsViewAura::OnDragUpdated(const ui::DropTargetEvent& event) {
-  std::unique_ptr<DropData> drop_data = std::make_unique<DropData>();
-  // Calling this here as event.data might become invalid inside the callback.
-  PrepareDropData(drop_data.get(), event.data());
-
-  web_contents_->GetInputEventRouter()
-      ->GetRenderWidgetHostAtPointAsynchronously(
-          web_contents_->GetRenderViewHost()->GetWidget()->GetView(),
-          event.location_f(),
-          base::BindOnce(&WebContentsViewAura::DragUpdatedCallback,
-                         weak_ptr_factory_.GetWeakPtr(), event,
-                         std::move(drop_data)));
   return ConvertFromWeb(current_drag_op_);
 }
 
@@ -1378,31 +1342,25 @@
   current_drop_data_.reset();
 }
 
-void WebContentsViewAura::PerformDropCallback(
-    const ui::DropTargetEvent& event,
-    std::unique_ptr<DropData> drop_data,
-    base::WeakPtr<RenderWidgetHostViewBase> target,
-    base::Optional<gfx::PointF> transformed_pt) {
-  if (!target)
-    return;
+int WebContentsViewAura::OnPerformDrop(const ui::DropTargetEvent& event) {
+  gfx::PointF transformed_pt;
   RenderWidgetHostImpl* target_rwh =
-      RenderWidgetHostImpl::From(target->GetRenderWidgetHost());
-  if (!IsValidDragTarget(target_rwh))
-    return;
+      web_contents_->GetInputEventRouter()->GetRenderWidgetHostAtPoint(
+          web_contents_->GetRenderViewHost()->GetWidget()->GetView(),
+          event.location_f(), &transformed_pt);
 
-  DCHECK(transformed_pt.has_value());
+  if (!IsValidDragTarget(target_rwh))
+    return ui::DragDropTypes::DRAG_NONE;
 
   gfx::PointF screen_pt(display::Screen::GetScreen()->GetCursorScreenPoint());
   if (target_rwh != current_rwh_for_drag_.get()) {
     if (current_rwh_for_drag_)
-      current_rwh_for_drag_->DragTargetDragLeave(transformed_pt.value(),
-                                                 screen_pt);
-    DragEnteredCallback(event, std::move(drop_data), target, transformed_pt);
+      current_rwh_for_drag_->DragTargetDragLeave(transformed_pt, screen_pt);
+    OnDragEntered(event);
   }
 
-  if (!current_drop_data_) {
-    return;
-  }
+  if (!current_drop_data_)
+    return ui::DragDropTypes::DRAG_NONE;
 
   const int key_modifiers = ui::EventFlagsToWebEventModifiers(event.flags());
 #if defined(OS_WIN)
@@ -1428,29 +1386,16 @@
       async_drop_navigation_observer_ =
           std::make_unique<AsyncDropNavigationObserver>(
               web_contents_, std::move(current_drop_data_), target_rwh,
-              transformed_pt.value(), screen_pt, key_modifiers);
-      return;
+              transformed_pt, screen_pt, key_modifiers);
+
+      return ConvertFromWeb(current_drag_op_);
     }
   }
 
 #endif
-  CompleteDrop(target_rwh, *current_drop_data_, transformed_pt.value(),
-               screen_pt, key_modifiers);
+  CompleteDrop(target_rwh, *current_drop_data_, transformed_pt, screen_pt,
+               key_modifiers);
   current_drop_data_.reset();
-}
-
-int WebContentsViewAura::OnPerformDrop(const ui::DropTargetEvent& event) {
-  std::unique_ptr<DropData> drop_data = std::make_unique<DropData>();
-  // Calling this here as event.data might become invalid inside the callback.
-  PrepareDropData(drop_data.get(), event.data());
-
-  web_contents_->GetInputEventRouter()
-      ->GetRenderWidgetHostAtPointAsynchronously(
-          web_contents_->GetRenderViewHost()->GetWidget()->GetView(),
-          event.location_f(),
-          base::BindOnce(&WebContentsViewAura::PerformDropCallback,
-                         weak_ptr_factory_.GetWeakPtr(), event,
-                         std::move(drop_data)));
   return ConvertFromWeb(current_drag_op_);
 }
 
diff --git a/content/browser/web_contents/web_contents_view_aura.h b/content/browser/web_contents/web_contents_view_aura.h
index 7037ca5..46ca496 100644
--- a/content/browser/web_contents/web_contents_view_aura.h
+++ b/content/browser/web_contents/web_contents_view_aura.h
@@ -73,7 +73,6 @@
   FRIEND_TEST_ALL_PREFIXES(WebContentsViewAuraTest,
                            DragDropVirtualFilesOriginateFromRenderer);
   FRIEND_TEST_ALL_PREFIXES(WebContentsViewAuraTest, DragDropUrlData);
-  FRIEND_TEST_ALL_PREFIXES(WebContentsViewAuraTest, DragDropOnOopif);
 
   class WindowObserver;
 
@@ -194,19 +193,6 @@
   void OnDragExited() override;
   int OnPerformDrop(const ui::DropTargetEvent& event) override;
 
-  void DragEnteredCallback(const ui::DropTargetEvent& event,
-                           std::unique_ptr<DropData> drop_data,
-                           base::WeakPtr<RenderWidgetHostViewBase> target,
-                           base::Optional<gfx::PointF> transformed_pt);
-  void DragUpdatedCallback(const ui::DropTargetEvent& event,
-                           std::unique_ptr<DropData> drop_data,
-                           base::WeakPtr<RenderWidgetHostViewBase> target,
-                           base::Optional<gfx::PointF> transformed_pt);
-  void PerformDropCallback(const ui::DropTargetEvent& event,
-                           std::unique_ptr<DropData> drop_data,
-                           base::WeakPtr<RenderWidgetHostViewBase> target,
-                           base::Optional<gfx::PointF> transformed_pt);
-
   // Completes a drop operation by communicating the drop data to the renderer
   // process.
   void CompleteDrop(RenderWidgetHostImpl* target_rwh,
@@ -284,9 +270,11 @@
 
   bool init_rwhv_with_null_parent_for_testing_;
 
-  // Used to ensure the drag and drop callbacks bound to this
+#if defined(OS_WIN)
+  // Used to ensure that the virtual files retrieval callback bound to this
   // object is canceled when this object is destroyed.
   base::WeakPtrFactory<WebContentsViewAura> weak_ptr_factory_{this};
+#endif
 
   DISALLOW_COPY_AND_ASSIGN(WebContentsViewAura);
 };
diff --git a/content/browser/web_contents/web_contents_view_aura_browsertest.cc b/content/browser/web_contents/web_contents_view_aura_browsertest.cc
index ed00327..fd229b8 100644
--- a/content/browser/web_contents/web_contents_view_aura_browsertest.cc
+++ b/content/browser/web_contents/web_contents_view_aura_browsertest.cc
@@ -41,12 +41,9 @@
 #include "content/public/test/test_renderer_host.h"
 #include "content/public/test/test_utils.h"
 #include "content/shell/browser/shell.h"
-#include "net/dns/mock_host_resolver.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_tree_host.h"
-#include "ui/base/dragdrop/drop_target_event.h"
-#include "ui/base/dragdrop/os_exchange_data.h"
 #include "ui/compositor/scoped_animation_duration_scale_mode.h"
 #include "ui/events/base_event_utils.h"
 #include "ui/events/event_sink.h"
@@ -90,28 +87,11 @@
         shell()->web_contents());
   }
 
-  void SetUpOnMainThread() override {
-    // Setup the server to allow serving separate sites, so we can perform
-    // cross-process navigation.
-    host_resolver()->AddRule("*", "127.0.0.1");
-  }
-
   void SetUpCommandLine(base::CommandLine* cmd) override {
     cmd->AppendSwitchASCII(switches::kTouchEventFeatureDetection,
                            switches::kTouchEventFeatureDetectionEnabled);
   }
 
-  void OnDropComplete(RenderWidgetHostImpl* target_rwh,
-                      const DropData& drop_data,
-                      const gfx::PointF& client_pt,
-                      const gfx::PointF& screen_pt,
-                      int key_modifiers,
-                      bool drop_allowed) {
-    // Cache the data for verification.
-    drop_target_widget_ = target_rwh;
-    std::move(async_drop_closure_).Run();
-  }
-
   void TestOverscrollNavigation(bool touch_handler) {
     ASSERT_NO_FATAL_FAILURE(StartTestWithPage("/overscroll_navigation.html"));
     WebContentsImpl* web_contents =
@@ -251,11 +231,6 @@
     ContentBrowserTest::PostRunTestOnMainThread();
   }
 
-  RenderWidgetHostImpl* drop_target_widget_;
-
-  // A closure indicating that async drop operation has completed.
-  base::OnceClosure async_drop_closure_;
-
  private:
   std::unique_ptr<RenderFrameSubmissionObserver> frame_observer_;
 
@@ -512,68 +487,6 @@
   window->AddChild(shell()->web_contents()->GetContentNativeView());
 }
 
-IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, DragDropOnOopif) {
-  ASSERT_TRUE(embedded_test_server()->Start());
-  GURL url = embedded_test_server()->GetURL(
-      "a.com", "/overlapping_cross_site_iframe.html");
-  EXPECT_TRUE(NavigateToURL(shell(), url));
-
-  WebContentsImpl* contents =
-      static_cast<WebContentsImpl*>(shell()->web_contents());
-  WebContentsViewAura* view =
-      static_cast<WebContentsViewAura*>(contents->GetView());
-  ui::OSExchangeData data;
-
-  // Drop on the root frame.
-  {
-    view->RegisterDropCallbackForTesting(base::BindOnce(
-        &WebContentsViewAuraTest::OnDropComplete, base::Unretained(this)));
-    base::RunLoop run_loop;
-    async_drop_closure_ = run_loop.QuitClosure();
-
-    gfx::PointF point = {10, 10};
-    ui::DropTargetEvent event(data, point, point, ui::DragDropTypes::DRAG_COPY);
-    view->OnDragEntered(event);
-    view->OnPerformDrop(event);
-
-    run_loop.Run();
-
-    EXPECT_EQ(drop_target_widget_,
-              RenderWidgetHostImpl::From(contents->GetFrameTree()
-                                             ->root()
-                                             ->current_frame_host()
-                                             ->GetRenderWidgetHost()));
-  }
-  // Drop on the element in the root frame overlapping the embeded OOPIF.
-  {
-    view->RegisterDropCallbackForTesting(base::BindOnce(
-        &WebContentsViewAuraTest::OnDropComplete, base::Unretained(this)));
-    base::RunLoop run_loop;
-    async_drop_closure_ = run_loop.QuitClosure();
-
-    int left =
-        EvalJs(contents,
-               "document.getElementById('target').getBoundingClientRect().left")
-            .ExtractInt();
-    int top =
-        EvalJs(contents,
-               "document.getElementById('target').getBoundingClientRect().top")
-            .ExtractInt();
-    gfx::PointF point = {left + 5, top + 5};
-    ui::DropTargetEvent event(data, point, point, ui::DragDropTypes::DRAG_COPY);
-    view->OnDragEntered(event);
-    view->OnPerformDrop(event);
-
-    run_loop.Run();
-
-    EXPECT_EQ(drop_target_widget_,
-              RenderWidgetHostImpl::From(contents->GetFrameTree()
-                                             ->root()
-                                             ->current_frame_host()
-                                             ->GetRenderWidgetHost()));
-  }
-}
-
 IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, ContentWindowClose) {
   ASSERT_NO_FATAL_FAILURE(StartTestWithPage("/overscroll_navigation.html"));
 
diff --git a/content/common/cursors/webcursor.cc b/content/common/cursors/webcursor.cc
index 0023114..3d7c97a 100644
--- a/content/common/cursors/webcursor.cc
+++ b/content/common/cursors/webcursor.cc
@@ -20,8 +20,13 @@
 }
 
 WebCursor::WebCursor(const WebCursor& other) {
-  SetInfo(other.info_);
-  CopyPlatformData(other);
+  CopyAllData(other);
+}
+
+WebCursor& WebCursor::operator=(const WebCursor& other) {
+  CleanupPlatformData();
+  CopyAllData(other);
+  return *this;
 }
 
 bool WebCursor::SetInfo(const CursorInfo& info) {
@@ -60,4 +65,9 @@
   return !(*this == other);
 }
 
+void WebCursor::CopyAllData(const WebCursor& other) {
+  SetInfo(other.info_);
+  CopyPlatformData(other);
+}
+
 }  // namespace content
diff --git a/content/common/cursors/webcursor.h b/content/common/cursors/webcursor.h
index dfdef03..1670794 100644
--- a/content/common/cursors/webcursor.h
+++ b/content/common/cursors/webcursor.h
@@ -30,6 +30,7 @@
   WebCursor() = default;
   explicit WebCursor(const CursorInfo& info);
   explicit WebCursor(const WebCursor& other);
+  WebCursor& operator=(const WebCursor& other);
   ~WebCursor();
 
   const CursorInfo& info() const { return info_; }
@@ -59,6 +60,9 @@
   // Returns true if this cursor's platform data matches that of |other|.
   bool IsPlatformDataEqual(const WebCursor& other) const;
 
+  // Copies all data from |other| to this object.
+  void CopyAllData(const WebCursor& other);
+
   // Copies platform specific data from the WebCursor instance passed in.
   void CopyPlatformData(const WebCursor& other);
 
diff --git a/content/common/frame.mojom b/content/common/frame.mojom
index a7cb70c..e8ad0f810 100644
--- a/content/common/frame.mojom
+++ b/content/common/frame.mojom
@@ -183,16 +183,22 @@
   // |javascript| is the string containing the JavaScript to be executed in the
   // target frame's context.
   //
+  // |wants_result| is true if the result of this execution is required by the
+  // caller. If it is false, a reply is still required by Mojo, but a null value
+  // should be returned to avoid issues serializing a large, unwanted reply.
+  //
   // TODO(hajimehoshi): This requires navigate association to keep the message
   // order with other navigation-related messages. Fix this and move this to a
   // non-navigate-related interface if possible.
   JavaScriptExecuteRequest(
-      mojo_base.mojom.String16 javascript) => (mojo_base.mojom.Value result);
+      mojo_base.mojom.String16 javascript,
+      bool wants_result) => (mojo_base.mojom.Value result);
 
   // ONLY FOR TESTS: Same as above but adds a fake UserGestureIndicator around
   // execution. (crbug.com/408426)
   JavaScriptExecuteRequestForTests(
       mojo_base.mojom.String16 javascript,
+      bool wants_result,
       bool has_user_gesture)
       => (mojo_base.mojom.Value result);
 
@@ -200,6 +206,7 @@
   // isolated world specified by the fourth parameter.
   JavaScriptExecuteRequestInIsolatedWorld(
       mojo_base.mojom.String16 javascript,
+      bool wants_result,
       int32 world_id) => (mojo_base.mojom.Value result);
 
   // Posts a message from a frame in another process to the current renderer.
diff --git a/content/public/browser/navigation_details.h b/content/public/browser/navigation_details.h
index 7155040..454f51b 100644
--- a/content/public/browser/navigation_details.h
+++ b/content/public/browser/navigation_details.h
@@ -14,9 +14,8 @@
 
 class NavigationEntry;
 
-// Provides the details for a NOTIFICATION_NAV_ENTRY_COMMITTED notification.
-// TODO(brettw) this mostly duplicates ProvisionalLoadDetails, it would be
-// nice to unify these somehow.
+// Provides the details of a committed navigation entry for the
+// WebContentsObserver::NavigationEntryCommitted() notification.
 struct CONTENT_EXPORT LoadCommittedDetails {
   // By default, the entry will be filled according to a new main frame
   // navigation.
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index 21bf76f..f432575 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -2572,6 +2572,7 @@
 
 void RenderFrameImpl::JavaScriptExecuteRequest(
     const base::string16& javascript,
+    bool wants_result,
     JavaScriptExecuteRequestCallback callback) {
   TRACE_EVENT_INSTANT0("test_tracing", "JavaScriptExecuteRequest",
                        TRACE_EVENT_SCOPE_THREAD);
@@ -2586,11 +2587,15 @@
   if (!weak_this)
     return;
 
-  std::move(callback).Run(GetJavaScriptExecutionResult(result));
+  if (wants_result)
+    std::move(callback).Run(GetJavaScriptExecutionResult(result));
+  else
+    std::move(callback).Run({});
 }
 
 void RenderFrameImpl::JavaScriptExecuteRequestForTests(
     const base::string16& javascript,
+    bool wants_result,
     bool has_user_gesture,
     JavaScriptExecuteRequestForTestsCallback callback) {
   TRACE_EVENT_INSTANT0("test_tracing", "JavaScriptExecuteRequestForTests",
@@ -2612,11 +2617,15 @@
   if (!weak_this)
     return;
 
-  std::move(callback).Run(GetJavaScriptExecutionResult(result));
+  if (wants_result)
+    std::move(callback).Run(GetJavaScriptExecutionResult(result));
+  else
+    std::move(callback).Run({});
 }
 
 void RenderFrameImpl::JavaScriptExecuteRequestInIsolatedWorld(
     const base::string16& javascript,
+    bool wants_result,
     int32_t world_id,
     JavaScriptExecuteRequestInIsolatedWorldCallback callback) {
   TRACE_EVENT_INSTANT0("test_tracing",
@@ -2635,15 +2644,18 @@
   v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
   WebScriptSource script = WebScriptSource(WebString::FromUTF16(javascript));
   JavaScriptIsolatedWorldRequest* request = new JavaScriptIsolatedWorldRequest(
-      weak_factory_.GetWeakPtr(), std::move(callback));
+      weak_factory_.GetWeakPtr(), wants_result, std::move(callback));
   frame_->RequestExecuteScriptInIsolatedWorld(
       world_id, &script, 1, false, WebLocalFrame::kSynchronous, request);
 }
 
 RenderFrameImpl::JavaScriptIsolatedWorldRequest::JavaScriptIsolatedWorldRequest(
     base::WeakPtr<RenderFrameImpl> render_frame_impl,
+    bool wants_result,
     JavaScriptExecuteRequestInIsolatedWorldCallback callback)
-    : render_frame_impl_(render_frame_impl), callback_(std::move(callback)) {}
+    : render_frame_impl_(render_frame_impl),
+      wants_result_(wants_result),
+      callback_(std::move(callback)) {}
 
 RenderFrameImpl::JavaScriptIsolatedWorldRequest::
     ~JavaScriptIsolatedWorldRequest() {
@@ -2658,7 +2670,7 @@
   }
 
   base::Value value;
-  if (!result.empty()) {
+  if (!result.empty() && wants_result_) {
     // It's safe to always use the main world context when converting
     // here. V8ValueConverterImpl shouldn't actually care about the
     // context scope, and it switches to v8::Object's creation context
@@ -3108,7 +3120,7 @@
 }
 
 void RenderFrameImpl::ExecuteJavaScript(const base::string16& javascript) {
-  JavaScriptExecuteRequest(javascript, base::DoNothing());
+  JavaScriptExecuteRequest(javascript, false, base::DoNothing());
 }
 
 void RenderFrameImpl::BindLocalInterface(
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h
index 32b80ee3..38a8f12 100644
--- a/content/renderer/render_frame_impl.h
+++ b/content/renderer/render_frame_impl.h
@@ -630,13 +630,16 @@
 
   void JavaScriptExecuteRequest(
       const base::string16& javascript,
+      bool wants_result,
       JavaScriptExecuteRequestCallback callback) override;
   void JavaScriptExecuteRequestForTests(
       const base::string16& javascript,
+      bool wants_result,
       bool has_user_gesture,
       JavaScriptExecuteRequestForTestsCallback callback) override;
   void JavaScriptExecuteRequestInIsolatedWorld(
       const base::string16& javascript,
+      bool wants_result,
       int32_t world_id,
       JavaScriptExecuteRequestInIsolatedWorldCallback callback) override;
   void OnPortalActivated(
@@ -1025,6 +1028,7 @@
    public:
     JavaScriptIsolatedWorldRequest(
         base::WeakPtr<RenderFrameImpl> render_frame_impl,
+        bool wants_result,
         JavaScriptExecuteRequestInIsolatedWorldCallback callback);
     void Completed(
         const blink::WebVector<v8::Local<v8::Value>>& result) override;
@@ -1033,6 +1037,7 @@
     ~JavaScriptIsolatedWorldRequest() override;
 
     base::WeakPtr<RenderFrameImpl> render_frame_impl_;
+    bool wants_result_;
     JavaScriptExecuteRequestInIsolatedWorldCallback callback_;
 
     DISALLOW_COPY_AND_ASSIGN(JavaScriptIsolatedWorldRequest);
diff --git a/content/shell/tools/breakpad_integration_test.py b/content/shell/tools/breakpad_integration_test.py
index 7bcf0d4..2e09b13 100755
--- a/content/shell/tools/breakpad_integration_test.py
+++ b/content/shell/tools/breakpad_integration_test.py
@@ -55,6 +55,17 @@
   return GetDevice.device
 
 
+def clear_android_dumps(device):
+  try:
+    pending = ANDROID_CRASH_DIR + '/pending/'
+    files = device.RunShellCommand(['ls', pending], as_root=True)
+    for f in files:
+      device.RunShellCommand(['rm', pending + f], check_return=True,
+                             as_root=True)
+  except:
+    print 'Failed to delete android crash dir %s' % ANDROID_CRASH_DIR
+
+
 def get_android_dump(crash_dir):
   global failure
 
@@ -90,6 +101,8 @@
     device = GetDevice()
 
     failure = None
+    clear_android_dumps(device)
+
     apk_path = os.path.join(options.build_dir, 'apks', 'ContentShell.apk')
     apk = apk_helper.ApkHelper(apk_path)
     view_activity = apk.GetViewActivityName()
@@ -297,14 +310,7 @@
     except:
       print 'Failed to delete temp directory "%s".' % crash_dir
     if options.platform == 'android':
-      try:
-        pending = ANDROID_CRASH_DIR + '/pending/'
-        files = device.RunShellCommand(['ls', pending], as_root=True)
-        for f in files:
-          GetDevice().RunShellCommand(['rm', pending + f], check_return=True,
-                                      as_root=True)
-      except:
-        print 'Failed to delete android crash dir %s' % ANDROID_CRASH_DIR
+      clear_android_dumps(GetDevice())
 
 
 if '__main__' == __name__:
diff --git a/content/test/data/overlapping_cross_site_iframe.html b/content/test/data/overlapping_cross_site_iframe.html
deleted file mode 100644
index d5cc19d..0000000
--- a/content/test/data/overlapping_cross_site_iframe.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<html>
-<title>Overlapping cross site iframe</title>
-
-This is the main body content.
-<iframe id="iframe" style="width:300px; height:300px; position:absolute; left:100px; top:100px"></iframe>
-<div id="target" style="background-color: yellow; position: absolute; top: 120px; left: 120px; width: 100px; height: 100px"></div>
-
-<script>
-
-  var url = window.location.protocol + '//b.com';
-  if (window.location.port)
-    url += ':' + window.location.port;
-  url += "/cross_site_iframe_factory.html?b()";
-
-  document.getElementById('iframe').src = url;
-</script>
-
-</html>
diff --git a/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt
index 95cabb2..4f91a0c 100644
--- a/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt
@@ -282,7 +282,7 @@
 
 # Flaky on 10.13 as well.
 crbug.com/870856 [ sierra amd ] conformance2/textures/misc/tex-mipmap-levels.html [ Failure ]
-crbug.com/870856 [ highsierra amd ] conformance2/textures/misc/tex-mipmap-levels.html [ RetryOnFailure ]
+crbug.com/870856 [ highsierra amd ] conformance2/textures/misc/tex-mipmap-levels.html [ Failure ]
 
 # Regressions in 10.13
 crbug.com/774826 [ highsierra intel-0xa2e ] deqp/functional/gles3/fbocolorbuffer/tex2d_00.html [ Failure ]
diff --git a/device/fido/ble/fido_ble_connection.cc b/device/fido/ble/fido_ble_connection.cc
index c03838ab..96b73ac3 100644
--- a/device/fido/ble/fido_ble_connection.cc
+++ b/device/fido/ble/fido_ble_connection.cc
@@ -93,28 +93,6 @@
   return os;
 }
 
-const BluetoothRemoteGattService* GetFidoService(
-    const BluetoothDevice* device) {
-  if (!device) {
-    FIDO_LOG(ERROR) << "No device present.";
-    return nullptr;
-  }
-
-  for (const auto* service : device->GetGattServices()) {
-    // This assumes that no device is representing as both a FIDO BLE
-    // and a caBLE device.
-    if (service->GetUUID() == BluetoothUUID(kFidoServiceUUID) ||
-        service->GetUUID() == BluetoothUUID(kCableAdvertisementUUID128)) {
-      FIDO_LOG(EVENT) << "Found caBLE service UUID: "
-                      << service->GetUUID().value();
-      return service;
-    }
-  }
-
-  FIDO_LOG(ERROR) << "No Fido service present.";
-  return nullptr;
-}
-
 void OnWriteRemoteCharacteristic(FidoBleConnection::WriteCallback callback) {
   FIDO_LOG(DEBUG) << "Writing Remote Characteristic Succeeded.";
   std::move(callback).Run(true);
@@ -224,7 +202,7 @@
 
 void FidoBleConnection::ReadControlPointLength(
     ControlPointLengthCallback callback) {
-  const auto* fido_service = GetFidoService(GetBleDevice());
+  const auto* fido_service = GetFidoService();
   if (!fido_service) {
     base::ThreadTaskRunnerHandle::Get()->PostTask(
         FROM_HERE, base::BindOnce(std::move(callback), base::nullopt));
@@ -258,7 +236,7 @@
 
 void FidoBleConnection::WriteControlPoint(const std::vector<uint8_t>& data,
                                           WriteCallback callback) {
-  const auto* fido_service = GetFidoService(GetBleDevice());
+  const auto* fido_service = GetFidoService();
   if (!fido_service) {
     base::ThreadTaskRunnerHandle::Get()->PostTask(
         FROM_HERE, base::BindOnce(std::move(callback), false));
@@ -332,7 +310,7 @@
 void FidoBleConnection::ConnectToFidoService() {
   FIDO_LOG(EVENT) << "Attempting to connect to a Fido service.";
   DCHECK(pending_connection_callback_);
-  const auto* fido_service = GetFidoService(GetBleDevice());
+  const auto* fido_service = GetFidoService();
   if (!fido_service) {
     FIDO_LOG(ERROR) << "Failed to get Fido Service.";
     base::ThreadTaskRunnerHandle::Get()->PostTask(
@@ -425,7 +403,7 @@
   auto callback = base::BindOnce(&FidoBleConnection::OnServiceRevisionWritten,
                                  weak_factory_.GetWeakPtr());
 
-  const auto* fido_service = GetFidoService(GetBleDevice());
+  const auto* fido_service = GetFidoService();
   if (!fido_service) {
     base::ThreadTaskRunnerHandle::Get()->PostTask(
         FROM_HERE, base::BindOnce(std::move(callback), false));
@@ -455,7 +433,7 @@
 
 void FidoBleConnection::StartNotifySession() {
   DCHECK(pending_connection_callback_);
-  const auto* fido_service = GetFidoService(GetBleDevice());
+  const auto* fido_service = GetFidoService();
   if (!fido_service) {
     base::ThreadTaskRunnerHandle::Get()->PostTask(
         FROM_HERE,
@@ -513,6 +491,30 @@
   }
 }
 
+const BluetoothRemoteGattService* FidoBleConnection::GetFidoService() {
+  if (!connection_ || !connection_->IsConnected()) {
+    FIDO_LOG(ERROR) << "No BLE connection.";
+    return nullptr;
+  }
+
+  DCHECK_EQ(address_, connection_->GetDeviceAddress());
+  BluetoothDevice* device = GetBleDevice();
+
+  for (const auto* service : device->GetGattServices()) {
+    // This assumes that no device is representing as both a FIDO BLE
+    // and a caBLE device.
+    if (service->GetUUID() == BluetoothUUID(kFidoServiceUUID) ||
+        service->GetUUID() == BluetoothUUID(kCableAdvertisementUUID128)) {
+      FIDO_LOG(EVENT) << "Found caBLE service UUID: "
+                      << service->GetUUID().value();
+      return service;
+    }
+  }
+
+  FIDO_LOG(ERROR) << "No Fido service present.";
+  return nullptr;
+}
+
 // static
 void FidoBleConnection::OnReadControlPointLength(
     ControlPointLengthCallback callback,
diff --git a/device/fido/ble/fido_ble_connection.h b/device/fido/ble/fido_ble_connection.h
index ecc59942..0b403bcb 100644
--- a/device/fido/ble/fido_ble_connection.h
+++ b/device/fido/ble/fido_ble_connection.h
@@ -87,6 +87,8 @@
   void GattServicesDiscovered(BluetoothAdapter* adapter,
                               BluetoothDevice* device) override;
 
+  const BluetoothRemoteGattService* GetFidoService();
+
   void OnCreateGattConnection(
       std::unique_ptr<BluetoothGattConnection> connection);
   void OnCreateGattConnectionError(
diff --git a/device/fido/ble/fido_ble_discovery.cc b/device/fido/ble/fido_ble_discovery.cc
index c6d74ab..de7cc60 100644
--- a/device/fido/ble/fido_ble_discovery.cc
+++ b/device/fido/ble/fido_ble_discovery.cc
@@ -9,6 +9,7 @@
 #include "base/bind.h"
 #include "base/callback_helpers.h"
 #include "base/time/time.h"
+#include "components/device_event_log/device_event_log.h"
 #include "device/bluetooth/bluetooth_adapter.h"
 #include "device/bluetooth/bluetooth_common.h"
 #include "device/bluetooth/bluetooth_discovery_session.h"
@@ -35,13 +36,13 @@
 
 void FidoBleDiscovery::OnSetPowered() {
   DCHECK(adapter());
-  VLOG(2) << "Adapter " << adapter()->GetAddress() << " is powered on.";
+  FIDO_LOG(DEBUG) << "Adapter " << adapter()->GetAddress() << " is powered on.";
 
   for (BluetoothDevice* device : adapter()->GetDevices()) {
     if (!CheckForExcludedDeviceAndCacheAddress(device) &&
         base::Contains(device->GetUUIDs(), FidoServiceUUID())) {
       const auto& device_address = device->GetAddress();
-      VLOG(2) << "FIDO BLE device: " << device_address;
+      FIDO_LOG(DEBUG) << "FIDO BLE device: " << device_address;
       AddDevice(std::make_unique<FidoBleDevice>(adapter(), device_address));
       CheckAndRecordDevicePairingModeOnDiscovery(
           FidoBleDevice::GetIdForAddress(device_address));
@@ -67,7 +68,7 @@
   if (!CheckForExcludedDeviceAndCacheAddress(device) &&
       base::Contains(device->GetUUIDs(), FidoServiceUUID())) {
     const auto& device_address = device->GetAddress();
-    VLOG(2) << "Discovered FIDO BLE device: " << device_address;
+    FIDO_LOG(DEBUG) << "Discovered FIDO BLE device: " << device_address;
     AddDevice(std::make_unique<FidoBleDevice>(adapter, device_address));
     CheckAndRecordDevicePairingModeOnDiscovery(
         FidoBleDevice::GetIdForAddress(device_address));
@@ -84,8 +85,8 @@
   auto authenticator_id = FidoBleDevice::GetIdForAddress(device->GetAddress());
   auto* authenticator = GetAuthenticator(authenticator_id);
   if (!authenticator) {
-    VLOG(2) << "Discovered FIDO service on existing BLE device: "
-            << device->GetAddress();
+    FIDO_LOG(DEBUG) << "Discovered FIDO service on existing BLE device: "
+                    << device->GetAddress();
     AddDevice(std::make_unique<FidoBleDevice>(adapter, device->GetAddress()));
     CheckAndRecordDevicePairingModeOnDiscovery(std::move(authenticator_id));
     return;
@@ -100,7 +101,7 @@
 void FidoBleDiscovery::DeviceRemoved(BluetoothAdapter* adapter,
                                      BluetoothDevice* device) {
   if (base::Contains(device->GetUUIDs(), FidoServiceUUID())) {
-    VLOG(2) << "FIDO BLE device removed: " << device->GetAddress();
+    FIDO_LOG(DEBUG) << "FIDO BLE device removed: " << device->GetAddress();
     auto device_id = FidoBleDevice::GetIdForAddress(device->GetAddress());
     RemoveDevice(device_id);
     RemoveDeviceFromPairingTracker(device_id);
@@ -131,8 +132,9 @@
   if (it != authenticators_.end())
     return;
 
-  VLOG(2) << "Discovered FIDO BLE device address change from old address : "
-          << old_address << " to new address : " << device->GetAddress();
+  FIDO_LOG(DEBUG)
+      << "Discovered FIDO BLE device address change from old address : "
+      << old_address << " to new address : " << device->GetAddress();
 
   auto change_map_keys = [&](auto* map) {
     auto it = map->find(previous_device_id);
diff --git a/docs/mojo_and_services.md b/docs/mojo_and_services.md
index 17a2412..492d62314 100644
--- a/docs/mojo_and_services.md
+++ b/docs/mojo_and_services.md
@@ -568,7 +568,7 @@
 by adding a block of code as follows:
 
 ``` cpp
-void ChromeContentUtilityClient::MaybeCreateMainThreadService(
+std::unique_ptr<service_manager::Service> ChromeContentUtilityClient::MaybeCreateMainThreadService(
     const std::string& service_name,
     service_manager::mojom::ServiceRequest request) {
   ...
diff --git a/fuchsia/http/http_service_unittest.cc b/fuchsia/http/http_service_unittest.cc
index ba15a54..fcea6be4 100644
--- a/fuchsia/http/http_service_unittest.cc
+++ b/fuchsia/http/http_service_unittest.cc
@@ -369,9 +369,7 @@
 }
 
 // Ensure the service can handle multiple concurrent requests.
-// TODO(crbug.com/972212): re-enable test when reason of the flakiness is
-// resolved.
-TEST_F(HttpServiceTest, DISABLED_MultipleRequests) {
+TEST_F(HttpServiceTest, MultipleRequests) {
   oldhttp::URLLoaderPtr url_loaders[100];
   for (int i = 0; i < 100; i++) {
     http_service()->CreateURLLoader(url_loaders[i].NewRequest());
diff --git a/ios/build/bots/scripts/test_runner.py b/ios/build/bots/scripts/test_runner.py
index 7b95221..078f54e 100644
--- a/ios/build/bots/scripts/test_runner.py
+++ b/ios/build/bots/scripts/test_runner.py
@@ -279,7 +279,7 @@
   Args:
     xcode_build_version: (string) Xcode build version to install.
     mac_toolchain_cmd: (string) Path to mac_toolchain command to install Xcode.
-      See https://chromium.googlesource.com/infra/infra/+/master/go/src/infra/cmd/mac_toolchain/
+    See https://chromium.googlesource.com/infra/infra/+/master/go/src/infra/cmd/mac_toolchain/
     xcode_app_path: (string) Path to install the contents of Xcode.app.
 
   Returns:
@@ -1005,6 +1005,7 @@
       test_filter: List of test cases to filter.
       invert: Whether to invert the filter or not. Inverted, the filter will
         match everything except the given test cases.
+      test_shard: How many shards the tests should be divided into.
 
     Returns:
       A list of strings forming the command to launch the test.
@@ -1505,9 +1506,6 @@
     if len(self.udid.splitlines()) != 1:
       raise DeviceDetectionError(self.udid)
     if xctest:
-      xcode_info = get_current_xcode_info()
-      xcode_version = float(xcode_info['version'])
-      inject_path = 'usr/lib/libXCTestBundleInject.dylib'
       self.xctestrun_file = tempfile.mkstemp()[1]
       self.xctestrun_data = {
         'TestTargetName': {
@@ -1516,7 +1514,8 @@
           'TestHostPath': '%s' % self.app_path,
           'TestingEnvironmentVariables': {
             'DYLD_INSERT_LIBRARIES':
-              '__PLATFORMS__/iPhoneOS.platform/Developer/%s' % inject_path,
+              '__PLATFORMS__/iPhoneOS.platform/Developer/usr/lib/'
+              'libXCTestBundleInject.dylib',
             'DYLD_LIBRARY_PATH':
               '__PLATFORMS__/iPhoneOS.platform/Developer/Library',
             'DYLD_FRAMEWORK_PATH':
diff --git a/ios/build/tools/setup-gn.py b/ios/build/tools/setup-gn.py
index a0d13c8e..8238ea3d 100755
--- a/ios/build/tools/setup-gn.py
+++ b/ios/build/tools/setup-gn.py
@@ -95,7 +95,7 @@
     args.append(('enable_stripping', 'enable_dsyms'))
     args.append(('is_official_build', self._config == 'Official'))
     args.append(('is_chrome_branded', 'is_official_build'))
-    args.append(('use_xcode_clang', 'is_official_build'))
+    args.append(('use_xcode_clang', 'false'))
     args.append(('use_clang_coverage', self._config == 'Coverage'))
     args.append(('is_component_build', False))
 
diff --git a/ios/chrome/browser/autocomplete/autocomplete_provider_client_impl.h b/ios/chrome/browser/autocomplete/autocomplete_provider_client_impl.h
index edc0cb3c..829f360e 100644
--- a/ios/chrome/browser/autocomplete/autocomplete_provider_client_impl.h
+++ b/ios/chrome/browser/autocomplete/autocomplete_provider_client_impl.h
@@ -37,7 +37,7 @@
   InMemoryURLIndex* GetInMemoryURLIndex() override;
   TemplateURLService* GetTemplateURLService() override;
   const TemplateURLService* GetTemplateURLService() const override;
-  ContextualSuggestionsService* GetContextualSuggestionsService(
+  RemoteSuggestionsService* GetRemoteSuggestionsService(
       bool create_if_necessary) const override;
   DocumentSuggestionsService* GetDocumentSuggestionsService(
       bool create_if_necessary) const override;
diff --git a/ios/chrome/browser/autocomplete/autocomplete_provider_client_impl.mm b/ios/chrome/browser/autocomplete/autocomplete_provider_client_impl.mm
index 52178d3a..d9ded109 100644
--- a/ios/chrome/browser/autocomplete/autocomplete_provider_client_impl.mm
+++ b/ios/chrome/browser/autocomplete/autocomplete_provider_client_impl.mm
@@ -99,8 +99,8 @@
   return ios::TemplateURLServiceFactory::GetForBrowserState(browser_state_);
 }
 
-ContextualSuggestionsService*
-AutocompleteProviderClientImpl::GetContextualSuggestionsService(
+RemoteSuggestionsService*
+AutocompleteProviderClientImpl::GetRemoteSuggestionsService(
     bool create_if_necessary) const {
   return nullptr;
 }
diff --git a/ios/chrome/browser/ui/autofill/chrome_autofill_client_ios.h b/ios/chrome/browser/ui/autofill/chrome_autofill_client_ios.h
index 5d87ef1fc..9bdfcaa 100644
--- a/ios/chrome/browser/ui/autofill/chrome_autofill_client_ios.h
+++ b/ios/chrome/browser/ui/autofill/chrome_autofill_client_ios.h
@@ -87,6 +87,7 @@
       std::unique_ptr<base::DictionaryValue> legal_message,
       SaveCreditCardOptions options,
       UploadSaveCardPromptCallback callback) override;
+  void CreditCardUploadCompleted() override;
   void ConfirmCreditCardFillAssist(const CreditCard& card,
                                    base::OnceClosure callback) override;
   bool HasCreditCardScanFeature() override;
diff --git a/ios/chrome/browser/ui/autofill/chrome_autofill_client_ios.mm b/ios/chrome/browser/ui/autofill/chrome_autofill_client_ios.mm
index 9f2f777..a109158f 100644
--- a/ios/chrome/browser/ui/autofill/chrome_autofill_client_ios.mm
+++ b/ios/chrome/browser/ui/autofill/chrome_autofill_client_ios.mm
@@ -264,6 +264,10 @@
   }
 }
 
+void ChromeAutofillClientIOS::CreditCardUploadCompleted() {
+  NOTIMPLEMENTED();
+}
+
 void ChromeAutofillClientIOS::ConfirmCreditCardFillAssist(
     const CreditCard& card,
     base::OnceClosure callback) {
diff --git a/ios/chrome/browser/ui/send_tab_to_self/OWNERS b/ios/chrome/browser/ui/send_tab_to_self/OWNERS
new file mode 100644
index 0000000..63e3f1f
--- /dev/null
+++ b/ios/chrome/browser/ui/send_tab_to_self/OWNERS
@@ -0,0 +1,7 @@
+# Primary
+file://components/send_tab_to_self/OWNERS
+
+# Secondary
+sczs@chromium.org
+
+# COMPONENT: UI>Browser>Sharing
diff --git a/ios/chrome/browser/ui/webui/version_ui.mm b/ios/chrome/browser/ui/webui/version_ui.mm
index 406c2b0..b889df0f 100644
--- a/ios/chrome/browser/ui/webui/version_ui.mm
+++ b/ios/chrome/browser/ui/webui/version_ui.mm
@@ -96,6 +96,12 @@
 
   html_source->AddString(version_ui::kSanitizer, version_info::GetSanitizerList());
 
+#if defined(__apple_build_version__)
+  html_source->AddString(version_ui::kCompiler, "Apple Clang");
+#else
+  html_source->AddString(version_ui::kCompiler, "LLVM clang");
+#endif
+
   html_source->SetJsonPath("strings.js");
   html_source->AddResourcePath(version_ui::kVersionJS, IDR_VERSION_UI_JS);
   html_source->AddResourcePath(version_ui::kAboutVersionCSS,
diff --git a/ios/chrome/test/earl_grey/accessibility_util.mm b/ios/chrome/test/earl_grey/accessibility_util.mm
index d036b1a0..3e3f7d558 100644
--- a/ios/chrome/test/earl_grey/accessibility_util.mm
+++ b/ios/chrome/test/earl_grey/accessibility_util.mm
@@ -108,6 +108,11 @@
 namespace chrome_test_util {
 
 void VerifyAccessibilityForCurrentScreen() {
+  // TODO(crbug.com/972681): The GTX analytics ping is preventing the app from
+  // idling, causing EG tests to fail.  Disabling analytics will allow tests to
+  // run, but may not be the correct long-term solution.
+  [GTXAnalytics setEnabled:NO];
+
   GTXToolKit* toolkit = [[GTXToolKit alloc] init];
   NSError* error = nil;
   for (UIWindow* window in [[UIApplication sharedApplication] windows]) {
diff --git a/ios/web_view/internal/autofill/web_view_autofill_client_ios.h b/ios/web_view/internal/autofill/web_view_autofill_client_ios.h
index 37647a4..050001d6 100644
--- a/ios/web_view/internal/autofill/web_view_autofill_client_ios.h
+++ b/ios/web_view/internal/autofill/web_view_autofill_client_ios.h
@@ -80,6 +80,7 @@
       std::unique_ptr<base::DictionaryValue> legal_message,
       SaveCreditCardOptions options,
       UploadSaveCardPromptCallback callback) override;
+  void CreditCardUploadCompleted() override;
   void ConfirmCreditCardFillAssist(const CreditCard& card,
                                    base::OnceClosure callback) override;
   bool HasCreditCardScanFeature() override;
diff --git a/ios/web_view/internal/autofill/web_view_autofill_client_ios.mm b/ios/web_view/internal/autofill/web_view_autofill_client_ios.mm
index 728461b..530fa7cd 100644
--- a/ios/web_view/internal/autofill/web_view_autofill_client_ios.mm
+++ b/ios/web_view/internal/autofill/web_view_autofill_client_ios.mm
@@ -176,6 +176,10 @@
   DCHECK(options.show_prompt);
 }
 
+void WebViewAutofillClientIOS::CreditCardUploadCompleted() {
+  NOTIMPLEMENTED();
+}
+
 void WebViewAutofillClientIOS::ConfirmCreditCardFillAssist(
     const CreditCard& card,
     base::OnceClosure callback) {}
diff --git a/ios/web_view/tools/build.py b/ios/web_view/tools/build.py
index c4d53f0a7..f66fbe6 100755
--- a/ios/web_view/tools/build.py
+++ b/ios/web_view/tools/build.py
@@ -49,7 +49,7 @@
 
   build_dir = os.path.join("out", target_dir_name(build_config, target_device))
   gn_args = ('target_os="ios" enable_websockets=false '
-            'is_component_build=false use_xcode_clang=true '
+            'is_component_build=false use_xcode_clang=false '
             'disable_file_support=true disable_ftp_support=true '
             'disable_brotli_filter=true ios_enable_code_signing=false '
             'enable_dsyms=true '
diff --git a/media/blink/webmediaplayer_impl.cc b/media/blink/webmediaplayer_impl.cc
index 0e361baf..e514cb2 100644
--- a/media/blink/webmediaplayer_impl.cc
+++ b/media/blink/webmediaplayer_impl.cc
@@ -709,7 +709,8 @@
     // worse performance since reads become asynchronous.
     if (loaded_url_.SchemeIs(url::kDataScheme)) {
       std::string mime_type, charset, data;
-      if (!net::DataURL::Parse(loaded_url_, &mime_type, &charset, &data)) {
+      if (!net::DataURL::Parse(loaded_url_, &mime_type, &charset, &data) ||
+          data.empty()) {
         DataSourceInitialized(false);
         return;
       }
diff --git a/testing/buildbot/chromium.android.json b/testing/buildbot/chromium.android.json
index b90a2c18..6037e29 100644
--- a/testing/buildbot/chromium.android.json
+++ b/testing/buildbot/chromium.android.json
@@ -4311,55 +4311,6 @@
       },
       {
         "args": [
-          "--disable-features=NetworkServiceInProcess",
-          "--gtest_filter=-org.chromium.chrome.browser.FeaturesAnnotationsTest#testFeaturesSetExistingFlags",
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "network_service_out_of_process_chrome_public_test_apk"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "name": "network_service_out_of_process_chrome_public_test_apk",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "KTU84Z",
-              "device_os_type": "userdebug",
-              "device_type": "flo",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "shards": 20
-        },
-        "test": "chrome_public_test_apk"
-      },
-      {
-        "args": [
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices"
         ],
@@ -4405,53 +4356,6 @@
       },
       {
         "args": [
-          "--disable-features=NetworkServiceInProcess",
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "network_service_out_of_process_components_browsertests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "name": "network_service_out_of_process_components_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "KTU84Z",
-              "device_os_type": "userdebug",
-              "device_type": "flo",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "components_browsertests"
-      },
-      {
-        "args": [
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices"
         ],
@@ -4544,102 +4448,6 @@
       },
       {
         "args": [
-          "--disable-features=NetworkServiceInProcess",
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "network_service_out_of_process_content_browsertests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "name": "network_service_out_of_process_content_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "KTU84Z",
-              "device_os_type": "userdebug",
-              "device_type": "flo",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "shards": 5
-        },
-        "test": "content_browsertests"
-      },
-      {
-        "args": [
-          "--disable-features=NetworkService",
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "non_network_service_content_browsertests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "name": "non_network_service_content_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "KTU84Z",
-              "device_os_type": "userdebug",
-              "device_type": "flo",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "shards": 5
-        },
-        "test": "content_browsertests"
-      },
-      {
-        "args": [
           "--disable-perfetto",
           "--gtest_filter=TracingControllerTest.*:BackgroundTracingManagerBrowserTest.*",
           "--gs-results-bucket=chromium-result-details",
@@ -4734,102 +4542,6 @@
       },
       {
         "args": [
-          "--disable-features=NetworkServiceInProcess",
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "network_service_out_of_process_content_shell_test_apk"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "name": "network_service_out_of_process_content_shell_test_apk",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "KTU84Z",
-              "device_os_type": "userdebug",
-              "device_type": "flo",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "shards": 5
-        },
-        "test": "content_shell_test_apk"
-      },
-      {
-        "args": [
-          "--disable-features=NetworkService",
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "non_network_service_content_shell_test_apk"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "name": "non_network_service_content_shell_test_apk",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "KTU84Z",
-              "device_os_type": "userdebug",
-              "device_type": "flo",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "shards": 5
-        },
-        "test": "content_shell_test_apk"
-      },
-      {
-        "args": [
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices"
         ],
@@ -10465,55 +10177,6 @@
       },
       {
         "args": [
-          "--disable-features=NetworkServiceInProcess",
-          "--gtest_filter=-org.chromium.chrome.browser.FeaturesAnnotationsTest#testFeaturesSetExistingFlags",
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "network_service_out_of_process_chrome_public_test_apk"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "name": "network_service_out_of_process_chrome_public_test_apk",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "LMY49B",
-              "device_os_type": "userdebug",
-              "device_type": "flo",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "shards": 20
-        },
-        "test": "chrome_public_test_apk"
-      },
-      {
-        "args": [
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices"
         ],
@@ -10559,53 +10222,6 @@
       },
       {
         "args": [
-          "--disable-features=NetworkServiceInProcess",
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "network_service_out_of_process_components_browsertests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "name": "network_service_out_of_process_components_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "LMY49B",
-              "device_os_type": "userdebug",
-              "device_type": "flo",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "components_browsertests"
-      },
-      {
-        "args": [
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices"
         ],
@@ -10698,102 +10314,6 @@
       },
       {
         "args": [
-          "--disable-features=NetworkServiceInProcess",
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "network_service_out_of_process_content_browsertests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "name": "network_service_out_of_process_content_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "LMY49B",
-              "device_os_type": "userdebug",
-              "device_type": "flo",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "shards": 5
-        },
-        "test": "content_browsertests"
-      },
-      {
-        "args": [
-          "--disable-features=NetworkService",
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "non_network_service_content_browsertests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "name": "non_network_service_content_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "LMY49B",
-              "device_os_type": "userdebug",
-              "device_type": "flo",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "shards": 5
-        },
-        "test": "content_browsertests"
-      },
-      {
-        "args": [
           "--disable-perfetto",
           "--gtest_filter=TracingControllerTest.*:BackgroundTracingManagerBrowserTest.*",
           "--gs-results-bucket=chromium-result-details",
@@ -10888,102 +10408,6 @@
       },
       {
         "args": [
-          "--disable-features=NetworkServiceInProcess",
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "network_service_out_of_process_content_shell_test_apk"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "name": "network_service_out_of_process_content_shell_test_apk",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "LMY49B",
-              "device_os_type": "userdebug",
-              "device_type": "flo",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "shards": 5
-        },
-        "test": "content_shell_test_apk"
-      },
-      {
-        "args": [
-          "--disable-features=NetworkService",
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "non_network_service_content_shell_test_apk"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "name": "non_network_service_content_shell_test_apk",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "LMY49B",
-              "device_os_type": "userdebug",
-              "device_type": "flo",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "shards": 5
-        },
-        "test": "content_shell_test_apk"
-      },
-      {
-        "args": [
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices"
         ],
@@ -16597,55 +16021,6 @@
       },
       {
         "args": [
-          "--disable-features=NetworkServiceInProcess",
-          "--gtest_filter=-org.chromium.chrome.browser.FeaturesAnnotationsTest#testFeaturesSetExistingFlags",
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "network_service_out_of_process_chrome_public_test_apk"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "name": "network_service_out_of_process_chrome_public_test_apk",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "MRA58Z",
-              "device_os_type": "userdebug",
-              "device_type": "flo",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "shards": 20
-        },
-        "test": "chrome_public_test_apk"
-      },
-      {
-        "args": [
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices"
         ],
@@ -16691,53 +16066,6 @@
       },
       {
         "args": [
-          "--disable-features=NetworkServiceInProcess",
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "network_service_out_of_process_components_browsertests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "name": "network_service_out_of_process_components_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "MRA58Z",
-              "device_os_type": "userdebug",
-              "device_type": "flo",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ]
-        },
-        "test": "components_browsertests"
-      },
-      {
-        "args": [
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices"
         ],
@@ -16830,102 +16158,6 @@
       },
       {
         "args": [
-          "--disable-features=NetworkServiceInProcess",
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "network_service_out_of_process_content_browsertests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "name": "network_service_out_of_process_content_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "MRA58Z",
-              "device_os_type": "userdebug",
-              "device_type": "flo",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "shards": 5
-        },
-        "test": "content_browsertests"
-      },
-      {
-        "args": [
-          "--disable-features=NetworkService",
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "non_network_service_content_browsertests"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "name": "non_network_service_content_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "MRA58Z",
-              "device_os_type": "userdebug",
-              "device_type": "flo",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "shards": 5
-        },
-        "test": "content_browsertests"
-      },
-      {
-        "args": [
           "--disable-perfetto",
           "--gtest_filter=TracingControllerTest.*:BackgroundTracingManagerBrowserTest.*",
           "--gs-results-bucket=chromium-result-details",
@@ -17020,102 +16252,6 @@
       },
       {
         "args": [
-          "--disable-features=NetworkServiceInProcess",
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "network_service_out_of_process_content_shell_test_apk"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "name": "network_service_out_of_process_content_shell_test_apk",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "MRA58Z",
-              "device_os_type": "userdebug",
-              "device_type": "flo",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "shards": 5
-        },
-        "test": "content_shell_test_apk"
-      },
-      {
-        "args": [
-          "--disable-features=NetworkService",
-          "--gs-results-bucket=chromium-result-details",
-          "--recover-devices"
-        ],
-        "merge": {
-          "args": [
-            "--bucket",
-            "chromium-result-details",
-            "--test-name",
-            "non_network_service_content_shell_test_apk"
-          ],
-          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
-        },
-        "name": "non_network_service_content_shell_test_apk",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "cipd_packages": [
-            {
-              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
-              "location": "bin",
-              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
-            }
-          ],
-          "dimension_sets": [
-            {
-              "device_os": "MRA58Z",
-              "device_os_type": "userdebug",
-              "device_type": "flo",
-              "os": "Android"
-            }
-          ],
-          "expiration": 10800,
-          "output_links": [
-            {
-              "link": [
-                "https://luci-logdog.appspot.com/v/?s",
-                "=android%2Fswarming%2Flogcats%2F",
-                "${TASK_ID}%2F%2B%2Funified_logcats"
-              ],
-              "name": "shard #${SHARD_INDEX} logcats"
-            }
-          ],
-          "shards": 5
-        },
-        "test": "content_shell_test_apk"
-      },
-      {
-        "args": [
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices"
         ],
diff --git a/testing/buildbot/chromium.dawn.json b/testing/buildbot/chromium.dawn.json
index fc1a665a..d5bc429 100644
--- a/testing/buildbot/chromium.dawn.json
+++ b/testing/buildbot/chromium.dawn.json
@@ -22,8 +22,7 @@
               "os": "Ubuntu",
               "pool": "Chrome-GPU"
             }
-          ],
-          "shards": 4
+          ]
         },
         "test": "dawn_end2end_tests"
       },
@@ -46,8 +45,7 @@
               "os": "Ubuntu",
               "pool": "Chrome-GPU"
             }
-          ],
-          "shards": 4
+          ]
         },
         "test": "dawn_end2end_tests"
       },
@@ -147,8 +145,7 @@
               "os": "Ubuntu-14.04",
               "pool": "Chrome-GPU"
             }
-          ],
-          "shards": 4
+          ]
         },
         "test": "dawn_end2end_tests"
       },
@@ -171,8 +168,7 @@
               "os": "Ubuntu-14.04",
               "pool": "Chrome-GPU"
             }
-          ],
-          "shards": 4
+          ]
         },
         "test": "dawn_end2end_tests"
       },
@@ -371,8 +367,7 @@
               "os": "Mac-10.13.6",
               "pool": "Chrome-GPU"
             }
-          ],
-          "shards": 4
+          ]
         },
         "test": "dawn_end2end_tests"
       },
@@ -396,8 +391,7 @@
               "os": "Mac-10.13.6",
               "pool": "Chrome-GPU"
             }
-          ],
-          "shards": 4
+          ]
         },
         "test": "dawn_end2end_tests"
       },
@@ -498,8 +492,7 @@
               "os": "Mac-10.13.6",
               "pool": "Chrome-GPU"
             }
-          ],
-          "shards": 4
+          ]
         },
         "test": "dawn_end2end_tests"
       },
@@ -522,8 +515,7 @@
               "os": "Mac-10.13.6",
               "pool": "Chrome-GPU"
             }
-          ],
-          "shards": 4
+          ]
         },
         "test": "dawn_end2end_tests"
       },
@@ -721,8 +713,7 @@
               "os": "Windows-10",
               "pool": "Chrome-GPU"
             }
-          ],
-          "shards": 4
+          ]
         },
         "test": "dawn_end2end_tests"
       },
@@ -745,8 +736,7 @@
               "os": "Windows-10",
               "pool": "Chrome-GPU"
             }
-          ],
-          "shards": 4
+          ]
         },
         "test": "dawn_end2end_tests"
       },
@@ -846,8 +836,7 @@
               "os": "Windows-10",
               "pool": "Chrome-GPU"
             }
-          ],
-          "shards": 4
+          ]
         },
         "test": "dawn_end2end_tests"
       },
@@ -870,8 +859,7 @@
               "os": "Windows-10",
               "pool": "Chrome-GPU"
             }
-          ],
-          "shards": 4
+          ]
         },
         "test": "dawn_end2end_tests"
       },
@@ -1069,8 +1057,7 @@
               "os": "Windows-10",
               "pool": "Chrome-GPU"
             }
-          ],
-          "shards": 4
+          ]
         },
         "test": "dawn_end2end_tests"
       },
@@ -1093,8 +1080,7 @@
               "os": "Windows-10",
               "pool": "Chrome-GPU"
             }
-          ],
-          "shards": 4
+          ]
         },
         "test": "dawn_end2end_tests"
       },
@@ -1192,8 +1178,7 @@
               "os": "Windows-10",
               "pool": "Chrome-GPU"
             }
-          ],
-          "shards": 4
+          ]
         },
         "test": "dawn_end2end_tests"
       },
@@ -1216,8 +1201,7 @@
               "os": "Windows-10",
               "pool": "Chrome-GPU"
             }
-          ],
-          "shards": 4
+          ]
         },
         "test": "dawn_end2end_tests"
       },
diff --git a/testing/buildbot/chromium.perf.json b/testing/buildbot/chromium.perf.json
index d9065cb..33edf4a 100644
--- a/testing/buildbot/chromium.perf.json
+++ b/testing/buildbot/chromium.perf.json
@@ -1970,9 +1970,10 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "8086:5912",
+              "gpu": null,
               "os": "Windows-10",
-              "pool": "chrome.tests.perf"
+              "pool": "chrome.tests.perf",
+              "synthetic_product_name": "OptiPlex 7050 (Dell Inc.)"
             }
           ],
           "expiration": 7200,
@@ -2007,9 +2008,10 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "8086:5912",
+              "gpu": null,
               "os": "Windows-10",
-              "pool": "chrome.tests.perf"
+              "pool": "chrome.tests.perf",
+              "synthetic_product_name": "OptiPlex 7050 (Dell Inc.)"
             }
           ],
           "expiration": 7200,
@@ -2044,9 +2046,10 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "8086:5912",
+              "gpu": null,
               "os": "Windows-10",
-              "pool": "chrome.tests.perf"
+              "pool": "chrome.tests.perf",
+              "synthetic_product_name": "OptiPlex 7050 (Dell Inc.)"
             }
           ],
           "expiration": 7200,
@@ -2081,9 +2084,10 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "8086:5912",
+              "gpu": null,
               "os": "Windows-10",
-              "pool": "chrome.tests.perf"
+              "pool": "chrome.tests.perf",
+              "synthetic_product_name": "OptiPlex 7050 (Dell Inc.)"
             }
           ],
           "expiration": 7200,
@@ -2118,9 +2122,10 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "8086:5912",
+              "gpu": null,
               "os": "Windows-10",
-              "pool": "chrome.tests.perf"
+              "pool": "chrome.tests.perf",
+              "synthetic_product_name": "OptiPlex 7050 (Dell Inc.)"
             }
           ],
           "expiration": 7200,
@@ -2159,9 +2164,10 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "gpu": "8086:5912",
+              "gpu": null,
               "os": "Windows-10",
-              "pool": "chrome.tests.perf"
+              "pool": "chrome.tests.perf",
+              "synthetic_product_name": "OptiPlex 7050 (Dell Inc.)"
             }
           ],
           "expiration": 7200,
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl
index 356db40..211dbec 100644
--- a/testing/buildbot/test_suite_exceptions.pyl
+++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -301,8 +301,6 @@
       'mac-archive-rel',
     ],
   },
-  # Note: keep experiment percentages the same as
-  # network_service_chrome_public_test_apk.
   'chrome_public_test_apk': {
     'remove_from': [
       'android-asan',  # https://crbug.com/964562
@@ -892,36 +890,6 @@
       },
     },
   },
-  # Note: keep experiment percentages the same as chrome_public_test_apk.
-  'network_service_chrome_public_test_apk': {
-    # Only run these on the phone testers for now due to capacity.
-    'remove_from': [
-      # chromium.android
-      'android-kitkat-arm-rel',
-      'android-marshmallow-arm64-rel',
-      'KitKat Tablet Tester',
-      'Lollipop Tablet Tester',
-      'Marshmallow Tablet Tester',
-      'KitKat Phone Tester (dbg)',
-      # chromium.memory
-      'android-asan',  # https://crbug.com/964562
-      'Android CFI',
-      # chromium.clang
-      'ToTAndroid',
-      'ToTAndroidCFI',
-    ],
-    'modifications': {
-      # chromium.android
-      'Marshmallow 64 bit Tester': {
-        # TODO(crbug.com/731759): Enable this once we're confident that it
-        # passes.
-        'experiment_percentage': 100,
-      },
-      'Oreo Phone Tester': {
-        'experiment_percentage': 100,
-      },
-    },
-  },
   'network_service_components_browsertests': {
     'remove_from': [
       # chromium.memory
@@ -963,24 +931,6 @@
       'ToTMacASan',
     ],
   },
-  'network_service_content_shell_test_apk': {
-    # Only run these on the phone testers for now due to capacity.
-    'remove_from': [
-      # chromium.android
-      'android-kitkat-arm-rel',
-      'android-marshmallow-arm64-rel',
-      'KitKat Tablet Tester',
-      'Lollipop Tablet Tester',
-      'Marshmallow Tablet Tester',
-      'KitKat Phone Tester (dbg)',
-      # chromium.memory
-      'android-asan',  # https://crbug.com/964562
-      'Android CFI',
-      # chromium.clang
-      'ToTAndroid',
-      'ToTAndroidCFI',
-    ],
-  },
   'network_service_extensions_browsertests': {
     'remove_from': [
       # chromium.clang
@@ -1041,7 +991,11 @@
       'android-asan',
       # Don't run on trybots; waterfall is enough.
       'android-kitkat-arm-rel',
-      'android-marshmallow-arm64-rel'
+      'android-marshmallow-arm64-rel',
+      # No capacity for tablet testers.
+      'KitKat Tablet Tester',
+      'Lollipop Tablet Tester',
+      'Marshmallow Tablet Tester',
     ],
   },
   'network_service_out_of_process_components_browsertests': {
@@ -1050,7 +1004,11 @@
       'android-asan',
       # Don't run on trybots; waterfall is enough.
       'android-kitkat-arm-rel',
-      'android-marshmallow-arm64-rel'
+      'android-marshmallow-arm64-rel',
+      # No capacity for tablet testers.
+      'KitKat Tablet Tester',
+      'Lollipop Tablet Tester',
+      'Marshmallow Tablet Tester',
     ],
   },
   'network_service_out_of_process_content_browsertests': {
@@ -1059,7 +1017,11 @@
       'android-asan',
       # Don't run on trybots; waterfall is enough.
       'android-kitkat-arm-rel',
-      'android-marshmallow-arm64-rel'
+      'android-marshmallow-arm64-rel',
+      # No capacity for tablet testers.
+      'KitKat Tablet Tester',
+      'Lollipop Tablet Tester',
+      'Marshmallow Tablet Tester',
     ],
   },
   'network_service_out_of_process_content_shell_test_apk': {
@@ -1068,7 +1030,11 @@
       'android-asan',
       # Don't run on trybots; waterfall is enough.
       'android-kitkat-arm-rel',
-      'android-marshmallow-arm64-rel'
+      'android-marshmallow-arm64-rel',
+      # No capacity for tablet testers.
+      'KitKat Tablet Tester',
+      'Lollipop Tablet Tester',
+      'Marshmallow Tablet Tester',
     ],
   },
   'network_service_webview_instrumentation_test_apk': {
@@ -1095,7 +1061,11 @@
       'android-asan',
       # Don't run on trybots; waterfall is enough.
       'android-kitkat-arm-rel',
-      'android-marshmallow-arm64-rel'
+      'android-marshmallow-arm64-rel',
+      # No capacity for tablet testers.
+      'KitKat Tablet Tester',
+      'Lollipop Tablet Tester',
+      'Marshmallow Tablet Tester',
     ],
   },
   'non_network_service_content_shell_test_apk': {
@@ -1104,7 +1074,11 @@
       'android-asan',
       # Don't run on trybots; waterfall is enough.
       'android-kitkat-arm-rel',
-      'android-marshmallow-arm64-rel'
+      'android-marshmallow-arm64-rel',
+      # No capacity for tablet testers.
+      'KitKat Tablet Tester',
+      'Lollipop Tablet Tester',
+      'Marshmallow Tablet Tester',
     ],
   },
   'non_network_service_webkit_layout_tests' : {
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl
index 0d68436..df7c0ca8 100644
--- a/testing/buildbot/test_suites.pyl
+++ b/testing/buildbot/test_suites.pyl
@@ -3181,9 +3181,6 @@
           # Dawn test retries deliberately disabled to prevent flakiness.
           '--test-launcher-retry-limit=0'
         ],
-        'swarming': {
-          'shards': 4,
-        },
       },
       'dawn_end2end_wire_tests': {
         'desktop_args': [
@@ -3192,9 +3189,6 @@
           '--test-launcher-retry-limit=0',
           '--use-wire',
         ],
-        'swarming': {
-          'shards': 4,
-        },
         'test': 'dawn_end2end_tests',
       },
       'gl_tests': {
diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc
index c0df04c..7b45c1d 100644
--- a/third_party/blink/common/features.cc
+++ b/third_party/blink/common/features.cc
@@ -303,5 +303,8 @@
          base::FeatureList::IsEnabled(features::kPlzDedicatedWorker);
 }
 
+const base::Feature kCanvasAlwaysDeferral{"CanvasAlwaysDeferral",
+                                          base::FEATURE_ENABLED_BY_DEFAULT};
+
 }  // namespace features
 }  // namespace blink
diff --git a/third_party/blink/public/common/features.h b/third_party/blink/public/common/features.h
index 13c0f68..dd21498 100644
--- a/third_party/blink/public/common/features.h
+++ b/third_party/blink/public/common/features.h
@@ -89,6 +89,8 @@
 // Returns true when PlzDedicatedWorker is enabled.
 BLINK_COMMON_EXPORT bool IsPlzDedicatedWorkerEnabled();
 
+BLINK_COMMON_EXPORT extern const base::Feature kCanvasAlwaysDeferral;
+
 }  // namespace features
 }  // namespace blink
 
diff --git a/third_party/blink/renderer/core/editing/serializers/styled_markup_serializer.cc b/third_party/blink/renderer/core/editing/serializers/styled_markup_serializer.cc
index 502f8dd..36481ff9 100644
--- a/third_party/blink/renderer/core/editing/serializers/styled_markup_serializer.cc
+++ b/third_party/blink/renderer/core/editing/serializers/styled_markup_serializer.cc
@@ -365,15 +365,11 @@
         continue;
       }
 
-      if (!n->GetLayoutObject() &&
-          (!n->IsElementNode() || !ToElement(n)->HasDisplayContentsStyle()) &&
-          !EnclosingElementWithTag(FirstPositionInOrBeforeNode(*n),
-                                   kSelectTag)) {
-        next = Strategy::NextSkippingChildren(*n);
-        // Don't skip over pastEnd.
-        if (past_end && Strategy::IsDescendantOf(*past_end, *n))
-          next = past_end;
-      } else {
+      auto* element = DynamicTo<Element>(n);
+      if (n->GetLayoutObject() ||
+          (element && element->HasDisplayContentsStyle()) ||
+          EnclosingElementWithTag(FirstPositionInOrBeforeNode(*n),
+                                  kSelectTag)) {
         // Add the node to the markup if we're not skipping the descendants
         AppendStartMarkup(*n);
 
@@ -392,6 +388,11 @@
         }
         AppendEndMarkup(*n);
         last_closed = n;
+      } else {
+        next = Strategy::NextSkippingChildren(*n);
+        // Don't skip over pastEnd.
+        if (past_end && Strategy::IsDescendantOf(*past_end, *n))
+          next = past_end;
       }
     }
 
@@ -466,15 +467,15 @@
     accumulator_->PushMarkup(markup.ToString());
     return;
   }
-  if (!node.IsElementNode())
+  auto* element = DynamicTo<Element>(node);
+  if (!element)
     return;
-  Element& element = ToElement(node);
-  if (ShouldApplyWrappingStyle(element) || NeedsInlineStyle(element))
-    accumulator_->AppendElementWithInlineStyle(markup, element, style);
+  if (ShouldApplyWrappingStyle(*element) || NeedsInlineStyle(*element))
+    accumulator_->AppendElementWithInlineStyle(markup, *element, style);
   else
-    accumulator_->AppendElement(markup, element);
+    accumulator_->AppendElement(markup, *element);
   accumulator_->PushMarkup(markup.ToString());
-  accumulator_->AppendEndTag(ToElement(node));
+  accumulator_->AppendEndTag(*element);
 }
 
 template <typename Strategy>
@@ -482,9 +483,11 @@
     Node& node) {
   if (!accumulator_)
     return nullptr;
-  if (!node.IsElementNode())
+
+  auto* element = DynamicTo<Element>(node);
+  if (!element)
     return nullptr;
-  EditingStyle* inline_style = CreateInlineStyle(ToElement(node));
+  EditingStyle* inline_style = CreateInlineStyle(*element);
   if (ShouldConvertBlocksToInlines() && IsEnclosingBlock(&node))
     inline_style->ForceInline();
   return inline_style;
@@ -517,7 +520,7 @@
       break;
     }
     case Node::kElementNode: {
-      Element& element = ToElement(node);
+      auto& element = To<Element>(node);
       if ((element.IsHTMLElement() && ShouldAnnotate()) ||
           ShouldApplyWrappingStyle(element)) {
         EditingStyle* inline_style = CreateInlineStyle(element);
@@ -535,9 +538,10 @@
 
 template <typename Strategy>
 void StyledMarkupTraverser<Strategy>::AppendEndMarkup(Node& node) {
-  if (!accumulator_ || !node.IsElementNode())
+  auto* element = DynamicTo<Element>(node);
+  if (!accumulator_ || !element)
     return;
-  accumulator_->AppendEndTag(ToElement(node));
+  accumulator_->AppendEndTag(*element);
 }
 
 template <typename Strategy>
diff --git a/third_party/blink/renderer/core/editing/spellcheck/cold_mode_spell_check_requester.cc b/third_party/blink/renderer/core/editing/spellcheck/cold_mode_spell_check_requester.cc
index 44875dbb1..a01a37b8 100644
--- a/third_party/blink/renderer/core/editing/spellcheck/cold_mode_spell_check_requester.cc
+++ b/third_party/blink/renderer/core/editing/spellcheck/cold_mode_spell_check_requester.cc
@@ -63,11 +63,10 @@
   if (position.IsNull())
     return nullptr;
 
-  const ContainerNode* root = HighestEditableRoot(position);
-  if (!root || !root->isConnected() || !root->IsElementNode())
+  const auto* element = DynamicTo<Element>(HighestEditableRoot(position));
+  if (!element || !element->isConnected())
     return nullptr;
 
-  const Element* element = ToElement(root);
   if (!element->IsSpellCheckingEnabled() ||
       !SpellChecker::IsSpellCheckingEnabledAt(position))
     return nullptr;
diff --git a/third_party/blink/renderer/core/editing/testing/selection_sample.cc b/third_party/blink/renderer/core/editing/testing/selection_sample.cc
index 349c344..7b1ebd71 100644
--- a/third_party/blink/renderer/core/editing/testing/selection_sample.cc
+++ b/third_party/blink/renderer/core/editing/testing/selection_sample.cc
@@ -150,8 +150,8 @@
   // Traverses descendants of |node|. The |node| may be removed when it is
   // |CharacterData| node contains only selection markers.
   void Traverse(Node* node) {
-    if (node->IsElementNode()) {
-      HandleElementNode(ToElement(node));
+    if (auto* element = DynamicTo<Element>(node)) {
+      HandleElementNode(element);
       return;
     }
     if (auto* data = DynamicTo<CharacterData>(node)) {
@@ -282,8 +282,8 @@
   }
 
   void HandleNode(const Node& node) {
-    if (node.IsElementNode()) {
-      HandleElementNode(ToElement(node));
+    if (auto* element = DynamicTo<Element>(node)) {
+      HandleElementNode(*element);
       return;
     }
     if (node.IsTextNode()) {
diff --git a/third_party/blink/renderer/core/exported/web_element.cc b/third_party/blink/renderer/core/exported/web_element.cc
index 00e0fefd..41aaa70d 100644
--- a/third_party/blink/renderer/core/exported/web_element.cc
+++ b/third_party/blink/renderer/core/exported/web_element.cc
@@ -41,6 +41,7 @@
 #include "third_party/blink/renderer/core/html_names.h"
 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
 #include "third_party/blink/renderer/platform/graphics/image.h"
+#include "third_party/blink/renderer/platform/wtf/casting.h"
 #include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
 
@@ -172,7 +173,7 @@
 }
 
 WebElement::operator Element*() const {
-  return ToElement(private_.Get());
+  return blink::To<Element>(private_.Get());
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/exported/web_element_test.cc b/third_party/blink/renderer/core/exported/web_element_test.cc
index 47db70bc..1cb2230f 100644
--- a/third_party/blink/renderer/core/exported/web_element_test.cc
+++ b/third_party/blink/renderer/core/exported/web_element_test.cc
@@ -93,13 +93,15 @@
   )JS");
   GetDocument().body()->appendChild(script);
   auto* v0typeext = GetDocument().body()->lastChild();
-  EXPECT_FALSE(WebElement(ToElement(v0typeext)).IsAutonomousCustomElement());
+  EXPECT_FALSE(WebElement(To<Element>(v0typeext)).IsAutonomousCustomElement());
   auto* v0autonomous = v0typeext->previousSibling();
-  EXPECT_TRUE(WebElement(ToElement(v0autonomous)).IsAutonomousCustomElement());
+  EXPECT_TRUE(
+      WebElement(To<Element>(v0autonomous)).IsAutonomousCustomElement());
   auto* v1builtin = v0autonomous->previousSibling();
-  EXPECT_FALSE(WebElement(ToElement(v1builtin)).IsAutonomousCustomElement());
+  EXPECT_FALSE(WebElement(To<Element>(v1builtin)).IsAutonomousCustomElement());
   auto* v1autonomous = v1builtin->previousSibling();
-  EXPECT_TRUE(WebElement(ToElement(v1autonomous)).IsAutonomousCustomElement());
+  EXPECT_TRUE(
+      WebElement(To<Element>(v1autonomous)).IsAutonomousCustomElement());
 }
 
 TEST_F(WebElementTest, ShadowRoot) {
diff --git a/third_party/blink/renderer/core/exported/web_node.cc b/third_party/blink/renderer/core/exported/web_node.cc
index 128af455..acba6e35 100644
--- a/third_party/blink/renderer/core/exported/web_node.cc
+++ b/third_party/blink/renderer/core/exported/web_node.cc
@@ -131,12 +131,13 @@
 }
 
 bool WebNode::IsFocusable() const {
-  if (!private_->IsElementNode())
+  auto* element = DynamicTo<Element>(private_.Get());
+  if (!element)
     return false;
   if (!private_->GetDocument().HaveRenderBlockingResourcesLoaded())
     return false;
   private_->GetDocument().UpdateStyleAndLayoutTreeForNode(private_.Get());
-  return ToElement(private_.Get())->IsFocusable();
+  return element->IsFocusable();
 }
 
 bool WebNode::IsContentEditable() const {
diff --git a/third_party/blink/renderer/core/frame/smart_clip.cc b/third_party/blink/renderer/core/frame/smart_clip.cc
index a06219c8..3b3fde27 100644
--- a/third_party/blink/renderer/core/frame/smart_clip.cc
+++ b/third_party/blink/renderer/core/frame/smart_clip.cc
@@ -161,11 +161,10 @@
 
   while (node) {
     IntRect node_rect = node->PixelSnappedBoundingBox();
-
-    if (node->IsElementNode() &&
+    auto* element = DynamicTo<Element>(node);
+    if (element &&
         DeprecatedEqualIgnoringCase(
-            ToElement(node)->FastGetAttribute(html_names::kAriaHiddenAttr),
-            "true")) {
+            element->FastGetAttribute(html_names::kAriaHiddenAttr), "true")) {
       node = NodeTraversal::NextSkippingChildren(*node, root_node);
       continue;
     }
diff --git a/third_party/blink/renderer/core/frame/web_frame_serializer_impl.cc b/third_party/blink/renderer/core/frame/web_frame_serializer_impl.cc
index 37446f7..d7a974d 100644
--- a/third_party/blink/renderer/core/frame/web_frame_serializer_impl.cc
+++ b/third_party/blink/renderer/core/frame/web_frame_serializer_impl.cc
@@ -420,13 +420,13 @@
   switch (node->getNodeType()) {
     case Node::kElementNode:
       // Process open tag of element.
-      OpenTagToString(ToElement(node), param);
+      OpenTagToString(To<Element>(node), param);
       // Walk through the children nodes and process it.
       for (Node* child = node->firstChild(); child;
            child = child->nextSibling())
         BuildContentForNode(child, param);
       // Process end tag of element.
-      EndTagToString(ToElement(node), param);
+      EndTagToString(To<Element>(node), param);
       break;
     case Node::kTextNode:
       SaveHTMLContentToBuffer(CreateMarkup(node), param);
diff --git a/third_party/blink/renderer/core/html/custom/custom_element_registry.cc b/third_party/blink/renderer/core/html/custom/custom_element_registry.cc
index da1c2c1e..d31b4be 100644
--- a/third_party/blink/renderer/core/html/custom/custom_element_registry.cc
+++ b/third_party/blink/renderer/core/html/custom/custom_element_registry.cc
@@ -37,11 +37,10 @@
 
 void CollectUpgradeCandidateInNode(Node& root,
                                    HeapVector<Member<Element>>& candidates) {
-  if (root.IsElementNode()) {
-    Element& root_element = ToElement(root);
-    if (root_element.GetCustomElementState() == CustomElementState::kUndefined)
+  if (auto* root_element = DynamicTo<Element>(root)) {
+    if (root_element->GetCustomElementState() == CustomElementState::kUndefined)
       candidates.push_back(root_element);
-    if (auto* shadow_root = root_element.GetShadowRoot()) {
+    if (auto* shadow_root = root_element->GetShadowRoot()) {
       if (shadow_root->GetType() != ShadowRootType::kUserAgent)
         CollectUpgradeCandidateInNode(*shadow_root, candidates);
     }
diff --git a/third_party/blink/renderer/core/html/custom/custom_element_upgrade_sorter.cc b/third_party/blink/renderer/core/html/custom/custom_element_upgrade_sorter.cc
index 0e04540..2d40f4d 100644
--- a/third_party/blink/renderer/core/html/custom/custom_element_upgrade_sorter.cc
+++ b/third_party/blink/renderer/core/html/custom/custom_element_upgrade_sorter.cc
@@ -86,8 +86,8 @@
 
   // TODO(dominicc): When custom elements are used in UA shadow
   // roots, expand this to include UA shadow roots.
-  ShadowRoot* shadow_root =
-      parent->IsElementNode() ? ToElement(parent)->AuthorShadowRoot() : nullptr;
+  auto* element = DynamicTo<Element>(parent);
+  ShadowRoot* shadow_root = element ? element->AuthorShadowRoot() : nullptr;
   if (shadow_root)
     Visit(result, *children, children->find(shadow_root));
 
diff --git a/third_party/blink/renderer/core/html/forms/date_time_edit_element.cc b/third_party/blink/renderer/core/html/forms/date_time_edit_element.cc
index 22b0c35..890a17a 100644
--- a/third_party/blink/renderer/core/html/forms/date_time_edit_element.cc
+++ b/third_party/blink/renderer/core/html/forms/date_time_edit_element.cc
@@ -580,9 +580,9 @@
   float width = 0;
   for (Node* child = FieldsWrapperElement()->firstChild(); child;
        child = child->nextSibling()) {
-    if (!child->IsElementNode())
+    auto* child_element = DynamicTo<Element>(child);
+    if (!child_element)
       continue;
-    Element* child_element = ToElement(child);
     if (child_element->IsDateTimeFieldElement()) {
       // We need to pass the ComputedStyle of this element because child
       // elements can't resolve inherited style at this timing.
diff --git a/third_party/blink/renderer/core/html/forms/form_controller_test.cc b/third_party/blink/renderer/core/html/forms/form_controller_test.cc
index 5bf1e877..ed04ac88 100644
--- a/third_party/blink/renderer/core/html/forms/form_controller_test.cc
+++ b/third_party/blink/renderer/core/html/forms/form_controller_test.cc
@@ -20,7 +20,7 @@
   Element* html = doc.CreateRawElement(html_names::kHTMLTag);
   doc.appendChild(html);
   Node* body = html->appendChild(doc.CreateRawElement(html_names::kBodyTag));
-  ToElement(body)->SetInnerHTMLFromString("<select form='ff'></select>");
+  To<Element>(body)->SetInnerHTMLFromString("<select form='ff'></select>");
   DocumentState* document_state = doc.GetFormController().FormElementsState();
   Vector<String> state1 = document_state->ToStateVector();
   // <signature>, <control-size>, <form-key>, <name>, <type>, <data-size(0)>
diff --git a/third_party/blink/renderer/core/html/forms/html_option_element.cc b/third_party/blink/renderer/core/html/forms/html_option_element.cc
index 85281f9b..a79c57e 100644
--- a/third_party/blink/renderer/core/html/forms/html_option_element.cc
+++ b/third_party/blink/renderer/core/html/forms/html_option_element.cc
@@ -354,7 +354,8 @@
     if (node->IsTextNode())
       text.Append(node->nodeValue());
     // Text nodes inside script elements are not part of the option text.
-    if (node->IsElementNode() && ToElement(node)->IsScriptElement())
+    auto* element = DynamicTo<Element>(node);
+    if (element && element->IsScriptElement())
       node = NodeTraversal::NextSkippingChildren(*node, this);
     else
       node = NodeTraversal::Next(*node, this);
diff --git a/third_party/blink/renderer/core/html/forms/html_select_element_test.cc b/third_party/blink/renderer/core/html/forms/html_select_element_test.cc
index ad6bd35..1c853881 100644
--- a/third_party/blink/renderer/core/html/forms/html_select_element_test.cc
+++ b/third_party/blink/renderer/core/html/forms/html_select_element_test.cc
@@ -387,8 +387,8 @@
       ">Placeholder</option><optgroup><option>o2</option></optgroup></select>");
   HTMLSelectElement* select =
       ToHTMLSelectElement(GetDocument().body()->firstChild());
-  Element* option = ToElement(select->firstChild());
-  Element* optgroup = ToElement(option->nextSibling());
+  auto* option = To<Element>(select->firstChild());
+  auto* optgroup = To<Element>(option->nextSibling());
 
   EXPECT_EQ(String(), select->DefaultToolTip())
       << "defaultToolTip for SELECT without FORM and without required "
diff --git a/third_party/blink/renderer/core/html/forms/spin_button_element.h b/third_party/blink/renderer/core/html/forms/spin_button_element.h
index 5db266d..6b1e0abc 100644
--- a/third_party/blink/renderer/core/html/forms/spin_button_element.h
+++ b/third_party/blink/renderer/core/html/forms/spin_button_element.h
@@ -105,8 +105,8 @@
 DEFINE_TYPE_CASTS(SpinButtonElement,
                   Node,
                   node,
-                  ToElement(node)->IsSpinButtonElement(),
-                  ToElement(node).IsSpinButtonElement());
+                  To<Element>(node)->IsSpinButtonElement(),
+                  To<Element>(node).IsSpinButtonElement());
 
 template <>
 struct DowncastTraits<SpinButtonElement> {
diff --git a/third_party/blink/renderer/core/html/forms/text_control_element.h b/third_party/blink/renderer/core/html/forms/text_control_element.h
index 97833d5..47c266d0 100644
--- a/third_party/blink/renderer/core/html/forms/text_control_element.h
+++ b/third_party/blink/renderer/core/html/forms/text_control_element.h
@@ -234,7 +234,8 @@
 };
 
 inline bool IsTextControl(const Node& node) {
-  return node.IsElementNode() && ToElement(node).IsTextControl();
+  auto* element = DynamicTo<Element>(node);
+  return element && element->IsTextControl();
 }
 inline bool IsTextControl(const Node* node) {
   return node && IsTextControl(*node);
diff --git a/third_party/blink/renderer/core/html/html_content_element.h b/third_party/blink/renderer/core/html/html_content_element.h
index ecc7ead9..83db8015 100644
--- a/third_party/blink/renderer/core/html/html_content_element.h
+++ b/third_party/blink/renderer/core/html/html_content_element.h
@@ -88,9 +88,10 @@
     return true;
   if (!IsSelectValid())
     return false;
-  if (!siblings[nth]->IsElementNode())
+  auto* element = DynamicTo<Element>(siblings[nth].Get());
+  if (!element)
     return false;
-  return MatchSelector(*ToElement(siblings[nth]));
+  return MatchSelector(*element);
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/html/html_details_element.cc b/third_party/blink/renderer/core/html/html_details_element.cc
index 05eb10eb..4fdb511 100644
--- a/third_party/blink/renderer/core/html/html_details_element.cc
+++ b/third_party/blink/renderer/core/html/html_details_element.cc
@@ -102,7 +102,7 @@
   HTMLSlotElement* slot = To<HTMLSlotElement>(element);
   DCHECK(slot->firstChild());
   CHECK(IsHTMLSummaryElement(*slot->firstChild()));
-  return ToElement(slot->firstChild());
+  return To<Element>(slot->firstChild());
 }
 
 void HTMLDetailsElement::ParseAttribute(
diff --git a/third_party/blink/renderer/core/html/html_dialog_element.cc b/third_party/blink/renderer/core/html/html_dialog_element.cc
index dfaff74..67180791 100644
--- a/third_party/blink/renderer/core/html/html_dialog_element.cc
+++ b/third_party/blink/renderer/core/html/html_dialog_element.cc
@@ -54,9 +54,9 @@
                ? FlatTreeTraversal::NextSkippingChildren(*node, dialog)
                : FlatTreeTraversal::Next(*node, dialog);
 
-    if (!node->IsElementNode())
+    auto* element = DynamicTo<Element>(node);
+    if (!element)
       continue;
-    Element* element = ToElement(node);
     if (element->IsFormControlElement()) {
       HTMLFormControlElement* control = ToHTMLFormControlElement(node);
       if (control->IsAutofocusable() && control->IsFocusable()) {
diff --git a/third_party/blink/renderer/core/html/html_element.cc b/third_party/blink/renderer/core/html/html_element.cc
index 089695c3..ddbb318 100644
--- a/third_party/blink/renderer/core/html/html_element.cc
+++ b/third_party/blink/renderer/core/html/html_element.cc
@@ -127,10 +127,10 @@
     return true;
   if (IsSVGSVGElement(node))
     return true;
-  if (node.IsElementNode() &&
-      ToElement(node).HasTagName(mathml_names::kMathTag))
+  auto* element = DynamicTo<Element>(node);
+  if (element && element->HasTagName(mathml_names::kMathTag))
     return true;
-  return !node.IsElementNode() && node.parentNode()->IsHTMLElement();
+  return !element && node.parentNode()->IsHTMLElement();
 }
 
 const WebFeature kNoWebFeature = static_cast<WebFeature>(0);
@@ -1044,19 +1044,19 @@
   Node* node = FlatTreeTraversal::FirstChild(*this);
   while (node) {
     // Skip bdi, script, style and text form controls.
+    auto* element = DynamicTo<Element>(node);
     if (DeprecatedEqualIgnoringCase(node->nodeName(), "bdi") ||
         IsHTMLScriptElement(*node) || IsHTMLStyleElement(*node) ||
-        (node->IsElementNode() && ToElement(node)->IsTextControl()) ||
-        (node->IsElementNode() &&
-         ToElement(node)->ShadowPseudoId() == "-webkit-input-placeholder")) {
+        (element && element->IsTextControl()) ||
+        (element && element->ShadowPseudoId() == "-webkit-input-placeholder")) {
       node = FlatTreeTraversal::NextSkippingChildren(*node, this);
       continue;
     }
 
     // Skip elements with valid dir attribute
-    if (node->IsElementNode()) {
+    if (auto* element_node = DynamicTo<Element>(node)) {
       AtomicString dir_attribute_value =
-          ToElement(node)->FastGetAttribute(kDirAttr);
+          element_node->FastGetAttribute(kDirAttr);
       if (IsValidDirAttribute(dir_attribute_value)) {
         node = FlatTreeTraversal::NextSkippingChildren(*node, this);
         continue;
diff --git a/third_party/blink/renderer/core/html/html_slot_element.cc b/third_party/blink/renderer/core/html/html_slot_element.cc
index dbcbbffd..3cbedb1 100644
--- a/third_party/blink/renderer/core/html/html_slot_element.cc
+++ b/third_party/blink/renderer/core/html/html_slot_element.cc
@@ -412,8 +412,8 @@
   for (auto& node : assigned_nodes_) {
     if (!change.TraverseChild(*node))
       continue;
-    if (node->IsElementNode())
-      ToElement(node)->RecalcStyle(change);
+    if (auto* element = DynamicTo<Element>(node.Get()))
+      element->RecalcStyle(change);
     else if (auto* text_node = DynamicTo<Text>(node.Get()))
       text_node->RecalcTextStyle(change);
   }
diff --git a/third_party/blink/renderer/core/html/html_slot_element_test.cc b/third_party/blink/renderer/core/html/html_slot_element_test.cc
index d501b022..085fe72 100644
--- a/third_party/blink/renderer/core/html/html_slot_element_test.cc
+++ b/third_party/blink/renderer/core/html/html_slot_element_test.cc
@@ -157,16 +157,16 @@
   shadow_root.SetInnerHTMLFromString(
       R"HTML(<span><slot /></span>)HTML");
 
-  Element& shadow_span = *ToElement(shadow_root.firstChild());
+  auto* shadow_span = To<Element>(shadow_root.firstChild());
   GetDocument().View()->UpdateAllLifecyclePhases(
       DocumentLifecycle::LifecycleUpdateReason::kTest);
 
-  shadow_span.setAttribute(html_names::kStyleAttr, "display:block");
+  shadow_span->setAttribute(html_names::kStyleAttr, "display:block");
 
   GetDocument().Lifecycle().AdvanceTo(DocumentLifecycle::kInStyleRecalc);
   GetDocument().GetStyleEngine().RecalcStyle({});
 
-  EXPECT_TRUE(shadow_span.GetComputedStyle());
+  EXPECT_TRUE(shadow_span->GetComputedStyle());
   EXPECT_TRUE(span.GetComputedStyle());
 }
 
diff --git a/third_party/blink/renderer/core/html/html_summary_element.cc b/third_party/blink/renderer/core/html/html_summary_element.cc
index 75b2d11..9ac4c1b 100644
--- a/third_party/blink/renderer/core/html/html_summary_element.cc
+++ b/third_party/blink/renderer/core/html/html_summary_element.cc
@@ -87,9 +87,9 @@
 }
 
 static bool IsClickableControl(Node* node) {
-  if (!node->IsElementNode())
+  auto* element = DynamicTo<Element>(node);
+  if (!element)
     return false;
-  Element* element = ToElement(node);
   if (element->IsFormControlElement())
     return true;
   Element* host = element->OwnerShadowHost();
diff --git a/third_party/blink/renderer/core/html/html_view_source_document.cc b/third_party/blink/renderer/core/html/html_view_source_document.cc
index 1f07036c..26fd34d 100644
--- a/third_party/blink/renderer/core/html/html_view_source_document.cc
+++ b/third_party/blink/renderer/core/html/html_view_source_document.cc
@@ -289,7 +289,7 @@
   }
   AddText(text, class_name);
   if (!class_name.IsEmpty() && current_ != tbody_)
-    current_ = ToElement(current_->parentNode());
+    current_ = To<Element>(current_->parentNode());
   return end;
 }
 
@@ -337,7 +337,7 @@
       AtomicString link(tmp[0]);
       current_ = AddLink(link, false);
       AddText(srclist[i], "html-attribute-value");
-      current_ = ToElement(current_->parentNode());
+      current_ = To<Element>(current_->parentNode());
     } else {
       AddText(srclist[i], "html-attribute-value");
     }
diff --git a/third_party/blink/renderer/core/html/parser/html_construction_site.cc b/third_party/blink/renderer/core/html/parser/html_construction_site.cc
index b1385c63..4b2bf649 100644
--- a/third_party/blink/renderer/core/html/parser/html_construction_site.cc
+++ b/third_party/blink/renderer/core/html/parser/html_construction_site.cc
@@ -295,8 +295,9 @@
 void HTMLConstructionSite::AttachLater(ContainerNode* parent,
                                        Node* child,
                                        bool self_closing) {
-  DCHECK(ScriptingContentIsAllowed(parser_content_policy_) ||
-         !child->IsElementNode() || !ToElement(child)->IsScriptElement());
+  auto* element = DynamicTo<Element>(child);
+  DCHECK(ScriptingContentIsAllowed(parser_content_policy_) || !element ||
+         !element->IsScriptElement());
   DCHECK(PluginContentIsAllowed(parser_content_policy_) ||
          !IsHTMLPlugInElement(child));
 
diff --git a/third_party/blink/renderer/core/html/parser/html_element_stack.cc b/third_party/blink/renderer/core/html/parser/html_element_stack.cc
index 87d6b262b..5132af6 100644
--- a/third_party/blink/renderer/core/html/parser/html_element_stack.cc
+++ b/third_party/blink/renderer/core/html/parser/html_element_stack.cc
@@ -165,8 +165,9 @@
   stack_depth_ = 0;
   while (top_) {
     Node& node = *TopNode();
-    if (node.IsElementNode()) {
-      ToElement(node).FinishParsingChildren();
+    auto* element = DynamicTo<Element>(node);
+    if (element) {
+      element->FinishParsingChildren();
       if (auto* select = ToHTMLSelectElementOrNull(node))
         select->SetBlocksFormSubmission(true);
     }
@@ -470,7 +471,7 @@
 
 Element* HTMLElementStack::HtmlElement() const {
   DCHECK(root_node_);
-  return ToElement(root_node_);
+  return To<Element>(root_node_.Get());
 }
 
 Element* HTMLElementStack::HeadElement() const {
diff --git a/third_party/blink/renderer/core/html/parser/html_stack_item.h b/third_party/blink/renderer/core/html/parser/html_stack_item.h
index e300375..d81933a 100644
--- a/third_party/blink/renderer/core/html/parser/html_stack_item.h
+++ b/third_party/blink/renderer/core/html/parser/html_stack_item.h
@@ -64,7 +64,7 @@
         namespace_uri_(namespace_uri),
         is_document_fragment_node_(false) {}
 
-  Element* GetElement() const { return ToElement(node_.Get()); }
+  Element* GetElement() const { return To<Element>(node_.Get()); }
   ContainerNode* GetNode() const { return node_.Get(); }
 
   bool IsDocumentFragmentNode() const { return is_document_fragment_node_; }
diff --git a/third_party/blink/renderer/core/html/shadow/progress_shadow_element_test.cc b/third_party/blink/renderer/core/html/shadow/progress_shadow_element_test.cc
index d395dc21..97728d0 100644
--- a/third_party/blink/renderer/core/html/shadow/progress_shadow_element_test.cc
+++ b/third_party/blink/renderer/core/html/shadow/progress_shadow_element_test.cc
@@ -34,7 +34,7 @@
       ToHTMLProgressElement(GetDocument().getElementById("prog"));
   ASSERT_TRUE(progress);
 
-  Element* shadow_element = ToElement(progress->GetShadowRoot()->firstChild());
+  auto* shadow_element = To<Element>(progress->GetShadowRoot()->firstChild());
   ASSERT_TRUE(shadow_element);
 
   GetDocument().View()->UpdateAllLifecyclePhases(
diff --git a/third_party/blink/renderer/core/html/track/vtt/vtt_cue.cc b/third_party/blink/renderer/core/html/track/vtt/vtt_cue.cc
index 703a840..d21f5a2a 100644
--- a/third_party/blink/renderer/core/html/track/vtt/vtt_cue.cc
+++ b/third_party/blink/renderer/core/html/track/vtt/vtt_cue.cc
@@ -786,7 +786,7 @@
       child_vtt_element->SetIsPastNode(is_past_node);
       // Make an elemenet id match a cue id for style matching purposes.
       if (!id().IsEmpty())
-        ToElement(child).SetIdAttribute(id());
+        To<Element>(child).SetIdAttribute(id());
     }
   }
 }
diff --git a/third_party/blink/renderer/core/input/event_handler_test.cc b/third_party/blink/renderer/core/input/event_handler_test.cc
index ccfd1ca..dd33d45 100644
--- a/third_party/blink/renderer/core/input/event_handler_test.cc
+++ b/third_party/blink/renderer/core/input/event_handler_test.cc
@@ -540,7 +540,7 @@
 
 TEST_F(EventHandlerTest, ImagesCannotStartSelection) {
   SetHtmlInnerHTML("<img>");
-  Element* const img = ToElement(GetDocument().body()->firstChild());
+  auto* const img = To<Element>(GetDocument().body()->firstChild());
   HitTestLocation location(
       img->GetLayoutObject()->AbsoluteBoundingBoxRect().Center());
   HitTestResult hit =
diff --git a/third_party/blink/renderer/core/input/gesture_manager.cc b/third_party/blink/renderer/core/input/gesture_manager.cc
index d73ace65..77ef8b8 100644
--- a/third_party/blink/renderer/core/input/gesture_manager.cc
+++ b/third_party/blink/renderer/core/input/gesture_manager.cc
@@ -292,9 +292,7 @@
       tapped_element->UpdateDistributionForFlatTreeTraversal();
       Node* click_target_node = current_hit_test.InnerNode()->CommonAncestor(
           *tapped_element, event_handling_util::ParentForClickEvent);
-      Element* click_target_element = nullptr;
-      if (click_target_node && click_target_node->IsElementNode())
-        click_target_element = ToElement(click_target_node);
+      auto* click_target_element = DynamicTo<Element>(click_target_node);
 
       click_event_result =
           mouse_event_manager_->SetMousePositionAndDispatchMouseEvent(
diff --git a/third_party/blink/renderer/core/input/mouse_event_manager.cc b/third_party/blink/renderer/core/input/mouse_event_manager.cc
index ba9d7871..a52c3aae 100644
--- a/third_party/blink/renderer/core/input/mouse_event_manager.cc
+++ b/third_party/blink/renderer/core/input/mouse_event_manager.cc
@@ -45,10 +45,10 @@
 namespace {
 
 String CanvasRegionId(Node* node, const WebMouseEvent& mouse_event) {
-  if (!node->IsElementNode())
+  auto* element = DynamicTo<Element>(node);
+  if (!element)
     return String();
 
-  Element* element = ToElement(node);
   if (!element->IsInCanvasSubtree())
     return String();
 
diff --git a/third_party/blink/renderer/core/inspector/dom_patch_support.cc b/third_party/blink/renderer/core/inspector/dom_patch_support.cc
index 2dc2dbd..110f2a12 100644
--- a/third_party/blink/renderer/core/inspector/dom_patch_support.cc
+++ b/third_party/blink/renderer/core/inspector/dom_patch_support.cc
@@ -117,7 +117,7 @@
   // root children, as it provides an equivalent parsing context.
   if (target_node->IsShadowRoot())
     target_node = GetDocument().body();
-  Element* target_element = ToElement(target_node);
+  auto* target_element = To<Element>(target_node);
 
   // FIXME: This code should use one of createFragment* in Serialization.h
   if (GetDocument().IsHTMLDocument())
@@ -185,12 +185,12 @@
       return false;
   }
 
-  if (!old_node->IsElementNode())
+  auto* old_element = DynamicTo<Element>(old_node);
+  if (!old_element)
     return true;
 
   // Patch attributes
-  Element* old_element = ToElement(old_node);
-  Element* new_element = ToElement(new_node);
+  auto* new_element = To<Element>(new_node);
   if (old_digest->attrs_sha1_ != new_digest->attrs_sha1_) {
     // FIXME: Create a function in Element for removing all properties. Take in
     // account whether did/willModifyAttribute are important.
diff --git a/third_party/blink/renderer/core/inspector/inspect_tools.cc b/third_party/blink/renderer/core/inspector/inspect_tools.cc
index 17889b2..3a858776 100644
--- a/third_party/blink/renderer/core/inspector/inspect_tools.cc
+++ b/third_party/blink/renderer/core/inspector/inspect_tools.cc
@@ -33,13 +33,14 @@
 
 InspectorHighlightContrastInfo FetchContrast(Node* node) {
   InspectorHighlightContrastInfo result;
-  if (!node->IsElementNode())
+  auto* element = DynamicTo<Element>(node);
+  if (!element)
     return result;
 
   Vector<Color> bgcolors;
   String font_size;
   String font_weight;
-  InspectorCSSAgent::GetBackgroundColors(ToElement(node), &bgcolors, &font_size,
+  InspectorCSSAgent::GetBackgroundColors(element, &bgcolors, &font_size,
                                          &font_weight);
   if (bgcolors.size() == 1) {
     result.font_size = font_size;
diff --git a/third_party/blink/renderer/core/inspector/inspector_css_agent.cc b/third_party/blink/renderer/core/inspector/inspector_css_agent.cc
index fe39b43..1789bcd 100644
--- a/third_party/blink/renderer/core/inspector/inspector_css_agent.cc
+++ b/third_party/blink/renderer/core/inspector/inspector_css_agent.cc
@@ -169,9 +169,10 @@
       continue;
     if (node->IsPseudoElement() || node->IsTextNode())
       node = node->ParentOrShadowHostNode();
-    if (!node || node == previous_node || !node->IsElementNode())
+    auto* element = DynamicTo<Element>(node);
+    if (!node || node == previous_node || !element)
       continue;
-    elements.push_back(ToElement(node));
+    elements.push_back(element);
     previous_node = node;
   }
   return elements;
@@ -2135,7 +2136,7 @@
 void InspectorCSSAgent::ResetPseudoStates() {
   HeapHashSet<Member<Document>> documents_to_change;
   for (auto& state : node_id_to_forced_pseudo_state_) {
-    Element* element = ToElement(dom_agent_->NodeForId(state.key));
+    auto* element = To<Element>(dom_agent_->NodeForId(state.key));
     if (element && element->ownerDocument())
       documents_to_change.insert(element->ownerDocument());
   }
diff --git a/third_party/blink/renderer/core/inspector/inspector_dom_agent.cc b/third_party/blink/renderer/core/inspector/inspector_dom_agent.cc
index 84067ff..ae49f3f5 100644
--- a/third_party/blink/renderer/core/inspector/inspector_dom_agent.cc
+++ b/third_party/blink/renderer/core/inspector/inspector_dom_agent.cc
@@ -322,8 +322,8 @@
   if (ShadowRoot* root = node->GetShadowRoot())
     Unbind(root, nodes_map);
 
-  if (node->IsElementNode()) {
-    Element* element = ToElement(node);
+  auto* element = DynamicTo<Element>(node);
+  if (element) {
     if (element->GetPseudoElement(kPseudoIdBefore))
       Unbind(element->GetPseudoElement(kPseudoIdBefore), nodes_map);
     if (element->GetPseudoElement(kPseudoIdAfter))
@@ -387,9 +387,9 @@
   if (!response.isSuccess())
     return response;
 
-  if (!node->IsElementNode())
+  element = DynamicTo<Element>(node);
+  if (!element)
     return Response::Error("Node is not an Element");
-  element = ToElement(node);
   return Response::OK();
 }
 
@@ -766,10 +766,7 @@
     fragment->ParseXML(markup, contextElement, kAllowScriptingContent);
   }
 
-  Element* parsed_element =
-      fragment->firstChild() && fragment->firstChild()->IsElementNode()
-          ? ToElement(fragment->firstChild())
-          : nullptr;
+  Element* parsed_element = DynamicTo<Element>(fragment->firstChild());
   if (!parsed_element)
     return Response::Error("Could not parse value as attributes");
 
@@ -1033,7 +1030,7 @@
             break;
           }
           // Go through all attributes and serialize them.
-          const Element* element = ToElement(node);
+          const auto* element = To<Element>(node);
           AttributeCollection attributes = element->Attributes();
           for (auto& attribute : attributes) {
             // Add attribute pair
@@ -1252,9 +1249,9 @@
   Response response = AssertNode(node_id, backend_node_id, object_id, node);
   if (!response.isSuccess())
     return response;
-  if (!node->IsElementNode())
+  auto* element = DynamicTo<Element>(node);
+  if (!element)
     return Response::Error("Node is not an Element");
-  Element* element = ToElement(node);
   element->GetDocument().UpdateStyleAndLayout();
   if (!element->IsFocusable())
     return Response::Error("Element is not focusable");
@@ -1445,7 +1442,7 @@
       local_name = To<Attr>(node)->localName();
       break;
     case Node::kElementNode:
-      local_name = ToElement(node)->localName();
+      local_name = To<Element>(node)->localName();
       break;
     default:
       break;
@@ -1465,8 +1462,7 @@
     value->setIsSVG(true);
 
   bool force_push_children = false;
-  if (node->IsElementNode()) {
-    Element* element = ToElement(node);
+  if (auto* element = DynamicTo<Element>(node)) {
     value->setAttributes(BuildArrayForElementAttributes(element));
 
     if (auto* frame_owner = DynamicTo<HTMLFrameOwnerElement>(node)) {
@@ -1764,8 +1760,8 @@
   if (--depth <= 0)
     return;
 
-  if (pierce && node->IsElementNode()) {
-    Element* element = ToElement(node);
+  auto* element = DynamicTo<Element>(node);
+  if (pierce && element) {
     if (auto* frame_owner = DynamicTo<HTMLFrameOwnerElement>(node)) {
       if (frame_owner->ContentFrame() &&
           frame_owner->ContentFrame()->IsLocalFrame()) {
@@ -1978,7 +1974,7 @@
   if (!id)
     return;
 
-  RevalidateTask()->ScheduleStyleAttrRevalidationFor(ToElement(node));
+  RevalidateTask()->ScheduleStyleAttrRevalidationFor(To<Element>(node));
 }
 
 void InspectorDOMAgent::DidPushShadowRoot(Element* host, ShadowRoot* root) {
@@ -2089,12 +2085,13 @@
 }
 
 static ShadowRoot* ShadowRootForNode(Node* node, const String& type) {
-  if (!node->IsElementNode())
+  auto* element = DynamicTo<Element>(node);
+  if (!element)
     return nullptr;
   if (type == "a")
-    return ToElement(node)->AuthorShadowRoot();
+    return element->AuthorShadowRoot();
   if (type == "u")
-    return ToElement(node)->UserAgentShadowRoot();
+    return element->UserAgentShadowRoot();
   return nullptr;
 }
 
diff --git a/third_party/blink/renderer/core/inspector/inspector_dom_snapshot_agent.cc b/third_party/blink/renderer/core/inspector/inspector_dom_snapshot_agent.cc
index 6e72fa0..5cdf35d 100644
--- a/third_party/blink/renderer/core/inspector/inspector_dom_snapshot_agent.cc
+++ b/third_party/blink/renderer/core/inspector/inspector_dom_snapshot_agent.cc
@@ -416,8 +416,8 @@
     }
   }
 
-  if (node->IsElementNode()) {
-    Element* element = ToElement(node);
+  auto* element = DynamicTo<Element>(node);
+  if (element) {
     value->setAttributes(BuildArrayForElementAttributes(element));
 
     if (auto* frame_owner = DynamicTo<HTMLFrameOwnerElement>(node)) {
@@ -651,8 +651,8 @@
   if (node->WillRespondToMouseClickEvents())
     SetRare(nodes->getIsClickable(nullptr), index);
 
-  if (node->IsElementNode()) {
-    Element* element = ToElement(node);
+  auto* element = DynamicTo<Element>(node);
+  if (element) {
     if (auto* frame_owner = DynamicTo<HTMLFrameOwnerElement>(node)) {
       if (Document* doc = frame_owner->contentDocument()) {
         SetRare(nodes->getContentDocumentIndex(nullptr), index,
@@ -842,9 +842,10 @@
 std::unique_ptr<protocol::Array<int>>
 InspectorDOMSnapshotAgent::BuildArrayForElementAttributes2(Node* node) {
   auto result = protocol::Array<int>::create();
-  if (!node->IsElementNode())
+  auto* element = DynamicTo<Element>(node);
+  if (!element)
     return result;
-  AttributeCollection attributes = ToElement(node)->Attributes();
+  AttributeCollection attributes = element->Attributes();
   for (const auto& attribute : attributes) {
     result->addItem(AddString(attribute.GetName().ToString()));
     result->addItem(AddString(attribute.Value()));
@@ -935,8 +936,7 @@
         layout_tree_snapshot->getScrollRects(nullptr);
     DCHECK(scrollRects);
 
-    if (node->IsElementNode()) {
-      auto* element = ToElement(node);
+    if (auto* element = DynamicTo<Element>(node)) {
       offsetRects->addItem(
           BuildRectForLayout(element->OffsetLeft(), element->OffsetTop(),
                              element->OffsetWidth(), element->OffsetHeight()));
diff --git a/third_party/blink/renderer/core/inspector/inspector_highlight.cc b/third_party/blink/renderer/core/inspector/inspector_highlight.cc
index 2c073e5a..4a92437 100644
--- a/third_party/blink/renderer/core/inspector/inspector_highlight.cc
+++ b/third_party/blink/renderer/core/inspector/inspector_highlight.cc
@@ -466,8 +466,9 @@
   AppendPathsForShapeOutside(node, highlight_config);
   AppendNodeHighlight(node, highlight_config);
   auto* text_node = DynamicTo<Text>(node);
-  if (append_element_info && node->IsElementNode())
-    element_info_ = BuildElementInfo(ToElement(node));
+  auto* element = DynamicTo<Element>(node);
+  if (append_element_info && element)
+    element_info_ = BuildElementInfo(element);
   else if (append_element_info && text_node)
     element_info_ = BuildTextNodeInfo(text_node);
   if (element_info_ && highlight_config.show_styles)
@@ -523,9 +524,7 @@
   if (layout_object)
     AddLayoutBoxToDistanceInfo(layout_object);
 
-  if (node->IsElementNode()) {
-    Element* element = ToElement(node);
-
+  if (auto* element = DynamicTo<Element>(node)) {
     if (element->GetPseudoId()) {
       if (layout_object)
         VisitAndCollectDistanceInfo(element->GetPseudoId(), layout_object);
diff --git a/third_party/blink/renderer/core/inspector/inspector_style_sheet.cc b/third_party/blink/renderer/core/inspector/inspector_style_sheet.cc
index dda59f9..3422e21e 100644
--- a/third_party/blink/renderer/core/inspector/inspector_style_sheet.cc
+++ b/third_party/blink/renderer/core/inspector/inspector_style_sheet.cc
@@ -1858,9 +1858,9 @@
 
 Element* InspectorStyleSheet::OwnerStyleElement() {
   Node* owner_node = page_style_sheet_->ownerNode();
-  if (!owner_node || !owner_node->IsElementNode())
+  auto* owner_element = DynamicTo<Element>(owner_node);
+  if (!owner_element)
     return nullptr;
-  Element* owner_element = ToElement(owner_node);
 
   if (!IsHTMLStyleElement(owner_element) && !IsSVGStyleElement(owner_element))
     return nullptr;
diff --git a/third_party/blink/renderer/core/invisible_dom/invisible_dom.cc b/third_party/blink/renderer/core/invisible_dom/invisible_dom.cc
index dc13370..2114664 100644
--- a/third_party/blink/renderer/core/invisible_dom/invisible_dom.cc
+++ b/third_party/blink/renderer/core/invisible_dom/invisible_dom.cc
@@ -15,8 +15,8 @@
   if (!node.CanParticipateInFlatTree())
     return false;
   for (Node& ancestor : FlatTreeTraversal::InclusiveAncestorsOf(node)) {
-    if (ancestor.IsElementNode() &&
-        ToElement(ancestor).HasInvisibleAttribute()) {
+    auto* element = DynamicTo<Element>(ancestor);
+    if (element && element->HasInvisibleAttribute()) {
       return true;
     }
   }
@@ -28,9 +28,9 @@
     return nullptr;
   Element* root = nullptr;
   for (Node& ancestor : FlatTreeTraversal::InclusiveAncestorsOf(node)) {
-    if (ancestor.IsElementNode() &&
-        ToElement(ancestor).HasInvisibleAttribute()) {
-      root = &ToElement(ancestor);
+    auto* element = DynamicTo<Element>(ancestor);
+    if (element && element->HasInvisibleAttribute()) {
+      root = element;
     }
   }
   return root;
@@ -47,8 +47,9 @@
     if (!InvisibleDOM::IsInsideInvisibleSubtree(node))
       continue;
     for (Node& ancestor_node : FlatTreeTraversal::AncestorsOf(node)) {
-      if (ancestor_node.IsElementNode()) {
-        elements_to_activate.push_back(ToElement(ancestor_node));
+      auto* element = DynamicTo<Element>(ancestor_node);
+      if (element) {
+        elements_to_activate.push_back(element);
         break;
       }
     }
diff --git a/third_party/blink/renderer/core/layout/jank_tracker.cc b/third_party/blink/renderer/core/layout/jank_tracker.cc
index 7fd9bfae..bda98ab 100644
--- a/third_party/blink/renderer/core/layout/jank_tracker.cc
+++ b/third_party/blink/renderer/core/layout/jank_tracker.cc
@@ -27,6 +27,8 @@
 
 static constexpr TimeDelta kTimerDelay = TimeDelta::FromMilliseconds(500);
 static const float kRegionGranularitySteps = 60.0;
+// TODO: Vary by Finch experiment parameter.
+static const float kSweepLineRegionGranularity = 1.0;
 static const float kMovementThreshold = 3.0;  // CSS pixels.
 
 static FloatPoint LogicalStart(const FloatRect& rect,
@@ -49,7 +51,7 @@
 
 static float RegionGranularityScale(const IntRect& viewport) {
   if (RuntimeEnabledFeatures::JankTrackingSweepLineEnabled())
-    return 1;
+    return kSweepLineRegionGranularity;
 
   return kRegionGranularitySteps /
          std::min(viewport.Height(), viewport.Width());
@@ -275,13 +277,15 @@
     return;
 
   IntRect viewport = frame_view_->GetScrollableArea()->VisibleContentRect();
-  double granularity_scale = RegionGranularityScale(viewport);
-  viewport.Scale(granularity_scale);
-
   if (viewport.IsEmpty())
     return;
 
-  double viewport_area = double(viewport.Width()) * double(viewport.Height());
+  double granularity_scale = RegionGranularityScale(viewport);
+  IntRect scaled_viewport = viewport;
+  scaled_viewport.Scale(granularity_scale);
+
+  double viewport_area =
+      double(scaled_viewport.Width()) * double(scaled_viewport.Height());
   uint64_t region_area =
       use_sweep_line ? region_experimental_.Area() : region_.Area();
   double jank_fraction = region_area / viewport_area;
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 662f0d2..9b9feab 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
@@ -1022,8 +1022,14 @@
     auto_margins.inline_end = opportunity.rect.InlineSize() -
                               fragment.InlineSize() - auto_margins.inline_start;
   } else {
+    LayoutUnit inline_size = fragment.InlineSize();
+    // Negative margins are not used to determine opportunity, but need to take
+    // them into account for positioning.
+    LayoutUnit inline_margin = child_data.margins.InlineSum();
+    if (inline_margin < 0)
+      inline_size += inline_margin;
     ResolveInlineMargins(child_style, Style(), opportunity.rect.InlineSize(),
-                         fragment.InlineSize(), &auto_margins);
+                         inline_size, &auto_margins);
   }
 
   LayoutUnit child_bfc_line_offset = opportunity.rect.start_offset.line_offset +
diff --git a/third_party/blink/renderer/devtools/front_end/inspector_main/inspector_main_strings.grdp b/third_party/blink/renderer/devtools/front_end/inspector_main/inspector_main_strings.grdp
index a50e0df..c037edab 100644
--- a/third_party/blink/renderer/devtools/front_end/inspector_main/inspector_main_strings.grdp
+++ b/third_party/blink/renderer/devtools/front_end/inspector_main/inspector_main_strings.grdp
@@ -18,6 +18,9 @@
   <message name="IDS_DEVTOOLS_1808fb32cf4e8a03daa326b48d4246eb" desc="">
     Disable paused state overlay
   </message>
+  <message name="IDS_DEVTOOLS_1e7cf45a622bb0fe494f9e4da1016982" desc="">
+    Layout Shift Regions
+  </message>
   <message name="IDS_DEVTOOLS_2b1a578586beb46008e1542e9283ad99" desc="">
     Scrolling performance issues
   </message>
@@ -63,6 +66,9 @@
   <message name="IDS_DEVTOOLS_886f598a8a9e6a4bfe0c09fcf7779611" desc="">
     Emulate a focused page
   </message>
+  <message name="IDS_DEVTOOLS_901fd018d4023042914dedd5fee7f0d6" desc="">
+    Highlights areas of the page (blue) that were shifted
+  </message>
   <message name="IDS_DEVTOOLS_9182eda0635ccdc88276ba9e013c5c1b" desc="">
     Do not emulate a focused page
   </message>
diff --git a/third_party/blink/renderer/devtools/front_end/profiler/LiveHeapProfileView.js b/third_party/blink/renderer/devtools/front_end/profiler/LiveHeapProfileView.js
index 12ee406..5a360ba1 100644
--- a/third_party/blink/renderer/devtools/front_end/profiler/LiveHeapProfileView.js
+++ b/third_party/blink/renderer/devtools/front_end/profiler/LiveHeapProfileView.js
@@ -11,6 +11,34 @@
     /** @type {!Map<string, !Profiler.LiveHeapProfileView.GridNode>} */
     this._gridNodeByUrl = new Map();
     this.registerRequiredCSS('profiler/liveHeapProfile.css');
+
+    this._setting = Common.settings.moduleSetting('memoryLiveHeapProfile');
+    const toolbar = new UI.Toolbar('live-heap-profile-toolbar', this.contentElement);
+
+    this._toggleRecordAction =
+        /** @type {!UI.Action }*/ (UI.actionRegistry.action('live-heap-profile.toggle-recording'));
+    this._toggleRecordButton = UI.Toolbar.createActionButton(this._toggleRecordAction);
+    this._toggleRecordButton.setToggled(this._setting.get());
+    toolbar.appendToolbarItem(this._toggleRecordButton);
+
+    const mainTarget = SDK.targetManager.mainTarget();
+    if (mainTarget && mainTarget.model(SDK.ResourceTreeModel)) {
+      const startWithReloadAction =
+          /** @type {!UI.Action }*/ (UI.actionRegistry.action('live-heap-profile.start-with-reload'));
+      this._startWithReloadButton = UI.Toolbar.createActionButton(startWithReloadAction);
+      toolbar.appendToolbarItem(this._startWithReloadButton);
+    }
+
+    this._dataGrid = this._createDataGrid();
+    this._dataGrid.asWidget().show(this.contentElement);
+
+    this._currentPollId = 0;
+  }
+
+  /**
+   * @return {!DataGrid.SortableDataGrid}
+   */
+  _createDataGrid() {
     const columns = [
       {
         id: 'size',
@@ -19,19 +47,31 @@
         fixedWidth: true,
         sortable: true,
         align: DataGrid.DataGrid.Align.Right,
-        sort: DataGrid.DataGrid.Order.Descending
+        sort: DataGrid.DataGrid.Order.Descending,
+        tooltip: ls`Allocated JS heap size currently in use`,
       },
-      {id: 'isolates', title: ls`VMs`, width: '40px', fixedWidth: true, align: DataGrid.DataGrid.Align.Right},
-      {id: 'url', title: ls`Script URL`, fixedWidth: false, sortable: true}
+      {
+        id: 'isolates',
+        title: ls`VMs`,
+        width: '40px',
+        fixedWidth: true,
+        align: DataGrid.DataGrid.Align.Right,
+        tooltip: ls`Number of VMs sharing the same script source`
+      },
+      {id: 'url', title: ls`Script URL`, fixedWidth: false, sortable: true, tooltip: ls`URL of the script source`}
     ];
-    this._dataGrid = new DataGrid.SortableDataGrid(columns);
-    this._dataGrid.setResizeMethod(DataGrid.DataGrid.ResizeMethod.Last);
-    this._dataGrid.element.classList.add('flex-auto');
-    this._dataGrid.element.addEventListener('keydown', this._onKeyDown.bind(this), false);
-    this._dataGrid.addEventListener(DataGrid.DataGrid.Events.OpenedNode, this._revealSourceForSelectedNode, this);
-    this._dataGrid.addEventListener(DataGrid.DataGrid.Events.SortingChanged, this._sortingChanged, this);
-    this._dataGrid.asWidget().show(this.contentElement);
-    this._currentPollId = 0;
+    const dataGrid = new DataGrid.SortableDataGrid(columns);
+    dataGrid.setResizeMethod(DataGrid.DataGrid.ResizeMethod.Last);
+    dataGrid.element.classList.add('flex-auto');
+    dataGrid.element.addEventListener('keydown', this._onKeyDown.bind(this), false);
+    dataGrid.addEventListener(DataGrid.DataGrid.Events.OpenedNode, this._revealSourceForSelectedNode, this);
+    dataGrid.addEventListener(DataGrid.DataGrid.Events.SortingChanged, this._sortingChanged, this);
+    for (const info of columns) {
+      const headerCell = dataGrid.headerTableHeader(info.id);
+      if (headerCell)
+        headerCell.setAttribute('title', info.tooltip);
+    }
+    return dataGrid;
   }
 
   /**
@@ -39,6 +79,7 @@
    */
   wasShown() {
     this._poll();
+    this._setting.addChangeListener(this._settingChanged, this);
   }
 
   /**
@@ -46,6 +87,14 @@
    */
   willHide() {
     ++this._currentPollId;
+    this._setting.removeChangeListener(this._settingChanged, this);
+  }
+
+  /**
+   * @param {!Common.Event} value
+   */
+  _settingChanged(value) {
+    this._toggleRecordButton.setToggled(/** @type {boolean} */ (value.data));
   }
 
   async _poll() {
@@ -167,6 +216,33 @@
     const sortFunction = columnId === 'url' ? sortByUrl : sortBySize;
     this._dataGrid.sortNodes(sortFunction, this._dataGrid.isSortOrderAscending());
   }
+
+  _toggleRecording() {
+    const enable = !this._setting.get();
+    if (enable)
+      this._startRecording(false);
+    else
+      this._stopRecording();
+  }
+
+  /**
+   * @param {boolean=} reload
+   */
+  _startRecording(reload) {
+    this._setting.set(true);
+    if (!reload)
+      return;
+    const mainTarget = SDK.targetManager.mainTarget();
+    if (!mainTarget)
+      return;
+    const resourceTreeModel = /** @type {?SDK.ResourceTreeModel} */ (mainTarget.model(SDK.ResourceTreeModel));
+    if (resourceTreeModel)
+      resourceTreeModel.reloadPage();
+  }
+
+  async _stopRecording() {
+    this._setting.set(false);
+  }
 };
 
 Profiler.LiveHeapProfileView.GridNode = class extends DataGrid.SortableDataGridNode {
@@ -216,3 +292,41 @@
     return cell;
   }
 };
+
+/**
+ * @implements {UI.ActionDelegate}
+ */
+Profiler.LiveHeapProfileView.ActionDelegate = class {
+  /**
+   * @override
+   * @param {!UI.Context} context
+   * @param {string} actionId
+   * @return {boolean}
+   */
+  handleAction(context, actionId) {
+    (async () => {
+      const profileViewId = 'live_heap_profile';
+      await UI.viewManager.showView(profileViewId);
+      const widget = await UI.viewManager.view(profileViewId).widget();
+      this._innerHandleAction(/** @type {!Profiler.LiveHeapProfileView} */ (widget), actionId);
+    })();
+    return true;
+  }
+
+  /**
+   * @param {!Profiler.LiveHeapProfileView} profilerView
+   * @param {string} actionId
+   */
+  _innerHandleAction(profilerView, actionId) {
+    switch (actionId) {
+      case 'live-heap-profile.toggle-recording':
+        profilerView._toggleRecording();
+        break;
+      case 'live-heap-profile.start-with-reload':
+        profilerView._startRecording(true);
+        break;
+      default:
+        console.assert(false, `Unknown action: ${actionId}`);
+    }
+  }
+};
diff --git a/third_party/blink/renderer/devtools/front_end/profiler/liveHeapProfile.css b/third_party/blink/renderer/devtools/front_end/profiler/liveHeapProfile.css
index 4235455..357b296 100644
--- a/third_party/blink/renderer/devtools/front_end/profiler/liveHeapProfile.css
+++ b/third_party/blink/renderer/devtools/front_end/profiler/liveHeapProfile.css
@@ -17,3 +17,6 @@
     color: #999;
 }
 
+.toolbar {
+    border-bottom: 1px solid #ccc;
+}
\ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/profiler/module.json b/third_party/blink/renderer/devtools/front_end/profiler/module.json
index 5fb4ec3..12cd02d2 100644
--- a/third_party/blink/renderer/devtools/front_end/profiler/module.json
+++ b/third_party/blink/renderer/devtools/front_end/profiler/module.json
@@ -43,6 +43,33 @@
         },
         {
             "type": "action",
+            "actionId": "live-heap-profile.toggle-recording",
+            "iconClass": "largeicon-start-recording",
+            "toggledIconClass": "largeicon-stop-recording",
+            "toggleWithRedColor": true,
+            "className": "Profiler.LiveHeapProfileView.ActionDelegate",
+            "category": "Performance",
+            "options": [
+                {
+                    "value": true,
+                    "title": "Start recording heap allocations"
+                },
+                {
+                    "value": false,
+                    "title": "Stop recording heap allocations"
+                }
+            ]
+        },
+        {
+            "type": "action",
+            "actionId": "live-heap-profile.start-with-reload",
+            "iconClass": "largeicon-refresh",
+            "className": "Profiler.LiveHeapProfileView.ActionDelegate",
+            "category": "Performance",
+            "title": "Start recording heap allocations and reload the page"
+        },
+        {
+            "type": "action",
             "actionId": "profiler.heap-toggle-recording",
             "iconClass": "largeicon-start-recording",
             "toggledIconClass": "largeicon-stop-recording",
diff --git a/third_party/blink/renderer/devtools/front_end/profiler/profiler_strings.grdp b/third_party/blink/renderer/devtools/front_end/profiler/profiler_strings.grdp
index 9b5bb21d..e5992e5 100644
--- a/third_party/blink/renderer/devtools/front_end/profiler/profiler_strings.grdp
+++ b/third_party/blink/renderer/devtools/front_end/profiler/profiler_strings.grdp
@@ -18,6 +18,9 @@
   <message name="IDS_DEVTOOLS_04042b5589b3d4fd4e1e7e44265ad247" desc="">
     Total page JS heap size change trend over the last <ph name="TRENDINTERVALMINUTES">$1s</ph> minutes.
   </message>
+  <message name="IDS_DEVTOOLS_04e6490352d0b1a16a0391513cdd1b69" desc="">
+    Number of VMs sharing the same script source
+  </message>
   <message name="IDS_DEVTOOLS_05ce989cc1015cd221844376fc4cf206" desc="">
     Snapshot <ph name="PROFILE_UID">$1d</ph>
   </message>
@@ -168,6 +171,9 @@
   <message name="IDS_DEVTOOLS_60dcffb26f0ed1b0c73f8cea5d5d9772" desc="">
     Native memory allocation snapshot (<ph name="PROCESSTYPE">$1s</ph>)
   </message>
+  <message name="IDS_DEVTOOLS_610de28d957d1148614ecc6b2ec48443" desc="">
+    URL of the script source
+  </message>
   <message name="IDS_DEVTOOLS_61b4b76027d49142c386737a0e94cedb" desc="">
     NATIVE SNAPSHOTS
   </message>
@@ -177,6 +183,9 @@
   <message name="IDS_DEVTOOLS_678d0a4421b60dc59999ac02837496a6" desc="">
     Constructor
   </message>
+  <message name="IDS_DEVTOOLS_6a5084781ea4e6bf97a2dcd0cda17a1a" desc="">
+    Start recording heap allocations
+  </message>
   <message name="IDS_DEVTOOLS_6b59ba1fcfd868474cae169876f9cbfa" desc="">
     Native memory snapshots show sampled native allocations in the renderer process since start up.
               Chrome has to be started with --memlog=all flag. Check flags at chrome://flags
@@ -217,6 +226,9 @@
   <message name="IDS_DEVTOOLS_7ae47a5ac9257db8c7bb89c7afa4db7c" desc="">
     Take snapshot
   </message>
+  <message name="IDS_DEVTOOLS_7c2fa80073bfcabb697478facdd1209a" desc="">
+    Start recording heap allocations and reload the page
+  </message>
   <message name="IDS_DEVTOOLS_7cb94d94002a34c350cad72e6649c5fe" desc="">
     Stack was not recorded for this object because it had been allocated before this profile recording started.
   </message>
@@ -324,6 +336,9 @@
   <message name="IDS_DEVTOOLS_bd0a5e31e9b3c87eb2d3c19b00cedfc3" desc="">
     Heap memory usage
   </message>
+  <message name="IDS_DEVTOOLS_be1f3410c6bc2e72817218db717fa91c" desc="">
+    Allocated JS heap size currently in use
+  </message>
   <message name="IDS_DEVTOOLS_c22d30084d8ddc9a571512ddee6a83e9" desc="">
     Total time
   </message>
@@ -427,6 +442,9 @@
   <message name="IDS_DEVTOOLS_f6ff777632b4b524d2f203c78359eed2" desc="">
     Saving… <ph name="PERCENTVALUE">$1d</ph>%%
   </message>
+  <message name="IDS_DEVTOOLS_f7f9f5196d0888dc2cf6aa05be182e1f" desc="">
+    Stop recording heap allocations
+  </message>
   <message name="IDS_DEVTOOLS_fbbe8b507083defdbfe14a341551c77b" desc="">
     CPU profiles show where the execution time is spent in your page&apos;s JavaScript functions.
   </message>
diff --git a/third_party/blink/renderer/devtools/front_end/sdk/sdk_strings.grdp b/third_party/blink/renderer/devtools/front_end/sdk/sdk_strings.grdp
index 6353de9..5d42fda 100644
--- a/third_party/blink/renderer/devtools/front_end/sdk/sdk_strings.grdp
+++ b/third_party/blink/renderer/devtools/front_end/sdk/sdk_strings.grdp
@@ -153,6 +153,9 @@
   <message name="IDS_DEVTOOLS_9108ae673b7efa9620aec771edc9d4de" desc="">
     setTimeout fired
   </message>
+  <message name="IDS_DEVTOOLS_92907ecce0019f3a10f867cfd53dad0c" desc="">
+    Show layout shift regions
+  </message>
   <message name="IDS_DEVTOOLS_930c85a96d7227c515891c4f86a17c30" desc="">
     Disable JavaScript
   </message>
@@ -201,6 +204,9 @@
   <message name="IDS_DEVTOOLS_b600e0facf21b7d4a9a769a60b236ba1" desc="">
     Enable JavaScript
   </message>
+  <message name="IDS_DEVTOOLS_b9a5a0162829cba9db8b77daa75ec604" desc="">
+    Hide layout shift regions
+  </message>
   <message name="IDS_DEVTOOLS_ba50636875d999db0c9218b48b23027d" desc="">
     Do not capture async stack traces
   </message>
diff --git a/third_party/blink/renderer/modules/wake_lock/wake_lock_controller.cc b/third_party/blink/renderer/modules/wake_lock/wake_lock_controller.cc
index 25ee9105..2678fd03 100644
--- a/third_party/blink/renderer/modules/wake_lock/wake_lock_controller.cc
+++ b/third_party/blink/renderer/modules/wake_lock/wake_lock_controller.cc
@@ -12,7 +12,12 @@
 WakeLockController::WakeLockController(Document& document)
     : Supplement<Document>(document),
       ContextLifecycleObserver(&document),
-      PageVisibilityObserver(document.GetPage()) {}
+      PageVisibilityObserver(document.GetPage()),
+      state_records_{
+          MakeGarbageCollected<WakeLockStateRecord>(&document,
+                                                    WakeLockType::kScreen),
+          MakeGarbageCollected<WakeLockStateRecord>(&document,
+                                                    WakeLockType::kSystem)} {}
 
 const char WakeLockController::kSupplementName[] = "WakeLockController";
 
@@ -36,21 +41,17 @@
 
 void WakeLockController::AcquireWakeLock(WakeLockType type,
                                          ScriptPromiseResolver* resolver) {
-  // Use a reference so we can create an WakeLockStateRecord object on demand.
-  Member<WakeLockStateRecord>& state_record =
-      state_records_[static_cast<size_t>(type)];
-  if (!state_record) {
-    state_record =
-        MakeGarbageCollected<WakeLockStateRecord>(GetSupplementable(), type);
-  }
+  DCHECK_LE(type, WakeLockType::kMaxValue);
+  WakeLockStateRecord* state_record = state_records_[static_cast<size_t>(type)];
+  DCHECK(state_record);
   state_record->AcquireWakeLock(resolver);
 }
 
 void WakeLockController::ReleaseWakeLock(WakeLockType type,
                                          ScriptPromiseResolver* resolver) {
+  DCHECK_LE(type, WakeLockType::kMaxValue);
   WakeLockStateRecord* state_record = state_records_[static_cast<size_t>(type)];
-  if (!state_record)
-    return;
+  DCHECK(state_record);
   state_record->ReleaseWakeLock(resolver);
 }
 
diff --git a/third_party/blink/renderer/modules/wake_lock/wake_lock_controller_test.cc b/third_party/blink/renderer/modules/wake_lock/wake_lock_controller_test.cc
index de52b19..e44accb 100644
--- a/third_party/blink/renderer/modules/wake_lock/wake_lock_controller_test.cc
+++ b/third_party/blink/renderer/modules/wake_lock/wake_lock_controller_test.cc
@@ -72,29 +72,25 @@
   EXPECT_TRUE(system_lock.is_acquired());
 }
 
-TEST(WakeLockControllerTest, ReleaseWakeLockWithWrongType) {
+TEST(WakeLockControllerTest, ReleaseUnaquiredWakeLockRejectsPromise) {
   MockWakeLockService wake_lock_service;
   WakeLockTestingContext context(&wake_lock_service);
   auto& controller = WakeLockController::From(*context.GetDocument());
 
   MockWakeLock& screen_lock =
       wake_lock_service.get_wake_lock(WakeLockType::kScreen);
-  MockWakeLock& system_lock =
-      wake_lock_service.get_wake_lock(WakeLockType::kSystem);
 
   auto* resolver =
       MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState());
   ScriptPromise promise = resolver->Promise();
 
-  controller.AcquireWakeLock(WakeLockType::kScreen, resolver);
-  screen_lock.WaitForRequest();
-  controller.ReleaseWakeLock(WakeLockType::kSystem, resolver);
-
-  test::RunPendingTasks();
-
   EXPECT_EQ(v8::Promise::kPending, GetScriptPromiseState(promise));
-  EXPECT_TRUE(screen_lock.is_acquired());
-  EXPECT_FALSE(system_lock.is_acquired());
+  controller.ReleaseWakeLock(WakeLockType::kScreen, resolver);
+  context.WaitForPromiseRejection(promise);
+
+  // The promise is always rejected, even if it is not in [[ActiveLocks]].
+  EXPECT_EQ(v8::Promise::kRejected, GetScriptPromiseState(promise));
+  EXPECT_FALSE(screen_lock.is_acquired());
 }
 
 TEST(WakeLockControllerTest, ReleaseWakeLock) {
diff --git a/third_party/blink/renderer/modules/wake_lock/wake_lock_state_record.cc b/third_party/blink/renderer/modules/wake_lock/wake_lock_state_record.cc
index c060e4a..c5abb165 100644
--- a/third_party/blink/renderer/modules/wake_lock/wake_lock_state_record.cc
+++ b/third_party/blink/renderer/modules/wake_lock/wake_lock_state_record.cc
@@ -53,21 +53,17 @@
 }
 
 void WakeLockStateRecord::ReleaseWakeLock(ScriptPromiseResolver* resolver) {
-  ReleaseWakeLock(active_locks_.find(resolver));
-}
-
-void WakeLockStateRecord::ReleaseWakeLock(ActiveLocksType::iterator iterator) {
   // https://w3c.github.io/wake-lock/#release-wake-lock-algorithm
-  // 1. If record.[[ActiveLocks]] does not contain lockPromise, abort these
-  // steps.
-  if (iterator == active_locks_.end())
-    return;
-
-  // 2. Reject lockPromise with an "AbortError" DOMException.
-  ScriptPromiseResolver* resolver = *iterator;
+  // 1. Reject lockPromise with an "AbortError" DOMException.
   resolver->Reject(MakeGarbageCollected<DOMException>(
       DOMExceptionCode::kAbortError, "Wake Lock released"));
 
+  // 2. If record.[[ActiveLocks]] does not contain lockPromise, abort these
+  // steps.
+  auto iterator = active_locks_.find(resolver);
+  if (iterator == active_locks_.end())
+    return;
+
   // 3. Let document be the responsible document of the current settings object.
   // 4. Let record be the platform wake lock's state record associated with
   // document and type.
@@ -91,7 +87,7 @@
 
 void WakeLockStateRecord::ClearWakeLocks() {
   while (!active_locks_.IsEmpty())
-    ReleaseWakeLock(active_locks_.begin());
+    ReleaseWakeLock(*active_locks_.begin());
 }
 
 void WakeLockStateRecord::OnWakeLockConnectionError() {
diff --git a/third_party/blink/renderer/modules/wake_lock/wake_lock_state_record.h b/third_party/blink/renderer/modules/wake_lock/wake_lock_state_record.h
index ac01af4..bf6c4325 100644
--- a/third_party/blink/renderer/modules/wake_lock/wake_lock_state_record.h
+++ b/third_party/blink/renderer/modules/wake_lock/wake_lock_state_record.h
@@ -34,10 +34,6 @@
 
   friend class WakeLockControllerTest;
 
-  // Actually releases a given wake lock. Callers are responsible for passing a
-  // valid |iterator|.
-  void ReleaseWakeLock(ActiveLocksType::iterator iterator);
-
   // Handle connection errors from |wake_lock_|.
   void OnWakeLockConnectionError();
 
@@ -57,6 +53,7 @@
   FRIEND_TEST_ALL_PREFIXES(WakeLockStateRecordTest, ReleaseAllWakeLocks);
   FRIEND_TEST_ALL_PREFIXES(WakeLockStateRecordTest, ReleaseNonExistentWakeLock);
   FRIEND_TEST_ALL_PREFIXES(WakeLockStateRecordTest, ReleaseOneWakeLock);
+  FRIEND_TEST_ALL_PREFIXES(WakeLockStateRecordTest, ReleaseRejectsPromise);
   FRIEND_TEST_ALL_PREFIXES(WakeLockStateRecordTest, ClearWakeLocks);
   FRIEND_TEST_ALL_PREFIXES(WakeLockStateRecordTest, WakeLockConnectionError);
 };
diff --git a/third_party/blink/renderer/modules/wake_lock/wake_lock_state_record_test.cc b/third_party/blink/renderer/modules/wake_lock/wake_lock_state_record_test.cc
index f0c9c23..eae4954 100644
--- a/third_party/blink/renderer/modules/wake_lock/wake_lock_state_record_test.cc
+++ b/third_party/blink/renderer/modules/wake_lock/wake_lock_state_record_test.cc
@@ -160,6 +160,28 @@
   EXPECT_TRUE(screen_lock.is_acquired());
 }
 
+TEST(WakeLockStateRecordTest, ReleaseRejectsPromise) {
+  MockWakeLockService wake_lock_service;
+  WakeLockTestingContext context(&wake_lock_service);
+  auto* state_record = MakeStateRecord(context, WakeLockType::kScreen);
+
+  MockWakeLock& screen_lock =
+      wake_lock_service.get_wake_lock(WakeLockType::kScreen);
+
+  auto* resolver =
+      MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState());
+  ScriptPromise promise = resolver->Promise();
+
+  EXPECT_EQ(v8::Promise::kPending, GetScriptPromiseState(promise));
+
+  state_record->ReleaseWakeLock(resolver);
+  context.WaitForPromiseRejection(promise);
+
+  EXPECT_EQ(v8::Promise::kRejected, GetScriptPromiseState(promise));
+  EXPECT_EQ(0U, state_record->active_locks_.size());
+  EXPECT_FALSE(screen_lock.is_acquired());
+}
+
 TEST(WakeLockStateRecordTest, ClearEmptyActiveLocksList) {
   MockWakeLockService wake_lock_service;
   WakeLockTestingContext context(&wake_lock_service);
diff --git a/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.cc b/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.cc
index 964506b..5126e0a 100644
--- a/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.cc
+++ b/third_party/blink/renderer/platform/graphics/canvas_2d_layer_bridge.cc
@@ -58,7 +58,8 @@
     : logger_(std::make_unique<Logger>()),
       have_recorded_draw_commands_(false),
       is_hidden_(false),
-      is_deferral_enabled_(true),
+      is_deferral_enabled_(
+          base::FeatureList::IsEnabled(features::kCanvasAlwaysDeferral)),
       software_rendering_while_hidden_(false),
       acceleration_mode_(acceleration_mode),
       color_params_(color_params),
@@ -605,28 +606,9 @@
   return layer_.get();
 }
 
-void Canvas2DLayerBridge::DidDraw(const FloatRect& rect) {
-  if (!is_deferral_enabled_)
-    return;
-
-  have_recorded_draw_commands_ = true;
-  IntRect pixel_bounds = EnclosingIntRect(rect);
-  base::CheckedNumeric<int> pixel_bounds_size = pixel_bounds.Width();
-  pixel_bounds_size *= pixel_bounds.Height();
-  recording_pixel_count_ += pixel_bounds_size;
-  if (!recording_pixel_count_.IsValid()) {
-    DisableDeferral(kDisableDeferralReasonExpensiveOverdrawHeuristic);
-    return;
-  }
-  base::CheckedNumeric<int> threshold_size = size_.Width();
-  threshold_size *= size_.Height();
-  threshold_size *= canvas_heuristic_parameters::kExpensiveOverdrawThreshold;
-  if (!threshold_size.IsValid()) {
-    DisableDeferral(kDisableDeferralReasonExpensiveOverdrawHeuristic);
-    return;
-  }
-  if (recording_pixel_count_.ValueOrDie() >= threshold_size.ValueOrDie())
-    DisableDeferral(kDisableDeferralReasonExpensiveOverdrawHeuristic);
+void Canvas2DLayerBridge::DidDraw(const FloatRect& /* rect */) {
+  if (is_deferral_enabled_)
+    have_recorded_draw_commands_ = true;
 }
 
 void Canvas2DLayerBridge::FinalizeFrame() {
diff --git a/third_party/blink/renderer/platform/graphics/graphics_types.h b/third_party/blink/renderer/platform/graphics/graphics_types.h
index 2d485eb..c938ca49 100644
--- a/third_party/blink/renderer/platform/graphics/graphics_types.h
+++ b/third_party/blink/renderer/platform/graphics/graphics_types.h
@@ -128,7 +128,6 @@
 enum DisableDeferralReason {
   kDisableDeferralReasonUnknown =
       0,  // Should not appear in production histograms
-  kDisableDeferralReasonExpensiveOverdrawHeuristic = 1,
   kDisableDeferralReasonUsingTextureBackedPattern = 2,
   kDisableDeferralReasonDrawImageOfVideo = 3,
   kDisableDeferralReasonLowEndDevice = 7,
diff --git a/third_party/blink/renderer/platform/graphics/paint/paint_property_node.h b/third_party/blink/renderer/platform/graphics/paint/paint_property_node.h
index 81d7675..4e4b92f 100644
--- a/third_party/blink/renderer/platform/graphics/paint/paint_property_node.h
+++ b/third_party/blink/renderer/platform/graphics/paint/paint_property_node.h
@@ -155,10 +155,10 @@
 
  protected:
   PaintPropertyNode(const NodeType* parent, bool is_parent_alias = false)
-      : parent_(parent),
-        is_parent_alias_(is_parent_alias),
+      : is_parent_alias_(is_parent_alias),
         changed_(parent ? PaintPropertyChangeType::kNodeAddedOrRemoved
-                        : PaintPropertyChangeType::kUnchanged) {}
+                        : PaintPropertyChangeType::kUnchanged),
+        parent_(parent) {}
 
   PaintPropertyChangeType SetParent(const NodeType* parent) {
     DCHECK(!IsRoot());
@@ -183,13 +183,6 @@
   // Object paint properties can set the parent directly for an alias update.
   friend class ObjectPaintProperties;
 
-  scoped_refptr<const NodeType> parent_;
-
-  // Caches the id of the associated cc property node. It's valid only when
-  // cc_sequence_number_ matches the sequence number of the cc property tree.
-  mutable int cc_node_id_ = -1;
-  mutable int cc_sequence_number_ = 0;
-
   // Indicates whether this node is an alias for its parent. Parent aliases are
   // nodes that do not affect rendering and are ignored for the purposes of
   // display item list generation.
@@ -203,6 +196,13 @@
   // PaintController::FinishCycle.
   mutable PaintPropertyChangeType changed_;
 
+  scoped_refptr<const NodeType> parent_;
+
+  // Caches the id of the associated cc property node. It's valid only when
+  // cc_sequence_number_ matches the sequence number of the cc property tree.
+  mutable int cc_node_id_ = -1;
+  mutable int cc_sequence_number_ = 0;
+
 #if DCHECK_IS_ON()
   String debug_name_;
 #endif
diff --git a/third_party/blink/web_tests/external/wpt/css/CSS2/normal-flow/negative-margin-001-ref.html b/third_party/blink/web_tests/external/wpt/css/CSS2/normal-flow/negative-margin-001-ref.html
new file mode 100644
index 0000000..e98059a
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/CSS2/normal-flow/negative-margin-001-ref.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<style>
+html, body {
+  margin: 0;
+}
+html {
+  margin-left: 10px;
+}
+outer {
+  display: block;
+  border: blue 10px solid;
+  width: 100px;
+}
+inner {
+  display: block;
+  border: orange 10px solid;
+  margin-left: -20px;
+  margin-right: -50px;
+  height: 10px;
+}
+</style>
+<body>
+  <outer>
+    <inner></inner>
+  </outer>
+  <outer>
+    <inner></inner>
+  </outer>
+  <outer>
+    <inner></inner>
+  </outer>
+  <outer>
+    <inner></inner>
+  </outer>
+</body>
diff --git a/third_party/blink/web_tests/external/wpt/css/CSS2/normal-flow/negative-margin-001.html b/third_party/blink/web_tests/external/wpt/css/CSS2/normal-flow/negative-margin-001.html
new file mode 100644
index 0000000..597516d5
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/CSS2/normal-flow/negative-margin-001.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<title>Negative margins in LTR/RTL and BFC/non-BFC</title>
+<link rel="author" title="Koji Ishii" href="kojii@chromium.org">
+<link rel="help" href="https://www.w3.org/TR/CSS22/box.html#margin-properties" title="Margin properties">
+<link rel="match" href="negative-margin-001-ref.html">
+<style>
+html, body {
+  margin: 0;
+}
+html {
+  margin-left: 10px;
+}
+outer {
+  display: block;
+  border: blue 10px solid;
+  width: 100px;
+}
+inner {
+  display: block;
+  border: orange 10px solid;
+  margin-left: -20px;
+  margin-right: -50px;
+  height: 10px;
+}
+inner.bfc {
+  overflow: hidden;
+}
+</style>
+<body>
+  <outer>
+    <inner></inner>
+  </outer>
+  <outer dir="rtl">
+    <inner></inner>
+  </outer>
+  <outer>
+    <inner class="bfc"></inner>
+  </outer>
+  <outer dir="rtl">
+    <inner class="bfc"></inner>
+  </outer>
+</body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-flexbox/parsing/flex-computed.html b/third_party/blink/web_tests/external/wpt/css/css-flexbox/parsing/flex-computed.html
new file mode 100644
index 0000000..5f53986
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-flexbox/parsing/flex-computed.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>CSS Flexible Box Layout: getComputedValue().flex</title>
+<link rel="help" href="https://drafts.csswg.org/css-flexbox/#propdef-flex">
+<meta name="assert" content="flex computed value is specified keywords and/or computed <length-percentage>.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/computed-testcommon.js"></script>
+<style>
+  #target {
+    font-size: 40px;
+  }
+</style>
+</head>
+<body>
+<div id="target"></div>
+<script>
+test_computed_value("flex", "none", "0 0 auto");
+test_computed_value("flex", "1", "1 1 0%");
+test_computed_value("flex", "2 3", "2 3 0%");
+test_computed_value("flex", "4 5 6px");
+test_computed_value("flex", "7% 8", "8 1 7%");
+test_computed_value("flex", "8 auto", "8 1 auto");
+test_computed_value("flex", "calc(10px + 0.5em)", "1 1 30px");
+test_computed_value("flex", "calc(10px - 0.5em)", "1 1 0px");
+</script>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-multicol/parsing/column-rule-computed.html b/third_party/blink/web_tests/external/wpt/css/css-multicol/parsing/column-rule-computed.html
new file mode 100644
index 0000000..a0907cd
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-multicol/parsing/column-rule-computed.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>CSS Multi-column Layout: getComputedValue().columnRule</title>
+<link rel="help" href="https://drafts.csswg.org/css-multicol/#propdef-column-rule">
+<meta name="assert" content="column-rule computed value is as specified.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/computed-testcommon.js"></script>
+<style>
+  #reference {
+    column-rule-style: dotted; /* Avoid column-rule-width computed style 0px */
+    column-rule-width: medium;
+  }
+  #target {
+    color: lime;
+  }
+</style>
+</head>
+<body>
+<div id="reference"></div>
+<div id="target"></div>
+<script>
+const currentColor = 'rgb(0, 255, 0)';
+const mediumWidth = getComputedStyle(document.getElementById('reference')).columnRuleWidth; // e.g. 3px
+
+test_computed_value("column-rule", "10px", "0px none " + currentColor);
+test_computed_value("column-rule", "dotted", mediumWidth + " dotted " + currentColor);
+test_computed_value("column-rule", "0px none rgb(255, 0, 255)");
+test_computed_value("column-rule", "10px dotted rgb(255, 0, 255)");
+
+test_computed_value("column-rule", "medium hidden currentcolor", "0px hidden " + currentColor);
+test_computed_value("column-rule", "medium solid currentcolor", mediumWidth + " solid " + currentColor);
+</script>
+</body>
+</html>
diff --git a/third_party/polymer/v3_0/components-chromium/paper-ripple/paper-ripple.js b/third_party/polymer/v3_0/components-chromium/paper-ripple/paper-ripple.js
index 0288d836..4ad33bc 100644
--- a/third_party/polymer/v3_0/components-chromium/paper-ripple/paper-ripple.js
+++ b/third_party/polymer/v3_0/components-chromium/paper-ripple/paper-ripple.js
@@ -1,736 +1,253 @@
-/**
-@license
-Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
-This code may only be used under the BSD style license found at
-http://polymer.github.io/LICENSE.txt The complete set of authors may be found at
-http://polymer.github.io/AUTHORS.txt The complete set of contributors may be
-found at http://polymer.github.io/CONTRIBUTORS.txt Code distributed by Google as
-part of the polymer project is also subject to an additional IP rights grant
-found at http://polymer.github.io/PATENTS.txt
-*/
-import '../polymer/polymer_bundled.min.js';
-
 import {IronA11yKeysBehavior} from '../iron-a11y-keys-behavior/iron-a11y-keys-behavior.js';
-import {Polymer} from '../polymer/polymer_bundled.min.js';
-import {dom} from '../polymer/polymer_bundled.min.js';
-import {html} from '../polymer/polymer_bundled.min.js';
+import {Polymer, dom, html} from '../polymer/polymer_bundled.min.js';
 
-var Utility = {
-  distance: function(x1, y1, x2, y2) {
-    var xDelta = (x1 - x2);
-    var yDelta = (y1 - y2);
-
-    return Math.sqrt(xDelta * xDelta + yDelta * yDelta);
-  },
-
-  now: window.performance && window.performance.now ?
-      window.performance.now.bind(window.performance) :
-      Date.now
-};
+var MAX_RADIUS_PX = 300;
+var MIN_DURATION_MS = 800;
 
 /**
- * @param {HTMLElement} element
- * @constructor
+ * @param {number} x1
+ * @param {number} y1
+ * @param {number} x2
+ * @param {number} y2
+ * @return {number} The distance between (x1, y1) and (x2, y2).
  */
-function ElementMetrics(element) {
-  this.element = element;
-  this.width = this.boundingRect.width;
-  this.height = this.boundingRect.height;
-
-  this.size = Math.max(this.width, this.height);
-}
-
-ElementMetrics.prototype = {
-  get boundingRect() {
-    return this.element.getBoundingClientRect();
-  },
-
-  furthestCornerDistanceFrom: function(x, y) {
-    var topLeft = Utility.distance(x, y, 0, 0);
-    var topRight = Utility.distance(x, y, this.width, 0);
-    var bottomLeft = Utility.distance(x, y, 0, this.height);
-    var bottomRight = Utility.distance(x, y, this.width, this.height);
-
-    return Math.max(topLeft, topRight, bottomLeft, bottomRight);
-  }
+var distance = function(x1, y1, x2, y2) {
+  var xDelta = x1 - x2;
+  var yDelta = y1 - y2;
+  return Math.sqrt(xDelta * xDelta + yDelta * yDelta);
 };
 
-/**
- * @param {HTMLElement} element
- * @constructor
- */
-function Ripple(element) {
-  this.element = element;
-  this.color = window.getComputedStyle(element).color;
-
-  this.wave = document.createElement('div');
-  this.waveContainer = document.createElement('div');
-  this.wave.style.backgroundColor = this.color;
-  this.wave.classList.add('wave');
-  this.waveContainer.classList.add('wave-container');
-  dom(this.waveContainer).appendChild(this.wave);
-
-  this.resetInteractionState();
-}
-
-Ripple.MAX_RADIUS = 300;
-
-Ripple.prototype = {
-  get recenters() {
-    return this.element.recenters;
-  },
-
-  get center() {
-    return this.element.center;
-  },
-
-  get mouseDownElapsed() {
-    var elapsed;
-
-    if (!this.mouseDownStart) {
-      return 0;
-    }
-
-    elapsed = Utility.now() - this.mouseDownStart;
-
-    if (this.mouseUpStart) {
-      elapsed -= this.mouseUpElapsed;
-    }
-
-    return elapsed;
-  },
-
-  get mouseUpElapsed() {
-    return this.mouseUpStart ? Utility.now() - this.mouseUpStart : 0;
-  },
-
-  get mouseDownElapsedSeconds() {
-    return this.mouseDownElapsed / 1000;
-  },
-
-  get mouseUpElapsedSeconds() {
-    return this.mouseUpElapsed / 1000;
-  },
-
-  get mouseInteractionSeconds() {
-    return this.mouseDownElapsedSeconds + this.mouseUpElapsedSeconds;
-  },
-
-  get initialOpacity() {
-    return this.element.initialOpacity;
-  },
-
-  get opacityDecayVelocity() {
-    return this.element.opacityDecayVelocity;
-  },
-
-  get radius() {
-    var width2 = this.containerMetrics.width * this.containerMetrics.width;
-    var height2 = this.containerMetrics.height * this.containerMetrics.height;
-    var waveRadius =
-        Math.min(Math.sqrt(width2 + height2), Ripple.MAX_RADIUS) * 1.1 + 5;
-
-    var duration = 1.1 - 0.2 * (waveRadius / Ripple.MAX_RADIUS);
-    var timeNow = this.mouseInteractionSeconds / duration;
-    var size = waveRadius * (1 - Math.pow(80, -timeNow));
-
-    return Math.abs(size);
-  },
-
-  get opacity() {
-    if (!this.mouseUpStart) {
-      return this.initialOpacity;
-    }
-
-    return Math.max(
-        0,
-        this.initialOpacity -
-            this.mouseUpElapsedSeconds * this.opacityDecayVelocity);
-  },
-
-  get outerOpacity() {
-    // Linear increase in background opacity, capped at the opacity
-    // of the wavefront (waveOpacity).
-    var outerOpacity = this.mouseUpElapsedSeconds * 0.3;
-    var waveOpacity = this.opacity;
-
-    return Math.max(0, Math.min(outerOpacity, waveOpacity));
-  },
-
-  get isOpacityFullyDecayed() {
-    return this.opacity < 0.01 &&
-        this.radius >= Math.min(this.maxRadius, Ripple.MAX_RADIUS);
-  },
-
-  get isRestingAtMaxRadius() {
-    return this.opacity >= this.initialOpacity &&
-        this.radius >= Math.min(this.maxRadius, Ripple.MAX_RADIUS);
-  },
-
-  get isAnimationComplete() {
-    return this.mouseUpStart ? this.isOpacityFullyDecayed :
-                               this.isRestingAtMaxRadius;
-  },
-
-  get translationFraction() {
-    return Math.min(
-        1, this.radius / this.containerMetrics.size * 2 / Math.sqrt(2));
-  },
-
-  get xNow() {
-    if (this.xEnd) {
-      return this.xStart + this.translationFraction * (this.xEnd - this.xStart);
-    }
-
-    return this.xStart;
-  },
-
-  get yNow() {
-    if (this.yEnd) {
-      return this.yStart + this.translationFraction * (this.yEnd - this.yStart);
-    }
-
-    return this.yStart;
-  },
-
-  get isMouseDown() {
-    return this.mouseDownStart && !this.mouseUpStart;
-  },
-
-  resetInteractionState: function() {
-    this.maxRadius = 0;
-    this.mouseDownStart = 0;
-    this.mouseUpStart = 0;
-
-    this.xStart = 0;
-    this.yStart = 0;
-    this.xEnd = 0;
-    this.yEnd = 0;
-    this.slideDistance = 0;
-
-    this.containerMetrics = new ElementMetrics(this.element);
-  },
-
-  draw: function() {
-    var scale;
-    var dx;
-    var dy;
-
-    this.wave.style.opacity = this.opacity;
-
-    scale = this.radius / (this.containerMetrics.size / 2);
-    dx = this.xNow - (this.containerMetrics.width / 2);
-    dy = this.yNow - (this.containerMetrics.height / 2);
-
-
-    // 2d transform for safari because of border-radius and overflow:hidden
-    // clipping bug. https://bugs.webkit.org/show_bug.cgi?id=98538
-    this.waveContainer.style.webkitTransform =
-        'translate(' + dx + 'px, ' + dy + 'px)';
-    this.waveContainer.style.transform =
-        'translate3d(' + dx + 'px, ' + dy + 'px, 0)';
-    this.wave.style.webkitTransform = 'scale(' + scale + ',' + scale + ')';
-    this.wave.style.transform = 'scale3d(' + scale + ',' + scale + ',1)';
-  },
-
-  /** @param {Event=} event */
-  downAction: function(event) {
-    var xCenter = this.containerMetrics.width / 2;
-    var yCenter = this.containerMetrics.height / 2;
-
-    this.resetInteractionState();
-    this.mouseDownStart = Utility.now();
-
-    if (this.center) {
-      this.xStart = xCenter;
-      this.yStart = yCenter;
-      this.slideDistance =
-          Utility.distance(this.xStart, this.yStart, this.xEnd, this.yEnd);
-    } else {
-      this.xStart = event ?
-          event.detail.x - this.containerMetrics.boundingRect.left :
-          this.containerMetrics.width / 2;
-      this.yStart = event ?
-          event.detail.y - this.containerMetrics.boundingRect.top :
-          this.containerMetrics.height / 2;
-    }
-
-    if (this.recenters) {
-      this.xEnd = xCenter;
-      this.yEnd = yCenter;
-      this.slideDistance =
-          Utility.distance(this.xStart, this.yStart, this.xEnd, this.yEnd);
-    }
-
-    this.maxRadius = this.containerMetrics.furthestCornerDistanceFrom(
-        this.xStart, this.yStart);
-
-    this.waveContainer.style.top =
-        (this.containerMetrics.height - this.containerMetrics.size) / 2 + 'px';
-    this.waveContainer.style.left =
-        (this.containerMetrics.width - this.containerMetrics.size) / 2 + 'px';
-
-    this.waveContainer.style.width = this.containerMetrics.size + 'px';
-    this.waveContainer.style.height = this.containerMetrics.size + 'px';
-  },
-
-  /** @param {Event=} event */
-  upAction: function(event) {
-    if (!this.isMouseDown) {
-      return;
-    }
-
-    this.mouseUpStart = Utility.now();
-  },
-
-  remove: function() {
-    dom(this.waveContainer.parentNode).removeChild(this.waveContainer);
-  }
-};
-
-/**
-Material design: [Surface
-reaction](https://www.google.com/design/spec/animation/responsive-interaction.html#responsive-interaction-surface-reaction)
-
-`paper-ripple` provides a visual effect that other paper elements can
-use to simulate a rippling effect emanating from the point of contact.  The
-effect can be visualized as a concentric circle with motion.
-
-Example:
-
-    <div style="position:relative">
-      <paper-ripple></paper-ripple>
-    </div>
-
-Note, it's important that the parent container of the ripple be relative
-position, otherwise the ripple will emanate outside of the desired container.
-
-`paper-ripple` listens to "mousedown" and "mouseup" events so it would display
-ripple effect when touches on it.  You can also defeat the default behavior and
-manually route the down and up actions to the ripple element.  Note that it is
-important if you call `downAction()` you will have to make sure to call
-`upAction()` so that `paper-ripple` would end the animation loop.
-
-Example:
-
-    <paper-ripple id="ripple" style="pointer-events: none;"></paper-ripple>
-    ...
-    downAction: function(e) {
-      this.$.ripple.downAction(e.detail);
-    },
-    upAction: function(e) {
-      this.$.ripple.upAction();
-    }
-
-Styling ripple effect:
-
-  Use CSS color property to style the ripple:
-
-    paper-ripple {
-      color: #4285f4;
-    }
-
-  Note that CSS color property is inherited so it is not required to set it on
-  the `paper-ripple` element directly.
-
-By default, the ripple is centered on the point of contact.  Apply the
-`recenters` attribute to have the ripple grow toward the center of its
-container.
-
-    <paper-ripple recenters></paper-ripple>
-
-You can also  center the ripple inside its container from the start.
-
-    <paper-ripple center></paper-ripple>
-
-Apply `circle` class to make the rippling effect within a circle.
-
-    <paper-ripple class="circle"></paper-ripple>
-
-@group Paper Elements
-@element paper-ripple
-@hero hero.svg
-@demo demo/index.html
-*/
 Polymer({
   _template: html`
     <style>
       :host {
-        display: block;
-        position: absolute;
         border-radius: inherit;
-        overflow: hidden;
-        top: 0;
-        left: 0;
-        right: 0;
         bottom: 0;
-
-        /* See PolymerElements/paper-behaviors/issues/34. On non-Chrome browsers,
-         * creating a node (with a position:absolute) in the middle of an event
-         * handler "interrupts" that event handler (which happens when the
-         * ripple is created on demand) */
+        display: block;
+        left: 0;
+        overflow: hidden;
         pointer-events: none;
-      }
-
-      :host([animating]) {
-        /* This resolves a rendering issue in Chrome (as of 40) where the
-           ripple is not properly clipped by its parent (which may have
-           rounded corners). See: http://jsbin.com/temexa/4
-
-           Note: We only apply this style conditionally. Otherwise, the browser
-           will create a new compositing layer for every ripple element on the
-           page, and that would be bad. */
-        -webkit-transform: translate(0, 0);
+        position: absolute;
+        right: 0;
+        top: 0;
+        /* For rounded corners: http://jsbin.com/temexa/4. */
         transform: translate3d(0, 0, 0);
       }
 
-      #background,
-      #waves,
-      .wave-container,
-      .wave {
+      .ripple {
+        background-color: currentcolor;
+        left: 0;
+        opacity: var(--paper-ripple-opacity, 0.25);
         pointer-events: none;
         position: absolute;
-        top: 0;
-        left: 0;
-        width: 100%;
-        height: 100%;
+        will-change: height, transform, width;
       }
 
-      #background,
-      .wave {
-        opacity: 0;
-      }
-
-      #waves,
-      .wave {
-        overflow: hidden;
-      }
-
-      .wave-container,
-      .wave {
+      .ripple,
+      :host(.circle) {
         border-radius: 50%;
       }
-
-      :host(.circle) #background,
-      :host(.circle) #waves {
-        border-radius: 50%;
-      }
-
-      :host(.circle) .wave-container {
-        overflow: hidden;
-      }
     </style>
-
-    <div id="background"></div>
-    <div id="waves"></div>
 `,
 
   is: 'paper-ripple',
   behaviors: [IronA11yKeysBehavior],
 
   properties: {
-    /**
-     * The initial opacity set on the wave.
-     *
-     * @attribute initialOpacity
-     * @type number
-     * @default 0.25
-     */
-    initialOpacity: {type: Number, value: 0.25},
-
-    /**
-     * How fast (opacity per second) the wave fades out.
-     *
-     * @attribute opacityDecayVelocity
-     * @type number
-     * @default 0.8
-     */
-    opacityDecayVelocity: {type: Number, value: 0.8},
-
-    /**
-     * If true, ripples will exhibit a gravitational pull towards
-     * the center of their container as they fade away.
-     *
-     * @attribute recenters
-     * @type boolean
-     * @default false
-     */
-    recenters: {type: Boolean, value: false},
-
-    /**
-     * If true, ripples will center inside its container
-     *
-     * @attribute recenters
-     * @type boolean
-     * @default false
-     */
     center: {type: Boolean, value: false},
-
-    /**
-     * A list of the visual ripples.
-     *
-     * @attribute ripples
-     * @type Array
-     * @default []
-     */
-    ripples: {
-      type: Array,
-      value: function() {
-        return [];
-      }
-    },
-
-    /**
-     * True when there are visible ripples animating within the
-     * element.
-     */
-    animating:
-        {type: Boolean, readOnly: true, reflectToAttribute: true, value: false},
-
-    /**
-     * If true, the ripple will remain in the "down" state until `holdDown`
-     * is set to false again.
-     */
     holdDown: {type: Boolean, value: false, observer: '_holdDownChanged'},
-
-    /**
-     * If true, the ripple will not generate a ripple effect
-     * via pointer interaction.
-     * Calling ripple's imperative api like `simulatedRipple` will
-     * still generate the ripple effect.
-     */
+    recenters: {type: Boolean, value: false},
     noink: {type: Boolean, value: false},
-
-    _animating: {type: Boolean},
-
-    _boundAnimate: {
-      type: Function,
-      value: function() {
-        return this.animate.bind(this);
-      }
-    }
   },
 
-  get target() {
-    return this.keyEventTarget;
-  },
-
-  /**
-   * @type {!Object}
-   */
   keyBindings: {
     'enter:keydown': '_onEnterKeydown',
     'space:keydown': '_onSpaceKeydown',
-    'space:keyup': '_onSpaceKeyup'
+    'space:keyup': '_onSpaceKeyup',
   },
 
+  /** @override */
+  created: function() {
+    /** @type {Array<!Element>} */
+    this.ripples = [];
+  },
+
+  /** @override */
   attached: function() {
-    // Set up a11yKeysBehavior to listen to key events on the target,
-    // so that space and enter activate the ripple even if the target doesn't
-    // handle key events. The key handlers deal with `noink` themselves.
-    if (this.parentNode.nodeType == 11) {  // DOCUMENT_FRAGMENT_NODE
-      this.keyEventTarget = dom(this).getOwnerRoot().host;
-    } else {
-      this.keyEventTarget = this.parentNode;
-    }
-    var keyEventTarget = /** @type {!EventTarget} */ (this.keyEventTarget);
-    this.listen(keyEventTarget, 'up', 'uiUpAction');
-    this.listen(keyEventTarget, 'down', 'uiDownAction');
+    this.keyEventTarget = this.parentNode.nodeType == 11 ?
+        dom(this).getOwnerRoot().host : this.parentNode;
+    this.keyEventTarget = /** @type {!EventTarget} */ (this.keyEventTarget);
+    this.listen(this.keyEventTarget, 'up', 'uiUpAction');
+    this.listen(this.keyEventTarget, 'down', 'uiDownAction');
   },
 
+  /** @override */
   detached: function() {
     this.unlisten(this.keyEventTarget, 'up', 'uiUpAction');
     this.unlisten(this.keyEventTarget, 'down', 'uiDownAction');
     this.keyEventTarget = null;
   },
 
-  get shouldKeepAnimating() {
-    for (var index = 0; index < this.ripples.length; ++index) {
-      if (!this.ripples[index].isAnimationComplete) {
-        return true;
-      }
-    }
-
-    return false;
-  },
-
   simulatedRipple: function() {
-    this.downAction(null);
-
-    // Please see polymer/polymer#1305
-    this.async(function() {
-      this.upAction();
-    }, 1);
+    this.downAction();
+    // Using a 1ms delay ensures a macro-task.
+    this.async(function() { this.upAction(); }.bind(this), 1);
   },
 
-  /**
-   * Provokes a ripple down effect via a UI event,
-   * respecting the `noink` property.
-   * @param {Event=} event
-   */
-  uiDownAction: function(event) {
-    if (!this.noink) {
-      this.downAction(event);
-    }
+  /** @param {Event=} e */
+  uiDownAction: function(e) {
+    if (!this.noink)
+      this.downAction(e);
   },
 
-  /**
-   * Provokes a ripple down effect via a UI event,
-   * *not* respecting the `noink` property.
-   * @param {Event=} event
-   */
-  downAction: function(event) {
-    if (this.holdDown && this.ripples.length > 0) {
+  /** @param {Event=} e */
+  downAction: function(e) {
+    if (this.ripples.length && this.holdDown)
       return;
-    }
-
-    var ripple = this.addRipple();
-
-    ripple.downAction(event);
-
-    if (!this._animating) {
-      this._animating = true;
-      this.animate();
-    }
+    // TODO(dbeam): some things (i.e. paper-icon-button-light) dynamically
+    // create ripples on 'up', Ripples register an event listener on their
+    // parent (or shadow DOM host) when attached().  This sometimes causes
+    // duplicate events to fire on us.
+    this.debounce('show ripple', function() { this.__showRipple(e); }, 1);
   },
 
-  /**
-   * Provokes a ripple up effect via a UI event,
-   * respecting the `noink` property.
-   * @param {Event=} event
-   */
-  uiUpAction: function(event) {
-    if (!this.noink) {
-      this.upAction(event);
-    }
+  clear: function() {
+    this.__hideRipple();
+    this.holdDown = false;
   },
 
-  /**
-   * Provokes a ripple up effect via a UI event,
-   * *not* respecting the `noink` property.
-   * @param {Event=} event
-   */
-  upAction: function(event) {
-    if (this.holdDown) {
-      return;
-    }
-
-    this.ripples.forEach(function(ripple) {
-      ripple.upAction(event);
+  showAndHoldDown: function() {
+    this.ripples.forEach(ripple => {
+      ripple.remove();
     });
-
-    this._animating = true;
-    this.animate();
-  },
-
-  onAnimationComplete: function() {
-    this._animating = false;
-    this.$.background.style.backgroundColor = null;
-    this.fire('transitionend');
-  },
-
-  addRipple: function() {
-    var ripple = new Ripple(this);
-
-    dom(this.$.waves).appendChild(ripple.waveContainer);
-    this.$.background.style.backgroundColor = ripple.color;
-    this.ripples.push(ripple);
-
-    this._setAnimating(true);
-
-    return ripple;
-  },
-
-  removeRipple: function(ripple) {
-    var rippleIndex = this.ripples.indexOf(ripple);
-
-    if (rippleIndex < 0) {
-      return;
-    }
-
-    this.ripples.splice(rippleIndex, 1);
-
-    ripple.remove();
-
-    if (!this.ripples.length) {
-      this._setAnimating(false);
-    }
+    this.ripples = [];
+    this.holdDown = true;
   },
 
   /**
-   * Deprecated. Please use animateRipple() instead.
-   *
-   * This method name conflicts with Element#animate().
-   * https://developer.mozilla.org/en-US/docs/Web/API/Element/animate.
-   *
+   * @param {Event=} e
+   * @private
    * @suppress {checkTypes}
    */
-  animate: function() {
-    if (!this._animating) {
-      return;
-    }
-    var index;
-    var ripple;
+  __showRipple: function(e) {
+    var rect = this.getBoundingClientRect();
 
-    for (index = 0; index < this.ripples.length; ++index) {
-      ripple = this.ripples[index];
+    var roundedCenterX = function() { return Math.round(rect.width / 2); };
+    var roundedCenterY = function() { return Math.round(rect.height / 2); };
 
-      ripple.draw();
-
-      this.$.background.style.opacity = ripple.outerOpacity;
-
-      if (ripple.isOpacityFullyDecayed && !ripple.isRestingAtMaxRadius) {
-        this.removeRipple(ripple);
-      }
-    }
-
-    if (!this.shouldKeepAnimating && this.ripples.length === 0) {
-      this.onAnimationComplete();
+    var centered = !e || this.center;
+    if (centered) {
+      var x = roundedCenterX();
+      var y = roundedCenterY();
     } else {
-      window.requestAnimationFrame(this._boundAnimate);
+      var sourceEvent = e.detail.sourceEvent;
+      var x = Math.round(sourceEvent.clientX - rect.left);
+      var y = Math.round(sourceEvent.clientY - rect.top);
     }
+
+    var corners = [
+      {x: 0, y: 0},
+      {x: rect.width, y: 0},
+      {x: 0, y: rect.height},
+      {x: rect.width, y: rect.height},
+    ];
+
+    var cornerDistances = corners.map(function(corner) {
+      return Math.round(distance(x, y, corner.x, corner.y));
+    });
+
+    var radius = Math.min(MAX_RADIUS_PX, Math.max.apply(Math, cornerDistances));
+
+    var startTranslate = (x - radius) + 'px, ' + (y - radius) + 'px';
+    if (this.recenters && !centered) {
+      var endTranslate = (roundedCenterX() - radius) + 'px, ' +
+                         (roundedCenterY() - radius) + 'px';
+    } else {
+      var endTranslate = startTranslate;
+    }
+
+    var ripple = document.createElement('div');
+    ripple.classList.add('ripple');
+    ripple.style.height = ripple.style.width = (2 * radius) + 'px';
+
+    this.ripples.push(ripple);
+    this.shadowRoot.appendChild(ripple);
+
+    ripple.animate({
+      // TODO(dbeam): scale to 90% of radius at .75 offset?
+      transform: ['translate(' + startTranslate + ') scale(0)',
+                  'translate(' + endTranslate + ') scale(1)'],
+    }, {
+      duration: Math.max(MIN_DURATION_MS, Math.log(radius) * radius) || 0,
+      easing: 'cubic-bezier(.2, .9, .1, .9)',
+      fill: 'forwards',
+    });
+  },
+
+  /** @param {Event=} e */
+  uiUpAction: function(e) {
+    if (!this.noink)
+      this.upAction();
+  },
+
+  /** @param {Event=} e */
+  upAction: function(e) {
+    if (!this.holdDown)
+      this.debounce('hide ripple', function() { this.__hideRipple(); }, 1);
   },
 
   /**
-   * An alias for animate() whose name does not conflict with the platform
-   * Element.animate() method.
+   * @private
+   * @suppress {checkTypes}
    */
-  animateRipple: function() {
-    return this.animate();
+  __hideRipple: function() {
+    Promise.all(this.ripples.map(function(ripple) {
+      return new Promise(function(resolve) {
+        var removeRipple = function() {
+          ripple.remove();
+          resolve();
+        };
+        var opacity = getComputedStyle(ripple).opacity;
+        if (!opacity.length) {
+          removeRipple();
+        } else {
+          var animation = ripple.animate({
+            opacity: [opacity, 0],
+          }, {
+            duration: 150,
+            fill: 'forwards',
+          });
+          animation.addEventListener('finish', removeRipple);
+          animation.addEventListener('cancel', removeRipple);
+        }
+      });
+    })).then(function() { this.fire('transitionend'); }.bind(this));
+    this.ripples = [];
   },
 
+  /** @protected */
   _onEnterKeydown: function() {
     this.uiDownAction();
     this.async(this.uiUpAction, 1);
   },
 
+  /** @protected */
   _onSpaceKeydown: function() {
     this.uiDownAction();
   },
 
+  /** @protected */
   _onSpaceKeyup: function() {
     this.uiUpAction();
   },
 
-  // note: holdDown does not respect noink since it can be a focus based
-  // effect.
-  _holdDownChanged: function(newVal, oldVal) {
-    if (oldVal === undefined) {
+  /** @protected */
+  _holdDownChanged: function(newHoldDown, oldHoldDown) {
+    if (oldHoldDown === undefined)
       return;
-    }
-    if (newVal) {
+    if (newHoldDown)
       this.downAction();
-    } else {
+    else
       this.upAction();
-    }
-  }
-
-  /**
-  Fired when the animation finishes.
-  This is useful if you want to wait until
-  the ripple animation finishes to perform some action.
-
-  @event transitionend
-  @param {{node: Object}} detail Contains the animated node.
-  */
+  },
 });
diff --git a/third_party/polymer/v3_0/reproduce.sh b/third_party/polymer/v3_0/reproduce.sh
index 74746f2..38e74dc1 100755
--- a/third_party/polymer/v3_0/reproduce.sh
+++ b/third_party/polymer/v3_0/reproduce.sh
@@ -56,6 +56,10 @@
 find components-chromium/ -name '*.js' -exec sed -i \
   's/\/polymer\/[a-zA-Z\/\.-]\+/\/polymer\/polymer_bundled.min.js/' {} +
 
+# Undo any changes in paper-ripple, since Chromium's implementation is a fork of
+# the original paper-ripple.
+git checkout -- components-chromium/paper-ripple/*
+
 new=$(git status --porcelain components-chromium | grep '^??' | \
       cut -d' ' -f2 | egrep '\.(js|css)$' || true)
 
diff --git a/tools/android/asan/third_party/README.chromium b/tools/android/asan/third_party/README.chromium
index 2d06990..c35bff0 100644
--- a/tools/android/asan/third_party/README.chromium
+++ b/tools/android/asan/third_party/README.chromium
@@ -1,6 +1,6 @@
 Name: asan_device_setup.sh
-License: University of Illinois Open Source License.
-Version: 281410
+License: Apache 2.0
+Version: 351636
 URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/scripts/asan_device_setup?view=co
 Security Critical: no
 
diff --git a/tools/android/asan/third_party/asan_device_setup.sh b/tools/android/asan/third_party/asan_device_setup.sh
index dee2ba2e..041bf92 100755
--- a/tools/android/asan/third_party/asan_device_setup.sh
+++ b/tools/android/asan/third_party/asan_device_setup.sh
@@ -1,10 +1,9 @@
 #!/bin/bash
 #===- lib/asan/scripts/asan_device_setup -----------------------------------===#
 #
-#                     The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open Source
-# License. See LICENSE.TXT for details.
+# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+# See https://llvm.org/LICENSE.txt for license information.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 #
 # Prepare Android device to run ASan applications.
 #
@@ -52,7 +51,7 @@
     local STORAGE=`$ADB shell mount | grep /system | cut -d ' ' -f1`
     if [ "$STORAGE" != "" ]; then
       echo Remounting $STORAGE at /system
-      $ADB shell su -c "mount -o remount,rw $STORAGE /system"
+      $ADB shell su -c "mount -o rw,remount $STORAGE /system"
     else
       echo Failed to get storage device name for "/system" mount point
     fi
@@ -95,7 +94,7 @@
     local _ARCH=
     local _ARCH64=
     if [[ $_ABI == x86* ]]; then
-        _ARCH=i686
+        _ARCH=i386
     elif [[ $_ABI == armeabi* ]]; then
         _ARCH=arm
     elif [[ $_ABI == arm64-v8a* ]]; then
@@ -181,6 +180,17 @@
   ASAN_RT64="libclang_rt.asan-$ARCH64-android.so"
 fi
 
+RELEASE=$(adb_shell getprop ro.build.version.release)
+PRE_L=0
+if echo "$RELEASE" | grep '^4\.' >&/dev/null; then
+    PRE_L=1
+fi
+ANDROID_O=0
+if echo "$RELEASE" | grep '^8\.0\.' >&/dev/null; then
+    # 8.0.x is for Android O
+    ANDROID_O=1
+fi
+
 if [[ x$revert == xyes ]]; then
     echo '>> Uninstalling ASan'
 
@@ -202,6 +212,10 @@
       adb_shell ln -s /system/bin/app_process32 /system/bin/app_process
     fi
 
+    if [[ ANDROID_O -eq 1 ]]; then
+      adb_shell mv /system/etc/ld.config.txt.saved /system/etc/ld.config.txt
+    fi
+
     echo '>> Restarting shell'
     adb_shell stop
     adb_shell start
@@ -251,12 +265,6 @@
 TMPDIR="$TMPDIRBASE/new"
 mkdir "$TMPDIROLD"
 
-RELEASE=$(adb_shell getprop ro.build.version.release)
-PRE_L=0
-if echo "$RELEASE" | grep '^4\.' >&/dev/null; then
-    PRE_L=1
-fi
-
 if ! adb_shell ls -l /system/bin/app_process | grep -o '\->.*app_process' >&/dev/null; then
 
     if adb_pull /system/bin/app_process.real /dev/null >&/dev/null; then
@@ -300,18 +308,22 @@
   cp "$ASAN_RT_PATH/$ASAN_RT64" "$TMPDIR/"
 fi
 
-ASAN_OPTIONS=start_deactivated=1,malloc_context_size=0
+ASAN_OPTIONS=start_deactivated=1
 
-function generate_zygote_wrapper { # from, to, asan_rt
+# The name of a symlink to libclang_rt.asan-$ARCH-android.so used in LD_PRELOAD.
+# The idea is to have the same name in lib and lib64 to keep it from falling
+# apart when a 64-bit process spawns a 32-bit one, inheriting the environment.
+ASAN_RT_SYMLINK=symlink-to-libclang_rt.asan
+
+function generate_zygote_wrapper { # from, to
   local _from=$1
   local _to=$2
-  local _asan_rt=$3
   if [[ PRE_L -eq 0 ]]; then
     # LD_PRELOAD parsing is broken in N if it starts with ":". Luckily, it is
     # unset in the system environment since L.
-    local _ld_preload=$_asan_rt
+    local _ld_preload=$ASAN_RT_SYMLINK
   else
-    local _ld_preload=\$LD_PRELOAD:$_asan_rt
+    local _ld_preload=\$LD_PRELOAD:$ASAN_RT_SYMLINK
   fi
   cat <<EOF >"$TMPDIR/$_from"
 #!/system/bin/sh-from-zygote
@@ -324,6 +336,8 @@
 }
 
 # On Android-L not allowing user segv handler breaks some applications.
+# Since ~May 2017 this is the default setting; included for compatibility with
+# older library versions.
 if [[ PRE_L -eq 0 ]]; then
     ASAN_OPTIONS="$ASAN_OPTIONS,allow_user_segv_handler=1"
 fi
@@ -340,18 +354,18 @@
     mv "$TMPDIR/app_process32" "$TMPDIR/app_process32.real"
     mv "$TMPDIR/app_process64" "$TMPDIR/app_process64.real"
   fi
-  generate_zygote_wrapper "app_process32" "/system/bin/app_process32.real" "$ASAN_RT"
-  generate_zygote_wrapper "app_process64" "/system/bin/app_process64.real" "$ASAN_RT64"
+  generate_zygote_wrapper "app_process32" "/system/bin/app_process32.real"
+  generate_zygote_wrapper "app_process64" "/system/bin/app_process64.real"
 else
   # A 32-bit device.
-  generate_zygote_wrapper "app_process.wrap" "/system/bin/app_process32" "$ASAN_RT"
+  generate_zygote_wrapper "app_process.wrap" "/system/bin/app_process32"
 fi
 
 # General command-line tool wrapper (use for anything that's not started as
 # zygote).
 cat <<EOF >"$TMPDIR/asanwrapper"
 #!/system/bin/sh
-LD_PRELOAD=$ASAN_RT \\
+LD_PRELOAD=$ASAN_RT_SYMLINK \\
 exec \$@
 
 EOF
@@ -359,7 +373,7 @@
 if [[ -n "$ASAN_RT64" ]]; then
   cat <<EOF >"$TMPDIR/asanwrapper64"
 #!/system/bin/sh
-LD_PRELOAD=$ASAN_RT64 \\
+LD_PRELOAD=$ASAN_RT_SYMLINK \\
 exec \$@
 
 EOF
@@ -410,12 +424,20 @@
       install "$TMPDIR/app_process64.real" /system/bin 755 $CTX
       install "$TMPDIR/asanwrapper" /system/bin 755
       install "$TMPDIR/asanwrapper64" /system/bin 755
+
+      adb_shell rm -f /system/lib/$ASAN_RT_SYMLINK
+      adb_shell ln -s $ASAN_RT /system/lib/$ASAN_RT_SYMLINK
+      adb_shell rm -f /system/lib64/$ASAN_RT_SYMLINK
+      adb_shell ln -s $ASAN_RT64 /system/lib64/$ASAN_RT_SYMLINK
     else
       install "$TMPDIR/$ASAN_RT" /system/lib 644
       install "$TMPDIR/app_process32" /system/bin 755 $CTX
       install "$TMPDIR/app_process.wrap" /system/bin 755 $CTX
       install "$TMPDIR/asanwrapper" /system/bin 755 $CTX
 
+      adb_shell rm -f /system/lib/$ASAN_RT_SYMLINK
+      adb_shell ln -s $ASAN_RT /system/lib/$ASAN_RT_SYMLINK
+
       adb_shell rm /system/bin/app_process
       adb_shell ln -s /system/bin/app_process.wrap /system/bin/app_process
     fi
@@ -423,6 +445,11 @@
     adb_shell cp /system/bin/sh /system/bin/sh-from-zygote
     adb_shell chcon $CTX /system/bin/sh-from-zygote
 
+    if [[ ANDROID_O -eq 1 ]]; then
+      # For Android O, the linker namespace is temporarily disabled.
+      adb_shell mv /system/etc/ld.config.txt /system/etc/ld.config.txt.saved
+    fi
+
     if [ $ENFORCING == 1 ]; then
         adb_shell setenforce 1
     fi
@@ -436,4 +463,4 @@
     echo '>> Device is up to date'
 fi
 
-rm -r "$TMPDIRBASE"
\ No newline at end of file
+rm -r "$TMPDIRBASE"
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl
index fecc36a..e5d1c177 100644
--- a/tools/mb/mb_config.pyl
+++ b/tools/mb/mb_config.pyl
@@ -855,7 +855,7 @@
     },
 
     'tryserver.webrtc': {
-      'win_chromium_compile': 'gpu_tests_release_trybot_x86_resource_whitelisting',
+      'win_chromium_compile': 'gpu_tests_release_trybot_resource_whitelisting',
       'mac_chromium_compile': 'gpu_tests_release_trybot',
       'linux_chromium_compile': 'release_trybot',
       'android_chromium_compile': 'android_release_trybot',
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 12395ef..ae540d0 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -10361,6 +10361,37 @@
   <int value="1515864914" label="ZZCR (Early prod samples)"/>
 </enum>
 
+<enum name="Cr50FlashLogs">
+  <summary>
+    List of currently defined Cr50 flash log event types. The latest and
+    greatest set can be found in
+    https://chromium.googlesource.com/chromiumos/platform/ec/+/refs/heads/master/include/flash_log.h
+    (enum flash_event_type and enum nvmem_failure_type). Note that NVMEM errors
+    are logged as subevents of flash log event 5, we register them offset by
+    200.
+  </summary>
+  <int value="0" label="Start"/>
+  <int value="1" label="Corrupted Log"/>
+  <int value="2" label="I2C Error"/>
+  <int value="3" label="Log Overflow"/>
+  <int value="4" label="Log Lock"/>
+  <int value="6" label="TPM Wipe"/>
+  <int value="7" label="TRNG Stall"/>
+  <int value="200" label="Nvmem Malloc"/>
+  <int value="201" label="Nvmem Page Header Size Mismatch"/>
+  <int value="202" label="Nvmem Read Underrun"/>
+  <int value="203" label="Nvmem Corrupted Flash"/>
+  <int value="204" label="Nvmem Migration Failure"/>
+  <int value="205" label="Nvmem Legacy Erase Failure"/>
+  <int value="206" label="Nvmem Deleting Too Many Objects"/>
+  <int value="207" label="Nvmem Unexpected Last Obj"/>
+  <int value="208" label="Nvmem Missing Obj"/>
+  <int value="209" label="Nvmem Section Verification"/>
+  <int value="210" label="Nvmem Pre Erase Mismatch"/>
+  <int value="211" label="Nvmem Page List Oveflow"/>
+  <int value="212" label="Nvmem Cipher Error"/>
+</enum>
+
 <enum name="CrashExitCodes">
 <!-- These are abs() raw exit codes, so always positive. See MapCrashExitCodeForHistogram  function. See also the WindowsExitCode enum. -->
 
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 32edc27..007f19bc4 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -84355,6 +84355,8 @@
 
     To know how common this last condition is, compare the total count of this
     histogram to the total number of omnibox events.
+
+    Android started logging this in M76.
   </summary>
 </histogram>
 
@@ -93912,6 +93914,19 @@
   </summary>
 </histogram>
 
+<histogram name="Platform.Cr50.FlashLog" enum="Cr50FlashLogs"
+    expires_after="2020-06-30">
+  <owner>apronin@chromium.org</owner>
+  <owner>vbendeb@chromium.org</owner>
+  <summary>
+    A histogram of flash log event types collected from the H1 device. Log event
+    type is an 8 bit value. This histogram does not allow to drill into
+    particular log entries' contents, but allows to collect a general statistics
+    of events. A script running on the Chrome OS device polls the H1 for new
+    flash log events after every start up.
+  </summary>
+</histogram>
+
 <histogram name="Platform.Cr50.MatchingBoardId" enum="Cr50CrosRlzCodes">
   <owner>vbendeb@chromium.org</owner>
   <summary>
diff --git a/tools/perf/core/perf_data_generator.py b/tools/perf/core/perf_data_generator.py
index dbcb095..4b9c18a 100755
--- a/tools/perf/core/perf_data_generator.py
+++ b/tools/perf/core/perf_data_generator.py
@@ -146,7 +146,7 @@
     'dimension': {
       'pool': 'chrome.tests.perf-fyi',
       'id': 'build370-a7',
-      # (TODO crbug.com/971204) Explicitly set the gpu to None to make
+      # TODO(crbug.com/971204): Explicitly set the gpu to None to make
       # chromium_swarming recipe_module ignore this dimension.
       'gpu': None,
     },
@@ -157,6 +157,11 @@
 # build/scripts/slave/recipe_modules/chromium_tests and must be kept in sync
 # to generate the correct json for each tester
 #
+# The dimensions in pinpoint configs, excluding the dimension "pool",
+# must be kept in sync with the dimensions here.
+# This is to make sure the same type of machines are used between waterfall
+# tests and pinpoint jobs
+#
 # On desktop builders, chromedriver is added as an additional compile target.
 # The perf waterfall builds this target for each commit, and the resulting
 # ChromeDriver is archived together with Chrome for use in bisecting.
@@ -494,8 +499,12 @@
     'target_bits': 64,
     'dimension': {
       'pool': 'chrome.tests.perf',
+      # TODO(crbug.com/966238): Add more specific windows version.
       'os': 'Windows-10',
-      'gpu': '8086:5912'
+      # TODO(crbug.com/971204): Explicitly set the gpu to None to make
+      # chromium_swarming recipe_module ignore this dimension.
+      'gpu': None,
+      'synthetic_product_name': 'OptiPlex 7050 (Dell Inc.)'
     },
   },
   'Win 7 Perf': {
diff --git a/tools/perf/core/perf_json_config_validator.py b/tools/perf/core/perf_json_config_validator.py
index 4690a166..b47dd72 100644
--- a/tools/perf/core/perf_json_config_validator.py
+++ b/tools/perf/core/perf_json_config_validator.py
@@ -11,7 +11,8 @@
 
 _VALID_SWARMING_DIMENSIONS = {
     'gpu', 'device_ids', 'os', 'pool', 'perf_tests', 'perf_tests_with_args',
-    'device_os', 'device_type', 'device_os_flavor', 'id'}
+    'device_os', 'device_type', 'device_os_flavor', 'id',
+    'synthetic_product_name'}
 _DEFAULT_VALID_PERF_POOLS = {
     'chrome.tests.perf', 'chrome.tests.perf-webview',
     'chrome.tests.perf-fyi', 'chrome.tests.perf-webview-fyi'}
diff --git a/tools/traffic_annotation/scripts/annotation_tokenizer.py b/tools/traffic_annotation/scripts/annotation_tokenizer.py
new file mode 100644
index 0000000..85ca918
--- /dev/null
+++ b/tools/traffic_annotation/scripts/annotation_tokenizer.py
@@ -0,0 +1,107 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""
+A tokenizer for traffic annotation definitions.
+"""
+
+from collections import namedtuple
+
+import re
+
+# Regexen that match a token inside the annotation definition arguments. Stored
+# as a list instead of a dict, to preserve order.
+#
+# Order matters because otherwise, 'symbol' could be parsed before
+# 'string_literal' (i.e., R"(...)" would be misinterpreted as the symbol 'R',
+# followed by a string with parentheses in it).
+TOKEN_REGEXEN = [
+    # Comma for separating args.
+    ('comma', re.compile(r'(,)')),
+    # String literal. "string" or R"(string)".
+    ('string_literal',
+     re.compile(r'"((?:[^"]|\\.)*?)"|R"\((.*?)\)"', re.DOTALL)),
+    # C++ identifier.
+    ('symbol', re.compile(r'([a-zA-Z_][a-zA-Z_0-9]*)')),
+    # Left parenthesis.
+    ('left_paren', re.compile(r'(\()')),
+    # Right parenthesis.
+    ('right_paren', re.compile(r'(\))')),
+]
+
+
+Token = namedtuple('Token', ['type', 'value', 'pos'])
+
+
+class Tokenizer:
+  """Simple tokenizer with basic error reporting.
+
+  Use advance() or maybe_advance() to take tokens from the string, one at a
+  time.
+  """
+
+  def __init__(self, body, file_path, line_number):
+    self.body = body
+    self.pos = 0
+    self.file_path = file_path
+    self.line_number = line_number
+
+  def _assert_token_type(self, token, expected_type):
+    """Like assert(), but reports errors in a _somewhat_ useful way."""
+    if token and token.type == expected_type:
+      return
+    raise Exception(
+        "Expected %s in annotation definition at %s:%d.\nnear '%s'" %
+        (expected_type, self.file_path, self.line_number,
+         self.body[self.pos:self.pos+10]))
+
+  def _get_token(self):
+    """Return the token here, or None on failure."""
+    # Skip initial whitespace
+    whitespace_re = re.compile(r'\s*')
+    pos = whitespace_re.match(self.body, self.pos).end()
+
+    # Find the token here, if there's one.
+    token = None
+
+    for (token_type, regex) in TOKEN_REGEXEN:
+      re_match = regex.match(self.body, pos)
+      if re_match:
+        token_content = filter(lambda x: x is not None, re_match.groups())[0]
+        token = Token(token_type, token_content, re_match.end())
+        break
+
+    return token
+
+  def maybe_advance(self, expected_type):
+    """Advance the tokenizer by one token if it has |expected_type|.
+
+    Args:
+      expected_type: expected |type| attribute of the token.
+
+    Returns:
+      The |value| attribute of the token if it has the right type, or None if it
+      has another type.
+    """
+    token = self._get_token()
+    if token and token.type == expected_type:
+      self.pos = token.pos
+      return token.value
+    return None
+
+  def advance(self, expected_type):
+    """Advance the tokenizer by one token, asserting its type.
+
+    Throws an error if the token at point has the wrong type.
+
+    Args:
+      expected_type: expected |type| attribute of the token.
+
+    Returns:
+      The |value| attribute of the token at point.
+    """
+    token = self._get_token()
+    self._assert_token_type(token, expected_type)
+    self.pos = token.pos
+    return token.value
diff --git a/tools/traffic_annotation/scripts/annotation_tokenizer_test.py b/tools/traffic_annotation/scripts/annotation_tokenizer_test.py
new file mode 100755
index 0000000..ed5b8c47d
--- /dev/null
+++ b/tools/traffic_annotation/scripts/annotation_tokenizer_test.py
@@ -0,0 +1,92 @@
+#!/usr/bin/env python
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""
+Unit tests for annotation_tokenizer.py.
+"""
+
+import unittest
+
+from annotation_tokenizer import Tokenizer
+
+class AnnotationTokenizerTest(unittest.TestCase):
+  def testRealAnnotationDefinition(self):
+    real_definition = """
+        DefineNetworkTrafficAnnotation("foobar_fetcher", R"(
+          semantics {
+            sender: "Foobar Component"
+            description: "Fetches Foobars for the user."
+            trigger: "The user requests a new Foobar."
+            data: "The type of Foobar the user requested."
+            destination: GOOGLE_OWNED_SERVICE
+          }
+          policy {
+            cookies_allowed: NO
+            setting: "Privacy and Security > Enable Foobars"
+            chrome_policy {
+              FoobarsEnabled {
+                FoobarsEnabled: false
+              }
+            }
+          })");"""
+    tokenizer = Tokenizer(real_definition,
+                          'components/foobar/foobar_request_handler.cc', 42)
+    self.assertEqual('DefineNetworkTrafficAnnotation',
+                     tokenizer.advance('symbol'))
+    self.assertEqual('(', tokenizer.advance('left_paren'))
+    self.assertEqual('foobar_fetcher', tokenizer.advance('string_literal'))
+    self.assertEqual(',', tokenizer.advance('comma'))
+    self.assertTrue(bool(tokenizer.advance('string_literal')))
+    self.assertEqual(')', tokenizer.advance('right_paren'))
+
+  def testAdvanceHappyPath(self):
+    tokenizer = Tokenizer('"hello", R"(world)", function_name())));',
+                          'foo.txt', 33)
+    self.assertEqual('hello', tokenizer.advance('string_literal'))
+    self.assertEqual(',', tokenizer.advance('comma'))
+    self.assertEqual('world', tokenizer.advance('string_literal'))
+    self.assertEqual(',', tokenizer.advance('comma'))
+    self.assertEqual('function_name', tokenizer.advance('symbol'))
+    self.assertEqual('(', tokenizer.advance('left_paren'))
+    self.assertEqual(')', tokenizer.advance('right_paren'))
+    self.assertEqual(')', tokenizer.advance('right_paren'))
+
+  def testAdvanceMultiline(self):
+    tokenizer = Tokenizer('\n\tR"(the quick\nbrown\nfox)"', 'foo.txt', 33)
+    self.assertEqual(
+        'the quick\nbrown\nfox', tokenizer.advance('string_literal'))
+
+  def testAdvanceErrorPaths(self):
+    tokenizer = Tokenizer('  hello , ', 'foo.txt', 33)
+    tokenizer.advance('symbol')
+    with self.assertRaisesRegexp(Exception,
+                                 'Expected symbol.+at foo.txt:33'):
+      # There are no more tokens.
+      tokenizer.advance('symbol')
+
+    tokenizer = Tokenizer('"hello"', 'foo.txt', 33)
+    with self.assertRaisesRegexp(Exception,
+                                 'Expected comma.+at foo.txt:33'):
+      # The type doesn't match.
+      tokenizer.advance('comma')
+
+    tokenizer = Tokenizer('{', 'foo.txt', 33)
+    with self.assertRaisesRegexp(Exception,
+                                 'Expected string_literal.+at foo.txt:33'):
+      # Not a valid token at all.
+      tokenizer.advance('string_literal')
+
+  def testMaybeAdvance(self):
+    tokenizer = Tokenizer('"hello", world', 'foo.txt', 33)
+    self.assertEqual(None, tokenizer.maybe_advance('symbol'))
+    self.assertEqual('hello', tokenizer.maybe_advance('string_literal'))
+    self.assertEqual(',', tokenizer.maybe_advance('comma'))
+    self.assertEqual(None, tokenizer.maybe_advance('left_paren'))
+    self.assertEqual('world', tokenizer.maybe_advance('symbol'))
+    self.assertEqual(None, tokenizer.maybe_advance('right_paren'))
+
+
+if __name__ == '__main__':
+  unittest.main()
diff --git a/tools/traffic_annotation/scripts/annotation_tools.py b/tools/traffic_annotation/scripts/annotation_tools.py
index ca372dc..8180f4d 100644
--- a/tools/traffic_annotation/scripts/annotation_tools.py
+++ b/tools/traffic_annotation/scripts/annotation_tools.py
@@ -8,6 +8,11 @@
 import subprocess
 import sys
 
+script_dir = os.path.dirname(os.path.realpath(__file__))
+tool_dir = os.path.abspath(os.path.join(script_dir, '../../clang/pylib'))
+sys.path.insert(0, tool_dir)
+
+from clang import compile_db
 
 class NetworkTrafficAnnotationTools():
   def __init__(self, build_path=None):
@@ -61,6 +66,18 @@
     return all(os.path.exists(
         os.path.join(path, item)) for item in ('gen', 'build.ninja'))
 
+  def GetCompDBFiles(self):
+    """Gets the list of files.
+
+    Returns:
+      A set of absolute filepaths, with all compile-able C++ files (based on the
+      compilation database).
+    """
+    compdb = compile_db.Read(self.build_path)
+    return set(
+        os.path.abspath(os.path.join(self.build_path, e['file']))
+        for e in compdb)
+
   def GetModifiedFiles(self):
     """Gets the list of modified files from git. Returns None if any error
     happens.
diff --git a/tools/traffic_annotation/scripts/extractor.py b/tools/traffic_annotation/scripts/extractor.py
new file mode 100755
index 0000000..0b2c2f7
--- /dev/null
+++ b/tools/traffic_annotation/scripts/extractor.py
@@ -0,0 +1,185 @@
+#!/usr/bin/env python
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""
+Extracts network traffic annotation definitions from C++ source code.
+"""
+
+import argparse
+import os
+import re
+import sys
+
+from annotation_tools import NetworkTrafficAnnotationTools
+from annotation_tokenizer import Tokenizer
+
+ANNOTATION_TYPES = {
+    'DefineNetworkTrafficAnnotation': 'Definition',
+    'DefinePartialNetworkTrafficAnnotation': 'Partial',
+    'CompleteNetworkTrafficAnnotation': 'Completing',
+    'BranchedCompleteNetworkTrafficAnnotation': 'BranchedCompleting',
+    # TODO(crbug/966883): Add 'Mutable' type.
+}
+
+
+# Regex that matches an annotation definition.
+CALL_DETECTION_REGEX = re.compile(r'''
+  \b
+  # Look for one of the tracked function names.
+  # Capture group 1.
+  (
+    ''' + ('|'.join(ANNOTATION_TYPES.keys())) + r'''
+  )
+  # Followed by a left-paren.
+  \s*
+  \(
+''', re.VERBOSE | re.DOTALL)
+
+
+class Annotation:
+  """A network annotation definition in C++ code."""
+
+  def __init__(self, file_path, re_match):
+    """Parses the annotation and populates object fields.
+
+    Args:
+      file_path: Path to the file that contains this annotation.
+      re_match: A MatchObject obtained from CALL_DETECTION_REGEX.
+    """
+    self.file_path = file_path
+    # TODO(crbug/966883): Either find a way to detect parent function name, or
+    # (more likely) remove function_name-related code from the auditor.
+    self.function_name = "XXX_UNIMPLEMENTED_XXX"
+    self.line_number = get_line_number_at(re_match.string, re_match.start())
+
+    definition_function = re_match.group(1)
+    self.type_name = ANNOTATION_TYPES[definition_function]
+
+    # These are populated by _parse_body().
+    self.unique_id = ''
+    self.extra_id = ''
+    self.text = ''
+
+    # Parse the arguments given to the definition function, populating
+    # |unique_id|, |text| and (possibly) |extra_id|.
+    body = re_match.string[re_match.end():]
+    self._parse_body(body)
+
+  def clang_tool_output_string(self):
+    """Returns a string formatted for clang-tool-style output."""
+    return "\n".join(map(str, [
+        "==== NEW ANNOTATION ====",
+        self.file_path,
+        self.function_name,
+        self.line_number,
+        self.type_name,
+        self.unique_id,
+        self.extra_id,
+        self.text,
+        "==== ANNOTATION ENDS ====",
+    ]))
+
+  def _parse_body(self, body):
+    """Tokenizes and parses the arguments given to the definition function."""
+    tokenizer = Tokenizer(body, self.file_path, self.line_number)
+
+    # unique_id
+    self.unique_id = tokenizer.advance('string_literal')
+    tokenizer.advance('comma')
+
+    # extra_id (Partial/BranchedCompleting)
+    if self.type_name == 'Partial' or self.type_name == 'BranchedCompleting':
+      self.extra_id = tokenizer.advance('string_literal')
+      tokenizer.advance('comma')
+
+    # partial_annotation (Completing/BranchedCompleting)
+    if self.type_name == 'Completing' or self.type_name == 'BranchedCompleting':
+      # Skip the |partial_annotation| argument. It can be a variable_name, or a
+      # FunctionName(), so skip the parentheses if they're there.
+      tokenizer.advance('symbol')
+      if tokenizer.maybe_advance('left_paren'):
+        tokenizer.advance('right_paren')
+      tokenizer.advance('comma')
+
+    # proto text
+    self.text = tokenizer.advance('string_literal')
+
+    # The function call should end here without any more arguments.
+    assert tokenizer.advance('right_paren')
+
+
+def get_line_number_at(string, pos):
+  """Find the line number for the char at position |pos|. 1-indexed."""
+  # This is inefficient: O(n). But we only run it once for each annotation
+  # definition, so the effect on total runtime is negligible.
+  return 1 + len(re.compile(r'\n').findall(string[:pos]))
+
+
+def is_inside_comment(string, pos):
+  """Checks if the position |pos| within string seems to be inside a comment.
+
+  This is a bit naive. Only checks for single-line comments (// ...), not block
+  comments (/* ...  */).
+
+  Args:
+    string: string to scan.
+    pos: position within the string.
+
+  Returns:
+    True if |string[pos]| looks like it's inside a C++ comment.
+  """
+  # Look for "//" on the same line in the reversed string.
+  return bool(re.match(r'[^\n]*//', string[pos::-1]))
+  # TODO(crbug/966883): Add multi-line comment support.
+
+
+def extract_annotations(file_path):
+  """Extracts and returns annotations from the file at |file_path|."""
+  with open(file_path) as f:
+    contents = f.read()
+
+  defs = []
+  for re_match in CALL_DETECTION_REGEX.finditer(contents):
+    if is_inside_comment(re_match.string, re_match.start()):
+      continue
+    defs.append(Annotation(file_path, re_match))
+  return defs
+
+
+def main():
+  parser = argparse.ArgumentParser(
+      description="Network Traffic Annotation Extractor.")
+  parser.add_argument(
+      '--build-path',
+      help='Specifies a compiled build directory, e.g. out/Debug.')
+  parser.add_argument(
+      '--no-filter', action='store_true',
+      help='Do not filter files based on compdb entries')
+  parser.add_argument(
+      'file_paths', nargs='+', help='List of files to process.')
+
+  args = parser.parse_args()
+
+  tools = NetworkTrafficAnnotationTools(args.build_path)
+  compdb_files = tools.GetCompDBFiles()
+
+  annotation_definitions = []
+
+  # Parse all the files.
+  # TODO(crbug/966883): Do this in parallel.
+  for file_path in args.file_paths:
+    if not args.no_filter and os.path.abspath(file_path) not in compdb_files:
+      continue
+    annotation_definitions.extend(extract_annotations(file_path))
+
+  # Print output.
+  for annotation in annotation_definitions:
+    print(annotation.clang_tool_output_string())
+
+  return 0
+
+
+if '__main__' == __name__:
+  sys.exit(main())
diff --git a/tools/traffic_annotation/scripts/extractor_test.py b/tools/traffic_annotation/scripts/extractor_test.py
new file mode 100755
index 0000000..d3c58e4
--- /dev/null
+++ b/tools/traffic_annotation/scripts/extractor_test.py
@@ -0,0 +1,85 @@
+#!/usr/bin/env python
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""
+Unit tests for extractor.py.
+"""
+
+import argparse
+import glob
+import os
+import unittest
+import re
+import subprocess
+
+def run_extractor(file):
+  script_path = os.path.join('..', 'extractor.py')
+  cmd_line = ["python", script_path, '--no-filter', file]
+  return subprocess.Popen(
+      cmd_line, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+
+
+def get_expected_files(source_file):
+  stdout_file = re.sub('\.cc$', '-stdout.txt', source_file)
+  stderr_file = re.sub('\.cc$', '-stderr.txt', source_file)
+  return (stdout_file, stderr_file)
+
+
+def remove_tracebacks(str):
+  """Removes python tracebacks from the string."""
+  regex = re.compile(
+      r'''
+       # A line that says "Traceback (...):"
+       ^Traceback[^\n]*:\n
+       # Followed by lines that begin with whitespace.
+       ((\s.*)?\n)*''',
+      re.MULTILINE | re.VERBOSE)
+  return re.sub(regex, '', str)
+
+
+class ExtractorTest(unittest.TestCase):
+  def testExtractor(self):
+    os.chdir(os.path.join(os.path.dirname(__file__), 'test_data'))
+    for source_file in glob.glob('*.cc'):
+      print("Running test on %s..." % source_file)
+      (stdout_file, stderr_file) = get_expected_files(source_file)
+      with open(stdout_file) as f:
+        expected_stdout = f.read()
+      with open(stderr_file) as f:
+        expected_stderr = f.read()
+
+      proc = run_extractor(source_file)
+      (stdout, stderr) = proc.communicate()
+
+      self.assertEqual(expected_stderr, remove_tracebacks(stderr))
+      self.assertEqual(int(bool(expected_stderr)), proc.returncode)
+      self.assertEqual(expected_stdout, stdout)
+
+
+def generate_expected_files():
+  os.chdir(os.path.join(os.path.dirname(__file__), 'test_data'))
+  for source_file in glob.glob('*.cc'):
+    proc = run_extractor(source_file)
+    (stdout, stderr) = proc.communicate()
+
+    (stdout_file, stderr_file) = get_expected_files(source_file)
+    with open(stdout_file, "w") as f:
+      f.write(stdout)
+    with open(stderr_file, "w") as f:
+      f.write(remove_tracebacks(stderr))
+
+
+if __name__ == '__main__':
+  parser = argparse.ArgumentParser(
+      description="Network Traffic Annotation Extractor Unit Tests")
+  parser.add_argument(
+      '--generate-expected-files', action='store_true',
+      help='Generate "-stdout.txt" and "-stderr.txt" for file in test_data')
+  args = parser.parse_args()
+
+  if args.generate_expected_files:
+    generate_expected_files()
+  else:
+    unittest.main()
diff --git a/tools/traffic_annotation/scripts/test_data/too_few_args-stderr.txt b/tools/traffic_annotation/scripts/test_data/too_few_args-stderr.txt
new file mode 100644
index 0000000..2661894
--- /dev/null
+++ b/tools/traffic_annotation/scripts/test_data/too_few_args-stderr.txt
@@ -0,0 +1,3 @@
+Exception: Expected comma in annotation definition at too_few_args.cc:8.
+near ');
+'
diff --git a/tools/traffic_annotation/scripts/test_data/too_few_args-stdout.txt b/tools/traffic_annotation/scripts/test_data/too_few_args-stdout.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tools/traffic_annotation/scripts/test_data/too_few_args-stdout.txt
diff --git a/tools/traffic_annotation/scripts/test_data/too_few_args.cc b/tools/traffic_annotation/scripts/test_data/too_few_args.cc
new file mode 100644
index 0000000..175eb44
--- /dev/null
+++ b/tools/traffic_annotation/scripts/test_data/too_few_args.cc
@@ -0,0 +1,8 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/traffic_annotation/network_traffic_annotation.h"
+
+net::NetworkTrafficAnnotationTag kTrafficAnnotation =
+    net::DefineNetworkTrafficAnnotation("id1");
diff --git a/tools/traffic_annotation/scripts/test_data/valid_file-stderr.txt b/tools/traffic_annotation/scripts/test_data/valid_file-stderr.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tools/traffic_annotation/scripts/test_data/valid_file-stderr.txt
diff --git a/tools/traffic_annotation/scripts/test_data/valid_file-stdout.txt b/tools/traffic_annotation/scripts/test_data/valid_file-stdout.txt
new file mode 100644
index 0000000..749d5c2
--- /dev/null
+++ b/tools/traffic_annotation/scripts/test_data/valid_file-stdout.txt
@@ -0,0 +1,77 @@
+==== NEW ANNOTATION ====
+source_file.cc
+XXX_UNIMPLEMENTED_XXX
+14
+Definition
+id1
+
+
+        semantics {
+          sender: "sender1"
+          description: "desc1"
+          trigger: "trigger1"
+          data: "data1"
+          destination: GOOGLE_OWNED_SERVICE
+        }
+        policy {
+          cookies_allowed: NO
+          setting: "setting1"
+          chrome_policy {
+            SpellCheckServiceEnabled {
+                SpellCheckServiceEnabled: false
+            }
+          }
+        }
+        comments: "comment1"
+==== ANNOTATION ENDS ====
+==== NEW ANNOTATION ====
+source_file.cc
+XXX_UNIMPLEMENTED_XXX
+36
+Partial
+id2
+completing_id2
+
+        semantics {
+          sender: "sender2"
+          description: "desc2"
+          trigger: "trigger2"
+          data: "data2"
+          destination: WEBSITE
+        }
+==== ANNOTATION ENDS ====
+==== NEW ANNOTATION ====
+source_file.cc
+XXX_UNIMPLEMENTED_XXX
+46
+Completing
+id3
+
+
+        policy {
+          cookies_allowed: YES
+          cookie_store: "user"
+          setting: "setting3"
+          chrome_policy {
+            SpellCheckServiceEnabled {
+                SpellCheckServiceEnabled: false
+            }
+          }
+        }
+        comments: "comment3"
+==== ANNOTATION ENDS ====
+==== NEW ANNOTATION ====
+source_file.cc
+XXX_UNIMPLEMENTED_XXX
+61
+BranchedCompleting
+id4
+branch4
+
+        policy {
+          cookies_allowed: YES
+          cookie_store: "user"
+          setting: "setting4"
+          policy_exception_justification: "justification"
+        }
+==== ANNOTATION ENDS ====
diff --git a/tools/traffic_annotation/scripts/test_data/valid_file.cc b/tools/traffic_annotation/scripts/test_data/valid_file.cc
new file mode 100644
index 0000000..b0bbe248
--- /dev/null
+++ b/tools/traffic_annotation/scripts/test_data/valid_file.cc
@@ -0,0 +1,124 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/traffic_annotation/network_traffic_annotation.h"
+
+#include "dummy_classes.h"
+
+// This file provides samples for testing the extractor.py replacement script
+// for the clang tool.
+namespace {
+
+net::NetworkTrafficAnnotationTag kTrafficAnnotation =
+    net::DefineNetworkTrafficAnnotation("id1", R"(
+        semantics {
+          sender: "sender1"
+          description: "desc1"
+          trigger: "trigger1"
+          data: "data1"
+          destination: GOOGLE_OWNED_SERVICE
+        }
+        policy {
+          cookies_allowed: NO
+          setting: "setting1"
+          chrome_policy {
+            SpellCheckServiceEnabled {
+                SpellCheckServiceEnabled: false
+            }
+          }
+        }
+        comments: "comment1")");
+}
+
+void TestAnnotations() {
+  net::PartialNetworkTrafficAnnotationTag partial_traffic_annotation =
+      net::DefinePartialNetworkTrafficAnnotation("id2", "completing_id2", R"(
+        semantics {
+          sender: "sender2"
+          description: "desc2"
+          trigger: "trigger2"
+          data: "data2"
+          destination: WEBSITE
+        })");
+
+  net::NetworkTrafficAnnotationTag completed_traffic_annotation =
+      net::CompleteNetworkTrafficAnnotation("id3", partial_traffic_annotation,
+                                            R"(
+        policy {
+          cookies_allowed: YES
+          cookie_store: "user"
+          setting: "setting3"
+          chrome_policy {
+            SpellCheckServiceEnabled {
+                SpellCheckServiceEnabled: false
+            }
+          }
+        }
+        comments: "comment3")");
+
+  net::NetworkTrafficAnnotationTag completed_branch_traffic_annotation =
+      net::BranchedCompleteNetworkTrafficAnnotation(
+          "id4", "branch4", partial_traffic_annotation, R"(
+        policy {
+          cookies_allowed: YES
+          cookie_store: "user"
+          setting: "setting4"
+          policy_exception_justification: "justification"
+        })");
+}
+
+void TestURLFetcherCreate() {
+  net::URLFetcherDelegate* delegate = nullptr;
+  net::URLFetcher::Create(GURL(), net::URLFetcher::RequestType::TEST_VALUE,
+                          delegate);
+
+  net::URLFetcher::Create(0, GURL(), net::URLFetcher::RequestType::TEST_VALUE,
+                          delegate);
+
+  net::URLFetcher::Create(GURL(), net::URLFetcher::RequestType::TEST_VALUE,
+                          delegate, kTrafficAnnotation);
+
+  net::URLFetcher::Create(0, GURL(), net::URLFetcher::RequestType::TEST_VALUE,
+                          delegate, NO_TRAFFIC_ANNOTATION_YET);
+}
+
+void TestCreateRequest() {
+  net::URLRequest::Delegate* delegate = nullptr;
+  net::URLRequestContext context;
+
+  context.CreateRequest(GURL(), net::RequestPriority::TEST_VALUE, delegate);
+  context.CreateRequest(GURL(), net::RequestPriority::TEST_VALUE, delegate,
+                        kTrafficAnnotation);
+}
+
+void TestInitList() {
+  net::NetworkTrafficAnnotationTag({-1});
+  net::MutableNetworkTrafficAnnotationTag({-2});
+  net::PartialNetworkTrafficAnnotationTag({-1});
+  net::MutablePartialNetworkTrafficAnnotationTag({-2});
+  int i = 0;
+  net::NetworkTrafficAnnotationTag({i});
+}
+
+void TestAssignment() {
+  net::MutableNetworkTrafficAnnotationTag tag1;
+  tag1.unique_id_hash_code = 1;
+
+  net::MutablePartialNetworkTrafficAnnotationTag tag2;
+  tag2.unique_id_hash_code = 2;
+
+  // Test if assignment to |unique_id_hash_code| of another structure is not
+  // caught.
+  struct something_else {
+    int unique_id_hash_code;
+  } x;
+
+  x.unique_id_hash_code = 3;
+}
+
+void DummyFunction(net::NetworkTrafficAnnotationTag traffic_annotation) {}
+
+void TestMacroExpansion() {
+  DummyFunction(NO_TRAFFIC_ANNOTATION_YET);
+}
diff --git a/tools/traffic_annotation/scripts/test_data/wrong_arg_type-stderr.txt b/tools/traffic_annotation/scripts/test_data/wrong_arg_type-stderr.txt
new file mode 100644
index 0000000..8136ace
--- /dev/null
+++ b/tools/traffic_annotation/scripts/test_data/wrong_arg_type-stderr.txt
@@ -0,0 +1,2 @@
+Exception: Expected string_literal in annotation definition at wrong_arg_type.cc:8.
+near 'should_be_'
diff --git a/tools/traffic_annotation/scripts/test_data/wrong_arg_type-stdout.txt b/tools/traffic_annotation/scripts/test_data/wrong_arg_type-stdout.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tools/traffic_annotation/scripts/test_data/wrong_arg_type-stdout.txt
diff --git a/tools/traffic_annotation/scripts/test_data/wrong_arg_type.cc b/tools/traffic_annotation/scripts/test_data/wrong_arg_type.cc
new file mode 100644
index 0000000..8028fea
--- /dev/null
+++ b/tools/traffic_annotation/scripts/test_data/wrong_arg_type.cc
@@ -0,0 +1,8 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/traffic_annotation/network_traffic_annotation.h"
+
+net::NetworkTrafficAnnotationTag kTrafficAnnotation =
+    net::DefineNetworkTrafficAnnotation(should_be_a_string_literal, "XXX");
diff --git a/tools/traffic_annotation/summary/annotations.xml b/tools/traffic_annotation/summary/annotations.xml
index b17f0c9..8064b0e3 100644
--- a/tools/traffic_annotation/summary/annotations.xml
+++ b/tools/traffic_annotation/summary/annotations.xml
@@ -173,8 +173,8 @@
  <item id="omnibox_result_change" hash_code="73107389" type="0" content_hash_code="24802647" os_list="linux,windows" file_path="chrome/browser/ui/omnibox/chrome_omnibox_client.cc"/>
  <item id="omnibox_suggest" hash_code="47815025" type="0" content_hash_code="86297726" os_list="linux,windows" file_path="components/omnibox/browser/search_provider.cc"/>
  <item id="omnibox_suggest_deletion" hash_code="84212388" type="0" content_hash_code="24981550" os_list="linux,windows" file_path="components/omnibox/browser/base_search_provider.cc"/>
- <item id="omnibox_zerosuggest" hash_code="7687691" type="0" content_hash_code="119419625" os_list="linux,windows" file_path="components/omnibox/browser/contextual_suggestions_service.cc"/>
- <item id="omnibox_zerosuggest_experimental" hash_code="3813491" type="0" content_hash_code="22929259" os_list="linux,windows" file_path="components/omnibox/browser/contextual_suggestions_service.cc"/>
+ <item id="omnibox_zerosuggest" hash_code="7687691" type="0" content_hash_code="119419625" os_list="linux,windows" file_path="components/omnibox/browser/remote_suggestions_service.cc"/>
+ <item id="omnibox_zerosuggest_experimental" hash_code="3813491" type="0" content_hash_code="22929259" os_list="linux,windows" file_path="components/omnibox/browser/remote_suggestions_service.cc"/>
  <item id="one_google_bar_service" hash_code="78917933" type="0" content_hash_code="46527252" os_list="linux,windows" file_path="chrome/browser/search/one_google_bar/one_google_bar_loader_impl.cc"/>
  <item id="open_search" hash_code="107267424" type="0" content_hash_code="83025542" os_list="linux,windows" file_path="components/search_engines/template_url_fetcher.cc"/>
  <item id="origin_policy_loader" hash_code="6483617" type="0" content_hash_code="20680909" os_list="linux,windows" file_path="services/network/origin_policy/origin_policy_fetcher.cc"/>
diff --git a/tools/web_dev_style/css_checker.py b/tools/web_dev_style/css_checker.py
index da17bd8..4c13441 100644
--- a/tools/web_dev_style/css_checker.py
+++ b/tools/web_dev_style/css_checker.py
@@ -22,6 +22,41 @@
     self.output_api = output_api
     self.file_filter = file_filter
 
+  def RemoveAtBlocks(self, s):
+    re = self.input_api.re
+
+    def _remove_comments(s):
+      return re.sub(r'/\*.*\*/', '', s)
+
+    lines = s.splitlines()
+    i = 0
+    while i < len(lines):
+      line = _remove_comments(lines[i]).strip()
+      if (len(line) > 0 and line[0] == '@' and
+          not line[1:].startswith(("apply", "page")) and
+          line[-1] == '{' and not re.match("\d+x\b", line[1:])):
+        j = i
+        open_brackets = 1
+        while open_brackets > 0:
+          j += 1
+          inner_line = _remove_comments(lines[j]).strip()
+          if not inner_line:
+            continue
+          if inner_line[-1] == '{':
+            open_brackets += 1
+          elif inner_line[-1] == '}':
+            # Ignore single line keyframes (from { height: 0; }).
+            if not re.match(r'\s*(from|to|\d+%)\s*{', inner_line):
+              open_brackets -= 1
+          elif len(inner_line) > 1 and inner_line[-2:] == '};':
+            # End of mixin. TODO(dbeam): worth detecting ": {" start?
+            open_brackets -= 1
+        del lines[j]  # Later index first, as indices shift with deletion.
+        del lines[i]
+      else:
+        i += 1
+    return '\n'.join(lines)
+
   def RunChecks(self):
     # We use this a lot, so make a nick name variable.
     re = self.input_api.re
@@ -32,27 +67,11 @@
     def _is_gray(s):
       return s[0] == s[1] == s[2] if len(s) == 3 else s[0:2] == s[2:4] == s[4:6]
 
-    def _remove_all(s):
-      s = _remove_grit(s)  # Must be done first.
-      s = _remove_ats(s)
-      s = _remove_comments_except_for_disables(s)
-      s = _remove_mixins_and_valid_vars(s)
-      s = _remove_template_expressions(s)
-      return s
-
     def _extract_inline_style(s):
       return '\n'.join(re.findall(r'<style\b[^>]*>([^<]*)<\/style>', s))
 
-    def _remove_ats(s):
-      return re.sub(r"""
-          @(?!apply)(?!\d+x\b)    # @at-keyword, not (apply|2x)
-          \w+[^'"]*?{             # selector junk {
-          (.*{.*?})+              # inner { curly } blocks, rules, and selector
-          .*?}                    # stuff up to the first end curly }
-          """, r'\1', s, flags=re.DOTALL | re.VERBOSE)
-
     def _remove_comments_except_for_disables(s):
-      return re.sub(r'/\*(?! %s \*/$).*?\*/' % self.DISABLE_FORMAT,'', s,
+      return re.sub(r'/\*(?! %s \*/$).*?\*/' % self.DISABLE_FORMAT, '', s,
                     flags=re.DOTALL | re.MULTILINE)
 
     def _remove_grit(s):
@@ -454,13 +473,25 @@
       if not is_html and not path.endswith('.css'):
         continue
 
+      file_contents = '\n'.join(f.NewContents())
+
       # Remove all /*comments*/, @at-keywords, and grit <if|include> tags; we're
       # not using a real parser. TODO(dbeam): Check alpha in <if> blocks.
-      file_contents = _remove_all('\n'.join(f.NewContents()))
 
-      # Handle CSS files and HTML files with inline styles.
+      file_contents = _remove_grit(file_contents)  # Must be done first.
+
       if is_html:
-        file_contents = _extract_inline_style(file_contents)
+        # The <style> extraction regex can't handle <if> nor /* <tag> */.
+        prepped_html = _remove_comments_except_for_disables(file_contents)
+        file_contents = _extract_inline_style(prepped_html)
+
+      file_contents = self.RemoveAtBlocks(file_contents)
+
+      if not is_html:
+        file_contents = _remove_comments_except_for_disables(file_contents)
+
+      file_contents = _remove_mixins_and_valid_vars(file_contents)
+      file_contents = _remove_template_expressions(file_contents)
 
       files.append((path, file_contents))
 
diff --git a/tools/web_dev_style/css_checker_test.py b/tools/web_dev_style/css_checker_test.py
index a122afd..3b177fee1 100755
--- a/tools/web_dev_style/css_checker_test.py
+++ b/tools/web_dev_style/css_checker_test.py
@@ -88,13 +88,23 @@
   visibility: hidden;
   opacity: 1; /* TODO(dbeam): Fix this. */
 }
-</if>""", """
+</if>
+
+@media (prefers-color-scheme: dark) {
+  a[href] {
+    z-index: 3;
+    color: blue;
+  }
+}""", """
 - Alphabetize properties and list vendor specific (i.e. -webkit) above standard.
     display: block;
     color: red;
 
     z-index: 5;
-    color: black;""")
+    color: black;
+
+    z-index: 3;
+    color: blue;""")
 
   def testCssStringWithAt(self):
     self.VerifyContentIsValid("""
@@ -196,11 +206,6 @@
 
   def testCssCloseBraceOnNewLine(self):
     self.VerifyContentsProducesOutput("""
-@media { /* TODO(dbeam) Fix this case. */
-  .rule {
-    display: block;
-  }}
-
 @-webkit-keyframe blah {
   from { height: rotate(-10turn); }
   100% { height: 500px; }
@@ -583,7 +588,7 @@
     flex-direction:column;
 """, filename='test.html')
 
-  def testInlineSTyleInHtmlWithTagsInComments(self):
+  def testInlineStyleInHtmlWithTagsInComments(self):
     self.VerifyContentsProducesOutput("""<!doctype html>
 <html>
   <style>
@@ -598,6 +603,108 @@
     flex-direction:column;
 """, filename='test.html')
 
+  def testRemoveAtBlocks(self):
+    self.mox.ReplayAll()
+    self.input_api.AffectedFiles(include_deletes=False, file_filter=None)
+
+    checker = css_checker.CSSChecker(self.input_api, self.output_api)
+
+    self.assertEqual(checker.RemoveAtBlocks("""
+@media (prefers-color-scheme: dark) {
+  .magic {
+    color: #000;
+  }
+}"""), """
+  .magic {
+    color: #000;
+  }""")
+
+    self.assertEqual(checker.RemoveAtBlocks("""
+@media (prefers-color-scheme: dark) {
+  .magic {
+    --mixin-definition: {
+      color: red;
+    };
+  }
+}"""), """
+  .magic {
+    --mixin-definition: {
+      color: red;
+    };
+  }""")
+
+    self.assertEqual(checker.RemoveAtBlocks("""
+@keyframes jiggle {
+  from { left: 0; }
+  50% { left: 100%; }
+  to { left: 10%; }
+}"""), """
+  from { left: 0; }
+  50% { left: 100%; }
+  to { left: 10%; }""")
+
+    self.assertEqual(checker.RemoveAtBlocks("""
+@media print {
+  .rule1 {
+    color: black;
+  }
+  .rule2 {
+    margin: 1in;
+  }
+}"""), """
+  .rule1 {
+    color: black;
+  }
+  .rule2 {
+    margin: 1in;
+  }""")
+
+    self.assertEqual(checker.RemoveAtBlocks("""
+@media (prefers-color-scheme: dark) {
+  .rule1 {
+    color: gray;
+  }
+  .rule2 {
+    margin: .5in;
+  }
+  @keyframe dark-fade {
+    0% { background: black; }
+    100% { background: darkgray; }
+  }
+}"""), """
+  .rule1 {
+    color: gray;
+  }
+  .rule2 {
+    margin: .5in;
+  }
+    0% { background: black; }
+    100% { background: darkgray; }""")
+
+    self.assertEqual(checker.RemoveAtBlocks("""
+@-webkit-keyframe anim {
+  0% { /* Ignore key frames */
+    width: 0px;
+  }
+  10% {
+    width: 10px;
+  }
+  50% { background-image: url(blah.svg); }
+  100% {
+    width: 100px;
+  }
+}"""), """
+  0% { /* Ignore key frames */
+    width: 0px;
+  }
+  10% {
+    width: 10px;
+  }
+  50% { background-image: url(blah.svg); }
+  100% {
+    width: 100px;
+  }""")
+
 
 if __name__ == '__main__':
   unittest.main()
diff --git a/ui/android/resources/resource_manager_impl_unittest.cc b/ui/android/resources/resource_manager_impl_unittest.cc
index 077a050..051aea2d 100644
--- a/ui/android/resources/resource_manager_impl_unittest.cc
+++ b/ui/android/resources/resource_manager_impl_unittest.cc
@@ -5,7 +5,7 @@
 #include <stddef.h>
 
 #include "base/macros.h"
-#include "base/message_loop/message_loop.h"
+#include "base/test/scoped_task_environment.h"
 #include "base/trace_event/memory_dump_manager.h"
 #include "base/trace_event/process_memory_dump.h"
 #include "cc/resources/ui_resource_bitmap.h"
@@ -113,7 +113,7 @@
   }
 
  private:
-  base::MessageLoop message_loop_;
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
   WindowAndroid* window_android_;
 
  protected:
diff --git a/ui/base/clipboard/clipboard_util_win.cc b/ui/base/clipboard/clipboard_util_win.cc
index 7091ece..20614ef3 100644
--- a/ui/base/clipboard/clipboard_util_win.cc
+++ b/ui/base/clipboard/clipboard_util_win.cc
@@ -197,12 +197,11 @@
   base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
                                                 base::BlockingType::MAY_BLOCK);
 
-  base::FilePath temp_path = base::FilePath();
-
   if (!hdata)
-    return temp_path;
+    return base::FilePath();
 
-  temp_path = CreateTemporaryFileWithSuggestedName(suggested_name);
+  base::FilePath temp_path =
+      CreateTemporaryFileWithSuggestedName(suggested_name);
 
   if (!temp_path.empty()) {
     base::win::ScopedHGlobal<char*> data(hdata);
@@ -401,7 +400,6 @@
     unsigned int uniquifier = 1;
 
     for (size_t i = 0; i < num_files; i++) {
-      base::FilePath display_name;
       // Folder entries not currently supported--skip this item.
       if ((fgd->fgd[i].dwFlags & FD_ATTRIBUTES) &&
           (fgd->fgd[i].dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
@@ -410,7 +408,7 @@
                       << "' refers to a directory (not supported).";
         continue;
       }
-      display_name = GetUniqueVirtualFilename(
+      base::FilePath display_name = GetUniqueVirtualFilename(
           ConvertString(fgd->fgd[i].cFileName), *filenames, &uniquifier);
 
       filenames->push_back(display_name);
diff --git a/ui/base/dragdrop/os_exchange_data_win_unittest.cc b/ui/base/dragdrop/os_exchange_data_win_unittest.cc
index bf74612e..3fbcc72 100644
--- a/ui/base/dragdrop/os_exchange_data_win_unittest.cc
+++ b/ui/base/dragdrop/os_exchange_data_win_unittest.cc
@@ -370,7 +370,6 @@
       EXPECT_EQ(path_placeholder, file_infos[i].path);
     }
 
-    std::string read_contents;
     base::FilePath temp_dir;
     EXPECT_TRUE(base::GetTempDir(&temp_dir));
 
@@ -399,6 +398,7 @@
           base::MakeLongFilePath(retrieved_virtual_files_[i].path.DirName()));
       EXPECT_EQ(kTestFilenames_and_Contents[i].first.Extension(),
                 retrieved_virtual_files_[i].path.Extension());
+      std::string read_contents;
       EXPECT_TRUE(base::ReadFileToString(retrieved_virtual_files_[i].path,
                                          &read_contents));
       if (tymed != TYMED_ISTORAGE) {
@@ -495,7 +495,6 @@
       }
     }
 
-    std::string read_contents;
     base::FilePath temp_dir;
     EXPECT_TRUE(base::GetTempDir(&temp_dir));
 
@@ -535,6 +534,7 @@
           base::MakeLongFilePath(retrieved_virtual_files_[i].path.DirName()));
       EXPECT_EQ(kTestFilenames_and_Contents[i].first.Extension(),
                 retrieved_virtual_files_[i].path.Extension());
+      std::string read_contents;
       EXPECT_TRUE(base::ReadFileToString(retrieved_virtual_files_[i].path,
                                          &read_contents));
       if (tymed != TYMED_ISTORAGE) {
@@ -578,7 +578,6 @@
       }
     }
 
-    std::string read_contents;
     base::FilePath temp_dir;
     EXPECT_TRUE(base::GetTempDir(&temp_dir));
 
@@ -618,6 +617,7 @@
           base::MakeLongFilePath(retrieved_virtual_files_[i].path.DirName()));
       EXPECT_EQ(kTestFilenames_and_Contents[i].first.Extension(),
                 retrieved_virtual_files_[i].path.Extension());
+      std::string read_contents;
       EXPECT_TRUE(base::ReadFileToString(retrieved_virtual_files_[i].path,
                                          &read_contents));
       if (tymed != TYMED_ISTORAGE) {
@@ -651,7 +651,7 @@
           {pathWithInvalidFileNameCharacters,
            std::string("just some data\0with\0nulls", 25)},
           {// Test that still get a unique name if a previous uniquified
-           // name is duplicate of this one.
+           // name is a duplicate of this one.
            pathWithInvalidFileNameCharacters.InsertBeforeExtension(
                FILE_PATH_LITERAL(" (1)")),
            std::string("just some more data")},
@@ -660,7 +660,7 @@
           {empty_display_name, std::string("data for an empty display name")},
           {empty_display_name,
            std::string("data for another empty display name")},
-          // Expect a good behavior if the display name length exceeds MAX_PATH.
+          // Expect good behavior if the display name length exceeds MAX_PATH.
           {maxpath_display_name,
            std::string("data for a >MAX_PATH display name")},
           {maxpath_display_name,
@@ -689,7 +689,6 @@
       }
     }
 
-    std::string read_contents;
     base::FilePath temp_dir;
     EXPECT_TRUE(base::GetTempDir(&temp_dir));
 
@@ -737,6 +736,7 @@
           base::MakeLongFilePath(retrieved_virtual_files_[i].path.DirName()));
       EXPECT_EQ(kTestFilenames_and_Contents[i].first.Extension(),
                 retrieved_virtual_files_[i].path.Extension());
+      std::string read_contents;
       // Ability to read the contents implies a temp file was successfully
       // created on the file system even though the original suggested display
       // name had invalid filename characters.
@@ -775,7 +775,6 @@
                 file_infos[i].display_name);
     }
 
-    std::string read_contents;
     base::FilePath temp_dir;
     EXPECT_TRUE(base::GetTempDir(&temp_dir));
 
@@ -805,6 +804,7 @@
           base::MakeLongFilePath(retrieved_virtual_files_[i].path.DirName()));
       EXPECT_EQ(kTestFilenames_and_Contents[i].first.Extension(),
                 retrieved_virtual_files_[i].path.Extension());
+      std::string read_contents;
       EXPECT_TRUE(base::ReadFileToString(retrieved_virtual_files_[i].path,
                                          &read_contents));
       // IStorage uses compound files, so temp files won't be flat text files.
diff --git a/ui/compositor/BUILD.gn b/ui/compositor/BUILD.gn
index fd7903188..f102bec3 100644
--- a/ui/compositor/BUILD.gn
+++ b/ui/compositor/BUILD.gn
@@ -53,6 +53,7 @@
     "layer_threaded_animation_delegate.h",
     "layer_tree_owner.cc",
     "layer_tree_owner.h",
+    "layer_type.cc",
     "layer_type.h",
     "overscroll/scroll_input_handler.cc",
     "overscroll/scroll_input_handler.h",
diff --git a/ui/compositor/layer.h b/ui/compositor/layer.h
index 60ec24e..0850558 100644
--- a/ui/compositor/layer.h
+++ b/ui/compositor/layer.h
@@ -255,6 +255,7 @@
   // Furthermore: A mask layer can only be set to one layer.
   void SetMaskLayer(Layer* layer_mask);
   Layer* layer_mask_layer() { return layer_mask_; }
+  const Layer* layer_mask_layer() const { return layer_mask_; }
 
   // Sets the visibility of the Layer. A Layer may be visible but not drawn.
   // This happens if any ancestor of a Layer is not visible.
@@ -431,6 +432,7 @@
   size_t GetApproximateUnsharedMemoryUsage() const override;
 
   cc::Layer* cc_layer_for_testing() { return cc_layer_; }
+  const cc::Layer* cc_layer_for_testing() const { return cc_layer_; }
 
   // TextureLayerClient implementation.
   bool PrepareTransferableResource(
diff --git a/ui/compositor/layer_type.cc b/ui/compositor/layer_type.cc
new file mode 100644
index 0000000..8abc00a
--- /dev/null
+++ b/ui/compositor/layer_type.cc
@@ -0,0 +1,26 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/compositor/layer_type.h"
+
+#include "base/logging.h"
+
+namespace ui {
+
+base::StringPiece LayerTypeToString(LayerType type) {
+  switch (type) {
+    case LayerType::LAYER_NOT_DRAWN:
+      return "not_drawn";
+    case LayerType::LAYER_TEXTURED:
+      return "textured";
+    case LayerType::LAYER_SOLID_COLOR:
+      return "solid_color";
+    case LayerType::LAYER_NINE_PATCH:
+      return "nine_patch";
+  }
+  NOTREACHED();
+  return {};
+}
+
+}  // namespace ui
diff --git a/ui/compositor/layer_type.h b/ui/compositor/layer_type.h
index 9831916e..18f4bb7 100644
--- a/ui/compositor/layer_type.h
+++ b/ui/compositor/layer_type.h
@@ -5,6 +5,9 @@
 #ifndef UI_COMPOSITOR_LAYER_TYPE_H_
 #define UI_COMPOSITOR_LAYER_TYPE_H_
 
+#include "base/strings/string_piece.h"
+#include "ui/compositor/compositor_export.h"
+
 namespace ui {
 
 enum LayerType {
@@ -22,6 +25,8 @@
   LAYER_NINE_PATCH = 3,
 };
 
+COMPOSITOR_EXPORT base::StringPiece LayerTypeToString(LayerType type);
+
 }  // namespace ui
 
 #endif  // UI_COMPOSITOR_LAYER_TYPE_H_
diff --git a/ui/gl/android/android_surface_control_compat.cc b/ui/gl/android/android_surface_control_compat.cc
index 8dadd57..7ad22f4 100644
--- a/ui/gl/android/android_surface_control_compat.cc
+++ b/ui/gl/android/android_surface_control_compat.cc
@@ -330,13 +330,15 @@
 SurfaceControl::Surface::Surface(const Surface& parent, const char* name) {
   surface_ = SurfaceControlMethods::Get().ASurfaceControl_createFn(
       parent.surface(), name);
-  DCHECK(surface_);
+  if (!surface_)
+    LOG(ERROR) << "Failed to create ASurfaceControl : " << name;
 }
 
 SurfaceControl::Surface::Surface(ANativeWindow* parent, const char* name) {
   surface_ = SurfaceControlMethods::Get().ASurfaceControl_createFromWindowFn(
       parent, name);
-  DCHECK(surface_);
+  if (!surface_)
+    LOG(ERROR) << "Failed to create ASurfaceControl : " << name;
 }
 
 SurfaceControl::Surface::~Surface() {
diff --git a/ui/gl/gl_surface_egl_surface_control.cc b/ui/gl/gl_surface_egl_surface_control.cc
index fe2be62..af1c77e 100644
--- a/ui/gl/gl_surface_egl_surface_control.cc
+++ b/ui/gl/gl_surface_egl_surface_control.cc
@@ -65,6 +65,9 @@
 }
 
 bool GLSurfaceEGLSurfaceControl::Initialize(GLSurfaceFormat format) {
+  if (!root_surface_->surface())
+    return false;
+
   format_ = format;
 
   // Surfaceless is always disabled on Android so we create a 1x1 pbuffer