diff --git a/DEPS b/DEPS
index df441687..8ba00fb2 100644
--- a/DEPS
+++ b/DEPS
@@ -105,11 +105,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': 'c45a5c559365b2e04c89a3ef09752e5c1bb24aa2',
+  'skia_revision': '94fee93c9b23bd1a32604753da8bef755d6c8a95',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'v8_revision': '66a2db59c17dfef7405a3ad13b47d28d815d7584',
+  'v8_revision': 'dcf3638eea939ac243535d77afa3aa0b522ba02b',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling swarming_client
   # and whatever else without interference from each other.
@@ -117,7 +117,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
-  'angle_revision': 'e076a2327f0d082d46683f32614c495e049a4bb2',
+  'angle_revision': '6fb8ba4e866045dbcbeaabb6d58bb62f66e2c48c',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling build tools
   # and whatever else without interference from each other.
@@ -129,7 +129,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
-  'pdfium_revision': '481749905d444745ee0ba76d9bcf42b3b009bb27',
+  'pdfium_revision': 'ff402c2c4ce8ae8690959262ca731d5cc6bd7015',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling openmax_dl
   # and whatever else without interference from each other.
@@ -153,7 +153,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling NaCl
   # and whatever else without interference from each other.
-  'nacl_revision': 'e6ce828ef60c4c1438867b535efbbb5d9a177c0e',
+  'nacl_revision': 'aebc9e5205dcaad5d5954a18abc532316a954644',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling freetype
   # and whatever else without interference from each other.
@@ -550,7 +550,7 @@
 
   # Build tools for Chrome OS. Note: This depends on third_party/pyelftools.
   'src/third_party/chromite': {
-      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '9a962fc1e6e5de1a1881292cb7575fc0bfd4b1a9',
+      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '9e945c84d2bebbeb4d2db11da9c193fbada97dc6',
       'condition': 'checkout_linux',
   },
 
@@ -575,7 +575,7 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'fb734036f4b5ae6d5afc63cbfc41d3a5d1c29a82',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '40bacee96a94600ad2179d69a8025469d119960f',
 
   'src/third_party/devtools-node-modules':
     Var('chromium_git') + '/external/github.com/ChromeDevTools/devtools-node-modules' + '@' + Var('devtools_node_modules_revision'),
@@ -923,7 +923,7 @@
   },
 
   'src/third_party/perfetto':
-    Var('android_git') + '/platform/external/perfetto.git' + '@' +  '4d831cea60c7428162cd3843a2b3f0ff225a6e07',
+    Var('android_git') + '/platform/external/perfetto.git' + '@' +  '0b69a335b8824928bd64d532046c0676d8a18c8a',
 
   'src/third_party/perl': {
       'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + 'ac0d98b5cee6c024b0cffeb4f8f45b6fc5ccdb78',
@@ -1045,7 +1045,7 @@
     Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + 'a5c263cc63ffc2cc189b5214074c8792067c1853',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + '056d811b6a044cd7e02da1133a520bc2d489836f',
+    Var('webrtc_git') + '/src.git' + '@' + '4597e0c46fc5ecb1c63c325f87f91bdfc3c1c3fd',
 
   'src/third_party/xdg-utils': {
       'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d',
diff --git a/apps/OWNERS b/apps/OWNERS
index 82a80f6..9dc06ee 100644
--- a/apps/OWNERS
+++ b/apps/OWNERS
@@ -2,5 +2,9 @@
 benwells@chromium.org
 tapted@chromium.org
 
+# Cleanups / renames
+dominickn@chromium.org
+mgiuca@chromium.org
+
 # TEAM: apps-dev@chromium.org
 # COMPONENT: Platform>Apps
diff --git a/ash/BUILD.gn b/ash/BUILD.gn
index effe450e..83400ea 100644
--- a/ash/BUILD.gn
+++ b/ash/BUILD.gn
@@ -151,6 +151,8 @@
     "assistant/ui/main_stage/suggestion_container_view.h",
     "assistant/ui/main_stage/ui_element_container_view.cc",
     "assistant/ui/main_stage/ui_element_container_view.h",
+    "assistant/util/animation_util.cc",
+    "assistant/util/animation_util.h",
     "assistant/util/deep_link_util.cc",
     "assistant/util/deep_link_util.h",
     "autoclick/autoclick_controller.cc",
diff --git a/ash/assistant/assistant_ui_controller.cc b/ash/assistant/assistant_ui_controller.cc
index 98d001e3..cb68116 100644
--- a/ash/assistant/assistant_ui_controller.cc
+++ b/ash/assistant/assistant_ui_controller.cc
@@ -138,6 +138,17 @@
     container_view_->GetWidget()->Activate();
 }
 
+void AssistantUiController::OnAssistantMiniViewPressed() {
+  InputModality input_modality = assistant_controller_->interaction_controller()
+                                     ->model()
+                                     ->input_modality();
+
+  // When not using stylus input modality, pressing the Assistant mini view
+  // will cause the UI to expand.
+  if (input_modality != InputModality::kStylus)
+    UpdateUiMode(AssistantUiMode::kMainUi);
+}
+
 bool AssistantUiController::OnCaptionButtonPressed(CaptionButtonId id) {
   switch (id) {
     case CaptionButtonId::kBack:
diff --git a/ash/assistant/assistant_ui_controller.h b/ash/assistant/assistant_ui_controller.h
index 9ae4b96..7f11bb12 100644
--- a/ash/assistant/assistant_ui_controller.h
+++ b/ash/assistant/assistant_ui_controller.h
@@ -11,6 +11,7 @@
 #include "ash/assistant/model/assistant_screen_context_model_observer.h"
 #include "ash/assistant/model/assistant_ui_model.h"
 #include "ash/assistant/model/assistant_ui_model_observer.h"
+#include "ash/assistant/ui/assistant_mini_view.h"
 #include "ash/assistant/ui/caption_bar.h"
 #include "ash/assistant/ui/dialog_plate/dialog_plate.h"
 #include "ash/highlighter/highlighter_controller.h"
@@ -44,6 +45,7 @@
       public AssistantInteractionModelObserver,
       public AssistantScreenContextModelObserver,
       public AssistantUiModelObserver,
+      public AssistantMiniViewDelegate,
       public CaptionBarDelegate,
       public DialogPlateObserver,
       public HighlighterController::Observer {
@@ -78,6 +80,9 @@
   void OnScreenContextRequestStateChanged(
       ScreenContextRequestState request_state) override;
 
+  // AssistantMiniViewDelegate:
+  void OnAssistantMiniViewPressed() override;
+
   // CaptionBarDelegate:
   bool OnCaptionButtonPressed(CaptionButtonId id) override;
 
diff --git a/ash/assistant/ui/assistant_container_view.cc b/ash/assistant/ui/assistant_container_view.cc
index 47786da..7998c29b 100644
--- a/ash/assistant/ui/assistant_container_view.cc
+++ b/ash/assistant/ui/assistant_container_view.cc
@@ -103,6 +103,7 @@
   // Mini view.
   assistant_mini_view_ =
       std::make_unique<AssistantMiniView>(assistant_controller_);
+  assistant_mini_view_->set_delegate(assistant_controller_->ui_controller());
   assistant_mini_view_->set_owned_by_client();
 
   // Web view.
diff --git a/ash/assistant/ui/assistant_mini_view.cc b/ash/assistant/ui/assistant_mini_view.cc
index 14589de..0b49a43 100644
--- a/ash/assistant/ui/assistant_mini_view.cc
+++ b/ash/assistant/ui/assistant_mini_view.cc
@@ -30,7 +30,9 @@
 }  // namespace
 
 AssistantMiniView::AssistantMiniView(AssistantController* assistant_controller)
-    : assistant_controller_(assistant_controller), label_(new views::Label()) {
+    : views::Button(this),
+      assistant_controller_(assistant_controller),
+      label_(new views::Label()) {
   InitLayout();
 
   // AssistantController indirectly owns the view hierarchy to which
@@ -85,6 +87,12 @@
                              ->input_modality());
 }
 
+void AssistantMiniView::ButtonPressed(views::Button* sender,
+                                      const ui::Event& event) {
+  if (delegate_)
+    delegate_->OnAssistantMiniViewPressed();
+}
+
 void AssistantMiniView::OnInputModalityChanged(InputModality input_modality) {
   switch (input_modality) {
     case InputModality::kStylus:
diff --git a/ash/assistant/ui/assistant_mini_view.h b/ash/assistant/ui/assistant_mini_view.h
index 413aad9..969c4143 100644
--- a/ash/assistant/ui/assistant_mini_view.h
+++ b/ash/assistant/ui/assistant_mini_view.h
@@ -7,7 +7,7 @@
 
 #include "ash/assistant/model/assistant_interaction_model_observer.h"
 #include "base/macros.h"
-#include "ui/views/view.h"
+#include "ui/views/controls/button/button.h"
 
 namespace views {
 class Label;
@@ -17,7 +17,21 @@
 
 class AssistantController;
 
-class AssistantMiniView : public views::View,
+// AssistantMiniViewDelegate ---------------------------------------------------
+
+class AssistantMiniViewDelegate {
+ public:
+  // Invoked when the AssistantMiniView is pressed.
+  virtual void OnAssistantMiniViewPressed() {}
+
+ protected:
+  virtual ~AssistantMiniViewDelegate() = default;
+};
+
+// AssistantMiniView -----------------------------------------------------------
+
+class AssistantMiniView : public views::Button,
+                          public views::ButtonListener,
                           public AssistantInteractionModelObserver {
  public:
   explicit AssistantMiniView(AssistantController* assistant_controller);
@@ -28,15 +42,24 @@
   int GetHeightForWidth(int width) const override;
   void ChildPreferredSizeChanged(views::View* child) override;
 
+  // views::ButtonListener:
+  void ButtonPressed(views::Button* sender, const ui::Event& event) override;
+
   // AssistantInteractionModelObserver:
   void OnInputModalityChanged(InputModality input_modality) override;
 
+  void set_delegate(AssistantMiniViewDelegate* delegate) {
+    delegate_ = delegate;
+  }
+
  private:
   void InitLayout();
 
   AssistantController* const assistant_controller_;  // Owned by Shell.
   views::Label* label_;                              // Owned by view hierarchy.
 
+  AssistantMiniViewDelegate* delegate_ = nullptr;
+
   DISALLOW_COPY_AND_ASSIGN(AssistantMiniView);
 };
 
diff --git a/ash/assistant/ui/dialog_plate/action_view.cc b/ash/assistant/ui/dialog_plate/action_view.cc
index 363f0d0..b2a2a60 100644
--- a/ash/assistant/ui/dialog_plate/action_view.cc
+++ b/ash/assistant/ui/dialog_plate/action_view.cc
@@ -26,10 +26,7 @@
 
 ActionView::ActionView(AssistantController* assistant_controller,
                        ActionViewListener* listener)
-    : assistant_controller_(assistant_controller),
-      listener_(listener),
-      keyboard_action_view_(new views::ImageView()),
-      voice_action_view_(BaseLogoView::Create()) {
+    : assistant_controller_(assistant_controller), listener_(listener) {
   InitLayout();
   UpdateState(/*animate=*/false);
 
@@ -49,17 +46,10 @@
 void ActionView::InitLayout() {
   SetLayoutManager(std::make_unique<views::FillLayout>());
 
-  gfx::Size size = gfx::Size(kPreferredSizeDip, kPreferredSizeDip);
-
-  // Keyboard action.
-  keyboard_action_view_->SetImage(
-      gfx::CreateVectorIcon(kSendIcon, kPreferredSizeDip, gfx::kGoogleBlue500));
-  keyboard_action_view_->SetImageSize(size);
-  keyboard_action_view_->SetPreferredSize(size);
-  AddChildView(keyboard_action_view_);
-
   // Voice action.
-  voice_action_view_->SetPreferredSize(size);
+  voice_action_view_ = BaseLogoView::Create();
+  voice_action_view_->SetPreferredSize(
+      gfx::Size(kPreferredSizeDip, kPreferredSizeDip));
   AddChildView(voice_action_view_);
 }
 
@@ -79,10 +69,6 @@
   return true;
 }
 
-void ActionView::OnInputModalityChanged(InputModality input_modality) {
-  UpdateState(/*animate=*/false);
-}
-
 void ActionView::OnMicStateChanged(MicState mic_state) {
   is_user_speaking_ = false;
   UpdateState(/*animate=*/true);
@@ -105,18 +91,6 @@
   const AssistantInteractionModel* interaction_model =
       assistant_controller_->interaction_controller()->model();
 
-  InputModality input_modality = interaction_model->input_modality();
-
-  // We don't need to handle stylus input modality.
-  if (input_modality == InputModality::kStylus)
-    return;
-
-  if (input_modality == InputModality::kKeyboard) {
-    voice_action_view_->SetVisible(false);
-    keyboard_action_view_->SetVisible(true);
-    return;
-  }
-
   BaseLogoView::State mic_state;
   switch (interaction_model->mic_state()) {
     case MicState::kClosed:
@@ -128,9 +102,6 @@
       break;
   }
   voice_action_view_->SetState(mic_state, animate);
-
-  keyboard_action_view_->SetVisible(false);
-  voice_action_view_->SetVisible(true);
 }
 
 }  // namespace ash
diff --git a/ash/assistant/ui/dialog_plate/action_view.h b/ash/assistant/ui/dialog_plate/action_view.h
index 72f1fac..b3b6e9c 100644
--- a/ash/assistant/ui/dialog_plate/action_view.h
+++ b/ash/assistant/ui/dialog_plate/action_view.h
@@ -9,10 +9,6 @@
 #include "base/macros.h"
 #include "ui/views/view.h"
 
-namespace views {
-class ImageView;
-}  // namespace views
-
 namespace ash {
 
 class ActionView;
@@ -44,7 +40,6 @@
   bool OnMousePressed(const ui::MouseEvent& event) override;
 
   // AssistantInteractionModelObserver:
-  void OnInputModalityChanged(InputModality input_modality) override;
   void OnMicStateChanged(MicState mic_state) override;
   void OnSpeechLevelChanged(float speech_level_db) override;
 
@@ -58,7 +53,6 @@
   AssistantController* const assistant_controller_;  // Owned by Shell.
   ActionViewListener* listener_;
 
-  views::ImageView* keyboard_action_view_;  // Owned by view hierarchy.
   BaseLogoView* voice_action_view_;         // Owned by view hierarchy.
 
   // True when speech level goes above a threshold and sets LogoView in
diff --git a/ash/assistant/ui/dialog_plate/dialog_plate.cc b/ash/assistant/ui/dialog_plate/dialog_plate.cc
index f96fc64..5e299363 100644
--- a/ash/assistant/ui/dialog_plate/dialog_plate.cc
+++ b/ash/assistant/ui/dialog_plate/dialog_plate.cc
@@ -10,11 +10,13 @@
 #include "ash/assistant/assistant_interaction_controller.h"
 #include "ash/assistant/assistant_ui_controller.h"
 #include "ash/assistant/ui/assistant_ui_constants.h"
+#include "ash/assistant/util/animation_util.h"
 #include "ash/public/cpp/vector_icons/vector_icons.h"
 #include "ash/resources/vector_icons/vector_icons.h"
 #include "ash/strings/grit/ash_strings.h"
 #include "base/strings/utf_string_conversions.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/compositor/layer_animator.h"
 #include "ui/gfx/canvas.h"
 #include "ui/gfx/color_palette.h"
 #include "ui/gfx/paint_vector_icon.h"
@@ -33,6 +35,12 @@
 constexpr int kIconSizeDip = 24;
 constexpr int kPreferredHeightDip = 48;
 
+// Animation.
+constexpr base::TimeDelta kAnimationFadeInDuration =
+    base::TimeDelta::FromMilliseconds(100);
+constexpr base::TimeDelta kAnimationFadeOutDuration =
+    base::TimeDelta::FromMilliseconds(83);
+
 // Helpers ---------------------------------------------------------------------
 
 // Creates a settings button. Caller takes ownership.
@@ -105,6 +113,8 @@
 
 void DialogPlate::InitKeyboardLayoutContainer() {
   keyboard_layout_container_ = new views::View();
+  keyboard_layout_container_->SetPaintToLayer();
+  keyboard_layout_container_->layer()->SetFillsBoundsOpaquely(false);
 
   views::BoxLayout* layout_manager =
       keyboard_layout_container_->SetLayoutManager(
@@ -155,6 +165,8 @@
 
 void DialogPlate::InitVoiceLayoutContainer() {
   voice_layout_container_ = new views::View();
+  voice_layout_container_->SetPaintToLayer();
+  voice_layout_container_->layer()->SetFillsBoundsOpaquely(false);
 
   views::BoxLayout* layout_manager = voice_layout_container_->SetLayoutManager(
       std::make_unique<views::BoxLayout>(
@@ -215,18 +227,38 @@
 void DialogPlate::OnInputModalityChanged(InputModality input_modality) {
   switch (input_modality) {
     case InputModality::kKeyboard:
-      keyboard_layout_container_->SetVisible(true);
-      voice_layout_container_->SetVisible(false);
+      // Animate voice layout container opacity to 0%.
+      voice_layout_container_->layer()->GetAnimator()->StartAnimation(
+          assistant::util::CreateLayerAnimationSequence(
+              ui::LayerAnimationElement::CreateOpacityElement(
+                  0.f, kAnimationFadeOutDuration)));
 
-      // When switching to text input modality we give focus to the textfield.
+      // Animate keyboard layout container opacity to 100% with delay.
+      keyboard_layout_container_->layer()->GetAnimator()->StartAnimation(
+          assistant::util::CreateLayerAnimationSequenceWithDelay(
+              ui::LayerAnimationElement::CreateOpacityElement(
+                  1.f, kAnimationFadeInDuration),
+              /*delay=*/kAnimationFadeOutDuration));
+
+      // When switching to keyboard input modality, we focus the textfield.
       textfield_->RequestFocus();
       break;
     case InputModality::kVoice:
-      keyboard_layout_container_->SetVisible(false);
-      voice_layout_container_->SetVisible(true);
+      // Animate keyboard layout container opacity to 0%.
+      keyboard_layout_container_->layer()->GetAnimator()->StartAnimation(
+          assistant::util::CreateLayerAnimationSequence(
+              ui::LayerAnimationElement::CreateOpacityElement(
+                  0.f, kAnimationFadeOutDuration)));
+
+      // Animate voice layout container opacity to 100% with delay;
+      voice_layout_container_->layer()->GetAnimator()->StartAnimation(
+          assistant::util::CreateLayerAnimationSequenceWithDelay(
+              ui::LayerAnimationElement::CreateOpacityElement(
+                  1.f, kAnimationFadeInDuration),
+              /*delay=*/kAnimationFadeOutDuration));
       break;
     case InputModality::kStylus:
-      // Not action necessary.
+      // No action necessary.
       break;
   }
 }
diff --git a/ash/assistant/util/animation_util.cc b/ash/assistant/util/animation_util.cc
new file mode 100644
index 0000000..9d907f6
--- /dev/null
+++ b/ash/assistant/util/animation_util.cc
@@ -0,0 +1,43 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ash/assistant/util/animation_util.h"
+
+#include "base/time/time.h"
+#include "ui/compositor/layer_animation_element.h"
+#include "ui/compositor/layer_animation_sequence.h"
+
+namespace ash {
+namespace assistant {
+namespace util {
+
+ui::LayerAnimationSequence* CreateLayerAnimationSequence(
+    std::unique_ptr<ui::LayerAnimationElement> layer_animation_element) {
+  return CreateLayerAnimationSequenceWithDelay(
+      std::move(layer_animation_element),
+      /*delay=*/base::TimeDelta());
+}
+
+ui::LayerAnimationSequence* CreateLayerAnimationSequenceWithDelay(
+    std::unique_ptr<ui::LayerAnimationElement> layer_animation_element,
+    base::TimeDelta delay) {
+  DCHECK(delay.InMilliseconds() >= 0);
+
+  ui::LayerAnimationSequence* layer_animation_sequence =
+      new ui::LayerAnimationSequence();
+
+  if (!delay.is_zero()) {
+    layer_animation_sequence->AddElement(
+        ui::LayerAnimationElement::CreatePauseElement(
+            layer_animation_element->properties(), delay));
+  }
+
+  layer_animation_sequence->AddElement(std::move(layer_animation_element));
+
+  return layer_animation_sequence;
+}
+
+}  // namespace util
+}  // namespace assistant
+}  // namespace ash
diff --git a/ash/assistant/util/animation_util.h b/ash/assistant/util/animation_util.h
new file mode 100644
index 0000000..6ee06f0
--- /dev/null
+++ b/ash/assistant/util/animation_util.h
@@ -0,0 +1,40 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ASH_ASSISTANT_UTIL_ANIMATION_UTIL_H_
+#define ASH_ASSISTANT_UTIL_ANIMATION_UTIL_H_
+
+#include <memory>
+
+namespace base {
+class TimeDelta;
+}  // namespace base
+
+namespace ui {
+class LayerAnimationElement;
+class LayerAnimationSequence;
+}  // namespace ui
+
+namespace ash {
+namespace assistant {
+namespace util {
+
+// Creates a LayerAnimationSequence containing the specified
+// |layer_animation_element|. The method caller assumes ownership of the
+// returned pointer.
+ui::LayerAnimationSequence* CreateLayerAnimationSequence(
+    std::unique_ptr<ui::LayerAnimationElement> layer_animation_element);
+
+// Creates a LayerAnimationSequence containing the specified
+// |layer_animation_element| to be started after the given |delay|. The method
+// caller assumes ownership of the returned pointer.
+ui::LayerAnimationSequence* CreateLayerAnimationSequenceWithDelay(
+    std::unique_ptr<ui::LayerAnimationElement> layer_animation_element,
+    base::TimeDelta delay);
+
+}  // namespace util
+}  // namespace assistant
+}  // namespace ash
+
+#endif  // ASH_ASSISTANT_UTIL_ANIMATION_UTIL_H_
diff --git a/ash/wayland/wayland_server_controller.cc b/ash/wayland/wayland_server_controller.cc
index cfa1596a..818558bb 100644
--- a/ash/wayland/wayland_server_controller.cc
+++ b/ash/wayland/wayland_server_controller.cc
@@ -71,7 +71,7 @@
   wm_helper_ = std::make_unique<exo::WMHelper>();
   exo::WMHelper::SetInstance(wm_helper_.get());
   display_ = std::make_unique<exo::Display>(
-      arc_notification_surface_manager_.get(), std::move(file_helper));
+      arc_notification_surface_manager_.get(), nullptr, std::move(file_helper));
   wayland_server_ = exo::wayland::Server::Create(display_.get());
   // Wayland server creation can fail if XDG_RUNTIME_DIR is not set correctly.
   if (wayland_server_)
diff --git a/base/allocator/partition_allocator/page_allocator_unittest.cc b/base/allocator/partition_allocator/page_allocator_unittest.cc
index 22c64555..fdc6a5e 100644
--- a/base/allocator/partition_allocator/page_allocator_unittest.cc
+++ b/base/allocator/partition_allocator/page_allocator_unittest.cc
@@ -11,12 +11,12 @@
 #include "build/build_config.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-#if defined(OS_POSIX) && !defined(OS_FUCHSIA)
+#if defined(OS_POSIX)
 #include <setjmp.h>
 #include <signal.h>
 #include <sys/mman.h>
 #include <sys/time.h>
-#endif  // defined(OS_POSIX) && !defined(OS_FUCHSIA)
+#endif  // defined(OS_POSIX)
 
 #if !defined(MEMORY_TOOL_REPLACES_ALLOCATOR)
 
@@ -134,7 +134,7 @@
 }
 
 // Test permission setting on POSIX, where we can set a trap handler.
-#if defined(OS_POSIX) && !defined(OS_FUCHSIA)
+#if defined(OS_POSIX)
 
 namespace {
 sigjmp_buf g_continuation;
@@ -217,7 +217,7 @@
   FreePages(buffer, kPageAllocationGranularity);
 }
 
-#endif  // defined(OS_POSIX) && !defined(OS_FUCHSIA)
+#endif  // defined(OS_POSIX)
 
 }  // namespace base
 
diff --git a/base/allocator/partition_allocator/partition_alloc_unittest.cc b/base/allocator/partition_allocator/partition_alloc_unittest.cc
index da06514..afff0906b 100644
--- a/base/allocator/partition_allocator/partition_alloc_unittest.cc
+++ b/base/allocator/partition_allocator/partition_alloc_unittest.cc
@@ -48,7 +48,7 @@
 #if !defined(ARCH_CPU_64_BITS) || !defined(OS_POSIX)
   // 32 bits => address space is limited already.
   return true;
-#elif defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_FUCHSIA)
+#elif defined(OS_POSIX) && !defined(OS_MACOSX)
   // macOS will accept, but not enforce, |RLIMIT_AS| changes. See
   // https://crbug.com/435269 and rdar://17576114.
   //
diff --git a/base/debug/stack_trace_unittest.cc b/base/debug/stack_trace_unittest.cc
index 959cd53..02f076a 100644
--- a/base/debug/stack_trace_unittest.cc
+++ b/base/debug/stack_trace_unittest.cc
@@ -153,7 +153,7 @@
 }
 #endif  // !defined(__UCLIBC__)
 
-#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_FUCHSIA)
+#if defined(OS_POSIX) && !defined(OS_ANDROID)
 #if !defined(OS_IOS)
 static char* newArray() {
   // Clang warns about the mismatched new[]/delete if they occur in the same
@@ -253,7 +253,7 @@
   EXPECT_EQ("0688", itoa_r_wrapper(0x688, 128, 16, 4));
   EXPECT_EQ("00688", itoa_r_wrapper(0x688, 128, 16, 5));
 }
-#endif  // defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_FUCHSIA)
+#endif  // defined(OS_POSIX) && !defined(OS_ANDROID)
 
 #if BUILDFLAG(CAN_UNWIND_WITH_FRAME_POINTERS)
 
diff --git a/base/files/file_path_watcher_unittest.cc b/base/files/file_path_watcher_unittest.cc
index bc5d9025..2530b27 100644
--- a/base/files/file_path_watcher_unittest.cc
+++ b/base/files/file_path_watcher_unittest.cc
@@ -543,7 +543,7 @@
   ASSERT_TRUE(WaitForEvents());
 }
 
-#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_FUCHSIA)
+#if defined(OS_POSIX) && !defined(OS_ANDROID)
 // Apps cannot create symlinks on Android in /sdcard as /sdcard uses the
 // "fuse" file system, while /data uses "ext4".  Running these tests in /data
 // would be preferable and allow testing file attributes and symlinks.
@@ -588,7 +588,7 @@
   ASSERT_TRUE(WriteFile(target2_file, "content"));
   ASSERT_TRUE(WaitForEvents());
 }
-#endif  // defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_FUCHSIA)
+#endif  // defined(OS_POSIX) && !defined(OS_ANDROID)
 
 TEST_F(FilePathWatcherTest, MoveChild) {
   FilePathWatcher file_watcher;
diff --git a/base/files/file_util_unittest.cc b/base/files/file_util_unittest.cc
index 05a3896..68abc7c 100644
--- a/base/files/file_util_unittest.cc
+++ b/base/files/file_util_unittest.cc
@@ -3179,7 +3179,7 @@
 }
 #endif  // defined(OS_WIN)
 
-#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_FUCHSIA)
+#if defined(OS_POSIX) && !defined(OS_MACOSX)
 TEST_F(FileUtilTest, ReadFileToStringWithProcFileSystem) {
   FilePath file_path("/proc/cpuinfo");
   std::string data = "temp";
@@ -3197,7 +3197,7 @@
 
   EXPECT_FALSE(ReadFileToStringWithMaxSize(file_path, nullptr, 4));
 }
-#endif  // defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_FUCHSIA)
+#endif  // defined(OS_POSIX) && !defined(OS_MACOSX)
 
 TEST_F(FileUtilTest, ReadFileToStringWithLargeFile) {
   std::string data(kLargeFileSize, 'c');
diff --git a/base/memory/platform_shared_memory_region_unittest.cc b/base/memory/platform_shared_memory_region_unittest.cc
index d4e9647..5a83ee9 100644
--- a/base/memory/platform_shared_memory_region_unittest.cc
+++ b/base/memory/platform_shared_memory_region_unittest.cc
@@ -175,8 +175,7 @@
   EXPECT_FALSE(mapping.IsValid());
 }
 
-#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_FUCHSIA) && \
-    !defined(OS_MACOSX)
+#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_MACOSX)
 // Tests that the second handle is closed after a conversion to read-only on
 // POSIX.
 TEST_F(PlatformSharedMemoryRegionTest,
diff --git a/base/path_service_unittest.cc b/base/path_service_unittest.cc
index 8fcd673..cf69ef1 100644
--- a/base/path_service_unittest.cc
+++ b/base/path_service_unittest.cc
@@ -30,7 +30,7 @@
   // Some paths might not exist on some platforms in which case confirming
   // |result| is true and !path.empty() is the best we can do.
   bool check_path_exists = true;
-#if defined(OS_POSIX) && !defined(OS_FUCHSIA)
+#if defined(OS_POSIX)
   // If chromium has never been started on this account, the cache path may not
   // exist.
   if (dir_type == DIR_CACHE)
@@ -117,7 +117,7 @@
        ++key) {
     EXPECT_PRED1(ReturnsValidPath, key);
   }
-#elif defined(OS_POSIX) && !defined(OS_FUCHSIA)
+#elif defined(OS_POSIX)
   for (int key = PATH_POSIX_START + 1; key < PATH_POSIX_END;
        ++key) {
     EXPECT_PRED1(ReturnsValidPath, key);
diff --git a/base/posix/eintr_wrapper.h b/base/posix/eintr_wrapper.h
index c0ffced5..0e6e437 100644
--- a/base/posix/eintr_wrapper.h
+++ b/base/posix/eintr_wrapper.h
@@ -19,7 +19,7 @@
 
 #include "build/build_config.h"
 
-#if defined(OS_POSIX) && !defined(OS_FUCHSIA)
+#if defined(OS_POSIX)
 
 #include <errno.h>
 
@@ -58,11 +58,11 @@
   eintr_wrapper_result; \
 })
 
-#else  // !OS_POSIX || OS_FUCHSIA
+#else  // !OS_POSIX
 
 #define HANDLE_EINTR(x) (x)
 #define IGNORE_EINTR(x) (x)
 
-#endif  // !OS_POSIX || OS_FUCHSIA
+#endif  // !OS_POSIX
 
 #endif  // BASE_POSIX_EINTR_WRAPPER_H_
diff --git a/base/process/kill.h b/base/process/kill.h
index 005b72e2..9acfb8a 100644
--- a/base/process/kill.h
+++ b/base/process/kill.h
@@ -92,7 +92,7 @@
 BASE_EXPORT TerminationStatus GetTerminationStatus(ProcessHandle handle,
                                                    int* exit_code);
 
-#if defined(OS_POSIX) && !defined(OS_FUCHSIA)
+#if defined(OS_POSIX)
 // Send a kill signal to the process and then wait for the process to exit
 // and get the termination status.
 //
@@ -116,7 +116,7 @@
 // and then reaps it.
 BASE_EXPORT void EnsureProcessGetsReaped(Process process);
 #endif  // defined(OS_LINUX)
-#endif  // defined(OS_POSIX) && !defined(OS_FUCHSIA)
+#endif  // defined(OS_POSIX)
 
 // Registers |process| to be asynchronously monitored for termination, forcibly
 // terminated if necessary, and reaped on exit. The caller should have signalled
diff --git a/base/process/process_metrics.h b/base/process/process_metrics.h
index 0170a0c..6bfd93e 100644
--- a/base/process/process_metrics.h
+++ b/base/process/process_metrics.h
@@ -267,12 +267,12 @@
 // at once. If the number is unavailable, a conservative best guess is returned.
 BASE_EXPORT size_t GetMaxFds();
 
-#if defined(OS_POSIX) && !defined(OS_FUCHSIA)
+#if defined(OS_POSIX)
 // Increases the file descriptor soft limit to |max_descriptors| or the OS hard
 // limit, whichever is lower. If the limit is already higher than
 // |max_descriptors|, then nothing happens.
 BASE_EXPORT void IncreaseFdLimitTo(unsigned int max_descriptors);
-#endif  // defined(OS_POSIX) && !defined(OS_FUCHSIA)
+#endif  // defined(OS_POSIX)
 
 #if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) || \
     defined(OS_ANDROID) || defined(OS_AIX) || defined(OS_FUCHSIA)
diff --git a/base/process/process_unittest.cc b/base/process/process_unittest.cc
index 9f678d1..219944d 100644
--- a/base/process/process_unittest.cc
+++ b/base/process/process_unittest.cc
@@ -147,7 +147,7 @@
   EXPECT_NE(TERMINATION_STATUS_STILL_RUNNING,
             GetTerminationStatus(process.Handle(), &exit_code));
 #if !defined(OS_POSIX) && !defined(OS_FUCHSIA)
-  // The POSIX implementation actually ignores the exit_code.
+  // The POSIX & Fuchsia implementations actually ignore the exit_code.
   EXPECT_EQ(kExpectedExitCode, exit_code);
 #endif
 }
diff --git a/base/rand_util.h b/base/rand_util.h
index 03bf46f..45e42832 100644
--- a/base/rand_util.h
+++ b/base/rand_util.h
@@ -69,7 +69,7 @@
   std::shuffle(first, last, RandomBitGenerator());
 }
 
-#if defined(OS_POSIX) && !defined(OS_FUCHSIA)
+#if defined(OS_POSIX)
 BASE_EXPORT int GetUrandomFD();
 #endif
 
diff --git a/base/synchronization/condition_variable_unittest.cc b/base/synchronization/condition_variable_unittest.cc
index 287defa..d66aecc4 100644
--- a/base/synchronization/condition_variable_unittest.cc
+++ b/base/synchronization/condition_variable_unittest.cc
@@ -194,7 +194,7 @@
   lock.Release();
 }
 
-#if defined(OS_POSIX) && !defined(OS_FUCHSIA)
+#if defined(OS_POSIX)
 const int kDiscontinuitySeconds = 2;
 
 void BackInTime(Lock* lock) {
diff --git a/base/test/test_shared_memory_util.cc b/base/test/test_shared_memory_util.cc
index cfc96a9..a923fd3 100644
--- a/base/test/test_shared_memory_util.cc
+++ b/base/test/test_shared_memory_util.cc
@@ -42,7 +42,7 @@
 // Common routine used with Posix file descriptors. Check that shared memory
 // file descriptor |fd| does not allow writable mappings. Return true on
 // success, false otherwise.
-#if defined(OS_POSIX) && !defined(OS_FUCHSIA)
+#if defined(OS_POSIX)
 static bool CheckReadOnlySharedMemoryFdPosix(int fd) {
 // Note that the error on Android is EPERM, unlike other platforms where
 // it will be EACCES.
diff --git a/build/config/BUILD.gn b/build/config/BUILD.gn
index 1ba2373..997cdc8 100644
--- a/build/config/BUILD.gn
+++ b/build/config/BUILD.gn
@@ -276,15 +276,18 @@
   }
 }
 
-# Dependencies that all executables and shared libraries should have.
-group("exe_and_shlib_deps") {
+# Only //build/config/BUILDCONFIG.gn should reference this.
+group("executable_and_loadable_module_and_shared_library_deps") {
   public_deps = []
+
   if (using_sanitizer) {
     public_deps += [ "//build/config/sanitizers:deps" ]
   }
+
   if (use_custom_libcxx) {
     public_deps += [ "//buildtools/third_party/libc++" ]
   }
+
   if (use_afl) {
     public_deps += [ "//third_party/afl" ]
   }
diff --git a/build/config/BUILDCONFIG.gn b/build/config/BUILDCONFIG.gn
index 2545815..fcc00ee0 100644
--- a/build/config/BUILDCONFIG.gn
+++ b/build/config/BUILDCONFIG.gn
@@ -664,7 +664,7 @@
         deps = []
       }
       if (!defined(invoker.no_default_deps) || !invoker.no_default_deps) {
-        deps += [ "//build/config:exe_and_shlib_deps" ]
+        deps += [ "//build/config:executable_and_loadable_module_and_shared_library_deps" ]
       }
     }
   }
diff --git a/cc/layers/heads_up_display_layer_impl.cc b/cc/layers/heads_up_display_layer_impl.cc
index c45a685..cd16765 100644
--- a/cc/layers/heads_up_display_layer_impl.cc
+++ b/cc/layers/heads_up_display_layer_impl.cc
@@ -137,10 +137,8 @@
 bool HeadsUpDisplayLayerImpl::WillDraw(
     DrawMode draw_mode,
     viz::ClientResourceProvider* resource_provider) {
-  if (draw_mode == DRAW_MODE_RESOURCELESS_SOFTWARE &&
-      !LayerImpl::WillDraw(draw_mode, resource_provider)) {
+  if (draw_mode == DRAW_MODE_RESOURCELESS_SOFTWARE)
     return false;
-  }
 
   int max_texture_size = layer_tree_impl()->max_texture_size();
   internal_contents_scale_ = GetIdealContentsScale();
@@ -149,7 +147,7 @@
   internal_content_bounds_.SetToMin(
       gfx::Size(max_texture_size, max_texture_size));
 
-  return true;
+  return LayerImpl::WillDraw(draw_mode, resource_provider);
 }
 
 void HeadsUpDisplayLayerImpl::AppendQuads(viz::RenderPass* render_pass,
diff --git a/cc/layers/heads_up_display_layer_impl_unittest.cc b/cc/layers/heads_up_display_layer_impl_unittest.cc
index f5dc43ee..1ffb91f9 100644
--- a/cc/layers/heads_up_display_layer_impl_unittest.cc
+++ b/cc/layers/heads_up_display_layer_impl_unittest.cc
@@ -51,7 +51,6 @@
   std::unique_ptr<HeadsUpDisplayLayerImpl> layer_ptr =
       HeadsUpDisplayLayerImpl::Create(host_impl.pending_tree(), 1);
   layer_ptr->SetBounds(gfx::Size(100, 100));
-  layer_ptr->set_visible_layer_rect(gfx::Rect(100, 100));
 
   HeadsUpDisplayLayerImpl* layer = layer_ptr.get();
 
@@ -85,7 +84,6 @@
   std::unique_ptr<HeadsUpDisplayLayerImpl> layer_ptr =
       HeadsUpDisplayLayerImpl::Create(host_impl.pending_tree(), 1);
   layer_ptr->SetBounds(gfx::Size(100, 100));
-  layer_ptr->set_visible_layer_rect(gfx::Rect(100, 100));
 
   HeadsUpDisplayLayerImpl* layer = layer_ptr.get();
 
diff --git a/cc/layers/layer_impl.cc b/cc/layers/layer_impl.cc
index f0ae0f4b..389e630 100644
--- a/cc/layers/layer_impl.cc
+++ b/cc/layers/layer_impl.cc
@@ -71,6 +71,7 @@
       effect_tree_index_(EffectTree::kInvalidNodeId),
       clip_tree_index_(ClipTree::kInvalidNodeId),
       scroll_tree_index_(ScrollTree::kInvalidNodeId),
+      current_draw_mode_(DRAW_MODE_NONE),
       debug_info_(nullptr),
       has_will_change_transform_hint_(false),
       needs_push_properties_(false),
@@ -88,6 +89,7 @@
 }
 
 LayerImpl::~LayerImpl() {
+  DCHECK_EQ(DRAW_MODE_NONE, current_draw_mode_);
   layer_tree_impl_->UnregisterLayer(this);
   layer_tree_impl_->RemoveFromElementLayerList(element_id_);
   TRACE_EVENT_OBJECT_DELETED_WITH_ID(
@@ -165,17 +167,17 @@
 
 bool LayerImpl::WillDraw(DrawMode draw_mode,
                          viz::ClientResourceProvider* resource_provider) {
-  if (visible_layer_rect().IsEmpty() ||
-      draw_properties().occlusion_in_content_space.IsOccluded(
-          visible_layer_rect())) {
-    return false;
-  }
-
+  // WillDraw/DidDraw must be matched.
+  DCHECK_NE(DRAW_MODE_NONE, draw_mode);
+  DCHECK_EQ(DRAW_MODE_NONE, current_draw_mode_);
   current_draw_mode_ = draw_mode;
   return true;
 }
 
-void LayerImpl::DidDraw(viz::ClientResourceProvider* resource_provider) {}
+void LayerImpl::DidDraw(viz::ClientResourceProvider* resource_provider) {
+  DCHECK_NE(DRAW_MODE_NONE, current_draw_mode_);
+  current_draw_mode_ = DRAW_MODE_NONE;
+}
 
 bool LayerImpl::ShowDebugBorders(DebugBorderType type) const {
   return layer_tree_impl()->debug_state().show_debug_borders.test(type);
diff --git a/cc/layers/layer_impl.h b/cc/layers/layer_impl.h
index dcbd0fb..9555515 100644
--- a/cc/layers/layer_impl.h
+++ b/cc/layers/layer_impl.h
@@ -133,7 +133,9 @@
   // WillDraw must be called before AppendQuads. If WillDraw returns false,
   // AppendQuads and DidDraw will not be called. If WillDraw returns true,
   // DidDraw is guaranteed to be called before another WillDraw or before
-  // the layer is destroyed.
+  // the layer is destroyed. To enforce this, any class that overrides
+  // WillDraw/DidDraw must call the base class version only if WillDraw
+  // returns true.
   virtual bool WillDraw(DrawMode draw_mode,
                         viz::ClientResourceProvider* resource_provider);
   virtual void AppendQuads(viz::RenderPass* render_pass,
diff --git a/cc/layers/surface_layer.cc b/cc/layers/surface_layer.cc
index 3f457b5..5b099a3 100644
--- a/cc/layers/surface_layer.cc
+++ b/cc/layers/surface_layer.cc
@@ -17,19 +17,8 @@
   return base::WrapRefCounted(new SurfaceLayer());
 }
 
-scoped_refptr<SurfaceLayer> SurfaceLayer::Create(
-    UpdateSubmissionStateCB update_submission_state_callback) {
-  return base::WrapRefCounted(
-      new SurfaceLayer(std::move(update_submission_state_callback)));
-}
-
 SurfaceLayer::SurfaceLayer() = default;
 
-SurfaceLayer::SurfaceLayer(
-    UpdateSubmissionStateCB update_submission_state_callback)
-    : update_submission_state_callback_(
-          std::move(update_submission_state_callback)) {}
-
 SurfaceLayer::~SurfaceLayer() {
   DCHECK(!layer_tree_host());
 }
@@ -108,16 +97,9 @@
   SetNeedsPushProperties();
 }
 
-void SurfaceLayer::SetMayContainVideo(bool may_contain_video) {
-  may_contain_video_ = may_contain_video;
-}
-
 std::unique_ptr<LayerImpl> SurfaceLayer::CreateLayerImpl(
     LayerTreeImpl* tree_impl) {
-  auto layer_impl = SurfaceLayerImpl::Create(tree_impl, id(),
-                                             update_submission_state_callback_);
-  layer_impl->set_may_contain_video(may_contain_video_);
-  return layer_impl;
+  return SurfaceLayerImpl::Create(tree_impl, id());
 }
 
 bool SurfaceLayer::HasDrawableContent() const {
diff --git a/cc/layers/surface_layer.h b/cc/layers/surface_layer.h
index cee2367..fcc684c 100644
--- a/cc/layers/surface_layer.h
+++ b/cc/layers/surface_layer.h
@@ -16,16 +16,11 @@
 
 namespace cc {
 
-// If given true, we should submit frames, as we are unoccluded on screen.
-// If given false, we should not submit compositor frames.
-using UpdateSubmissionStateCB = base::RepeatingCallback<void(bool)>;
-
 // A layer that renders a surface referencing the output of another compositor
 // instance or client.
 class CC_EXPORT SurfaceLayer : public Layer {
  public:
   static scoped_refptr<SurfaceLayer> Create();
-  static scoped_refptr<SurfaceLayer> Create(UpdateSubmissionStateCB);
 
   void SetPrimarySurfaceId(const viz::SurfaceId& surface_id,
                            const DeadlinePolicy& deadline_policy);
@@ -41,8 +36,6 @@
   void SetSurfaceHitTestable(bool surface_hit_testable);
   bool surface_hit_testable() const { return surface_hit_testable_; }
 
-  void SetMayContainVideo(bool);
-
   // Layer overrides.
   std::unique_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl) override;
   void SetLayerTreeHost(LayerTreeHost* host) override;
@@ -62,7 +55,6 @@
 
  protected:
   SurfaceLayer();
-  explicit SurfaceLayer(UpdateSubmissionStateCB);
   bool HasDrawableContent() const override;
 
  private:
@@ -71,9 +63,6 @@
   // Returns a SurfaceRange corresponding to the surface layer.
   viz::SurfaceRange GetSurfaceRange() const;
 
-  UpdateSubmissionStateCB update_submission_state_callback_;
-
-  bool may_contain_video_ = false;
   viz::SurfaceId primary_surface_id_;
   viz::SurfaceId fallback_surface_id_;
   base::Optional<uint32_t> deadline_in_frames_ = 0u;
diff --git a/cc/layers/surface_layer_impl.cc b/cc/layers/surface_layer_impl.cc
index 3577afa..8e383af 100644
--- a/cc/layers/surface_layer_impl.cc
+++ b/cc/layers/surface_layer_impl.cc
@@ -16,20 +16,14 @@
 
 namespace cc {
 
-SurfaceLayerImpl::SurfaceLayerImpl(
-    LayerTreeImpl* tree_impl,
-    int id,
-    UpdateSubmissionStateCB update_submission_state_callback)
-    : LayerImpl(tree_impl, id),
-      update_submission_state_callback_(
-          std::move(update_submission_state_callback)) {}
+SurfaceLayerImpl::SurfaceLayerImpl(LayerTreeImpl* tree_impl, int id)
+    : LayerImpl(tree_impl, id) {}
 
 SurfaceLayerImpl::~SurfaceLayerImpl() = default;
 
 std::unique_ptr<LayerImpl> SurfaceLayerImpl::CreateLayerImpl(
     LayerTreeImpl* tree_impl) {
-  return SurfaceLayerImpl::Create(tree_impl, id(),
-                                  std::move(update_submission_state_callback_));
+  return SurfaceLayerImpl::Create(tree_impl, id());
 }
 
 void SurfaceLayerImpl::SetPrimarySurfaceId(
@@ -95,22 +89,6 @@
   layer_impl->SetSurfaceHitTestable(surface_hit_testable_);
 }
 
-bool SurfaceLayerImpl::WillDraw(
-    DrawMode draw_mode,
-    viz::ClientResourceProvider* resource_provider) {
-  bool will_draw = LayerImpl::WillDraw(draw_mode, resource_provider);
-  // If we have a change in WillDraw (meaning that visibility has changed), we
-  // want to inform the VideoFrameSubmitter to start or stop submitting
-  // compositor frames.
-  if (will_draw_ != will_draw) {
-    will_draw_ = will_draw;
-    if (update_submission_state_callback_)
-      update_submission_state_callback_.Run(will_draw);
-  }
-
-  return primary_surface_id_.is_valid() && will_draw;
-}
-
 void SurfaceLayerImpl::AppendQuads(viz::RenderPass* render_pass,
                                    AppendQuadsData* append_quads_data) {
   AppendRainbowDebugBorder(render_pass);
diff --git a/cc/layers/surface_layer_impl.h b/cc/layers/surface_layer_impl.h
index cd433f7..ce24320 100644
--- a/cc/layers/surface_layer_impl.h
+++ b/cc/layers/surface_layer_impl.h
@@ -7,7 +7,6 @@
 
 #include <memory>
 
-#include "base/bind.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "cc/cc_export.h"
@@ -18,25 +17,12 @@
 
 namespace cc {
 
-// This must match SurfaceLayer::UpdateSubmissionStateCB.
-using UpdateSubmissionStateCB = base::RepeatingCallback<void(bool)>;
-
 class CC_EXPORT SurfaceLayerImpl : public LayerImpl {
  public:
-  static std::unique_ptr<SurfaceLayerImpl> Create(
-      LayerTreeImpl* tree_impl,
-      int id,
-      UpdateSubmissionStateCB update_submission_state_callback) {
-    return base::WrapUnique(new SurfaceLayerImpl(
-        tree_impl, id, std::move(update_submission_state_callback)));
-  }
-
   static std::unique_ptr<SurfaceLayerImpl> Create(LayerTreeImpl* tree_impl,
                                                   int id) {
-    return base::WrapUnique(
-        new SurfaceLayerImpl(tree_impl, id, base::BindRepeating([](bool) {})));
+    return base::WrapUnique(new SurfaceLayerImpl(tree_impl, id));
   }
-
   ~SurfaceLayerImpl() override;
 
   void SetPrimarySurfaceId(const viz::SurfaceId& surface_id,
@@ -70,14 +56,12 @@
   // LayerImpl overrides.
   std::unique_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl) override;
   void PushPropertiesTo(LayerImpl* layer) override;
-  bool WillDraw(DrawMode draw_mode,
-                viz::ClientResourceProvider* resource_provider) override;
   void AppendQuads(viz::RenderPass* render_pass,
                    AppendQuadsData* append_quads_data) override;
   bool is_surface_layer() const override;
 
  protected:
-  SurfaceLayerImpl(LayerTreeImpl* tree_impl, int id, UpdateSubmissionStateCB);
+  SurfaceLayerImpl(LayerTreeImpl* tree_impl, int id);
 
  private:
   viz::SurfaceDrawQuad* CreateSurfaceDrawQuad(
@@ -90,14 +74,12 @@
   void AsValueInto(base::trace_event::TracedValue* dict) const override;
   const char* LayerTypeAsString() const override;
 
-  UpdateSubmissionStateCB update_submission_state_callback_;
   viz::SurfaceId primary_surface_id_;
   viz::SurfaceId fallback_surface_id_;
   base::Optional<uint32_t> deadline_in_frames_;
 
   bool stretch_content_to_fill_bounds_ = false;
   bool surface_hit_testable_ = false;
-  bool will_draw_ = false;
 
   DISALLOW_COPY_AND_ASSIGN(SurfaceLayerImpl);
 };
diff --git a/cc/layers/surface_layer_impl_unittest.cc b/cc/layers/surface_layer_impl_unittest.cc
index 36a57d2..d8a5f6b 100644
--- a/cc/layers/surface_layer_impl_unittest.cc
+++ b/cc/layers/surface_layer_impl_unittest.cc
@@ -44,7 +44,6 @@
     LayerTestCommon::VerifyQuadsExactlyCoverRect(impl.quad_list(),
                                                  gfx::Rect(layer_size));
     EXPECT_EQ(1u, impl.quad_list().size());
-    EXPECT_TRUE(surface_layer_impl->WillDraw(DRAW_MODE_HARDWARE, nullptr));
   }
 
   {
@@ -54,7 +53,6 @@
 
     LayerTestCommon::VerifyQuadsExactlyCoverRect(impl.quad_list(), gfx::Rect());
     EXPECT_EQ(impl.quad_list().size(), 0u);
-    EXPECT_FALSE(surface_layer_impl->WillDraw(DRAW_MODE_HARDWARE, nullptr));
   }
 
   {
@@ -68,7 +66,6 @@
     // The layer outputs one quad, which is partially occluded.
     EXPECT_EQ(1u, impl.quad_list().size());
     EXPECT_EQ(1u, partially_occluded_count);
-    EXPECT_TRUE(surface_layer_impl->WillDraw(DRAW_MODE_HARDWARE, nullptr));
   }
 }
 
diff --git a/cc/layers/texture_layer_impl.cc b/cc/layers/texture_layer_impl.cc
index 137534d..9bf803b 100644
--- a/cc/layers/texture_layer_impl.cc
+++ b/cc/layers/texture_layer_impl.cc
@@ -88,9 +88,6 @@
     return false;
   }
 
-  if (!LayerImpl::WillDraw(draw_mode, resource_provider))
-    return false;
-
   if (own_resource_) {
     DCHECK(!resource_id_);
     if (!transferable_resource_.mailbox_holder.mailbox.IsZero()) {
@@ -101,7 +98,7 @@
     own_resource_ = false;
   }
 
-  return resource_id_;
+  return resource_id_ && LayerImpl::WillDraw(draw_mode, resource_provider);
 }
 
 void TextureLayerImpl::AppendQuads(viz::RenderPass* render_pass,
diff --git a/cc/layers/texture_layer_unittest.cc b/cc/layers/texture_layer_unittest.cc
index 18c72de3..4624e15 100644
--- a/cc/layers/texture_layer_unittest.cc
+++ b/cc/layers/texture_layer_unittest.cc
@@ -850,12 +850,6 @@
     EXPECT_TRUE(host_impl_.InitializeFrameSink(layer_tree_frame_sink_.get()));
   }
 
-  std::unique_ptr<TextureLayerImpl> CreateTextureLayer() {
-    auto layer = TextureLayerImpl::Create(host_impl_.active_tree(), 1);
-    layer->set_visible_layer_rect(gfx::Rect(100, 100));
-    return layer;
-  }
-
   bool WillDraw(TextureLayerImpl* layer, DrawMode mode) {
     bool will_draw = layer->WillDraw(
         mode, host_impl_.active_tree()->resource_provider());
@@ -879,7 +873,8 @@
       .Times(AnyNumber());
   // Hardware mode.
   {
-    std::unique_ptr<TextureLayerImpl> impl_layer = CreateTextureLayer();
+    std::unique_ptr<TextureLayerImpl> impl_layer =
+        TextureLayerImpl::Create(host_impl_.active_tree(), 1);
     impl_layer->SetTransferableResource(
         test_data_.resource1_,
         viz::SingleReleaseCallback::Create(test_data_.release_callback1_));
@@ -895,7 +890,8 @@
 
   // Software mode.
   {
-    std::unique_ptr<TextureLayerImpl> impl_layer = CreateTextureLayer();
+    std::unique_ptr<TextureLayerImpl> impl_layer =
+        TextureLayerImpl::Create(host_impl_.active_tree(), 1);
     impl_layer->SetTransferableResource(
         test_data_.resource1_,
         viz::SingleReleaseCallback::Create(test_data_.release_callback1_));
@@ -903,14 +899,16 @@
   }
 
   {
-    std::unique_ptr<TextureLayerImpl> impl_layer = CreateTextureLayer();
+    std::unique_ptr<TextureLayerImpl> impl_layer =
+        TextureLayerImpl::Create(host_impl_.active_tree(), 1);
     impl_layer->SetTransferableResource(viz::TransferableResource(), nullptr);
     EXPECT_FALSE(WillDraw(impl_layer.get(), DRAW_MODE_SOFTWARE));
   }
 
   {
     // Software resource.
-    std::unique_ptr<TextureLayerImpl> impl_layer = CreateTextureLayer();
+    std::unique_ptr<TextureLayerImpl> impl_layer =
+        TextureLayerImpl::Create(host_impl_.active_tree(), 1);
     impl_layer->SetTransferableResource(
         test_data_.sw_resource_,
         viz::SingleReleaseCallback::Create(test_data_.sw_release_callback_));
@@ -919,7 +917,8 @@
 
   // Resourceless software mode.
   {
-    std::unique_ptr<TextureLayerImpl> impl_layer = CreateTextureLayer();
+    std::unique_ptr<TextureLayerImpl> impl_layer =
+        TextureLayerImpl::Create(host_impl_.active_tree(), 1);
     impl_layer->SetTransferableResource(
         test_data_.resource1_,
         viz::SingleReleaseCallback::Create(test_data_.release_callback1_));
@@ -991,7 +990,8 @@
 
 TEST_F(TextureLayerImplWithResourceTest,
        TestDestructorCallbackOnCreatedResource) {
-  std::unique_ptr<TextureLayerImpl> impl_layer = CreateTextureLayer();
+  std::unique_ptr<TextureLayerImpl> impl_layer;
+  impl_layer = TextureLayerImpl::Create(host_impl_.active_tree(), 1);
   ASSERT_TRUE(impl_layer);
 
   EXPECT_CALL(test_data_.mock_callback_,
diff --git a/cc/layers/video_layer_impl.cc b/cc/layers/video_layer_impl.cc
index d4a18b06..3e41407 100644
--- a/cc/layers/video_layer_impl.cc
+++ b/cc/layers/video_layer_impl.cc
@@ -82,9 +82,6 @@
   if (draw_mode == DRAW_MODE_RESOURCELESS_SOFTWARE)
     return false;
 
-  if (!LayerImpl::WillDraw(draw_mode, resource_provider))
-    return false;
-
   // Explicitly acquire and release the provider mutex so it can be held from
   // WillDraw to DidDraw. Since the compositor thread is in the middle of
   // drawing, the layer will not be destroyed before DidDraw is called.
@@ -102,6 +99,9 @@
     return false;
   }
 
+  if (!LayerImpl::WillDraw(draw_mode, resource_provider))
+    return false;
+
   if (!updater_) {
     const LayerTreeSettings& settings = layer_tree_impl()->settings();
     updater_ = std::make_unique<media::VideoResourceUpdater>(
diff --git a/cc/layers/video_layer_impl_unittest.cc b/cc/layers/video_layer_impl_unittest.cc
index 56d9170..fc67628 100644
--- a/cc/layers/video_layer_impl_unittest.cc
+++ b/cc/layers/video_layer_impl_unittest.cc
@@ -50,7 +50,6 @@
       impl.AddChildToRoot<VideoLayerImpl>(&provider, media::VIDEO_ROTATION_0);
   video_layer_impl->SetBounds(layer_size);
   video_layer_impl->SetDrawsContent(true);
-  video_layer_impl->set_visible_layer_rect(gfx::Rect(layer_size));
 
   impl.CalcDrawProps(viewport_size);
 
@@ -314,7 +313,6 @@
       impl.AddChildToRoot<VideoLayerImpl>(&provider, media::VIDEO_ROTATION_0);
   video_layer_impl->SetBounds(layer_size);
   video_layer_impl->SetDrawsContent(true);
-  video_layer_impl->set_visible_layer_rect(gfx::Rect(layer_size));
   impl.host_impl()->active_tree()->BuildLayerListAndPropertyTreesForTesting();
 
   gfx::Rect occluded;
@@ -352,7 +350,6 @@
       impl.AddChildToRoot<VideoLayerImpl>(&provider, media::VIDEO_ROTATION_0);
   video_layer_impl->SetBounds(layer_size);
   video_layer_impl->SetDrawsContent(true);
-  video_layer_impl->set_visible_layer_rect(gfx::Rect(layer_size));
   impl.host_impl()->active_tree()->BuildLayerListAndPropertyTreesForTesting();
 
   gfx::Rect occluded;
@@ -396,7 +393,6 @@
       impl.AddChildToRoot<VideoLayerImpl>(&provider, media::VIDEO_ROTATION_0);
   video_layer_impl->SetBounds(layer_size);
   video_layer_impl->SetDrawsContent(true);
-  video_layer_impl->set_visible_layer_rect(gfx::Rect(layer_size));
   impl.host_impl()->active_tree()->BuildLayerListAndPropertyTreesForTesting();
 
   gfx::Rect occluded;
@@ -440,7 +436,6 @@
       impl.AddChildToRoot<VideoLayerImpl>(&provider, media::VIDEO_ROTATION_0);
   video_layer_impl->SetBounds(layer_size);
   video_layer_impl->SetDrawsContent(true);
-  video_layer_impl->set_visible_layer_rect(gfx::Rect(layer_size));
   impl.host_impl()->active_tree()->BuildLayerListAndPropertyTreesForTesting();
 
   gfx::Rect occluded;
diff --git a/cc/paint/image_transfer_cache_entry.cc b/cc/paint/image_transfer_cache_entry.cc
index 448ca06..fe63071a 100644
--- a/cc/paint/image_transfer_cache_entry.cc
+++ b/cc/paint/image_transfer_cache_entry.cc
@@ -36,8 +36,7 @@
     // TODO(ericrk): consider adding in the DeleteSkImageAndPreventCaching
     // optimization from GpuImageDecodeCache where we forcefully remove the
     // intermediate from Skia's cache.
-    uploaded_image = uploaded_image->makeColorSpace(
-        target_color_space, SkTransferFunctionBehavior::kIgnore);
+    uploaded_image = uploaded_image->makeColorSpace(target_color_space);
   }
 
   // Step 3: If we had a colorspace conversion, we couldn't mipmap in step 1, so
@@ -203,8 +202,7 @@
     if (!original)
       return false;
     if (target_color_space) {
-      image_ = original->makeColorSpace(target_color_space,
-                                        SkTransferFunctionBehavior::kIgnore);
+      image_ = original->makeColorSpace(target_color_space);
       // If color space conversion is a noop, use original data.
       if (image_ == original)
         image_ = SkImage::MakeRasterCopy(pixmap);
diff --git a/cc/paint/paint_image.cc b/cc/paint/paint_image.cc
index f82fcdf..34bb675 100644
--- a/cc/paint/paint_image.cc
+++ b/cc/paint/paint_image.cc
@@ -228,8 +228,7 @@
   auto image = GetSkImageForFrame(frame_index);
   DCHECK(image);
   if (color_space) {
-    image =
-        image->makeColorSpace(color_space, SkTransferFunctionBehavior::kIgnore);
+    image = image->makeColorSpace(color_space);
     if (!image)
       return false;
   }
diff --git a/cc/scheduler/scheduler_unittest.cc b/cc/scheduler/scheduler_unittest.cc
index 7c068ec..4d9c77ad 100644
--- a/cc/scheduler/scheduler_unittest.cc
+++ b/cc/scheduler/scheduler_unittest.cc
@@ -14,6 +14,7 @@
 #include "base/memory/ptr_util.h"
 #include "base/numerics/safe_conversions.h"
 #include "base/run_loop.h"
+#include "base/test/test_mock_time_task_runner.h"
 #include "base/time/time.h"
 #include "base/trace_event/trace_event.h"
 #include "cc/test/scheduler_test_common.h"
@@ -21,7 +22,6 @@
 #include "components/viz/test/begin_frame_args_test.h"
 #include "components/viz/test/fake_delay_based_time_source.h"
 #include "components/viz/test/fake_external_begin_frame_source.h"
-#include "components/viz/test/ordered_simple_task_runner.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -283,20 +283,71 @@
   THROTTLED_BFS,
 };
 
+class SchedulerTestTaskRunner : public base::TestMockTimeTaskRunner {
+ public:
+  SchedulerTestTaskRunner()
+      : base::TestMockTimeTaskRunner(
+            base::TestMockTimeTaskRunner::Type::kStandalone) {
+    AdvanceMockTickClock(base::TimeDelta::FromMicroseconds(110000));
+  }
+
+  void RunUntilTime(base::TimeTicks end_time) {
+    FastForwardBy(end_time - NowTicks());
+  }
+
+  // Runs all tasks posted before this call.
+  void RunPendingTasks() {
+    base::circular_deque<base::TestPendingTask> tasks = TakePendingTasks();
+    while (!tasks.empty()) {
+      base::TestPendingTask task = std::move(tasks.front());
+      tasks.pop_front();
+      // Set clock to the beginning of task and run it.
+      AdvanceMockTickClock(task.GetTimeToRun() - NowTicks());
+      std::move(task.task).Run();
+    }
+  }
+
+  // Runs tasks while condition is met.
+  // Condition is being checked when task exists and before it gets selected.
+  void RunTasksWhile(base::RepeatingCallback<bool()> condition) {
+    run_condition_ = condition;
+    FastForwardUntilNoTasksRemain();
+    run_condition_ = base::nullopt;
+    // We've moved all the pending tasks away to break the execution loop,
+    // now we should restore them.
+    while (!tasks_to_requeue_.empty()) {
+      base::TestPendingTask task = std::move(tasks_to_requeue_.front());
+      tasks_to_requeue_.pop_front();
+      PostDelayedTask(task.location, std::move(task.task),
+                      task.GetTimeToRun() - NowTicks());
+    }
+  }
+
+ protected:
+  void OnBeforeSelectingTask() override {
+    // Avoid potential infinite loops.
+    ASSERT_LT(++task_count_, 100u);
+
+    if (run_condition_ && HasPendingTask() && !run_condition_->Run()) {
+      // Execution will not continue because we move all the pending tasks away.
+      tasks_to_requeue_ = TakePendingTasks();
+    }
+  }
+
+ private:
+  ~SchedulerTestTaskRunner() override = default;  // Ref-counted.
+
+  size_t task_count_ = 0u;
+  base::Optional<base::RepeatingCallback<bool()>> run_condition_;
+  base::circular_deque<base::TestPendingTask> tasks_to_requeue_;
+};
+
 class SchedulerTest : public testing::Test {
  public:
   SchedulerTest()
-      : now_src_(new base::SimpleTestTickClock()),
-        task_runner_(new OrderedSimpleTaskRunner(now_src_.get(), true)),
+      : task_runner_(base::MakeRefCounted<SchedulerTestTaskRunner>()),
         fake_external_begin_frame_source_(nullptr),
-        fake_compositor_timing_history_(nullptr) {
-    now_src_->Advance(base::TimeDelta::FromMicroseconds(10000));
-    // A bunch of tests require NowTicks()
-    // to be > viz::BeginFrameArgs::DefaultInterval()
-    now_src_->Advance(base::TimeDelta::FromMilliseconds(100));
-    // Fail if we need to run 100 tasks in a row.
-    task_runner_->SetRunTaskLimit(100);
-  }
+        fake_compositor_timing_history_(nullptr) {}
 
   ~SchedulerTest() override = default;
 
@@ -304,14 +355,14 @@
   TestScheduler* CreateScheduler(BeginFrameSourceType bfs_type) {
     viz::BeginFrameSource* frame_source = nullptr;
     unthrottled_frame_source_.reset(new viz::BackToBackBeginFrameSource(
-        std::make_unique<viz::FakeDelayBasedTimeSource>(now_src_.get(),
-                                                        task_runner_.get())));
+        std::make_unique<viz::FakeDelayBasedTimeSource>(
+            task_runner_->GetMockTickClock(), task_runner_.get())));
     fake_external_begin_frame_source_.reset(
         new viz::FakeExternalBeginFrameSource(1.0, false));
     fake_external_begin_frame_source_->SetClient(client_.get());
     synthetic_frame_source_ = std::make_unique<viz::DelayBasedBeginFrameSource>(
-        std::make_unique<viz::FakeDelayBasedTimeSource>(now_src_.get(),
-                                                        task_runner_.get()),
+        std::make_unique<viz::FakeDelayBasedTimeSource>(
+            task_runner_->GetMockTickClock(), task_runner_.get()),
         viz::BeginFrameSource::kNotRestartableId);
     switch (bfs_type) {
       case EXTERNAL_BFS:
@@ -332,7 +383,7 @@
     fake_compositor_timing_history_ = fake_compositor_timing_history.get();
 
     scheduler_.reset(new TestScheduler(
-        now_src_.get(), client_.get(), scheduler_settings_, 0,
+        task_runner_->GetMockTickClock(), client_.get(), scheduler_settings_, 0,
         task_runner_.get(), std::move(fake_compositor_timing_history)));
     client_->set_scheduler(scheduler_.get());
     scheduler_->SetBeginFrameSource(frame_source);
@@ -359,9 +410,6 @@
     CreateScheduler(bfs_type);
   }
 
-  OrderedSimpleTaskRunner& task_runner() { return *task_runner_; }
-  base::SimpleTestTickClock* now_src() { return now_src_.get(); }
-
   // As this function contains EXPECT macros, to allow debugging it should be
   // called inside EXPECT_SCOPED like so;
   //   EXPECT_SCOPED(
@@ -394,8 +442,8 @@
       SCOPED_TRACE("Do first frame to commit after initialize.");
       AdvanceFrame();
 
-      now_src_->Advance(base::TimeDelta::FromMilliseconds(1));
-      scheduler_->NotifyBeginMainFrameStarted(now_src_->NowTicks());
+      task_runner_->AdvanceMockTickClock(base::TimeDelta::FromMilliseconds(1));
+      scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
       scheduler_->NotifyReadyToCommit();
       scheduler_->NotifyReadyToActivate();
       scheduler_->NotifyReadyToDraw();
@@ -474,10 +522,10 @@
               fake_external_begin_frame_source_.get());
     // Creep the time forward so that any viz::BeginFrameArgs is not equal to
     // the last one otherwise we violate the viz::BeginFrameSource contract.
-    now_src_->Advance(viz::BeginFrameArgs::DefaultInterval());
+    task_runner_->AdvanceMockTickClock(viz::BeginFrameArgs::DefaultInterval());
     viz::BeginFrameArgs args =
         fake_external_begin_frame_source_->CreateBeginFrameArgs(
-            BEGINFRAME_FROM_HERE, now_src());
+            BEGINFRAME_FROM_HERE, task_runner_->GetMockTickClock());
     args.animate_only = animate_only;
     fake_external_begin_frame_source_->TestOnBeginFrame(args);
     return args;
@@ -512,8 +560,7 @@
                                     ScrollHandlerState scroll_handler_state,
                                     base::TimeDelta durations);
 
-  std::unique_ptr<base::SimpleTestTickClock> now_src_;
-  scoped_refptr<OrderedSimpleTaskRunner> task_runner_;
+  scoped_refptr<SchedulerTestTaskRunner> task_runner_;
   std::unique_ptr<viz::FakeExternalBeginFrameSource>
       fake_external_begin_frame_source_;
   std::unique_ptr<viz::SyntheticBeginFrameSource> synthetic_frame_source_;
@@ -594,14 +641,14 @@
   client_->Reset();
 
   // If we don't swap on the deadline, we wait for the next BeginFrame.
-  task_runner().RunPendingTasks();  // Run posted deadline.
+  task_runner_->RunPendingTasks();  // Run posted deadline.
   EXPECT_NO_ACTION();
   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
   EXPECT_TRUE(scheduler_->begin_frames_expected());
   client_->Reset();
 
   // NotifyReadyToCommit should trigger the commit.
-  scheduler_->NotifyBeginMainFrameStarted(now_src()->NowTicks());
+  scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
   scheduler_->NotifyReadyToCommit();
   EXPECT_ACTIONS("ScheduledActionCommit");
   EXPECT_TRUE(scheduler_->begin_frames_expected());
@@ -621,7 +668,7 @@
   client_->Reset();
 
   // BeginImplFrame deadline should draw.
-  task_runner().RunPendingTasks();  // Run posted deadline.
+  task_runner_->RunPendingTasks();  // Run posted deadline.
   EXPECT_ACTIONS("ScheduledActionDrawIfPossible");
   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
   EXPECT_TRUE(scheduler_->begin_frames_expected());
@@ -634,7 +681,7 @@
   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
   client_->Reset();
 
-  task_runner().RunPendingTasks();  // Run posted deadline.
+  task_runner_->RunPendingTasks();  // Run posted deadline.
   EXPECT_ACTIONS("RemoveObserver(this)");
   client_->Reset();
 }
@@ -648,7 +695,7 @@
   EXPECT_NO_ACTION();
 
   client_->Reset();
-  task_runner().RunPendingTasks();
+  task_runner_->RunPendingTasks();
   // There are no pending tasks or actions.
   EXPECT_NO_ACTION();
   EXPECT_FALSE(scheduler_->begin_frames_expected());
@@ -684,7 +731,7 @@
   EXPECT_ACTIONS("WillBeginImplFrame");
 
   client_->Reset();
-  task_runner().RunPendingTasks();  // Run posted deadline.
+  task_runner_->RunPendingTasks();  // Run posted deadline.
   EXPECT_ACTIONS("ScheduledActionDrawIfPossible");
   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
   EXPECT_TRUE(scheduler_->begin_frames_expected());
@@ -716,7 +763,7 @@
   client_->Reset();
 
   // Finish the first commit.
-  scheduler_->NotifyBeginMainFrameStarted(now_src()->NowTicks());
+  scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
   scheduler_->NotifyReadyToCommit();
   EXPECT_ACTIONS("ScheduledActionCommit");
   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
@@ -728,7 +775,7 @@
   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
   client_->Reset();
 
-  task_runner().RunPendingTasks();  // Run posted deadline.
+  task_runner_->RunPendingTasks();  // Run posted deadline.
   EXPECT_ACTIONS("ScheduledActionDrawIfPossible");
   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
 
@@ -745,7 +792,7 @@
 
   // Finishing the commit before the deadline should post a new deadline task
   // to trigger the deadline early.
-  scheduler_->NotifyBeginMainFrameStarted(now_src()->NowTicks());
+  scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
   scheduler_->NotifyReadyToCommit();
   EXPECT_ACTIONS("ScheduledActionCommit");
   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
@@ -754,7 +801,7 @@
   EXPECT_ACTIONS("ScheduledActionActivateSyncTree");
   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
   client_->Reset();
-  task_runner().RunPendingTasks();  // Run posted deadline.
+  task_runner_->RunPendingTasks();  // Run posted deadline.
   EXPECT_ACTIONS("ScheduledActionDrawIfPossible");
   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
   EXPECT_TRUE(scheduler_->begin_frames_expected());
@@ -763,7 +810,7 @@
   // On the next BeginImplFrame, verify we go back to a quiescent state and
   // no longer request BeginImplFrames.
   EXPECT_SCOPED(AdvanceFrame());
-  task_runner().RunPendingTasks();  // Run posted deadline.
+  task_runner_->RunPendingTasks();  // Run posted deadline.
   EXPECT_FALSE(scheduler_->begin_frames_expected());
   client_->Reset();
 }
@@ -808,7 +855,7 @@
   EXPECT_EQ(0, client->num_draws());
 
   EXPECT_SCOPED(AdvanceFrame());
-  task_runner().RunPendingTasks();  // Run posted deadline.
+  task_runner_->RunPendingTasks();  // Run posted deadline.
   EXPECT_EQ(1, client->num_draws());
   EXPECT_TRUE(scheduler_->RedrawPending());
   EXPECT_TRUE(client->needs_begin_frames());
@@ -816,7 +863,7 @@
   client->SetRequestRedrawsInsideDraw(false);
 
   EXPECT_SCOPED(AdvanceFrame());
-  task_runner().RunPendingTasks();  // Run posted deadline.
+  task_runner_->RunPendingTasks();  // Run posted deadline.
   EXPECT_EQ(2, client_->num_draws());
   EXPECT_FALSE(scheduler_->RedrawPending());
   EXPECT_TRUE(client->needs_begin_frames());
@@ -824,7 +871,7 @@
   // We stop requesting BeginImplFrames after a BeginImplFrame where we don't
   // swap.
   EXPECT_SCOPED(AdvanceFrame());
-  task_runner().RunPendingTasks();  // Run posted deadline.
+  task_runner_->RunPendingTasks();  // Run posted deadline.
   EXPECT_EQ(2, client->num_draws());
   EXPECT_FALSE(scheduler_->RedrawPending());
   EXPECT_FALSE(client->needs_begin_frames());
@@ -846,7 +893,7 @@
 
   // Fail the draw.
   EXPECT_SCOPED(AdvanceFrame());
-  task_runner().RunPendingTasks();  // Run posted deadline.
+  task_runner_->RunPendingTasks();  // Run posted deadline.
   EXPECT_EQ(1, client->num_draws());
 
   // We have a commit pending and the draw failed, and we didn't lose the redraw
@@ -859,7 +906,7 @@
 
   // Fail the draw again.
   EXPECT_SCOPED(AdvanceFrame());
-  task_runner().RunPendingTasks();  // Run posted deadline.
+  task_runner_->RunPendingTasks();  // Run posted deadline.
   EXPECT_EQ(2, client->num_draws());
   EXPECT_TRUE(scheduler_->CommitPending());
   EXPECT_TRUE(scheduler_->RedrawPending());
@@ -868,7 +915,7 @@
   // Draw successfully.
   client->SetDrawWillHappen(true);
   EXPECT_SCOPED(AdvanceFrame());
-  task_runner().RunPendingTasks();  // Run posted deadline.
+  task_runner_->RunPendingTasks();  // Run posted deadline.
   EXPECT_EQ(3, client->num_draws());
   EXPECT_TRUE(scheduler_->CommitPending());
   EXPECT_FALSE(scheduler_->RedrawPending());
@@ -919,16 +966,16 @@
   client->SetNeedsBeginMainFrameOnNextDraw();
   EXPECT_SCOPED(AdvanceFrame());
   client->SetNeedsBeginMainFrameOnNextDraw();
-  task_runner().RunPendingTasks();  // Run posted deadline.
+  task_runner_->RunPendingTasks();  // Run posted deadline.
   EXPECT_EQ(1, client->num_draws());
   EXPECT_TRUE(scheduler_->CommitPending());
   EXPECT_TRUE(client->needs_begin_frames());
-  scheduler_->NotifyBeginMainFrameStarted(now_src()->NowTicks());
+  scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
   scheduler_->NotifyReadyToCommit();
   scheduler_->NotifyReadyToActivate();
 
   EXPECT_SCOPED(AdvanceFrame());
-  task_runner().RunPendingTasks();  // Run posted deadline.
+  task_runner_->RunPendingTasks();  // Run posted deadline.
   EXPECT_EQ(2, client->num_draws());
 
   EXPECT_FALSE(scheduler_->RedrawPending());
@@ -938,7 +985,7 @@
   // We stop requesting BeginImplFrames after a BeginImplFrame where we don't
   // swap.
   EXPECT_SCOPED(AdvanceFrame());
-  task_runner().RunPendingTasks();  // Run posted deadline.
+  task_runner_->RunPendingTasks();  // Run posted deadline.
   EXPECT_EQ(2, client->num_draws());
   EXPECT_FALSE(scheduler_->RedrawPending());
   EXPECT_FALSE(scheduler_->CommitPending());
@@ -960,7 +1007,7 @@
 
   // Fail the draw.
   EXPECT_SCOPED(AdvanceFrame());
-  task_runner().RunPendingTasks();  // Run posted deadline.
+  task_runner_->RunPendingTasks();  // Run posted deadline.
   EXPECT_EQ(1, client->num_draws());
 
   // We have a commit pending and the draw failed, and we didn't lose the commit
@@ -972,7 +1019,7 @@
   // Fail the draw again.
   EXPECT_SCOPED(AdvanceFrame());
 
-  task_runner().RunPendingTasks();  // Run posted deadline.
+  task_runner_->RunPendingTasks();  // Run posted deadline.
   EXPECT_EQ(2, client->num_draws());
   EXPECT_TRUE(scheduler_->CommitPending());
   EXPECT_TRUE(scheduler_->RedrawPending());
@@ -981,7 +1028,7 @@
   // Draw successfully.
   client->SetDrawWillHappen(true);
   EXPECT_SCOPED(AdvanceFrame());
-  task_runner().RunPendingTasks();  // Run posted deadline.
+  task_runner_->RunPendingTasks();  // Run posted deadline.
   EXPECT_EQ(3, client->num_draws());
   EXPECT_TRUE(scheduler_->CommitPending());
   EXPECT_FALSE(scheduler_->RedrawPending());
@@ -1001,7 +1048,7 @@
   // Draw successfully, this starts a new frame.
   client->SetNeedsBeginMainFrameOnNextDraw();
   EXPECT_SCOPED(AdvanceFrame());
-  task_runner().RunPendingTasks();  // Run posted deadline.
+  task_runner_->RunPendingTasks();  // Run posted deadline.
   EXPECT_EQ(1, client->num_draws());
 
   scheduler_->SetNeedsRedraw();
@@ -1012,7 +1059,7 @@
   client->SetDrawWillHappen(false);
   client->SetNeedsBeginMainFrameOnNextDraw();
   EXPECT_SCOPED(AdvanceFrame());
-  task_runner().RunPendingTasks();  // Run posted deadline.
+  task_runner_->RunPendingTasks();  // Run posted deadline.
   EXPECT_EQ(2, client->num_draws());
 }
 
@@ -1051,7 +1098,7 @@
 
   // On the deadline, the actions should have occured in the right order.
   client->Reset();
-  task_runner().RunPendingTasks();  // Run posted deadline.
+  task_runner_->RunPendingTasks();  // Run posted deadline.
   EXPECT_EQ(1, client->num_draws());
   EXPECT_TRUE(client->HasAction("ScheduledActionDrawIfPossible"));
   EXPECT_TRUE(client->HasAction("ScheduledActionPrepareTiles"));
@@ -1080,7 +1127,7 @@
   // then the PrepareTiles action will be triggered after the Draw.
   // Afterwards, neither a draw nor PrepareTiles are pending.
   client->Reset();
-  task_runner().RunPendingTasks();  // Run posted deadline.
+  task_runner_->RunPendingTasks();  // Run posted deadline.
   EXPECT_EQ(1, client->num_draws());
   EXPECT_TRUE(client->HasAction("ScheduledActionDrawIfPossible"));
   EXPECT_TRUE(client->HasAction("ScheduledActionPrepareTiles"));
@@ -1096,7 +1143,7 @@
   EXPECT_ACTIONS("WillBeginImplFrame");
   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
   client->Reset();
-  task_runner().RunPendingTasks();  // Run posted deadline.
+  task_runner_->RunPendingTasks();  // Run posted deadline.
   EXPECT_ACTIONS("RemoveObserver(this)");
   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
   EXPECT_EQ(0, client->num_draws());
@@ -1116,7 +1163,7 @@
   EXPECT_ACTIONS("WillBeginImplFrame");
   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
   client->Reset();
-  task_runner().RunPendingTasks();  // Run posted deadline.
+  task_runner_->RunPendingTasks();  // Run posted deadline.
   EXPECT_EQ(0, client->num_draws());
   EXPECT_FALSE(client->HasAction("ScheduledActionDrawIfPossible"));
   EXPECT_TRUE(client->HasAction("ScheduledActionPrepareTiles"));
@@ -1143,7 +1190,7 @@
   EXPECT_FALSE(scheduler_->PrepareTilesPending());
 
   client_->Reset();
-  task_runner().RunPendingTasks();  // Run posted deadline.
+  task_runner_->RunPendingTasks();  // Run posted deadline.
   EXPECT_EQ(1, client_->num_draws());
   EXPECT_TRUE(client_->HasAction("ScheduledActionDrawIfPossible"));
   EXPECT_FALSE(client_->HasAction("ScheduledActionPrepareTiles"));
@@ -1160,7 +1207,7 @@
   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
 
   client_->Reset();
-  task_runner().RunPendingTasks();  // Run posted deadline.
+  task_runner_->RunPendingTasks();  // Run posted deadline.
   EXPECT_EQ(1, client_->num_draws());
   EXPECT_TRUE(client_->HasAction("ScheduledActionDrawIfPossible"));
   EXPECT_TRUE(client_->HasAction("ScheduledActionPrepareTiles"));
@@ -1184,7 +1231,7 @@
   EXPECT_TRUE(scheduler_->PrepareTilesPending());
 
   client_->Reset();
-  task_runner().RunPendingTasks();  // Run posted deadline.
+  task_runner_->RunPendingTasks();  // Run posted deadline.
   EXPECT_EQ(1, client_->num_draws());
   EXPECT_TRUE(client_->HasAction("ScheduledActionDrawIfPossible"));
   EXPECT_FALSE(client_->HasAction("ScheduledActionPrepareTiles"));
@@ -1208,7 +1255,7 @@
   EXPECT_TRUE(scheduler_->PrepareTilesPending());
 
   client_->Reset();
-  task_runner().RunPendingTasks();  // Run posted deadline.
+  task_runner_->RunPendingTasks();  // Run posted deadline.
   EXPECT_EQ(1, client_->num_draws());
   EXPECT_TRUE(client_->HasAction("ScheduledActionDrawIfPossible"));
   EXPECT_FALSE(client_->HasAction("ScheduledActionPrepareTiles"));
@@ -1224,7 +1271,7 @@
   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
 
   client_->Reset();
-  task_runner().RunPendingTasks();  // Run posted deadline.
+  task_runner_->RunPendingTasks();  // Run posted deadline.
   EXPECT_EQ(1, client_->num_draws());
   EXPECT_TRUE(client_->HasAction("ScheduledActionDrawIfPossible"));
   EXPECT_TRUE(client_->HasAction("ScheduledActionPrepareTiles"));
@@ -1250,7 +1297,7 @@
   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
 
   client_->Reset();
-  task_runner().RunPendingTasks();  // Run posted deadline.
+  task_runner_->RunPendingTasks();  // Run posted deadline.
   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
   EXPECT_ACTIONS("ScheduledActionDrawIfPossible",
                  "ScheduledActionPrepareTiles");
@@ -1271,7 +1318,7 @@
   // No scheduled prepare tiles because we've already counted a prepare tiles in
   // between frames.
   client_->Reset();
-  task_runner().RunPendingTasks();  // Run posted deadline.
+  task_runner_->RunPendingTasks();  // Run posted deadline.
   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
   EXPECT_ACTIONS("ScheduledActionDrawIfPossible");
 
@@ -1283,7 +1330,7 @@
 
   // Resume scheduled prepare tiles.
   client_->Reset();
-  task_runner().RunPendingTasks();  // Run posted deadline.
+  task_runner_->RunPendingTasks();  // Run posted deadline.
   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
   EXPECT_ACTIONS("ScheduledActionDrawIfPossible",
                  "ScheduledActionPrepareTiles");
@@ -1315,7 +1362,7 @@
 
   // Begin new frame.
   EXPECT_SCOPED(AdvanceFrame());
-  scheduler_->NotifyBeginMainFrameStarted(now_src()->NowTicks());
+  scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
   EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame");
 
   client_->Reset();
@@ -1328,14 +1375,14 @@
 
   // Scheduler won't post deadline in the mode.
   client_->Reset();
-  task_runner().RunPendingTasks();  // Try to run posted deadline.
+  task_runner_->RunPendingTasks();  // Try to run posted deadline.
   // There is no posted deadline.
   EXPECT_NO_ACTION();
 
   // Scheduler received ready to draw signal, and posted deadline.
   scheduler_->NotifyReadyToDraw();
   client_->Reset();
-  task_runner().RunPendingTasks();  // Run posted deadline.
+  task_runner_->RunPendingTasks();  // Run posted deadline.
   EXPECT_EQ(1, client_->num_draws());
   EXPECT_TRUE(client_->HasAction("ScheduledActionDrawIfPossible"));
 }
@@ -1353,7 +1400,7 @@
 
   // Begin new frame.
   EXPECT_SCOPED(AdvanceFrame());
-  scheduler_->NotifyBeginMainFrameStarted(now_src()->NowTicks());
+  scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
   EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame");
 
   client_->Reset();
@@ -1366,7 +1413,7 @@
 
   // Scheduler won't post deadline in the mode.
   client_->Reset();
-  task_runner().RunPendingTasks();  // Try to run posted deadline.
+  task_runner_->RunPendingTasks();  // Try to run posted deadline.
   // There is no posted deadline.
   EXPECT_NO_ACTION();
 
@@ -1375,7 +1422,7 @@
   client_->Reset();
   scheduler_->DidLoseLayerTreeFrameSink();
   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
-  task_runner().RunPendingTasks();  // Run posted deadline.
+  task_runner_->RunPendingTasks();  // Run posted deadline.
   EXPECT_ACTIONS("ScheduledActionBeginLayerTreeFrameSinkCreation",
                  "RemoveObserver(this)");
 }
@@ -1386,9 +1433,9 @@
   EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
   EXPECT_SCOPED(AdvanceFrame());
   EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
-  task_runner().RunTasksWhile(client_->InsideBeginImplFrame(true));
+  task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
   EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
-  scheduler_->NotifyBeginMainFrameStarted(now_src()->NowTicks());
+  scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
   scheduler_->NotifyReadyToCommit();
   scheduler_->NotifyReadyToActivate();
   EXPECT_ACTIONS("AddObserver(this)", "WillBeginImplFrame",
@@ -1406,7 +1453,7 @@
   EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
   EXPECT_SCOPED(AdvanceFrame());
   EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
-  task_runner().RunTasksWhile(client_->InsideBeginImplFrame(true));
+  task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
   EXPECT_EQ(expect_send_begin_main_frame,
             scheduler_->MainThreadMissedLastDeadline());
   EXPECT_TRUE(client_->HasAction("WillBeginImplFrame"));
@@ -1426,16 +1473,17 @@
   scheduler_->SetNeedsBeginMainFrame();
 
   // Advance frame and create a begin frame.
-  now_src_->Advance(viz::BeginFrameArgs::DefaultInterval());
+  task_runner_->AdvanceMockTickClock(viz::BeginFrameArgs::DefaultInterval());
   viz::BeginFrameArgs args =
       fake_external_begin_frame_source_->CreateBeginFrameArgs(
-          BEGINFRAME_FROM_HERE, now_src());
+          BEGINFRAME_FROM_HERE, task_runner_->GetMockTickClock());
 
   // Deliver this begin frame super late.
-  now_src_->Advance(viz::BeginFrameArgs::DefaultInterval() * 100);
+  task_runner_->AdvanceMockTickClock(viz::BeginFrameArgs::DefaultInterval() *
+                                     100);
   fake_external_begin_frame_source_->TestOnBeginFrame(args);
 
-  task_runner().RunTasksWhile(client_->InsideBeginImplFrame(true));
+  task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
   EXPECT_EQ(true, scheduler_->MainThreadMissedLastDeadline());
   EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame",
                  "ScheduledActionDrawIfPossible");
@@ -1553,9 +1601,9 @@
   EXPECT_ACTIONS("AddObserver(this)", "WillBeginImplFrame",
                  "ScheduledActionSendBeginMainFrame");
   EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
-  task_runner().RunTasksWhile(client_->InsideBeginImplFrame(true));
+  task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
   EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
-  scheduler_->NotifyBeginMainFrameStarted(now_src()->NowTicks());
+  scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
   EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
 
   // After aborting the frame, make sure we don't skip the
@@ -1569,7 +1617,7 @@
   EXPECT_TRUE(client_->HasAction("WillBeginImplFrame"));
   EXPECT_TRUE(client_->HasAction("ScheduledActionSendBeginMainFrame"));
   EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
-  task_runner().RunTasksWhile(client_->InsideBeginImplFrame(true));
+  task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
   EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
 }
 
@@ -1588,9 +1636,9 @@
   EXPECT_ACTIONS("AddObserver(this)", "WillBeginImplFrame",
                  "ScheduledActionSendBeginMainFrame");
   EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
-  task_runner().RunTasksWhile(client_->InsideBeginImplFrame(true));
+  task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
   EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
-  scheduler_->NotifyBeginMainFrameStarted(now_src()->NowTicks());
+  scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
   EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
 
   // Make us abort the upcoming draw.
@@ -1616,7 +1664,7 @@
   EXPECT_TRUE(client_->HasAction("WillBeginImplFrame"));
   EXPECT_TRUE(client_->HasAction("ScheduledActionSendBeginMainFrame"));
   EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
-  task_runner().RunTasksWhile(client_->InsideBeginImplFrame(true));
+  task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
   EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
 }
 
@@ -1633,9 +1681,9 @@
   EXPECT_ACTIONS("AddObserver(this)", "WillBeginImplFrame",
                  "ScheduledActionSendBeginMainFrame");
   EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
-  task_runner().RunTasksWhile(client_->InsideBeginImplFrame(true));
+  task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
   EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
-  scheduler_->NotifyBeginMainFrameStarted(now_src()->NowTicks());
+  scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
   EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
 
   // Commit after the deadline.
@@ -1669,11 +1717,11 @@
                  "ScheduledActionSendBeginMainFrame");
 
   client_->Reset();
-  scheduler_->NotifyBeginMainFrameStarted(now_src()->NowTicks());
+  scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
   scheduler_->NotifyReadyToCommit();
   scheduler_->NotifyReadyToActivate();
   EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
-  task_runner().RunTasksWhile(client_->InsideBeginImplFrame(true));
+  task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
   EXPECT_ACTIONS("ScheduledActionCommit", "ScheduledActionActivateSyncTree",
                  "ScheduledActionDrawIfPossible");
 
@@ -1698,10 +1746,10 @@
     if (receive_ack_before_deadline) {
       // It shouldn't matter if the swap ack comes back before the deadline...
       scheduler_->DidReceiveCompositorFrameAck();
-      task_runner().RunTasksWhile(client_->InsideBeginImplFrame(true));
+      task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
     } else {
       // ... or after the deadline.
-      task_runner().RunTasksWhile(client_->InsideBeginImplFrame(true));
+      task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
       scheduler_->DidReceiveCompositorFrameAck();
     }
     EXPECT_NO_ACTION();
@@ -1714,10 +1762,10 @@
     EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame");
 
     client_->Reset();
-    scheduler_->NotifyBeginMainFrameStarted(now_src()->NowTicks());
+    scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
     scheduler_->NotifyReadyToCommit();
     scheduler_->NotifyReadyToActivate();
-    task_runner().RunTasksWhile(client_->InsideBeginImplFrame(true));
+    task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
     EXPECT_ACTIONS("ScheduledActionCommit", "ScheduledActionActivateSyncTree",
                    "ScheduledActionDrawIfPossible");
   }
@@ -1791,7 +1839,7 @@
 
   client_->Reset();
   EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
-  task_runner().RunTasksWhile(client_->InsideBeginImplFrame(true));
+  task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
   EXPECT_ACTIONS("ScheduledActionDrawIfPossible");
 
   // Verify we skip every other frame if the swap ack consistently
@@ -1824,7 +1872,7 @@
     client_->Reset();
     // Deadline should be immediate.
     EXPECT_TRUE(client_->IsInsideBeginImplFrame());
-    task_runner().RunUntilTime(now_src_->NowTicks());
+    task_runner_->RunUntilTime(task_runner_->NowTicks());
     EXPECT_FALSE(client_->IsInsideBeginImplFrame());
     EXPECT_ACTIONS("ScheduledActionDrawIfPossible");
   }
@@ -1843,11 +1891,11 @@
                  "ScheduledActionSendBeginMainFrame");
 
   client_->Reset();
-  scheduler_->NotifyBeginMainFrameStarted(now_src()->NowTicks());
+  scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
   scheduler_->NotifyReadyToCommit();
   scheduler_->NotifyReadyToActivate();
   EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
-  task_runner().RunTasksWhile(client_->InsideBeginImplFrame(true));
+  task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
   EXPECT_ACTIONS("ScheduledActionCommit", "ScheduledActionActivateSyncTree",
                  "ScheduledActionDrawIfPossible");
 
@@ -1867,10 +1915,10 @@
 
     client_->Reset();
     scheduler_->DidReceiveCompositorFrameAck();
-    scheduler_->NotifyBeginMainFrameStarted(now_src()->NowTicks());
+    scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
     scheduler_->NotifyReadyToCommit();
     scheduler_->NotifyReadyToActivate();
-    task_runner().RunTasksWhile(client_->InsideBeginImplFrame(true));
+    task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
 
     // Verify that we don't skip the actions of the BeginImplFrame
     EXPECT_ACTIONS("ScheduledActionSendBeginMainFrame", "ScheduledActionCommit",
@@ -1939,9 +1987,9 @@
   EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
   EXPECT_SCOPED(AdvanceFrame());
   EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
-  task_runner().RunTasksWhile(client_->InsideBeginImplFrame(true));
+  task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
   EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
-  scheduler_->NotifyBeginMainFrameStarted(now_src()->NowTicks());
+  scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
   scheduler_->NotifyReadyToCommit();
   scheduler_->NotifyReadyToActivate();
   EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
@@ -1956,8 +2004,8 @@
   EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
   EXPECT_SCOPED(AdvanceFrame());
   EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
-  task_runner().RunTasksWhile(client_->InsideBeginImplFrame(true));
-  scheduler_->NotifyBeginMainFrameStarted(now_src()->NowTicks());
+  task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
+  scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
   scheduler_->NotifyReadyToCommit();
   scheduler_->NotifyReadyToActivate();
 
@@ -1973,7 +2021,7 @@
   EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
   EXPECT_SCOPED(AdvanceFrame());
   EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
-  task_runner().RunTasksWhile(client_->InsideBeginImplFrame(true));
+  task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
 
   EXPECT_ACTIONS("WillBeginImplFrame");
   // Note: BeginMainFrame and swap are skipped here because of
@@ -1997,7 +2045,7 @@
   SendNextBeginFrame();
   EXPECT_TRUE(scheduler_->MainThreadMissedLastDeadline());
   scheduler_->DidReceiveCompositorFrameAck();
-  task_runner().RunTasksWhile(client_->InsideBeginImplFrame(true));
+  task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
 
   EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
   EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionDrawIfPossible");
@@ -2008,7 +2056,7 @@
   EXPECT_TRUE(scheduler_->NeedsBeginMainFrame());
   EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
   SendNextBeginFrame();
-  task_runner().RunTasksWhile(client_->InsideBeginImplFrame(true));
+  task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
   EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
   scheduler_->DidReceiveCompositorFrameAck();
   EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
@@ -2022,10 +2070,10 @@
   EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
   SendNextBeginFrame();
   EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
-  scheduler_->NotifyBeginMainFrameStarted(now_src()->NowTicks());
+  scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
   scheduler_->NotifyReadyToCommit();
   scheduler_->NotifyReadyToActivate();
-  task_runner().RunTasksWhile(client_->InsideBeginImplFrame(true));
+  task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
   EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
   scheduler_->DidReceiveCompositorFrameAck();
   EXPECT_FALSE(scheduler_->MainThreadMissedLastDeadline());
@@ -2057,9 +2105,9 @@
   EXPECT_SCOPED(AdvanceFrame());
   EXPECT_TRUE(scheduler_->CommitPending());
   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
-  task_runner().RunTasksWhile(client_->InsideBeginImplFrame(true));
+  task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
-  scheduler_->NotifyBeginMainFrameStarted(now_src()->NowTicks());
+  scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
   scheduler_->NotifyReadyToCommit();
   scheduler_->NotifyReadyToActivate();
   EXPECT_FALSE(scheduler_->CommitPending());
@@ -2073,11 +2121,11 @@
   EXPECT_FALSE(scheduler_->CommitPending());
   scheduler_->SetNeedsBeginMainFrame();
   EXPECT_SCOPED(AdvanceFrame());
-  scheduler_->NotifyBeginMainFrameStarted(now_src()->NowTicks());
+  scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
   scheduler_->NotifyReadyToCommit();
   scheduler_->NotifyReadyToActivate();
   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
-  task_runner().RunTasksWhile(client_->InsideBeginImplFrame(true));
+  task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
   EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame",
                  "ScheduledActionCommit");
@@ -2089,7 +2137,7 @@
   scheduler_->SetNeedsBeginMainFrame();
   EXPECT_SCOPED(AdvanceFrame());
   EXPECT_FALSE(scheduler_->CommitPending());
-  task_runner().RunPendingTasks();  // Run posted deadline.
+  task_runner_->RunPendingTasks();  // Run posted deadline.
   EXPECT_ACTIONS("WillBeginImplFrame");
 }
 
@@ -2118,10 +2166,10 @@
   EXPECT_SCOPED(AdvanceFrame());
   EXPECT_TRUE(scheduler_->CommitPending());
   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
-  task_runner().RunTasksWhile(client_->InsideBeginImplFrame(true));
+  task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
   scheduler_->DidReceiveCompositorFrameAck();
-  scheduler_->NotifyBeginMainFrameStarted(now_src()->NowTicks());
+  scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
   scheduler_->NotifyReadyToCommit();
   EXPECT_FALSE(scheduler_->CommitPending());
   EXPECT_ACTIONS("AddObserver(this)", "WillBeginImplFrame",
@@ -2136,10 +2184,10 @@
   EXPECT_SCOPED(AdvanceFrame());
   EXPECT_TRUE(scheduler_->CommitPending());
   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
-  task_runner().RunTasksWhile(client_->InsideBeginImplFrame(true));
+  task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
   scheduler_->DidReceiveCompositorFrameAck();
-  scheduler_->NotifyBeginMainFrameStarted(now_src()->NowTicks());
+  scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
   EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame",
                  "ScheduledActionDrawIfPossible");
 
@@ -2177,7 +2225,7 @@
   client_->Reset();
 
   // NotifyReadyToCommit should trigger the commit.
-  scheduler_->NotifyBeginMainFrameStarted(now_src()->NowTicks());
+  scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
   scheduler_->NotifyReadyToCommit();
   EXPECT_ACTIONS("ScheduledActionCommit");
   client_->Reset();
@@ -2195,7 +2243,7 @@
 
   // Make sure SetNeedsBeginFrame isn't called on the client
   // when the BeginFrame is no longer needed.
-  task_runner().RunPendingTasks();  // Run posted deadline.
+  task_runner_->RunPendingTasks();  // Run posted deadline.
   EXPECT_NO_ACTION();
   client_->Reset();
 }
@@ -2231,7 +2279,7 @@
   client_->Reset();
 
   // NotifyReadyToCommit should trigger the pending commit.
-  scheduler_->NotifyBeginMainFrameStarted(now_src()->NowTicks());
+  scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
   scheduler_->NotifyReadyToCommit();
   EXPECT_ACTIONS("ScheduledActionCommit");
   client_->Reset();
@@ -2243,7 +2291,7 @@
 
   // Swapping will put us into a swap throttled state.
   // Run posted deadline.
-  task_runner().RunTasksWhile(client_->InsideBeginImplFrame(true));
+  task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
   EXPECT_ACTIONS("ScheduledActionDrawIfPossible");
   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
   client_->Reset();
@@ -2260,9 +2308,9 @@
   base::TimeTicks before_deadline, after_deadline;
 
   // The deadline is set to the regular deadline.
-  before_deadline = now_src()->NowTicks();
-  task_runner().RunTasksWhile(client_->InsideBeginImplFrame(true));
-  after_deadline = now_src()->NowTicks();
+  before_deadline = task_runner_->NowTicks();
+  task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
+  after_deadline = task_runner_->NowTicks();
   // We can't do an equality comparison here because the scheduler uses a fudge
   // factor that's an internal implementation detail.
   EXPECT_GT(after_deadline, before_deadline);
@@ -2283,9 +2331,9 @@
   client_->Reset();
 
   // The deadline is set to the regular deadline.
-  before_deadline = now_src()->NowTicks();
-  task_runner().RunTasksWhile(client_->InsideBeginImplFrame(true));
-  after_deadline = now_src()->NowTicks();
+  before_deadline = task_runner_->NowTicks();
+  task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
+  after_deadline = task_runner_->NowTicks();
   // We can't do an equality comparison here because the scheduler uses a fudge
   // factor that's an internal implementation detail.
   EXPECT_GT(after_deadline, before_deadline);
@@ -2337,12 +2385,12 @@
   EXPECT_NO_ACTION();
 
   client_->Reset();
-  scheduler_->NotifyBeginMainFrameStarted(now_src()->NowTicks());
+  scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
   scheduler_->NotifyReadyToCommit();
   EXPECT_ACTIONS("ScheduledActionCommit", "ScheduledActionActivateSyncTree");
 
   client_->Reset();
-  task_runner().RunTasksWhile(client_->InsideBeginImplFrame(true));
+  task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
   EXPECT_ACTIONS("ScheduledActionBeginLayerTreeFrameSinkCreation",
                  "RemoveObserver(this)");
 }
@@ -2368,7 +2416,7 @@
   client_->Reset();
   // Run posted deadline.
   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
-  task_runner().RunTasksWhile(client_->InsideBeginImplFrame(true));
+  task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
   // OnBeginImplFrameDeadline didn't schedule LayerTreeFrameSink creation
   // because
   // main frame is not yet completed.
@@ -2377,13 +2425,13 @@
 
   // BeginImplFrame is not started.
   client_->Reset();
-  task_runner().RunUntilTime(now_src()->NowTicks() +
+  task_runner_->RunUntilTime(task_runner_->NowTicks() +
                              base::TimeDelta::FromMilliseconds(10));
   EXPECT_NO_ACTION();
   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
 
   client_->Reset();
-  scheduler_->NotifyBeginMainFrameStarted(now_src()->NowTicks());
+  scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
   scheduler_->NotifyReadyToCommit();
   EXPECT_ACTIONS("ScheduledActionCommit", "ScheduledActionActivateSyncTree",
                  "ScheduledActionBeginLayerTreeFrameSinkCreation");
@@ -2402,7 +2450,7 @@
   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
 
   client_->Reset();
-  scheduler_->NotifyBeginMainFrameStarted(now_src()->NowTicks());
+  scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
   scheduler_->NotifyReadyToCommit();
   EXPECT_ACTIONS("ScheduledActionCommit");
 
@@ -2413,7 +2461,7 @@
 
   // RemoveObserver(this) is not called until the end of the frame.
   client_->Reset();
-  task_runner().RunTasksWhile(client_->InsideBeginImplFrame(true));
+  task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
   EXPECT_ACTIONS("ScheduledActionBeginLayerTreeFrameSinkCreation",
                  "RemoveObserver(this)");
 }
@@ -2436,7 +2484,7 @@
   EXPECT_NO_ACTION();
 
   client_->Reset();
-  task_runner().RunTasksWhile(client_->InsideBeginImplFrame(true));
+  task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
   EXPECT_ACTIONS("ScheduledActionPrepareTiles",
                  "ScheduledActionBeginLayerTreeFrameSinkCreation",
                  "RemoveObserver(this)");
@@ -2458,7 +2506,7 @@
 
   // NotifyReadyToCommit should trigger the commit.
   client_->Reset();
-  scheduler_->NotifyBeginMainFrameStarted(now_src()->NowTicks());
+  scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
   scheduler_->NotifyReadyToCommit();
   EXPECT_ACTIONS("ScheduledActionCommit");
   EXPECT_TRUE(scheduler_->begin_frames_expected());
@@ -2476,7 +2524,7 @@
   EXPECT_TRUE(scheduler_->begin_frames_expected());
 
   client_->Reset();
-  task_runner().RunTasksWhile(client_->InsideBeginImplFrame(true));
+  task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
   EXPECT_ACTIONS("ScheduledActionBeginLayerTreeFrameSinkCreation");
   EXPECT_FALSE(scheduler_->begin_frames_expected());
 }
@@ -2494,7 +2542,7 @@
   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
 
   client_->Reset();
-  scheduler_->NotifyBeginMainFrameStarted(now_src()->NowTicks());
+  scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
   scheduler_->NotifyReadyToCommit();
   EXPECT_ACTIONS("ScheduledActionCommit");
 
@@ -2503,7 +2551,7 @@
   EXPECT_ACTIONS("ScheduledActionActivateSyncTree");
 
   client_->Reset();
-  task_runner().RunTasksWhile(client_->InsideBeginImplFrame(true));
+  task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
   EXPECT_ACTIONS("ScheduledActionDrawIfPossible");
 
   // Idle time between BeginFrames.
@@ -2526,14 +2574,14 @@
   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
 
   client_->Reset();
-  scheduler_->NotifyBeginMainFrameStarted(now_src()->NowTicks());
+  scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
   scheduler_->NotifyReadyToCommit();
   EXPECT_ACTIONS("ScheduledActionCommit");
   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
 
   client_->Reset();
   scheduler_->SetVisible(false);
-  task_runner().RunPendingTasks();  // Run posted deadline.
+  task_runner_->RunPendingTasks();  // Run posted deadline.
 
   // Sync tree should be forced to activate.
   EXPECT_ACTIONS("ScheduledActionActivateSyncTree", "RemoveObserver(this)");
@@ -2552,14 +2600,14 @@
   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
 
   client_->Reset();
-  scheduler_->NotifyBeginMainFrameStarted(now_src()->NowTicks());
+  scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
   scheduler_->NotifyReadyToCommit();
   EXPECT_ACTIONS("ScheduledActionCommit");
   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
 
   client_->Reset();
   fake_external_begin_frame_source_->SetPaused(true);
-  task_runner().RunPendingTasks();  // Run posted deadline.
+  task_runner_->RunPendingTasks();  // Run posted deadline.
 
   // Sync tree should be forced to activate.
   // Pausing the begin frame source aborts the draw. Then
@@ -2582,7 +2630,7 @@
   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
   EXPECT_TRUE(scheduler_->begin_frames_expected());
   client_->Reset();
-  task_runner().RunPendingTasks();  // Run posted deadline.
+  task_runner_->RunPendingTasks();  // Run posted deadline.
   EXPECT_ACTIONS("ScheduledActionDrawIfPossible");
   scheduler_->SetNeedsRedraw();
 
@@ -2591,13 +2639,13 @@
   client_->Reset();
 
   // Unthrottled frame source will immediately begin a new frame.
-  task_runner().RunPendingTasks();  // Run posted BeginFrame.
+  task_runner_->RunPendingTasks();  // Run posted BeginFrame.
   EXPECT_ACTIONS("WillBeginImplFrame");
   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
   client_->Reset();
 
   // If we don't swap on the deadline, we wait for the next BeginFrame.
-  task_runner().RunPendingTasks();  // Run posted deadline.
+  task_runner_->RunPendingTasks();  // Run posted deadline.
   EXPECT_ACTIONS("ScheduledActionDrawIfPossible");
   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
   client_->Reset();
@@ -2624,14 +2672,14 @@
   EXPECT_TRUE(scheduler_->begin_frames_expected());
   client_->Reset();
 
-  task_runner().RunPendingTasks();  // Run posted deadline.
+  task_runner_->RunPendingTasks();  // Run posted deadline.
   EXPECT_ACTIONS("ScheduledActionDrawIfPossible",
                  // Unthrottled frame source will immediately begin a new frame.
                  "WillBeginImplFrame");
   scheduler_->SetNeedsRedraw();
   client_->Reset();
 
-  task_runner().RunPendingTasks();  // Run posted deadline.
+  task_runner_->RunPendingTasks();  // Run posted deadline.
   EXPECT_ACTIONS("ScheduledActionDrawIfPossible");
   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
   client_->Reset();
@@ -2646,12 +2694,12 @@
   EXPECT_NO_ACTION();
   client_->Reset();
 
-  task_runner().RunPendingTasks();  // Run posted BeginFrame.
+  task_runner_->RunPendingTasks();  // Run posted BeginFrame.
   EXPECT_ACTIONS("WillBeginImplFrame");
   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
   client_->Reset();
 
-  task_runner().RunPendingTasks();  // Run posted deadline.
+  task_runner_->RunPendingTasks();  // Run posted deadline.
   EXPECT_ACTIONS("ScheduledActionDrawIfPossible");
   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
   client_->Reset();
@@ -2662,7 +2710,7 @@
 
   // SetNeedsRedraw should begin the frame on the next BeginImplFrame.
   scheduler_->SetNeedsRedraw();
-  task_runner().RunPendingTasks();
+  task_runner_->RunPendingTasks();
   EXPECT_NO_ACTION();
   client_->Reset();
 
@@ -2671,7 +2719,7 @@
   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
   EXPECT_TRUE(scheduler_->begin_frames_expected());
   client_->Reset();
-  task_runner().RunPendingTasks();  // Run posted deadline.
+  task_runner_->RunPendingTasks();  // Run posted deadline.
   EXPECT_ACTIONS("ScheduledActionDrawIfPossible");
 }
 
@@ -2692,7 +2740,7 @@
   client_->Reset();
 
   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
-  task_runner().RunPendingTasks();  // Run posted deadline.
+  task_runner_->RunPendingTasks();  // Run posted deadline.
   EXPECT_ACTIONS("ScheduledActionDrawIfPossible");
   EXPECT_FALSE(scheduler_->begin_frames_expected());
   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
@@ -2720,7 +2768,7 @@
   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
   client_->Reset();
 
-  task_runner().RunPendingTasks();
+  task_runner_->RunPendingTasks();
   EXPECT_ACTIONS("ScheduledActionDrawIfPossible");
 }
 
@@ -2736,7 +2784,7 @@
 
   // Begin new frame.
   EXPECT_SCOPED(AdvanceFrame());
-  scheduler_->NotifyBeginMainFrameStarted(now_src()->NowTicks());
+  scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
   EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame");
 
   client_->Reset();
@@ -2752,7 +2800,7 @@
   client_->Reset();
   scheduler_->DidLoseLayerTreeFrameSink();
   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
-  task_runner().RunPendingTasks();
+  task_runner_->RunPendingTasks();
   EXPECT_ACTIONS("ScheduledActionBeginLayerTreeFrameSinkCreation",
                  "RemoveObserver(this)");
 
@@ -2786,7 +2834,7 @@
 
   EXPECT_SCOPED(AdvanceFrame());
   scheduler_->SetMainThreadWantsBeginMainFrameNotExpected(true);
-  task_runner().RunPendingTasks();
+  task_runner_->RunPendingTasks();
   EXPECT_ACTIONS("WillBeginImplFrame",
                  "ScheduledActionBeginMainFrameNotExpectedUntil",
                  "ScheduledActionDrawIfPossible");
@@ -2803,10 +2851,10 @@
 
   // Trigger a frame draw.
   EXPECT_SCOPED(AdvanceFrame());
-  scheduler_->NotifyBeginMainFrameStarted(now_src()->NowTicks());
+  scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
   scheduler_->NotifyReadyToCommit();
   scheduler_->NotifyReadyToActivate();
-  task_runner().RunPendingTasks();
+  task_runner_->RunPendingTasks();
   EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame",
                  "ScheduledActionCommit", "ScheduledActionActivateSyncTree",
                  "ScheduledActionDrawIfPossible");
@@ -2822,7 +2870,7 @@
 
   // The BeginImplFrame deadline should SetNeedsBeginFrame(false) and send a
   // SendBeginMainFrameNotExpectedSoon.
-  task_runner().RunPendingTasks();  // Run posted deadline.
+  task_runner_->RunPendingTasks();  // Run posted deadline.
   EXPECT_ACTIONS("RemoveObserver(this)", "SendBeginMainFrameNotExpectedSoon");
   client_->Reset();
 }
@@ -2839,10 +2887,10 @@
 
   // Trigger a frame draw.
   EXPECT_SCOPED(AdvanceFrame());
-  scheduler_->NotifyBeginMainFrameStarted(now_src()->NowTicks());
+  scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
   scheduler_->NotifyReadyToCommit();
   scheduler_->NotifyReadyToActivate();
-  task_runner().RunPendingTasks();
+  task_runner_->RunPendingTasks();
   EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionSendBeginMainFrame",
                  "ScheduledActionCommit", "ScheduledActionActivateSyncTree",
                  "ScheduledActionDrawIfPossible");
@@ -2856,7 +2904,7 @@
   // The BeginImplFrame deadline should SetNeedsBeginFrame(false), but doesn't
   // send a SendBeginMainFrameNotExpectedSoon as it's not been requested by the
   // main thread.
-  task_runner().RunPendingTasks();  // Run posted deadline.
+  task_runner_->RunPendingTasks();  // Run posted deadline.
   EXPECT_ACTIONS("RemoveObserver(this)");
   client_->Reset();
 
@@ -2989,7 +3037,7 @@
   EXPECT_ACTIONS("AddObserver(this)");
 
   EXPECT_SCOPED(AdvanceFrame());
-  task_runner().RunPendingTasks();  // Run posted deadline.
+  task_runner_->RunPendingTasks();  // Run posted deadline.
   // Should not try to schedule a draw. (ScheduledActionDrawIfPossible should
   // not appear.)
   // When the frame is aborted, the scheduler does not ask for a proactive begin
@@ -3000,7 +3048,7 @@
 
   scheduler_->SetNeedsRedraw();
   EXPECT_SCOPED(AdvanceFrame());
-  task_runner().RunPendingTasks();  // Run posted deadline.
+  task_runner_->RunPendingTasks();  // Run posted deadline.
   EXPECT_EQ(0, client_->num_draws());
 }
 
@@ -3068,7 +3116,7 @@
             client_->last_begin_frame_ack());
   client_->Reset();
 
-  scheduler_->NotifyBeginMainFrameStarted(now_src()->NowTicks());
+  scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
   EXPECT_NO_ACTION();
 
   // Next vsync.
@@ -3234,7 +3282,7 @@
   EXPECT_ACTIONS("ScheduledActionSendBeginMainFrame");
   client_->Reset();
 
-  scheduler_->NotifyBeginMainFrameStarted(now_src()->NowTicks());
+  scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
   scheduler_->NotifyReadyToCommit();
   EXPECT_ACTIONS("ScheduledActionCommit");
   client_->Reset();
@@ -3292,13 +3340,13 @@
 
   EXPECT_EQ(initial_interval, scheduler_->BeginImplFrameInterval());
 
-  scheduler_->NotifyBeginMainFrameStarted(now_src_->NowTicks());
+  scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
   scheduler_->NotifyReadyToCommit();
   scheduler_->NotifyReadyToActivate();
-  task_runner().RunTasksWhile(client_->InsideBeginImplFrame(true));
+  task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
 
   // Test changing the interval on the frame source external to the scheduler.
-  synthetic_frame_source_->OnUpdateVSyncParameters(now_src_->NowTicks(),
+  synthetic_frame_source_->OnUpdateVSyncParameters(task_runner_->NowTicks(),
                                                    authoritative_interval);
 
   EXPECT_SCOPED(AdvanceFrame());
@@ -3368,7 +3416,7 @@
 
   // Abort the commit.
   client_->Reset();
-  scheduler_->NotifyBeginMainFrameStarted(now_src()->NowTicks());
+  scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
   scheduler_->BeginMainFrameAborted(
       CommitEarlyOutReason::ABORTED_LAYER_TREE_FRAME_SINK_LOST);
   EXPECT_ACTIONS("ScheduledActionBeginLayerTreeFrameSinkCreation");
@@ -3403,7 +3451,7 @@
   // actions since the impl-side invalidation request will be merged with the
   // commit.
   client_->Reset();
-  scheduler_->NotifyBeginMainFrameStarted(now_src()->NowTicks());
+  scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
   scheduler_->NotifyReadyToCommit();
   EXPECT_ACTIONS("ScheduledActionCommit");
   EXPECT_FALSE(scheduler_->needs_impl_side_invalidation());
@@ -3426,7 +3474,7 @@
   // should not be blocked on the main frame.
   client_->Reset();
   scheduler_->SetNeedsBeginMainFrame();
-  scheduler_->NotifyBeginMainFrameStarted(now_src()->NowTicks());
+  scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
   scheduler_->BeginMainFrameAborted(CommitEarlyOutReason::FINISHED_NO_UPDATES);
   EXPECT_ACTIONS("ScheduledActionPerformImplSideInvalidation");
 }
@@ -3533,7 +3581,7 @@
   EXPECT_TRUE(scheduler_->begin_frames_expected());
   client_->Reset();
 
-  task_runner().RunPendingTasks();  // Run posted deadline.
+  task_runner_->RunPendingTasks();  // Run posted deadline.
   EXPECT_ACTIONS("ScheduledActionDrawIfPossible");
   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
   EXPECT_TRUE(scheduler_->begin_frames_expected());
@@ -3555,7 +3603,7 @@
   client_->Reset();
 
   client_->SetDrawWillHappen(false);
-  task_runner().RunPendingTasks();  // Run posted deadline.
+  task_runner_->RunPendingTasks();  // Run posted deadline.
   EXPECT_ACTIONS("ScheduledActionDrawIfPossible",
                  // Failed draw triggers SendBeginMainFrame.
                  "ScheduledActionSendBeginMainFrame");
@@ -3587,7 +3635,7 @@
   EXPECT_TRUE(scheduler_->begin_frames_expected());
   client_->Reset();
 
-  task_runner().RunPendingTasks();  // Run posted deadline.
+  task_runner_->RunPendingTasks();  // Run posted deadline.
   EXPECT_ACTIONS("ScheduledActionDrawIfPossible");
   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
   EXPECT_TRUE(scheduler_->begin_frames_expected());
@@ -3675,7 +3723,7 @@
             client_->last_begin_frame_ack());
   client_->Reset();
 
-  task_runner().RunPendingTasks();  // Run deadline of prior BeginFrame.
+  task_runner_->RunPendingTasks();  // Run deadline of prior BeginFrame.
   EXPECT_ACTIONS("RemoveObserver(this)");
 
   // We'd expect an out-of-order ack for the prior BeginFrame.
@@ -3692,13 +3740,13 @@
   client_->Reset();
 
   // Send a missed BeginFrame with a passed deadline.
-  now_src_->Advance(viz::BeginFrameArgs::DefaultInterval());
+  task_runner_->AdvanceMockTickClock(viz::BeginFrameArgs::DefaultInterval());
   viz::BeginFrameArgs args =
       fake_external_begin_frame_source_->CreateBeginFrameArgs(
-          BEGINFRAME_FROM_HERE, now_src());
+          BEGINFRAME_FROM_HERE, task_runner_->GetMockTickClock());
   args.type = viz::BeginFrameArgs::MISSED;
-  now_src_->Advance(viz::BeginFrameArgs::DefaultInterval());
-  EXPECT_GT(now_src_->NowTicks(), args.deadline);
+  task_runner_->AdvanceMockTickClock(viz::BeginFrameArgs::DefaultInterval());
+  EXPECT_GT(task_runner_->NowTicks(), args.deadline);
   fake_external_begin_frame_source_->TestOnBeginFrame(args);
 
   EXPECT_NO_ACTION();
@@ -3727,14 +3775,15 @@
   scheduler_->SetNeedsRedraw();
   // An interval of 2ms makes sure that the main frame is considered slow.
   base::TimeDelta interval = base::TimeDelta::FromMilliseconds(2);
-  now_src_->Advance(interval);
+  task_runner_->AdvanceMockTickClock(interval);
   viz::BeginFrameArgs args = viz::BeginFrameArgs::Create(
-      BEGINFRAME_FROM_HERE, 0u, 1u, now_src_->NowTicks(),
-      now_src_->NowTicks() + interval, interval, viz::BeginFrameArgs::NORMAL);
+      BEGINFRAME_FROM_HERE, 0u, 1u, task_runner_->NowTicks(),
+      task_runner_->NowTicks() + interval, interval,
+      viz::BeginFrameArgs::NORMAL);
   fake_external_begin_frame_source_->TestOnBeginFrame(args);
   EXPECT_TRUE(scheduler_->ImplLatencyTakesPriority());
 
-  task_runner().RunPendingTasks();  // Run posted deadline to finish the frame.
+  task_runner_->RunPendingTasks();  // Run posted deadline to finish the frame.
   ASSERT_FALSE(client_->IsInsideBeginImplFrame());
 
   // Set an interval of 10ms. The bmf_to_activate_interval should be 1*4 = 4ms,
@@ -3743,14 +3792,15 @@
   // the main frame to be activated is 8ms, so it should be considered fast.
   scheduler_->SetNeedsRedraw();
   interval = base::TimeDelta::FromMilliseconds(10);
-  now_src_->Advance(interval);
-  args = viz::BeginFrameArgs::Create(
-      BEGINFRAME_FROM_HERE, 0u, 2u, now_src_->NowTicks(),
-      now_src_->NowTicks() + interval, interval, viz::BeginFrameArgs::NORMAL);
+  task_runner_->AdvanceMockTickClock(interval);
+  args = viz::BeginFrameArgs::Create(BEGINFRAME_FROM_HERE, 0u, 2u,
+                                     task_runner_->NowTicks(),
+                                     task_runner_->NowTicks() + interval,
+                                     interval, viz::BeginFrameArgs::NORMAL);
   fake_external_begin_frame_source_->TestOnBeginFrame(args);
   EXPECT_FALSE(scheduler_->ImplLatencyTakesPriority());
 
-  task_runner().RunPendingTasks();  // Run posted deadline to finish the frame.
+  task_runner_->RunPendingTasks();  // Run posted deadline to finish the frame.
   ASSERT_FALSE(client_->IsInsideBeginImplFrame());
 
   // Increase the draw duration to decrease the time available for the main
@@ -3758,10 +3808,11 @@
   scheduler_->SetNeedsRedraw();
   fake_compositor_timing_history_->SetDrawDurationEstimate(
       base::TimeDelta::FromMilliseconds(7));
-  now_src_->Advance(interval);
-  args = viz::BeginFrameArgs::Create(
-      BEGINFRAME_FROM_HERE, 0u, 3u, now_src_->NowTicks(),
-      now_src_->NowTicks() + interval, interval, viz::BeginFrameArgs::NORMAL);
+  task_runner_->AdvanceMockTickClock(interval);
+  args = viz::BeginFrameArgs::Create(BEGINFRAME_FROM_HERE, 0u, 3u,
+                                     task_runner_->NowTicks(),
+                                     task_runner_->NowTicks() + interval,
+                                     interval, viz::BeginFrameArgs::NORMAL);
   fake_external_begin_frame_source_->TestOnBeginFrame(args);
   EXPECT_TRUE(scheduler_->ImplLatencyTakesPriority());
 }
@@ -3784,10 +3835,11 @@
   client_->Reset();
 
   base::TimeDelta interval = base::TimeDelta::FromMilliseconds(16);
-  now_src_->Advance(interval);
+  task_runner_->AdvanceMockTickClock(interval);
   viz::BeginFrameArgs args = viz::BeginFrameArgs::Create(
-      BEGINFRAME_FROM_HERE, 0u, 1u, now_src_->NowTicks(),
-      now_src_->NowTicks() + interval, interval, viz::BeginFrameArgs::MISSED);
+      BEGINFRAME_FROM_HERE, 0u, 1u, task_runner_->NowTicks(),
+      task_runner_->NowTicks() + interval, interval,
+      viz::BeginFrameArgs::MISSED);
   fake_external_begin_frame_source_->TestOnBeginFrame(args);
   EXPECT_FALSE(client_->IsInsideBeginImplFrame());
 }
@@ -3813,10 +3865,10 @@
 
   // Uses MISSED BeginFrames even after the deadline has passed.
   base::TimeDelta interval = base::TimeDelta::FromMilliseconds(16);
-  now_src_->Advance(interval);
-  base::TimeTicks timestamp = now_src_->NowTicks();
+  task_runner_->AdvanceMockTickClock(interval);
+  base::TimeTicks timestamp = task_runner_->NowTicks();
   // Deadline should have passed after this.
-  now_src_->Advance(interval * 2);
+  task_runner_->AdvanceMockTickClock(interval * 2);
   viz::BeginFrameArgs args = viz::BeginFrameArgs::Create(
       BEGINFRAME_FROM_HERE, 0u, 1u, timestamp, timestamp + interval, interval,
       viz::BeginFrameArgs::MISSED);
@@ -3850,8 +3902,8 @@
 
   // Scheduler begins a frame even if otherwise idle.
   base::TimeDelta interval = base::TimeDelta::FromMilliseconds(16);
-  now_src_->Advance(interval);
-  base::TimeTicks timestamp = now_src_->NowTicks();
+  task_runner_->AdvanceMockTickClock(interval);
+  base::TimeTicks timestamp = task_runner_->NowTicks();
   viz::BeginFrameArgs args = viz::BeginFrameArgs::Create(
       BEGINFRAME_FROM_HERE, 0u, 1u, timestamp, timestamp + interval, interval,
       viz::BeginFrameArgs::NORMAL);
@@ -3861,7 +3913,7 @@
   client_->Reset();
 
   // BeginFrame deadline is blocked because commits are deferred.
-  task_runner().RunPendingTasks();
+  task_runner_->RunPendingTasks();
   EXPECT_ACTIONS();
   EXPECT_TRUE(client_->IsInsideBeginImplFrame());
   client_->Reset();
@@ -3944,7 +3996,7 @@
 
   // Draw deadline.
   client_->Reset();
-  task_runner().RunPendingTasks();
+  task_runner_->RunPendingTasks();
   EXPECT_ACTIONS();
 
   // Next frame. The invalidation should not be throttled.
@@ -3968,13 +4020,13 @@
 
   // Commit before deadline but not ready to activate.
   client_->Reset();
-  scheduler_->NotifyBeginMainFrameStarted(now_src_->NowTicks());
+  scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
   scheduler_->NotifyReadyToCommit();
   EXPECT_ACTIONS("ScheduledActionCommit");
 
   // Draw deadline.
   client_->Reset();
-  task_runner().RunPendingTasks();
+  task_runner_->RunPendingTasks();
   EXPECT_ACTIONS();
 
   // Next frame. The invalidation should still be throttled.
@@ -4007,7 +4059,7 @@
   client_->Reset();
   scheduler_->SetNeedsBeginMainFrame();
   EXPECT_SCOPED(AdvanceFrame());
-  task_runner().RunTasksWhile(client_->InsideBeginImplFrame(true));
+  task_runner_->RunTasksWhile(client_->InsideBeginImplFrame(true));
   EXPECT_ACTIONS("AddObserver(this)", "WillBeginImplFrame",
                  "ScheduledActionSendBeginMainFrame");
 
@@ -4017,7 +4069,7 @@
   client_->Reset();
   EXPECT_SCOPED(AdvanceFrame());
   scheduler_->SetNeedsBeginMainFrame();
-  scheduler_->NotifyBeginMainFrameStarted(now_src()->NowTicks());
+  scheduler_->NotifyBeginMainFrameStarted(task_runner_->NowTicks());
   scheduler_->NotifyReadyToCommit();
   EXPECT_ACTIONS("WillBeginImplFrame", "ScheduledActionCommit");
 
diff --git a/cc/test/layer_test_common.cc b/cc/test/layer_test_common.cc
index a657f266..58a40c0 100644
--- a/cc/test/layer_test_common.cc
+++ b/cc/test/layer_test_common.cc
@@ -191,10 +191,9 @@
                       SimpleEnclosedRegion(occluded), SimpleEnclosedRegion());
   layer_impl->draw_properties().occlusion_in_content_space = occlusion;
 
-  if (layer_impl->WillDraw(DRAW_MODE_HARDWARE, resource_provider())) {
-    layer_impl->AppendQuads(render_pass_.get(), &data);
-    layer_impl->DidDraw(resource_provider());
-  }
+  layer_impl->WillDraw(DRAW_MODE_HARDWARE, resource_provider());
+  layer_impl->AppendQuads(render_pass_.get(), &data);
+  layer_impl->DidDraw(resource_provider());
 }
 
 void LayerTestCommon::LayerImplTest::AppendQuadsForPassWithOcclusion(
diff --git a/cc/test/scheduler_test_common.cc b/cc/test/scheduler_test_common.cc
index 436eb48..c53b5a9 100644
--- a/cc/test/scheduler_test_common.cc
+++ b/cc/test/scheduler_test_common.cc
@@ -10,6 +10,7 @@
 
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
+#include "base/time/tick_clock.h"
 #include "cc/debug/rendering_stats_instrumentation.h"
 
 namespace cc {
@@ -133,7 +134,7 @@
     SchedulerClient* client,
     const SchedulerSettings& scheduler_settings,
     int layer_tree_host_id,
-    OrderedSimpleTaskRunner* task_runner,
+    base::SingleThreadTaskRunner* task_runner,
     std::unique_ptr<CompositorTimingHistory> compositor_timing_history)
     : Scheduler(client,
                 scheduler_settings,
diff --git a/cc/test/scheduler_test_common.h b/cc/test/scheduler_test_common.h
index 7e5df382..2c15eed6a 100644
--- a/cc/test/scheduler_test_common.h
+++ b/cc/test/scheduler_test_common.h
@@ -14,7 +14,6 @@
 #include "base/time/time.h"
 #include "cc/scheduler/compositor_timing_history.h"
 #include "cc/scheduler/scheduler.h"
-#include "components/viz/test/ordered_simple_task_runner.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace cc {
@@ -79,7 +78,7 @@
       SchedulerClient* client,
       const SchedulerSettings& scheduler_settings,
       int layer_tree_host_id,
-      OrderedSimpleTaskRunner* task_runner,
+      base::SingleThreadTaskRunner* task_runner,
       std::unique_ptr<CompositorTimingHistory> compositor_timing_history);
 
   bool IsDrawThrottled() const { return state_machine_.IsDrawThrottled(); }
diff --git a/cc/tiles/gpu_image_decode_cache.cc b/cc/tiles/gpu_image_decode_cache.cc
index bdc89db..3ad02f7f 100644
--- a/cc/tiles/gpu_image_decode_cache.cc
+++ b/cc/tiles/gpu_image_decode_cache.cc
@@ -303,8 +303,7 @@
   // Step 2: Apply a color-space conversion if necessary.
   if (uploaded_image && target_color_space) {
     sk_sp<SkImage> pre_converted_image = uploaded_image;
-    uploaded_image = uploaded_image->makeColorSpace(
-        target_color_space, SkTransferFunctionBehavior::kIgnore);
+    uploaded_image = uploaded_image->makeColorSpace(target_color_space);
 
     if (uploaded_image != pre_converted_image)
       DeleteSkImageAndPreventCaching(context, std::move(pre_converted_image));
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index 308f811..a329a48 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -1097,9 +1097,13 @@
         render_surface->AppendQuads(draw_mode, target_render_pass,
                                     &append_quads_data);
       }
-    } else if (it.state() == EffectTreeLayerListIterator::State::LAYER) {
+    } else if (it.state() == EffectTreeLayerListIterator::State::LAYER &&
+               !it.current_layer()->visible_layer_rect().IsEmpty()) {
       LayerImpl* layer = it.current_layer();
-      if (layer->WillDraw(draw_mode, &resource_provider_)) {
+      bool occluded =
+          layer->draw_properties().occlusion_in_content_space.IsOccluded(
+              layer->visible_layer_rect());
+      if (!occluded && layer->WillDraw(draw_mode, &resource_provider_)) {
         DCHECK_EQ(active_tree_.get(), layer->layer_tree_impl());
 
         frame->will_draw_layers.push_back(layer);
@@ -2201,8 +2205,6 @@
 }
 
 void LayerTreeHostImpl::DidDrawAllLayers(const FrameData& frame) {
-  // TODO(lethalantidote): LayerImpl::DidDraw can be removed when
-  // VideoLayerImpl is removed.
   for (size_t i = 0; i < frame.will_draw_layers.size(); ++i)
     frame.will_draw_layers[i]->DidDraw(&resource_provider_);
 
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc
index f996663..9cd7cf6 100644
--- a/cc/trees/layer_tree_host_impl_unittest.cc
+++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -4638,12 +4638,10 @@
 
   bool WillDraw(DrawMode draw_mode,
                 viz::ClientResourceProvider* provider) override {
-    if (!LayerImpl::WillDraw(draw_mode, provider))
-      return false;
+    will_draw_called_ = true;
     if (will_draw_returns_false_)
       return false;
-    will_draw_returned_true_ = true;
-    return true;
+    return LayerImpl::WillDraw(draw_mode, provider);
   }
 
   void AppendQuads(viz::RenderPass* render_pass,
@@ -4657,14 +4655,14 @@
     LayerImpl::DidDraw(provider);
   }
 
-  bool will_draw_returned_true() const { return will_draw_returned_true_; }
+  bool will_draw_called() const { return will_draw_called_; }
   bool append_quads_called() const { return append_quads_called_; }
   bool did_draw_called() const { return did_draw_called_; }
 
   void set_will_draw_returns_false() { will_draw_returns_false_ = true; }
 
   void ClearDidDrawCheck() {
-    will_draw_returned_true_ = false;
+    will_draw_called_ = false;
     append_quads_called_ = false;
     did_draw_called_ = false;
   }
@@ -4678,7 +4676,7 @@
   DidDrawCheckLayer(LayerTreeImpl* tree_impl, int id)
       : LayerImpl(tree_impl, id),
         will_draw_returns_false_(false),
-        will_draw_returned_true_(false),
+        will_draw_called_(false),
         append_quads_called_(false),
         did_draw_called_(false) {
     SetBounds(gfx::Size(10, 10));
@@ -4688,7 +4686,7 @@
 
  private:
   bool will_draw_returns_false_;
-  bool will_draw_returned_true_;
+  bool will_draw_called_;
   bool append_quads_called_;
   bool did_draw_called_;
 };
@@ -4788,7 +4786,7 @@
     host_impl_->DrawLayers(&frame);
     host_impl_->DidDrawAllLayers(frame);
 
-    EXPECT_TRUE(layer->will_draw_returned_true());
+    EXPECT_TRUE(layer->will_draw_called());
     EXPECT_TRUE(layer->append_quads_called());
     EXPECT_TRUE(layer->did_draw_called());
   }
@@ -4805,7 +4803,7 @@
     host_impl_->DrawLayers(&frame);
     host_impl_->DidDrawAllLayers(frame);
 
-    EXPECT_FALSE(layer->will_draw_returned_true());
+    EXPECT_TRUE(layer->will_draw_called());
     EXPECT_FALSE(layer->append_quads_called());
     EXPECT_FALSE(layer->did_draw_called());
   }
@@ -4831,14 +4829,14 @@
 
   TestFrameData frame;
 
-  EXPECT_FALSE(layer->will_draw_returned_true());
+  EXPECT_FALSE(layer->will_draw_called());
   EXPECT_FALSE(layer->did_draw_called());
 
   EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
   host_impl_->DrawLayers(&frame);
   host_impl_->DidDrawAllLayers(frame);
 
-  EXPECT_FALSE(layer->will_draw_returned_true());
+  EXPECT_FALSE(layer->will_draw_called());
   EXPECT_FALSE(layer->did_draw_called());
 
   EXPECT_TRUE(layer->visible_layer_rect().IsEmpty());
@@ -4848,14 +4846,14 @@
   layer->NoteLayerPropertyChanged();
   host_impl_->active_tree()->BuildPropertyTreesForTesting();
 
-  EXPECT_FALSE(layer->will_draw_returned_true());
+  EXPECT_FALSE(layer->will_draw_called());
   EXPECT_FALSE(layer->did_draw_called());
 
   EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
   host_impl_->DrawLayers(&frame);
   host_impl_->DidDrawAllLayers(frame);
 
-  EXPECT_TRUE(layer->will_draw_returned_true());
+  EXPECT_TRUE(layer->will_draw_called());
   EXPECT_TRUE(layer->did_draw_called());
 
   EXPECT_FALSE(layer->visible_layer_rect().IsEmpty());
@@ -4888,18 +4886,18 @@
 
   TestFrameData frame;
 
-  EXPECT_FALSE(occluded_layer->will_draw_returned_true());
+  EXPECT_FALSE(occluded_layer->will_draw_called());
   EXPECT_FALSE(occluded_layer->did_draw_called());
-  EXPECT_FALSE(top_layer->will_draw_returned_true());
+  EXPECT_FALSE(top_layer->will_draw_called());
   EXPECT_FALSE(top_layer->did_draw_called());
 
   EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
   host_impl_->DrawLayers(&frame);
   host_impl_->DidDrawAllLayers(frame);
 
-  EXPECT_FALSE(occluded_layer->will_draw_returned_true());
+  EXPECT_FALSE(occluded_layer->will_draw_called());
   EXPECT_FALSE(occluded_layer->did_draw_called());
-  EXPECT_TRUE(top_layer->will_draw_returned_true());
+  EXPECT_TRUE(top_layer->will_draw_called());
   EXPECT_TRUE(top_layer->did_draw_called());
 }
 
diff --git a/chrome/VERSION b/chrome/VERSION
index d708729a..2717ac2 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=69
 MINOR=0
-BUILD=3494
+BUILD=3495
 PATCH=0
diff --git a/chrome/android/java/res/layout/download_manager_image_item.xml b/chrome/android/java/res/layout/download_manager_image_item.xml
new file mode 100644
index 0000000..6fb4abb5
--- /dev/null
+++ b/chrome/android/java/res/layout/download_manager_image_item.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2018 The Chromium Authors. All rights reserved.
+     Use of this source code is governed by a BSD-style license that can be
+     found in the LICENSE file.
+-->
+
+<ImageView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/thumbnail"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:scaleType="centerCrop"
+    android:layout_gravity="center_vertical"
+    tools:ignore="ContentDescription" />
diff --git a/chrome/android/java/res/layout/password_generation_dialog.xml b/chrome/android/java/res/layout/password_generation_dialog.xml
index f2b44b9..099a394 100644
--- a/chrome/android/java/res/layout/password_generation_dialog.xml
+++ b/chrome/android/java/res/layout/password_generation_dialog.xml
@@ -8,19 +8,23 @@
     android:orientation="vertical"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    style="@style/AlertDialogContent">
+    android:paddingStart="@dimen/password_generation_dialog_padding"
+    android:paddingEnd="@dimen/password_generation_dialog_padding"
+    android:paddingTop="@dimen/password_generation_dialog_padding"
+    android:paddingBottom="@dimen/password_generation_dialog_padding">
 
-    <TextView
+    <org.chromium.ui.widget.TextViewWithLeading
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:id="@+id/generated_password"
-        android:textAppearance="@style/BlackHint1"
-        android:layout_marginBottom="20dp"/>
+        android:textAppearance="@style/BlackTitle1"
+        app:leading="20sp"
+        android:layout_marginBottom="24dp"/>
 
     <org.chromium.ui.widget.TextViewWithClickableSpans
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:id="@+id/generation_save_explanation"
         android:textAppearance="@style/BlackBody"
-        android:layout_marginBottom="20dp"/>
+        app:leading="20sp"/>
 </LinearLayout>
\ No newline at end of file
diff --git a/chrome/android/java/res/values/dimens.xml b/chrome/android/java/res/values/dimens.xml
index d393ade2..3f789f80 100644
--- a/chrome/android/java/res/values/dimens.xml
+++ b/chrome/android/java/res/values/dimens.xml
@@ -136,6 +136,9 @@
     <dimen name="password_generation_horizontal_margin">10dp</dimen>
     <dimen name="password_generation_text_vertical_margin">12dp</dimen>
 
+    <!-- Password generation dialog dimensions -->
+    <dimen name="password_generation_dialog_padding">24dp</dimen>
+
     <!-- Minimum height/width for a touchable item -->
     <dimen name="min_touch_target_size">48dp</dimen>
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java
index dafacd8d..f522883 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java
@@ -203,6 +203,7 @@
     public static final String DONT_PREFETCH_LIBRARIES = "DontPrefetchLibraries";
     public static final String DOWNLOAD_HOME_SHOW_STORAGE_INFO = "DownloadHomeShowStorageInfo";
     public static final String DOWNLOAD_PROGRESS_INFOBAR = "DownloadProgressInfoBar";
+    public static final String DOWNLOAD_HOME_V2 = "DownloadHomeV2";
     public static final String DOWNLOADS_FOREGROUND = "DownloadsForeground";
     public static final String DOWNLOADS_LOCATION_CHANGE = "DownloadsLocationChange";
     public static final String EXPERIMENTAL_APP_BANNERS = "ExperimentalAppBanners";
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/DownloadManagerCoordinatorFactory.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/DownloadManagerCoordinatorFactory.java
index 6df5ce63..4570b7ee 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/DownloadManagerCoordinatorFactory.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/DownloadManagerCoordinatorFactory.java
@@ -7,15 +7,13 @@
 import android.app.Activity;
 import android.content.ComponentName;
 
+import org.chromium.chrome.browser.ChromeFeatureList;
 import org.chromium.chrome.browser.download.ui.DownloadManagerUi;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.snackbar.SnackbarManager;
 
 /** A helper class to build and return an {@link DownloadManagerCoordinator}. */
 public class DownloadManagerCoordinatorFactory {
-    // TODO(850603): Add feature flag to enable new downloads home.
-    private static boolean sEnableDownloadsHomeV2 = false;
-
     /**
      * Returns an instance of a {@link DownloadManagerCoordinator} to be used in the UI.
      * @param activity           The parent {@link Activity}.
@@ -29,7 +27,7 @@
     public static DownloadManagerCoordinator create(Activity activity, boolean isOffTheRecord,
             SnackbarManager snackbarManager, ComponentName parentComponent,
             boolean isSeparateActivity) {
-        if (sEnableDownloadsHomeV2) {
+        if (ChromeFeatureList.isEnabled(ChromeFeatureList.DOWNLOAD_HOME_V2)) {
             return new DownloadManagerCoordinatorImpl(
                     Profile.getLastUsedProfile(), activity, isOffTheRecord, snackbarManager);
         } else {
@@ -37,4 +35,4 @@
                     activity, isOffTheRecord, parentComponent, isSeparateActivity, snackbarManager);
         }
     }
-}
\ No newline at end of file
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/DateOrderedListView.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/DateOrderedListView.java
index e6485a8..c3a8081 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/DateOrderedListView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/DateOrderedListView.java
@@ -107,7 +107,12 @@
 
             int availableWidth = getWidth() - mImagePaddingPx;
             int columnWidth = mImageWidthPx - mImagePaddingPx;
-            setSpanCount(Math.max(1, availableWidth / columnWidth));
+
+            int easyFitSpan = availableWidth / columnWidth;
+            double remaining =
+                    ((double) (availableWidth - easyFitSpan * columnWidth)) / columnWidth;
+            if (remaining > 0.5) easyFitSpan++;
+            setSpanCount(Math.max(1, easyFitSpan));
 
             super.onLayoutChildren(recycler, state);
         }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/ListItemViewHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/ListItemViewHolder.java
index 62ad781..8878193d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/ListItemViewHolder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/list/ListItemViewHolder.java
@@ -60,7 +60,7 @@
             case ListUtils.ViewType.VIDEO:
                 return new VideoViewHolder(parent);
             case ListUtils.ViewType.IMAGE:
-                return new ImageViewHolder(parent);
+                return ImageViewHolder.create(parent);
             case ListUtils.ViewType.CUSTOM_VIEW:
                 return new CustomViewHolder(parent);
             case ListUtils.ViewType.PREFETCH:
@@ -232,16 +232,34 @@
     }
 
     /** A {@link ViewHolder} specifically meant to display an image {@code OfflineItem}. */
-    public static class ImageViewHolder extends ListItemViewHolder {
-        public ImageViewHolder(ViewGroup parent) {
-            super(new AppCompatTextView(parent.getContext()));
+    public static class ImageViewHolder extends ThumbnailAwareViewHolder {
+        public static ImageViewHolder create(ViewGroup parent) {
+            View view = LayoutInflater.from(parent.getContext())
+                                .inflate(R.layout.download_manager_image_item, null);
+            int imageSize = parent.getContext().getResources().getDimensionPixelSize(
+                    R.dimen.download_manager_image_width);
+            return new ImageViewHolder(view, imageSize);
         }
 
-        // ListItemViewHolder implementation.
+        public ImageViewHolder(View view, int thumbnailSizePx) {
+            super(view, thumbnailSizePx, thumbnailSizePx);
+        }
+
+        // ThumbnailAwareViewHolder implementation.
         @Override
         public void bind(ListPropertyModel properties, ListItem item) {
+            super.bind(properties, item);
             OfflineItemListItem offlineItem = (OfflineItemListItem) item;
-            ((TextView) itemView).setText(offlineItem.item.title);
+            View imageView = itemView.findViewById(R.id.thumbnail);
+            imageView.setContentDescription(offlineItem.item.title);
+
+            itemView.setOnClickListener(
+                    v -> properties.getOpenCallback().onResult(offlineItem.item));
+        }
+
+        @Override
+        void onVisualsChanged(ImageView view, OfflineItemVisuals visuals) {
+            view.setImageBitmap(visuals == null ? null : visuals.icon);
         }
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/password_manager/PasswordGenerationDialogViewHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/password_manager/PasswordGenerationDialogViewHolder.java
index 5bc1f3be..da5b933d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/password_manager/PasswordGenerationDialogViewHolder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/password_manager/PasswordGenerationDialogViewHolder.java
@@ -66,6 +66,7 @@
                 Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
         mSaveExplantaionTextView.setText(explanationSpan);
         mSaveExplantaionTextView.setMovementMethod(LinkMovementMethod.getInstance());
+
         mView = new ModalDialogView(mController, params);
     }
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadActivityTest.java
index a57d2fb..42f0227 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadActivityTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadActivityTest.java
@@ -125,6 +125,7 @@
         HashMap<String, Boolean> features = new HashMap<String, Boolean>();
         features.put(ChromeFeatureList.DOWNLOADS_LOCATION_CHANGE, false);
         features.put(ChromeFeatureList.DOWNLOAD_HOME_SHOW_STORAGE_INFO, false);
+        features.put(ChromeFeatureList.DOWNLOAD_HOME_V2, false);
         ChromeFeatureList.setTestFeatures(features);
 
         mStubbedProvider = new StubbedProvider();
diff --git a/chrome/android/profiles/newest.txt b/chrome/android/profiles/newest.txt
index e083bfd..54d9dcb 100644
--- a/chrome/android/profiles/newest.txt
+++ b/chrome/android/profiles/newest.txt
@@ -1 +1 @@
-chromeos-chrome-amd64-69.0.3493.0_rc-r1.afdo.bz2
\ No newline at end of file
+chromeos-chrome-amd64-69.0.3494.0_rc-r1.afdo.bz2
\ No newline at end of file
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp
index 20261ba..376b7f8d 100644
--- a/chrome/app/chromeos_strings.grdp
+++ b/chrome/app/chromeos_strings.grdp
@@ -196,8 +196,8 @@
   </message>
 
   <!-- File Manager -->
-  <message name="IDS_FILE_BROWSER_ANDROID_FILES_ROOT_LABEL" desc="A label for the 'Play Files' root which shows Android files. 'Play' in this label is an abbreviation of 'Google Play', so it should not be translated.">
-    Play Files
+  <message name="IDS_FILE_BROWSER_ANDROID_FILES_ROOT_LABEL" desc="A label for the 'Play files' root which shows Android files. 'Play' in this label is an abbreviation of 'Google Play', so it should not be translated. Use sentence case.">
+    Play files
   </message>
   <message name="IDS_FILE_BROWSER_SHOW_ALL_ANDROID_FOLDERS_OPTION" desc="A label for an option menu item to show all Android folders. By default, only several folders are visible to users, and users will click this option menu item to show all folders. 'Play' in this label is an abbreviation of 'Google Play', so it should not be translated.">
     Show all Play folders
@@ -253,11 +253,11 @@
   <message name="IDS_FILE_BROWSER_DOWNLOADS_DIRECTORY_LABEL" desc="Downloads local directory label.">
     Downloads
   </message>
-  <message name="IDS_FILE_BROWSER_LINUX_FILES_ROOT_LABEL" desc="A label for the 'Linux Files' root which shows crostini files.">
-    Linux Files
+  <message name="IDS_FILE_BROWSER_LINUX_FILES_ROOT_LABEL" desc="A label for the 'Linux files' root which shows crostini files. Use sentence case.">
+    Linux files
   </message>
-  <message name="IDS_FILE_BROWSER_MY_FILES_ROOT_LABEL" desc="A label for the 'My Files' root which is parent of Downloads, Linux and Android files.">
-    My Files
+  <message name="IDS_FILE_BROWSER_MY_FILES_ROOT_LABEL" desc="A label for the 'My files' root which is parent of Downloads, Linux and Android files. Use sentence case.">
+    My files
   </message>
   <message name="IDS_FILE_BROWSER_MEDIA_VIEW_IMAGES_ROOT_LABEL" desc="A label for the 'Images' root of media views.">
     Images
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp
index 12a13ab..70c84b65 100644
--- a/chrome/app/settings_strings.grdp
+++ b/chrome/app/settings_strings.grdp
@@ -3291,6 +3291,9 @@
     <message name="IDS_SETTINGS_PEOPLE_LOCK_SCREEN_ENABLE_FINGERPRINT_CHECKBOX_LABEL" desc="The text on the label of the checkbox which allows users to enable or disable fingerprint usage.">
       Enable fingerprint unlock
     </message>
+    <message name="IDS_SETTINGS_ACCOUNT_MANAGER_ADD_ACCOUNT_LABEL" desc="Label of the Add account button in Account Manager.">
+      Add account
+    </message>
     <message name="IDS_SETTINGS_ACCOUNT_MANAGER_DESCRIPTION" desc="Description of the Account Manager Settings page. Shown just below the title of the page.">
       All of your signed in Google accounts from apps and websites can be managed here.
     </message>
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 6896f9f98..8402031 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -1151,6 +1151,8 @@
     "prefs/origin_trial_prefs.h",
     "prefs/pref_metrics_service.cc",
     "prefs/pref_metrics_service.h",
+    "prefs/pref_service_incognito_whitelist.cc",
+    "prefs/pref_service_incognito_whitelist.h",
     "prefs/pref_service_syncable_util.cc",
     "prefs/pref_service_syncable_util.h",
     "prefs/profile_pref_store_manager.cc",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 94cd53ab..1481c102 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -3001,10 +3001,12 @@
      ENABLE_DISABLE_VALUE_TYPE(
          chromeos::switches::kEnableFileManagerTouchMode,
          chromeos::switches::kDisableFileManagerTouchMode)},
-    {"show-android-files-in-files-app",
+    {"android-files-in-files-app",
      flag_descriptions::kShowAndroidFilesInFilesAppName,
      flag_descriptions::kShowAndroidFilesInFilesAppDescription, kOsCrOS,
-     SINGLE_VALUE_TYPE(chromeos::switches::kShowAndroidFilesInFilesApp)},
+     ENABLE_DISABLE_VALUE_TYPE(
+         chromeos::switches::kShowAndroidFilesInFilesApp,
+         chromeos::switches::kHideAndroidFilesInFilesApp)},
     {"disable-my-files-navigation",
      flag_descriptions::kFilesAppDisableMyFilesNavigationName,
      flag_descriptions::kFilesAppDisableMyFilesNavigationDescription, kOsCrOS,
@@ -3530,6 +3532,11 @@
      FEATURE_VALUE_TYPE(chrome::android::kDownloadProgressInfoBar)},
 #endif  // defined(OS_ANDROID)
 
+#if defined(OS_ANDROID)
+    {"download-home-v2", flag_descriptions::kDownloadHomeV2Name,
+     flag_descriptions::kDownloadHomeV2Description, kOsAndroid,
+     FEATURE_VALUE_TYPE(chrome::android::kDownloadHomeV2)},
+#endif
     {"enable-block-tab-unders", flag_descriptions::kBlockTabUndersName,
      flag_descriptions::kBlockTabUndersDescription, kOsAll,
      FEATURE_VALUE_TYPE(TabUnderNavigationThrottle::kBlockTabUnders)},
diff --git a/chrome/browser/android/chrome_feature_list.cc b/chrome/browser/android/chrome_feature_list.cc
index 59762341..cf36716d 100644
--- a/chrome/browser/android/chrome_feature_list.cc
+++ b/chrome/browser/android/chrome_feature_list.cc
@@ -97,6 +97,7 @@
     &kCustomFeedbackUi,
     &kDontPrefetchLibraries,
     &kDownloadProgressInfoBar,
+    &kDownloadHomeV2,
     &kDownloadHomeShowStorageInfo,
     &data_reduction_proxy::features::kDataReductionMainMenu,
     &kExploreSites,
@@ -270,6 +271,9 @@
 const base::Feature kDownloadProgressInfoBar{"DownloadProgressInfoBar",
                                              base::FEATURE_DISABLED_BY_DEFAULT};
 
+const base::Feature kDownloadHomeV2{"DownloadHomeV2",
+                                    base::FEATURE_DISABLED_BY_DEFAULT};
+
 const base::Feature kDownloadHomeShowStorageInfo{
     "DownloadHomeShowStorageInfo", base::FEATURE_DISABLED_BY_DEFAULT};
 
diff --git a/chrome/browser/android/chrome_feature_list.h b/chrome/browser/android/chrome_feature_list.h
index ad96f313..825bc4dd 100644
--- a/chrome/browser/android/chrome_feature_list.h
+++ b/chrome/browser/android/chrome_feature_list.h
@@ -44,6 +44,7 @@
 extern const base::Feature kDontPrefetchLibraries;
 extern const base::Feature kDownloadAutoResumptionThrottling;
 extern const base::Feature kDownloadProgressInfoBar;
+extern const base::Feature kDownloadHomeV2;
 extern const base::Feature kDownloadHomeShowStorageInfo;
 extern const base::Feature kExploreSites;
 extern const base::Feature kFullscreenActivity;
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index e0946c0..e040c2b5 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -90,6 +90,7 @@
 #include "chrome/browser/renderer_host/chrome_navigation_ui_data.h"
 #include "chrome/browser/renderer_host/chrome_render_message_filter.h"
 #include "chrome/browser/renderer_host/pepper/chrome_browser_pepper_host_factory.h"
+#include "chrome/browser/renderer_preferences_util.h"
 #include "chrome/browser/resource_coordinator/background_tab_navigation_throttle.h"
 #include "chrome/browser/resource_coordinator/chrome_browser_main_extra_parts_resource_coordinator.h"
 #include "chrome/browser/safe_browsing/certificate_reporting_service.h"
@@ -240,6 +241,7 @@
 #include "content/public/common/content_descriptors.h"
 #include "content/public/common/content_features.h"
 #include "content/public/common/content_switches.h"
+#include "content/public/common/renderer_preferences.h"
 #include "content/public/common/service_manager_connection.h"
 #include "content/public/common/service_names.mojom.h"
 #include "content/public/common/url_constants.h"
@@ -2189,6 +2191,15 @@
   return prefs && prefs->GetBoolean(prefs::kDataSaverEnabled);
 }
 
+void ChromeContentBrowserClient::UpdateRendererPreferencesForWorker(
+    content::BrowserContext* browser_context,
+    content::RendererPreferences* out_prefs) {
+  DCHECK(browser_context);
+  DCHECK(out_prefs);
+  renderer_preferences_util::UpdateFromSystemSettings(
+      out_prefs, Profile::FromBrowserContext(browser_context));
+}
+
 void ChromeContentBrowserClient::NavigationRequestStarted(
     int frame_tree_node_id,
     const GURL& url,
diff --git a/chrome/browser/chrome_content_browser_client.h b/chrome/browser/chrome_content_browser_client.h
index ff1be12..ce52ee0 100644
--- a/chrome/browser/chrome_content_browser_client.h
+++ b/chrome/browser/chrome_content_browser_client.h
@@ -167,6 +167,9 @@
   std::string GetAcceptLangs(content::BrowserContext* context) override;
   const gfx::ImageSkia* GetDefaultFavicon() override;
   bool IsDataSaverEnabled(content::BrowserContext* context) override;
+  void UpdateRendererPreferencesForWorker(
+      content::BrowserContext* browser_context,
+      content::RendererPreferences* out_prefs) override;
   void NavigationRequestStarted(
       int frame_tree_node_id,
       const GURL& url,
diff --git a/chrome/browser/chromeos/crostini/crostini_manager.cc b/chrome/browser/chromeos/crostini/crostini_manager.cc
index cb8e620..520587e 100644
--- a/chrome/browser/chromeos/crostini/crostini_manager.cc
+++ b/chrome/browser/chromeos/crostini/crostini_manager.cc
@@ -773,6 +773,34 @@
                      weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
 }
 
+void CrostiniManager::InstallLinuxPackage(
+    Profile* profile,
+    std::string vm_name,
+    std::string container_name,
+    std::string package_path,
+    InstallLinuxPackageCallback callback) {
+  if (!GetCiceroneClient()->IsInstallLinuxPackageProgressSignalConnected()) {
+    // Technically we could still start the install, but we wouldn't be able to
+    // detect when the install completes, successfully or otherwise.
+    LOG(ERROR)
+        << "Attempted to install package when progress signal not connected.";
+    std::move(callback).Run(ConciergeClientResult::INSTALL_LINUX_PACKAGE_FAILED,
+                            std::string());
+    return;
+  }
+
+  vm_tools::cicerone::InstallLinuxPackageRequest request;
+  request.set_owner_id(CryptohomeIdForProfile(profile));
+  request.set_vm_name(std::move(vm_name));
+  request.set_container_name(std::move(container_name));
+  request.set_file_path(std::move(package_path));
+
+  GetCiceroneClient()->InstallLinuxPackage(
+      std::move(request),
+      base::BindOnce(&CrostiniManager::OnInstallLinuxPackage,
+                     weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
+}
+
 void CrostiniManager::GetContainerSshKeys(
     std::string vm_name,
     std::string container_name,
@@ -880,6 +908,28 @@
       std::move(shutdown_callback));
 }
 
+void CrostiniManager::AddInstallLinuxPackageProgressObserver(
+    Profile* profile,
+    InstallLinuxPackageProgressObserver* observer) {
+  install_linux_package_progress_observers_.emplace(
+      CryptohomeIdForProfile(profile), observer);
+}
+
+void CrostiniManager::RemoveInstallLinuxPackageProgressObserver(
+    Profile* profile,
+    InstallLinuxPackageProgressObserver* observer) {
+  auto range = install_linux_package_progress_observers_.equal_range(
+      CryptohomeIdForProfile(profile));
+  for (auto it = range.first; it != range.second; ++it) {
+    if (it->second != observer) {
+      install_linux_package_progress_observers_.erase(it);
+      return;
+    }
+  }
+
+  NOTREACHED();
+}
+
 void CrostiniManager::OnCreateDiskImage(
     CreateDiskImageCallback callback,
     base::Optional<vm_tools::concierge::CreateDiskImageResponse> reply) {
@@ -1061,6 +1111,41 @@
   shutdown_container_callbacks_.erase(range.first, range.second);
 }
 
+void CrostiniManager::OnInstallLinuxPackageProgress(
+    const vm_tools::cicerone::InstallLinuxPackageProgressSignal& signal) {
+  if (signal.progress_percent() < 0 || signal.progress_percent() > 100) {
+    LOG(ERROR) << "Received install progress with invalid progress of "
+               << signal.progress_percent() << "%.";
+    return;
+  }
+
+  InstallLinuxPackageProgressStatus status;
+  switch (signal.status()) {
+    case vm_tools::cicerone::InstallLinuxPackageProgressSignal::SUCCEEDED:
+      status = InstallLinuxPackageProgressStatus::SUCCEEDED;
+      break;
+    case vm_tools::cicerone::InstallLinuxPackageProgressSignal::FAILED:
+      status = InstallLinuxPackageProgressStatus::FAILED;
+      break;
+    case vm_tools::cicerone::InstallLinuxPackageProgressSignal::DOWNLOADING:
+      status = InstallLinuxPackageProgressStatus::DOWNLOADING;
+      break;
+    case vm_tools::cicerone::InstallLinuxPackageProgressSignal::INSTALLING:
+      status = InstallLinuxPackageProgressStatus::INSTALLING;
+      break;
+    default:
+      NOTREACHED();
+  }
+
+  auto range =
+      install_linux_package_progress_observers_.equal_range(signal.owner_id());
+  for (auto it = range.first; it != range.second; ++it) {
+    it->second->OnInstallLinuxPackageProgress(
+        signal.vm_name(), signal.container_name(), status,
+        signal.progress_percent(), signal.failure_details());
+  }
+}
+
 void CrostiniManager::OnLaunchContainerApplication(
     LaunchContainerApplicationCallback callback,
     base::Optional<vm_tools::cicerone::LaunchContainerApplicationResponse>
@@ -1101,6 +1186,39 @@
   std::move(callback).Run(ConciergeClientResult::SUCCESS, icons);
 }
 
+void CrostiniManager::OnInstallLinuxPackage(
+    InstallLinuxPackageCallback callback,
+    base::Optional<vm_tools::cicerone::InstallLinuxPackageResponse> reply) {
+  if (!reply.has_value()) {
+    LOG(ERROR) << "Failed to install Linux package. Empty response.";
+    std::move(callback).Run(
+        ConciergeClientResult::LAUNCH_CONTAINER_APPLICATION_FAILED,
+        std::string());
+    return;
+  }
+  vm_tools::cicerone::InstallLinuxPackageResponse response = reply.value();
+
+  if (response.status() ==
+      vm_tools::cicerone::InstallLinuxPackageResponse::FAILED) {
+    LOG(ERROR) << "Failed to install Linux package: "
+               << response.failure_reason();
+    std::move(callback).Run(ConciergeClientResult::INSTALL_LINUX_PACKAGE_FAILED,
+                            response.failure_reason());
+    return;
+  }
+
+  if (response.status() ==
+      vm_tools::cicerone::InstallLinuxPackageResponse::INSTALL_ALREADY_ACTIVE) {
+    LOG(WARNING) << "Failed to install Linux package, install already active.";
+    std::move(callback).Run(
+        ConciergeClientResult::INSTALL_LINUX_PACKAGE_ALREADY_ACTIVE,
+        std::string());
+    return;
+  }
+
+  std::move(callback).Run(ConciergeClientResult::SUCCESS, std::string());
+}
+
 void CrostiniManager::OnGetContainerSshKeys(
     GetContainerSshKeysCallback callback,
     base::Optional<vm_tools::concierge::ContainerSshKeysResponse> reply) {
diff --git a/chrome/browser/chromeos/crostini/crostini_manager.h b/chrome/browser/chromeos/crostini/crostini_manager.h
index 916e1a4..ad58613 100644
--- a/chrome/browser/chromeos/crostini/crostini_manager.h
+++ b/chrome/browser/chromeos/crostini/crostini_manager.h
@@ -41,9 +41,18 @@
   DISK_TYPE_ERROR,
   CONTAINER_START_FAILED,
   LAUNCH_CONTAINER_APPLICATION_FAILED,
+  INSTALL_LINUX_PACKAGE_FAILED,
+  INSTALL_LINUX_PACKAGE_ALREADY_ACTIVE,
   UNKNOWN_ERROR,
 };
 
+enum class InstallLinuxPackageProgressStatus {
+  SUCCEEDED,
+  FAILED,
+  DOWNLOADING,
+  INSTALLING,
+};
+
 // Return type when getting app icons from within a container.
 struct Icon {
   std::string desktop_file_id;
@@ -52,6 +61,21 @@
   std::string content;
 };
 
+class InstallLinuxPackageProgressObserver {
+ public:
+  // A successfully started package install will continually fire progress
+  // events until it returns a status of SUCCEEDED or FAILED. The
+  // |progress_percent| field is given as a percentage of the given step,
+  // DOWNLOADING or INSTALLING. |failure_reason| is returned from the container
+  // for a FAILED case, and not necessarily localized.
+  virtual void OnInstallLinuxPackageProgress(
+      const std::string& vm_name,
+      const std::string& container_name,
+      InstallLinuxPackageProgressStatus status,
+      int progress_percent,
+      const std::string& failure_reason) = 0;
+};
+
 // CrostiniManager is a singleton which is used to check arguments for
 // ConciergeClient and CiceroneClient. ConciergeClient is dedicated to
 // communication with the Concierge service, CiceroneClient is dedicated to
@@ -94,6 +118,12 @@
   using GetContainerAppIconsCallback =
       base::OnceCallback<void(ConciergeClientResult result,
                               std::vector<Icon>& icons)>;
+  // The type of the callback for CrostiniManager::InstallLinuxPackage.
+  // |failure_reason| is returned from the container upon failure
+  // (INSTALL_LINUX_PACKAGE_FAILED), and not necessarily localized.
+  using InstallLinuxPackageCallback =
+      base::OnceCallback<void(ConciergeClientResult result,
+                              const std::string& failure_reason)>;
   // The type of the callback for CrostiniManager::GetContainerSshKeys.
   using GetContainerSshKeysCallback =
       base::OnceCallback<void(ConciergeClientResult result,
@@ -212,6 +242,15 @@
                             int scale,
                             GetContainerAppIconsCallback callback);
 
+  // Begin installation of a Linux Package inside the container. If the
+  // installation is successfully started, further updates will be sent to
+  // added InstallLinuxPackageProgressObservers.
+  void InstallLinuxPackage(Profile* profile,
+                           std::string vm_name,
+                           std::string container_name,
+                           std::string package_path,
+                           InstallLinuxPackageCallback callback);
+
   // Asynchronously gets SSH server public key of container and trusted SSH
   // client private key which can be used to connect to the container.
   // |callback| is called after the method call finishes.
@@ -259,6 +298,14 @@
       std::string container_name,
       ShutdownContainerCallback shutdown_callback);
 
+  // Add/remove observers for package install progress.
+  void AddInstallLinuxPackageProgressObserver(
+      Profile* profile,
+      InstallLinuxPackageProgressObserver* observer);
+  void RemoveInstallLinuxPackageProgressObserver(
+      Profile* profile,
+      InstallLinuxPackageProgressObserver* observer);
+
   // ConciergeClient::Observer:
   void OnContainerStartupFailed(
       const vm_tools::concierge::ContainerStartedSignal& signal) override;
@@ -268,6 +315,9 @@
       const vm_tools::cicerone::ContainerStartedSignal& signal) override;
   void OnContainerShutdown(
       const vm_tools::cicerone::ContainerShutdownSignal& signal) override;
+  void OnInstallLinuxPackageProgress(
+      const vm_tools::cicerone::InstallLinuxPackageProgressSignal& signal)
+      override;
 
   void RemoveCrostini(Profile* profile,
                       std::string vm_name,
@@ -350,6 +400,11 @@
       GetContainerAppIconsCallback callback,
       base::Optional<vm_tools::cicerone::ContainerAppIconResponse> reply);
 
+  // Callback for CrostiniManager::InstallLinuxPackage.
+  void OnInstallLinuxPackage(
+      InstallLinuxPackageCallback callback,
+      base::Optional<vm_tools::cicerone::InstallLinuxPackageResponse> reply);
+
   // Callback for CrostiniManager::GetContainerSshKeys. Called after the
   // Concierge service finishes.
   void OnGetContainerSshKeys(
@@ -384,6 +439,10 @@
   std::multimap<std::pair<std::string, std::string>, std::string>
       running_containers_;
 
+  // Keyed by owner_id.
+  std::multimap<std::string, InstallLinuxPackageProgressObserver*>
+      install_linux_package_progress_observers_;
+
   // Note: This should remain the last member so it'll be destroyed and
   // invalidate its weak pointers before any other members are destroyed.
   base::WeakPtrFactory<CrostiniManager> weak_ptr_factory_;
diff --git a/chrome/browser/chromeos/crostini/crostini_manager_unittest.cc b/chrome/browser/chromeos/crostini/crostini_manager_unittest.cc
index abb9d2b..3a2770b 100644
--- a/chrome/browser/chromeos/crostini/crostini_manager_unittest.cc
+++ b/chrome/browser/chromeos/crostini/crostini_manager_unittest.cc
@@ -108,6 +108,16 @@
     std::move(closure).Run();
   }
 
+  void InstallLinuxPackageCallback(base::OnceClosure closure,
+                                   ConciergeClientResult expected_result,
+                                   const std::string& expected_failure_reason,
+                                   ConciergeClientResult result,
+                                   const std::string& failure_reason) {
+    EXPECT_EQ(expected_result, result);
+    EXPECT_EQ(expected_failure_reason, failure_reason);
+    std::move(closure).Run();
+  }
+
   CrostiniManagerTest()
       : fake_cicerone_client_(new chromeos::FakeCiceroneClient()),
         fake_concierge_client_(new chromeos::FakeConciergeClient()),
@@ -367,6 +377,45 @@
   run_loop()->Run();
 }
 
+TEST_F(CrostiniManagerTest, InstallLinuxPackageSignalNotConnectedError) {
+  fake_cicerone_client_->set_install_linux_package_progress_signal_connected(
+      false);
+  CrostiniManager::GetInstance()->InstallLinuxPackage(
+      profile(), kVmName, kContainerName, "/tmp/package.deb",
+      base::BindOnce(&CrostiniManagerTest::InstallLinuxPackageCallback,
+                     base::Unretained(this), run_loop()->QuitClosure(),
+                     ConciergeClientResult::INSTALL_LINUX_PACKAGE_FAILED,
+                     std::string()));
+  run_loop()->Run();
+}
+
+TEST_F(CrostiniManagerTest, InstallLinuxPackageSignalSuccess) {
+  vm_tools::cicerone::InstallLinuxPackageResponse response;
+  response.set_status(vm_tools::cicerone::InstallLinuxPackageResponse::STARTED);
+  fake_cicerone_client_->set_install_linux_package_response(response);
+  CrostiniManager::GetInstance()->InstallLinuxPackage(
+      profile(), kVmName, kContainerName, "/tmp/package.deb",
+      base::BindOnce(&CrostiniManagerTest::InstallLinuxPackageCallback,
+                     base::Unretained(this), run_loop()->QuitClosure(),
+                     ConciergeClientResult::SUCCESS, std::string()));
+  run_loop()->Run();
+}
+
+TEST_F(CrostiniManagerTest, InstallLinuxPackageSignalFailure) {
+  vm_tools::cicerone::InstallLinuxPackageResponse response;
+  std::string failure_reason = "Unit tests can't install Linux packages!";
+  response.set_status(vm_tools::cicerone::InstallLinuxPackageResponse::FAILED);
+  response.set_failure_reason(failure_reason);
+  fake_cicerone_client_->set_install_linux_package_response(response);
+  CrostiniManager::GetInstance()->InstallLinuxPackage(
+      profile(), kVmName, kContainerName, "/tmp/package.deb",
+      base::BindOnce(&CrostiniManagerTest::InstallLinuxPackageCallback,
+                     base::Unretained(this), run_loop()->QuitClosure(),
+                     ConciergeClientResult::INSTALL_LINUX_PACKAGE_FAILED,
+                     failure_reason));
+  run_loop()->Run();
+}
+
 class CrostiniManagerRestartTest : public CrostiniManagerTest,
                                    public CrostiniManager::RestartObserver {
  public:
diff --git a/chrome/browser/chromeos/drive/drive_integration_service.cc b/chrome/browser/chromeos/drive/drive_integration_service.cc
index dbea63a..f5e76c5f0 100644
--- a/chrome/browser/chromeos/drive/drive_integration_service.cc
+++ b/chrome/browser/chromeos/drive/drive_integration_service.cc
@@ -276,6 +276,10 @@
         ->GetAccountId();
   }
 
+  void OnMountFailed(base::Optional<base::TimeDelta> remount_delay) override {
+    on_drivefs_unmounted_.Run(std::move(remount_delay));
+  }
+
   void OnMounted(const base::FilePath& path) override {
     on_drivefs_mounted_.Run();
   }
diff --git a/chrome/browser/chromeos/file_manager/volume_manager.cc b/chrome/browser/chromeos/file_manager/volume_manager.cc
index 0af201c..1ff1df2 100644
--- a/chrome/browser/chromeos/file_manager/volume_manager.cc
+++ b/chrome/browser/chromeos/file_manager/volume_manager.cc
@@ -76,11 +76,11 @@
                                           path);
 }
 
-// Returns true if the flag to show Android files
-// (--show-android-files-in-files-app) is enabled.
+// Returns true if the "Play files" root should be shown based on the current
+// flag settings (chrome://flags/#android-files-in-files-app).
 bool IsShowAndroidFilesEnabled() {
-  return base::CommandLine::ForCurrentProcess()->HasSwitch(
-      chromeos::switches::kShowAndroidFilesInFilesApp);
+  return !base::CommandLine::ForCurrentProcess()->HasSwitch(
+      chromeos::switches::kHideAndroidFilesInFilesApp);
 }
 
 // Registers a mount point for Android files to ExternalMountPoints.
diff --git a/chrome/browser/content_settings/content_settings_pref_provider_unittest.cc b/chrome/browser/content_settings/content_settings_pref_provider_unittest.cc
index 7200ee2..a3691e9 100644
--- a/chrome/browser/content_settings/content_settings_pref_provider_unittest.cc
+++ b/chrome/browser/content_settings/content_settings_pref_provider_unittest.cc
@@ -364,9 +364,12 @@
             TestUtils::GetContentSetting(&pref_content_settings_provider, host,
                                          host, CONTENT_SETTINGS_TYPE_PLUGINS,
                                          resource1, false));
-  pref_content_settings_provider.SetWebsiteSetting(
-      pattern, pattern, CONTENT_SETTINGS_TYPE_PLUGINS, resource1,
-      new base::Value(CONTENT_SETTING_BLOCK));
+  std::unique_ptr<base::Value> value(new base::Value(CONTENT_SETTING_BLOCK));
+  if (pref_content_settings_provider.SetWebsiteSetting(
+          pattern, pattern, CONTENT_SETTINGS_TYPE_PLUGINS, resource1,
+          value.get())) {
+    value.release();
+  }
 
   bool flash_is_ephemeral =
       ContentSettingsRegistry::GetInstance()
@@ -501,12 +504,20 @@
                              ResourceIdentifier(), value->DeepCopy());
 #if BUILDFLAG(ENABLE_PLUGINS)
   // Non-empty pattern, plugins, non-empty resource identifier.
-  provider.SetWebsiteSetting(pattern, wildcard, CONTENT_SETTINGS_TYPE_PLUGINS,
-                             res_id, value->DeepCopy());
+  std::unique_ptr<base::Value> value_copy(value->DeepCopy());
+  if (provider.SetWebsiteSetting(pattern, wildcard,
+                                 CONTENT_SETTINGS_TYPE_PLUGINS, res_id,
+                                 value_copy.get())) {
+    value_copy.release();
+  }
 
   // Empty pattern, plugins, non-empty resource identifier.
-  provider.SetWebsiteSetting(wildcard, wildcard, CONTENT_SETTINGS_TYPE_PLUGINS,
-                             res_id, value->DeepCopy());
+  value_copy.reset(value->DeepCopy());
+  if (provider.SetWebsiteSetting(wildcard, wildcard,
+                                 CONTENT_SETTINGS_TYPE_PLUGINS, res_id,
+                                 value_copy.get())) {
+    value_copy.release();
+  }
 #endif
   // Non-empty pattern, syncable, empty resource identifier.
   provider.SetWebsiteSetting(pattern, wildcard, CONTENT_SETTINGS_TYPE_COOKIES,
diff --git a/chrome/browser/extensions/forced_extensions/installation_tracker.cc b/chrome/browser/extensions/forced_extensions/installation_tracker.cc
index 80db14f..730dfc1 100644
--- a/chrome/browser/extensions/forced_extensions/installation_tracker.cc
+++ b/chrome/browser/extensions/forced_extensions/installation_tracker.cc
@@ -56,12 +56,9 @@
   if (!value || value->empty())
     return;
 
-  std::unique_ptr<ExtensionSet> installed_extensions =
-      registry_->GenerateInstalledExtensionsSet();
-
   for (const auto& entry : *value) {
     forced_extensions_.insert(entry.first);
-    if (!installed_extensions->Contains(entry.first))
+    if (!registry_->enabled_extensions().Contains(entry.first))
       pending_forced_extensions_.insert(entry.first);
   }
   if (pending_forced_extensions_.empty())
@@ -85,8 +82,17 @@
       UMA_HISTOGRAM_LONG_TIMES("Extensions.ForceInstalledLoadTime",
                                base::Time::Now() - start_time_);
     } else {
+      size_t enabled_missing_count = pending_forced_extensions_.size();
+      auto installed_extensions = registry_->GenerateInstalledExtensionsSet();
+      for (const auto& entry : *installed_extensions)
+        pending_forced_extensions_.erase(entry->id());
+      size_t installed_missing_count = pending_forced_extensions_.size();
+
       UMA_HISTOGRAM_COUNTS_100("Extensions.ForceInstalledTimedOutCount",
-                               pending_forced_extensions_.size());
+                               enabled_missing_count);
+      UMA_HISTOGRAM_COUNTS_100(
+          "Extensions.ForceInstalledTimedOutAndNotInstalledCount",
+          installed_missing_count);
     }
   }
   reported_ = true;
diff --git a/chrome/browser/extensions/forced_extensions/installation_tracker_unittest.cc b/chrome/browser/extensions/forced_extensions/installation_tracker_unittest.cc
index 2094b6d..a56ee3b 100644
--- a/chrome/browser/extensions/forced_extensions/installation_tracker_unittest.cc
+++ b/chrome/browser/extensions/forced_extensions/installation_tracker_unittest.cc
@@ -27,6 +27,8 @@
 
 constexpr char kLoadTimeStats[] = "Extensions.ForceInstalledLoadTime";
 constexpr char kTimedOutStats[] = "Extensions.ForceInstalledTimedOutCount";
+constexpr char kTimedOutNotInstalledStats[] =
+    "Extensions.ForceInstalledTimedOutAndNotInstalledCount";
 }  // namespace
 
 namespace extensions {
@@ -74,15 +76,19 @@
   tracker_->OnExtensionLoaded(&profile_, ext2.get());
   histogram_tester_.ExpectTotalCount(kLoadTimeStats, 1);
   histogram_tester_.ExpectTotalCount(kTimedOutStats, 0);
+  histogram_tester_.ExpectTotalCount(kTimedOutNotInstalledStats, 0);
 }
 
 TEST_F(ForcedExtensionsInstallationTrackerTest,
        ExtensionsInstallationTimedOut) {
   SetupForceList();
+  auto ext1 = ExtensionBuilder(kExtensionName1).SetID(kExtensionId1).Build();
+  registry_->AddEnabled(ext1.get());
   EXPECT_TRUE(fake_timer_->IsRunning());
   fake_timer_->Fire();
   histogram_tester_.ExpectTotalCount(kLoadTimeStats, 0);
   histogram_tester_.ExpectUniqueSample(kTimedOutStats, 2, 1);
+  histogram_tester_.ExpectUniqueSample(kTimedOutNotInstalledStats, 1, 1);
 }
 
 TEST_F(ForcedExtensionsInstallationTrackerTest, NoExtensionsConfigured) {
@@ -90,6 +96,7 @@
   fake_timer_->Fire();
   histogram_tester_.ExpectTotalCount(kLoadTimeStats, 0);
   histogram_tester_.ExpectTotalCount(kTimedOutStats, 0);
+  histogram_tester_.ExpectTotalCount(kTimedOutNotInstalledStats, 0);
 }
 
 }  // namespace extensions
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index dc8cea4..25b1b0d 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -2207,6 +2207,10 @@
 const char kDownloadProgressInfoBarDescription[] =
     "Enables an infobar notifying users about status of current downloads.";
 
+const char kDownloadHomeV2Name[] = "Enable download home v2";
+const char kDownloadHomeV2Description[] =
+    "Enables the new UI for download home";
+
 const char kEnableAndroidPayIntegrationV1Name[] = "Enable Android Pay v1";
 const char kEnableAndroidPayIntegrationV1Description[] =
     "Enable integration with Android Pay using the first version of the API";
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index 076d6e6..51d7b92 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -1346,6 +1346,9 @@
 extern const char kDownloadProgressInfoBarName[];
 extern const char kDownloadProgressInfoBarDescription[];
 
+extern const char kDownloadHomeV2Name[];
+extern const char kDownloadHomeV2Description[];
+
 extern const char kEnableAndroidPayIntegrationV1Name[];
 extern const char kEnableAndroidPayIntegrationV1Description[];
 
diff --git a/chrome/browser/media/webrtc/webrtc_event_log_manager_unittest.cc b/chrome/browser/media/webrtc/webrtc_event_log_manager_unittest.cc
index 6f3ac11..ba89a8ab 100644
--- a/chrome/browser/media/webrtc/webrtc_event_log_manager_unittest.cc
+++ b/chrome/browser/media/webrtc/webrtc_event_log_manager_unittest.cc
@@ -905,7 +905,7 @@
   WebRtcEventLogManagerTestBase* const test_;
 };
 
-#if defined(OS_POSIX) && !defined(OS_FUCHSIA)
+#if defined(OS_POSIX)
 void RemoveWritePermissionsFromDirectory(const base::FilePath& path) {
   int permissions;
   ASSERT_TRUE(base::GetPosixFilePermissions(path, &permissions));
@@ -915,7 +915,7 @@
   permissions &= ~write_permissions;
   ASSERT_TRUE(base::SetPosixFilePermissions(path, permissions));
 }
-#endif  // defined(OS_POSIX) && !defined(OS_FUCHSIA)
+#endif  // defined(OS_POSIX)
 
 // The factory for the following fake uploader produces a sequence of uploaders
 // which fail the test if given a file other than that which they expect. The
@@ -1468,7 +1468,7 @@
   EXPECT_TRUE(base::IsDirectoryEmpty(local_logs_base_dir_.GetPath()));
 }
 
-#if defined(OS_POSIX) && !defined(OS_FUCHSIA)
+#if defined(OS_POSIX)
 TEST_F(WebRtcEventLogManagerTest, LocalLogLegalPathWithoutPermissionsSanity) {
   RemoveWritePermissionsFromDirectory(local_logs_base_dir_.GetPath());
 
@@ -1496,7 +1496,7 @@
   EXPECT_TRUE(DisableLocalLogging());
   EXPECT_TRUE(base::IsDirectoryEmpty(local_logs_base_dir_.GetPath()));
 }
-#endif  // defined(OS_POSIX) && !defined(OS_FUCHSIA)
+#endif  // defined(OS_POSIX)
 
 TEST_F(WebRtcEventLogManagerTest, LocalLogEmptyStringHandledGracefully) {
   const auto key = GetPeerConnectionKey(rph_.get(), kLid);
@@ -2109,7 +2109,7 @@
             std::make_pair(false, true));
 }
 
-#if defined(OS_POSIX) && !defined(OS_FUCHSIA)
+#if defined(OS_POSIX)
 // TODO(crbug.com/775415): Add unit tests for lacking read permissions when
 // looking to upload the file.
 TEST_F(WebRtcEventLogManagerTest,
@@ -2174,7 +2174,7 @@
             std::make_pair(false, false));
   EXPECT_TRUE(base::IsDirectoryEmpty(remote_logs_path));
 }
-#endif  // defined(OS_POSIX) && !defined(OS_FUCHSIA)
+#endif  // defined(OS_POSIX)
 
 TEST_F(WebRtcEventLogManagerTest, RemoteLogLimitActiveLogFiles) {
   for (int i = 0; i < kMaxActiveRemoteLogFiles + 1; ++i) {
@@ -2592,7 +2592,7 @@
       std::accumulate(std::begin(logs), std::end(logs), std::string()));
 }
 
-#if defined(OS_POSIX) && !defined(OS_FUCHSIA)
+#if defined(OS_POSIX)
 TEST_F(WebRtcEventLogManagerTest,
        UnopenedRemoteLogFilesNotCountedTowardsActiveLogsLimit) {
   TestingProfile* browser_contexts[2];
@@ -2632,7 +2632,7 @@
                                    GetUniqueId(with_permissions_key)));
   }
 }
-#endif  // defined(OS_POSIX) && !defined(OS_FUCHSIA)
+#endif  // defined(OS_POSIX)
 
 TEST_F(WebRtcEventLogManagerTest,
        NoStartWebRtcSendingEventLogsWhenLocalEnabledWithoutPeerConnection) {
diff --git a/chrome/browser/media/webrtc/webrtc_event_log_uploader_impl_unittest.cc b/chrome/browser/media/webrtc/webrtc_event_log_uploader_impl_unittest.cc
index b819f8f..e99ed88 100644
--- a/chrome/browser/media/webrtc/webrtc_event_log_uploader_impl_unittest.cc
+++ b/chrome/browser/media/webrtc/webrtc_event_log_uploader_impl_unittest.cc
@@ -49,7 +49,7 @@
   base::OnceClosure on_complete_callback_;
 };
 
-#if defined(OS_POSIX) && !defined(OS_FUCHSIA)
+#if defined(OS_POSIX)
 void RemovePermissions(const base::FilePath& path, int removed_permissions) {
   int permissions;
   ASSERT_TRUE(base::GetPosixFilePermissions(path, &permissions));
@@ -70,7 +70,7 @@
                                     base::FILE_PERMISSION_WRITE_BY_OTHERS;
   RemovePermissions(path, write_permissions);
 }
-#endif  // defined(OS_POSIX) && !defined(OS_FUCHSIA)
+#endif  // defined(OS_POSIX)
 }  // namespace
 
 class WebRtcEventLogUploaderImplTest : public ::testing::Test {
@@ -245,7 +245,7 @@
   EXPECT_FALSE(base::PathExists(log_file_));
 }
 
-#if defined(OS_POSIX) && !defined(OS_FUCHSIA)
+#if defined(OS_POSIX)
 TEST_F(WebRtcEventLogUploaderImplTest, FailureToReadFileReportedToObserver) {
   UseFakeUrlFetcherFactory();
 
@@ -291,7 +291,7 @@
   // Cleaup
   ASSERT_TRUE(base::SetPosixFilePermissions(logs_dir, permissions));
 }
-#endif  // defined(OS_POSIX) && !defined(OS_FUCHSIA)
+#endif  // defined(OS_POSIX)
 
 TEST_F(WebRtcEventLogUploaderImplTest, FilesUpToMaxSizeUploaded) {
   UseFakeUrlFetcherFactory();
diff --git a/chrome/browser/password_manager/password_manager_interactive_test_base.cc b/chrome/browser/password_manager/password_manager_interactive_test_base.cc
index cc15f49..2365888e 100644
--- a/chrome/browser/password_manager/password_manager_interactive_test_base.cc
+++ b/chrome/browser/password_manager/password_manager_interactive_test_base.cc
@@ -36,6 +36,8 @@
                               ui::DomCodeToUsLayoutKeyboardCode(dom_code),
                               false, shift, false, false);
   }
+  // Execute an empty script to sync the pressed keys for an upcoming JS.
+  ASSERT_TRUE(content::ExecuteScript(RenderFrameHost(), ";"));
 }
 
 void PasswordManagerInteractiveTestBase::VerifyPasswordIsSavedAndFilled(
diff --git a/chrome/browser/password_manager/password_manager_interactive_uitest.cc b/chrome/browser/password_manager/password_manager_interactive_uitest.cc
index fd376b5..f7ee8ab 100644
--- a/chrome/browser/password_manager/password_manager_interactive_uitest.cc
+++ b/chrome/browser/password_manager/password_manager_interactive_uitest.cc
@@ -281,7 +281,7 @@
 // Tests that if a site embeds the login and signup forms into one <form>, the
 // login form still gets autofilled.
 IN_PROC_BROWSER_TEST_P(PasswordManagerBrowserTestWithConditionalPopupViews,
-                       DISABLED_AutofillLoginSignupForm) {
+                       AutofillLoginSignupForm) {
   std::string submit = "document.getElementById('submit').click();";
   VerifyPasswordIsSavedAndFilled("/password/login_signup_form.html", "username",
                                  "password", submit);
@@ -291,7 +291,7 @@
 // Tests that password suggestions still work if the fields have the
 // "autocomplete" attribute set to off.
 IN_PROC_BROWSER_TEST_P(PasswordManagerBrowserTestWithConditionalPopupViews,
-                       DISABLED_AutofillPasswordFormWithAutocompleteOff) {
+                       AutofillPasswordFormWithAutocompleteOff) {
   std::string submit = "document.getElementById('submit').click();";
   VerifyPasswordIsSavedAndFilled(
       "/password/password_autocomplete_off_test.html", "username", "password",
@@ -300,7 +300,7 @@
 
 // Disabled for flakiness crbug.com/849582.
 IN_PROC_BROWSER_TEST_P(PasswordManagerBrowserTestWithConditionalPopupViews,
-                       DISABLED_AutofillPasswordNoFormElement) {
+                       AutofillPasswordNoFormElement) {
   VerifyPasswordIsSavedAndFilled("/password/no_form_element.html",
                                  "username_field", "password_field",
                                  "send_xhr();");
@@ -310,7 +310,7 @@
 // Check that we can fill in cases where <base href> is set and the action of
 // the form is not set. Regression test for https://crbug.com/360230.
 IN_PROC_BROWSER_TEST_P(PasswordManagerBrowserTestWithConditionalPopupViews,
-                       DISABLED_AutofillBaseTagWithNoActionTest) {
+                       AutofillBaseTagWithNoActionTest) {
   std::string submit = "document.getElementById('submit_button').click();";
   VerifyPasswordIsSavedAndFilled("/password/password_xhr_submit.html",
                                  "username_field", "password_field", submit);
diff --git a/chrome/browser/prefs/pref_service_incognito_whitelist.cc b/chrome/browser/prefs/pref_service_incognito_whitelist.cc
new file mode 100644
index 0000000..7cabe64
--- /dev/null
+++ b/chrome/browser/prefs/pref_service_incognito_whitelist.cc
@@ -0,0 +1,1493 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/prefs/pref_service_incognito_whitelist.h"
+
+#include <vector>
+#include "build/build_config.h"
+#include "chrome/common/pref_names.h"
+#include "components/autofill/core/common/autofill_pref_names.h"
+#include "components/bookmarks/common/bookmark_pref_names.h"
+#include "components/browsing_data/core/pref_names.h"
+#include "components/certificate_transparency/pref_names.h"
+#include "components/component_updater/pref_names.h"
+#include "components/consent_auditor/pref_names.h"
+#include "components/content_settings/core/common/pref_names.h"
+#include "components/data_reduction_proxy/core/common/data_reduction_proxy_pref_names.h"
+#include "components/dom_distiller/core/pref_names.h"
+#include "components/flags_ui/flags_ui_pref_names.h"
+#include "components/google/core/browser/google_pref_names.h"
+#include "components/invalidation/impl/invalidation_prefs.h"
+#include "components/language/core/browser/pref_names.h"
+#include "components/metrics/metrics_pref_names.h"
+#include "components/network_time/network_time_pref_names.h"
+#include "components/ntp_snippets/pref_names.h"
+#include "components/ntp_tiles/pref_names.h"
+#include "components/omnibox/browser/omnibox_pref_names.h"
+#include "components/onc/onc_pref_names.h"
+#include "components/password_manager/core/common/password_manager_pref_names.h"
+#include "components/policy/core/common/policy_pref_names.h"
+#include "components/proxy_config/proxy_config_pref_names.h"
+#include "components/proxy_config/proxy_prefs.h"
+#include "components/rappor/rappor_pref_names.h"
+#include "components/rappor/rappor_prefs.h"
+#include "components/reading_list/core/reading_list_pref_names.h"
+#include "components/safe_browsing/common/safe_browsing_prefs.h"
+#include "components/search_engines/search_engines_pref_names.h"
+#include "components/signin/core/browser/signin_pref_names.h"
+#include "components/spellcheck/browser/pref_names.h"
+#include "components/startup_metric_utils/browser/pref_names.h"
+#include "components/suggestions/suggestions_pref_names.h"
+#include "components/sync/base/pref_names.h"
+#include "components/translate/core/browser/translate_pref_names.h"
+#include "components/translate/core/browser/translate_prefs.h"
+#include "components/ukm/ukm_pref_names.h"
+#include "components/unified_consent/pref_names.h"
+#include "components/variations/pref_names.h"
+#include "components/web_resource/web_resource_pref_names.h"
+#include "services/preferences/public/cpp/tracked/pref_names.h"
+
+#if defined(OS_ANDROID)
+#include "chrome/browser/android/contextual_suggestions/contextual_suggestions_prefs.h"
+#include "components/feed/core/pref_names.h"
+#endif  // defined(OS_ANDROID)
+
+#if !defined(OS_ANDROID)
+#include "chrome/browser/accessibility/animation_policy_prefs.h"
+#include "extensions/browser/api/audio/pref_names.h"
+#include "extensions/browser/pref_names.h"
+#endif  // !defined(OS_ANDROID)
+
+#if defined(OS_CHROMEOS)
+#include "ash/public/cpp/ash_pref_names.h"
+#include "ash/public/cpp/shelf_prefs.h"
+#include "chrome/browser/chromeos/crostini/crostini_pref_names.h"
+#include "chromeos/chromeos_pref_names.h"
+#include "chromeos/components/proximity_auth/proximity_auth_pref_names.h"
+#include "chromeos/components/tether/pref_names.h"
+#include "components/arc/arc_prefs.h"
+#include "components/cryptauth/pref_names.h"
+#include "components/drive/drive_pref_names.h"
+#include "ui/base/ime/chromeos/extension_ime_util.h"
+#include "ui/chromeos/events/pref_names.h"
+#endif  // defined(OS_CHROMEOS)
+
+namespace {
+
+// TODO(https://crbug.com/861722): Remove this list and file.
+//
+// WARNING: PLEASE DO NOT ADD ANYTHING TO THIS FILE.
+// This file is temporarily added for transition of incognito preferences
+// storage default, from on disk to in memory. All items in this list will be
+// audited and checked with owners and removed from whitelist.
+const char* incognito_whitelist[] = {
+
+// ash/public/cpp/ash_pref_names.h
+#if defined(OS_CHROMEOS)
+    ash::prefs::kAccessibilityLargeCursorEnabled,
+    ash::prefs::kAccessibilityLargeCursorDipSize,
+    ash::prefs::kAccessibilityStickyKeysEnabled,
+
+    // TODO(https://crbug.com/861722): Check with code owners why this pref is
+    // required in tests, if possible, update tests and remove.
+    ash::prefs::kAccessibilitySpokenFeedbackEnabled,
+    ash::prefs::kAccessibilityHighContrastEnabled,
+    ash::prefs::kAccessibilityScreenMagnifierCenterFocus,
+    ash::prefs::kAccessibilityScreenMagnifierEnabled,
+    ash::prefs::kAccessibilityScreenMagnifierScale,
+    ash::prefs::kAccessibilityVirtualKeyboardEnabled,
+    ash::prefs::kAccessibilityMonoAudioEnabled,
+    ash::prefs::kAccessibilityAutoclickEnabled,
+    ash::prefs::kAccessibilityAutoclickDelayMs,
+    ash::prefs::kAccessibilityCaretHighlightEnabled,
+    ash::prefs::kAccessibilityCursorHighlightEnabled,
+    ash::prefs::kAccessibilityFocusHighlightEnabled,
+    ash::prefs::kAccessibilitySelectToSpeakEnabled,
+    ash::prefs::kAccessibilitySwitchAccessEnabled,
+    ash::prefs::kAccessibilityDictationEnabled,
+    ash::prefs::kShouldAlwaysShowAccessibilityMenu,
+    ash::prefs::kDockedMagnifierEnabled, ash::prefs::kDockedMagnifierScale,
+    ash::prefs::kDockedMagnifierAcceleratorDialogHasBeenAccepted,
+    ash::prefs::kHighContrastAcceleratorDialogHasBeenAccepted,
+    ash::prefs::kScreenMagnifierAcceleratorDialogHasBeenAccepted,
+    ash::prefs::kDisplayMixedMirrorModeParams, ash::prefs::kDisplayPowerState,
+    ash::prefs::kDisplayProperties, ash::prefs::kDisplayRotationLock,
+    ash::prefs::kDisplayTouchAssociations,
+    ash::prefs::kDisplayTouchPortAssociations,
+    ash::prefs::kExternalDisplayMirrorInfo, ash::prefs::kSecondaryDisplays,
+    ash::prefs::kHasSeenStylus, ash::prefs::kShownPaletteWelcomeBubble,
+    ash::prefs::kEnableStylusTools, ash::prefs::kLaunchPaletteOnEjectEvent,
+    ash::prefs::kNightLightEnabled, ash::prefs::kNightLightTemperature,
+    ash::prefs::kNightLightScheduleType, ash::prefs::kNightLightCustomStartTime,
+    ash::prefs::kNightLightCustomEndTime, ash::prefs::kAllowScreenLock,
+    ash::prefs::kEnableAutoScreenLock, ash::prefs::kPowerAcScreenDimDelayMs,
+    ash::prefs::kPowerAcScreenOffDelayMs, ash::prefs::kPowerAcScreenLockDelayMs,
+    ash::prefs::kPowerAcIdleWarningDelayMs, ash::prefs::kPowerAcIdleDelayMs,
+    ash::prefs::kPowerBatteryScreenDimDelayMs,
+    ash::prefs::kPowerBatteryScreenOffDelayMs,
+    ash::prefs::kPowerBatteryScreenLockDelayMs,
+    ash::prefs::kPowerBatteryIdleWarningDelayMs,
+    ash::prefs::kPowerBatteryIdleDelayMs,
+    ash::prefs::kPowerLockScreenDimDelayMs,
+    ash::prefs::kPowerLockScreenOffDelayMs, ash::prefs::kPowerAcIdleAction,
+    ash::prefs::kPowerBatteryIdleAction, ash::prefs::kPowerLidClosedAction,
+    ash::prefs::kPowerUseAudioActivity, ash::prefs::kPowerUseVideoActivity,
+    ash::prefs::kPowerAllowScreenWakeLocks,
+    ash::prefs::kPowerPresentationScreenDimDelayFactor,
+    ash::prefs::kPowerUserActivityScreenDimDelayFactor,
+    ash::prefs::kPowerWaitForInitialUserActivity,
+    ash::prefs::kPowerForceNonzeroBrightnessForUserActivity,
+    ash::prefs::kShelfAlignment, ash::prefs::kShelfAlignmentLocal,
+    ash::prefs::kShelfAutoHideBehavior, ash::prefs::kShelfAutoHideBehaviorLocal,
+    ash::prefs::kShelfPreferences, ash::prefs::kShowLogoutButtonInTray,
+    ash::prefs::kLogoutDialogDurationMs, ash::prefs::kUserWallpaperInfo,
+    ash::prefs::kWallpaperColors, ash::prefs::kUserBluetoothAdapterEnabled,
+    ash::prefs::kSystemBluetoothAdapterEnabled, ash::prefs::kTapDraggingEnabled,
+    ash::prefs::kTapToClickEnabled, ash::prefs::kOwnerTapToClickEnabled,
+    ash::prefs::kTouchpadEnabled, ash::prefs::kTouchscreenEnabled,
+    ash::prefs::kQuickUnlockPinSalt, ash::prefs::kDetachableBaseDevices,
+#endif  // defined(OS_CHROMEOS)
+
+// ash/public/cpp/shelf_prefs.h
+#if defined(OS_CHROMEOS)
+    ash::kShelfAutoHideBehaviorAlways, ash::kShelfAutoHideBehaviorNever,
+    ash::kShelfAlignmentBottom, ash::kShelfAlignmentLeft,
+    ash::kShelfAlignmentRight,
+#endif  // defined(OS_CHROMEOS)
+
+// chrome/browser/chromeos/crostini/crostini_pref_names.h
+#if defined(OS_CHROMEOS)
+    crostini::prefs::kCrostiniEnabled,
+#endif  // defined(OS_CHROMEOS)
+
+// chrome/browser/accessibility/animation_policy_prefs.h
+#if !defined(OS_ANDROID)
+    kAnimationPolicyAllowed, kAnimationPolicyOnce, kAnimationPolicyNone,
+#endif  // !defined(OS_ANDROID)
+
+// chrome/browser/android/contextual_suggestions/contextual_suggestions_prefs.h
+#if defined(OS_ANDROID)
+    contextual_suggestions::prefs::kContextualSuggestionsEnabled,
+#endif  // defined(OS_ANDROID)
+
+    // chrome/common/pref_names.h
+    prefs::kAbusiveExperienceInterventionEnforce,
+    prefs::kChildAccountStatusKnown, prefs::kDefaultApps,
+    prefs::kSafeBrowsingForTrustedSourcesEnabled, prefs::kDisableScreenshots,
+    prefs::kDownloadRestrictions, prefs::kForceEphemeralProfiles,
+    prefs::kHomePageIsNewTabPage, prefs::kHomePage,
+    prefs::kImportantSitesDialogHistory,
+#if defined(OS_WIN)
+    prefs::kLastProfileResetTimestamp, prefs::kChromeCleanerResetPending,
+#endif
+    prefs::kNewTabPageLocationOverride, prefs::kProfileIconVersion,
+    prefs::kRestoreOnStartup, prefs::kSessionExitedCleanly,
+    prefs::kSessionExitType, prefs::kObservedSessionTime,
+    prefs::kRecurrentSSLInterstitial, prefs::kSiteEngagementLastUpdateTime,
+    prefs::kSupervisedUserApprovedExtensions,
+    prefs::kSupervisedUserCustodianEmail, prefs::kSupervisedUserCustodianName,
+    prefs::kSupervisedUserCustodianProfileImageURL,
+    prefs::kSupervisedUserCustodianProfileURL,
+    prefs::kSupervisedUserManualHosts, prefs::kSupervisedUserManualURLs,
+    prefs::kSupervisedUserSafeSites, prefs::kSupervisedUserSecondCustodianEmail,
+    prefs::kSupervisedUserSecondCustodianName,
+    prefs::kSupervisedUserSecondCustodianProfileImageURL,
+    prefs::kSupervisedUserSecondCustodianProfileURL,
+    prefs::kSupervisedUserSharedSettings, prefs::kSupervisedUserWhitelists,
+    prefs::kURLsToRestoreOnStartup,
+
+#if BUILDFLAG(ENABLE_RLZ)
+    prefs::kRlzPingDelaySeconds,
+#endif  // BUILDFLAG(ENABLE_RLZ)
+
+#if defined(OS_CHROMEOS)
+    prefs::kApplicationLocaleBackup, prefs::kApplicationLocaleAccepted,
+    prefs::kOwnerLocale, prefs::kAllowedUILocales,
+#endif
+
+    prefs::kDefaultCharset, prefs::kAcceptLanguages, prefs::kWebKitCommonScript,
+    prefs::kWebKitStandardFontFamily, prefs::kWebKitFixedFontFamily,
+    prefs::kWebKitSerifFontFamily, prefs::kWebKitSansSerifFontFamily,
+    prefs::kWebKitCursiveFontFamily, prefs::kWebKitFantasyFontFamily,
+    prefs::kWebKitPictographFontFamily,
+
+    // prefs::kWebKitScriptsForFontFamilyMaps,
+    // prefs::kWebKitScriptsForFontFamilyMapsLength,
+
+    prefs::kWebKitStandardFontFamilyMap, prefs::kWebKitFixedFontFamilyMap,
+    prefs::kWebKitSerifFontFamilyMap, prefs::kWebKitSansSerifFontFamilyMap,
+    prefs::kWebKitCursiveFontFamilyMap, prefs::kWebKitFantasyFontFamilyMap,
+    prefs::kWebKitPictographFontFamilyMap,
+
+    prefs::kWebKitStandardFontFamilyArabic,
+#if defined(OS_WIN)
+    prefs::kWebKitFixedFontFamilyArabic,
+#endif
+    prefs::kWebKitSerifFontFamilyArabic,
+    prefs::kWebKitSansSerifFontFamilyArabic,
+#if defined(OS_WIN)
+    prefs::kWebKitStandardFontFamilyCyrillic,
+    prefs::kWebKitFixedFontFamilyCyrillic,
+    prefs::kWebKitSerifFontFamilyCyrillic,
+    prefs::kWebKitSansSerifFontFamilyCyrillic,
+    prefs::kWebKitStandardFontFamilyGreek, prefs::kWebKitFixedFontFamilyGreek,
+    prefs::kWebKitSerifFontFamilyGreek, prefs::kWebKitSansSerifFontFamilyGreek,
+#endif
+    prefs::kWebKitStandardFontFamilyJapanese,
+    prefs::kWebKitFixedFontFamilyJapanese,
+    prefs::kWebKitSerifFontFamilyJapanese,
+    prefs::kWebKitSansSerifFontFamilyJapanese,
+    prefs::kWebKitStandardFontFamilyKorean, prefs::kWebKitFixedFontFamilyKorean,
+    prefs::kWebKitSerifFontFamilyKorean,
+    prefs::kWebKitSansSerifFontFamilyKorean,
+#if defined(OS_WIN)
+    prefs::kWebKitCursiveFontFamilyKorean,
+#endif
+    prefs::kWebKitStandardFontFamilySimplifiedHan,
+    prefs::kWebKitFixedFontFamilySimplifiedHan,
+    prefs::kWebKitSerifFontFamilySimplifiedHan,
+    prefs::kWebKitSansSerifFontFamilySimplifiedHan,
+    prefs::kWebKitStandardFontFamilyTraditionalHan,
+    prefs::kWebKitFixedFontFamilyTraditionalHan,
+    prefs::kWebKitSerifFontFamilyTraditionalHan,
+    prefs::kWebKitSansSerifFontFamilyTraditionalHan,
+#if defined(OS_WIN) || defined(OS_MACOSX)
+    prefs::kWebKitCursiveFontFamilySimplifiedHan,
+    prefs::kWebKitCursiveFontFamilyTraditionalHan,
+#endif
+
+    prefs::kWebKitDefaultFontSize, prefs::kWebKitDefaultFixedFontSize,
+    prefs::kWebKitMinimumFontSize, prefs::kWebKitMinimumLogicalFontSize,
+    prefs::kWebKitJavascriptEnabled, prefs::kWebKitWebSecurityEnabled,
+    prefs::kWebKitLoadsImagesAutomatically, prefs::kWebKitPluginsEnabled,
+    prefs::kWebKitDomPasteEnabled, prefs::kWebKitTextAreasAreResizable,
+    prefs::kWebKitJavascriptCanAccessClipboard, prefs::kWebkitTabsToLinks,
+    prefs::kWebKitAllowRunningInsecureContent,
+#if defined(OS_ANDROID)
+    prefs::kWebKitFontScaleFactor, prefs::kWebKitForceEnableZoom,
+    prefs::kWebKitPasswordEchoEnabled,
+#endif
+    prefs::kDataSaverEnabled, prefs::kSSLErrorOverrideAllowed,
+    prefs::kIncognitoModeAvailability, prefs::kSearchSuggestEnabled,
+#if defined(OS_ANDROID)
+    prefs::kContextualSearchEnabled,
+#endif  // defined(OS_ANDROID)
+#if defined(OS_MACOSX) || defined(OS_WIN) || \
+    (defined(OS_LINUX) && !defined(OS_CHROMEOS))
+    prefs::kConfirmToQuitEnabled,
+#endif
+#if defined(OS_MACOSX)
+    prefs::kShowFullscreenToolbar, prefs::kAllowJavascriptAppleEvents,
+#endif
+    prefs::kPromptForDownload, prefs::kAlternateErrorPagesEnabled,
+    prefs::kDnsPrefetchingStartupList, prefs::kDnsPrefetchingHostReferralList,
+    prefs::kQuicAllowed, prefs::kNetworkQualities,
+#if defined(OS_ANDROID)
+    prefs::kLastPolicyCheckTime,
+#endif
+    prefs::kNetworkPredictionOptions, prefs::kDefaultAppsInstallState,
+    prefs::kHideWebStoreIcon,
+#if defined(OS_CHROMEOS)
+    prefs::kEnableTouchpadThreeFingerClick, prefs::kNaturalScroll,
+    prefs::kPrimaryMouseButtonRight, prefs::kMouseReverseScroll,
+    prefs::kMouseSensitivity, prefs::kTouchpadSensitivity,
+    prefs::kUse24HourClock, prefs::kUserTimezone,
+    prefs::kResolveTimezoneByGeolocation,
+    prefs::kResolveTimezoneByGeolocationMethod,
+    prefs::kResolveTimezoneByGeolocationMigratedToMethod,
+    prefs::kLanguageCurrentInputMethod, prefs::kLanguagePreviousInputMethod,
+    prefs::kLanguageAllowedInputMethods, prefs::kLanguagePreferredLanguages,
+    prefs::kLanguagePreferredLanguagesSyncable, prefs::kLanguagePreloadEngines,
+    prefs::kLanguagePreloadEnginesSyncable, prefs::kLanguageEnabledImes,
+    prefs::kLanguageEnabledImesSyncable, prefs::kLanguageImeMenuActivated,
+    prefs::kLanguageShouldMergeInputMethods, prefs::kLanguageSendFunctionKeys,
+    prefs::kLanguageXkbAutoRepeatEnabled, prefs::kLanguageXkbAutoRepeatDelay,
+    prefs::kLanguageXkbAutoRepeatInterval,
+
+    prefs::kLabsAdvancedFilesystemEnabled, prefs::kLabsMediaplayerEnabled,
+    prefs::kShow3gPromoNotification, prefs::kDataSaverPromptsShown,
+    prefs::kChromeOSReleaseNotesVersion, prefs::kNoteTakingAppId,
+    prefs::kNoteTakingAppEnabledOnLockScreen,
+    prefs::kNoteTakingAppsLockScreenWhitelist,
+    prefs::kNoteTakingAppsLockScreenToastShown,
+    prefs::kRestoreLastLockScreenNote, prefs::kSessionUserActivitySeen,
+    prefs::kSessionStartTime, prefs::kSessionLengthLimit,
+    prefs::kSessionWaitForInitialUserActivity, prefs::kLastSessionType,
+    prefs::kLastSessionLength, prefs::kTermsOfServiceURL,
+    prefs::kAttestationEnabled, prefs::kAttestationExtensionWhitelist,
+    prefs::kMultiProfileNeverShowIntro,
+    prefs::kMultiProfileWarningShowDismissed, prefs::kMultiProfileUserBehavior,
+    prefs::kFirstRunTutorialShown, prefs::kSAMLOfflineSigninTimeLimit,
+    prefs::kSAMLLastGAIASignInTime, prefs::kTimeOnOobe,
+    prefs::kFileSystemProviderMounted, prefs::kTouchVirtualKeyboardEnabled,
+    prefs::kWakeOnWifiDarkConnect,
+    prefs::kCaptivePortalAuthenticationIgnoresProxy,
+    prefs::kForceMaximizeOnFirstRun, prefs::kPlatformKeys,
+    prefs::kUnifiedDesktopEnabledByDefault,
+    prefs::kHatsLastInteractionTimestamp, prefs::kHatsSurveyCycleEndTimestamp,
+    prefs::kHatsDeviceIsSelected, prefs::kQuickUnlockPinSecret,
+    prefs::kQuickUnlockFingerprintRecord, prefs::kEolStatus,
+    prefs::kEolNotificationDismissed, prefs::kPinUnlockFeatureNotificationShown,
+    prefs::kFingerprintUnlockFeatureNotificationShown,
+    prefs::kQuickUnlockModeWhitelist, prefs::kQuickUnlockTimeout,
+    prefs::kPinUnlockMinimumLength, prefs::kPinUnlockMaximumLength,
+    prefs::kPinUnlockWeakPinsAllowed, prefs::kEnableQuickUnlockFingerprint,
+    prefs::kInstantTetheringAllowed, prefs::kInstantTetheringEnabled,
+    prefs::kInstantTetheringBleAdvertisingSupported,
+    prefs::kCastReceiverEnabled, prefs::kMinimumAllowedChromeVersion,
+    prefs::kShowSyncSettingsOnSessionStart, prefs::kTextToSpeechLangToVoiceName,
+    prefs::kTextToSpeechRate, prefs::kTextToSpeechPitch,
+    prefs::kTextToSpeechVolume, prefs::kFirstScreenStartTime,
+    prefs::kCurrentScreenStartTime, prefs::kScreenTimeMinutesUsed,
+    prefs::kUsageTimeLimit, prefs::kScreenTimeLastState,
+    prefs::kEnableSyncConsent,
+#endif  // defined(OS_CHROMEOS)
+    prefs::kShowHomeButton, prefs::kSpeechRecognitionFilterProfanities,
+    prefs::kSavingBrowserHistoryDisabled, prefs::kAllowDeletingBrowserHistory,
+#if !defined(OS_ANDROID)
+    prefs::kMdHistoryMenuPromoShown,
+#endif
+    prefs::kForceGoogleSafeSearch, prefs::kForceYouTubeRestrict,
+    prefs::kForceSessionSync, prefs::kAllowedDomainsForApps,
+    prefs::kSafeSitesFilterBehavior,
+#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+    prefs::kUsesSystemTheme,
+#endif
+    prefs::kCurrentThemePackFilename, prefs::kCurrentThemeID,
+    prefs::kCurrentThemeImages, prefs::kCurrentThemeColors,
+    prefs::kCurrentThemeTints, prefs::kCurrentThemeDisplayProperties,
+    prefs::kExtensionsUIDeveloperMode,
+    // prefs::kExtensionsUIDismissedADTPromo,
+    prefs::kExtensionCommands, prefs::kPluginsLastInternalDirectory,
+    prefs::kPluginsPluginsList, prefs::kPluginsDisabledPlugins,
+    prefs::kPluginsDisabledPluginsExceptions, prefs::kPluginsEnabledPlugins,
+    prefs::kPluginsAlwaysOpenPdfExternally,
+#if BUILDFLAG(ENABLE_PLUGINS)
+    prefs::kPluginsShowDetails,
+#endif
+    prefs::kPluginsAllowOutdated, prefs::kRunAllFlashInAllowMode,
+#if BUILDFLAG(ENABLE_PLUGINS)
+    prefs::kPluginsMetadata, prefs::kPluginsResourceCacheUpdate,
+#endif
+    prefs::kDefaultBrowserLastDeclined, prefs::kResetCheckDefaultBrowser,
+    prefs::kDefaultBrowserSettingEnabled,
+#if defined(OS_MACOSX)
+    prefs::kShowUpdatePromotionInfoBar,
+#endif
+#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+    prefs::kUseCustomChromeFrame,
+#endif
+#if BUILDFLAG(ENABLE_PLUGINS)
+    prefs::kContentSettingsPluginWhitelist,
+#endif
+#if !defined(OS_ANDROID)
+    prefs::kPartitionDefaultZoomLevel, prefs::kPartitionPerHostZoomLevels,
+
+    prefs::kPinnedTabs,
+#endif  // !defined(OS_ANDROID)
+
+    prefs::kDisable3DAPIs, prefs::kEnableDeprecatedWebPlatformFeatures,
+    prefs::kEnableHyperlinkAuditing,
+
+    // TODO(https://crbug.com/861722): Check with code owners why this pref is
+    // required in tests, if possible, update tests and remove.
+    prefs::kEnableReferrers, prefs::kEnableDoNotTrack,
+    prefs::kEnableEncryptedMedia,
+
+    prefs::kImportAutofillFormData, prefs::kImportBookmarks,
+    prefs::kImportHistory, prefs::kImportHomepage, prefs::kImportSavedPasswords,
+    prefs::kImportSearchEngine,
+
+    prefs::kImportDialogAutofillFormData, prefs::kImportDialogBookmarks,
+    prefs::kImportDialogHistory, prefs::kImportDialogSavedPasswords,
+    prefs::kImportDialogSearchEngine,
+
+    prefs::kProfileAvatarIndex, prefs::kProfileUsingDefaultName,
+    prefs::kProfileName, prefs::kProfileUsingDefaultAvatar,
+    prefs::kProfileUsingGAIAAvatar, prefs::kSupervisedUserId,
+
+    prefs::kProfileGAIAInfoUpdateTime, prefs::kProfileGAIAInfoPictureURL,
+
+    prefs::kProfileAvatarTutorialShown,
+
+    prefs::kInvertNotificationShown,
+
+    prefs::kPrintingEnabled, prefs::kPrintPreviewDisabled,
+    prefs::kPrintPreviewDefaultDestinationSelectionRules,
+
+#if !defined(OS_CHROMEOS) && !defined(OS_ANDROID)
+    prefs::kPrintPreviewUseSystemDefaultPrinter,
+#endif
+
+#if defined(OS_CHROMEOS)
+    prefs::kPrintingDevices, prefs::kRecommendedNativePrinters,
+    prefs::kRecommendedNativePrintersFile,
+    prefs::kRecommendedNativePrintersAccessMode,
+    prefs::kRecommendedNativePrintersBlacklist,
+    prefs::kRecommendedNativePrintersWhitelist,
+    prefs::kUserNativePrintersAllowed,
+#endif  // OS_CHROMEOS
+
+    prefs::kDefaultSupervisedUserFilteringBehavior,
+
+    prefs::kSupervisedUserCreationAllowed, prefs::kSupervisedUsers,
+
+    prefs::kMessageCenterDisabledExtensionIds,
+    prefs::kMessageCenterDisabledSystemComponentIds,
+
+    prefs::kFullscreenAllowed,
+
+    prefs::kLocalDiscoveryNotificationsEnabled,
+
+#if defined(OS_ANDROID)
+    prefs::kNotificationsVibrateEnabled,
+    prefs::kMigratedToSiteNotificationChannels,
+    prefs::kClearedBlockedSiteNotificationChannels,
+#endif
+
+    prefs::kPushMessagingAppIdentifierMap,
+
+    prefs::kGCMProductCategoryForSubtypes,
+
+    prefs::kEasyUnlockAllowed, prefs::kEasyUnlockPairing,
+
+#if BUILDFLAG(ENABLE_EXTENSIONS)
+    prefs::kToolbarIconSurfacingBubbleAcknowledged,
+    prefs::kToolbarIconSurfacingBubbleLastShowTime,
+#endif
+
+    prefs::kWebRTCMultipleRoutesEnabled, prefs::kWebRTCNonProxiedUdpEnabled,
+    prefs::kWebRTCIPHandlingPolicy, prefs::kWebRTCUDPPortRange,
+
+#if !defined(OS_ANDROID)
+    prefs::kHasSeenWelcomePage,
+#endif
+
+#if defined(OS_WIN)
+    prefs::kHasSeenWin10PromoPage,
+#if defined(GOOGLE_CHROME_BUILD)
+    prefs::kHasSeenGoogleAppsPromoPage,
+#endif  // defined(GOOGLE_CHROME_BUILD)
+#endif  // defined(OS_WIN)
+
+#if defined(OS_ANDROID)
+    prefs::kCrashReportingEnabled,
+#endif  // defined(OS_ANDROID)
+
+    prefs::kProfileLastUsed, prefs::kProfilesLastActive,
+    prefs::kProfilesNumCreated, prefs::kProfileInfoCache,
+    prefs::kProfileCreatedByVersion, prefs::kProfilesDeleted,
+
+    prefs::kStabilityOtherUserCrashCount, prefs::kStabilityKernelCrashCount,
+    prefs::kStabilitySystemUncleanShutdownCount,
+
+    prefs::kStabilityPluginStats, prefs::kStabilityPluginName,
+    prefs::kStabilityPluginLaunches, prefs::kStabilityPluginInstances,
+    prefs::kStabilityPluginCrashes, prefs::kStabilityPluginLoadingErrors,
+
+    prefs::kBrowserSuppressDefaultBrowserPrompt,
+
+    // prefs::kBrowserWindowPlacement, prefs::kBrowserWindowPlacementPopup,
+    prefs::kTaskManagerWindowPlacement, prefs::kTaskManagerColumnVisibility,
+    prefs::kTaskManagerEndProcessEnabled, prefs::kAppWindowPlacement,
+
+    prefs::kDownloadDefaultDirectory, prefs::kDownloadExtensionsToOpen,
+    prefs::kDownloadDirUpgraded,
+#if defined(OS_WIN) || defined(OS_LINUX) || defined(OS_MACOSX)
+    prefs::kOpenPdfDownloadInSystemReader,
+#endif
+#if defined(OS_ANDROID)
+    prefs::kPromptForDownloadAndroid, prefs::kShowMissingSdCardErrorAndroid,
+#endif
+
+    // prefs::kSaveFileDefaultDirectory, prefs::kSaveFileType,
+    prefs::kTrustedDownloadSources,
+
+    prefs::kAllowFileSelectionDialogs, prefs::kDefaultTasksByMimeType,
+    prefs::kDefaultTasksBySuffix,
+
+    prefs::kSelectFileLastDirectory,
+
+    prefs::kExcludedSchemes,
+
+    prefs::kOptionsWindowLastTabIndex,
+
+    prefs::kLastKnownIntranetRedirectOrigin,
+
+    prefs::kShutdownType, prefs::kShutdownNumProcesses,
+    prefs::kShutdownNumProcessesSlow,
+
+    prefs::kRestartLastSessionOnShutdown,
+#if !defined(OS_ANDROID)
+#if !defined(OS_CHROMEOS)
+    prefs::kPromotionalTabsEnabled,
+#endif
+    prefs::kSuppressUnsupportedOSWarning, prefs::kWasRestarted,
+#endif  // !defined(OS_ANDROID)
+
+    prefs::kDisableExtensions,
+
+    prefs::kNtpAppPageNames, prefs::kNtpCollapsedForeignSessions,
+#if defined(OS_ANDROID)
+    prefs::kNtpCollapsedRecentlyClosedTabs,
+    prefs::kNtpCollapsedSnapshotDocument, prefs::kNtpCollapsedSyncPromo,
+    prefs::kContentSuggestionsNotificationsEnabled,
+    prefs::kContentSuggestionsConsecutiveIgnoredPrefName,
+    prefs::kContentSuggestionsNotificationsSentDay,
+    prefs::kContentSuggestionsNotificationsSentCount,
+#endif  // defined(OS_ANDROID)
+    prefs::kNtpShownPage,
+
+    prefs::kDevToolsAdbKey, prefs::kDevToolsAvailability,
+    prefs::kDevToolsDiscoverUsbDevicesEnabled, prefs::kDevToolsEditedFiles,
+    prefs::kDevToolsFileSystemPaths, prefs::kDevToolsPortForwardingEnabled,
+    prefs::kDevToolsPortForwardingDefaultSet,
+    prefs::kDevToolsPortForwardingConfig, prefs::kDevToolsPreferences,
+    prefs::kDevToolsDiscoverTCPTargetsEnabled,
+    prefs::kDevToolsTCPDiscoveryConfig,
+#if defined(OS_ANDROID)
+    prefs::kDevToolsRemoteEnabled,
+#endif
+
+    prefs::kGoogleServicesPasswordHash,
+
+#if !defined(OS_ANDROID)
+    prefs::kDiceSigninUserMenuPromoCount, prefs::kSignInPromoStartupCount,
+    prefs::kSignInPromoUserSkipped, prefs::kSignInPromoShowOnFirstRunAllowed,
+    prefs::kSignInPromoShowNTPBubble,
+#endif
+
+#if !defined(OS_CHROMEOS) && !defined(OS_ANDROID)
+    prefs::kCrossDevicePromoOptedOut, prefs::kCrossDevicePromoShouldBeShown,
+    prefs::kCrossDevicePromoObservedSingleAccountCookie,
+    prefs::kCrossDevicePromoNextFetchListDevicesTime,
+    prefs::kCrossDevicePromoNumDevices,
+    prefs::kCrossDevicePromoLastDeviceActiveTime,
+#endif
+
+    prefs::kWebAppCreateOnDesktop, prefs::kWebAppCreateInAppsMenu,
+    prefs::kWebAppCreateInQuickLaunchBar,
+
+    prefs::kWebAppInstallForceList,
+
+    prefs::kGeolocationAccessToken,
+
+    prefs::kDefaultAudioCaptureDevice, prefs::kDefaultVideoCaptureDevice,
+    prefs::kMediaDeviceIdSalt, prefs::kMediaStorageIdSalt,
+
+    prefs::kPrintPreviewStickySettings, prefs::kCloudPrintRoot,
+    prefs::kCloudPrintProxyEnabled, prefs::kCloudPrintProxyId,
+    prefs::kCloudPrintAuthToken, prefs::kCloudPrintEmail,
+    prefs::kCloudPrintPrintSystemSettings, prefs::kCloudPrintEnableJobPoll,
+    prefs::kCloudPrintRobotRefreshToken, prefs::kCloudPrintRobotEmail,
+    prefs::kCloudPrintConnectNewPrinters, prefs::kCloudPrintXmppPingEnabled,
+    prefs::kCloudPrintXmppPingTimeout, prefs::kCloudPrintPrinters,
+    prefs::kCloudPrintSubmitEnabled, prefs::kCloudPrintUserSettings,
+
+    prefs::kMaxConnectionsPerProxy,
+
+    prefs::kAudioCaptureAllowed, prefs::kAudioCaptureAllowedUrls,
+    prefs::kVideoCaptureAllowed, prefs::kVideoCaptureAllowedUrls,
+
+#if defined(OS_CHROMEOS)
+    prefs::kDeviceSettingsCache, prefs::kHardwareKeyboardLayout,
+    prefs::kCarrierDealPromoShown, prefs::kShouldAutoEnroll,
+    prefs::kAutoEnrollmentPowerLimit, prefs::kDeviceActivityTimes,
+    prefs::kUserActivityTimes, prefs::kExternalStorageDisabled,
+    prefs::kExternalStorageReadOnly, prefs::kOwnerPrimaryMouseButtonRight,
+    prefs::kUptimeLimit, prefs::kRebootAfterUpdate,
+    prefs::kDeviceRobotAnyApiRefreshToken, prefs::kDeviceEnrollmentRequisition,
+    prefs::kDeviceEnrollmentAutoStart, prefs::kDeviceEnrollmentCanExit,
+    prefs::kDeviceDMToken, prefs::kTimesHIDDialogShown,
+    prefs::kUsersLastInputMethod, prefs::kEchoCheckedOffers,
+    prefs::kCachedMultiProfileUserBehavior, prefs::kInitialLocale,
+    prefs::kOobeComplete, prefs::kOobeScreenPending,
+    prefs::kOobeControllerDetected, prefs::kCanShowOobeGoodiesPage,
+    prefs::kDeviceRegistered, prefs::kEnrollmentRecoveryRequired,
+    prefs::kUsedPolicyCertificates, prefs::kServerBackedDeviceState,
+    prefs::kCustomizationDefaultWallpaperURL, prefs::kLogoutStartedLast,
+    // prefs::kConsumerManagementStage,
+    prefs::kIsBootstrappingSlave, prefs::kReportArcStatusEnabled,
+    prefs::kNetworkThrottlingEnabled, prefs::kPowerMetricsDailySample,
+    prefs::kPowerMetricsIdleScreenDimCount,
+    prefs::kPowerMetricsIdleScreenOffCount,
+    prefs::kPowerMetricsIdleSuspendCount,
+    prefs::kPowerMetricsLidClosedSuspendCount, prefs::kReportingUsers,
+    prefs::kArcAppInstallEventLoggingEnabled, prefs::kRemoveUsersRemoteCommand,
+    prefs::kCameraMediaConsolidated,
+#endif  // defined(OS_CHROMEOS)
+
+    prefs::kClearPluginLSODataEnabled, prefs::kPepperFlashSettingsEnabled,
+    prefs::kDiskCacheDir, prefs::kDiskCacheSize, prefs::kMediaCacheSize,
+
+    prefs::kChromeOsReleaseChannel,
+
+    prefs::kPerformanceTracingEnabled,
+
+    prefs::kTabStripStackedLayout,
+
+    prefs::kRegisteredBackgroundContents,
+
+#if defined(OS_WIN)
+    prefs::kLastWelcomedOSVersion, prefs::kWelcomePageOnOSUpgradeEnabled,
+#endif
+
+    prefs::kAuthSchemes, prefs::kDisableAuthNegotiateCnameLookup,
+    prefs::kEnableAuthNegotiatePort, prefs::kAuthServerWhitelist,
+    prefs::kAuthNegotiateDelegateWhitelist, prefs::kGSSAPILibraryName,
+    prefs::kAuthAndroidNegotiateAccountType, prefs::kAllowCrossOriginAuthPrompt,
+
+#if defined(OS_POSIX)
+    prefs::kNtlmV2Enabled,
+#endif  // defined(OS_POSIX)
+
+    prefs::kCertRevocationCheckingEnabled,
+    prefs::kCertRevocationCheckingRequiredLocalAnchors,
+    prefs::kCertEnableSha1LocalAnchors,
+    prefs::kCertEnableSymantecLegacyInfrastructure, prefs::kSSLVersionMin,
+    prefs::kSSLVersionMax, prefs::kTLS13Variant, prefs::kCipherSuiteBlacklist,
+
+    prefs::kBuiltInDnsClientEnabled, prefs::kDnsOverHttpsServers,
+    prefs::kDnsOverHttpsServerMethods,
+
+    prefs::kRegisteredProtocolHandlers, prefs::kIgnoredProtocolHandlers,
+    prefs::kPolicyRegisteredProtocolHandlers,
+    prefs::kPolicyIgnoredProtocolHandlers, prefs::kCustomHandlersEnabled,
+
+#if defined(OS_MACOSX)
+    prefs::kUserRemovedLoginItem, prefs::kChromeCreatedLoginItem,
+    prefs::kMigratedLoginItemPref, prefs::kNotifyWhenAppsKeepChromeAlive,
+#endif
+
+    prefs::kBackgroundModeEnabled, prefs::kHardwareAccelerationModeEnabled,
+    prefs::kHardwareAccelerationModePrevious,
+
+    prefs::kDevicePolicyRefreshRate,
+
+    prefs::kFactoryResetRequested, prefs::kFactoryResetTPMFirmwareUpdateMode,
+    prefs::kDebuggingFeaturesRequested,
+
+#if defined(OS_CHROMEOS)
+    prefs::kSigninScreenTimezone, prefs::kResolveDeviceTimezoneByGeolocation,
+    prefs::kResolveDeviceTimezoneByGeolocationMethod,
+    prefs::kSystemTimezoneAutomaticDetectionPolicy,
+#endif  // defined(OS_CHROMEOS)
+
+    prefs::kEnableMediaRouter,
+#if !defined(OS_ANDROID)
+    prefs::kShowCastIconInToolbar,
+#endif  // !defined(OS_ANDROID)
+
+#if !defined(OS_ANDROID)
+#if !defined(OS_CHROMEOS)
+    prefs::kRelaunchNotification,
+#endif  // !defined(OS_CHROMEOS)
+    prefs::kRelaunchNotificationPeriod,
+#endif  // !defined(OS_ANDROID)
+
+#if !defined(OS_ANDROID)
+    prefs::kAttemptedToEnableAutoupdate,
+
+    prefs::kMediaGalleriesUniqueId, prefs::kMediaGalleriesRememberedGalleries,
+#endif  // !defined(OS_ANDROID)
+
+#if defined(OS_CHROMEOS)
+    prefs::kShelfChromeIconIndex, prefs::kPinnedLauncherApps,
+    prefs::kPolicyPinnedLauncherApps,
+#endif  // defined(OS_CHROMEOS)
+
+#if defined(OS_WIN)
+    prefs::kNetworkProfileWarningsLeft, prefs::kNetworkProfileLastWarningTime,
+#endif
+
+#if defined(OS_CHROMEOS)
+    prefs::kRLZBrand, prefs::kRLZDisabled,
+#endif
+
+#if BUILDFLAG(ENABLE_APP_LIST)
+    prefs::kAppListLocalState,
+#endif  // BUILDFLAG(ENABLE_APP_LIST)
+
+#if defined(OS_WIN)
+    prefs::kAppLaunchForMetroRestart, prefs::kAppLaunchForMetroRestartProfile,
+#endif
+    prefs::kAppShortcutsVersion,
+
+    prefs::kModuleConflictBubbleShown,
+
+    prefs::kDRMSalt, prefs::kEnableDRM,
+
+    prefs::kWatchdogExtensionActive,
+
+#if defined(OS_ANDROID)
+    prefs::kPartnerBookmarkMappings,
+#endif  // defined(OS_ANDROID)
+
+    prefs::kQuickCheckEnabled, prefs::kPacHttpsUrlStrippingEnabled,
+    prefs::kBrowserGuestModeEnabled, prefs::kBrowserAddPersonEnabled,
+    prefs::kForceBrowserSignin,
+
+    prefs::kCryptAuthDeviceId, prefs::kEasyUnlockHardlockState,
+    prefs::kEasyUnlockLocalStateTpmKeys, prefs::kEasyUnlockLocalStateUserPrefs,
+
+    prefs::kRecoveryComponentNeedsElevation,
+
+    prefs::kRegisteredSupervisedUserWhitelists,
+
+    prefs::kCloudPolicyOverridesMachinePolicy,
+
+#if BUILDFLAG(ENABLE_BACKGROUND_MODE)
+// prefs::kRestartInBackground,
+#endif
+
+#if BUILDFLAG(ENABLE_EXTENSIONS)
+    prefs::kAnimationPolicy, prefs::kSecurityKeyPermitAttestation,
+#endif
+
+    prefs::kBackgroundTracingLastUpload,
+
+    prefs::kAllowDinosaurEasterEgg,
+
+#if defined(OS_ANDROID)
+    prefs::kClickedUpdateMenuItem,
+    prefs::kLatestVersionWhenClickedUpdateMenuItem,
+#endif
+
+    prefs::kMediaRouterCloudServicesPrefSet,
+    prefs::kMediaRouterEnableCloudServices,
+    prefs::kMediaRouterFirstRunFlowAcknowledged,
+    prefs::kMediaRouterMediaRemotingEnabled,
+    // prefs::kMediaRouterTabMirroringSources,
+
+    prefs::kOriginTrialPublicKey, prefs::kOriginTrialDisabledFeatures,
+    prefs::kOriginTrialDisabledTokens,
+
+    prefs::kComponentUpdatesEnabled,
+
+#if defined(OS_ANDROID)
+    prefs::kLocationSettingsBackoffLevelDSE,
+    prefs::kLocationSettingsBackoffLevelDefault,
+    prefs::kLocationSettingsNextShowDSE,
+    prefs::kLocationSettingsNextShowDefault,
+
+    prefs::kSearchGeolocationDisclosureDismissed,
+    prefs::kSearchGeolocationDisclosureShownCount,
+    prefs::kSearchGeolocationDisclosureLastShowDate,
+    prefs::kSearchGeolocationPreDisclosureMetricsRecorded,
+    prefs::kSearchGeolocationPostDisclosureMetricsRecorded,
+#endif
+
+    prefs::kDSEGeolocationSettingDeprecated,
+
+    prefs::kDSEPermissionsSettings, prefs::kDSEWasDisabledByPolicy,
+
+    prefs::kWebShareVisitedTargets,
+
+#if defined(OS_WIN)
+    prefs::kIOSPromotionEligible, prefs::kIOSPromotionDone,
+    prefs::kIOSPromotionSMSEntryPoint, prefs::kIOSPromotionShownEntryPoints,
+    prefs::kIOSPromotionLastImpression, prefs::kIOSPromotionVariationId,
+    prefs::kNumberSavePasswordsBubbleIOSPromoShown,
+    prefs::kSavePasswordsBubbleIOSPromoDismissed,
+    prefs::kNumberBookmarksBubbleIOSPromoShown,
+    prefs::kBookmarksBubbleIOSPromoDismissed,
+    prefs::kNumberBookmarksFootNoteIOSPromoShown,
+    prefs::kBookmarksFootNoteIOSPromoDismissed,
+    prefs::kNumberHistoryPageIOSPromoShown,
+    prefs::kHistoryPageIOSPromoDismissed,
+
+#if defined(GOOGLE_CHROME_BUILD)
+    prefs::kIncompatibleApplications, prefs::kModuleBlacklistCacheMD5Digest,
+    prefs::kProblematicPrograms, prefs::kThirdPartyBlockingEnabled,
+#endif  // defined(GOOGLE_CHROME_BUILD)
+#endif  // defined(OS_WIN)
+
+    prefs::kSettingsResetPromptPromptWave,
+    prefs::kSettingsResetPromptLastTriggeredForDefaultSearch,
+    prefs::kSettingsResetPromptLastTriggeredForStartupUrls,
+    prefs::kSettingsResetPromptLastTriggeredForHomepage,
+
+#if defined(OS_ANDROID)
+    prefs::kClipboardLastModifiedTime,
+#endif
+
+#if BUILDFLAG(ENABLE_OFFLINE_PAGES)
+    prefs::kOfflinePrefetchBackoff, prefs::kOfflineUsageStartObserved,
+    prefs::kOfflineUsageOnlineObserved, prefs::kOfflineUsageOfflineObserved,
+    prefs::kPrefetchUsageEnabledObserved, prefs::kPrefetchUsageHasPagesObserved,
+    prefs::kPrefetchUsageFetchObserved, prefs::kPrefetchUsageOpenObserved,
+    prefs::kOfflineUsageTrackingDay, prefs::kOfflineUsageUnusedCount,
+    prefs::kOfflineUsageStartedCount, prefs::kOfflineUsageOfflineCount,
+    prefs::kOfflineUsageOnlineCount, prefs::kOfflineUsageMixedCount,
+    prefs::kPrefetchUsageEnabledCount, prefs::kPrefetchUsageHasPagesCount,
+    prefs::kPrefetchUsageFetchedCount, prefs::kPrefetchUsageOpenedCount,
+    prefs::kPrefetchUsageMixedCount,
+#endif
+
+    prefs::kMediaEngagementSchemaVersion,
+
+    // Preferences for recording metrics about tab and window usage.
+    prefs::kTabStatsTotalTabCountMax, prefs::kTabStatsMaxTabsPerWindow,
+    prefs::kTabStatsWindowCountMax, prefs::kTabStatsDailySample,
+
+    prefs::kUnsafelyTreatInsecureOriginAsSecure,
+
+    prefs::kIsolateOrigins, prefs::kSitePerProcess,
+    prefs::kWebDriverOverridesIncompatiblePolicies,
+
+#if !defined(OS_ANDROID)
+    prefs::kAutoplayAllowed, prefs::kAutoplayWhitelist,
+    prefs::kNTPCustomBackgroundURL,
+#endif
+
+// chromeos/chromeos_pref_names.h
+#if defined(OS_CHROMEOS)
+    chromeos::prefs::kAudioDevicesMute,
+    chromeos::prefs::kAudioDevicesVolumePercent, chromeos::prefs::kAudioMute,
+    chromeos::prefs::kAudioOutputAllowed, chromeos::prefs::kAudioVolumePercent,
+    chromeos::prefs::kAudioDevicesState,
+    chromeos::prefs::kQuirksClientLastServerCheck,
+#endif  // defined(OS_CHROMEOS)
+
+// chromeos/components/proximity_auth/proximity_auth_pref_names.h
+#if defined(OS_CHROMEOS)
+    proximity_auth::prefs::kEasyUnlockEnabled,
+    proximity_auth::prefs::kEasyUnlockEnabledStateSet,
+    proximity_auth::prefs::kEasyUnlockProximityThreshold,
+    proximity_auth::prefs::kProximityAuthLastPromotionCheckTimestampMs,
+    proximity_auth::prefs::kProximityAuthPromotionShownCount,
+    proximity_auth::prefs::kProximityAuthRemoteBleDevices,
+    proximity_auth::prefs::kProximityAuthIsChromeOSLoginEnabled,
+#endif  // defined(OS_CHROMEOS)
+
+// chromeos/components/tether/pref_names.h
+#if defined(OS_CHROMEOS)
+    chromeos::tether::prefs::kMostRecentTetherAvailablilityResponderIds,
+    chromeos::tether::prefs::kMostRecentConnectTetheringResponderIds,
+    chromeos::tether::prefs::kActiveHostStatus,
+    chromeos::tether::prefs::kActiveHostDeviceId,
+    chromeos::tether::prefs::kTetherNetworkGuid,
+    chromeos::tether::prefs::kWifiNetworkGuid,
+    chromeos::tether::prefs::kDisconnectingWifiNetworkPath,
+    chromeos::tether::prefs::kHostScanCache,
+#endif  // defined(OS_CHROMEOS)
+
+// components/arc/arc_prefs.h
+#if defined(OS_CHROMEOS)
+    arc::prefs::kArcActiveDirectoryPlayUserId, arc::prefs::kArcApps,
+    arc::prefs::kArcBackupRestoreEnabled, arc::prefs::kArcDataRemoveRequested,
+    arc::prefs::kArcEnabled, arc::prefs::kArcFastAppReinstallPackages,
+    arc::prefs::kArcFastAppReinstallStarted,
+    arc::prefs::kArcInitialSettingsPending,
+    arc::prefs::kArcPolicyComplianceReported, arc::prefs::kArcTermsAccepted,
+    arc::prefs::kArcTermsShownInOobe, arc::prefs::kArcLocationServiceEnabled,
+    arc::prefs::kArcPackages, arc::prefs::kArcPaiStarted,
+    arc::prefs::kArcPushInstallAppsRequested,
+    arc::prefs::kArcPushInstallAppsPending,
+    arc::prefs::kArcSetNotificationsEnabledDeferred, arc::prefs::kArcSignedIn,
+    arc::prefs::kArcSkippedReportingNotice,
+    arc::prefs::kArcSupervisionTransition,
+    arc::prefs::kArcCompatibleFilesystemChosen,
+    arc::prefs::kArcVoiceInteractionValuePropAccepted,
+    arc::prefs::kEcryptfsMigrationStrategy, arc::prefs::kSmsConnectEnabled,
+    arc::prefs::kVoiceInteractionEnabled,
+    arc::prefs::kVoiceInteractionContextEnabled,
+    arc::prefs::kVoiceInteractionHotwordEnabled,
+#endif  // defined(OS_CHROMEOS)
+
+    // components/autofill/core/common/autofill_pref_names.h
+    autofill::prefs::kAutofillAcceptSaveCreditCardPromptState,
+    autofill::prefs::kAutofillBillingCustomerNumber,
+    autofill::prefs::kAutofillCreditCardEnabled,
+    autofill::prefs::kAutofillCreditCardSigninPromoImpressionCount,
+    autofill::prefs::kAutofillProfileEnabled, autofill::prefs::kAutofillEnabled,
+    autofill::prefs::kAutofillLastVersionDeduped,
+    autofill::prefs::kAutofillLastVersionDisusedAddressesDeleted,
+    autofill::prefs::kAutofillLastVersionDisusedCreditCardsDeleted,
+    autofill::prefs::kAutofillOrphanRowsRemoved,
+    autofill::prefs::kAutofillWalletImportEnabled,
+    autofill::prefs::kAutofillWalletImportStorageCheckboxState,
+
+    // components/bookmarks/common/bookmark_pref_names.h
+    bookmarks::prefs::kBookmarkEditorExpandedNodes,
+    bookmarks::prefs::kEditBookmarksEnabled,
+    bookmarks::prefs::kManagedBookmarks,
+    bookmarks::prefs::kManagedBookmarksFolderName,
+    bookmarks::prefs::kShowAppsShortcutInBookmarkBar,
+    bookmarks::prefs::kShowManagedBookmarksInBookmarkBar,
+    bookmarks::prefs::kShowBookmarkBar,
+
+    // components/browsing_data/core/pref_names.h
+    browsing_data::prefs::kDeleteTimePeriod,
+    browsing_data::prefs::kDeleteTimePeriodBasic,
+    browsing_data::prefs::kDeleteBrowsingHistory,
+    browsing_data::prefs::kDeleteBrowsingHistoryBasic,
+    browsing_data::prefs::kDeleteDownloadHistory,
+    browsing_data::prefs::kDeleteCache, browsing_data::prefs::kDeleteCacheBasic,
+    browsing_data::prefs::kDeleteCookies,
+    browsing_data::prefs::kDeleteCookiesBasic,
+    browsing_data::prefs::kDeletePasswords,
+    browsing_data::prefs::kDeleteFormData,
+    browsing_data::prefs::kDeleteHostedAppsData,
+    browsing_data::prefs::kDeleteMediaLicenses,
+    browsing_data::prefs::kDeleteSiteSettings,
+    browsing_data::prefs::kLastClearBrowsingDataTime,
+    browsing_data::prefs::kClearBrowsingDataHistoryNoticeShownTimes,
+    browsing_data::prefs::kLastClearBrowsingDataTab,
+    browsing_data::prefs::kPreferencesMigratedToBasic,
+
+    // components/certificate_transparency/pref_names.h
+    certificate_transparency::prefs::kCTRequiredHosts,
+    certificate_transparency::prefs::kCTExcludedHosts,
+    certificate_transparency::prefs::kCTExcludedSPKIs,
+    certificate_transparency::prefs::kCTExcludedLegacySPKIs,
+
+    // components/component_updater/pref_names.h
+    prefs::kRecoveryComponentVersion, prefs::kRecoveryComponentUnpackPath,
+
+#if defined(OS_WIN)
+    // Local state prefs.
+    prefs::kSwReporterLastExitCode, prefs::kSwReporterLastTimeTriggered,
+    prefs::kSwReporterLastTimeSentReport, prefs::kSwReporterEnabled,
+    prefs::kSwReporterReportingEnabled,
+
+    // Profile prefs.
+    // prefs::kSwReporterPromptReason,
+    prefs::kSwReporterPromptVersion, prefs::kSwReporterPromptSeed,
+#endif
+
+    // components/consent_auditor/pref_names.h
+    consent_auditor::prefs::kLocalConsentsDictionary,
+
+    // components/content_settings/core/common/pref_names.h
+    // TODO(https://crbug.com/861722): Check with code owners why this pref is
+    // required in tests, if possible, update tests and remove.
+    prefs::kBlockThirdPartyCookies, prefs::kContentSettingsVersion,
+
+    prefs::kContentSettingsWindowLastTabIndex, prefs::kManagedDefaultAdsSetting,
+    prefs::kManagedDefaultCookiesSetting, prefs::kManagedDefaultImagesSetting,
+    prefs::kManagedDefaultJavaScriptSetting,
+    prefs::kManagedDefaultPluginsSetting, prefs::kManagedDefaultPopupsSetting,
+    prefs::kManagedDefaultGeolocationSetting,
+    prefs::kManagedDefaultNotificationsSetting,
+    prefs::kManagedDefaultMediaStreamSetting,
+    prefs::kManagedDefaultWebBluetoothGuardSetting,
+    prefs::kManagedDefaultWebUsbGuardSetting,
+    prefs::kManagedCookiesAllowedForUrls, prefs::kManagedCookiesBlockedForUrls,
+    prefs::kManagedCookiesSessionOnlyForUrls,
+    prefs::kManagedImagesAllowedForUrls, prefs::kManagedImagesBlockedForUrls,
+    prefs::kManagedJavaScriptAllowedForUrls,
+    prefs::kManagedJavaScriptBlockedForUrls,
+    prefs::kManagedPluginsAllowedForUrls, prefs::kManagedPluginsBlockedForUrls,
+    prefs::kManagedPopupsAllowedForUrls, prefs::kManagedPopupsBlockedForUrls,
+    prefs::kManagedNotificationsAllowedForUrls,
+    prefs::kManagedNotificationsBlockedForUrls,
+    prefs::kManagedAutoSelectCertificateForUrls,
+    prefs::kManagedWebUsbAskForUrls, prefs::kManagedWebUsbBlockedForUrls,
+
+// components/cryptauth/pref_names.h
+#if defined(CHROMEOS)
+    cryptauth::prefs::kCryptAuthDeviceSyncLastSyncTimeSeconds,
+    cryptauth::prefs::kCryptAuthDeviceSyncIsRecoveringFromFailure,
+    cryptauth::prefs::kCryptAuthDeviceSyncReason,
+    cryptauth::prefs::kCryptAuthDeviceSyncUnlockKeys,
+    cryptauth::prefs::kCryptAuthEnrollmentIsRecoveringFromFailure,
+    cryptauth::prefs::kCryptAuthEnrollmentLastEnrollmentTimeSeconds,
+    cryptauth::prefs::kCryptAuthEnrollmentReason,
+    cryptauth::prefs::kCryptAuthEnrollmentUserPublicKey,
+    cryptauth::prefs::kCryptAuthEnrollmentUserPrivateKey,
+    cryptauth::prefs::kCryptAuthGCMRegistrationId,
+#endif  // defined(CHROMEOS)
+
+    // components/data_reduction_proxy/core/common/
+    // data_reduction_proxy_pref_names.h
+    data_reduction_proxy::prefs::
+        kDailyContentLengthHttpsWithDataReductionProxyEnabled,
+    data_reduction_proxy::prefs::
+        kDailyContentLengthLongBypassWithDataReductionProxyEnabled,
+    data_reduction_proxy::prefs::
+        kDailyContentLengthShortBypassWithDataReductionProxyEnabled,
+    data_reduction_proxy::prefs::
+        kDailyContentLengthUnknownWithDataReductionProxyEnabled,
+    data_reduction_proxy::prefs::kDailyContentLengthViaDataReductionProxy,
+    data_reduction_proxy::prefs::
+        kDailyContentLengthViaDataReductionProxyApplication,
+    data_reduction_proxy::prefs::kDailyContentLengthViaDataReductionProxyVideo,
+    data_reduction_proxy::prefs::
+        kDailyContentLengthViaDataReductionProxyUnknown,
+    data_reduction_proxy::prefs::
+        kDailyContentLengthWithDataReductionProxyEnabled,
+    data_reduction_proxy::prefs::
+        kDailyContentLengthWithDataReductionProxyEnabledApplication,
+    data_reduction_proxy::prefs::
+        kDailyContentLengthWithDataReductionProxyEnabledVideo,
+    data_reduction_proxy::prefs::
+        kDailyContentLengthWithDataReductionProxyEnabledUnknown,
+    data_reduction_proxy::prefs::kDailyHttpContentLengthLastUpdateDate,
+    data_reduction_proxy::prefs::kDailyHttpOriginalContentLength,
+    data_reduction_proxy::prefs::kDailyHttpOriginalContentLengthApplication,
+    data_reduction_proxy::prefs::kDailyHttpOriginalContentLengthVideo,
+    data_reduction_proxy::prefs::kDailyHttpOriginalContentLengthUnknown,
+    data_reduction_proxy::prefs::kDailyHttpReceivedContentLength,
+    data_reduction_proxy::prefs::kDailyHttpReceivedContentLengthApplication,
+    data_reduction_proxy::prefs::kDailyHttpReceivedContentLengthVideo,
+    data_reduction_proxy::prefs::kDailyHttpReceivedContentLengthUnknown,
+    data_reduction_proxy::prefs::
+        kDailyOriginalContentLengthViaDataReductionProxy,
+    data_reduction_proxy::prefs::
+        kDailyOriginalContentLengthViaDataReductionProxyApplication,
+    data_reduction_proxy::prefs::
+        kDailyOriginalContentLengthViaDataReductionProxyVideo,
+    data_reduction_proxy::prefs::
+        kDailyOriginalContentLengthViaDataReductionProxyUnknown,
+    data_reduction_proxy::prefs::
+        kDailyOriginalContentLengthWithDataReductionProxyEnabled,
+    data_reduction_proxy::prefs::
+        kDailyOriginalContentLengthWithDataReductionProxyEnabledApplication,
+    data_reduction_proxy::prefs::
+        kDailyOriginalContentLengthWithDataReductionProxyEnabledVideo,
+    data_reduction_proxy::prefs::
+        kDailyOriginalContentLengthWithDataReductionProxyEnabledUnknown,
+    data_reduction_proxy::prefs::kDataReductionProxy,
+    data_reduction_proxy::prefs::kDataReductionProxyConfig,
+    data_reduction_proxy::prefs::kDataUsageReportingEnabled,
+    data_reduction_proxy::prefs::kDataReductionProxyWasEnabledBefore,
+    data_reduction_proxy::prefs::kDataReductionProxyLastEnabledTime,
+    data_reduction_proxy::prefs::
+        kDataReductionProxySavingsClearedNegativeSystemClock,
+    data_reduction_proxy::prefs::kHttpOriginalContentLength,
+    data_reduction_proxy::prefs::kHttpReceivedContentLength,
+    data_reduction_proxy::prefs::kDataReductionProxyLastConfigRetrievalTime,
+    data_reduction_proxy::prefs::kNetworkProperties,
+
+    data_reduction_proxy::prefs::kThisWeekNumber,
+    data_reduction_proxy::prefs::kThisWeekServicesDownstreamBackgroundKB,
+    data_reduction_proxy::prefs::kThisWeekServicesDownstreamForegroundKB,
+    data_reduction_proxy::prefs::kLastWeekServicesDownstreamBackgroundKB,
+    data_reduction_proxy::prefs::kLastWeekServicesDownstreamForegroundKB,
+    data_reduction_proxy::prefs::kThisWeekUserTrafficContentTypeDownstreamKB,
+    data_reduction_proxy::prefs::kLastWeekUserTrafficContentTypeDownstreamKB,
+
+    // components/dom_distiller/core/pref_names.h
+    dom_distiller::prefs::kFont, dom_distiller::prefs::kTheme,
+    dom_distiller::prefs::kFontScale,
+    dom_distiller::prefs::kReaderForAccessibility,
+
+// components/drive/drive_pref_names.h
+#if defined(OS_CHROMEOS)
+    drive::prefs::kDisableDrive, drive::prefs::kDisableDriveOverCellular,
+    drive::prefs::kDisableDriveHostedFiles,
+#endif  // defined(OS_CHROMEOS)
+
+// components/feed/core/pref_names.h
+#if defined(OS_ANDROID)
+    feed::prefs::kBackgroundRefreshPeriod, feed::prefs::kLastFetchAttemptTime,
+    feed::prefs::kUserClassifierAverageNTPOpenedPerHour,
+    feed::prefs::kUserClassifierAverageSuggestionsUsedPerHour,
+    feed::prefs::kUserClassifierLastTimeToOpenNTP,
+    feed::prefs::kUserClassifierLastTimeToUseSuggestions,
+#endif  // defined(OS_ANDROID)
+
+    // components/flags_ui/flags_ui_pref_names.h
+    flags_ui::prefs::kEnabledLabsExperiments,
+
+    // components/google/core/browser/google_pref_names.h
+    prefs::kLastKnownGoogleURL, prefs::kLastPromptedGoogleURL,
+
+    // components/invalidation/impl/invalidation_prefs.h
+    invalidation::prefs::kInvalidatorClientId,
+    invalidation::prefs::kInvalidatorInvalidationState,
+    invalidation::prefs::kInvalidatorSavedInvalidations,
+    invalidation::prefs::kInvalidationServiceUseGCMChannel,
+
+    // components/language/core/browser/pref_names.h
+    language::prefs::kApplicationLocale, language::prefs::kUserLanguageProfile,
+
+    // components/metrics/metrics_pref_names.h
+    // metrics::prefs::kDeprecatedMetricsInitialLogs,
+    // metrics::prefs::kDeprecatedMetricsOngoingLogs,
+    metrics::prefs::kInstallDate, metrics::prefs::kMetricsClientID,
+    metrics::prefs::kMetricsDefaultOptIn, metrics::prefs::kMetricsInitialLogs,
+    metrics::prefs::kMetricsLowEntropySource, metrics::prefs::kMetricsMachineId,
+    metrics::prefs::kMetricsOngoingLogs, metrics::prefs::kMetricsResetIds,
+
+    metrics::prefs::kMetricsReportingEnabled,
+    metrics::prefs::kMetricsReportingEnabledTimestamp,
+    metrics::prefs::kMetricsSessionID, metrics::prefs::kMetricsLastSeenPrefix,
+
+    // Preferences for recording stability logs.
+    metrics::prefs::kStabilityBreakpadRegistrationFail,
+    metrics::prefs::kStabilityBreakpadRegistrationSuccess,
+    metrics::prefs::kStabilityBrowserLastLiveTimeStamp,
+    metrics::prefs::kStabilityChildProcessCrashCount,
+    metrics::prefs::kStabilityCrashCount,
+    metrics::prefs::kStabilityCrashCountWithoutGmsCoreUpdate,
+    metrics::prefs::kStabilityDebuggerNotPresent,
+    metrics::prefs::kStabilityDebuggerPresent,
+    metrics::prefs::kStabilityDeferredCount,
+    metrics::prefs::kStabilityDiscardCount,
+    metrics::prefs::kStabilityExecutionPhase,
+    metrics::prefs::kStabilityExitedCleanly,
+    metrics::prefs::kStabilityExtensionRendererCrashCount,
+    metrics::prefs::kStabilityExtensionRendererFailedLaunchCount,
+    metrics::prefs::kStabilityExtensionRendererLaunchCount,
+    metrics::prefs::kStabilityGmsCoreVersion,
+    metrics::prefs::kStabilityIncompleteSessionEndCount,
+    metrics::prefs::kStabilityLaunchCount,
+    metrics::prefs::kStabilityPageLoadCount,
+    metrics::prefs::kStabilityRendererCrashCount,
+    metrics::prefs::kStabilityRendererFailedLaunchCount,
+    metrics::prefs::kStabilityRendererHangCount,
+    metrics::prefs::kStabilityRendererLaunchCount,
+    metrics::prefs::kStabilitySavedSystemProfile,
+    metrics::prefs::kStabilitySavedSystemProfileHash,
+    metrics::prefs::kStabilitySessionEndCompleted,
+    metrics::prefs::kStabilityStatsBuildTime,
+    metrics::prefs::kStabilityStatsVersion,
+    metrics::prefs::kStabilitySystemCrashCount,
+    metrics::prefs::kStabilityVersionMismatchCount,
+
+    // Preferences for generating metrics at uninstall time.
+    metrics::prefs::kUninstallLaunchCount,
+    metrics::prefs::kUninstallMetricsPageLoadCount,
+    metrics::prefs::kUninstallMetricsUptimeSec,
+
+    // For measuring data use for throttling UMA log uploads on cellular.
+    metrics::prefs::kUkmCellDataUse, metrics::prefs::kUmaCellDataUse,
+    metrics::prefs::kUserCellDataUse,
+
+    // components/network_time/network_time_pref_names.h
+    network_time::prefs::kNetworkTimeMapping,
+    network_time::prefs::kNetworkTimeQueriesEnabled,
+
+    // components/ntp_snippets/pref_names.h
+    ntp_snippets::prefs::kEnableSnippets,
+    ntp_snippets::prefs::kArticlesListVisible,
+    ntp_snippets::prefs::kRemoteSuggestionCategories,
+    ntp_snippets::prefs::kSnippetLastFetchAttemptTime,
+    ntp_snippets::prefs::kSnippetLastSuccessfulFetchTime,
+    ntp_snippets::prefs::kSnippetPersistentFetchingIntervalWifi,
+    ntp_snippets::prefs::kSnippetPersistentFetchingIntervalFallback,
+    ntp_snippets::prefs::kSnippetStartupFetchingIntervalWifi,
+    ntp_snippets::prefs::kSnippetStartupFetchingIntervalFallback,
+    ntp_snippets::prefs::kSnippetShownFetchingIntervalWifi,
+    ntp_snippets::prefs::kSnippetShownFetchingIntervalFallback,
+    ntp_snippets::prefs::kSnippetFetcherRequestCount,
+    ntp_snippets::prefs::kSnippetFetcherInteractiveRequestCount,
+    ntp_snippets::prefs::kSnippetFetcherRequestsDay,
+    ntp_snippets::prefs::kSnippetThumbnailsRequestCount,
+    ntp_snippets::prefs::kSnippetThumbnailsInteractiveRequestCount,
+    ntp_snippets::prefs::kSnippetThumbnailsRequestsDay,
+    ntp_snippets::prefs::kDismissedAssetDownloadSuggestions,
+    ntp_snippets::prefs::kDismissedForeignSessionsSuggestions,
+    ntp_snippets::prefs::kDismissedOfflinePageDownloadSuggestions,
+    ntp_snippets::prefs::kDismissedCategories,
+    ntp_snippets::prefs::kUserClassifierAverageNTPOpenedPerHour,
+    ntp_snippets::prefs::kUserClassifierAverageSuggestionsShownPerHour,
+    ntp_snippets::prefs::kUserClassifierAverageSuggestionsUsedPerHour,
+    ntp_snippets::prefs::kUserClassifierLastTimeToOpenNTP,
+    ntp_snippets::prefs::kUserClassifierLastTimeToShowSuggestions,
+    ntp_snippets::prefs::kUserClassifierLastTimeToUseSuggestions,
+    ntp_snippets::prefs::kClickBasedCategoryRankerOrderWithClicks,
+    ntp_snippets::prefs::kClickBasedCategoryRankerLastDecayTime,
+    ntp_snippets::prefs::kBreakingNewsSubscriptionDataToken,
+    ntp_snippets::prefs::kBreakingNewsSubscriptionDataIsAuthenticated,
+    ntp_snippets::prefs::kBreakingNewsGCMSubscriptionTokenCache,
+    ntp_snippets::prefs::kBreakingNewsGCMLastTokenValidationTime,
+    ntp_snippets::prefs::kBreakingNewsGCMLastForcedSubscriptionTime,
+
+    // components/ntp_tiles/pref_names.h
+    ntp_tiles::prefs::kNumPersonalTiles,
+
+    ntp_tiles::prefs::kPopularSitesOverrideURL,
+    ntp_tiles::prefs::kPopularSitesOverrideDirectory,
+    ntp_tiles::prefs::kPopularSitesOverrideCountry,
+    ntp_tiles::prefs::kPopularSitesOverrideVersion,
+
+    ntp_tiles::prefs::kPopularSitesLastDownloadPref,
+    ntp_tiles::prefs::kPopularSitesURLPref,
+    ntp_tiles::prefs::kPopularSitesJsonPref,
+    ntp_tiles::prefs::kPopularSitesVersionPref,
+
+    // components/omnibox/browser/omnibox_pref_names.h
+    omnibox::kZeroSuggestCachedResults,
+
+    // components/onc/onc_pref_names.h
+    onc::prefs::kDeviceOpenNetworkConfiguration,
+    onc::prefs::kOpenNetworkConfiguration,
+
+    // components/password_manager/core/common/password_manager_pref_names.h
+    password_manager::prefs::kCredentialsEnableAutosignin,
+    password_manager::prefs::kCredentialsEnableService,
+
+#if !defined(OS_MACOSX) && !defined(OS_CHROMEOS) && defined(OS_POSIX)
+    password_manager::prefs::kLocalProfileId,
+#endif
+
+#if defined(OS_WIN)
+    password_manager::prefs::kOsPasswordBlank,
+    password_manager::prefs::kOsPasswordLastChanged,
+#endif
+
+#if defined(OS_MACOSX)
+    password_manager::prefs::kKeychainMigrationStatus,
+#endif
+
+    password_manager::prefs::kWasAutoSignInFirstRunExperienceShown,
+    password_manager::prefs::kWasSignInPasswordPromoClicked,
+    password_manager::prefs::kNumberSignInPasswordPromoShown,
+    password_manager::prefs::kSyncPasswordHash,
+    password_manager::prefs::kSyncPasswordLengthAndHashSalt,
+    password_manager::prefs::kBlacklistedCredentialsStripped,
+    password_manager::prefs::kPasswordHashDataList,
+
+    // components/policy/core/common/policy_pref_names.h
+    policy::policy_prefs::kLastPolicyStatisticsUpdate,
+    policy::policy_prefs::kUrlBlacklist, policy::policy_prefs::kUrlWhitelist,
+    policy::policy_prefs::kUserPolicyRefreshRate,
+    policy::policy_prefs::kMachineLevelUserCloudPolicyEnrollmentToken,
+
+    // components/proxy_config/proxy_config_pref_names.h
+    // proxy_config::prefs::kProxy,
+    proxy_config::prefs::kUseSharedProxies,
+
+    // components/proxy_config/proxy_prefs.h
+    ProxyPrefs::kDirectProxyModeName, ProxyPrefs::kAutoDetectProxyModeName,
+    ProxyPrefs::kPacScriptProxyModeName, ProxyPrefs::kFixedServersProxyModeName,
+    ProxyPrefs::kSystemProxyModeName,
+
+    // components/rappor/rappor_pref_names.h
+    rappor::prefs::kRapporCohortDeprecated, rappor::prefs::kRapporCohortSeed,
+    rappor::prefs::kRapporLastDailySample, rappor::prefs::kRapporSecret,
+
+    // components/rappor/rappor_prefs.h
+    rappor::internal::kLoadCohortHistogramName,
+    rappor::internal::kLoadSecretHistogramName,
+
+    // components/reading_list/core/reading_list_pref_names.h
+    reading_list::prefs::kReadingListHasUnseenEntries,
+
+    // components/safe_browsing/common/safe_browsing_prefs.h
+    prefs::kSafeBrowsingExtendedReportingOptInAllowed,
+    prefs::kSafeBrowsingIncidentsSent,
+    prefs::kSafeBrowsingProceedAnywayDisabled,
+    prefs::kSafeBrowsingSawInterstitialExtendedReporting,
+    prefs::kSafeBrowsingSawInterstitialScoutReporting,
+    prefs::kSafeBrowsingScoutGroupSelected,
+    prefs::kSafeBrowsingScoutReportingEnabled,
+    prefs::kSafeBrowsingTriggerEventTimestamps,
+    prefs::kSafeBrowsingUnhandledSyncPasswordReuses,
+    prefs::kSafeBrowsingWhitelistDomains,
+    prefs::kPasswordProtectionChangePasswordURL,
+    prefs::kPasswordProtectionLoginURLs,
+    prefs::kPasswordProtectionWarningTrigger,
+
+    // components/search_engines/search_engines_pref_names.h
+    prefs::kSyncedDefaultSearchProviderGUID,
+    prefs::kDefaultSearchProviderEnabled, prefs::kSearchProviderOverrides,
+    prefs::kSearchProviderOverridesVersion, prefs::kCountryIDAtInstall,
+
+// components/signin/core/browser/signin_pref_names.h
+#if defined(OS_CHROMEOS)
+    prefs::kAccountConsistencyMirrorRequired,
+#endif
+    prefs::kAccountIdMigrationState, prefs::kAutologinEnabled,
+    prefs::kGaiaCookieHash, prefs::kGaiaCookieChangedTime,
+    prefs::kGaiaCookiePeriodicReportTime, prefs::kGoogleServicesAccountId,
+    prefs::kGoogleServicesHostedDomain, prefs::kGoogleServicesLastAccountId,
+    prefs::kGoogleServicesLastUsername,
+    prefs::kGoogleServicesSigninScopedDeviceId,
+    prefs::kGoogleServicesUserAccountId, prefs::kGoogleServicesUsername,
+    prefs::kGoogleServicesUsernamePattern, prefs::kReverseAutologinEnabled,
+    prefs::kReverseAutologinRejectedEmailList, prefs::kSignedInTime,
+    prefs::kSigninAllowed, prefs::kTokenServiceDiceCompatible,
+    prefs::kTokenServiceExcludeAllSecondaryAccounts,
+    prefs::kTokenServiceExcludedSecondaryAccounts,
+
+    // components/spellcheck/browser/pref_names.h
+    spellcheck::prefs::kSpellCheckEnable,
+    spellcheck::prefs::kSpellCheckDictionaries,
+    spellcheck::prefs::kSpellCheckForcedDictionaries,
+    spellcheck::prefs::kSpellCheckDictionary,
+    spellcheck::prefs::kSpellCheckUseSpellingService,
+
+    // components/startup_metric_utils/browser/pref_names.h
+    startup_metric_utils::prefs::kLastStartupTimestamp,
+    startup_metric_utils::prefs::kLastStartupVersion,
+    startup_metric_utils::prefs::kSameVersionStartupCount,
+
+    // components/suggestions/suggestions_pref_names.h
+    suggestions::prefs::kSuggestionsBlacklist,
+    suggestions::prefs::kSuggestionsData,
+
+    // components/sync/base/pref_names.h
+    syncer::prefs::kSyncLastSyncedTime, syncer::prefs::kSyncLastPollTime,
+    syncer::prefs::kSyncShortPollIntervalSeconds,
+    syncer::prefs::kSyncLongPollIntervalSeconds,
+    syncer::prefs::kSyncHasAuthError, syncer::prefs::kSyncFirstSetupComplete,
+    syncer::prefs::kSyncKeepEverythingSynced, syncer::prefs::kSyncAppList,
+    syncer::prefs::kSyncAppNotifications, syncer::prefs::kSyncAppSettings,
+    syncer::prefs::kSyncApps, syncer::prefs::kSyncArcPackage,
+    syncer::prefs::kSyncArticles, syncer::prefs::kSyncAutofillProfile,
+    syncer::prefs::kSyncAutofillWallet,
+    syncer::prefs::kSyncAutofillWalletMetadata, syncer::prefs::kSyncAutofill,
+    syncer::prefs::kSyncBookmarks, syncer::prefs::kSyncDeviceInfo,
+    syncer::prefs::kSyncDictionary, syncer::prefs::kSyncExtensionSettings,
+    syncer::prefs::kSyncExtensions, syncer::prefs::kSyncFaviconImages,
+    syncer::prefs::kSyncFaviconTracking,
+    syncer::prefs::kSyncHistoryDeleteDirectives,
+    syncer::prefs::kSyncMountainShares, syncer::prefs::kSyncPasswords,
+    syncer::prefs::kSyncPreferences, syncer::prefs::kSyncPriorityPreferences,
+    syncer::prefs::kSyncPrinters, syncer::prefs::kSyncReadingList,
+    syncer::prefs::kSyncSearchEngines, syncer::prefs::kSyncSessions,
+    syncer::prefs::kSyncSupervisedUserSettings,
+    syncer::prefs::kSyncSupervisedUserSharedSettings,
+    syncer::prefs::kSyncSupervisedUserWhitelists,
+    syncer::prefs::kSyncSupervisedUsers,
+    syncer::prefs::kSyncSyncedNotificationAppInfo,
+    syncer::prefs::kSyncSyncedNotifications, syncer::prefs::kSyncTabs,
+    syncer::prefs::kSyncThemes, syncer::prefs::kSyncTypedUrls,
+    syncer::prefs::kSyncUserConsents, syncer::prefs::kSyncUserEvents,
+    syncer::prefs::kSyncWifiCredentials, syncer::prefs::kSyncManaged,
+    syncer::prefs::kSyncSuppressStart,
+    syncer::prefs::kSyncEncryptionBootstrapToken,
+    syncer::prefs::kSyncKeystoreEncryptionBootstrapToken,
+    syncer::prefs::kSyncSessionsGUID,
+
+#if defined(OS_CHROMEOS)
+    syncer::prefs::kSyncSpareBootstrapToken,
+#endif  // defined(OS_CHROMEOS)
+
+    syncer::prefs::kSyncFirstSyncTime, syncer::prefs::kSyncPassphrasePrompted,
+    syncer::prefs::kSyncMemoryPressureWarningCount,
+    syncer::prefs::kSyncShutdownCleanly,
+    syncer::prefs::kSyncInvalidationVersions,
+    syncer::prefs::kSyncLastRunVersion,
+    syncer::prefs::kSyncPassphraseEncryptionTransitionInProgress,
+    syncer::prefs::kSyncNigoriStateForPassphraseTransition,
+    syncer::prefs::kEnableLocalSyncBackend, syncer::prefs::kLocalSyncBackendDir,
+
+    // components/translate/core/browser/translate_pref_names.h
+    prefs::kOfferTranslateEnabled,
+
+    // components/translate/core/browser/translate_prefs.h
+    // translate::TranslatePrefs::kPrefLanguageProfile,
+    // translate::TranslatePrefs::kPrefForceTriggerTranslateCount,
+    // translate::TranslatePrefs::kPrefTranslateSiteBlacklist,
+    // translate::TranslatePrefs::kPrefTranslateWhitelists,
+    translate::TranslatePrefs::kPrefTranslateDeniedCount,
+    translate::TranslatePrefs::kPrefTranslateIgnoredCount,
+    translate::TranslatePrefs::kPrefTranslateAcceptedCount,
+    // translate::TranslatePrefs::kPrefTranslateBlockedLanguages,
+    translate::TranslatePrefs::kPrefTranslateLastDeniedTimeForLanguage,
+    translate::TranslatePrefs::kPrefTranslateTooOftenDeniedForLanguage,
+    translate::TranslatePrefs::kPrefTranslateRecentTarget,
+#if defined(OS_ANDROID)
+    translate::TranslatePrefs::kPrefTranslateAutoAlwaysCount,
+    translate::TranslatePrefs::kPrefTranslateAutoNeverCount,
+#endif
+
+    // components/ukm/ukm_pref_names.h
+    ukm::prefs::kUkmClientId, ukm::prefs::kUkmPersistedLogs,
+    ukm::prefs::kUkmSessionId,
+
+    // components/unified_consent/pref_names.h
+    unified_consent::prefs::kUnifiedConsentGiven,
+    unified_consent::prefs::kUnifiedConsentMigrationState,
+    unified_consent::prefs::kUrlKeyedAnonymizedDataCollectionEnabled,
+
+    // components/variations/pref_names.h
+    variations::prefs::kVariationsCompressedSeed,
+    variations::prefs::kVariationsCountry,
+    variations::prefs::kVariationsCrashStreak,
+    variations::prefs::kVariationsFailedToFetchSeedStreak,
+    variations::prefs::kVariationsLastFetchTime,
+    variations::prefs::kVariationsPermanentConsistencyCountry,
+    variations::prefs::kVariationsPermutedEntropyCache,
+    variations::prefs::kVariationsRestrictParameter,
+    variations::prefs::kVariationsSafeCompressedSeed,
+    variations::prefs::kVariationsSafeSeedDate,
+    variations::prefs::kVariationsSafeSeedFetchTime,
+    variations::prefs::kVariationsSafeSeedLocale,
+    variations::prefs::kVariationsSafeSeedPermanentConsistencyCountry,
+    variations::prefs::kVariationsSafeSeedSessionConsistencyCountry,
+    variations::prefs::kVariationsSafeSeedSignature,
+    variations::prefs::kVariationsSeedDate,
+    variations::prefs::kVariationsSeedSignature,
+
+    // components/web_resource/web_resource_pref_names.h
+    prefs::kEulaAccepted,
+
+// extensions/browser/api/audio/pref_names.h
+#if !defined(OS_ANDROID)
+    extensions::kAudioApiStableDeviceIds,
+#endif  // !defined(OS_ANDROID)
+
+// extensions/browser/pref_names.h
+#if !defined(OS_ANDROID)
+    extensions::pref_names::kAlertsInitialized,
+    extensions::pref_names::kAllowedInstallSites,
+    extensions::pref_names::kAllowedTypes,
+    extensions::pref_names::kAppFullscreenAllowed,
+    extensions::pref_names::kBookmarkAppCreationLaunchType,
+    extensions::pref_names::kExtensions,
+    extensions::pref_names::kExtensionManagement,
+    extensions::pref_names::kInstallAllowList,
+    extensions::pref_names::kInstallDenyList,
+    extensions::pref_names::kInstallForceList,
+    extensions::pref_names::kInstallLoginScreenAppList,
+    extensions::pref_names::kLastChromeVersion,
+    extensions::pref_names::kLastUpdateCheck,
+    extensions::pref_names::kNativeMessagingBlacklist,
+    extensions::pref_names::kNativeMessagingWhitelist,
+    extensions::pref_names::kNativeMessagingUserLevelHosts,
+    extensions::pref_names::kNextUpdateCheck,
+    extensions::pref_names::kStorageGarbageCollect,
+    extensions::pref_names::kToolbar, extensions::pref_names::kToolbarSize,
+    extensions::pref_names::kPrefPreferences,
+    extensions::pref_names::kPrefIncognitoPreferences,
+    extensions::pref_names::kPrefRegularOnlyPreferences,
+    extensions::pref_names::kPrefContentSettings,
+    extensions::pref_names::kPrefIncognitoContentSettings,
+#endif  //! defined(OS_ANDROID)
+
+    // services/preferences/public/cpp/tracked/pref_names.h
+    user_prefs::kPreferenceResetTime,
+
+// ui/base/ime/chromeos/extension_ime_util.h
+#if defined(OS_CHROMEOS)
+    chromeos::extension_ime_util::kBrailleImeExtensionId,
+    chromeos::extension_ime_util::kBrailleImeExtensionPath,
+
+    // TODO(https://crbug.com/861722): Check with code owners why this pref is
+    // required in tests, if possible, update tests and remove.
+    chromeos::extension_ime_util::kBrailleImeEngineId,
+    chromeos::extension_ime_util::kArcImeLanguage,
+#endif  // defined(OS_CHROMEOS)
+
+// ui/chromeos/events/pref_names.h
+#if defined(OS_CHROMEOS)
+    prefs::kLanguageRemapCapsLockKeyTo, prefs::kLanguageRemapSearchKeyTo,
+    prefs::kLanguageRemapControlKeyTo, prefs::kLanguageRemapAltKeyTo,
+    prefs::kLanguageRemapEscapeKeyTo, prefs::kLanguageRemapBackspaceKeyTo,
+    prefs::kLanguageRemapDiamondKeyTo,
+#endif  // defined(OS_CHROMEOS)
+};
+
+}  // namespace
+
+namespace prefs {
+
+// TODO(https://crbug.com/861722): Remove this function and file.
+// WARNING: PLEASE DO NOT ADD ANYTHING TO THIS FILE.
+// This is temporarily added for transition of incognito preferences
+// storage default, from on disk to in memory. All items in this list will be
+// audited and checked with owners and removed from whitelist.
+void GetIncognitoWhitelist(std::vector<const char*>* whitelist) {
+  whitelist->insert(
+      whitelist->end(), incognito_whitelist,
+      incognito_whitelist + sizeof(incognito_whitelist) / sizeof(char*));
+}
+
+}  // namespace prefs
diff --git a/chrome/browser/prefs/pref_service_incognito_whitelist.h b/chrome/browser/prefs/pref_service_incognito_whitelist.h
new file mode 100644
index 0000000..15f53b0
--- /dev/null
+++ b/chrome/browser/prefs/pref_service_incognito_whitelist.h
@@ -0,0 +1,18 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_PREFS_PREF_SERVICE_INCOGNITO_WHITELIST_H_
+#define CHROME_BROWSER_PREFS_PREF_SERVICE_INCOGNITO_WHITELIST_H_
+
+#include <vector>
+
+namespace prefs {
+
+// Populate a whitelist of all preferences that are stored on disk in incognito
+// mode. Please refere to the comments in .cc file.
+void GetIncognitoWhitelist(std::vector<const char*>* whitelist);
+
+}  // namespace prefs
+
+#endif  // CHROME_BROWSER_PREFS_PREF_SERVICE_INCOGNITO_WHITELIST_H_
diff --git a/chrome/browser/prefs/pref_service_syncable_util.cc b/chrome/browser/prefs/pref_service_syncable_util.cc
index 198965a..6e1755d 100644
--- a/chrome/browser/prefs/pref_service_syncable_util.cc
+++ b/chrome/browser/prefs/pref_service_syncable_util.cc
@@ -6,16 +6,10 @@
 
 #include <vector>
 
-#include "base/logging.h"
-#include "build/build_config.h"
+#include "chrome/browser/prefs/pref_service_incognito_whitelist.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/common/pref_names.h"
 #include "components/sync_preferences/pref_service_syncable.h"
-#include "components/translate/core/browser/translate_prefs.h"
 
-#if defined(OS_ANDROID)
-#include "components/proxy_config/proxy_config_pref_names.h"
-#endif
 
 sync_preferences::PrefServiceSyncable* PrefServiceSyncableFromProfile(
     Profile* profile) {
@@ -34,22 +28,20 @@
     sync_preferences::PrefServiceSyncable* pref_service,
     PrefStore* incognito_extension_pref_store,
     std::unique_ptr<PrefValueStore::Delegate> delegate) {
-  // List of keys that cannot be changed in the user prefs file by the incognito
-  // profile.  All preferences that store information about the browsing history
-  // or behavior of the user should have this property.
-  std::vector<const char*> overlay_pref_names;
-  overlay_pref_names.push_back(prefs::kBrowserWindowPlacement);
-  overlay_pref_names.push_back(prefs::kMediaRouterTabMirroringSources);
-  overlay_pref_names.push_back(prefs::kSaveFileDefaultDirectory);
-  overlay_pref_names.push_back(
-      translate::TranslatePrefs::kPrefTranslateSiteBlacklist);
-  overlay_pref_names.push_back(
-      translate::TranslatePrefs::kPrefTranslateBlockedLanguages);
-  overlay_pref_names.push_back(
-      translate::TranslatePrefs::kPrefTranslateWhitelists);
-#if defined(OS_ANDROID)
-  overlay_pref_names.push_back(proxy_config::prefs::kProxy);
-#endif
+  // List of keys that can be changed in the user prefs file by the incognito
+  // profile.
+  std::vector<const char*> persistent_pref_names;
+
+  // TODO(https://crbug.com/861722): Remove |GetIncognitoWhitelist| and its
+  // file. This list is ONLY added for transition of code from blacklist to
+  // whitelist. All whitelisted prefs can be added here to
+  // |persistent_pref_names|.
+  prefs::GetIncognitoWhitelist(&persistent_pref_names);
+
+  // TODO(https://crbug.com/861722): Current implementation does not cover
+  // preferences from iOS. The code should be refactored to cover it.
+
   return pref_service->CreateIncognitoPrefService(
-      incognito_extension_pref_store, overlay_pref_names, std::move(delegate));
+      incognito_extension_pref_store, persistent_pref_names,
+      std::move(delegate));
 }
diff --git a/chrome/browser/resources/settings/people_page/BUILD.gn b/chrome/browser/resources/settings/people_page/BUILD.gn
index 386d06d55..6426f36 100644
--- a/chrome/browser/resources/settings/people_page/BUILD.gn
+++ b/chrome/browser/resources/settings/people_page/BUILD.gn
@@ -7,6 +7,7 @@
 js_type_check("closure_compile") {
   deps = [
     ":account_manager",
+    ":account_manager_browser_proxy",
     ":change_picture",
     ":change_picture_browser_proxy",
     ":easy_unlock_browser_proxy",
@@ -37,9 +38,17 @@
 
 js_library("account_manager") {
   deps = [
+    ":account_manager_browser_proxy",
     "//ui/webui/resources/js:cr",
     "//ui/webui/resources/js:i18n_behavior",
     "//ui/webui/resources/js:icon",
+    "//ui/webui/resources/js:web_ui_listener_behavior",
+  ]
+}
+
+js_library("account_manager_browser_proxy") {
+  deps = [
+    "//ui/webui/resources/js:cr",
   ]
 }
 
diff --git a/chrome/browser/resources/settings/people_page/account_manager.html b/chrome/browser/resources/settings/people_page/account_manager.html
index 7ad4dd0..95750103 100644
--- a/chrome/browser/resources/settings/people_page/account_manager.html
+++ b/chrome/browser/resources/settings/people_page/account_manager.html
@@ -3,9 +3,11 @@
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
 <link rel="import" href="chrome://resources/html/util.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html">
+<link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
 <link rel="import" href="../i18n_setup.html">
 <link rel="import" href="../route.html">
 <link rel="import" href="../settings_shared_css.html">
+<link rel="import" href="account_manager_browser_proxy.html">
 
 <dom-module id="settings-account-manager">
   <template>
@@ -23,6 +25,10 @@
         margin-right: auto;
         width: 90%;
       }
+
+      #add-account-button {
+        cursor: pointer;
+      }
     </style>
     <div class="settings-box first">$i18n{accountManagerDescription}</div>
     <div class="settings-box first">
@@ -41,6 +47,9 @@
           </div>
         </div>
       </template>
+      <div id="add-account-button" class="settings-box" on-tap="addAccount_">
+        $i18n{addAccountLabel}
+      </div>
       <div class="clear settings-box"></div>
     </div>
   </template>
diff --git a/chrome/browser/resources/settings/people_page/account_manager.js b/chrome/browser/resources/settings/people_page/account_manager.js
index b3d4c9b..f0c6ae8 100644
--- a/chrome/browser/resources/settings/people_page/account_manager.js
+++ b/chrome/browser/resources/settings/people_page/account_manager.js
@@ -8,27 +8,18 @@
  * list, add and delete Secondary Google Accounts.
  */
 
-/**
- * Information for an account managed by Chrome OS AccountManager.
- * @typedef {{
- *   fullName: string,
- *   email: string,
- *   pic: string,
- * }}
- */
-let Account;
-
 Polymer({
   is: 'settings-account-manager',
 
   behaviors: [
     I18nBehavior,
+    WebUIListenerBehavior,
   ],
 
   properties: {
     /**
      * List of Accounts.
-     * @type {!Array<Account>}
+     * @type {!Array<settings.Account>}
      */
     accounts_: {
       type: Array,
@@ -38,18 +29,43 @@
     },
   },
 
+  /** @private {?settings.AccountManagerBrowserProxy} */
+  browserProxy_: null,
+
+  /** @override */
+  attached: function() {
+    this.addWebUIListener('accounts-changed', this.refreshAccounts_.bind(this));
+  },
+
   /** @override */
   ready: function() {
-    cr.sendWithPromise('getAccounts').then(accounts => {
-      this.set('accounts_', accounts);
-    });
+    this.browserProxy_ = settings.AccountManagerBrowserProxyImpl.getInstance();
+    this.refreshAccounts_();
   },
 
   /**
    * @param {string} iconUrl
    * @return {string} A CSS image-set for multiple scale factors.
-   * @private */
+   * @private
+   */
   getIconImageSet_: function(iconUrl) {
     return cr.icon.getImage(iconUrl);
   },
+
+  /**
+   * @param {!Event} event
+   * @private
+   */
+  addAccount_: function(event) {
+    this.browserProxy_.addAccount();
+  },
+
+  /**
+   * @private
+   */
+  refreshAccounts_: function() {
+    this.browserProxy_.getAccounts().then(accounts => {
+      this.set('accounts_', accounts);
+    });
+  },
 });
diff --git a/chrome/browser/resources/settings/people_page/account_manager_browser_proxy.html b/chrome/browser/resources/settings/people_page/account_manager_browser_proxy.html
new file mode 100644
index 0000000..7228ead
--- /dev/null
+++ b/chrome/browser/resources/settings/people_page/account_manager_browser_proxy.html
@@ -0,0 +1 @@
+<script src="account_manager_browser_proxy.js"></script>
diff --git a/chrome/browser/resources/settings/people_page/account_manager_browser_proxy.js b/chrome/browser/resources/settings/people_page/account_manager_browser_proxy.js
new file mode 100644
index 0000000..c1257ad
--- /dev/null
+++ b/chrome/browser/resources/settings/people_page/account_manager_browser_proxy.js
@@ -0,0 +1,58 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview A helper object used from the "Google accounts" subsection of
+ * the "People" section of Settings, to interact with the browser. Chrome OS
+ * only.
+ */
+cr.exportPath('settings');
+
+/**
+ * Information for an account managed by Chrome OS AccountManager.
+ * @typedef {{
+ *   fullName: string,
+ *   email: string,
+ *   pic: string,
+ * }}
+ */
+settings.Account;
+
+cr.define('settings', function() {
+  /** @interface */
+  class AccountManagerBrowserProxy {
+    /**
+     * Returns a Promise for the list of GAIA accounts held in AccountManager.
+     * @return {!Promise<!Array<settings.Account>>}
+     */
+    getAccounts() {}
+
+    /**
+     * Triggers the 'Add account' flow.
+     */
+    addAccount() {}
+  }
+
+  /**
+   * @implements {settings.AccountManagerBrowserProxy}
+   */
+  class AccountManagerBrowserProxyImpl {
+    /** @override */
+    getAccounts() {
+      return cr.sendWithPromise('getAccounts');
+    }
+
+    /** @override */
+    addAccount() {
+      chrome.send('addAccount');
+    }
+  }
+
+  cr.addSingletonGetter(AccountManagerBrowserProxyImpl);
+
+  return {
+    AccountManagerBrowserProxy: AccountManagerBrowserProxy,
+    AccountManagerBrowserProxyImpl: AccountManagerBrowserProxyImpl,
+  };
+});
diff --git a/chrome/browser/resources/settings/settings_resources.grd b/chrome/browser/resources/settings/settings_resources.grd
index 3e10295..1d1120ef 100644
--- a/chrome/browser/resources/settings/settings_resources.grd
+++ b/chrome/browser/resources/settings/settings_resources.grd
@@ -1368,6 +1368,16 @@
                    file="people_page/account_manager.js"
                    type="chrome_html"
                    preprocess="true" />
+        <structure
+            name="IDR_SETTINGS_PEOPLE_PAGE_ACCOUNT_MANAGER_BROWSER_PROXY_HTML"
+                   file="people_page/account_manager_browser_proxy.html"
+                   type="chrome_html"
+                   preprocess="true" />
+        <structure
+            name="IDR_SETTINGS_PEOPLE_PAGE_ACCOUNT_MANAGER_BROWSER_PROXY_JS"
+                   file="people_page/account_manager_browser_proxy.js"
+                   type="chrome_html"
+                   preprocess="true" />
         <structure name="IDR_SETTINGS_PEOPLE_PAGE_CHANGE_PICTURE_HTML"
                    file="people_page/change_picture.html"
                    type="chrome_html"
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index b1e13ab5..ba825b07 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -2145,6 +2145,8 @@
       "webui/settings/tts_handler.h",
       "webui/signin/inline_login_handler_chromeos.cc",
       "webui/signin/inline_login_handler_chromeos.h",
+      "webui/signin/inline_login_handler_dialog_chromeos.cc",
+      "webui/signin/inline_login_handler_dialog_chromeos.h",
       "webui/version_handler_chromeos.cc",
       "webui/version_handler_chromeos.h",
       "window_sizer/window_sizer_ash.cc",
diff --git a/chrome/browser/ui/cocoa/apps/native_app_window_cocoa.mm b/chrome/browser/ui/cocoa/apps/native_app_window_cocoa.mm
index 4800874..f8d4517 100644
--- a/chrome/browser/ui/cocoa/apps/native_app_window_cocoa.mm
+++ b/chrome/browser/ui/cocoa/apps/native_app_window_cocoa.mm
@@ -44,7 +44,7 @@
 
 using extensions::AppWindow;
 
-@interface NSWindow (NSPrivateApis)
+@interface NSWindow (NSPrivateNativeAppWindowApis)
 - (void)setBottomCornerRounded:(BOOL)rounded;
 - (BOOL)_isTitleHidden;
 @end
diff --git a/chrome/browser/ui/cocoa/browser_window_controller_private.mm b/chrome/browser/ui/cocoa/browser_window_controller_private.mm
index a35b1b3..27fe1aef 100644
--- a/chrome/browser/ui/cocoa/browser_window_controller_private.mm
+++ b/chrome/browser/ui/cocoa/browser_window_controller_private.mm
@@ -57,7 +57,7 @@
 using content::RenderWidgetHostView;
 using content::WebContents;
 
-@interface NSView (PrivateAPI)
+@interface NSView (PrivateBrowserWindowControllerAPI)
 // Returns the fullscreen button's origin in window coordinates. This method is
 // only available on NSThemeFrame (the contentView's superview), and it should
 // not be relied on to exist on macOS >10.9 (which doesn't have a separate
@@ -80,7 +80,7 @@
 
 }  // namespace
 
-@interface NSWindow (NSPrivateApis)
+@interface NSWindow (NSPrivateBrowserWindowControllerApis)
 // Note: These functions are private, use -[NSObject respondsToSelector:]
 // before calling them.
 - (NSWindow*)_windowForToolbar;
diff --git a/chrome/browser/ui/cocoa/tabbed_browser_window.mm b/chrome/browser/ui/cocoa/tabbed_browser_window.mm
index 38163a1..1d7f07d 100644
--- a/chrome/browser/ui/cocoa/tabbed_browser_window.mm
+++ b/chrome/browser/ui/cocoa/tabbed_browser_window.mm
@@ -36,7 +36,7 @@
     __attribute__((availability(macos, obsoleted = 10.10)));
 @end
 
-@interface NSWindow (PrivateAPI)
+@interface NSWindow (PrivateTabbedBrowserWindowAPI)
 + (Class)frameViewClassForStyleMask:(NSUInteger)windowStyle;
 @end
 
@@ -125,7 +125,7 @@
   return styleMask;
 }
 
-// NSWindow (PrivateAPI) overrides.
+// NSWindow (PrivateTabbedBrowserWindowAPI) overrides.
 
 + (Class)frameViewClassForStyleMask:(NSUInteger)windowStyle {
   // Because NSThemeFrame is imported weakly, if it's not present at runtime
diff --git a/chrome/browser/ui/cocoa/tabs/tab_strip_controller.mm b/chrome/browser/ui/cocoa/tabs/tab_strip_controller.mm
index bfd79bb1..72cd8916 100644
--- a/chrome/browser/ui/cocoa/tabs/tab_strip_controller.mm
+++ b/chrome/browser/ui/cocoa/tabs/tab_strip_controller.mm
@@ -150,7 +150,7 @@
 
 }  // namespace
 
-@interface NSView (PrivateAPI)
+@interface NSView (PrivateTabStripControllerAPI)
 // Called by AppKit to check if dragging this view should move the window.
 // NSButton overrides this method in the same way so dragging window buttons
 // has no effect. NSView implementation returns NSZeroRect so the whole view
diff --git a/chrome/browser/ui/cocoa/tabs/tab_view.mm b/chrome/browser/ui/cocoa/tabs/tab_view.mm
index e505757..fcff9ca7e 100644
--- a/chrome/browser/ui/cocoa/tabs/tab_view.mm
+++ b/chrome/browser/ui/cocoa/tabs/tab_view.mm
@@ -60,7 +60,7 @@
 // has moved less than the threshold, we want to close the tab.
 const CGFloat kRapidCloseDist = 2.5;
 
-@interface NSView (PrivateAPI)
+@interface NSView (PrivateTabViewAPI)
 // Called by AppKit to check if dragging this view should move the window.
 // NSButton overrides this method in the same way so dragging window buttons
 // has no effect. NSView implementation returns NSZeroRect so the whole view
diff --git a/chrome/browser/ui/views/chrome_browser_main_extra_parts_views.cc b/chrome/browser/ui/views/chrome_browser_main_extra_parts_views.cc
index b23e26b4..51f7bd6 100644
--- a/chrome/browser/ui/views/chrome_browser_main_extra_parts_views.cc
+++ b/chrome/browser/ui/views/chrome_browser_main_extra_parts_views.cc
@@ -150,24 +150,17 @@
 void ChromeBrowserMainExtraPartsViews::ServiceManagerConnectionStarted(
     content::ServiceManagerConnection* connection) {
   DCHECK(connection);
-#if defined(USE_AURA)
-  if (aura::Env::GetInstance()->mode() == aura::Env::Mode::LOCAL)
-    return;
-
 #if defined(OS_CHROMEOS)
-  // Start up the window service and the ash system UI service.
-  if (!features::IsAshInBrowserProcess()) {
-    connection->GetConnector()->StartService(
-        service_manager::Identity(ui::mojom::kServiceName));
-    connection->GetConnector()->StartService(
-        service_manager::Identity(ash::mojom::kServiceName));
+  if (aura::Env::GetInstance()->mode() == aura::Env::Mode::LOCAL ||
+      features::IsAshInBrowserProcess()) {
+    return;
   }
-#endif
 
-#if defined(OS_CHROMEOS)
-  if (features::IsAshInBrowserProcess())
-    return;
-#endif
+  // Start up the window service and the ash system UI service.
+  connection->GetConnector()->StartService(
+      service_manager::Identity(ui::mojom::kServiceName));
+  connection->GetConnector()->StartService(
+      service_manager::Identity(ash::mojom::kServiceName));
 
   views::MusClient::InitParams params;
   params.connector = connection->GetConnector();
@@ -175,8 +168,9 @@
       content::BrowserThread::IO);
   // WMState is owned as a member, so don't have MusClient create it.
   params.create_wm_state = false;
+  params.wtc_config = aura::WindowTreeClient::Config::kMus2;
   mus_client_ = std::make_unique<views::MusClient>(params);
-#endif  // defined(USE_AURA)
+#endif  // defined(OS_CHROMEOS)
 }
 
 void ChromeBrowserMainExtraPartsViews::PostBrowserStart() {
diff --git a/chrome/browser/ui/views/frame/browser_native_widget_window_mac.mm b/chrome/browser/ui/views/frame/browser_native_widget_window_mac.mm
index 1b97762..13b3ec6 100644
--- a/chrome/browser/ui/views/frame/browser_native_widget_window_mac.mm
+++ b/chrome/browser/ui/views/frame/browser_native_widget_window_mac.mm
@@ -13,11 +13,11 @@
 #include "chrome/browser/ui/views/frame/browser_view.h"
 #include "ui/views/widget/widget.h"
 
-@interface NSWindow (PrivateAPI)
+@interface NSWindow (PrivateBrowserNativeWidgetAPI)
 + (Class)frameViewClassForStyleMask:(NSUInteger)windowStyle;
 @end
 
-@interface NSThemeFrame (PrivateAPI)
+@interface NSThemeFrame (PrivateBrowserNativeWidgetAPI)
 - (CGFloat)_titlebarHeight;
 - (void)setStyleMask:(NSUInteger)styleMask;
 @end
diff --git a/chrome/browser/ui/webui/settings/chromeos/account_manager_handler.cc b/chrome/browser/ui/webui/settings/chromeos/account_manager_handler.cc
index aba28c25..9090944 100644
--- a/chrome/browser/ui/webui/settings/chromeos/account_manager_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/account_manager_handler.cc
@@ -14,6 +14,7 @@
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h"
+#include "chrome/browser/ui/webui/signin/inline_login_handler_dialog_chromeos.h"
 #include "chromeos/account_manager/account_manager.h"
 #include "chromeos/account_manager/account_manager_factory.h"
 #include "components/signin/core/browser/account_tracker_service.h"
@@ -29,15 +30,25 @@
     AccountTrackerService* account_tracker_service)
     : account_manager_(account_manager),
       account_tracker_service_(account_tracker_service),
-      weak_factory_(this) {}
+      weak_factory_(this) {
+  account_manager_->AddObserver(this);
+  account_tracker_service_->AddObserver(this);
+}
 
-AccountManagerUIHandler::~AccountManagerUIHandler() = default;
+AccountManagerUIHandler::~AccountManagerUIHandler() {
+  account_manager_->RemoveObserver(this);
+  account_tracker_service_->RemoveObserver(this);
+}
 
 void AccountManagerUIHandler::RegisterMessages() {
   web_ui()->RegisterMessageCallback(
       "getAccounts",
       base::BindRepeating(&AccountManagerUIHandler::HandleGetAccounts,
                           weak_factory_.GetWeakPtr()));
+  web_ui()->RegisterMessageCallback(
+      "addAccount",
+      base::BindRepeating(&AccountManagerUIHandler::HandleAddAccount,
+                          weak_factory_.GetWeakPtr()));
 }
 
 void AccountManagerUIHandler::HandleGetAccounts(const base::ListValue* args) {
@@ -71,6 +82,12 @@
         account_tracker_service_->FindAccountInfoByGaiaId(account_key.id);
     DCHECK(!account_info.IsEmpty());
 
+    if (account_info.full_name.empty()) {
+      // Account info has not been fully fetched yet from GAIA. Ignore this
+      // account.
+      continue;
+    }
+
     base::DictionaryValue account;
     account.SetString("fullName", account_info.full_name);
     account.SetString("email", account_info.email);
@@ -96,9 +113,52 @@
   ResolveJavascriptCallback(callback_id, accounts);
 }
 
+void AccountManagerUIHandler::HandleAddAccount(const base::ListValue* args) {
+  AllowJavascript();
+  InlineLoginHandlerDialogChromeOS::Show();
+}
+
 void AccountManagerUIHandler::OnJavascriptAllowed() {}
 
 void AccountManagerUIHandler::OnJavascriptDisallowed() {}
 
+// |AccountManager::Observer| overrides.
+// Note: We need to listen on |AccountManager| in addition to
+// |AccountTrackerService| because there is no guarantee that |AccountManager|
+// (our source of truth) will have a newly added account by the time
+// |AccountTrackerService| has it.
+void AccountManagerUIHandler::OnTokenUpserted(
+    const AccountManager::AccountKey& account_key) {
+  RefreshUI();
+}
+
+void AccountManagerUIHandler::OnAccountRemoved(
+    const AccountManager::AccountKey& account_key) {
+  RefreshUI();
+}
+
+// |AccountTrackerService::Observer| overrides.
+// For newly added accounts, |AccountTrackerService| may take some time to
+// fetch user's full name and account image. Whenever that is completed, we
+// may need to update the UI with this new set of information.
+// Note that we may be listening to |AccountTrackerService| but we still
+// consider |AccountManager| to be the source of truth for account list.
+void AccountManagerUIHandler::OnAccountUpdated(const AccountInfo& info) {
+  RefreshUI();
+}
+
+void AccountManagerUIHandler::OnAccountImageUpdated(
+    const std::string& account_id,
+    const gfx::Image& image) {
+  RefreshUI();
+}
+
+void AccountManagerUIHandler::OnAccountRemoved(const AccountInfo& account_key) {
+}
+
+void AccountManagerUIHandler::RefreshUI() {
+  FireWebUIListener("accounts-changed");
+}
+
 }  // namespace settings
 }  // namespace chromeos
diff --git a/chrome/browser/ui/webui/settings/chromeos/account_manager_handler.h b/chrome/browser/ui/webui/settings/chromeos/account_manager_handler.h
index 953167172..078a51c 100644
--- a/chrome/browser/ui/webui/settings/chromeos/account_manager_handler.h
+++ b/chrome/browser/ui/webui/settings/chromeos/account_manager_handler.h
@@ -5,19 +5,21 @@
 #ifndef CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_ACCOUNT_MANAGER_HANDLER_H_
 #define CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_ACCOUNT_MANAGER_HANDLER_H_
 
+#include <string>
 #include <vector>
 
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h"
 #include "chromeos/account_manager/account_manager.h"
-
-class AccountTrackerService;
+#include "components/signin/core/browser/account_tracker_service.h"
 
 namespace chromeos {
 namespace settings {
 
-class AccountManagerUIHandler : public ::settings::SettingsPageUIHandler {
+class AccountManagerUIHandler : public ::settings::SettingsPageUIHandler,
+                                public AccountManager::Observer,
+                                public AccountTrackerService::Observer {
  public:
   // Accepts non-owning pointers to |AccountManager| and
   // |AccountTrackerService|. Both of these must outlive |this| instance.
@@ -30,15 +32,33 @@
   void OnJavascriptAllowed() override;
   void OnJavascriptDisallowed() override;
 
+  // |AccountManager::Observer| overrides.
+  // |AccountManager| is considered to be the source of truth for account
+  // information.
+  void OnTokenUpserted(const AccountManager::AccountKey& account_key) override;
+  void OnAccountRemoved(const AccountManager::AccountKey& account_key) override;
+
+  // |AccountTrackerService::Observer| overrides.
+  void OnAccountUpdated(const AccountInfo& info) override;
+  void OnAccountImageUpdated(const std::string& account_id,
+                             const gfx::Image& image) override;
+  void OnAccountRemoved(const AccountInfo& account_key) override;
+
  private:
   // WebUI "getAccounts" message callback.
   void HandleGetAccounts(const base::ListValue* args);
 
+  // WebUI "addAccount" message callback.
+  void HandleAddAccount(const base::ListValue* args);
+
   // |AccountManager::GetAccounts| callback.
   void GetAccountsCallbackHandler(
       base::Value callback_id,
       std::vector<AccountManager::AccountKey> account_keys);
 
+  // Refreshes the UI.
+  void RefreshUI();
+
   // A non-owning pointer to |AccountManager|.
   AccountManager* const account_manager_;
 
diff --git a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
index 50d1344..3df9d3f 100644
--- a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
+++ b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
@@ -1486,6 +1486,7 @@
     {"accountManagerPageTitle", IDS_SETTINGS_ACCOUNT_MANAGER_PAGE_TITLE},
     {"accountManagerDescription", IDS_SETTINGS_ACCOUNT_MANAGER_DESCRIPTION},
     {"accountListHeader", IDS_SETTINGS_ACCOUNT_MANAGER_LIST_HEADER},
+    {"addAccountLabel", IDS_SETTINGS_ACCOUNT_MANAGER_ADD_ACCOUNT_LABEL},
     {"configureFingerprintTitle", IDS_SETTINGS_ADD_FINGERPRINT_DIALOG_TITLE},
     {"configureFingerprintInstructionLocateScannerStep",
      IDS_SETTINGS_ADD_FINGERPRINT_DIALOG_INSTRUCTION_LOCATE_SCANNER},
diff --git a/chrome/browser/ui/webui/signin/inline_login_handler_chromeos.cc b/chrome/browser/ui/webui/signin/inline_login_handler_chromeos.cc
index 1f6891a..b3dd76c 100644
--- a/chrome/browser/ui/webui/signin/inline_login_handler_chromeos.cc
+++ b/chrome/browser/ui/webui/signin/inline_login_handler_chromeos.cc
@@ -4,6 +4,8 @@
 
 #include "chrome/browser/ui/webui/signin/inline_login_handler_chromeos.h"
 
+#include <string>
+
 #include "base/logging.h"
 #include "base/macros.h"
 #include "base/threading/sequenced_task_runner_handle.h"
@@ -34,12 +36,14 @@
   SigninHelper(
       Profile* profile,
       chromeos::AccountManager* account_manager,
+      const base::RepeatingClosure& close_dialog_closure,
       scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
       const std::string& gaia_id,
       const std::string& email,
       const std::string& auth_code)
       : profile_(profile),
         account_manager_(account_manager),
+        close_dialog_closure_(close_dialog_closure),
         email_(email),
         gaia_auth_fetcher_(this,
                            GaiaConstants::kChromeSource,
@@ -66,13 +70,13 @@
 
     account_manager_->UpsertToken(account_key_, result.refresh_token);
 
-    // TODO(sinhak): Close the dialog.
+    close_dialog_closure_.Run();
     base::SequencedTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this);
   }
 
   void OnClientOAuthFailure(const GoogleServiceAuthError& error) override {
     // TODO(sinhak): Display an error.
-    // TODO(sinhak): Close the dialog.
+    close_dialog_closure_.Run();
     base::SequencedTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this);
   }
 
@@ -81,6 +85,8 @@
   Profile* const profile_;
   // A non-owning pointer to Chrome OS AccountManager.
   chromeos::AccountManager* const account_manager_;
+  // A closure to close the hosting dialog window.
+  base::RepeatingClosure close_dialog_closure_;
   // The user's AccountKey for which |this| object has been created.
   chromeos::AccountManager::AccountKey account_key_;
   // The user's email for which |this| object has been created.
@@ -93,7 +99,9 @@
 
 }  // namespace
 
-InlineLoginHandlerChromeOS::InlineLoginHandlerChromeOS() = default;
+InlineLoginHandlerChromeOS::InlineLoginHandlerChromeOS(
+    const base::RepeatingClosure& close_dialog_closure)
+    : close_dialog_closure_(close_dialog_closure) {}
 
 InlineLoginHandlerChromeOS::~InlineLoginHandlerChromeOS() = default;
 
@@ -138,8 +146,8 @@
           ->GetAccountManager(profile->GetPath().value());
 
   // SigninHelper deletes itself after its work is done.
-  new SigninHelper(profile, account_manager, url_loader_factory, gaia_id, email,
-                   auth_code);
+  new SigninHelper(profile, account_manager, close_dialog_closure_,
+                   url_loader_factory, gaia_id, email, auth_code);
 }
 
 }  // namespace chromeos
diff --git a/chrome/browser/ui/webui/signin/inline_login_handler_chromeos.h b/chrome/browser/ui/webui/signin/inline_login_handler_chromeos.h
index 99fa863..5844d59 100644
--- a/chrome/browser/ui/webui/signin/inline_login_handler_chromeos.h
+++ b/chrome/browser/ui/webui/signin/inline_login_handler_chromeos.h
@@ -5,8 +5,6 @@
 #ifndef CHROME_BROWSER_UI_WEBUI_SIGNIN_INLINE_LOGIN_HANDLER_CHROMEOS_H_
 #define CHROME_BROWSER_UI_WEBUI_SIGNIN_INLINE_LOGIN_HANDLER_CHROMEOS_H_
 
-#include <string>
-
 #include "base/macros.h"
 #include "chrome/browser/ui/webui/signin/inline_login_handler.h"
 #include "chromeos/account_manager/account_manager.h"
@@ -17,7 +15,8 @@
 
 class InlineLoginHandlerChromeOS : public InlineLoginHandler {
  public:
-  InlineLoginHandlerChromeOS();
+  explicit InlineLoginHandlerChromeOS(
+      const base::RepeatingClosure& close_dialog_closure);
   ~InlineLoginHandlerChromeOS() override;
 
   // InlineLoginHandler overrides.
@@ -25,6 +24,7 @@
   void CompleteLogin(const base::ListValue* args) override;
 
  private:
+  base::RepeatingClosure close_dialog_closure_;
   DISALLOW_COPY_AND_ASSIGN(InlineLoginHandlerChromeOS);
 };
 
diff --git a/chrome/browser/ui/webui/signin/inline_login_handler_dialog_chromeos.cc b/chrome/browser/ui/webui/signin/inline_login_handler_dialog_chromeos.cc
new file mode 100644
index 0000000..035f5a5
--- /dev/null
+++ b/chrome/browser/ui/webui/signin/inline_login_handler_dialog_chromeos.cc
@@ -0,0 +1,43 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/webui/signin/inline_login_handler_dialog_chromeos.h"
+
+#include <string>
+
+#include "base/macros.h"
+#include "chrome/browser/ui/webui/chromeos/system_web_dialog_delegate.h"
+#include "chrome/common/webui_url_constants.h"
+
+namespace chromeos {
+
+// static
+void InlineLoginHandlerDialogChromeOS::Show() {
+  // Will be deleted by |SystemWebDialogDelegate::OnDialogClosed|.
+  InlineLoginHandlerDialogChromeOS* dialog =
+      new InlineLoginHandlerDialogChromeOS();
+  dialog->ShowSystemDialog(false /* is_minimal_style */);
+}
+
+InlineLoginHandlerDialogChromeOS::InlineLoginHandlerDialogChromeOS()
+    : SystemWebDialogDelegate(GURL(chrome::kChromeUIChromeSigninURL),
+                              base::string16() /* title */) {}
+
+InlineLoginHandlerDialogChromeOS::~InlineLoginHandlerDialogChromeOS() = default;
+
+std::string InlineLoginHandlerDialogChromeOS::GetDialogArgs() const {
+  return std::string();
+}
+
+bool InlineLoginHandlerDialogChromeOS::ShouldShowDialogTitle() const {
+  return false;
+}
+
+void InlineLoginHandlerDialogChromeOS::GetDialogSize(gfx::Size* size) const {
+  constexpr int kSigninDialogWidth = 800;
+  constexpr int kSigninDialogHeight = 700;
+  size->SetSize(kSigninDialogWidth, kSigninDialogHeight);
+}
+
+}  // namespace chromeos
diff --git a/chrome/browser/ui/webui/signin/inline_login_handler_dialog_chromeos.h b/chrome/browser/ui/webui/signin/inline_login_handler_dialog_chromeos.h
new file mode 100644
index 0000000..a03b1647
--- /dev/null
+++ b/chrome/browser/ui/webui/signin/inline_login_handler_dialog_chromeos.h
@@ -0,0 +1,34 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_SIGNIN_INLINE_LOGIN_HANDLER_DIALOG_CHROMEOS_H_
+#define CHROME_BROWSER_UI_WEBUI_SIGNIN_INLINE_LOGIN_HANDLER_DIALOG_CHROMEOS_H_
+
+#include <string>
+
+#include "base/macros.h"
+#include "chrome/browser/ui/webui/chromeos/system_web_dialog_delegate.h"
+
+namespace chromeos {
+
+class InlineLoginHandlerDialogChromeOS : public SystemWebDialogDelegate {
+ public:
+  static void Show();
+
+ protected:
+  InlineLoginHandlerDialogChromeOS();
+  ~InlineLoginHandlerDialogChromeOS() override;
+
+  // ui::WebDialogDelegate overrides
+  void GetDialogSize(gfx::Size* size) const override;
+  std::string GetDialogArgs() const override;
+  bool ShouldShowDialogTitle() const override;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(InlineLoginHandlerDialogChromeOS);
+};
+
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_UI_WEBUI_SIGNIN_INLINE_LOGIN_HANDLER_DIALOG_CHROMEOS_H_
diff --git a/chrome/browser/ui/webui/signin/inline_login_ui.cc b/chrome/browser/ui/webui/signin/inline_login_ui.cc
index 64ce3a8..3f0c38f2 100644
--- a/chrome/browser/ui/webui/signin/inline_login_ui.cc
+++ b/chrome/browser/ui/webui/signin/inline_login_ui.cc
@@ -63,13 +63,16 @@
 
 InlineLoginUI::InlineLoginUI(content::WebUI* web_ui)
     : WebDialogUI(web_ui),
-      auth_extension_(Profile::FromWebUI(web_ui)) {
+      auth_extension_(Profile::FromWebUI(web_ui)),
+      weak_factory_(this) {
   Profile* profile = Profile::FromWebUI(web_ui);
   content::WebUIDataSource::Add(profile, CreateWebUIDataSource());
 
 #if defined(OS_CHROMEOS)
   web_ui->AddMessageHandler(
-      std::make_unique<chromeos::InlineLoginHandlerChromeOS>());
+      std::make_unique<chromeos::InlineLoginHandlerChromeOS>(
+          base::BindRepeating(&WebDialogUIBase::CloseDialog,
+                              weak_factory_.GetWeakPtr(), nullptr /* args */)));
 #else
   web_ui->AddMessageHandler(std::make_unique<InlineLoginHandlerImpl>());
 #endif  // defined(OS_CHROMEOS)
diff --git a/chrome/browser/ui/webui/signin/inline_login_ui.h b/chrome/browser/ui/webui/signin/inline_login_ui.h
index 8863b9c2..c5842a3e 100644
--- a/chrome/browser/ui/webui/signin/inline_login_ui.h
+++ b/chrome/browser/ui/webui/signin/inline_login_ui.h
@@ -6,6 +6,7 @@
 #define CHROME_BROWSER_UI_WEBUI_SIGNIN_INLINE_LOGIN_UI_H_
 
 #include "base/macros.h"
+#include "base/memory/weak_ptr.h"
 #include "chrome/browser/extensions/signin/scoped_gaia_auth_extension.h"
 #include "ui/web_dialogs/web_dialog_ui.h"
 
@@ -25,6 +26,7 @@
  private:
   ScopedGaiaAuthExtension auth_extension_;
 
+  base::WeakPtrFactory<InlineLoginUI> weak_factory_;
   DISALLOW_COPY_AND_ASSIGN(InlineLoginUI);
 };
 
diff --git a/chrome/browser/ui/webui/signin/sync_confirmation_handler.cc b/chrome/browser/ui/webui/signin/sync_confirmation_handler.cc
index e471806..96f6635 100644
--- a/chrome/browser/ui/webui/signin/sync_confirmation_handler.cc
+++ b/chrome/browser/ui/webui/signin/sync_confirmation_handler.cc
@@ -13,6 +13,7 @@
 #include "chrome/browser/profiles/profile_avatar_icon_util.h"
 #include "chrome/browser/signin/account_tracker_service_factory.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
+#include "chrome/browser/signin/unified_consent_helper.h"
 #include "chrome/browser/ui/browser_list.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/signin_view_controller_delegate.h"
@@ -31,11 +32,13 @@
 
 SyncConfirmationHandler::SyncConfirmationHandler(
     Browser* browser,
-    const std::unordered_map<std::string, int>& string_to_grd_id_map)
+    const std::unordered_map<std::string, int>& string_to_grd_id_map,
+    consent_auditor::Feature consent_feature)
     : profile_(browser->profile()),
       browser_(browser),
       did_user_explicitly_interact(false),
-      string_to_grd_id_map_(string_to_grd_id_map) {
+      string_to_grd_id_map_(string_to_grd_id_map),
+      consent_feature_(consent_feature) {
   DCHECK(profile_);
   DCHECK(browser_);
   BrowserList::AddObserver(this);
@@ -119,8 +122,8 @@
   ConsentAuditorFactory::GetForProfile(profile_)->RecordGaiaConsent(
       SigninManagerFactory::GetForProfile(profile_)
           ->GetAuthenticatedAccountId(),
-      consent_auditor::Feature::CHROME_SYNC, consent_text_ids,
-      consent_confirmation_id, consent_auditor::ConsentStatus::GIVEN);
+      consent_feature_, consent_text_ids, consent_confirmation_id,
+      consent_auditor::ConsentStatus::GIVEN);
 }
 
 void SyncConfirmationHandler::SetUserImageURL(const std::string& picture_url) {
diff --git a/chrome/browser/ui/webui/signin/sync_confirmation_handler.h b/chrome/browser/ui/webui/signin/sync_confirmation_handler.h
index 8cab0b74..17f7d07 100644
--- a/chrome/browser/ui/webui/signin/sync_confirmation_handler.h
+++ b/chrome/browser/ui/webui/signin/sync_confirmation_handler.h
@@ -11,6 +11,7 @@
 #include "base/macros.h"
 #include "chrome/browser/ui/browser_list_observer.h"
 #include "chrome/browser/ui/webui/signin/login_ui_service.h"
+#include "components/consent_auditor/consent_auditor.h"
 #include "components/signin/core/browser/account_tracker_service.h"
 #include "content/public/browser/web_ui_message_handler.h"
 
@@ -27,7 +28,8 @@
   // mapped to their GRD IDs.
   explicit SyncConfirmationHandler(
       Browser* browser,
-      const std::unordered_map<std::string, int>& string_to_grd_id_map);
+      const std::unordered_map<std::string, int>& string_to_grd_id_map,
+      consent_auditor::Feature consent_feature);
   ~SyncConfirmationHandler() override;
 
   // content::WebUIMessageHandler:
@@ -93,6 +95,9 @@
   // and their respective GRD IDs.
   std::unordered_map<std::string, int> string_to_grd_id_map_;
 
+  // Contains the features to use when the user consent decision is recorded.
+  consent_auditor::Feature consent_feature_;
+
   DISALLOW_COPY_AND_ASSIGN(SyncConfirmationHandler);
 };
 
diff --git a/chrome/browser/ui/webui/signin/sync_confirmation_handler_unittest.cc b/chrome/browser/ui/webui/signin/sync_confirmation_handler_unittest.cc
index b02fd6b..4908ea2 100644
--- a/chrome/browser/ui/webui/signin/sync_confirmation_handler_unittest.cc
+++ b/chrome/browser/ui/webui/signin/sync_confirmation_handler_unittest.cc
@@ -50,7 +50,9 @@
       Browser* browser,
       content::WebUI* web_ui,
       std::unordered_map<std::string, int> string_to_grd_id_map)
-      : SyncConfirmationHandler(browser, string_to_grd_id_map) {
+      : SyncConfirmationHandler(browser,
+                                string_to_grd_id_map,
+                                consent_auditor::Feature::CHROME_SYNC) {
     set_web_ui(web_ui);
   }
 
diff --git a/chrome/browser/ui/webui/signin/sync_confirmation_ui.cc b/chrome/browser/ui/webui/signin/sync_confirmation_ui.cc
index fd173de..48e1cd78 100644
--- a/chrome/browser/ui/webui/signin/sync_confirmation_ui.cc
+++ b/chrome/browser/ui/webui/signin/sync_confirmation_ui.cc
@@ -26,7 +26,8 @@
 #include "ui/base/webui/web_ui_util.h"
 
 SyncConfirmationUI::SyncConfirmationUI(content::WebUI* web_ui)
-    : SigninWebDialogUI(web_ui) {
+    : SigninWebDialogUI(web_ui),
+      consent_feature_(consent_auditor::Feature::CHROME_SYNC) {
   Profile* profile = Profile::FromWebUI(web_ui);
   bool is_sync_allowed = profile->IsSyncAllowed();
   bool is_unified_consent_enabled = IsUnifiedConsentEnabled(profile);
@@ -108,6 +109,7 @@
     title_ids = IDS_SYNC_CONFIRMATION_UNITY_TITLE;
     confirm_button_ids = IDS_SYNC_CONFIRMATION_DICE_CONFIRM_BUTTON_LABEL;
     undo_button_ids = IDS_CANCEL;
+    consent_feature_ = consent_auditor::Feature::CHROME_UNIFIED_CONSENT;
   } else {
     source->SetDefaultResource(IDR_SYNC_CONFIRMATION_HTML);
     source->AddResourcePath("sync_confirmation.css", IDR_SYNC_CONFIRMATION_CSS);
@@ -133,6 +135,7 @@
                     : IDS_SYNC_CONFIRMATION_TITLE;
     confirm_button_ids = IDS_SYNC_CONFIRMATION_CONFIRM_BUTTON_LABEL;
     undo_button_ids = IDS_SYNC_CONFIRMATION_UNDO_BUTTON_LABEL;
+    consent_feature_ = consent_auditor::Feature::CHROME_SYNC;
     if (!is_sync_allowed) {
       title_ids = IDS_SYNC_DISABLED_CONFIRMATION_CHROME_SYNC_TITLE;
       confirm_button_ids = IDS_SYNC_DISABLED_CONFIRMATION_CONFIRM_BUTTON_LABEL;
@@ -160,7 +163,7 @@
 
 void SyncConfirmationUI::InitializeMessageHandlerWithBrowser(Browser* browser) {
   web_ui()->AddMessageHandler(std::make_unique<SyncConfirmationHandler>(
-      browser, js_localized_string_to_ids_map_));
+      browser, js_localized_string_to_ids_map_, consent_feature_));
 }
 
 void SyncConfirmationUI::AddStringResource(content::WebUIDataSource* source,
diff --git a/chrome/browser/ui/webui/signin/sync_confirmation_ui.h b/chrome/browser/ui/webui/signin/sync_confirmation_ui.h
index 0763d79..a2b773e1 100644
--- a/chrome/browser/ui/webui/signin/sync_confirmation_ui.h
+++ b/chrome/browser/ui/webui/signin/sync_confirmation_ui.h
@@ -11,6 +11,7 @@
 
 #include "base/macros.h"
 #include "chrome/browser/ui/webui/signin/signin_web_dialog_ui.h"
+#include "components/consent_auditor/consent_auditor.h"
 
 namespace content {
 class WebUIDataSource;
@@ -43,6 +44,8 @@
 
   std::unordered_map<std::string, int> js_localized_string_to_ids_map_;
 
+  consent_auditor::Feature consent_feature_;
+
   DISALLOW_COPY_AND_ASSIGN(SyncConfirmationUI);
 };
 
diff --git a/chrome/browser/web_applications/BUILD.gn b/chrome/browser/web_applications/BUILD.gn
index 2deb4ad..1930917 100644
--- a/chrome/browser/web_applications/BUILD.gn
+++ b/chrome/browser/web_applications/BUILD.gn
@@ -60,5 +60,6 @@
   deps = [
     ":web_applications_unit_tests",
     "//chrome/browser/web_applications/bookmark_apps:unit_tests",
+    "//chrome/browser/web_applications/components:components_unit_tests",
   ]
 }
diff --git a/chrome/browser/web_applications/OWNERS b/chrome/browser/web_applications/OWNERS
index f75720b4..42d8ae46 100644
--- a/chrome/browser/web_applications/OWNERS
+++ b/chrome/browser/web_applications/OWNERS
@@ -3,3 +3,7 @@
 
 # Windows
 calamity@chromium.org
+
+# Cleanups / renames
+dominickn@chromium.org
+mgiuca@chromium.org
diff --git a/chrome/browser/web_applications/components/BUILD.gn b/chrome/browser/web_applications/components/BUILD.gn
index 83a7034..fb61002 100644
--- a/chrome/browser/web_applications/components/BUILD.gn
+++ b/chrome/browser/web_applications/components/BUILD.gn
@@ -12,3 +12,17 @@
     "//base",
   ]
 }
+
+source_set("components_unit_tests") {
+  testonly = true
+
+  sources = [
+    "web_app_helpers_unittest.cc",
+  ]
+
+  deps = [
+    ":components",
+    "//testing/gtest",
+    "//url",
+  ]
+}
diff --git a/chrome/browser/web_applications/components/web_app_helpers.cc b/chrome/browser/web_applications/components/web_app_helpers.cc
index b53b454..60e9224 100644
--- a/chrome/browser/web_applications/components/web_app_helpers.cc
+++ b/chrome/browser/web_applications/components/web_app_helpers.cc
@@ -4,16 +4,13 @@
 
 #include "chrome/browser/web_applications/components/web_app_helpers.h"
 
+#include "base/strings/strcat.h"
 #include "url/gurl.h"
 
 namespace web_app {
 
 std::string GenerateApplicationNameFromURL(const GURL& url) {
-  std::string t;
-  t.append(url.host());
-  t.append("_");
-  t.append(url.path());
-  return t;
+  return base::StrCat({url.host_piece(), "_", url.path_piece()});
 }
 
 }  // namespace web_app
diff --git a/chrome/browser/web_applications/components/web_app_helpers_unittest.cc b/chrome/browser/web_applications/components/web_app_helpers_unittest.cc
new file mode 100644
index 0000000..fb881320
--- /dev/null
+++ b/chrome/browser/web_applications/components/web_app_helpers_unittest.cc
@@ -0,0 +1,22 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/web_applications/components/web_app_helpers.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+namespace web_app {
+
+TEST(WebAppHelpers, GenerateApplicationNameFromURL) {
+  EXPECT_EQ("_", GenerateApplicationNameFromURL(GURL()));
+
+  EXPECT_EQ("example.com_/",
+            GenerateApplicationNameFromURL(GURL("http://example.com")));
+
+  EXPECT_EQ("example.com_/path",
+            GenerateApplicationNameFromURL(GURL("https://example.com/path")));
+}
+
+}  // namespace web_app
diff --git a/chrome/common/extensions/api/tabs.json b/chrome/common/extensions/api/tabs.json
index c55e18a2..20526ff 100644
--- a/chrome/common/extensions/api/tabs.json
+++ b/chrome/common/extensions/api/tabs.json
@@ -746,7 +746,7 @@
       {
         "name": "captureVisibleTab",
         "type": "function",
-        "description": "Captures the visible area of the currently active tab in the specified window. You must have <a href='declare_permissions'>&lt;all_urls&gt;</a> permission to use this method.",
+        "description": "Captures the visible area of the currently active tab in the specified window. In order to call this method, the extension must have either the <a href='declare_permissions'>&lt;all_urls&gt;</a> permission or the <a href='activeTab'>activeTab</a> permission. In addition to sites extensions can normally access, this method allows extensions to capture sensitive sites that are otherwise restricted, including chrome:-scheme pages, other extensions' pages, and data: URLs. These sensitive sites can only be captured with the activeTab permission. File URLs may be captured only if the extension has been granted file access.",
         "parameters": [
           {
             "type": "integer",
diff --git a/chrome_elf/BUILD.gn b/chrome_elf/BUILD.gn
index 1b1823b8..d0949dc 100644
--- a/chrome_elf/BUILD.gn
+++ b/chrome_elf/BUILD.gn
@@ -360,9 +360,6 @@
     "hook_util/test/hook_util_test_dll.cc",
     "hook_util/test/hook_util_test_dll.h",
   ]
-  deps = [
-    "//build/config:exe_and_shlib_deps",
-  ]
 }
 
 shared_library("main_unittest_dll_1") {
diff --git a/chromecast/BUILD.gn b/chromecast/BUILD.gn
index 873fa46..c4364a0 100644
--- a/chromecast/BUILD.gn
+++ b/chromecast/BUILD.gn
@@ -450,7 +450,6 @@
   deps = [
     ":cast_shell_lib",
     ":chromecast_locales_pak",
-    "//build/config:exe_and_shlib_deps",
     "//chromecast/app",
     "//content/public/app:both",
   ]
diff --git a/chromeos/chromeos_switches.cc b/chromeos/chromeos_switches.cc
index 3e0ccb4..b9f2070 100644
--- a/chromeos/chromeos_switches.cc
+++ b/chromeos/chromeos_switches.cc
@@ -573,6 +573,9 @@
 // If true, files in Android internal storage will be shown in Files app.
 const char kShowAndroidFilesInFilesApp[] = "show-android-files-in-files-app";
 
+// If true, files in Android internal storage will be hidden in Files app.
+const char kHideAndroidFilesInFilesApp[] = "hide-android-files-in-files-app";
+
 // If true, Files app navigation is NOT displayed with "My Files". Items are NOT
 // re-ordered and "Downloads" is NOT displayed inside section "My Files".
 const char kFilesAppDisableMyFilesNavigation[] = "disable-my-files-navigation";
diff --git a/chromeos/chromeos_switches.h b/chromeos/chromeos_switches.h
index d2af949..f8ff4c2 100644
--- a/chromeos/chromeos_switches.h
+++ b/chromeos/chromeos_switches.h
@@ -133,6 +133,7 @@
 CHROMEOS_EXPORT extern const char kHasChromeOSDiamondKey[];
 CHROMEOS_EXPORT extern const char kHasChromeOSKeyboard[];
 CHROMEOS_EXPORT extern const char kHideActiveAppsFromShelf[];
+CHROMEOS_EXPORT extern const char kHideAndroidFilesInFilesApp[];
 CHROMEOS_EXPORT extern const char kHomedir[];
 CHROMEOS_EXPORT extern const char kHostPairingOobe[];
 CHROMEOS_EXPORT extern const char kIgnoreUserProfileMappingForTests[];
diff --git a/chromeos/components/drivefs/drivefs_host.cc b/chromeos/components/drivefs/drivefs_host.cc
index ee0c3cf1..202b3cdb 100644
--- a/chromeos/components/drivefs/drivefs_host.cc
+++ b/chromeos/components/drivefs/drivefs_host.cc
@@ -148,13 +148,12 @@
       return true;
     }
     if (error_code != chromeos::MOUNT_ERROR_NONE) {
+      host_->delegate_->OnMountFailed({});
       return false;
     }
-    mount_path_ = base::FilePath(mount_info.mount_path);
     DCHECK(!mount_info.mount_path.empty());
-    if (mounted()) {
-      NotifyDelegateOnMounted();
-    }
+    mount_path_ = base::FilePath(mount_info.mount_path);
+    MaybeNotifyDelegateOnMounted();
     return true;
   }
 
@@ -181,9 +180,19 @@
   void OnMounted() override {
     DCHECK_CALLED_ON_VALID_SEQUENCE(host_->sequence_checker_);
     drivefs_has_mounted_ = true;
-    if (mounted()) {
-      NotifyDelegateOnMounted();
-    }
+    MaybeNotifyDelegateOnMounted();
+  }
+
+  void OnMountFailed(base::Optional<base::TimeDelta> remount_delay) override {
+    DCHECK_CALLED_ON_VALID_SEQUENCE(host_->sequence_checker_);
+    drivefs_has_mounted_ = false;
+    host_->delegate_->OnMountFailed(std::move(remount_delay));
+  }
+
+  void OnUnmounted(base::Optional<base::TimeDelta> remount_delay) override {
+    DCHECK_CALLED_ON_VALID_SEQUENCE(host_->sequence_checker_);
+    drivefs_has_mounted_ = false;
+    host_->delegate_->OnUnmounted(std::move(remount_delay));
   }
 
   void OnSyncingStatusUpdate(mojom::SyncingStatusPtr status) override {
@@ -192,12 +201,6 @@
     }
   }
 
-  void OnUnmounted(base::Optional<base::TimeDelta> remount_delay) override {
-    DCHECK_CALLED_ON_VALID_SEQUENCE(host_->sequence_checker_);
-    drivefs_has_mounted_ = false;
-    NotifyDelegateOnUnmounted(std::move(remount_delay));
-  }
-
   void OnFilesChanged(std::vector<mojom::FileChangePtr> changes) override {
     std::vector<mojom::FileChange> changes_values;
     changes_values.reserve(changes.size());
@@ -209,11 +212,10 @@
     }
   }
 
-  void NotifyDelegateOnMounted() { host_->delegate_->OnMounted(mount_path()); }
-
-  void NotifyDelegateOnUnmounted(
-      base::Optional<base::TimeDelta> remount_delay) {
-    host_->delegate_->OnUnmounted(std::move(remount_delay));
+  void MaybeNotifyDelegateOnMounted() {
+    if (mounted()) {
+      host_->delegate_->OnMounted(mount_path());
+    }
   }
 
   void AccountReady(const AccountInfo& info,
@@ -346,6 +348,7 @@
   if (!mount_state_) {
     return;
   }
+
   if (!mount_state_->OnMountEvent(event, error_code, mount_info)) {
     Unmount();
   }
diff --git a/chromeos/components/drivefs/drivefs_host.h b/chromeos/components/drivefs/drivefs_host.h
index 5607af0..b5fa487 100644
--- a/chromeos/components/drivefs/drivefs_host.h
+++ b/chromeos/components/drivefs/drivefs_host.h
@@ -69,6 +69,8 @@
 
     virtual void OnMounted(const base::FilePath& mount_path) = 0;
     virtual void OnUnmounted(base::Optional<base::TimeDelta> remount_delay) = 0;
+    virtual void OnMountFailed(
+        base::Optional<base::TimeDelta> remount_delay) = 0;
 
    private:
     DISALLOW_COPY_AND_ASSIGN(Delegate);
diff --git a/chromeos/components/drivefs/drivefs_host_unittest.cc b/chromeos/components/drivefs/drivefs_host_unittest.cc
index 9156f6b..f19724d 100644
--- a/chromeos/components/drivefs/drivefs_host_unittest.cc
+++ b/chromeos/components/drivefs/drivefs_host_unittest.cc
@@ -119,6 +119,7 @@
 
   // DriveFsHost::Delegate:
   MOCK_METHOD1(OnMounted, void(const base::FilePath&));
+  MOCK_METHOD1(OnMountFailed, void(base::Optional<base::TimeDelta>));
   MOCK_METHOD1(OnUnmounted, void(base::Optional<base::TimeDelta>));
 
  private:
@@ -300,7 +301,11 @@
     delegate_ptr_->OnUnmounted(std::move(delay));
   }
 
-  void DoMount() {
+  void SendMountFailed(base::Optional<base::TimeDelta> delay) {
+    delegate_ptr_->OnMountFailed(std::move(delay));
+  }
+
+  void EstablishConnection() {
     auto token = StartMount();
     DispatchMountSuccessEvent(token);
 
@@ -310,6 +315,10 @@
       bootstrap_binding_.set_connection_error_handler(run_loop.QuitClosure());
       run_loop.Run();
     }
+  }
+
+  void DoMount() {
+    EstablishConnection();
     base::RunLoop run_loop;
     base::OnceClosure quit_closure = run_loop.QuitClosure();
     EXPECT_CALL(*host_delegate_,
@@ -375,6 +384,39 @@
   EXPECT_EQ(base::FilePath("/media/drivefsroot/g-ID"), host_->GetMountPath());
 }
 
+TEST_F(DriveFsHostTest, OnMountFailedFromMojo) {
+  ASSERT_FALSE(host_->IsMounted());
+
+  ASSERT_NO_FATAL_FAILURE(EstablishConnection());
+  base::RunLoop run_loop;
+  base::OnceClosure quit_closure = run_loop.QuitClosure();
+  EXPECT_CALL(*host_delegate_, OnMountFailed(_))
+      .WillOnce(RunQuitClosure(&quit_closure));
+  SendMountFailed({});
+  run_loop.Run();
+  ASSERT_FALSE(host_->IsMounted());
+}
+
+TEST_F(DriveFsHostTest, OnMountFailedFromDbus) {
+  ASSERT_FALSE(host_->IsMounted());
+
+  auto token = StartMount();
+
+  base::RunLoop run_loop;
+  base::OnceClosure quit_closure = run_loop.QuitClosure();
+  EXPECT_CALL(*host_delegate_, OnMountFailed(_))
+      .WillOnce(RunQuitClosure(&quit_closure));
+  DispatchMountEvent(chromeos::disks::DiskMountManager::MOUNTING,
+                     chromeos::MOUNT_ERROR_INVALID_MOUNT_OPTIONS,
+                     {base::StrCat({"drivefs://", token}),
+                      "/media/drivefsroot/g-ID",
+                      chromeos::MOUNT_TYPE_NETWORK_STORAGE,
+                      {}});
+  run_loop.Run();
+
+  ASSERT_FALSE(host_->IsMounted());
+}
+
 TEST_F(DriveFsHostTest, UnmountAfterMountComplete) {
   MockDriveFsHostObserver observer;
   ScopedObserver<DriveFsHost, DriveFsHostObserver> observer_scoper(&observer);
diff --git a/chromeos/components/drivefs/mojom/drivefs.mojom b/chromeos/components/drivefs/mojom/drivefs.mojom
index d243c21..1e75a03 100644
--- a/chromeos/components/drivefs/mojom/drivefs.mojom
+++ b/chromeos/components/drivefs/mojom/drivefs.mojom
@@ -41,13 +41,17 @@
   // Invoked when the mount is ready for use.
   OnMounted();
 
-  // Invoked when the syncing status changes.
-  OnSyncingStatusUpdate(SyncingStatus status);
+  // Invoked if mounting has failed. If retry_delay is present the
+  // browser should try to mount again after the specified interval.
+  OnMountFailed(mojo_base.mojom.TimeDelta? retry_delay);
 
   // Invoked when the mount is going away. If retry_delay is present the
-  // browser should try to mount DriveFs again after the specified interval.
+  // browser should try to mount again after the specified interval.
   OnUnmounted(mojo_base.mojom.TimeDelta? retry_delay);
 
+  // Invoked when the syncing status changes.
+  OnSyncingStatusUpdate(SyncingStatus status);
+
   // Invoked when server-side file changes are received.
   OnFilesChanged(array<FileChange> changes);
 };
diff --git a/chromeos/dbus/cicerone_client.cc b/chromeos/dbus/cicerone_client.cc
index cde0605..2013c42 100644
--- a/chromeos/dbus/cicerone_client.cc
+++ b/chromeos/dbus/cicerone_client.cc
@@ -36,6 +36,10 @@
     return is_container_shutdown_signal_connected_;
   }
 
+  bool IsInstallLinuxPackageProgressSignalConnected() override {
+    return is_install_linux_package_progress_signal_connected_;
+  }
+
   void LaunchContainerApplication(
       const vm_tools::cicerone::LaunchContainerApplicationRequest& request,
       DBusMethodCallback<vm_tools::cicerone::LaunchContainerApplicationResponse>
@@ -53,7 +57,7 @@
     }
 
     cicerone_proxy_->CallMethod(
-        &method_call, dbus::ObjectProxy::TIMEOUT_INFINITE,
+        &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
         base::BindOnce(
             &CiceroneClientImpl::OnDBusProtoResponse<
                 vm_tools::cicerone::LaunchContainerApplicationResponse>,
@@ -76,12 +80,34 @@
     }
 
     cicerone_proxy_->CallMethod(
-        &method_call, dbus::ObjectProxy::TIMEOUT_INFINITE,
+        &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
         base::BindOnce(&CiceroneClientImpl::OnDBusProtoResponse<
                            vm_tools::cicerone::ContainerAppIconResponse>,
                        weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
   }
 
+  void InstallLinuxPackage(
+      const vm_tools::cicerone::InstallLinuxPackageRequest& request,
+      DBusMethodCallback<vm_tools::cicerone::InstallLinuxPackageResponse>
+          callback) override {
+    dbus::MethodCall method_call(
+        vm_tools::cicerone::kVmCiceroneInterface,
+        vm_tools::cicerone::kInstallLinuxPackageMethod);
+    dbus::MessageWriter writer(&method_call);
+
+    if (!writer.AppendProtoAsArrayOfBytes(request)) {
+      LOG(ERROR) << "Failed to encode InstallLinuxPackageRequest protobuf";
+      std::move(callback).Run(base::nullopt);
+      return;
+    }
+
+    cicerone_proxy_->CallMethod(
+        &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
+        base::BindOnce(&CiceroneClientImpl::OnDBusProtoResponse<
+                           vm_tools::cicerone::InstallLinuxPackageResponse>,
+                       weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
+  }
+
   void WaitForServiceToBeAvailable(
       dbus::ObjectProxy::WaitForServiceToBeAvailableCallback callback)
       override {
@@ -111,6 +137,14 @@
                             weak_ptr_factory_.GetWeakPtr()),
         base::BindOnce(&CiceroneClientImpl::OnSignalConnected,
                        weak_ptr_factory_.GetWeakPtr()));
+    cicerone_proxy_->ConnectToSignal(
+        vm_tools::cicerone::kVmCiceroneInterface,
+        vm_tools::cicerone::kInstallLinuxPackageProgressSignal,
+        base::BindRepeating(
+            &CiceroneClientImpl::OnInstallLinuxPackageProgressSignal,
+            weak_ptr_factory_.GetWeakPtr()),
+        base::BindOnce(&CiceroneClientImpl::OnSignalConnected,
+                       weak_ptr_factory_.GetWeakPtr()));
   }
 
  private:
@@ -155,6 +189,18 @@
     }
   }
 
+  void OnInstallLinuxPackageProgressSignal(dbus::Signal* signal) {
+    vm_tools::cicerone::InstallLinuxPackageProgressSignal proto;
+    dbus::MessageReader reader(signal);
+    if (!reader.PopArrayOfBytesAsProto(&proto)) {
+      LOG(ERROR) << "Failed to parse proto from DBus Signal";
+      return;
+    }
+    for (auto& observer : observer_list_) {
+      observer.OnInstallLinuxPackageProgress(proto);
+    }
+  }
+
   void OnSignalConnected(const std::string& interface_name,
                          const std::string& signal_name,
                          bool is_connected) {
@@ -167,6 +213,9 @@
       is_container_started_signal_connected_ = is_connected;
     } else if (signal_name == vm_tools::cicerone::kContainerShutdownSignal) {
       is_container_shutdown_signal_connected_ = is_connected;
+    } else if (signal_name ==
+               vm_tools::cicerone::kInstallLinuxPackageProgressSignal) {
+      is_install_linux_package_progress_signal_connected_ = is_connected;
     } else {
       NOTREACHED();
     }
@@ -178,6 +227,7 @@
 
   bool is_container_started_signal_connected_ = false;
   bool is_container_shutdown_signal_connected_ = false;
+  bool is_install_linux_package_progress_signal_connected_ = false;
 
   // Note: This should remain the last member so it'll be destroyed and
   // invalidate its weak pointers before any other members are destroyed.
diff --git a/chromeos/dbus/cicerone_client.h b/chromeos/dbus/cicerone_client.h
index 3016287f3..8e481fc 100644
--- a/chromeos/dbus/cicerone_client.h
+++ b/chromeos/dbus/cicerone_client.h
@@ -30,6 +30,12 @@
     virtual void OnContainerShutdown(
         const vm_tools::cicerone::ContainerShutdownSignal& signal) = 0;
 
+    // This is signaled from the container while a package is being installed
+    // via InstallLinuxPackage.
+    virtual void OnInstallLinuxPackageProgress(
+        const vm_tools::cicerone::InstallLinuxPackageProgressSignal&
+            signal) = 0;
+
    protected:
     virtual ~Observer() = default;
   };
@@ -50,6 +56,9 @@
   // is called.
   virtual bool IsContainerShutdownSignalConnected() = 0;
 
+  // This should be true prior to calling InstallLinuxPackage.
+  virtual bool IsInstallLinuxPackageProgressSignalConnected() = 0;
+
   // Launches an application inside a running Container.
   // |callback| is called after the method call finishes.
   virtual void LaunchContainerApplication(
@@ -64,6 +73,13 @@
       DBusMethodCallback<vm_tools::cicerone::ContainerAppIconResponse>
           callback) = 0;
 
+  // Installs a package inside the container.
+  // |callback| is called after the method call finishes.
+  virtual void InstallLinuxPackage(
+      const vm_tools::cicerone::InstallLinuxPackageRequest& request,
+      DBusMethodCallback<vm_tools::cicerone::InstallLinuxPackageResponse>
+          callback) = 0;
+
   // Registers |callback| to run when the Cicerone service becomes available.
   // If the service is already available, or if connecting to the name-owner-
   // changed signal fails, |callback| will be run once asynchronously.
diff --git a/chromeos/dbus/fake_cicerone_client.cc b/chromeos/dbus/fake_cicerone_client.cc
index 19d8b7a..010b937 100644
--- a/chromeos/dbus/fake_cicerone_client.cc
+++ b/chromeos/dbus/fake_cicerone_client.cc
@@ -13,6 +13,10 @@
   launch_container_application_response_.set_success(true);
 
   container_app_icon_response_.Clear();
+
+  install_linux_package_response_.Clear();
+  install_linux_package_response_.set_status(
+      vm_tools::cicerone::InstallLinuxPackageResponse::STARTED);
 }
 FakeCiceroneClient::~FakeCiceroneClient() = default;
 
@@ -32,6 +36,10 @@
   return is_container_shutdown_signal_connected_;
 }
 
+bool FakeCiceroneClient::IsInstallLinuxPackageProgressSignalConnected() {
+  return is_install_linux_package_progress_signal_connected;
+}
+
 void FakeCiceroneClient::LaunchContainerApplication(
     const vm_tools::cicerone::LaunchContainerApplicationRequest& request,
     DBusMethodCallback<vm_tools::cicerone::LaunchContainerApplicationResponse>
@@ -49,6 +57,15 @@
       base::BindOnce(std::move(callback), container_app_icon_response_));
 }
 
+void FakeCiceroneClient::InstallLinuxPackage(
+    const vm_tools::cicerone::InstallLinuxPackageRequest& request,
+    DBusMethodCallback<vm_tools::cicerone::InstallLinuxPackageResponse>
+        callback) {
+  base::ThreadTaskRunnerHandle::Get()->PostTask(
+      FROM_HERE,
+      base::BindOnce(std::move(callback), install_linux_package_response_));
+}
+
 void FakeCiceroneClient::WaitForServiceToBeAvailable(
     dbus::ObjectProxy::WaitForServiceToBeAvailableCallback callback) {
   base::ThreadTaskRunnerHandle::Get()->PostTask(
diff --git a/chromeos/dbus/fake_cicerone_client.h b/chromeos/dbus/fake_cicerone_client.h
index 8025b5d..253d782 100644
--- a/chromeos/dbus/fake_cicerone_client.h
+++ b/chromeos/dbus/fake_cicerone_client.h
@@ -29,6 +29,9 @@
   // is called.
   bool IsContainerShutdownSignalConnected() override;
 
+  // This should be true prior to calling InstallLinuxPackage.
+  bool IsInstallLinuxPackageProgressSignalConnected() override;
+
   // Fake version of the method that launches an application inside a running
   // Container. |callback| is called after the method call finishes.
   void LaunchContainerApplication(
@@ -43,6 +46,14 @@
       DBusMethodCallback<vm_tools::cicerone::ContainerAppIconResponse> callback)
       override;
 
+  // Fake version of the method that installs an application inside a running
+  // Container. |callback| is called after the method call finishes. This does
+  // not cause progress events to be fired.
+  void InstallLinuxPackage(
+      const vm_tools::cicerone::InstallLinuxPackageRequest& request,
+      DBusMethodCallback<vm_tools::cicerone::InstallLinuxPackageResponse>
+          callback) override;
+
   // Fake version of the method that waits for the Cicerone service to be
   // availble.  |callback| is called after the method call finishes.
   void WaitForServiceToBeAvailable(
@@ -58,28 +69,43 @@
     is_container_shutdown_signal_connected_ = connected;
   }
 
+  // Set InstallLinuxPackageProgressSignalConnected state
+  void set_install_linux_package_progress_signal_connected(bool connected) {
+    is_install_linux_package_progress_signal_connected = connected;
+  }
+
   void set_launch_container_application_response(
       const vm_tools::cicerone::LaunchContainerApplicationResponse&
           launch_container_application_response) {
     launch_container_application_response_ =
         launch_container_application_response;
   }
+
   void set_container_app_icon_response(
       const vm_tools::cicerone::ContainerAppIconResponse&
           container_app_icon_response) {
     container_app_icon_response_ = container_app_icon_response;
   }
 
+  void set_install_linux_package_response(
+      const vm_tools::cicerone::InstallLinuxPackageResponse&
+          install_linux_package_response) {
+    install_linux_package_response_ = install_linux_package_response;
+  }
+
  protected:
   void Init(dbus::Bus* bus) override {}
 
  private:
   bool is_container_started_signal_connected_ = true;
   bool is_container_shutdown_signal_connected_ = true;
+  bool is_install_linux_package_progress_signal_connected = true;
 
   vm_tools::cicerone::LaunchContainerApplicationResponse
       launch_container_application_response_;
   vm_tools::cicerone::ContainerAppIconResponse container_app_icon_response_;
+  vm_tools::cicerone::InstallLinuxPackageResponse
+      install_linux_package_response_;
   base::ObserverList<Observer> observer_list_;
 
   DISALLOW_COPY_AND_ASSIGN(FakeCiceroneClient);
diff --git a/chromeos/services/BUILD.gn b/chromeos/services/BUILD.gn
index e8f1592d..047dc25 100644
--- a/chromeos/services/BUILD.gn
+++ b/chromeos/services/BUILD.gn
@@ -4,6 +4,7 @@
 
 import("//build/config/ui.gni")
 import("//chromeos/assistant/assistant.gni")
+import("//chromeos/services/ime/public/features.gni")
 import("//services/catalog/public/tools/catalog.gni")
 import("//services/service_manager/public/tools/test/service_test.gni")
 import("//testing/test.gni")
@@ -40,6 +41,10 @@
     deps += [ "//chromeos/services/assistant:tests" ]
   }
 
+  if (enable_cros_ime_service) {
+    deps += [ "//chromeos/services/ime:unit_tests" ]
+  }
+
   catalog = ":chromeos_services_unittests_catalog"
 }
 
@@ -51,4 +56,8 @@
   if (enable_cros_assistant) {
     catalog_deps += [ "//chromeos/services/assistant:tests_catalog" ]
   }
+
+  if (enable_cros_ime_service) {
+    catalog_deps += [ "//chromeos/services/ime:tests_catalog" ]
+  }
 }
diff --git a/chromeos/services/ime/BUILD.gn b/chromeos/services/ime/BUILD.gn
new file mode 100644
index 0000000..c7c2e3a
--- /dev/null
+++ b/chromeos/services/ime/BUILD.gn
@@ -0,0 +1,66 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//chromeos/services/ime/public/features.gni")
+import("//services/catalog/public/tools/catalog.gni")
+import("//services/service_manager/public/cpp/service.gni")
+import("//services/service_manager/public/service_manifest.gni")
+
+assert(is_chromeos)
+assert(enable_cros_ime_service)
+
+source_set("lib") {
+  sources = [
+    "ime_service.cc",
+    "ime_service.h",
+    "input_engine.cc",
+    "input_engine.h",
+  ]
+
+  deps = [
+    "//base",
+    "//chromeos/services/ime/public/cpp:buildflags",
+    "//chromeos/services/ime/public/mojom",
+    "//services/service_manager/public/cpp",
+    "//services/service_manager/public/mojom",
+  ]
+
+  if (enable_cros_ime_decoder) {
+    sources += [
+      "decoder/decoder_engine.cc",
+      "decoder/decoder_engine.h",
+    ]
+  }
+}
+
+service_manifest("manifest") {
+  name = "ime"
+  source = "manifest.json"
+}
+
+source_set("unit_tests") {
+  testonly = true
+  deps = [
+    ":lib",
+    "//base",
+    "//mojo/public/cpp/bindings",
+    "//services/identity/public/mojom",
+    "//services/service_manager/public/cpp",
+    "//services/service_manager/public/cpp:service_test_support",
+  ]
+  sources = [
+    "ime_service_unittest.cc",
+  ]
+}
+
+service_manifest("unittest_manifest") {
+  name = "ime_unittests"
+  source = "test_manifest.json"
+  packaged_services = [ ":manifest" ]
+}
+
+catalog("tests_catalog") {
+  testonly = true
+  embedded_services = [ ":unittest_manifest" ]
+}
diff --git a/chromeos/services/ime/DEPS b/chromeos/services/ime/DEPS
new file mode 100644
index 0000000..7f957bc
--- /dev/null
+++ b/chromeos/services/ime/DEPS
@@ -0,0 +1,4 @@
+include_rules = [
+  "+mojo/public",
+  "+services/service_manager/public",
+]
diff --git a/chromeos/services/ime/OWNERS b/chromeos/services/ime/OWNERS
new file mode 100644
index 0000000..36d24774
--- /dev/null
+++ b/chromeos/services/ime/OWNERS
@@ -0,0 +1,8 @@
+googleo@chromium.org
+shuchen@chromium.org
+
+per-file manifest.json=set noparent
+per-file manifest.json=file://ipc/SECURITY_OWNERS
+
+per-file test_manifest.json=set noparent
+per-file test_manifest.json=file://ipc/SECURITY_OWNERS
diff --git a/chromeos/services/ime/README.md b/chromeos/services/ime/README.md
new file mode 100644
index 0000000..e680ee30
--- /dev/null
+++ b/chromeos/services/ime/README.md
@@ -0,0 +1,6 @@
+IME Mojo service provides core IME functionality.
+
+The service prvoides basic rule-based IMEs, and is able to support
+advanced IME features by loading a qualified shared library.
+
+Work in progress, design doc: go/cros-ime-decoders-mojo
diff --git a/chromeos/services/ime/decoder/decoder_engine.cc b/chromeos/services/ime/decoder/decoder_engine.cc
new file mode 100644
index 0000000..5e9fc47
--- /dev/null
+++ b/chromeos/services/ime/decoder/decoder_engine.cc
@@ -0,0 +1,67 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromeos/services/ime/decoder/decoder_engine.h"
+
+#include "base/files/file_path.h"
+#include "build/buildflag.h"
+#include "chromeos/services/ime/public/cpp/buildflags.h"
+
+namespace chromeos {
+namespace ime {
+
+namespace {
+
+#if BUILDFLAG(ENABLE_CROS_IME_EXAMPLE_SO)
+const char kDecoderLibName[] = "input_decoder_example";
+#else
+const char kDecoderLibName[] = "input_decoder_engine";
+#endif
+
+}  // namespace
+
+DecoderEngine::DecoderEngine(
+    service_manager::Connector* connector,
+    scoped_refptr<base::SequencedTaskRunner> task_runner) {
+  // TODO(https://crbug.com/837156): Connect utility services for InputEngine
+  // via connector(). Eg. take advantage of the file and network services to
+  // download relevant language models required by the decocers to the device.
+
+  // Load the decoder library.
+  base::NativeLibraryLoadError load_error;
+  base::FilePath lib_path(base::GetNativeLibraryName(kDecoderLibName));
+  library_.Reset(base::LoadNativeLibrary(lib_path, &load_error));
+
+  if (!library_.is_valid()) {
+    return;
+  }
+
+  // TODO(https://crbug.com/837156): Based on the defined function pointer types
+  // in DecoderAPILibrary, load all required function pointers.
+}
+
+DecoderEngine::~DecoderEngine() {}
+
+void DecoderEngine::BindRequest(const std::string& ime_spec,
+                                mojom::InputChannelRequest request,
+                                mojom::InputChannelPtr client,
+                                const std::vector<uint8_t>& extra) {
+  // TODO(https://crbug.com/837156): Build a ClientWrapper with the clientPtr,
+  // inside we ensure the clientPtr will run in the correct SequencedTaskRunner,
+  // then pass the wrapper to the native library instead of the clientPtr.
+  channel_bindings_.AddBinding(this, std::move(request));
+  // TODO(https://crbug.com/837156): Registry connection error handler.
+}
+
+void DecoderEngine::ProcessMessage(const std::vector<uint8_t>& message,
+                                   ProcessMessageCallback callback) {
+  std::vector<uint8_t> result;
+
+  // TODO(https://crbug.com/837156): Implement the functions below by calling
+  // the corresponding functions of the shared library loaded.
+  std::move(callback).Run(result);
+}
+
+}  // namespace ime
+}  // namespace chromeos
diff --git a/chromeos/services/ime/decoder/decoder_engine.h b/chromeos/services/ime/decoder/decoder_engine.h
new file mode 100644
index 0000000..de23cd22
--- /dev/null
+++ b/chromeos/services/ime/decoder/decoder_engine.h
@@ -0,0 +1,50 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMEOS_SERVICES_IME_DECODER_DECODER_ENGINE_H_
+#define CHROMEOS_SERVICES_IME_DECODER_DECODER_ENGINE_H_
+
+#include "base/scoped_native_library.h"
+#include "chromeos/services/ime/input_engine.h"
+#include "chromeos/services/ime/public/mojom/input_engine.mojom.h"
+#include "mojo/public/cpp/bindings/binding_set.h"
+#include "services/service_manager/public/cpp/connector.h"
+
+namespace chromeos {
+namespace ime {
+
+// TODO(https://crbug.com/837156): Introduce a DecoderAPILibrary class/struct.
+// Inside, we define the shared function pointer types which are implemented
+// in the decoder shared library.
+
+// An enhanced implementation of the basic InputEngine which allows the input
+// engine to call a customized transliteration library (aka decoder) to provide
+// a premium typing experience.
+class DecoderEngine : public InputEngine {
+ public:
+  DecoderEngine(service_manager::Connector* connector,
+                scoped_refptr<base::SequencedTaskRunner> task_runner);
+  ~DecoderEngine() override;
+
+  // InputEngine overrides:
+  void BindRequest(const std::string& ime_spec,
+                   mojom::InputChannelRequest request,
+                   mojom::InputChannelPtr client,
+                   const std::vector<uint8_t>& extra) override;
+  void ProcessMessage(const std::vector<uint8_t>& message,
+                      ProcessMessageCallback callback) override;
+
+ private:
+  // Shared library handle of the implementation for input logic with decoders.
+  base::ScopedNativeLibrary library_;
+
+  mojo::BindingSet<mojom::InputChannel> channel_bindings_;
+
+  DISALLOW_COPY_AND_ASSIGN(DecoderEngine);
+};
+
+}  // namespace ime
+}  // namespace chromeos
+
+#endif  // CHROMEOS_SERVICES_IME_DECODER_DECODER_ENGINE_H_
diff --git a/chromeos/services/ime/ime_service.cc b/chromeos/services/ime/ime_service.cc
new file mode 100644
index 0000000..4137a06
--- /dev/null
+++ b/chromeos/services/ime/ime_service.cc
@@ -0,0 +1,64 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromeos/services/ime/ime_service.h"
+
+#include "base/bind.h"
+#include "build/buildflag.h"
+#include "chromeos/services/ime/public/cpp/buildflags.h"
+
+#if BUILDFLAG(ENABLE_CROS_IME_DECODER)
+#include "chromeos/services/ime/decoder/decoder_engine.h"
+#include "services/service_manager/public/cpp/service_context.h"
+#endif
+
+namespace chromeos {
+namespace ime {
+
+std::unique_ptr<service_manager::Service> CreateImeService() {
+  return std::make_unique<ImeService>();
+}
+
+ImeService::ImeService() {}
+
+ImeService::~ImeService() {}
+
+void ImeService::OnStart() {
+  binder_registry_.AddInterface<mojom::InputEngineManager>(base::BindRepeating(
+      &ImeService::BindInputEngineManagerRequest, base::Unretained(this)));
+
+#if BUILDFLAG(ENABLE_CROS_IME_DECODER)
+  input_engine_ = std::make_unique<DecoderEngine>(
+      context()->connector(), base::SequencedTaskRunnerHandle::Get());
+#else
+  input_engine_ = std::make_unique<InputEngine>();
+#endif
+}
+
+void ImeService::OnBindInterface(
+    const service_manager::BindSourceInfo& source_info,
+    const std::string& interface_name,
+    mojo::ScopedMessagePipeHandle interface_pipe) {
+  binder_registry_.BindInterface(interface_name, std::move(interface_pipe));
+}
+
+void ImeService::ConnectToImeEngine(
+    const std::string& ime_spec,
+    mojom::InputChannelRequest to_engine_request,
+    mojom::InputChannelPtr from_engine,
+    const std::vector<uint8_t>& extra,
+    ConnectToImeEngineCallback callback) {
+  DCHECK(input_engine_);
+  input_engine_->BindRequest(ime_spec, std::move(to_engine_request),
+                             std::move(from_engine), extra);
+}
+
+void ImeService::BindInputEngineManagerRequest(
+    mojom::InputEngineManagerRequest request) {
+  engine_manager_bindings_.AddBinding(this, std::move(request));
+  // TODO(https://crbug.com/837156): Registry connection error handler.
+}
+
+}  // namespace ime
+}  // namespace chromeos
diff --git a/chromeos/services/ime/ime_service.h b/chromeos/services/ime/ime_service.h
new file mode 100644
index 0000000..3428c63
--- /dev/null
+++ b/chromeos/services/ime/ime_service.h
@@ -0,0 +1,56 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMEOS_SERVICES_IME_IME_SERVICE_H_
+#define CHROMEOS_SERVICES_IME_IME_SERVICE_H_
+
+#include "chromeos/services/ime/input_engine.h"
+#include "chromeos/services/ime/public/mojom/input_engine.mojom.h"
+#include "mojo/public/cpp/bindings/binding_set.h"
+#include "services/service_manager/public/cpp/binder_registry.h"
+#include "services/service_manager/public/cpp/service.h"
+
+namespace chromeos {
+namespace ime {
+
+std::unique_ptr<service_manager::Service> CreateImeService();
+
+class ImeService : public service_manager::Service,
+                   public mojom::InputEngineManager {
+ public:
+  ImeService();
+  ~ImeService() override;
+
+ private:
+  // service_manager::Service:
+  void OnStart() override;
+  void OnBindInterface(const service_manager::BindSourceInfo& source_info,
+                       const std::string& interface_name,
+                       mojo::ScopedMessagePipeHandle interface_pipe) override;
+
+  // mojom::InputEngineManager overrides:
+  void ConnectToImeEngine(const std::string& ime_spec,
+                          mojom::InputChannelRequest to_engine_request,
+                          mojom::InputChannelPtr from_engine,
+                          const std::vector<uint8_t>& extra,
+                          ConnectToImeEngineCallback callback) override;
+
+  // Binds the mojom::InputEngineManager interface to this object.
+  void BindInputEngineManagerRequest(mojom::InputEngineManagerRequest request);
+
+  // For the duration of this service lifetime, there should be only one
+  // input engine instance.
+  std::unique_ptr<InputEngine> input_engine_;
+
+  mojo::BindingSet<mojom::InputEngineManager> engine_manager_bindings_;
+
+  service_manager::BinderRegistry binder_registry_;
+
+  DISALLOW_COPY_AND_ASSIGN(ImeService);
+};
+
+}  // namespace ime
+}  // namespace chromeos
+
+#endif  // CHROMEOS_SERVICES_IME_IME_SERVICE_H_
diff --git a/chromeos/services/ime/ime_service_unittest.cc b/chromeos/services/ime/ime_service_unittest.cc
new file mode 100644
index 0000000..7e32332b
--- /dev/null
+++ b/chromeos/services/ime/ime_service_unittest.cc
@@ -0,0 +1,85 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/bind.h"
+
+#include "chromeos/services/ime/public/mojom/constants.mojom.h"
+#include "chromeos/services/ime/public/mojom/input_engine.mojom.h"
+
+#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/bindings/interface_request.h"
+#include "services/service_manager/public/cpp/service_context.h"
+#include "services/service_manager/public/cpp/service_test.h"
+
+namespace chromeos {
+namespace ime {
+
+namespace {
+
+const char kTestServiceName[] = "ime_unittests";
+const std::vector<uint8_t> extra{0x66, 0x77, 0x88};
+
+void RunCallback(bool* success, bool result) {
+  *success = result;
+}
+
+class ImeServiceTest : public service_manager::test::ServiceTest {
+ public:
+  ImeServiceTest() : service_manager::test::ServiceTest(kTestServiceName) {}
+  ~ImeServiceTest() override {}
+
+  void SetUp() override {
+    ServiceTest::SetUp();
+    // TODO(https://crbug.com/837156): Start or bind other services used.
+    // Eg.  connector()->StartService(kServiceName) or
+    //      connector()->BindInterface(kServiceName, &ptr);
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ImeServiceTest);
+};
+
+class FakeClient : mojom::InputChannel {
+ public:
+  FakeClient() : binding_(this) {}
+
+  mojom::InputChannelPtr CreateInterfacePtrAndBind() {
+    mojom::InputChannelPtr ptr;
+    binding_.Bind(mojo::MakeRequest(&ptr));
+    return ptr;
+  }
+
+ private:
+  // mojom::InputEngineClient:
+  void ProcessText(const std::string& message,
+                   ProcessTextCallback callback) override{};
+  void ProcessMessage(const std::vector<uint8_t>& message,
+                      ProcessMessageCallback callback) override{};
+
+  mojo::Binding<mojom::InputChannel> binding_;
+
+  DISALLOW_COPY_AND_ASSIGN(FakeClient);
+};
+
+}  // namespace
+
+// Tests activating an IME and set its delegate.
+TEST_F(ImeServiceTest, ConnectImeEngine) {
+  connector()->StartService(mojom::kServiceName);
+
+  mojom::InputEngineManagerPtr manager;
+  connector()->BindInterface(mojom::kServiceName, &manager);
+
+  bool success = false;
+  FakeClient client;
+
+  mojom::InputChannelPtr to_engine_ptr;
+
+  manager->ConnectToImeEngine("FakeIME", mojo::MakeRequest(&to_engine_ptr),
+                              client.CreateInterfacePtrAndBind(), extra,
+                              base::BindOnce(&RunCallback, &success));
+}
+
+}  // namespace ime
+}  // namespace chromeos
diff --git a/chromeos/services/ime/input_engine.cc b/chromeos/services/ime/input_engine.cc
new file mode 100644
index 0000000..e919992
--- /dev/null
+++ b/chromeos/services/ime/input_engine.cc
@@ -0,0 +1,45 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromeos/services/ime/input_engine.h"
+
+#include "base/logging.h"
+#include "base/strings/string_util.h"
+
+namespace chromeos {
+namespace ime {
+
+InputEngine::InputEngine() {}
+
+InputEngine::~InputEngine() {}
+
+void InputEngine::BindRequest(const std::string& ime_spec,
+                              mojom::InputChannelRequest request,
+                              mojom::InputChannelPtr client,
+                              const std::vector<uint8_t>& extra) {
+  channel_bindings_.AddBinding(this, std::move(request), ime_spec);
+  // TODO(https://crbug.com/837156): Registry connection error handler.
+}
+
+void InputEngine::ProcessText(const std::string& message,
+                              ProcessTextCallback callback) {
+  auto& ime_spec = channel_bindings_.dispatch_context();
+  std::string result = Process(message, ime_spec);
+  std::move(callback).Run(result);
+}
+
+void InputEngine::ProcessMessage(const std::vector<uint8_t>& message,
+                                 ProcessMessageCallback callback) {
+  NOTREACHED() << "No defined protobuf message in this implementation";
+}
+
+const std::string& InputEngine::Process(const std::string& message,
+                                        const std::string& ime_spec) {
+  // TODO(https://crbug.com/859432) Implement the m17n model to handle message
+  // by ime_spec.
+  return base::EmptyString();
+}
+
+}  // namespace ime
+}  // namespace chromeos
diff --git a/chromeos/services/ime/input_engine.h b/chromeos/services/ime/input_engine.h
new file mode 100644
index 0000000..2b42d8f
--- /dev/null
+++ b/chromeos/services/ime/input_engine.h
@@ -0,0 +1,46 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMEOS_SERVICES_IME_INPUT_ENGINE_H_
+#define CHROMEOS_SERVICES_IME_INPUT_ENGINE_H_
+
+#include "chromeos/services/ime/public/mojom/input_engine.mojom.h"
+#include "mojo/public/cpp/bindings/binding_set.h"
+
+namespace chromeos {
+namespace ime {
+
+// A basic implementation of InputEngine without using any decoder.
+class InputEngine : public mojom::InputChannel {
+ public:
+  InputEngine();
+  ~InputEngine() override;
+
+  // Binds the mojom::InputChannel interface to this object.
+  virtual void BindRequest(const std::string& ime_spec,
+                           mojom::InputChannelRequest request,
+                           mojom::InputChannelPtr client,
+                           const std::vector<uint8_t>& extra);
+
+  // mojom::MessageChannel overrides:
+  void ProcessText(const std::string& message,
+                   ProcessTextCallback callback) override;
+  void ProcessMessage(const std::vector<uint8_t>& message,
+                      ProcessMessageCallback callback) override;
+
+  // TODO(https://crbug.com/837156): Implement a state for the interface.
+
+ private:
+  const std::string& Process(const std::string& message,
+                             const std::string& ime_spec);
+
+  mojo::BindingSet<mojom::InputChannel, std::string> channel_bindings_;
+
+  DISALLOW_COPY_AND_ASSIGN(InputEngine);
+};
+
+}  // namespace ime
+}  // namespace chromeos
+
+#endif  // CHROMEOS_SERVICES_IME_INPUT_ENGINE_H_
diff --git a/chromeos/services/ime/manifest.json b/chromeos/services/ime/manifest.json
new file mode 100644
index 0000000..ed51c97
--- /dev/null
+++ b/chromeos/services/ime/manifest.json
@@ -0,0 +1,14 @@
+{
+  "name": "ime",
+  "display_name": "IME",
+  "interface_provider_specs": {
+    "service_manager:connector": {
+      "provides": {
+        "input_engine" : [ "chromeos.ime.mojom.InputEngine" ]
+      },
+      "requires": {
+        "service_manager": [ "service_manager:all_users" ]
+      }
+    }
+  }
+}
diff --git a/chromeos/services/ime/public/cpp/BUILD.gn b/chromeos/services/ime/public/cpp/BUILD.gn
new file mode 100644
index 0000000..fdac14d3
--- /dev/null
+++ b/chromeos/services/ime/public/cpp/BUILD.gn
@@ -0,0 +1,16 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/buildflag_header.gni")
+import("//chromeos/services/ime/public/features.gni")
+
+buildflag_header("buildflags") {
+  header = "buildflags.h"
+
+  flags = [
+    "ENABLE_CROS_IME_SERVICE=$enable_cros_ime_service",
+    "ENABLE_CROS_IME_DECODER=$enable_cros_ime_decoder",
+    "ENABLE_CROS_IME_EXAMPLE_SO=$enable_cros_ime_example_so",
+  ]
+}
diff --git a/chromeos/services/ime/public/features.gni b/chromeos/services/ime/public/features.gni
new file mode 100644
index 0000000..d44d63d
--- /dev/null
+++ b/chromeos/services/ime/public/features.gni
@@ -0,0 +1,17 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+declare_args() {
+  # Enable IME Mojo service. IME Mojo service related code is compiled only
+  # when true. The default IME Mojo service implementation is m17n.
+  enable_cros_ime_service = false
+
+  # Enable a full featured IME implementation with decoders. This requires
+  # enable_cros_ime_service also enabled.
+  enable_cros_ime_decoder = false
+
+  # Enable build an example deocder shared library from local checkout.
+  # This is for development purposes only.
+  enable_cros_ime_example_so = false
+}
diff --git a/chromeos/services/ime/public/mojom/BUILD.gn b/chromeos/services/ime/public/mojom/BUILD.gn
new file mode 100644
index 0000000..1f14dea
--- /dev/null
+++ b/chromeos/services/ime/public/mojom/BUILD.gn
@@ -0,0 +1,16 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//mojo/public/tools/bindings/mojom.gni")
+
+mojom("mojom") {
+  sources = [
+    "constants.mojom",
+    "input_engine.mojom",
+  ]
+
+  public_deps = [
+    "//mojo/public/mojom/base",
+  ]
+}
diff --git a/chromeos/services/ime/public/mojom/OWNERS b/chromeos/services/ime/public/mojom/OWNERS
new file mode 100644
index 0000000..08850f4
--- /dev/null
+++ b/chromeos/services/ime/public/mojom/OWNERS
@@ -0,0 +1,2 @@
+per-file *.mojom=set noparent
+per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/chromeos/services/ime/public/mojom/constants.mojom b/chromeos/services/ime/public/mojom/constants.mojom
new file mode 100644
index 0000000..9bcb91cb
--- /dev/null
+++ b/chromeos/services/ime/public/mojom/constants.mojom
@@ -0,0 +1,7 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module chromeos.ime.mojom;
+
+const string kServiceName = "ime_service";
diff --git a/chromeos/services/ime/public/mojom/input_engine.mojom b/chromeos/services/ime/public/mojom/input_engine.mojom
new file mode 100644
index 0000000..a990ecf
--- /dev/null
+++ b/chromeos/services/ime/public/mojom/input_engine.mojom
@@ -0,0 +1,35 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module chromeos.ime.mojom;
+
+// Manages access to a set of IME engines.
+interface InputEngineManager {
+  // Sets up the connection by binding the |to_engine_request| to the input
+  // engine identified by the |ime_spec|. The |extra| is an optional serialized
+  // protobuf data for setting up the IME engine. On success, return |success|
+  // as true, and the input data can be sent to the engine by the channel using
+  // the interface of |to_engine_request|. The channel interface |from_engine|
+  // is implmented on the client and used to receive data sent from the engine.
+  // On failure (e.g. input engine is not found), |success| is false.
+  ConnectToImeEngine(string ime_spec,
+                     InputChannel& to_engine_request,
+                     InputChannel from_engine,
+                     array<uint8> extra)
+                     => (bool success);
+};
+
+// A message channel is a paired message sender and receiver, representing
+// the communication channel between an client and the input engine connected.
+// In order to encapsulate all the communication, (e.g. access to some
+// closed-sourced input engine with decoders), implement the method that takes
+// a serialized protobuf message (instead of a plaintext) as its argument.
+interface InputChannel {
+  // Returns a plaintext result after processing a plaintext message.
+  ProcessText(string message) => (string result);
+
+  // Returns a serialized protobuf result after processing a serialized
+  // protobuf message.
+  ProcessMessage(array<uint8> message) => (array<uint8> result);
+};
diff --git a/chromeos/services/ime/test_manifest.json b/chromeos/services/ime/test_manifest.json
new file mode 100644
index 0000000..4e5963c
--- /dev/null
+++ b/chromeos/services/ime/test_manifest.json
@@ -0,0 +1,11 @@
+{
+  "name": "ime_unittests",
+  "display_name": "IME Unittests",
+  "interface_provider_specs": {
+    "service_manager:connector": {
+      "requires": {
+        "ime": [ "input_engine" ]
+      }
+    }
+  }
+}
diff --git a/components/content_settings/core/common/features.cc b/components/content_settings/core/common/features.cc
index 1bf1adac..e372175f 100644
--- a/components/content_settings/core/common/features.cc
+++ b/components/content_settings/core/common/features.cc
@@ -12,7 +12,7 @@
 
 // Makes Flash plugin permissions persistent only through the current session.
 const base::Feature kEnableEphemeralFlashPermission{
-    "EnableEphemeralFlashPermission", base::FEATURE_DISABLED_BY_DEFAULT};
+    "EnableEphemeralFlashPermission", base::FEATURE_ENABLED_BY_DEFAULT};
 
 }  // namespace features
 }  // namespace content_settings
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.cc
index 8b1b2d4..b62bcafc 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.cc
@@ -190,7 +190,7 @@
 
 DataReductionProxyConfigServiceClient::
     ~DataReductionProxyConfigServiceClient() {
-  net::NetworkChangeNotifier::RemoveIPAddressObserver(this);
+  net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
 }
 
 base::TimeDelta
@@ -230,7 +230,7 @@
           &DataReductionProxyConfigServiceClient::OnApplicationStateChange,
           base::Unretained(this))));
 #endif
-  net::NetworkChangeNotifier::AddIPAddressObserver(this);
+  net::NetworkChangeNotifier::AddNetworkChangeObserver(this);
   url_request_context_getter_ = url_request_context_getter;
 }
 
@@ -391,8 +391,13 @@
   return base::Time::Now();
 }
 
-void DataReductionProxyConfigServiceClient::OnIPAddressChanged() {
+void DataReductionProxyConfigServiceClient::OnNetworkChanged(
+    net::NetworkChangeNotifier::ConnectionType type) {
   DCHECK(thread_checker_.CalledOnValidThread());
+
+  if (type == net::NetworkChangeNotifier::CONNECTION_NONE)
+    return;
+
   GetBackoffEntry()->Reset();
   last_ip_address_change_ = base::TimeTicks::Now();
   failed_attempts_before_success_ = 0;
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.h b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.h
index 9cf4b0c..87aa6a52 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.h
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.h
@@ -83,7 +83,7 @@
 // fetch policy is different if Chrome is in the background. Every time a config
 // is fetched, it is written to the disk.
 class DataReductionProxyConfigServiceClient
-    : public net::NetworkChangeNotifier::IPAddressObserver,
+    : public net::NetworkChangeNotifier::NetworkChangeObserver,
       public net::URLFetcherDelegate {
  public:
   // The caller must ensure that all parameters remain alive for the lifetime of
@@ -162,8 +162,9 @@
       const base::TimeDelta& config_expiration,
       const base::TimeDelta& backoff_delay);
 
-  // Override of net::NetworkChangeNotifier::IPAddressObserver.
-  void OnIPAddressChanged() override;
+  // Override of net::NetworkChangeNotifier::NetworkChangeObserver.
+  void OnNetworkChanged(
+      net::NetworkChangeNotifier::ConnectionType type) override;
 
   // Override of net::URLFetcherDelegate.
   void OnURLFetchComplete(const net::URLFetcher* source) override;
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client_unittest.cc
index 64457206..a7853c5 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client_unittest.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client_unittest.cc
@@ -703,7 +703,8 @@
     EXPECT_EQ(kFailureCount, config_client()->GetBackoffErrorCount());
 
     // IP address change should reset.
-    config_client()->OnIPAddressChanged();
+    config_client()->OnNetworkChanged(
+        net::NetworkChangeNotifier::CONNECTION_WIFI);
     EXPECT_EQ(0, config_client()->GetBackoffErrorCount());
     EXPECT_EQ(i == 0, persisted_config().empty());
     EXPECT_EQ(i == 0, persisted_config_retrieval_time().is_null());
@@ -745,7 +746,8 @@
   EXPECT_EQ(kFailureCount, config_client()->GetBackoffErrorCount());
 
   // IP address change should reset.
-  config_client()->OnIPAddressChanged();
+  config_client()->OnNetworkChanged(
+      net::NetworkChangeNotifier::CONNECTION_WIFI);
   EXPECT_EQ(0, config_client()->GetBackoffErrorCount());
   EXPECT_TRUE(persisted_config().empty());
   EXPECT_TRUE(persisted_config_retrieval_time().is_null());
@@ -795,7 +797,8 @@
   }
 
   EXPECT_EQ(0, config_client()->GetBackoffErrorCount());
-  config_client()->OnIPAddressChanged();
+  config_client()->OnNetworkChanged(
+      net::NetworkChangeNotifier::CONNECTION_WIFI);
   EXPECT_EQ(0, config_client()->GetBackoffErrorCount());
 
   config_client()->RetrieveConfig();
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate.cc
index 21a0b7b..c58414a 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate.cc
@@ -58,14 +58,14 @@
 
 DataReductionProxyDelegate::~DataReductionProxyDelegate() {
   DCHECK(thread_checker_.CalledOnValidThread());
-  net::NetworkChangeNotifier::RemoveIPAddressObserver(this);
+  net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
 }
 
 void DataReductionProxyDelegate::InitializeOnIOThread(
     DataReductionProxyIOData* io_data) {
   DCHECK(io_data);
   DCHECK(thread_checker_.CalledOnValidThread());
-  net::NetworkChangeNotifier::AddIPAddressObserver(this);
+  net::NetworkChangeNotifier::AddNetworkChangeObserver(this);
   io_data_ = io_data;
 }
 
@@ -238,8 +238,13 @@
                             QUIC_PROXY_STATUS_BOUNDARY);
 }
 
-void DataReductionProxyDelegate::OnIPAddressChanged() {
+void DataReductionProxyDelegate::OnNetworkChanged(
+    net::NetworkChangeNotifier::ConnectionType type) {
   DCHECK(thread_checker_.CalledOnValidThread());
+
+  if (type == net::NetworkChangeNotifier::CONNECTION_NONE)
+    return;
+
   last_network_change_time_ = tick_clock_->NowTicks();
 }
 
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate.h b/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate.h
index 3f94d38..dd575589 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate.h
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate.h
@@ -34,7 +34,7 @@
 
 class DataReductionProxyDelegate
     : public net::ProxyDelegate,
-      public net::NetworkChangeNotifier::IPAddressObserver {
+      public net::NetworkChangeNotifier::NetworkChangeObserver {
  public:
   // ProxyDelegate instance is owned by io_thread. |auth_handler| and |config|
   // outlives this class instance.
@@ -77,8 +77,9 @@
   // Records the availability status of data reduction proxy.
   void RecordQuicProxyStatus(QuicProxyStatus status) const;
 
-  // NetworkChangeNotifier::IPAddressObserver:
-  void OnIPAddressChanged() override;
+  // NetworkChangeNotifier::NetworkChangeObserver:
+  void OnNetworkChanged(
+      net::NetworkChangeNotifier::ConnectionType type) override;
 
   // Checks if the first proxy server in |result| supports QUIC and if so
   // adds an alternative proxy configuration to |result|.
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.h b/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.h
index 4fe0374d..96eac346 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.h
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.h
@@ -109,7 +109,7 @@
 
   ~TestDataReductionProxyConfigServiceClient() override;
 
-  using DataReductionProxyConfigServiceClient::OnIPAddressChanged;
+  using DataReductionProxyConfigServiceClient::OnNetworkChanged;
 
   void SetNow(const base::Time& time);
 
diff --git a/components/exo/BUILD.gn b/components/exo/BUILD.gn
index b566ab631..6e4c020 100644
--- a/components/exo/BUILD.gn
+++ b/components/exo/BUILD.gn
@@ -27,6 +27,9 @@
     "display.h",
     "gaming_seat.cc",
     "gaming_seat.h",
+    "input_method_surface.cc",
+    "input_method_surface.h",
+    "input_method_surface_manager.h",
     "keyboard.cc",
     "keyboard.h",
     "keyboard_delegate.h",
diff --git a/components/exo/display.cc b/components/exo/display.cc
index ebc4804b..7b515e7 100644
--- a/components/exo/display.cc
+++ b/components/exo/display.cc
@@ -15,6 +15,8 @@
 #include "components/exo/client_controlled_shell_surface.h"
 #include "components/exo/data_device.h"
 #include "components/exo/file_helper.h"
+#include "components/exo/input_method_surface.h"
+#include "components/exo/input_method_surface_manager.h"
 #include "components/exo/notification_surface.h"
 #include "components/exo/notification_surface_manager.h"
 #include "components/exo/shared_memory.h"
@@ -40,11 +42,13 @@
 ////////////////////////////////////////////////////////////////////////////////
 // Display, public:
 
-Display::Display() : Display(nullptr, std::unique_ptr<FileHelper>()) {}
+Display::Display() : Display(nullptr, nullptr, std::unique_ptr<FileHelper>()) {}
 
 Display::Display(NotificationSurfaceManager* notification_surface_manager,
+                 InputMethodSurfaceManager* input_method_surface_manager,
                  std::unique_ptr<FileHelper> file_helper)
     : notification_surface_manager_(notification_surface_manager),
+      input_method_surface_manager_(input_method_surface_manager),
       file_helper_(std::move(file_helper))
 #if defined(USE_OZONE)
       ,
@@ -202,4 +206,24 @@
   return std::make_unique<DataDevice>(delegate, &seat_, file_helper_.get());
 }
 
+std::unique_ptr<InputMethodSurface> Display::CreateInputMethodSurface(
+    Surface* surface,
+    double default_device_scale_factor) {
+  TRACE_EVENT1("exo", "Display::CreateInputMethodSurface", "surface",
+               surface->AsTracedValue());
+
+  if (!input_method_surface_manager_) {
+    DLOG(ERROR) << "Input method surface cannot be registered";
+    return nullptr;
+  }
+
+  if (surface->HasSurfaceDelegate()) {
+    DLOG(ERROR) << "Surface has already been assigned a role";
+    return nullptr;
+  }
+
+  return std::make_unique<InputMethodSurface>(
+      input_method_surface_manager_, surface, default_device_scale_factor);
+}
+
 }  // namespace exo
diff --git a/components/exo/display.h b/components/exo/display.h
index 25a3bfff..8e2632f 100644
--- a/components/exo/display.h
+++ b/components/exo/display.h
@@ -30,6 +30,8 @@
 class DataDevice;
 class DataDeviceDelegate;
 class FileHelper;
+class InputMethodSurface;
+class InputMethodSurfaceManager;
 class NotificationSurface;
 class NotificationSurfaceManager;
 class SharedMemory;
@@ -49,6 +51,7 @@
  public:
   Display();
   Display(NotificationSurfaceManager* notification_surface_manager,
+          InputMethodSurfaceManager* input_method_surface_manager,
           std::unique_ptr<FileHelper> file_helper);
   ~Display();
 
@@ -96,11 +99,17 @@
   // Creates a data device for a |delegate|.
   std::unique_ptr<DataDevice> CreateDataDevice(DataDeviceDelegate* delegate);
 
+  // Creates a input method surface for a surface.
+  std::unique_ptr<InputMethodSurface> CreateInputMethodSurface(
+      Surface* surface,
+      double default_device_scale_factor);
+
   // Obtains seat instance.
   Seat* seat() { return &seat_; }
 
  private:
   NotificationSurfaceManager* const notification_surface_manager_;
+  InputMethodSurfaceManager* const input_method_surface_manager_;
   std::unique_ptr<FileHelper> file_helper_;
   Seat seat_;
 
diff --git a/components/exo/display_unittest.cc b/components/exo/display_unittest.cc
index fd80b228f..7a598364 100644
--- a/components/exo/display_unittest.cc
+++ b/components/exo/display_unittest.cc
@@ -240,7 +240,7 @@
 
 TEST_F(DisplayTest, CreateDataDevice) {
   TestDataDeviceDelegate device_delegate;
-  Display display(nullptr, std::make_unique<TestFileHelper>());
+  Display display(nullptr, nullptr, std::make_unique<TestFileHelper>());
 
   std::unique_ptr<DataDevice> device =
       display.CreateDataDevice(&device_delegate);
diff --git a/components/exo/input_method_surface.cc b/components/exo/input_method_surface.cc
new file mode 100644
index 0000000..e24072d
--- /dev/null
+++ b/components/exo/input_method_surface.cc
@@ -0,0 +1,39 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/exo/input_method_surface.h"
+
+#include "ash/public/cpp/shell_window_ids.h"
+#include "components/exo/input_method_surface_manager.h"
+
+namespace exo {
+
+InputMethodSurface::InputMethodSurface(InputMethodSurfaceManager* manager,
+                                       Surface* surface,
+                                       double default_device_scale_factor)
+    : ClientControlledShellSurface(
+          surface,
+          true /* can_minimize */,
+          ash::kShellWindowId_ArcVirtualKeyboardContainer),
+      manager_(manager),
+      added_to_manager_(false) {
+  SetScale(default_device_scale_factor);
+  host_window()->SetName("ExoInputMethodSurface");
+}
+
+InputMethodSurface::~InputMethodSurface() {
+  if (added_to_manager_)
+    manager_->RemoveSurface(this);
+}
+
+void InputMethodSurface::OnSurfaceCommit() {
+  ClientControlledShellSurface::OnSurfaceCommit();
+
+  if (!added_to_manager_) {
+    added_to_manager_ = true;
+    manager_->AddSurface(this);
+  }
+}
+
+}  // namespace exo
diff --git a/components/exo/input_method_surface.h b/components/exo/input_method_surface.h
new file mode 100644
index 0000000..fe2a700
--- /dev/null
+++ b/components/exo/input_method_surface.h
@@ -0,0 +1,37 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_EXO_INPUT_METHOD_SURFACE_H_
+#define COMPONENTS_EXO_INPUT_METHOD_SURFACE_H_
+
+#include "base/macros.h"
+#include "components/exo/client_controlled_shell_surface.h"
+#include "components/exo/surface_delegate.h"
+#include "components/exo/surface_observer.h"
+
+namespace exo {
+
+class InputMethodSurfaceManager;
+
+// Handles input method surface role of a given surface.
+class InputMethodSurface : public ClientControlledShellSurface {
+ public:
+  InputMethodSurface(InputMethodSurfaceManager* manager,
+                     Surface* surface,
+                     double default_device_scale_factor);
+  ~InputMethodSurface() override;
+
+  // Overridden from SurfaceDelegate:
+  void OnSurfaceCommit() override;
+
+ private:
+  InputMethodSurfaceManager* const manager_;
+  bool added_to_manager_ = false;
+
+  DISALLOW_COPY_AND_ASSIGN(InputMethodSurface);
+};
+
+}  // namespace exo
+
+#endif  // COMPONENTS_EXO_INPUT_METHOD_SURFACE_H_
diff --git a/components/exo/input_method_surface_manager.h b/components/exo/input_method_surface_manager.h
new file mode 100644
index 0000000..f9ea3b7
--- /dev/null
+++ b/components/exo/input_method_surface_manager.h
@@ -0,0 +1,28 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_EXO_INPUT_METHOD_SURFACE_MANAGER_H_
+#define COMPONENTS_EXO_INPUT_METHOD_SURFACE_MANAGER_H_
+
+namespace exo {
+
+class InputMethodSurface;
+
+class InputMethodSurfaceManager {
+ public:
+  virtual ~InputMethodSurfaceManager() = default;
+
+  // Gets the InputMethodSurface currently used.
+  virtual InputMethodSurface* GetSurface() const = 0;
+
+  // Adds an InputMethodSurface to the manager.
+  virtual void AddSurface(InputMethodSurface* surface) = 0;
+
+  // Removes a InputMethodSurface from the manager.
+  virtual void RemoveSurface(InputMethodSurface* surface) = 0;
+};
+
+}  // namespace exo
+
+#endif  // COMPONENTS_EXO_INPUT_METHOD_SURFACE_MANAGER_H_
diff --git a/components/exo/wayland/clients/test/wayland_client_test.cc b/components/exo/wayland/clients/test/wayland_client_test.cc
index b3346b9a5..46739b1 100644
--- a/components/exo/wayland/clients/test/wayland_client_test.cc
+++ b/components/exo/wayland/clients/test/wayland_client_test.cc
@@ -146,7 +146,7 @@
 
   wm_helper_ = std::make_unique<WMHelper>();
   WMHelper::SetInstance(wm_helper_.get());
-  display_ = std::make_unique<Display>(nullptr, nullptr);
+  display_ = std::make_unique<Display>(nullptr, nullptr, nullptr);
   wayland_server_ = exo::wayland::Server::Create(display_.get());
   DCHECK(wayland_server_);
   wayland_watcher_ = std::make_unique<WaylandWatcher>(wayland_server_.get());
diff --git a/components/exo/wayland/server.cc b/components/exo/wayland/server.cc
index 9451039..2bdfa1b 100644
--- a/components/exo/wayland/server.cc
+++ b/components/exo/wayland/server.cc
@@ -71,6 +71,7 @@
 #include "components/exo/gamepad_delegate.h"
 #include "components/exo/gaming_seat.h"
 #include "components/exo/gaming_seat_delegate.h"
+#include "components/exo/input_method_surface.h"
 #include "components/exo/keyboard.h"
 #include "components/exo/keyboard_delegate.h"
 #include "components/exo/keyboard_device_configuration_delegate.h"
@@ -2496,6 +2497,16 @@
                                            notification_surface_set_app_id};
 
 ////////////////////////////////////////////////////////////////////////////////
+// input_method_surface_interface:
+
+void input_method_surface_destroy(wl_client* client, wl_resource* resource) {
+  wl_resource_destroy(resource);
+}
+
+const struct zcr_input_method_surface_v1_interface
+    input_method_surface_implementation = {input_method_surface_destroy};
+
+////////////////////////////////////////////////////////////////////////////////
 // remote_shell_interface:
 
 // Implements remote shell interface and monitors workspace state needed
@@ -2555,6 +2566,13 @@
     return display_->CreateNotificationSurface(surface, notification_key);
   }
 
+  std::unique_ptr<InputMethodSurface> CreateInputMethodSurface(
+      Surface* surface,
+      double default_device_scale_factor) {
+    return display_->CreateInputMethodSurface(surface,
+                                              default_device_scale_factor);
+  }
+
   // Overridden from display::DisplayObserver:
   void OnDisplayAdded(const display::Display& new_display) override {
     ScheduleSendDisplayMetrics(0);
@@ -2914,11 +2932,39 @@
                     std::move(notification_surface));
 }
 
+void remote_shell_get_input_method_surface(wl_client* client,
+                                           wl_resource* resource,
+                                           uint32_t id,
+                                           wl_resource* surface) {
+  if (GetUserDataAs<Surface>(surface)->HasSurfaceDelegate()) {
+    wl_resource_post_error(resource, ZCR_REMOTE_SHELL_V1_ERROR_ROLE,
+                           "surface has already been assigned a role");
+    return;
+  }
+
+  std::unique_ptr<ClientControlledShellSurface> input_method_surface =
+      GetUserDataAs<WaylandRemoteShell>(resource)->CreateInputMethodSurface(
+          GetUserDataAs<Surface>(surface), GetDefaultDeviceScaleFactor());
+  if (!input_method_surface) {
+    wl_resource_post_error(resource, ZCR_REMOTE_SHELL_V1_ERROR_ROLE,
+                           "Cannot create an IME surface");
+    return;
+  }
+
+  wl_resource* input_method_surface_resource =
+      wl_resource_create(client, &zcr_input_method_surface_v1_interface,
+                         wl_resource_get_version(resource), id);
+  SetImplementation(input_method_surface_resource,
+                    &input_method_surface_implementation,
+                    std::move(input_method_surface));
+}
+
 const struct zcr_remote_shell_v1_interface remote_shell_implementation = {
     remote_shell_destroy, remote_shell_get_remote_surface,
-    remote_shell_get_notification_surface};
+    remote_shell_get_notification_surface,
+    remote_shell_get_input_method_surface};
 
-const uint32_t remote_shell_version = 16;
+const uint32_t remote_shell_version = 17;
 
 void bind_remote_shell(wl_client* client,
                        void* data,
diff --git a/components/gcm_driver/gcm_profile_service.cc b/components/gcm_driver/gcm_profile_service.cc
index 171d8082..46e3cc44 100644
--- a/components/gcm_driver/gcm_profile_service.cc
+++ b/components/gcm_driver/gcm_profile_service.cc
@@ -29,6 +29,7 @@
 #include "components/gcm_driver/gcm_desktop_utils.h"
 #include "components/gcm_driver/gcm_driver_desktop.h"
 #include "net/url_request/url_request_context_getter.h"
+#include "services/identity/public/cpp/identity_manager.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 #endif
 
@@ -37,7 +38,8 @@
 #if !BUILDFLAG(USE_GCM_FROM_PLATFORM)
 // Identity observer only has actual work to do when the user is actually signed
 // in. It ensures that account tracker is taking
-class GCMProfileService::IdentityObserver : public SigninManagerBase::Observer {
+class GCMProfileService::IdentityObserver
+    : public identity::IdentityManager::Observer {
  public:
   IdentityObserver(identity::IdentityManager* identity_manager,
                    SigninManagerBase* signin_manager,
@@ -46,11 +48,10 @@
                    GCMDriver* driver);
   ~IdentityObserver() override;
 
-  // SigninManagerBase::Observer:
-  void GoogleSigninSucceeded(const std::string& account_id,
-                             const std::string& username) override;
-  void GoogleSignedOut(const std::string& account_id,
-                       const std::string& username) override;
+  // identity::IdentityManager::Observer:
+  void OnPrimaryAccountSet(const AccountInfo& primary_account_info) override;
+  void OnPrimaryAccountCleared(
+      const AccountInfo& previous_primary_account_info) override;
 
  private:
   void StartAccountTracker(net::URLRequestContextGetter* request_context);
@@ -81,34 +82,31 @@
       signin_manager_(signin_manager),
       token_service_(token_service),
       weak_ptr_factory_(this) {
-  signin_manager_->AddObserver(this);
+  identity_manager_->AddObserver(this);
 
-  GoogleSigninSucceeded(signin_manager_->GetAuthenticatedAccountId(),
-                        signin_manager_->GetAuthenticatedAccountInfo().email);
+  OnPrimaryAccountSet(identity_manager_->GetPrimaryAccountInfo());
   StartAccountTracker(request_context);
 }
 
 GCMProfileService::IdentityObserver::~IdentityObserver() {
   if (gcm_account_tracker_)
     gcm_account_tracker_->Shutdown();
-  signin_manager_->RemoveObserver(this);
+  identity_manager_->RemoveObserver(this);
 }
 
-void GCMProfileService::IdentityObserver::GoogleSigninSucceeded(
-    const std::string& account_id,
-    const std::string& username) {
+void GCMProfileService::IdentityObserver::OnPrimaryAccountSet(
+    const AccountInfo& primary_account_info) {
   // This might be called multiple times when the password changes.
-  if (account_id == account_id_)
+  if (primary_account_info.account_id == account_id_)
     return;
-  account_id_ = account_id;
+  account_id_ = primary_account_info.account_id;
 
   // Still need to notify GCMDriver for UMA purpose.
   driver_->OnSignedIn();
 }
 
-void GCMProfileService::IdentityObserver::GoogleSignedOut(
-    const std::string& account_id,
-    const std::string& username) {
+void GCMProfileService::IdentityObserver::OnPrimaryAccountCleared(
+    const AccountInfo& previous_primary_account_info) {
   account_id_.clear();
 
   // Still need to notify GCMDriver for UMA purpose.
diff --git a/components/prefs/overlay_user_pref_store.cc b/components/prefs/overlay_user_pref_store.cc
index 618033a..2b45d8c64 100644
--- a/components/prefs/overlay_user_pref_store.cc
+++ b/components/prefs/overlay_user_pref_store.cc
@@ -16,41 +16,42 @@
 // binding additional arguments).
 class OverlayUserPrefStore::ObserverAdapter : public PrefStore::Observer {
  public:
-  ObserverAdapter(bool overlay, OverlayUserPrefStore* parent)
-      : overlay_(overlay), parent_(parent) {}
+  ObserverAdapter(bool ephemeral, OverlayUserPrefStore* parent)
+      : ephemeral_user_pref_store_(ephemeral), parent_(parent) {}
 
   // Methods of PrefStore::Observer.
   void OnPrefValueChanged(const std::string& key) override {
-    parent_->OnPrefValueChanged(overlay_, key);
+    parent_->OnPrefValueChanged(ephemeral_user_pref_store_, key);
   }
   void OnInitializationCompleted(bool succeeded) override {
-    parent_->OnInitializationCompleted(overlay_, succeeded);
+    parent_->OnInitializationCompleted(ephemeral_user_pref_store_, succeeded);
   }
 
  private:
-  // Is the update for the overlay?
-  const bool overlay_;
+  // Is the update for the ephemeral?
+  const bool ephemeral_user_pref_store_;
   OverlayUserPrefStore* const parent_;
 };
 
-OverlayUserPrefStore::OverlayUserPrefStore(PersistentPrefStore* underlay)
-    : OverlayUserPrefStore(new InMemoryPrefStore(), underlay) {}
+OverlayUserPrefStore::OverlayUserPrefStore(PersistentPrefStore* persistent)
+    : OverlayUserPrefStore(new InMemoryPrefStore(), persistent) {}
 
-OverlayUserPrefStore::OverlayUserPrefStore(PersistentPrefStore* overlay,
-                                           PersistentPrefStore* underlay)
-    : overlay_observer_(
+OverlayUserPrefStore::OverlayUserPrefStore(PersistentPrefStore* ephemeral,
+                                           PersistentPrefStore* persistent)
+    : ephemeral_pref_store_observer_(
           std::make_unique<OverlayUserPrefStore::ObserverAdapter>(true, this)),
-      underlay_observer_(
+      persistent_pref_store_observer_(
           std::make_unique<OverlayUserPrefStore::ObserverAdapter>(false, this)),
-      overlay_(overlay),
-      underlay_(underlay) {
-  DCHECK(overlay->IsInitializationComplete());
-  overlay_->AddObserver(overlay_observer_.get());
-  underlay_->AddObserver(underlay_observer_.get());
+      ephemeral_user_pref_store_(ephemeral),
+      persistent_user_pref_store_(persistent) {
+  DCHECK(ephemeral->IsInitializationComplete());
+  ephemeral_user_pref_store_->AddObserver(ephemeral_pref_store_observer_.get());
+  persistent_user_pref_store_->AddObserver(
+      persistent_pref_store_observer_.get());
 }
 
 bool OverlayUserPrefStore::IsSetInOverlay(const std::string& key) const {
-  return overlay_->GetValue(key, nullptr);
+  return ephemeral_user_pref_store_->GetValue(key, nullptr);
 }
 
 void OverlayUserPrefStore::AddObserver(PrefStore::Observer* observer) {
@@ -66,27 +67,33 @@
 }
 
 bool OverlayUserPrefStore::IsInitializationComplete() const {
-  return underlay_->IsInitializationComplete() &&
-         overlay_->IsInitializationComplete();
+  return persistent_user_pref_store_->IsInitializationComplete() &&
+         ephemeral_user_pref_store_->IsInitializationComplete();
 }
 
 bool OverlayUserPrefStore::GetValue(const std::string& key,
                                     const base::Value** result) const {
-  // If the |key| shall NOT be stored in the overlay store, there must not
+  // If the |key| shall NOT be stored in the ephemeral store, there must not
   // be an entry.
-  DCHECK(ShallBeStoredInOverlay(key) || !overlay_->GetValue(key, nullptr));
+  DCHECK(!ShallBeStoredInPersistent(key) ||
+         !ephemeral_user_pref_store_->GetValue(key, nullptr));
 
-  if (overlay_->GetValue(key, result))
+  if (ephemeral_user_pref_store_->GetValue(key, result))
     return true;
-  return underlay_->GetValue(key, result);
+  return persistent_user_pref_store_->GetValue(key, result);
 }
 
 std::unique_ptr<base::DictionaryValue> OverlayUserPrefStore::GetValues() const {
-  auto values = underlay_->GetValues();
-  auto overlay_values = overlay_->GetValues();
-  for (const auto& key : overlay_names_set_) {
+  auto values = ephemeral_user_pref_store_->GetValues();
+  auto persistent_values = persistent_user_pref_store_->GetValues();
+
+  // Output |values| are read from |ephemeral_user_pref_store_| (in-memory
+  // store). Then the values of preferences in |persistent_names_set_| are
+  // overwritten by the content of |persistent_user_pref_store_| (the persistent
+  // store).
+  for (const auto& key : persistent_names_set_) {
     std::unique_ptr<base::Value> out_value;
-    overlay_values->Remove(key, &out_value);
+    persistent_values->Remove(key, &out_value);
     if (out_value) {
       values->Set(key, std::move(out_value));
     }
@@ -96,56 +103,60 @@
 
 bool OverlayUserPrefStore::GetMutableValue(const std::string& key,
                                            base::Value** result) {
-  if (!ShallBeStoredInOverlay(key))
-    return underlay_->GetMutableValue(key, result);
+  if (ShallBeStoredInPersistent(key))
+    return persistent_user_pref_store_->GetMutableValue(key, result);
 
-  written_overlay_names_.insert(key);
-  if (overlay_->GetMutableValue(key, result))
+  written_ephemeral_names_.insert(key);
+  if (ephemeral_user_pref_store_->GetMutableValue(key, result))
     return true;
 
-  // Try to create copy of underlay if the overlay does not contain a value.
-  base::Value* underlay_value = nullptr;
-  if (!underlay_->GetMutableValue(key, &underlay_value))
+  // Try to create copy of persistent if the ephemeral does not contain a value.
+  base::Value* persistent_value = nullptr;
+  if (!persistent_user_pref_store_->GetMutableValue(key, &persistent_value))
     return false;
 
-  *result = underlay_value->DeepCopy();
-  overlay_->SetValue(key, base::WrapUnique(*result),
-                     WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
+  *result = persistent_value->DeepCopy();
+  ephemeral_user_pref_store_->SetValue(
+      key, base::WrapUnique(*result),
+      WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
   return true;
 }
 
 void OverlayUserPrefStore::SetValue(const std::string& key,
                                     std::unique_ptr<base::Value> value,
                                     uint32_t flags) {
-  if (!ShallBeStoredInOverlay(key)) {
-    underlay_->SetValue(key, std::move(value), flags);
+  if (ShallBeStoredInPersistent(key)) {
+    persistent_user_pref_store_->SetValue(key, std::move(value), flags);
     return;
   }
 
-  written_overlay_names_.insert(key);
-  overlay_->SetValue(key, std::move(value), flags);
+  // TODO(https://crbug.com/861722): If we always store in in-memory storage
+  // and conditionally also stored in persistent one, we wouldn't have to do a
+  // complex merge in GetValues().
+  written_ephemeral_names_.insert(key);
+  ephemeral_user_pref_store_->SetValue(key, std::move(value), flags);
 }
 
 void OverlayUserPrefStore::SetValueSilently(const std::string& key,
                                             std::unique_ptr<base::Value> value,
                                             uint32_t flags) {
-  if (!ShallBeStoredInOverlay(key)) {
-    underlay_->SetValueSilently(key, std::move(value), flags);
+  if (ShallBeStoredInPersistent(key)) {
+    persistent_user_pref_store_->SetValueSilently(key, std::move(value), flags);
     return;
   }
 
-  written_overlay_names_.insert(key);
-  overlay_->SetValueSilently(key, std::move(value), flags);
+  written_ephemeral_names_.insert(key);
+  ephemeral_user_pref_store_->SetValueSilently(key, std::move(value), flags);
 }
 
 void OverlayUserPrefStore::RemoveValue(const std::string& key, uint32_t flags) {
-  if (!ShallBeStoredInOverlay(key)) {
-    underlay_->RemoveValue(key, flags);
+  if (ShallBeStoredInPersistent(key)) {
+    persistent_user_pref_store_->RemoveValue(key, flags);
     return;
   }
 
-  written_overlay_names_.insert(key);
-  overlay_->RemoveValue(key, flags);
+  written_ephemeral_names_.insert(key);
+  ephemeral_user_pref_store_->RemoveValue(key, flags);
 }
 
 bool OverlayUserPrefStore::ReadOnly() const {
@@ -158,7 +169,7 @@
 
 PersistentPrefStore::PrefReadError OverlayUserPrefStore::ReadPrefs() {
   // We do not read intentionally.
-  OnInitializationCompleted(/* overlay */ false, true);
+  OnInitializationCompleted(/* ephemeral */ false, true);
   return PersistentPrefStore::PREF_READ_ERROR_NONE;
 }
 
@@ -166,16 +177,16 @@
     ReadErrorDelegate* error_delegate_raw) {
   std::unique_ptr<ReadErrorDelegate> error_delegate(error_delegate_raw);
   // We do not read intentionally.
-  OnInitializationCompleted(/* overlay */ false, true);
+  OnInitializationCompleted(/* ephemeral */ false, true);
 }
 
 void OverlayUserPrefStore::CommitPendingWrite(base::OnceClosure done_callback) {
-  underlay_->CommitPendingWrite(std::move(done_callback));
+  persistent_user_pref_store_->CommitPendingWrite(std::move(done_callback));
   // We do not write our content intentionally.
 }
 
 void OverlayUserPrefStore::SchedulePendingLossyWrites() {
-  underlay_->SchedulePendingLossyWrites();
+  persistent_user_pref_store_->SchedulePendingLossyWrites();
 }
 
 void OverlayUserPrefStore::ReportValueChanged(const std::string& key,
@@ -184,39 +195,42 @@
     observer.OnPrefValueChanged(key);
 }
 
-void OverlayUserPrefStore::RegisterOverlayPref(const std::string& key) {
+void OverlayUserPrefStore::RegisterPersistentPref(const std::string& key) {
   DCHECK(!key.empty()) << "Key is empty";
-  DCHECK(overlay_names_set_.find(key) == overlay_names_set_.end())
-      << "Key already registered";
-  overlay_names_set_.insert(key);
+  DCHECK(persistent_names_set_.find(key) == persistent_names_set_.end())
+      << "Key already registered: " << key;
+  persistent_names_set_.insert(key);
 }
 
 void OverlayUserPrefStore::ClearMutableValues() {
-  for (const auto& key : written_overlay_names_) {
-    overlay_->RemoveValue(key, WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
+  for (const auto& key : written_ephemeral_names_) {
+    ephemeral_user_pref_store_->RemoveValue(
+        key, WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
   }
 }
 
 void OverlayUserPrefStore::OnStoreDeletionFromDisk() {
-  underlay_->OnStoreDeletionFromDisk();
+  persistent_user_pref_store_->OnStoreDeletionFromDisk();
 }
 
 OverlayUserPrefStore::~OverlayUserPrefStore() {
-  overlay_->RemoveObserver(overlay_observer_.get());
-  underlay_->RemoveObserver(underlay_observer_.get());
+  ephemeral_user_pref_store_->RemoveObserver(
+      ephemeral_pref_store_observer_.get());
+  persistent_user_pref_store_->RemoveObserver(
+      persistent_pref_store_observer_.get());
 }
 
-void OverlayUserPrefStore::OnPrefValueChanged(bool overlay,
+void OverlayUserPrefStore::OnPrefValueChanged(bool ephemeral,
                                               const std::string& key) {
-  if (overlay) {
+  if (ephemeral) {
     ReportValueChanged(key, DEFAULT_PREF_WRITE_FLAGS);
   } else {
-    if (!overlay_->GetValue(key, nullptr))
+    if (!ephemeral_user_pref_store_->GetValue(key, nullptr))
       ReportValueChanged(key, DEFAULT_PREF_WRITE_FLAGS);
   }
 }
 
-void OverlayUserPrefStore::OnInitializationCompleted(bool overlay,
+void OverlayUserPrefStore::OnInitializationCompleted(bool ephemeral,
                                                      bool succeeded) {
   if (!IsInitializationComplete())
     return;
@@ -224,7 +238,7 @@
     observer.OnInitializationCompleted(succeeded);
 }
 
-bool OverlayUserPrefStore::ShallBeStoredInOverlay(
+bool OverlayUserPrefStore::ShallBeStoredInPersistent(
     const std::string& key) const {
-  return overlay_names_set_.find(key) != overlay_names_set_.end();
+  return persistent_names_set_.find(key) != persistent_names_set_.end();
 }
diff --git a/components/prefs/overlay_user_pref_store.h b/components/prefs/overlay_user_pref_store.h
index 77fcd9b..0817aed 100644
--- a/components/prefs/overlay_user_pref_store.h
+++ b/components/prefs/overlay_user_pref_store.h
@@ -20,18 +20,19 @@
 // PersistentPrefStore that directs all write operations into an in-memory
 // PrefValueMap. Read operations are first answered by the PrefValueMap.
 // If the PrefValueMap does not contain a value for the requested key,
-// the look-up is passed on to an underlying PersistentPrefStore |underlay_|.
+// the look-up is passed on to an underlying PersistentPrefStore
+// |persistent_user_pref_store_|.
 class COMPONENTS_PREFS_EXPORT OverlayUserPrefStore
     : public PersistentPrefStore {
  public:
-  explicit OverlayUserPrefStore(PersistentPrefStore* underlay);
-  // The |overlay| must already be initialized.
-  OverlayUserPrefStore(PersistentPrefStore* overlay,
-                       PersistentPrefStore* underlay);
+  explicit OverlayUserPrefStore(PersistentPrefStore* persistent);
+  // The |ephemeral| store must already be initialized.
+  OverlayUserPrefStore(PersistentPrefStore* ephemeral,
+                       PersistentPrefStore* persistent);
 
   // Returns true if a value has been set for the |key| in this
   // OverlayUserPrefStore, i.e. if it potentially overrides a value
-  // from the |underlay_|.
+  // from the |persistent_user_pref_store_|.
   virtual bool IsSetInOverlay(const std::string& key) const;
 
   // Methods of PrefStore.
@@ -60,7 +61,9 @@
   void SchedulePendingLossyWrites() override;
   void ReportValueChanged(const std::string& key, uint32_t flags) override;
 
-  void RegisterOverlayPref(const std::string& key);
+  // Registers preferences that should be stored in the persistent preferences
+  // (|persistent_user_pref_store_|).
+  void RegisterPersistentPref(const std::string& key);
 
   void ClearMutableValues() override;
   void OnStoreDeletionFromDisk() override;
@@ -72,20 +75,20 @@
   typedef std::set<std::string> NamesSet;
   class ObserverAdapter;
 
-  void OnPrefValueChanged(bool overlay, const std::string& key);
-  void OnInitializationCompleted(bool overlay, bool succeeded);
+  void OnPrefValueChanged(bool ephemeral, const std::string& key);
+  void OnInitializationCompleted(bool ephemeral, bool succeeded);
 
   // Returns true if |key| corresponds to a preference that shall be stored in
-  // an in-memory PrefStore that is not persisted to disk.
-  bool ShallBeStoredInOverlay(const std::string& key) const;
+  // persistent PrefStore.
+  bool ShallBeStoredInPersistent(const std::string& key) const;
 
   base::ObserverList<PrefStore::Observer, true> observers_;
-  std::unique_ptr<ObserverAdapter> overlay_observer_;
-  std::unique_ptr<ObserverAdapter> underlay_observer_;
-  scoped_refptr<PersistentPrefStore> overlay_;
-  scoped_refptr<PersistentPrefStore> underlay_;
-  NamesSet overlay_names_set_;
-  NamesSet written_overlay_names_;
+  std::unique_ptr<ObserverAdapter> ephemeral_pref_store_observer_;
+  std::unique_ptr<ObserverAdapter> persistent_pref_store_observer_;
+  scoped_refptr<PersistentPrefStore> ephemeral_user_pref_store_;
+  scoped_refptr<PersistentPrefStore> persistent_user_pref_store_;
+  NamesSet persistent_names_set_;
+  NamesSet written_ephemeral_names_;
 
   DISALLOW_COPY_AND_ASSIGN(OverlayUserPrefStore);
 };
diff --git a/components/prefs/overlay_user_pref_store_unittest.cc b/components/prefs/overlay_user_pref_store_unittest.cc
index 528b9ab..5f0d725 100644
--- a/components/prefs/overlay_user_pref_store_unittest.cc
+++ b/components/prefs/overlay_user_pref_store_unittest.cc
@@ -23,8 +23,8 @@
 const char kShowBookmarkBar[] = "bookmark_bar.show_on_all_tabs";
 const char kSharedKey[] = "sync_promo.show_on_first_run_allowed";
 
-const char* const overlay_key = kBrowserWindowPlacement;
-const char* const regular_key = kShowBookmarkBar;
+const char* const regular_key = kBrowserWindowPlacement;
+const char* const persistent_key = kShowBookmarkBar;
 const char* const shared_key = kSharedKey;
 
 }  // namespace
@@ -34,8 +34,8 @@
   OverlayUserPrefStoreTest()
       : underlay_(new TestingPrefStore()),
         overlay_(new OverlayUserPrefStore(underlay_.get())) {
-    overlay_->RegisterOverlayPref(overlay_key);
-    overlay_->RegisterOverlayPref(shared_key);
+    overlay_->RegisterPersistentPref(persistent_key);
+    overlay_->RegisterPersistentPref(shared_key);
   }
 
   ~OverlayUserPrefStoreTest() override {}
@@ -50,117 +50,6 @@
   overlay_->AddObserver(&obs);
 
   // Check that underlay first value is reported.
-  underlay_->SetValue(overlay_key, std::make_unique<Value>(42),
-                      WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
-  obs.VerifyAndResetChangedKey(overlay_key);
-
-  // Check that underlay overwriting is reported.
-  underlay_->SetValue(overlay_key, std::make_unique<Value>(43),
-                      WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
-  obs.VerifyAndResetChangedKey(overlay_key);
-
-  // Check that overwriting change in overlay is reported.
-  overlay_->SetValue(overlay_key, std::make_unique<Value>(44),
-                     WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
-  obs.VerifyAndResetChangedKey(overlay_key);
-
-  // Check that hidden underlay change is not reported.
-  underlay_->SetValue(overlay_key, std::make_unique<Value>(45),
-                      WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
-  EXPECT_TRUE(obs.changed_keys.empty());
-
-  // Check that overlay remove is reported.
-  overlay_->RemoveValue(overlay_key,
-                        WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
-  obs.VerifyAndResetChangedKey(overlay_key);
-
-  // Check that underlay remove is reported.
-  underlay_->RemoveValue(overlay_key,
-                         WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
-  obs.VerifyAndResetChangedKey(overlay_key);
-
-  // Check respecting of silence.
-  overlay_->SetValueSilently(overlay_key, std::make_unique<Value>(46),
-                             WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
-  EXPECT_TRUE(obs.changed_keys.empty());
-
-  overlay_->RemoveObserver(&obs);
-
-  // Check successful unsubscription.
-  underlay_->SetValue(overlay_key, std::make_unique<Value>(47),
-                      WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
-  overlay_->SetValue(overlay_key, std::make_unique<Value>(48),
-                     WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
-  EXPECT_TRUE(obs.changed_keys.empty());
-}
-
-TEST_F(OverlayUserPrefStoreTest, GetAndSet) {
-  const Value* value = nullptr;
-  EXPECT_FALSE(overlay_->GetValue(overlay_key, &value));
-  EXPECT_FALSE(underlay_->GetValue(overlay_key, &value));
-
-  underlay_->SetValue(overlay_key, std::make_unique<Value>(42),
-                      WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
-
-  // Value shines through:
-  EXPECT_TRUE(overlay_->GetValue(overlay_key, &value));
-  EXPECT_TRUE(base::Value(42).Equals(value));
-
-  EXPECT_TRUE(underlay_->GetValue(overlay_key, &value));
-  EXPECT_TRUE(base::Value(42).Equals(value));
-
-  overlay_->SetValue(overlay_key, std::make_unique<Value>(43),
-                     WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
-
-  EXPECT_TRUE(overlay_->GetValue(overlay_key, &value));
-  EXPECT_TRUE(base::Value(43).Equals(value));
-
-  EXPECT_TRUE(underlay_->GetValue(overlay_key, &value));
-  EXPECT_TRUE(base::Value(42).Equals(value));
-
-  overlay_->RemoveValue(overlay_key,
-                        WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
-
-  // Value shines through:
-  EXPECT_TRUE(overlay_->GetValue(overlay_key, &value));
-  EXPECT_TRUE(base::Value(42).Equals(value));
-
-  EXPECT_TRUE(underlay_->GetValue(overlay_key, &value));
-  EXPECT_TRUE(base::Value(42).Equals(value));
-}
-
-// Check that GetMutableValue does not return the dictionary of the underlay.
-TEST_F(OverlayUserPrefStoreTest, ModifyDictionaries) {
-  underlay_->SetValue(overlay_key, std::make_unique<DictionaryValue>(),
-                      WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
-
-  Value* modify = nullptr;
-  EXPECT_TRUE(overlay_->GetMutableValue(overlay_key, &modify));
-  ASSERT_TRUE(modify);
-  ASSERT_TRUE(modify->is_dict());
-  static_cast<DictionaryValue*>(modify)->SetInteger(overlay_key, 42);
-
-  Value* original_in_underlay = nullptr;
-  EXPECT_TRUE(underlay_->GetMutableValue(overlay_key, &original_in_underlay));
-  ASSERT_TRUE(original_in_underlay);
-  ASSERT_TRUE(original_in_underlay->is_dict());
-  EXPECT_TRUE(static_cast<DictionaryValue*>(original_in_underlay)->empty());
-
-  Value* modified = nullptr;
-  EXPECT_TRUE(overlay_->GetMutableValue(overlay_key, &modified));
-  ASSERT_TRUE(modified);
-  ASSERT_TRUE(modified->is_dict());
-  EXPECT_EQ(*modify, *modified);
-}
-
-// Here we consider a global preference that is not overlayed.
-TEST_F(OverlayUserPrefStoreTest, GlobalPref) {
-  PrefStoreObserverMock obs;
-  overlay_->AddObserver(&obs);
-
-  const Value* value = nullptr;
-
-  // Check that underlay first value is reported.
   underlay_->SetValue(regular_key, std::make_unique<Value>(42),
                       WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
   obs.VerifyAndResetChangedKey(regular_key);
@@ -170,29 +59,25 @@
                       WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
   obs.VerifyAndResetChangedKey(regular_key);
 
-  // Check that we get this value from the overlay
-  EXPECT_TRUE(overlay_->GetValue(regular_key, &value));
-  EXPECT_TRUE(base::Value(43).Equals(value));
-
   // Check that overwriting change in overlay is reported.
   overlay_->SetValue(regular_key, std::make_unique<Value>(44),
                      WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
   obs.VerifyAndResetChangedKey(regular_key);
 
-  // Check that we get this value from the overlay and the underlay.
-  EXPECT_TRUE(overlay_->GetValue(regular_key, &value));
-  EXPECT_TRUE(base::Value(44).Equals(value));
-  EXPECT_TRUE(underlay_->GetValue(regular_key, &value));
-  EXPECT_TRUE(base::Value(44).Equals(value));
+  // Check that hidden underlay change is not reported.
+  underlay_->SetValue(regular_key, std::make_unique<Value>(45),
+                      WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
+  EXPECT_TRUE(obs.changed_keys.empty());
 
   // Check that overlay remove is reported.
   overlay_->RemoveValue(regular_key,
                         WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
   obs.VerifyAndResetChangedKey(regular_key);
 
-  // Check that value was removed from overlay and underlay
-  EXPECT_FALSE(overlay_->GetValue(regular_key, &value));
-  EXPECT_FALSE(underlay_->GetValue(regular_key, &value));
+  // Check that underlay remove is reported.
+  underlay_->RemoveValue(regular_key,
+                         WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
+  obs.VerifyAndResetChangedKey(regular_key);
 
   // Check respecting of silence.
   overlay_->SetValueSilently(regular_key, std::make_unique<Value>(46),
@@ -209,50 +94,165 @@
   EXPECT_TRUE(obs.changed_keys.empty());
 }
 
+TEST_F(OverlayUserPrefStoreTest, GetAndSet) {
+  const Value* value = nullptr;
+  EXPECT_FALSE(overlay_->GetValue(regular_key, &value));
+  EXPECT_FALSE(underlay_->GetValue(regular_key, &value));
+
+  underlay_->SetValue(regular_key, std::make_unique<Value>(42),
+                      WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
+
+  // Value shines through:
+  EXPECT_TRUE(overlay_->GetValue(regular_key, &value));
+  EXPECT_TRUE(base::Value(42).Equals(value));
+
+  EXPECT_TRUE(underlay_->GetValue(regular_key, &value));
+  EXPECT_TRUE(base::Value(42).Equals(value));
+
+  overlay_->SetValue(regular_key, std::make_unique<Value>(43),
+                     WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
+
+  EXPECT_TRUE(overlay_->GetValue(regular_key, &value));
+  EXPECT_TRUE(base::Value(43).Equals(value));
+
+  EXPECT_TRUE(underlay_->GetValue(regular_key, &value));
+  EXPECT_TRUE(base::Value(42).Equals(value));
+
+  overlay_->RemoveValue(regular_key,
+                        WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
+
+  // Value shines through:
+  EXPECT_TRUE(overlay_->GetValue(regular_key, &value));
+  EXPECT_TRUE(base::Value(42).Equals(value));
+
+  EXPECT_TRUE(underlay_->GetValue(regular_key, &value));
+  EXPECT_TRUE(base::Value(42).Equals(value));
+}
+
+// Check that GetMutableValue does not return the dictionary of the underlay.
+TEST_F(OverlayUserPrefStoreTest, ModifyDictionaries) {
+  underlay_->SetValue(regular_key, std::make_unique<DictionaryValue>(),
+                      WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
+
+  Value* modify = nullptr;
+  EXPECT_TRUE(overlay_->GetMutableValue(regular_key, &modify));
+  ASSERT_TRUE(modify);
+  ASSERT_TRUE(modify->is_dict());
+  static_cast<DictionaryValue*>(modify)->SetInteger(regular_key, 42);
+
+  Value* original_in_underlay = nullptr;
+  EXPECT_TRUE(underlay_->GetMutableValue(regular_key, &original_in_underlay));
+  ASSERT_TRUE(original_in_underlay);
+  ASSERT_TRUE(original_in_underlay->is_dict());
+  EXPECT_TRUE(static_cast<DictionaryValue*>(original_in_underlay)->empty());
+
+  Value* modified = nullptr;
+  EXPECT_TRUE(overlay_->GetMutableValue(regular_key, &modified));
+  ASSERT_TRUE(modified);
+  ASSERT_TRUE(modified->is_dict());
+  EXPECT_EQ(*modify, *modified);
+}
+
+// Here we consider a global preference that is not overlayed.
+TEST_F(OverlayUserPrefStoreTest, GlobalPref) {
+  PrefStoreObserverMock obs;
+  overlay_->AddObserver(&obs);
+
+  const Value* value = nullptr;
+
+  // Check that underlay first value is reported.
+  underlay_->SetValue(persistent_key, std::make_unique<Value>(42),
+                      WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
+  obs.VerifyAndResetChangedKey(persistent_key);
+
+  // Check that underlay overwriting is reported.
+  underlay_->SetValue(persistent_key, std::make_unique<Value>(43),
+                      WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
+  obs.VerifyAndResetChangedKey(persistent_key);
+
+  // Check that we get this value from the overlay
+  EXPECT_TRUE(overlay_->GetValue(persistent_key, &value));
+  EXPECT_TRUE(base::Value(43).Equals(value));
+
+  // Check that overwriting change in overlay is reported.
+  overlay_->SetValue(persistent_key, std::make_unique<Value>(44),
+                     WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
+  obs.VerifyAndResetChangedKey(persistent_key);
+
+  // Check that we get this value from the overlay and the underlay.
+  EXPECT_TRUE(overlay_->GetValue(persistent_key, &value));
+  EXPECT_TRUE(base::Value(44).Equals(value));
+  EXPECT_TRUE(underlay_->GetValue(persistent_key, &value));
+  EXPECT_TRUE(base::Value(44).Equals(value));
+
+  // Check that overlay remove is reported.
+  overlay_->RemoveValue(persistent_key,
+                        WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
+  obs.VerifyAndResetChangedKey(persistent_key);
+
+  // Check that value was removed from overlay and underlay
+  EXPECT_FALSE(overlay_->GetValue(persistent_key, &value));
+  EXPECT_FALSE(underlay_->GetValue(persistent_key, &value));
+
+  // Check respecting of silence.
+  overlay_->SetValueSilently(persistent_key, std::make_unique<Value>(46),
+                             WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
+  EXPECT_TRUE(obs.changed_keys.empty());
+
+  overlay_->RemoveObserver(&obs);
+
+  // Check successful unsubscription.
+  underlay_->SetValue(persistent_key, std::make_unique<Value>(47),
+                      WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
+  overlay_->SetValue(persistent_key, std::make_unique<Value>(48),
+                     WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
+  EXPECT_TRUE(obs.changed_keys.empty());
+}
+
 // Check that mutable values are removed correctly.
 TEST_F(OverlayUserPrefStoreTest, ClearMutableValues) {
   // Set in overlay and underlay the same preference.
-  underlay_->SetValue(overlay_key, std::make_unique<Value>(42),
+  underlay_->SetValue(regular_key, std::make_unique<Value>(42),
                       WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
-  overlay_->SetValue(overlay_key, std::make_unique<Value>(43),
+  overlay_->SetValue(regular_key, std::make_unique<Value>(43),
                      WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
 
   const Value* value = nullptr;
   // Check that an overlay preference is returned.
-  EXPECT_TRUE(overlay_->GetValue(overlay_key, &value));
+  EXPECT_TRUE(overlay_->GetValue(regular_key, &value));
   EXPECT_TRUE(base::Value(43).Equals(value));
   overlay_->ClearMutableValues();
 
   // Check that an underlay preference is returned.
-  EXPECT_TRUE(overlay_->GetValue(overlay_key, &value));
+  EXPECT_TRUE(overlay_->GetValue(regular_key, &value));
   EXPECT_TRUE(base::Value(42).Equals(value));
 }
 
 // Check that mutable values are removed correctly when using a silent set.
 TEST_F(OverlayUserPrefStoreTest, ClearMutableValues_Silently) {
   // Set in overlay and underlay the same preference.
-  underlay_->SetValueSilently(overlay_key, std::make_unique<Value>(42),
+  underlay_->SetValueSilently(regular_key, std::make_unique<Value>(42),
                               WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
-  overlay_->SetValueSilently(overlay_key, std::make_unique<Value>(43),
+  overlay_->SetValueSilently(regular_key, std::make_unique<Value>(43),
                              WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
 
   const Value* value = nullptr;
   // Check that an overlay preference is returned.
-  EXPECT_TRUE(overlay_->GetValue(overlay_key, &value));
+  EXPECT_TRUE(overlay_->GetValue(regular_key, &value));
   EXPECT_TRUE(base::Value(43).Equals(value));
   overlay_->ClearMutableValues();
 
   // Check that an underlay preference is returned.
-  EXPECT_TRUE(overlay_->GetValue(overlay_key, &value));
+  EXPECT_TRUE(overlay_->GetValue(regular_key, &value));
   EXPECT_TRUE(base::Value(42).Equals(value));
 }
 
 TEST_F(OverlayUserPrefStoreTest, GetValues) {
   // To check merge behavior, create underlay and overlay so each has a key the
   // other doesn't have and they have one key in common.
-  underlay_->SetValue(regular_key, std::make_unique<Value>(42),
+  underlay_->SetValue(persistent_key, std::make_unique<Value>(42),
                       WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
-  overlay_->SetValue(overlay_key, std::make_unique<Value>(43),
+  overlay_->SetValue(regular_key, std::make_unique<Value>(43),
                      WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
   underlay_->SetValue(shared_key, std::make_unique<Value>(42),
                       WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
@@ -262,12 +262,12 @@
   auto values = overlay_->GetValues();
   const Value* value = nullptr;
   // Check that an overlay preference is returned.
-  ASSERT_TRUE(values->Get(overlay_key, &value));
-  EXPECT_TRUE(base::Value(43).Equals(value));
+  ASSERT_TRUE(values->Get(persistent_key, &value));
+  EXPECT_TRUE(base::Value(42).Equals(value));
 
   // Check that an underlay preference is returned.
   ASSERT_TRUE(values->Get(regular_key, &value));
-  EXPECT_TRUE(base::Value(42).Equals(value));
+  EXPECT_TRUE(base::Value(43).Equals(value));
 
   // Check that the overlay is preferred.
   ASSERT_TRUE(values->Get(shared_key, &value));
diff --git a/components/services/pdf_compositor/public/cpp/pdf_compositor_service_factory.cc b/components/services/pdf_compositor/public/cpp/pdf_compositor_service_factory.cc
index 0af223b..763208c 100644
--- a/components/services/pdf_compositor/public/cpp/pdf_compositor_service_factory.cc
+++ b/components/services/pdf_compositor/public/cpp/pdf_compositor_service_factory.cc
@@ -14,7 +14,7 @@
 
 std::unique_ptr<service_manager::Service> CreatePdfCompositorService(
     const std::string& creator) {
-#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_FUCHSIA)
+#if defined(OS_POSIX) && !defined(OS_ANDROID)
   content::UtilityThread::Get()->EnsureBlinkInitializedWithSandboxSupport();
 #else
   content::UtilityThread::Get()->EnsureBlinkInitialized();
diff --git a/components/sync_preferences/pref_service_syncable.cc b/components/sync_preferences/pref_service_syncable.cc
index c8ed9a9..e95aa297 100644
--- a/components/sync_preferences/pref_service_syncable.cc
+++ b/components/sync_preferences/pref_service_syncable.cc
@@ -85,7 +85,7 @@
 std::unique_ptr<PrefServiceSyncable>
 PrefServiceSyncable::CreateIncognitoPrefService(
     PrefStore* incognito_extension_pref_store,
-    const std::vector<const char*>& overlay_pref_names,
+    const std::vector<const char*>& persistent_pref_names,
     std::unique_ptr<PrefValueStore::Delegate> delegate) {
   pref_service_forked_ = true;
   auto pref_notifier = std::make_unique<PrefNotifierImpl>();
@@ -96,14 +96,14 @@
   auto overlay = base::MakeRefCounted<InMemoryPrefStore>();
   if (delegate) {
     delegate->InitIncognitoUserPrefs(overlay, user_pref_store_,
-                                     overlay_pref_names);
+                                     persistent_pref_names);
     delegate->InitPrefRegistry(forked_registry.get());
   }
   auto incognito_pref_store = base::MakeRefCounted<OverlayUserPrefStore>(
       overlay.get(), user_pref_store_.get());
 
-  for (const char* overlay_pref_name : overlay_pref_names)
-    incognito_pref_store->RegisterOverlayPref(overlay_pref_name);
+  for (const char* persistent_pref_name : persistent_pref_names)
+    incognito_pref_store->RegisterPersistentPref(persistent_pref_name);
 
   auto pref_value_store = pref_value_store_->CloneAndSpecialize(
       nullptr,  // managed
diff --git a/components/sync_preferences/pref_service_syncable.h b/components/sync_preferences/pref_service_syncable.h
index c94f5f2..baad874 100644
--- a/components/sync_preferences/pref_service_syncable.h
+++ b/components/sync_preferences/pref_service_syncable.h
@@ -50,11 +50,11 @@
   // Creates an incognito copy of the pref service that shares most pref stores
   // but uses a fresh non-persistent overlay for the user pref store and an
   // individual extension pref store (to cache the effective extension prefs for
-  // incognito windows). |overlay_pref_names| is a list of preference names
-  // whose changes will not be persisted by the returned incognito pref service.
+  // incognito windows). |persistent_pref_names| is a list of preference names
+  // whose changes will be persisted by the returned incognito pref service.
   std::unique_ptr<PrefServiceSyncable> CreateIncognitoPrefService(
       PrefStore* incognito_extension_pref_store,
-      const std::vector<const char*>& overlay_pref_names,
+      const std::vector<const char*>& persistent_pref_names,
       std::unique_ptr<PrefValueStore::Delegate> delegate);
 
   // Returns true if preferences state has synchronized with the remote
diff --git a/components/url_formatter/top_domains/BUILD.gn b/components/url_formatter/top_domains/BUILD.gn
index 69c05de7..aa76af7 100644
--- a/components/url_formatter/top_domains/BUILD.gn
+++ b/components/url_formatter/top_domains/BUILD.gn
@@ -28,7 +28,6 @@
   ]
   deps = [
     "//base",
-    "//build/config:exe_and_shlib_deps",
     "//net/tools/huffman_trie:huffman_trie_generator_sources",
   ]
   if (is_ios) {
diff --git a/components/viz/test/BUILD.gn b/components/viz/test/BUILD.gn
index 83aa2fd0..4ef4ba27 100644
--- a/components/viz/test/BUILD.gn
+++ b/components/viz/test/BUILD.gn
@@ -30,8 +30,6 @@
     "mock_display_client.cc",
     "mock_display_client.h",
     "mock_helper.h",
-    "ordered_simple_task_runner.cc",
-    "ordered_simple_task_runner.h",
     "ordered_texture_map.cc",
     "ordered_texture_map.h",
     "paths.cc",
@@ -98,7 +96,6 @@
   sources = [
     "begin_frame_source_test_unittest.cc",
     "mock_helper_unittest.cc",
-    "ordered_simple_task_runner_unittest.cc",
     "test_gles2_interface_unittest.cc",
   ]
   deps = [
diff --git a/components/viz/test/ordered_simple_task_runner.cc b/components/viz/test/ordered_simple_task_runner.cc
deleted file mode 100644
index db795d2..0000000
--- a/components/viz/test/ordered_simple_task_runner.cc
+++ /dev/null
@@ -1,362 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/viz/test/ordered_simple_task_runner.h"
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <limits>
-#include <set>
-#include <sstream>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include "base/auto_reset.h"
-#include "base/numerics/safe_conversions.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/trace_event/trace_event.h"
-#include "base/trace_event/trace_event_argument.h"
-
-#define TRACE_TASK(function, task)                                        \
-  TRACE_EVENT_INSTANT1("viz", function, TRACE_EVENT_SCOPE_THREAD, "task", \
-                       task.AsValue());
-
-#define TRACE_TASK_RUN(function, tag, task)
-
-namespace cc {
-
-// TestOrderablePendingTask implementation
-TestOrderablePendingTask::TestOrderablePendingTask()
-    : task_id_(TestOrderablePendingTask::task_id_counter++) {}
-
-TestOrderablePendingTask::TestOrderablePendingTask(
-    const base::Location& location,
-    base::OnceClosure task,
-    base::TimeTicks post_time,
-    base::TimeDelta delay,
-    TestNestability nestability)
-    : base::TestPendingTask(location,
-                            std::move(task),
-                            post_time,
-                            delay,
-                            nestability),
-      task_id_(TestOrderablePendingTask::task_id_counter++) {}
-
-TestOrderablePendingTask::TestOrderablePendingTask(TestOrderablePendingTask&&) =
-    default;
-
-TestOrderablePendingTask& TestOrderablePendingTask::operator=(
-    TestOrderablePendingTask&&) = default;
-
-size_t TestOrderablePendingTask::task_id_counter = 0;
-
-TestOrderablePendingTask::~TestOrderablePendingTask() {}
-
-bool TestOrderablePendingTask::operator==(
-    const TestOrderablePendingTask& other) const {
-  return task_id_ == other.task_id_;
-}
-
-bool TestOrderablePendingTask::operator<(
-    const TestOrderablePendingTask& other) const {
-  if (*this == other)
-    return false;
-
-  if (GetTimeToRun() == other.GetTimeToRun()) {
-    return task_id_ < other.task_id_;
-  }
-  return ShouldRunBefore(other);
-}
-
-std::unique_ptr<base::trace_event::ConvertableToTraceFormat>
-TestOrderablePendingTask::AsValue() const {
-  std::unique_ptr<base::trace_event::TracedValue> state(
-      new base::trace_event::TracedValue());
-  AsValueInto(state.get());
-  return std::move(state);
-}
-
-void TestOrderablePendingTask::AsValueInto(
-    base::trace_event::TracedValue* state) const {
-  state->SetInteger("id", base::saturated_cast<int>(task_id_));
-  state->SetInteger("run_at", GetTimeToRun().since_origin().InMicroseconds());
-  state->SetString("posted_from", location.ToString());
-}
-
-OrderedSimpleTaskRunner::OrderedSimpleTaskRunner(
-    base::SimpleTestTickClock* now_src,
-    bool advance_now)
-    : advance_now_(advance_now),
-      now_src_(now_src),
-      max_tasks_(kAbsoluteMaxTasks),
-      inside_run_tasks_until_(false) {}
-
-OrderedSimpleTaskRunner::~OrderedSimpleTaskRunner() {}
-
-// base::TestSimpleTaskRunner implementation
-bool OrderedSimpleTaskRunner::PostDelayedTask(const base::Location& from_here,
-                                              base::OnceClosure task,
-                                              base::TimeDelta delay) {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  TestOrderablePendingTask pt(from_here, std::move(task), now_src_->NowTicks(),
-                              delay, base::TestPendingTask::NESTABLE);
-
-  TRACE_TASK("OrderedSimpleTaskRunner::PostDelayedTask", pt);
-  pending_tasks_.insert(std::move(pt));
-  return true;
-}
-
-bool OrderedSimpleTaskRunner::PostNonNestableDelayedTask(
-    const base::Location& from_here,
-    base::OnceClosure task,
-    base::TimeDelta delay) {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  TestOrderablePendingTask pt(from_here, std::move(task), now_src_->NowTicks(),
-                              delay, base::TestPendingTask::NON_NESTABLE);
-
-  TRACE_TASK("OrderedSimpleTaskRunner::PostNonNestableDelayedTask", pt);
-  pending_tasks_.insert(std::move(pt));
-  return true;
-}
-
-bool OrderedSimpleTaskRunner::RunsTasksInCurrentSequence() const {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  return true;
-}
-
-size_t OrderedSimpleTaskRunner::NumPendingTasks() const {
-  return pending_tasks_.size();
-}
-
-bool OrderedSimpleTaskRunner::HasPendingTasks() const {
-  return pending_tasks_.size() > 0;
-}
-
-base::TimeTicks OrderedSimpleTaskRunner::NextTaskTime() {
-  RemoveCancelledTasks();
-
-  if (pending_tasks_.size() <= 0) {
-    return base::TimeTicks::Max();
-  }
-
-  return pending_tasks_.begin()->GetTimeToRun();
-}
-
-base::TimeDelta OrderedSimpleTaskRunner::DelayToNextTaskTime() {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  RemoveCancelledTasks();
-
-  if (pending_tasks_.size() <= 0) {
-    return base::TimeTicks::Max().since_origin();
-  }
-
-  base::TimeDelta delay = NextTaskTime() - now_src_->NowTicks();
-  if (delay > base::TimeDelta())
-    return delay;
-  return base::TimeDelta();
-}
-
-const size_t OrderedSimpleTaskRunner::kAbsoluteMaxTasks =
-    std::numeric_limits<size_t>::max();
-
-bool OrderedSimpleTaskRunner::RunTasksWhile(
-    base::Callback<bool(void)> condition) {
-  std::vector<base::Callback<bool(void)>> conditions(1);
-  conditions[0] = condition;
-  return RunTasksWhile(conditions);
-}
-
-bool OrderedSimpleTaskRunner::RunTasksWhile(
-    const std::vector<base::Callback<bool(void)>>& conditions) {
-  TRACE_EVENT2("viz", "OrderedSimpleTaskRunner::RunPendingTasks", "this",
-               AsValue(), "nested", inside_run_tasks_until_);
-  DCHECK(thread_checker_.CalledOnValidThread());
-
-  if (inside_run_tasks_until_)
-    return true;
-
-  base::AutoReset<bool> reset_inside_run_tasks_until_(&inside_run_tasks_until_,
-                                                      true);
-
-  // Make a copy so we can append some extra run checks.
-  std::vector<base::Callback<bool(void)>> modifiable_conditions(conditions);
-
-  // Provide a timeout base on number of tasks run so this doesn't loop
-  // forever.
-  modifiable_conditions.push_back(TaskRunCountBelow(max_tasks_));
-
-  // If to advance now or not
-  if (!advance_now_) {
-    modifiable_conditions.push_back(NowBefore(now_src_->NowTicks()));
-  } else {
-    modifiable_conditions.push_back(AdvanceNow());
-  }
-
-  while (pending_tasks_.size() > 0) {
-    // Skip canceled tasks.
-    if (pending_tasks_.begin()->task.IsCancelled()) {
-      pending_tasks_.erase(pending_tasks_.begin());
-      continue;
-    }
-    // Check if we should continue to run pending tasks.
-    bool condition_success = true;
-    for (std::vector<base::Callback<bool(void)>>::iterator it =
-             modifiable_conditions.begin();
-         it != modifiable_conditions.end(); it++) {
-      condition_success = it->Run();
-      if (!condition_success)
-        break;
-    }
-
-    // Conditions could modify the pending task length, so we need to recheck
-    // that there are tasks to run.
-    if (!condition_success || !HasPendingTasks()) {
-      break;
-    }
-
-    std::set<TestOrderablePendingTask>::iterator task_to_run =
-        pending_tasks_.begin();
-    {
-      TRACE_EVENT1("viz", "OrderedSimpleTaskRunner::RunPendingTasks running",
-                   "task", task_to_run->AsValue());
-      // It's safe to remove const and consume |task| here, since |task| is not
-      // used for ordering the item.
-      base::OnceClosure& task =
-          const_cast<base::OnceClosure&>(task_to_run->task);
-      std::move(task).Run();
-    }
-
-    pending_tasks_.erase(task_to_run);
-  }
-
-  return HasPendingTasks();
-}
-
-bool OrderedSimpleTaskRunner::RunPendingTasks() {
-  return RunTasksWhile(TaskExistedInitially());
-}
-
-bool OrderedSimpleTaskRunner::RunUntilIdle() {
-  return RunTasksWhile(std::vector<base::Callback<bool(void)>>());
-}
-
-bool OrderedSimpleTaskRunner::RunUntilTime(base::TimeTicks time) {
-  // If we are not auto advancing, force now forward to the time.
-  if (!advance_now_ && now_src_->NowTicks() < time)
-    now_src_->Advance(time - now_src_->NowTicks());
-
-  // Run tasks
-  bool result = RunTasksWhile(NowBefore(time));
-
-  bool has_reached_task_limit = HasPendingTasks() && NextTaskTime() <= time;
-
-  // If the next task is after the stopping time and auto-advancing now, then
-  // force time to be the stopping time.
-  if (!has_reached_task_limit && advance_now_ && now_src_->NowTicks() < time) {
-    now_src_->Advance(time - now_src_->NowTicks());
-  }
-
-  return result;
-}
-
-bool OrderedSimpleTaskRunner::RunForPeriod(base::TimeDelta period) {
-  return RunUntilTime(now_src_->NowTicks() + period);
-}
-
-// base::trace_event tracing functionality
-std::unique_ptr<base::trace_event::ConvertableToTraceFormat>
-OrderedSimpleTaskRunner::AsValue() const {
-  std::unique_ptr<base::trace_event::TracedValue> state(
-      new base::trace_event::TracedValue());
-  AsValueInto(state.get());
-  return std::move(state);
-}
-
-void OrderedSimpleTaskRunner::AsValueInto(
-    base::trace_event::TracedValue* state) const {
-  state->SetInteger("pending_tasks",
-                    base::saturated_cast<int>(pending_tasks_.size()));
-
-  state->BeginArray("tasks");
-  for (std::set<TestOrderablePendingTask>::const_iterator it =
-           pending_tasks_.begin();
-       it != pending_tasks_.end(); ++it) {
-    state->BeginDictionary();
-    it->AsValueInto(state);
-    state->EndDictionary();
-  }
-  state->EndArray();
-
-  state->BeginDictionary("now_src");
-  state->SetDouble("now_in_ms",
-                   now_src_->NowTicks().since_origin().InMillisecondsF());
-  state->EndDictionary();
-
-  state->SetBoolean("advance_now", advance_now_);
-  state->SetBoolean("inside_run_tasks_until", inside_run_tasks_until_);
-  state->SetString("max_tasks", base::NumberToString(max_tasks_));
-}
-
-base::Callback<bool(void)> OrderedSimpleTaskRunner::TaskRunCountBelow(
-    size_t max_tasks) {
-  return base::Bind(&OrderedSimpleTaskRunner::TaskRunCountBelowCallback,
-                    max_tasks, base::Owned(new size_t(0)));
-}
-
-bool OrderedSimpleTaskRunner::TaskRunCountBelowCallback(size_t max_tasks,
-                                                        size_t* tasks_run) {
-  return (*tasks_run)++ < max_tasks;
-}
-
-base::Callback<bool(void)> OrderedSimpleTaskRunner::TaskExistedInitially() {
-  std::set<size_t> task_ids;
-  for (const auto& task : pending_tasks_)
-    task_ids.insert(task.task_id());
-
-  return base::Bind(&OrderedSimpleTaskRunner::TaskExistedInitiallyCallback,
-                    base::Unretained(this), std::move(task_ids));
-}
-
-bool OrderedSimpleTaskRunner::TaskExistedInitiallyCallback(
-    const std::set<size_t>& existing_tasks) {
-  return existing_tasks.find(pending_tasks_.begin()->task_id()) !=
-         existing_tasks.end();
-}
-
-base::Callback<bool(void)> OrderedSimpleTaskRunner::NowBefore(
-    base::TimeTicks stop_at) {
-  return base::Bind(&OrderedSimpleTaskRunner::NowBeforeCallback,
-                    base::Unretained(this), stop_at);
-}
-bool OrderedSimpleTaskRunner::NowBeforeCallback(base::TimeTicks stop_at) {
-  return NextTaskTime() <= stop_at;
-}
-
-base::Callback<bool(void)> OrderedSimpleTaskRunner::AdvanceNow() {
-  return base::Bind(&OrderedSimpleTaskRunner::AdvanceNowCallback,
-                    base::Unretained(this));
-}
-
-bool OrderedSimpleTaskRunner::AdvanceNowCallback() {
-  base::TimeTicks next_task_time = NextTaskTime();
-  if (now_src_->NowTicks() < next_task_time) {
-    now_src_->Advance(next_task_time - now_src_->NowTicks());
-  }
-  return true;
-}
-
-void OrderedSimpleTaskRunner::RemoveCancelledTasks() {
-  std::set<TestOrderablePendingTask>::iterator it = pending_tasks_.begin();
-  while (it != pending_tasks_.end()) {
-    if (it->task.IsCancelled()) {
-      it = pending_tasks_.erase(it);
-    } else {
-      it++;
-    }
-  }
-}
-
-}  // namespace cc
diff --git a/components/viz/test/ordered_simple_task_runner.h b/components/viz/test/ordered_simple_task_runner.h
deleted file mode 100644
index 401e1aa..0000000
--- a/components/viz/test/ordered_simple_task_runner.h
+++ /dev/null
@@ -1,167 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_VIZ_TEST_ORDERED_SIMPLE_TASK_RUNNER_H_
-#define COMPONENTS_VIZ_TEST_ORDERED_SIMPLE_TASK_RUNNER_H_
-
-#include <stddef.h>
-
-#include <limits>
-#include <memory>
-#include <set>
-#include <vector>
-
-#include "base/callback.h"
-#include "base/compiler_specific.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/test/simple_test_tick_clock.h"
-#include "base/test/test_simple_task_runner.h"
-#include "base/threading/thread_checker.h"
-#include "base/trace_event/trace_event.h"
-
-namespace cc {
-
-// Subclass of TestPendingTask which has a unique ID for every task, supports
-// being used inside a std::set and has debug tracing support.
-class TestOrderablePendingTask : public base::TestPendingTask {
- public:
-  TestOrderablePendingTask();
-  TestOrderablePendingTask(const base::Location& location,
-                           base::OnceClosure task,
-                           base::TimeTicks post_time,
-                           base::TimeDelta delay,
-                           TestNestability nestability);
-  TestOrderablePendingTask(TestOrderablePendingTask&&);
-  ~TestOrderablePendingTask();
-
-  TestOrderablePendingTask& operator=(TestOrderablePendingTask&&);
-
-  // operators needed by std::set and comparison
-  bool operator==(const TestOrderablePendingTask& other) const;
-  bool operator<(const TestOrderablePendingTask& other) const;
-
-  // base::trace_event tracing functionality
-  std::unique_ptr<base::trace_event::ConvertableToTraceFormat> AsValue() const;
-  void AsValueInto(base::trace_event::TracedValue* state) const;
-
-  size_t task_id() const { return task_id_; }
-
- private:
-  static size_t task_id_counter;
-  size_t task_id_;
-
-  DISALLOW_COPY_AND_ASSIGN(TestOrderablePendingTask);
-};
-
-// This runs pending tasks based on task's post_time + delay.
-// We should not execute a delayed task sooner than some of the queued tasks
-// which don't have a delay even though it is queued early.
-class OrderedSimpleTaskRunner : public base::SingleThreadTaskRunner {
- public:
-  OrderedSimpleTaskRunner(base::SimpleTestTickClock* now_src, bool advance_now);
-
-  // base::TestSimpleTaskRunner implementation:
-  bool PostDelayedTask(const base::Location& from_here,
-                       base::OnceClosure task,
-                       base::TimeDelta delay) override;
-  bool PostNonNestableDelayedTask(const base::Location& from_here,
-                                  base::OnceClosure task,
-                                  base::TimeDelta delay) override;
-
-  bool RunsTasksInCurrentSequence() const override;
-
-  // Set a maximum number of tasks to run at once. Useful as a timeout to
-  // prevent infinite task loops.
-  static const size_t kAbsoluteMaxTasks;
-  void SetRunTaskLimit(size_t max_tasks) { max_tasks_ = max_tasks; }
-  void ClearRunTaskLimit() { max_tasks_ = kAbsoluteMaxTasks; }
-
-  // Allow task runner to advance now when running tasks.
-  void SetAutoAdvanceNowToPendingTasks(bool advance_now) {
-    advance_now_ = advance_now;
-  }
-
-  size_t NumPendingTasks() const;
-  bool HasPendingTasks() const;
-  base::TimeTicks NextTaskTime();
-  base::TimeDelta DelayToNextTaskTime();
-
-  // Run tasks while the callback returns true or too many tasks have been run.
-  // Returns true if there are still pending tasks left.
-  bool RunTasksWhile(base::Callback<bool(void)> condition);
-
-  // Run tasks while *all* of the callbacks return true or too many tasks have
-  // been run. Exits on the *first* condition which returns false, skipping
-  // calling all remaining conditions. Conditions can have side effects,
-  // including modifying the task queue.
-  // Returns true if there are still pending tasks left.
-  bool RunTasksWhile(const std::vector<base::Callback<bool(void)>>& conditions);
-
-  // Convenience functions to run tasks with common conditions.
-
-  // Run tasks which existed at the start of this call.
-  // Return code indicates tasks still exist to run.
-  bool RunPendingTasks();
-  // Keep running tasks until no tasks are left.
-  // Return code indicates tasks still exist to run which also indicates if
-  // runner reached idle.
-  bool RunUntilIdle();
-  // Keep running tasks until given time period.
-  // Return code indicates tasks still exist to run.
-  bool RunUntilTime(base::TimeTicks time);
-  bool RunForPeriod(base::TimeDelta period);
-
-  // base::trace_event tracing functionality
-  std::unique_ptr<base::trace_event::ConvertableToTraceFormat> AsValue() const;
-  virtual void AsValueInto(base::trace_event::TracedValue* state) const;
-
-  // Common conditions to run for, exposed publicly to allow external users to
-  // use their own combinations.
-  // -------------------------------------------------------------------------
-
-  // Keep running until the given number of tasks have run.
-  // You generally shouldn't use this check as it will cause your tests to fail
-  // when code is changed adding a new task. It is useful as a "timeout" type
-  // solution.
-  base::Callback<bool(void)> TaskRunCountBelow(size_t max_tasks);
-
-  // Keep running until a task which didn't exist initially would run.
-  base::Callback<bool(void)> TaskExistedInitially();
-
-  // Stop running tasks when NextTaskTime() >= stop_at
-  base::Callback<bool(void)> NowBefore(base::TimeTicks stop_at);
-
-  // Advance Now() to the next task to run.
-  base::Callback<bool(void)> AdvanceNow();
-
-  // Removes all tasks whose weak pointer has been revoked.
-  void RemoveCancelledTasks();
-
- protected:
-  static bool TaskRunCountBelowCallback(size_t max_tasks, size_t* task_run);
-  bool TaskExistedInitiallyCallback(const std::set<size_t>& existing_tasks);
-  bool NowBeforeCallback(base::TimeTicks stop_at);
-  bool AdvanceNowCallback();
-
-  ~OrderedSimpleTaskRunner() override;
-
-  base::ThreadChecker thread_checker_;
-
-  bool advance_now_;
-  // Not owned.
-  base::SimpleTestTickClock* now_src_;
-
-  size_t max_tasks_;
-
-  bool inside_run_tasks_until_;
-  std::set<TestOrderablePendingTask> pending_tasks_;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(OrderedSimpleTaskRunner);
-};
-
-}  // namespace cc
-
-#endif  // COMPONENTS_VIZ_TEST_ORDERED_SIMPLE_TASK_RUNNER_H_
diff --git a/components/viz/test/ordered_simple_task_runner_unittest.cc b/components/viz/test/ordered_simple_task_runner_unittest.cc
deleted file mode 100644
index cba677b..0000000
--- a/components/viz/test/ordered_simple_task_runner_unittest.cc
+++ /dev/null
@@ -1,435 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/viz/test/ordered_simple_task_runner.h"
-
-#include <memory>
-#include <string>
-
-#include "base/cancelable_callback.h"
-#include "base/format_macros.h"
-#include "base/macros.h"
-#include "base/strings/stringprintf.h"
-#include "base/test/test_pending_task.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-// We pass EXPECT_TRUE / EXPECT_FALSE macros rather than a boolean as on some
-// compilers EXPECT_EQ(false, XXXX) fails to compile as gtest tries to convert
-// the false value to null causing a -Werror=conversion-null error.
-#define RUN_AND_CHECK_RESULT(tasks_remain_expect_macro, run_func, \
-                             expected_result)                     \
-  tasks_remain_expect_macro(task_runner_->run_func);              \
-  EXPECT_EQ(expected_result, executed_tasks_);                    \
-  executed_tasks_ = "";
-
-namespace {
-
-bool ReturnTrue() {
-  return true;
-}
-
-bool ReturnFalse() {
-  return false;
-}
-};  // namespace
-
-namespace cc {
-
-TEST(TestOrderablePendingTask, Ordering) {
-  TestOrderablePendingTask a;
-  TestOrderablePendingTask b;
-  TestOrderablePendingTask c;
-
-  EXPECT_EQ(a, a);
-  EXPECT_EQ(b, b);
-  EXPECT_EQ(c, c);
-  EXPECT_LT(a, b);
-  EXPECT_LT(b, c);
-  EXPECT_LT(a, c);
-
-  TestOrderablePendingTask a2 = std::move(a);
-  EXPECT_LT(a2, b);
-  EXPECT_LT(b, c);
-  EXPECT_LT(a2, c);
-}
-
-class OrderedSimpleTaskRunnerTest : public testing::Test {
- public:
-  OrderedSimpleTaskRunnerTest()
-      : now_src_(new base::SimpleTestTickClock()),
-        task_runner_(new OrderedSimpleTaskRunner(now_src_.get(), true)) {}
-  ~OrderedSimpleTaskRunnerTest() override {}
-
- protected:
-  std::string executed_tasks_;
-  std::unique_ptr<base::SimpleTestTickClock> now_src_;
-  scoped_refptr<OrderedSimpleTaskRunner> task_runner_;
-
-  void PostTask(int task_num, base::TimeDelta delay) {
-    base::Closure test_task = base::Bind(&OrderedSimpleTaskRunnerTest::Task,
-                                         base::Unretained(this), task_num);
-    task_runner_->PostDelayedTask(FROM_HERE, test_task, delay);
-  }
-
-  void PostTaskWhichPostsInstantTask(int task_num, base::TimeDelta delay) {
-    base::Closure test_task =
-        base::Bind(&OrderedSimpleTaskRunnerTest::TaskWhichPostsInstantTask,
-                   base::Unretained(this), task_num);
-    task_runner_->PostDelayedTask(FROM_HERE, test_task, delay);
-  }
-
-  void PostTaskWhichPostsDelayedTask(int task_num,
-                                     base::TimeDelta delay1,
-                                     base::TimeDelta delay2) {
-    base::Closure test_task =
-        base::Bind(&OrderedSimpleTaskRunnerTest::TaskWhichPostsDelayedTask,
-                   base::Unretained(this), task_num, delay2);
-    task_runner_->PostDelayedTask(FROM_HERE, test_task, delay1);
-  }
-
-  void PostTaskWhichCallsRun(int task_num, base::TimeDelta delay) {
-    base::Closure test_task =
-        base::Bind(&OrderedSimpleTaskRunnerTest::TaskWhichCallsRun,
-                   base::Unretained(this), task_num);
-    task_runner_->PostDelayedTask(FROM_HERE, test_task, delay);
-  }
-
-  void PostTaskWhichPostsTaskAgain(int task_num, base::TimeDelta delay) {
-    base::Closure test_task =
-        base::Bind(&OrderedSimpleTaskRunnerTest::TaskWhichPostsAgain,
-                   base::Unretained(this), task_num, delay);
-    task_runner_->PostDelayedTask(FROM_HERE, test_task, delay);
-  }
-
- private:
-  void Task(int task_num) {
-    if (!executed_tasks_.empty())
-      executed_tasks_ += " ";
-    executed_tasks_ += base::StringPrintf(
-        "%d(%" PRId64 "ms)", task_num,
-        (now_src_->NowTicks() - base::TimeTicks()).InMilliseconds());
-  }
-
-  void TaskWhichPostsInstantTask(int task_num) {
-    Task(task_num);
-    PostTask(-task_num, base::TimeDelta());
-  }
-
-  void TaskWhichPostsDelayedTask(int task_num, base::TimeDelta delay) {
-    Task(task_num);
-    PostTask(-task_num, delay);
-  }
-
-  void TaskWhichCallsRun(int task_num) {
-    Task(task_num);
-    task_runner_->RunPendingTasks();
-  }
-
-  void TaskWhichPostsAgain(int task_num, base::TimeDelta delay) {
-    Task(task_num);
-    PostTaskWhichPostsTaskAgain(task_num, delay);
-  }
-
-  DISALLOW_COPY_AND_ASSIGN(OrderedSimpleTaskRunnerTest);
-};
-
-TEST_F(OrderedSimpleTaskRunnerTest, SimpleOrderingTest) {
-  PostTask(1, base::TimeDelta());
-  PostTask(2, base::TimeDelta());
-  PostTask(3, base::TimeDelta());
-
-  RUN_AND_CHECK_RESULT(EXPECT_FALSE, RunPendingTasks(), "1(0ms) 2(0ms) 3(0ms)");
-  RUN_AND_CHECK_RESULT(EXPECT_FALSE, RunPendingTasks(), "");
-
-  PostTask(4, base::TimeDelta());
-  RUN_AND_CHECK_RESULT(EXPECT_FALSE, RunPendingTasks(), "4(0ms)");
-  RUN_AND_CHECK_RESULT(EXPECT_FALSE, RunPendingTasks(), "");
-}
-
-TEST_F(OrderedSimpleTaskRunnerTest, SimpleOrderingTestPostingTasks) {
-  PostTaskWhichPostsInstantTask(1, base::TimeDelta());
-  PostTaskWhichPostsInstantTask(2, base::TimeDelta());
-  PostTaskWhichPostsInstantTask(3, base::TimeDelta());
-
-  RUN_AND_CHECK_RESULT(EXPECT_TRUE, RunPendingTasks(), "1(0ms) 2(0ms) 3(0ms)");
-  RUN_AND_CHECK_RESULT(EXPECT_FALSE, RunPendingTasks(),
-                       "-1(0ms) -2(0ms) -3(0ms)");
-  RUN_AND_CHECK_RESULT(EXPECT_FALSE, RunPendingTasks(), "");
-}
-
-TEST_F(OrderedSimpleTaskRunnerTest, SimpleOrderingTestPostingDelayedTasks) {
-  PostTaskWhichPostsDelayedTask(1, base::TimeDelta(),
-                                base::TimeDelta::FromMilliseconds(1));
-  PostTaskWhichPostsDelayedTask(2, base::TimeDelta(),
-                                base::TimeDelta::FromMilliseconds(1));
-  PostTaskWhichPostsDelayedTask(3, base::TimeDelta(),
-                                base::TimeDelta::FromMilliseconds(1));
-
-  RUN_AND_CHECK_RESULT(EXPECT_TRUE, RunPendingTasks(), "1(0ms) 2(0ms) 3(0ms)");
-  RUN_AND_CHECK_RESULT(EXPECT_FALSE, RunPendingTasks(),
-                       "-1(1ms) -2(1ms) -3(1ms)");
-  RUN_AND_CHECK_RESULT(EXPECT_FALSE, RunPendingTasks(), "");
-}
-
-TEST_F(OrderedSimpleTaskRunnerTest,
-       SimpleOrderingTestPostingReordingDelayedTasks) {
-  PostTaskWhichPostsDelayedTask(1, base::TimeDelta::FromMilliseconds(1),
-                                base::TimeDelta::FromMilliseconds(20));
-  PostTaskWhichPostsDelayedTask(2, base::TimeDelta::FromMilliseconds(2),
-                                base::TimeDelta::FromMilliseconds(5));
-  PostTaskWhichPostsDelayedTask(3, base::TimeDelta::FromMilliseconds(3),
-                                base::TimeDelta::FromMilliseconds(5));
-
-  RUN_AND_CHECK_RESULT(EXPECT_TRUE, RunPendingTasks(), "1(1ms) 2(2ms) 3(3ms)");
-  RUN_AND_CHECK_RESULT(EXPECT_FALSE, RunPendingTasks(),
-                       "-2(7ms) -3(8ms) -1(21ms)");
-  RUN_AND_CHECK_RESULT(EXPECT_FALSE, RunPendingTasks(), "");
-}
-
-TEST_F(OrderedSimpleTaskRunnerTest,
-       SimpleOrderingTestPostingReordingDelayedTasksOverlap) {
-  PostTaskWhichPostsDelayedTask(1, base::TimeDelta::FromMilliseconds(1),
-                                base::TimeDelta::FromMilliseconds(5));
-  PostTaskWhichPostsDelayedTask(2, base::TimeDelta::FromMilliseconds(5),
-                                base::TimeDelta::FromMilliseconds(10));
-  PostTaskWhichPostsDelayedTask(3, base::TimeDelta::FromMilliseconds(10),
-                                base::TimeDelta::FromMilliseconds(1));
-
-  RUN_AND_CHECK_RESULT(EXPECT_TRUE, RunPendingTasks(), "1(1ms) 2(5ms)");
-  RUN_AND_CHECK_RESULT(EXPECT_TRUE, RunPendingTasks(), "-1(6ms) 3(10ms)");
-  RUN_AND_CHECK_RESULT(EXPECT_FALSE, RunPendingTasks(), "-3(11ms) -2(15ms)");
-  RUN_AND_CHECK_RESULT(EXPECT_FALSE, RunPendingTasks(), "");
-}
-
-TEST_F(OrderedSimpleTaskRunnerTest, SimpleOrderingTestPostingAndRentrantTasks) {
-  PostTaskWhichPostsInstantTask(1, base::TimeDelta());
-  PostTaskWhichCallsRun(2, base::TimeDelta());
-  PostTaskWhichPostsInstantTask(3, base::TimeDelta());
-
-  RUN_AND_CHECK_RESULT(EXPECT_TRUE, RunPendingTasks(), "1(0ms) 2(0ms) 3(0ms)");
-  RUN_AND_CHECK_RESULT(EXPECT_FALSE, RunPendingTasks(), "-1(0ms) -3(0ms)");
-  RUN_AND_CHECK_RESULT(EXPECT_FALSE, RunPendingTasks(), "");
-}
-
-TEST_F(OrderedSimpleTaskRunnerTest,
-       SimpleOrderingTestPostingDelayedAndRentrantTasks) {
-  PostTaskWhichPostsDelayedTask(1, base::TimeDelta(),
-                                base::TimeDelta::FromMilliseconds(1));
-  PostTaskWhichCallsRun(2, base::TimeDelta());
-  PostTaskWhichPostsDelayedTask(3, base::TimeDelta(),
-                                base::TimeDelta::FromMilliseconds(1));
-
-  RUN_AND_CHECK_RESULT(EXPECT_TRUE, RunPendingTasks(), "1(0ms) 2(0ms) 3(0ms)");
-  RUN_AND_CHECK_RESULT(EXPECT_FALSE, RunPendingTasks(), "-1(1ms) -3(1ms)");
-  RUN_AND_CHECK_RESULT(EXPECT_FALSE, RunPendingTasks(), "");
-}
-
-TEST_F(OrderedSimpleTaskRunnerTest, OrderingTestWithDelayedTasks) {
-  PostTask(1, base::TimeDelta());
-  PostTask(2, base::TimeDelta::FromMilliseconds(15));
-  PostTask(3, base::TimeDelta());
-  PostTask(4, base::TimeDelta::FromMilliseconds(8));
-
-  RUN_AND_CHECK_RESULT(EXPECT_FALSE, RunPendingTasks(),
-                       "1(0ms) 3(0ms) 4(8ms) 2(15ms)");
-  RUN_AND_CHECK_RESULT(EXPECT_FALSE, RunPendingTasks(), "");
-}
-
-TEST_F(OrderedSimpleTaskRunnerTest, OrderingTestWithDelayedPostingTasks) {
-  PostTaskWhichPostsInstantTask(1, base::TimeDelta());
-  PostTaskWhichPostsInstantTask(2, base::TimeDelta::FromMilliseconds(15));
-  PostTaskWhichPostsInstantTask(3, base::TimeDelta());
-  PostTaskWhichPostsInstantTask(4, base::TimeDelta::FromMilliseconds(8));
-
-  RUN_AND_CHECK_RESULT(EXPECT_TRUE, RunPendingTasks(), "1(0ms) 3(0ms)");
-  RUN_AND_CHECK_RESULT(EXPECT_TRUE, RunPendingTasks(),
-                       "-1(0ms) -3(0ms) 4(8ms)");
-  RUN_AND_CHECK_RESULT(EXPECT_TRUE, RunPendingTasks(), "-4(8ms) 2(15ms)");
-  RUN_AND_CHECK_RESULT(EXPECT_FALSE, RunPendingTasks(), "-2(15ms)");
-  RUN_AND_CHECK_RESULT(EXPECT_FALSE, RunPendingTasks(), "");
-}
-
-TEST_F(OrderedSimpleTaskRunnerTest, OrderingTestWithDelayedTasksManualNow) {
-  task_runner_->SetAutoAdvanceNowToPendingTasks(false);
-  PostTask(1, base::TimeDelta());
-  PostTask(2, base::TimeDelta::FromMilliseconds(15));
-  PostTask(3, base::TimeDelta());
-  PostTask(4, base::TimeDelta::FromMilliseconds(8));
-
-  RUN_AND_CHECK_RESULT(EXPECT_TRUE, RunPendingTasks(), "1(0ms) 3(0ms)");
-  RUN_AND_CHECK_RESULT(EXPECT_TRUE, RunPendingTasks(), "");
-  EXPECT_EQ(task_runner_->DelayToNextTaskTime(),
-            base::TimeDelta::FromMilliseconds(8));
-  now_src_->Advance(base::TimeDelta::FromMicroseconds(5000));
-  EXPECT_EQ(task_runner_->DelayToNextTaskTime(),
-            base::TimeDelta::FromMilliseconds(3));
-  now_src_->Advance(base::TimeDelta::FromMicroseconds(20000));
-  EXPECT_EQ(task_runner_->DelayToNextTaskTime(), base::TimeDelta());
-  RUN_AND_CHECK_RESULT(EXPECT_FALSE, RunPendingTasks(), "4(25ms) 2(25ms)");
-  RUN_AND_CHECK_RESULT(EXPECT_FALSE, RunPendingTasks(), "");
-}
-
-TEST_F(OrderedSimpleTaskRunnerTest, RunUntilIdle) {
-  PostTaskWhichPostsInstantTask(1, base::TimeDelta());
-  RUN_AND_CHECK_RESULT(EXPECT_FALSE, RunUntilIdle(), "1(0ms) -1(0ms)");
-  RUN_AND_CHECK_RESULT(EXPECT_FALSE, RunUntilIdle(), "");
-}
-
-TEST_F(OrderedSimpleTaskRunnerTest, RunUntilTimeAutoNow) {
-  PostTaskWhichPostsInstantTask(1, base::TimeDelta());
-  PostTaskWhichPostsInstantTask(2, base::TimeDelta::FromMilliseconds(2));
-  PostTaskWhichPostsInstantTask(3, base::TimeDelta::FromMilliseconds(3));
-
-  task_runner_->SetAutoAdvanceNowToPendingTasks(true);
-
-  base::TimeTicks run_at = base::TimeTicks();
-
-  run_at += base::TimeDelta::FromMilliseconds(2);
-  RUN_AND_CHECK_RESULT(EXPECT_TRUE, RunUntilTime(run_at),
-                       "1(0ms) -1(0ms) 2(2ms) -2(2ms)");
-  EXPECT_EQ(run_at, now_src_->NowTicks());
-
-  run_at += base::TimeDelta::FromMilliseconds(1);
-  RUN_AND_CHECK_RESULT(EXPECT_FALSE, RunUntilTime(run_at), "3(3ms) -3(3ms)");
-  EXPECT_EQ(run_at, now_src_->NowTicks());
-
-  run_at += base::TimeDelta::FromMilliseconds(1);
-  RUN_AND_CHECK_RESULT(EXPECT_FALSE, RunUntilTime(run_at), "");
-  EXPECT_EQ(run_at, now_src_->NowTicks());
-}
-
-TEST_F(OrderedSimpleTaskRunnerTest, RunUntilTimeManualNow) {
-  PostTaskWhichPostsInstantTask(1, base::TimeDelta());
-  PostTaskWhichPostsInstantTask(2, base::TimeDelta::FromMilliseconds(2));
-  PostTaskWhichPostsInstantTask(3, base::TimeDelta::FromMilliseconds(3));
-
-  task_runner_->SetAutoAdvanceNowToPendingTasks(false);
-
-  base::TimeTicks run_at = base::TimeTicks();
-
-  run_at += base::TimeDelta::FromMilliseconds(2);
-  RUN_AND_CHECK_RESULT(EXPECT_TRUE, RunUntilTime(run_at),
-                       "1(2ms) 2(2ms) -1(2ms) -2(2ms)");
-  EXPECT_EQ(run_at, now_src_->NowTicks());
-
-  run_at += base::TimeDelta::FromMilliseconds(1);
-  RUN_AND_CHECK_RESULT(EXPECT_FALSE, RunUntilTime(run_at), "3(3ms) -3(3ms)");
-  EXPECT_EQ(run_at, now_src_->NowTicks());
-
-  run_at += base::TimeDelta::FromMilliseconds(1);
-  RUN_AND_CHECK_RESULT(EXPECT_FALSE, RunUntilTime(run_at), "");
-  EXPECT_EQ(run_at, now_src_->NowTicks());
-}
-
-TEST_F(OrderedSimpleTaskRunnerTest, RunForPeriod) {
-  PostTaskWhichPostsInstantTask(1, base::TimeDelta());
-  PostTaskWhichPostsInstantTask(2, base::TimeDelta::FromMilliseconds(2));
-  PostTaskWhichPostsInstantTask(3, base::TimeDelta::FromMilliseconds(3));
-
-  RUN_AND_CHECK_RESULT(EXPECT_TRUE,
-                       RunForPeriod(base::TimeDelta::FromMilliseconds(2)),
-                       "1(0ms) -1(0ms) 2(2ms) -2(2ms)");
-  EXPECT_EQ(base::TimeTicks() + base::TimeDelta::FromMilliseconds(2),
-            now_src_->NowTicks());
-
-  RUN_AND_CHECK_RESULT(EXPECT_FALSE,
-                       RunForPeriod(base::TimeDelta::FromMilliseconds(1)),
-                       "3(3ms) -3(3ms)");
-  EXPECT_EQ(base::TimeTicks() + base::TimeDelta::FromMilliseconds(3),
-            now_src_->NowTicks());
-
-  RUN_AND_CHECK_RESULT(EXPECT_FALSE,
-                       RunForPeriod(base::TimeDelta::FromMilliseconds(1)), "");
-  EXPECT_EQ(base::TimeTicks() + base::TimeDelta::FromMilliseconds(4),
-            now_src_->NowTicks());
-}
-
-TEST_F(OrderedSimpleTaskRunnerTest, RunTasksWhileWithCallback) {
-  base::Callback<bool(void)> return_true = base::Bind(&ReturnTrue);
-  base::Callback<bool(void)> return_false = base::Bind(&ReturnFalse);
-
-  PostTask(1, base::TimeDelta());
-
-  RUN_AND_CHECK_RESULT(EXPECT_TRUE, RunTasksWhile(return_false), "");
-  RUN_AND_CHECK_RESULT(EXPECT_FALSE, RunTasksWhile(return_true), "1(0ms)");
-}
-
-TEST_F(OrderedSimpleTaskRunnerTest, EmptyTaskList) {
-  RUN_AND_CHECK_RESULT(EXPECT_FALSE, RunPendingTasks(), "");
-  RUN_AND_CHECK_RESULT(EXPECT_FALSE, RunUntilIdle(), "");
-
-  ASSERT_EQ(base::TimeTicks(), now_src_->NowTicks());
-
-  RUN_AND_CHECK_RESULT(
-      EXPECT_FALSE,
-      RunUntilTime(base::TimeTicks() + base::TimeDelta::FromMicroseconds(100)),
-      "");
-  EXPECT_EQ(base::TimeTicks() + base::TimeDelta::FromMicroseconds(100),
-            now_src_->NowTicks());
-
-  RUN_AND_CHECK_RESULT(
-      EXPECT_FALSE, RunForPeriod(base::TimeDelta::FromMicroseconds(100)), "");
-  EXPECT_EQ(base::TimeTicks() + base::TimeDelta::FromMicroseconds(200),
-            now_src_->NowTicks());
-
-  base::Callback<bool(void)> return_true = base::Bind(&ReturnTrue);
-  RUN_AND_CHECK_RESULT(EXPECT_FALSE, RunTasksWhile(return_true), "");
-}
-
-TEST_F(OrderedSimpleTaskRunnerTest, RunPendingTasksTimeout) {
-  PostTask(1, base::TimeDelta());
-  PostTask(2, base::TimeDelta());
-  PostTask(3, base::TimeDelta());
-  PostTask(4, base::TimeDelta());
-  PostTask(5, base::TimeDelta());
-  PostTask(6, base::TimeDelta());
-
-  task_runner_->SetRunTaskLimit(3);
-  RUN_AND_CHECK_RESULT(EXPECT_TRUE, RunPendingTasks(), "1(0ms) 2(0ms) 3(0ms)");
-
-  task_runner_->SetRunTaskLimit(2);
-  RUN_AND_CHECK_RESULT(EXPECT_TRUE, RunPendingTasks(), "4(0ms) 5(0ms)");
-
-  task_runner_->SetRunTaskLimit(0);
-  RUN_AND_CHECK_RESULT(EXPECT_TRUE, RunPendingTasks(), "");
-}
-
-TEST_F(OrderedSimpleTaskRunnerTest, RunUntilIdleTimeout) {
-  PostTaskWhichPostsTaskAgain(1, base::TimeDelta::FromMilliseconds(3));
-
-  task_runner_->SetRunTaskLimit(3);
-  RUN_AND_CHECK_RESULT(EXPECT_TRUE, RunUntilIdle(), "1(3ms) 1(6ms) 1(9ms)");
-
-  task_runner_->SetRunTaskLimit(2);
-  RUN_AND_CHECK_RESULT(EXPECT_TRUE, RunUntilIdle(), "1(12ms) 1(15ms)");
-
-  task_runner_->SetRunTaskLimit(0);
-  RUN_AND_CHECK_RESULT(EXPECT_TRUE, RunUntilIdle(), "");
-}
-
-TEST_F(OrderedSimpleTaskRunnerTest, RunUntilTimeout) {
-  base::TimeTicks run_to = base::TimeTicks() + base::TimeDelta::FromSeconds(1);
-
-  PostTask(1, base::TimeDelta::FromMilliseconds(1));
-  PostTask(2, base::TimeDelta::FromMilliseconds(2));
-  PostTask(3, base::TimeDelta::FromMilliseconds(3));
-  PostTask(4, base::TimeDelta::FromMilliseconds(4));
-  PostTask(5, base::TimeDelta::FromMilliseconds(5));
-
-  EXPECT_EQ(base::TimeTicks(), now_src_->NowTicks());
-  task_runner_->SetRunTaskLimit(3);
-  RUN_AND_CHECK_RESULT(EXPECT_TRUE, RunUntilTime(run_to),
-                       "1(1ms) 2(2ms) 3(3ms)");
-  EXPECT_EQ(base::TimeTicks() + base::TimeDelta::FromMilliseconds(3),
-            now_src_->NowTicks());
-
-  task_runner_->SetRunTaskLimit(0);
-  RUN_AND_CHECK_RESULT(EXPECT_TRUE, RunUntilTime(run_to), "");
-
-  task_runner_->SetRunTaskLimit(100);
-  RUN_AND_CHECK_RESULT(EXPECT_FALSE, RunUntilTime(run_to), "4(4ms) 5(5ms)");
-  EXPECT_EQ(run_to, now_src_->NowTicks());
-}
-
-}  // namespace cc
diff --git a/content/browser/appcache/chrome_appcache_service.h b/content/browser/appcache/chrome_appcache_service.h
index 6c2ca7e..316f2c4 100644
--- a/content/browser/appcache/chrome_appcache_service.h
+++ b/content/browser/appcache/chrome_appcache_service.h
@@ -59,8 +59,11 @@
   void Bind(std::unique_ptr<mojom::AppCacheBackend> backend,
             mojom::AppCacheBackendRequest request,
             int process_id);
-  // Unbinds the pipe corresponding the to the given process_id.
-  // It does nothing if no pipe was bound.
+  // Unbinds the pipe corresponding to the given process_id. Unbinding
+  // unregisters and destroys the existing backend for that process_id.
+  // The function must be called before a new backend is created for the given
+  // process_id to ensure that there is at most one backend per process_id.
+  // The function does nothing if no pipe was bound.
   void Unbind(int process_id);
 
   void Shutdown();
diff --git a/content/browser/do_not_track_browsertest.cc b/content/browser/do_not_track_browsertest.cc
index cc053f0..63c48bd 100644
--- a/content/browser/do_not_track_browsertest.cc
+++ b/content/browser/do_not_track_browsertest.cc
@@ -3,6 +3,8 @@
 // found in the LICENSE file.
 
 #include "base/strings/utf_string_conversions.h"
+#include "build/build_config.h"
+#include "content/public/browser/content_browser_client.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/renderer_preferences.h"
 #include "content/public/test/browser_test_utils.h"
@@ -13,10 +15,23 @@
 #include "net/test/embedded_test_server/http_request.h"
 #include "net/test/embedded_test_server/http_response.h"
 
+#if defined(OS_ANDROID)
+#include "base/sys_info.h"
+#endif
+
 namespace content {
 
 namespace {
 
+class MockContentBrowserClient final : public ContentBrowserClient {
+ public:
+  void UpdateRendererPreferencesForWorker(BrowserContext*,
+                                          RendererPreferences* prefs) override {
+    prefs->enable_do_not_track = true;
+    prefs->enable_referrers = true;
+  }
+};
+
 class DoNotTrackTest : public ContentBrowserTest {
  protected:
   void EnableDoNotTrack() {
@@ -193,8 +208,20 @@
 }
 
 // Checks that the DNT header is preserved when fetching from a service worker.
-// Disabled due to crbug.com/853085.
-IN_PROC_BROWSER_TEST_F(DoNotTrackTest, DISABLED_FetchFromServiceWorker) {
+IN_PROC_BROWSER_TEST_F(DoNotTrackTest, FetchFromServiceWorker) {
+#if defined(OS_ANDROID)
+  // TODO(crbug.com/864403): It seems that we call unsupported Android APIs on
+  // KitKat when we set a ContentBrowserClient. Don't call such APIs and make
+  // this test available on KitKat.
+  int32_t major_version = 0, minor_version = 0, bugfix_version = 0;
+  base::SysInfo::OperatingSystemVersionNumbers(&major_version, &minor_version,
+                                               &bugfix_version);
+  if (major_version < 5)
+    return;
+#endif
+  MockContentBrowserClient client;
+  ContentBrowserClient* original_client = SetBrowserClientForTesting(&client);
+
   ASSERT_TRUE(embedded_test_server()->Start());
   EnableDoNotTrack();
   const GURL fetch_url = embedded_test_server()->GetURL("/echoheader?DNT");
@@ -208,6 +235,7 @@
   EXPECT_EQ(title, watcher.WaitAndGetTitle());
 
   ExpectPageTextEq("1");
+  SetBrowserClientForTesting(original_client);
 }
 
 }  // namespace
diff --git a/content/browser/frame_host/navigation_request.cc b/content/browser/frame_host/navigation_request.cc
index 0db1cb0..7fab20e8 100644
--- a/content/browser/frame_host/navigation_request.cc
+++ b/content/browser/frame_host/navigation_request.cc
@@ -728,9 +728,7 @@
   // Reset the NavigationHandle, which is now incorrectly marked as
   // same-document. Ensure |loader_| does not exist as it can hold raw pointers
   // to objects owned by the handle (see the comment in the header).
-  // TODO(falken): Turn this CHECK to a DCHECK if it holds, or else call
-  // loader_.reset() manually.
-  CHECK(!loader_);
+  DCHECK(!loader_);
   navigation_handle_.reset();
 
   // Convert the navigation type to the appropriate cross-document one.
@@ -1297,9 +1295,7 @@
   // |loader_| should not exist if the service worker handle and app cache
   // handles will be destroyed, since it holds raw pointers to them. See the
   // comment in the header for |loader_|.
-  // TODO(falken): Turn this into a DCHECK if it holds, or else manually call
-  // loader_.reset() here.
-  CHECK(!loader_);
+  DCHECK(!loader_);
 
   // Only initialize the ServiceWorkerNavigationHandle if it can be created for
   // this frame.
diff --git a/content/browser/frame_host/navigation_request.h b/content/browser/frame_host/navigation_request.h
index d23786e..10440a4a 100644
--- a/content/browser/frame_host/navigation_request.h
+++ b/content/browser/frame_host/navigation_request.h
@@ -374,10 +374,11 @@
 
   NavigationState state_;
 
-  // It's important to ensure |navigation_handle_| outlives |loader_|, since
-  // the loader holds raw pointers to objects owned by the navigation handle
-  // (namely, the AppCache and service worker handles). So, declare the handle
-  // before the loader.
+  // It's important to ensure |navigation_handle_| outlives |loader_|, since the
+  // loader holds raw pointers to objects owned by the navigation handle
+  // (namely, the AppCache and service worker handles). The destruction order
+  // matters because it occurs over separate tasks on the IO thread. So, declare
+  // the handle before the loader.
   std::unique_ptr<NavigationHandleImpl> navigation_handle_;
   std::unique_ptr<NavigationURLLoader> loader_;
 
diff --git a/content/browser/renderer_host/media/audio_service_listener.cc b/content/browser/renderer_host/media/audio_service_listener.cc
index 08157dc..a9737789 100644
--- a/content/browser/renderer_host/media/audio_service_listener.cc
+++ b/content/browser/renderer_host/media/audio_service_listener.cc
@@ -6,12 +6,16 @@
 
 #include <utility>
 
+#include "base/feature_list.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/time/default_tick_clock.h"
+#include "content/browser/media/audio_log_factory.h"
 #include "content/public/browser/child_process_data.h"
 #include "content/public/browser/child_process_termination_info.h"
+#include "content/public/common/content_features.h"
 #include "mojo/public/cpp/bindings/strong_binding.h"
 #include "services/audio/public/mojom/constants.mojom.h"
+#include "services/audio/public/mojom/log_factory_manager.mojom.h"
 
 namespace content {
 
@@ -88,14 +92,15 @@
 AudioServiceListener::AudioServiceListener(
     std::unique_ptr<service_manager::Connector> connector)
     : binding_(this),
+      connector_(std::move(connector)),
       metrics_(base::DefaultTickClock::GetInstance()) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
-  if (!connector)
+  if (!connector_)
     return;  // Happens in unittests.
 
   service_manager::mojom::ServiceManagerPtr service_manager;
-  connector->BindInterface(service_manager::mojom::kServiceName,
-                           &service_manager);
+  connector_->BindInterface(service_manager::mojom::kServiceName,
+                            &service_manager);
   service_manager::mojom::ServiceManagerListenerPtr listener;
   service_manager::mojom::ServiceManagerListenerRequest request(
       mojo::MakeRequest(&listener));
@@ -123,6 +128,7 @@
     if (instance->identity.name() == audio::mojom::kServiceName) {
       process_id_ = instance->pid;
       metrics_.ServiceAlreadyRunning();
+      MaybeSetLogFactory();
       break;
     }
   }
@@ -134,6 +140,7 @@
   if (service->identity.name() != audio::mojom::kServiceName)
     return;
   metrics_.ServiceCreated();
+  MaybeSetLogFactory();
 }
 
 void AudioServiceListener::OnServiceStarted(
@@ -169,6 +176,7 @@
   if (identity.name() != audio::mojom::kServiceName)
     return;
   metrics_.ServiceStopped();
+  log_factory_is_set_ = false;
 }
 
 void AudioServiceListener::BrowserChildProcessHostDisconnected(
@@ -203,4 +211,20 @@
       Metrics::ServiceProcessTerminationStatus::kKill);
 }
 
+void AudioServiceListener::MaybeSetLogFactory() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+  if (!base::FeatureList::IsEnabled(features::kAudioServiceOutOfProcess) ||
+      !connector_ || log_factory_is_set_)
+    return;
+
+  media::mojom::AudioLogFactoryPtr audio_log_factory_ptr;
+  mojo::MakeStrongBinding(std::make_unique<AudioLogFactory>(),
+                          mojo::MakeRequest(&audio_log_factory_ptr));
+  audio::mojom::LogFactoryManagerPtr log_factory_manager_ptr;
+  connector_->BindInterface(audio::mojom::kServiceName,
+                            mojo::MakeRequest(&log_factory_manager_ptr));
+  log_factory_manager_ptr->SetLogFactory(std::move(audio_log_factory_ptr));
+  log_factory_is_set_ = true;
+}
+
 }  // namespace content
diff --git a/content/browser/renderer_host/media/audio_service_listener.h b/content/browser/renderer_host/media/audio_service_listener.h
index 6062398..41942d5b 100644
--- a/content/browser/renderer_host/media/audio_service_listener.h
+++ b/content/browser/renderer_host/media/audio_service_listener.h
@@ -116,9 +116,13 @@
   void BrowserChildProcessKilled(const ChildProcessData& data,
                                  const ChildProcessTerminationInfo& info) final;
 
+  void MaybeSetLogFactory();
+
   mojo::Binding<service_manager::mojom::ServiceManagerListener> binding_;
+  std::unique_ptr<service_manager::Connector> connector_;
   base::ProcessId process_id_ = base::kNullProcessId;
   Metrics metrics_;
+  bool log_factory_is_set_ = false;
   SEQUENCE_CHECKER(owning_sequence_);
 
   DISALLOW_COPY_AND_ASSIGN(AudioServiceListener);
diff --git a/content/browser/service_worker/embedded_worker_instance.cc b/content/browser/service_worker/embedded_worker_instance.cc
index aff967f..113f9e18 100644
--- a/content/browser/service_worker/embedded_worker_instance.cc
+++ b/content/browser/service_worker/embedded_worker_instance.cc
@@ -7,6 +7,7 @@
 #include <utility>
 
 #include "base/bind_helpers.h"
+#include "base/feature_list.h"
 #include "base/macros.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/trace_event/trace_event.h"
@@ -30,6 +31,7 @@
 #include "content/public/common/content_switches.h"
 #include "ipc/ipc_message.h"
 #include "mojo/public/cpp/bindings/strong_binding.h"
+#include "third_party/blink/public/common/features.h"
 #include "third_party/blink/public/common/service_worker/service_worker_utils.h"
 #include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom.h"
 #include "third_party/blink/public/web/web_console_message.h"
@@ -138,7 +140,9 @@
   // as most of those workers will have byte-to-byte equality and abort instead
   // of running.
   blink::mojom::CacheStoragePtr cache_storage;
-  if (!params->pause_after_download) {
+  if (base::FeatureList::IsEnabled(
+          blink::features::kEagerCacheStorageSetupForServiceWorkers) &&
+      !params->pause_after_download) {
     rph->BindCacheStorage(mojo::MakeRequest(&cache_storage),
                           url::Origin::Create(params->script_url));
   }
@@ -209,6 +213,11 @@
   devtools_proxy = std::make_unique<EmbeddedWorkerInstance::DevToolsProxy>(
       process_id, routing_id);
 
+  // TODO(crbug.com/862854): Support changes to RendererPreferences while the
+  // worker is running.
+  GetContentClient()->browser()->UpdateRendererPreferencesForWorker(
+      process_manager->browser_context(), &params->renderer_preferences);
+
   // Continue to OnSetupCompleted on the IO thread.
   BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE,
diff --git a/content/browser/service_worker/embedded_worker_instance_unittest.cc b/content/browser/service_worker/embedded_worker_instance_unittest.cc
index db23b95e..5af2051b 100644
--- a/content/browser/service_worker/embedded_worker_instance_unittest.cc
+++ b/content/browser/service_worker/embedded_worker_instance_unittest.cc
@@ -989,6 +989,64 @@
   }
 }
 
+// Test that the worker is not given a CacheStoragePtr during startup when
+// the feature is disabled.
+TEST_P(EmbeddedWorkerInstanceTest, CacheStorageOptimizationIsDisabled) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndDisableFeature(
+      blink::features::kEagerCacheStorageSetupForServiceWorkers);
+
+  const GURL scope("http://example.com/");
+  const GURL url("http://example.com/worker.js");
+  auto helper = std::make_unique<RecordCacheStorageHelper>();
+  auto* helper_rawptr = helper.get();
+  helper_ = std::move(helper);
+
+  RegistrationAndVersionPair pair = PrepareRegistrationAndVersion(scope, url);
+  const int64_t version_id = pair.second->version_id();
+  std::unique_ptr<EmbeddedWorkerInstance> worker =
+      embedded_worker_registry()->CreateWorker(pair.second.get());
+
+  // First, test a worker without pause after download.
+  {
+    // Start the worker.
+    mojom::EmbeddedWorkerStartParamsPtr params =
+        CreateStartParams(version_id, scope, url);
+    StartWorker(worker.get(), std::move(params));
+
+    // Cache storage should not have been sent.
+    EXPECT_FALSE(helper_rawptr->had_cache_storage());
+
+    // Stop the worker.
+    worker->Stop();
+    base::RunLoop().RunUntilIdle();
+  }
+
+  // Second, test a worker with pause after download.
+  {
+    // Start the worker until paused.
+    mojom::EmbeddedWorkerStartParamsPtr params =
+        CreateStartParams(version_id, scope, url);
+    params->pause_after_download = true;
+    worker->Start(std::move(params), CreateProviderInfoGetter(),
+                  base::DoNothing());
+    base::RunLoop().RunUntilIdle();
+    EXPECT_EQ(EmbeddedWorkerStatus::STARTING, worker->status());
+
+    // Finish starting.
+    worker->ResumeAfterDownload();
+    base::RunLoop().RunUntilIdle();
+    EXPECT_EQ(EmbeddedWorkerStatus::RUNNING, worker->status());
+
+    // Cache storage should not have been sent.
+    EXPECT_FALSE(helper_rawptr->had_cache_storage());
+
+    // Stop the worker.
+    worker->Stop();
+    base::RunLoop().RunUntilIdle();
+  }
+}
+
 // Starts the worker with kAbruptCompletion status.
 class AbruptCompletionHelper : public EmbeddedWorkerTestHelper {
  public:
diff --git a/content/browser/site_per_process_hit_test_browsertest.cc b/content/browser/site_per_process_hit_test_browsertest.cc
index aee47ae..f3e9acba 100644
--- a/content/browser/site_per_process_hit_test_browsertest.cc
+++ b/content/browser/site_per_process_hit_test_browsertest.cc
@@ -1860,10 +1860,18 @@
   EXPECT_FALSE(child_frame_monitor.EventWasReceived());
 }
 
+#if defined(OS_CHROMEOS)
+// Flaky on Chrome OS. crbug.com/833380
+#define MAYBE_AsynchronousHitTestChildTimeout \
+  DISABLED_AsynchronousHitTestChildTimeout
+#else
+#define MAYBE_AsynchronousHitTestChildTimeout AsynchronousHitTestChildTimeout
+#endif
+
 // Verify that an event is properly retargeted to the main frame when an
 // asynchronous hit test to the child frame times out.
 IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestBrowserTest,
-                       AsynchronousHitTestChildTimeout) {
+                       MAYBE_AsynchronousHitTestChildTimeout) {
   GURL main_url(embedded_test_server()->GetURL(
       "/frame_tree/page_with_positioned_busy_frame.html"));
   EXPECT_TRUE(NavigateToURL(shell(), main_url));
diff --git a/content/common/service_worker/embedded_worker.mojom b/content/common/service_worker/embedded_worker.mojom
index 152f137..04f9c97c 100644
--- a/content/common/service_worker/embedded_worker.mojom
+++ b/content/common/service_worker/embedded_worker.mojom
@@ -48,6 +48,8 @@
   bool is_installed;
   // Determines how eagerly V8 creates the code cache.
   V8CacheOptions v8_cache_options;
+  // Used to set up fetch requests.
+  RendererPreferences renderer_preferences;
 
   // Used to dispatch events from (via) the browser process.
   ServiceWorkerEventDispatcher& dispatcher_request;
diff --git a/content/public/app/mojo/content_browser_manifest.json b/content/public/app/mojo/content_browser_manifest.json
index c14c0d3..c75cda9 100644
--- a/content/public/app/mojo/content_browser_manifest.json
+++ b/content/public/app/mojo/content_browser_manifest.json
@@ -81,6 +81,7 @@
           "info",
           "debug_recording",
           "device_notifier",
+          "log_factory_manager",
           "stream_factory",
           "testing_api"
         ],
diff --git a/content/public/browser/content_browser_client.cc b/content/public/browser/content_browser_client.cc
index bef2c6a..7f2f608 100644
--- a/content/public/browser/content_browser_client.cc
+++ b/content/public/browser/content_browser_client.cc
@@ -270,6 +270,10 @@
   return false;
 }
 
+void ContentBrowserClient::UpdateRendererPreferencesForWorker(
+    BrowserContext* browser_context,
+    RendererPreferences* out_prefs) {}
+
 bool ContentBrowserClient::AllowGetCookie(const GURL& url,
                                           const GURL& first_party,
                                           const net::CookieList& cookie_list,
diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h
index 88e9ab2..fd5d62fe 100644
--- a/content/public/browser/content_browser_client.h
+++ b/content/public/browser/content_browser_client.h
@@ -175,6 +175,7 @@
 struct MainFunctionParams;
 struct OpenURLParams;
 struct Referrer;
+struct RendererPreferences;
 struct WebPreferences;
 
 CONTENT_EXPORT void OverrideOnBindInterface(
@@ -477,6 +478,14 @@
 
   virtual bool IsDataSaverEnabled(BrowserContext* context);
 
+  // Updates the given prefs for Service Worker and Shared Worker. The prefs
+  // are to be sent to the renderer process when a worker is created. Note that
+  // We don't use this method for Dedicated Workers as they inherit preferences
+  // from their closest ancestor frame.
+  virtual void UpdateRendererPreferencesForWorker(
+      BrowserContext* browser_context,
+      RendererPreferences* out_prefs);
+
   // Allow the embedder to return additional headers that should be sent when
   // fetching |url| as well as add extra load flags.
   virtual void NavigationRequestStarted(
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc
index 09d9193e..95b0a79 100644
--- a/content/public/common/content_features.cc
+++ b/content/public/common/content_features.cc
@@ -78,7 +78,7 @@
 
 // Enables code caching for inline scripts.
 const base::Feature kCacheInlineScriptCode{"CacheInlineScriptCode",
-                                           base::FEATURE_DISABLED_BY_DEFAULT};
+                                           base::FEATURE_ENABLED_BY_DEFAULT};
 
 // If Canvas2D Image Chromium is allowed, this feature controls whether it is
 // enabled.
diff --git a/content/public/test/browser_test_base.cc b/content/public/test/browser_test_base.cc
index 1357447d..eb8f5ad5 100644
--- a/content/public/test/browser_test_base.cc
+++ b/content/public/test/browser_test_base.cc
@@ -64,7 +64,7 @@
 namespace content {
 namespace {
 
-#if defined(OS_POSIX) && !defined(OS_FUCHSIA)
+#if defined(OS_POSIX)
 // On SIGSEGV or SIGTERM (sent by the runner on timeouts), dump a stack trace
 // (to make debugging easier) and also exit with a known error code (so that
 // the test framework considers this a failure -- http://crbug.com/57578).
@@ -85,7 +85,7 @@
   }
   _exit(128 + signal);
 }
-#endif  // defined(OS_POSIX) && !defined(OS_FUCHSIA)
+#endif  // defined(OS_POSIX)
 
 void RunTaskOnRendererThread(const base::Closure& task,
                              const base::Closure& quit_task) {
@@ -354,13 +354,13 @@
 }
 
 void BrowserTestBase::ProxyRunTestOnMainThreadLoop() {
-#if defined(OS_POSIX) && !defined(OS_FUCHSIA)
+#if defined(OS_POSIX)
   g_browser_process_pid = base::GetCurrentProcId();
   signal(SIGSEGV, DumpStackTraceSignalHandler);
 
   if (handle_sigterm_)
     signal(SIGTERM, DumpStackTraceSignalHandler);
-#endif  // defined(OS_POSIX) && !defined(OS_FUCHSIA)
+#endif  // defined(OS_POSIX)
 
   if (base::CommandLine::ForCurrentProcess()->HasSwitch(
           switches::kEnableTracing)) {
diff --git a/content/public/utility/utility_thread.h b/content/public/utility/utility_thread.h
index f17e3670..5acc89a 100644
--- a/content/public/utility/utility_thread.h
+++ b/content/public/utility/utility_thread.h
@@ -29,7 +29,7 @@
   // Initializes blink if it hasn't already been initialized.
   virtual void EnsureBlinkInitialized() = 0;
 
-#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_FUCHSIA)
+#if defined(OS_POSIX) && !defined(OS_ANDROID)
   // Initializes blink with web sandbox support.
   virtual void EnsureBlinkInitializedWithSandboxSupport() = 0;
 #endif
diff --git a/content/renderer/loader/web_worker_fetch_context_impl.h b/content/renderer/loader/web_worker_fetch_context_impl.h
index 95239ba..519e3bc 100644
--- a/content/renderer/loader/web_worker_fetch_context_impl.h
+++ b/content/renderer/loader/web_worker_fetch_context_impl.h
@@ -200,7 +200,8 @@
   GURL origin_url_;
   int appcache_host_id_ = blink::WebApplicationCacheHost::kAppCacheNoHostId;
 
-  // TODO(shimazu): Propagate preference changes from the browser process.
+  // TODO(crbug.com/862854): Propagate preference changes from the browser
+  // process.
   RendererPreferences renderer_preferences_;
 
   // This is owned by ThreadedMessagingProxyBase on the main thread.
diff --git a/content/renderer/renderer_blink_platform_impl.cc b/content/renderer/renderer_blink_platform_impl.cc
index 12ce92d..4030cd3b 100644
--- a/content/renderer/renderer_blink_platform_impl.cc
+++ b/content/renderer/renderer_blink_platform_impl.cc
@@ -187,6 +187,8 @@
       return gpu::CONTEXT_TYPE_WEBGL1;
     case blink::Platform::kWebGL2ContextType:
       return gpu::CONTEXT_TYPE_WEBGL2;
+    case blink::Platform::kWebGL2ComputeContextType:
+      return gpu::CONTEXT_TYPE_WEBGL2_COMPUTE;
     case blink::Platform::kGLES2ContextType:
       return gpu::CONTEXT_TYPE_OPENGLES2;
     case blink::Platform::kGLES3ContextType:
@@ -586,7 +588,7 @@
   return content::LoadFont(src_font, out, font_id);
 }
 
-#elif defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_FUCHSIA)
+#elif defined(OS_POSIX) && !defined(OS_ANDROID)
 
 void RendererBlinkPlatformImpl::SandboxSupport::GetFallbackFontForCharacter(
     blink::WebUChar32 character,
diff --git a/content/renderer/service_worker/embedded_worker_instance_client_impl.cc b/content/renderer/service_worker/embedded_worker_instance_client_impl.cc
index 062accd..7bcd23f4 100644
--- a/content/renderer/service_worker/embedded_worker_instance_client_impl.cc
+++ b/content/renderer/service_worker/embedded_worker_instance_client_impl.cc
@@ -14,6 +14,7 @@
 #include "content/renderer/render_thread_impl.h"
 #include "content/renderer/service_worker/service_worker_context_client.h"
 #include "content/renderer/service_worker/web_service_worker_installed_scripts_manager_impl.h"
+#include "third_party/blink/public/common/features.h"
 #include "third_party/blink/public/platform/modules/service_worker/web_service_worker_installed_scripts_manager.h"
 #include "third_party/blink/public/platform/web_content_settings_client.h"
 #include "third_party/blink/public/platform/web_security_origin.h"
@@ -55,6 +56,9 @@
                "EmbeddedWorkerInstanceClientImpl::StartWorker");
   auto start_timing = mojom::EmbeddedWorkerStartTiming::New();
   start_timing->start_worker_received_time = base::TimeTicks::Now();
+  DCHECK(!params->provider_info->cache_storage ||
+         base::FeatureList::IsEnabled(
+             blink::features::kEagerCacheStorageSetupForServiceWorkers));
   blink::mojom::CacheStoragePtrInfo cache_storage =
       std::move(params->provider_info->cache_storage);
   service_manager::mojom::InterfaceProviderPtrInfo interface_provider =
@@ -64,6 +68,7 @@
       params->embedded_worker_id, params->service_worker_version_id,
       params->scope, params->script_url,
       !params->installed_scripts_info.is_null(),
+      std::move(params->renderer_preferences),
       std::move(params->dispatcher_request),
       std::move(params->controller_request), std::move(params->instance_host),
       std::move(params->provider_info), std::move(temporal_self_),
diff --git a/content/renderer/service_worker/service_worker_context_client.cc b/content/renderer/service_worker/service_worker_context_client.cc
index 0eab347..cc85122a 100644
--- a/content/renderer/service_worker/service_worker_context_client.cc
+++ b/content/renderer/service_worker/service_worker_context_client.cc
@@ -697,6 +697,7 @@
     const GURL& service_worker_scope,
     const GURL& script_url,
     bool is_starting_installed_worker,
+    RendererPreferences renderer_preferences,
     mojom::ServiceWorkerEventDispatcherRequest dispatcher_request,
     mojom::ControllerServiceWorkerRequest controller_request,
     mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host,
@@ -709,6 +710,7 @@
       service_worker_scope_(service_worker_scope),
       script_url_(script_url),
       is_starting_installed_worker_(is_starting_installed_worker),
+      renderer_preferences_(std::move(renderer_preferences)),
       main_thread_task_runner_(std::move(main_thread_task_runner)),
       proxy_(nullptr),
       pending_dispatcher_request_(std::move(dispatcher_request)),
@@ -1339,7 +1341,7 @@
   }
 
   return std::make_unique<ServiceWorkerFetchContextImpl>(
-      script_url_, url_loader_factory_bundle->Clone(),
+      renderer_preferences_, script_url_, url_loader_factory_bundle->Clone(),
       std::move(script_loader_factory_info), provider_context_->provider_id(),
       GetContentClient()->renderer()->CreateURLLoaderThrottleProvider(
           URLLoaderThrottleProviderType::kWorker),
diff --git a/content/renderer/service_worker/service_worker_context_client.h b/content/renderer/service_worker/service_worker_context_client.h
index 5bed31c..4cf7dd0 100644
--- a/content/renderer/service_worker/service_worker_context_client.h
+++ b/content/renderer/service_worker/service_worker_context_client.h
@@ -92,6 +92,7 @@
       const GURL& service_worker_scope,
       const GURL& script_url,
       bool is_starting_installed_worker,
+      RendererPreferences renderer_preferences,
       mojom::ServiceWorkerEventDispatcherRequest dispatcher_request,
       mojom::ControllerServiceWorkerRequest controller_request,
       mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host,
@@ -410,6 +411,8 @@
   // startup time.
   const bool is_starting_installed_worker_;
 
+  RendererPreferences renderer_preferences_;
+
   scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_;
   scoped_refptr<base::TaskRunner> worker_task_runner_;
 
diff --git a/content/renderer/service_worker/service_worker_context_client_unittest.cc b/content/renderer/service_worker/service_worker_context_client_unittest.cc
index eeb086b..19f9049 100644
--- a/content/renderer/service_worker/service_worker_context_client_unittest.cc
+++ b/content/renderer/service_worker/service_worker_context_client_unittest.cc
@@ -277,7 +277,8 @@
         std::make_unique<ServiceWorkerContextClient>(
             1 /* embedded_worker_id */, 1 /* service_worker_version_id */,
             kScope, kScript, false /* is_script_streaming */,
-            std::move(event_dispatcher_request), std::move(controller_request),
+            RendererPreferences(), std::move(event_dispatcher_request),
+            std::move(controller_request),
             embedded_worker_host_ptr.PassInterface(), CreateProviderInfo(),
             nullptr /* embedded_worker_client */,
             mojom::EmbeddedWorkerStartTiming::New(),
diff --git a/content/renderer/service_worker/service_worker_fetch_context_impl.cc b/content/renderer/service_worker/service_worker_fetch_context_impl.cc
index 3d75091d..5cdaab33 100644
--- a/content/renderer/service_worker/service_worker_fetch_context_impl.cc
+++ b/content/renderer/service_worker/service_worker_fetch_context_impl.cc
@@ -5,6 +5,7 @@
 #include "content/renderer/service_worker/service_worker_fetch_context_impl.h"
 
 #include "base/feature_list.h"
+#include "content/common/content_constants_internal.h"
 #include "content/public/common/content_features.h"
 #include "content/public/renderer/url_loader_throttle_provider.h"
 #include "content/public/renderer/websocket_handshake_throttle_provider.h"
@@ -18,6 +19,7 @@
 namespace content {
 
 ServiceWorkerFetchContextImpl::ServiceWorkerFetchContextImpl(
+    RendererPreferences renderer_preferences,
     const GURL& worker_script_url,
     std::unique_ptr<network::SharedURLLoaderFactoryInfo>
         url_loader_factory_info,
@@ -27,7 +29,8 @@
     std::unique_ptr<URLLoaderThrottleProvider> throttle_provider,
     std::unique_ptr<WebSocketHandshakeThrottleProvider>
         websocket_handshake_throttle_provider)
-    : worker_script_url_(worker_script_url),
+    : renderer_preferences_(std::move(renderer_preferences)),
+      worker_script_url_(worker_script_url),
       url_loader_factory_info_(std::move(url_loader_factory_info)),
       script_loader_factory_info_(std::move(script_loader_factory_info)),
       service_worker_provider_id_(service_worker_provider_id),
@@ -84,6 +87,10 @@
 
 void ServiceWorkerFetchContextImpl::WillSendRequest(
     blink::WebURLRequest& request) {
+  if (renderer_preferences_.enable_do_not_track) {
+    request.SetHTTPHeaderField(blink::WebString::FromUTF8(kDoNotTrackHeader),
+                               "1");
+  }
   auto extra_data = std::make_unique<RequestExtraData>();
   extra_data->set_service_worker_provider_id(service_worker_provider_id_);
   extra_data->set_originated_from_service_worker(true);
@@ -93,6 +100,11 @@
         MSG_ROUTING_NONE, request, WebURLRequestToResourceType(request)));
   }
   request.SetExtraData(std::move(extra_data));
+
+  if (!renderer_preferences_.enable_referrers) {
+    request.SetHTTPReferrer(blink::WebString(),
+                            blink::kWebReferrerPolicyDefault);
+  }
 }
 
 blink::mojom::ControllerServiceWorkerMode
diff --git a/content/renderer/service_worker/service_worker_fetch_context_impl.h b/content/renderer/service_worker/service_worker_fetch_context_impl.h
index d5129ea..082614a 100644
--- a/content/renderer/service_worker/service_worker_fetch_context_impl.h
+++ b/content/renderer/service_worker/service_worker_fetch_context_impl.h
@@ -5,6 +5,7 @@
 #ifndef CONTENT_RENDERER_SERVICE_WORKER_SERVICE_WORKER_FETCH_CONTEXT_IMPL_H_
 #define CONTENT_RENDERER_SERVICE_WORKER_SERVICE_WORKER_FETCH_CONTEXT_IMPL_H_
 
+#include "content/public/common/renderer_preferences.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 #include "third_party/blink/public/platform/web_worker_fetch_context.h"
 #include "url/gurl.h"
@@ -24,6 +25,7 @@
   // worker when InstalledScriptsManager doesn't have the requested script. It
   // is a ServiceWorkerScriptLoaderFactory, which loads and installs the script.
   ServiceWorkerFetchContextImpl(
+      RendererPreferences renderer_preferences,
       const GURL& worker_script_url,
       std::unique_ptr<network::SharedURLLoaderFactoryInfo>
           url_loader_factory_info,
@@ -51,6 +53,7 @@
   CreateWebSocketHandshakeThrottle() override;
 
  private:
+  RendererPreferences renderer_preferences_;
   const GURL worker_script_url_;
   // Consumed on the worker thread to create |url_loader_factory_|.
   std::unique_ptr<network::SharedURLLoaderFactoryInfo> url_loader_factory_info_;
diff --git a/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.cc b/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.cc
index a781d9a..099b1a0e 100644
--- a/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.cc
+++ b/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.cc
@@ -4,7 +4,9 @@
 
 #include "content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.h"
 
+#include <set>
 #include <utility>
+#include <vector>
 
 #include "base/bind.h"
 #include "base/bind_helpers.h"
@@ -595,7 +597,7 @@
               base::BindOnce(&NotifyServicesDiscovered,
                              base::RetainedRef(adapter_ptr), device_ptr));
 
-          DCHECK(services.size() == 0);
+          DCHECK(services.empty());
           return false;
         }
 
@@ -903,7 +905,7 @@
                 base::BindOnce(&NotifyDeviceChanged,
                                base::RetainedRef(adapter_ptr), device_ptr));
           }
-          DCHECK(services.size() == 0);
+          DCHECK(services.empty());
           return false;
         }
 
@@ -1126,7 +1128,6 @@
             ON_CALL(*notify_session, Stop(_))
                 .WillByDefault(Invoke([adapter_ptr, device_ptr, disconnect](
                     const base::Closure& callback) {
-
                   device_ptr->PushPendingCallback(callback);
 
                   if (disconnect) {
@@ -1595,16 +1596,6 @@
       .WillByDefault(
           RunCallback<1>(BluetoothRemoteGattService::GATT_ERROR_NOT_SUPPORTED));
 
-  ON_CALL(*characteristic, GetDescriptors())
-      .WillByDefault(
-          Invoke(characteristic.get(),
-                 &MockBluetoothGattCharacteristic::GetMockDescriptors));
-
-  ON_CALL(*characteristic, GetDescriptor(_))
-      .WillByDefault(
-          Invoke(characteristic.get(),
-                 &MockBluetoothGattCharacteristic::GetMockDescriptor));
-
   return characteristic;
 }
 
diff --git a/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.h b/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.h
index 46176d8..328c428 100644
--- a/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.h
+++ b/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.h
@@ -7,6 +7,9 @@
 
 #include <stdint.h>
 
+#include <memory>
+#include <string>
+
 #include "base/callback.h"
 #include "device/bluetooth/test/mock_bluetooth_adapter.h"
 #include "device/bluetooth/test/mock_bluetooth_device.h"
diff --git a/content/utility/utility_blink_platform_with_sandbox_support_impl.cc b/content/utility/utility_blink_platform_with_sandbox_support_impl.cc
index 13ab692..51eab09 100644
--- a/content/utility/utility_blink_platform_with_sandbox_support_impl.cc
+++ b/content/utility/utility_blink_platform_with_sandbox_support_impl.cc
@@ -10,7 +10,7 @@
 #include "base/mac/foundation_util.h"
 #include "content/child/child_process_sandbox_support_impl_mac.h"
 #include "third_party/blink/public/platform/mac/web_sandbox_support.h"
-#elif defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_FUCHSIA)
+#elif defined(OS_POSIX) && !defined(OS_ANDROID)
 #include "base/synchronization/lock.h"
 #include "content/child/child_process_sandbox_support_impl_linux.h"
 #include "content/child/child_thread_impl.h"
@@ -27,7 +27,7 @@
 
 namespace content {
 
-#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_FUCHSIA)
+#if defined(OS_POSIX) && !defined(OS_ANDROID)
 
 class UtilityBlinkPlatformWithSandboxSupportImpl::SandboxSupport
     : public blink::WebSandboxSupport {
@@ -63,7 +63,7 @@
 #endif  // defined(OS_MACOSX)
 };
 
-#endif  // defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_FUCHSIA)
+#endif  // defined(OS_POSIX) && !defined(OS_ANDROID)
 
 UtilityBlinkPlatformWithSandboxSupportImpl::
     UtilityBlinkPlatformWithSandboxSupportImpl(
@@ -82,7 +82,7 @@
 
 blink::WebSandboxSupport*
 UtilityBlinkPlatformWithSandboxSupportImpl::GetSandboxSupport() {
-#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_FUCHSIA)
+#if defined(OS_POSIX) && !defined(OS_ANDROID)
   return sandbox_support_.get();
 #else
   return nullptr;
@@ -98,7 +98,7 @@
   return content::LoadFont(src_font, out, font_id);
 }
 
-#elif defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_FUCHSIA)
+#elif defined(OS_POSIX) && !defined(OS_ANDROID)
 
 void UtilityBlinkPlatformWithSandboxSupportImpl::SandboxSupport::
     GetFallbackFontForCharacter(blink::WebUChar32 character,
diff --git a/content/utility/utility_blink_platform_with_sandbox_support_impl.h b/content/utility/utility_blink_platform_with_sandbox_support_impl.h
index bdb6e9e..3461acdd 100644
--- a/content/utility/utility_blink_platform_with_sandbox_support_impl.h
+++ b/content/utility/utility_blink_platform_with_sandbox_support_impl.h
@@ -11,7 +11,7 @@
 #include "build/build_config.h"
 #include "content/utility/utility_blink_platform_impl.h"
 
-#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_FUCHSIA)
+#if defined(OS_POSIX) && !defined(OS_ANDROID)
 #include "components/services/font/public/cpp/font_loader.h"  // nogncheck
 #include "third_party/skia/include/core/SkRefCnt.h"           // nogncheck
 #endif
@@ -40,7 +40,7 @@
   blink::WebSandboxSupport* GetSandboxSupport() override;
 
  private:
-#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_FUCHSIA)
+#if defined(OS_POSIX) && !defined(OS_ANDROID)
   class SandboxSupport;
   std::unique_ptr<SandboxSupport> sandbox_support_;
 #endif
diff --git a/content/utility/utility_thread_impl.cc b/content/utility/utility_thread_impl.cc
index 65b164f..607cea7 100644
--- a/content/utility/utility_thread_impl.cc
+++ b/content/utility/utility_thread_impl.cc
@@ -99,7 +99,7 @@
   EnsureBlinkInitializedInternal(/*sandbox_support=*/false);
 }
 
-#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_FUCHSIA)
+#if defined(OS_POSIX) && !defined(OS_ANDROID)
 void UtilityThreadImpl::EnsureBlinkInitializedWithSandboxSupport() {
   EnsureBlinkInitializedInternal(/*sandbox_support=*/true);
 }
diff --git a/content/utility/utility_thread_impl.h b/content/utility/utility_thread_impl.h
index 618459cc..a1b8d47b 100644
--- a/content/utility/utility_thread_impl.h
+++ b/content/utility/utility_thread_impl.h
@@ -42,7 +42,7 @@
   // UtilityThread:
   void ReleaseProcess() override;
   void EnsureBlinkInitialized() override;
-#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_FUCHSIA)
+#if defined(OS_POSIX) && !defined(OS_ANDROID)
   void EnsureBlinkInitializedWithSandboxSupport() override;
 #endif
 #if defined(OS_MACOSX)
diff --git a/device/bluetooth/BUILD.gn b/device/bluetooth/BUILD.gn
index 1585804..4fd41efe 100644
--- a/device/bluetooth/BUILD.gn
+++ b/device/bluetooth/BUILD.gn
@@ -156,6 +156,8 @@
     "bluetooth_low_energy_discovery_manager_mac.mm",
     "bluetooth_low_energy_peripheral_delegate.h",
     "bluetooth_low_energy_peripheral_delegate.mm",
+    "bluetooth_low_energy_peripheral_manager_delegate.h",
+    "bluetooth_low_energy_peripheral_manager_delegate.mm",
     "bluetooth_low_energy_win.cc",
     "bluetooth_low_energy_win.h",
     "bluetooth_remote_gatt_characteristic.cc",
diff --git a/device/bluetooth/bluetooth_adapter_mac.h b/device/bluetooth/bluetooth_adapter_mac.h
index a31b33b1..2dd3692d 100644
--- a/device/bluetooth/bluetooth_adapter_mac.h
+++ b/device/bluetooth/bluetooth_adapter_mac.h
@@ -31,6 +31,7 @@
 @class NSDate;
 
 @class BluetoothLowEnergyCentralManagerDelegate;
+@class BluetoothLowEnergyPeripheralManagerDelegate;
 
 namespace device {
 
@@ -151,6 +152,9 @@
   // Returns the CBCentralManager instance.
   CBCentralManager* GetCentralManager();
 
+  // Returns the CBPeripheralManager instance.
+  CBPeripheralManager* GetPeripheralManager();
+
   // Allow the mocking out of getting the HostController state for testing.
   void SetHostControllerStateFunctionForTesting(
       HostControllerStateFunction controller_state_function);
@@ -167,6 +171,7 @@
   friend class BluetoothTestMac;
   friend class BluetoothAdapterMacTest;
   friend class BluetoothLowEnergyCentralManagerBridge;
+  friend class BluetoothLowEnergyPeripheralManagerBridge;
 
   BluetoothAdapterMac();
   ~BluetoothAdapterMac() override;
@@ -264,6 +269,11 @@
   base::scoped_nsobject<BluetoothLowEnergyCentralManagerDelegate>
       low_energy_central_manager_delegate_;
 
+  // Underlying CoreBluetooth CBPeripheralManager and its delegate.
+  base::scoped_nsobject<CBPeripheralManager> low_energy_peripheral_manager_;
+  base::scoped_nsobject<BluetoothLowEnergyPeripheralManagerDelegate>
+      low_energy_peripheral_manager_delegate_;
+
   base::WeakPtrFactory<BluetoothAdapterMac> weak_ptr_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(BluetoothAdapterMac);
diff --git a/device/bluetooth/bluetooth_adapter_mac.mm b/device/bluetooth/bluetooth_adapter_mac.mm
index 30a0f680..c9377b7d 100644
--- a/device/bluetooth/bluetooth_adapter_mac.mm
+++ b/device/bluetooth/bluetooth_adapter_mac.mm
@@ -30,6 +30,7 @@
 #include "device/bluetooth/bluetooth_discovery_session.h"
 #include "device/bluetooth/bluetooth_discovery_session_outcome.h"
 #include "device/bluetooth/bluetooth_low_energy_central_manager_delegate.h"
+#include "device/bluetooth/bluetooth_low_energy_peripheral_manager_delegate.h"
 #include "device/bluetooth/bluetooth_socket_mac.h"
 
 extern "C" {
@@ -136,6 +137,12 @@
                    queue:dispatch_get_main_queue()]);
     low_energy_discovery_manager_->SetCentralManager(
         low_energy_central_manager_);
+    low_energy_peripheral_manager_delegate_.reset(
+        [[BluetoothLowEnergyPeripheralManagerDelegate alloc]
+            initWithAdapter:this]);
+    low_energy_peripheral_manager_.reset([[CBPeripheralManager alloc]
+        initWithDelegate:low_energy_peripheral_manager_delegate_
+                   queue:dispatch_get_main_queue()]);
   }
   DCHECK(classic_discovery_manager_);
 }
@@ -337,6 +344,10 @@
   return low_energy_central_manager_;
 }
 
+CBPeripheralManager* BluetoothAdapterMac::GetPeripheralManager() {
+  return low_energy_peripheral_manager_;
+}
+
 void BluetoothAdapterMac::SetHostControllerStateFunctionForTesting(
     HostControllerStateFunction controller_state_function) {
   controller_state_function_ = std::move(controller_state_function);
diff --git a/device/bluetooth/bluetooth_low_energy_peripheral_manager_delegate.h b/device/bluetooth/bluetooth_low_energy_peripheral_manager_delegate.h
new file mode 100644
index 0000000..7e0b612
--- /dev/null
+++ b/device/bluetooth/bluetooth_low_energy_peripheral_manager_delegate.h
@@ -0,0 +1,32 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef DEVICE_BLUETOOTH_BLUETOOTH_LOW_ENERGY_PERIPHERAL_MANAGER_DELEGATE_H_
+#define DEVICE_BLUETOOTH_BLUETOOTH_LOW_ENERGY_PERIPHERAL_MANAGER_DELEGATE_H_
+
+#include "base/mac/sdk_forward_declarations.h"
+#include "base/memory/ref_counted.h"
+#include "build/build_config.h"
+
+#if defined(OS_IOS)
+#import <CoreBluetooth/CoreBluetooth.h>
+#else
+#import <IOBluetooth/IOBluetooth.h>
+#endif
+
+namespace device {
+class BluetoothAdapterMac;
+class BluetoothLowEnergyPeripheralManagerBridge;
+}  // namespace device
+
+@interface BluetoothLowEnergyPeripheralManagerDelegate
+    : NSObject<CBPeripheralManagerDelegate> {
+  std::unique_ptr<device::BluetoothLowEnergyPeripheralManagerBridge> bridge_;
+}
+
+- (id)initWithAdapter:(device::BluetoothAdapterMac*)adapter;
+
+@end
+
+#endif  // DEVICE_BLUETOOTH_BLUETOOTH_LOW_ENERGY_PERIPHERAL_MANAGER_DELEGATE_H_
diff --git a/device/bluetooth/bluetooth_low_energy_peripheral_manager_delegate.mm b/device/bluetooth/bluetooth_low_energy_peripheral_manager_delegate.mm
new file mode 100644
index 0000000..a2866d9
--- /dev/null
+++ b/device/bluetooth/bluetooth_low_energy_peripheral_manager_delegate.mm
@@ -0,0 +1,62 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "device/bluetooth/bluetooth_low_energy_peripheral_manager_delegate.h"
+
+#include "device/bluetooth/bluetooth_adapter_mac.h"
+
+namespace device {
+
+// This class exists to bridge between the Objective-C
+// CBPeripheralManagerDelegate class and our BluetoothAdapterMac classes.
+class BluetoothLowEnergyPeripheralManagerBridge {
+ public:
+  BluetoothLowEnergyPeripheralManagerBridge(BluetoothAdapterMac* adapter)
+      : adapter_(adapter) {}
+
+  ~BluetoothLowEnergyPeripheralManagerBridge() {}
+
+  void UpdatedState() {
+    // TODO(tengs): Hook this up to BluetoothAdapterMac.
+  }
+
+  void DidStartAdvertising(NSError* error) {
+    // TODO(tengs): Hook this up to BluetoothAdapterMac.
+  }
+
+  CBPeripheralManager* GetPeripheralManager() {
+    return adapter_->GetPeripheralManager();
+  }
+
+ private:
+  BluetoothAdapterMac* adapter_;
+};
+
+}  // namespace device
+
+@implementation BluetoothLowEnergyPeripheralManagerDelegate
+
+- (id)initWithAdapter:(device::BluetoothAdapterMac*)adapter {
+  if ((self = [super init])) {
+    bridge_.reset(
+        new device::BluetoothLowEnergyPeripheralManagerBridge(adapter));
+  }
+  return self;
+}
+
+- (void)dealloc {
+  [bridge_->GetPeripheralManager() setDelegate:nil];
+  [super dealloc];
+}
+
+- (void)peripheralManagerDidUpdateState:(CBPeripheralManager*)peripheral {
+  bridge_->UpdatedState();
+}
+
+- (void)peripheralManagerDidStartAdvertising:(CBPeripheralManager*)peripheral
+                                       error:(NSError*)error {
+  bridge_->DidStartAdvertising(error);
+}
+
+@end
diff --git a/device/bluetooth/bluetooth_remote_gatt_characteristic.cc b/device/bluetooth/bluetooth_remote_gatt_characteristic.cc
index ae0d141..e84ab7f 100644
--- a/device/bluetooth/bluetooth_remote_gatt_characteristic.cc
+++ b/device/bluetooth/bluetooth_remote_gatt_characteristic.cc
@@ -4,6 +4,8 @@
 
 #include "device/bluetooth/bluetooth_remote_gatt_characteristic.h"
 
+#include <utility>
+
 #include "base/bind.h"
 #include "base/location.h"
 #include "base/single_thread_task_runner.h"
@@ -23,14 +25,29 @@
 }
 
 std::vector<BluetoothRemoteGattDescriptor*>
+BluetoothRemoteGattCharacteristic::GetDescriptors() const {
+  std::vector<BluetoothRemoteGattDescriptor*> descriptors;
+  descriptors.reserve(descriptors_.size());
+  for (const auto& pair : descriptors_)
+    descriptors.push_back(pair.second.get());
+  return descriptors;
+}
+
+BluetoothRemoteGattDescriptor* BluetoothRemoteGattCharacteristic::GetDescriptor(
+    const std::string& identifier) const {
+  auto iter = descriptors_.find(identifier);
+  return iter != descriptors_.end() ? iter->second.get() : nullptr;
+}
+
+std::vector<BluetoothRemoteGattDescriptor*>
 BluetoothRemoteGattCharacteristic::GetDescriptorsByUUID(
     const BluetoothUUID& uuid) const {
   std::vector<BluetoothRemoteGattDescriptor*> descriptors;
-  for (BluetoothRemoteGattDescriptor* descriptor : GetDescriptors()) {
-    if (descriptor->GetUUID() == uuid) {
-      descriptors.push_back(descriptor);
-    }
+  for (const auto& pair : descriptors_) {
+    if (pair.second->GetUUID() == uuid)
+      descriptors.push_back(pair.second.get());
   }
+
   return descriptors;
 }
 
@@ -89,6 +106,17 @@
   return false;
 }
 
+bool BluetoothRemoteGattCharacteristic::AddDescriptor(
+    std::unique_ptr<BluetoothRemoteGattDescriptor> descriptor) {
+  if (!descriptor)
+    return false;
+
+  auto* descriptor_raw = descriptor.get();
+  return descriptors_
+      .try_emplace(descriptor_raw->GetIdentifier(), std::move(descriptor))
+      .second;
+}
+
 void BluetoothRemoteGattCharacteristic::StartNotifySessionInternal(
     const base::Optional<NotificationType>& notification_type,
     const NotifySessionCallback& callback,
diff --git a/device/bluetooth/bluetooth_remote_gatt_characteristic.h b/device/bluetooth/bluetooth_remote_gatt_characteristic.h
index 1a30eec..c475063f 100644
--- a/device/bluetooth/bluetooth_remote_gatt_characteristic.h
+++ b/device/bluetooth/bluetooth_remote_gatt_characteristic.h
@@ -14,6 +14,7 @@
 
 #include "base/callback.h"
 #include "base/callback_forward.h"
+#include "base/containers/flat_map.h"
 #include "base/containers/queue.h"
 #include "base/containers/span.h"
 #include "base/macros.h"
@@ -62,18 +63,17 @@
 
   // Returns the list of GATT characteristic descriptors that provide more
   // information about this characteristic.
-  virtual std::vector<BluetoothRemoteGattDescriptor*> GetDescriptors()
-      const = 0;
+  virtual std::vector<BluetoothRemoteGattDescriptor*> GetDescriptors() const;
 
   // Returns the GATT characteristic descriptor with identifier |identifier| if
   // it belongs to this GATT characteristic.
   virtual BluetoothRemoteGattDescriptor* GetDescriptor(
-      const std::string& identifier) const = 0;
+      const std::string& identifier) const;
 
   // Returns the GATT characteristic descriptors that match |uuid|. There may be
   // multiple, as illustrated by Core Bluetooth Specification [V4.2 Vol 3 Part G
   // 3.3.3.5 Characteristic Presentation Format].
-  std::vector<BluetoothRemoteGattDescriptor*> GetDescriptorsByUUID(
+  virtual std::vector<BluetoothRemoteGattDescriptor*> GetDescriptorsByUUID(
       const BluetoothUUID& uuid) const;
 
   // Get a weak pointer to the characteristic.
@@ -201,6 +201,14 @@
       const base::Closure& callback,
       const ErrorCallback& error_callback) = 0;
 
+  // Utility function to add a |descriptor| to the map of |descriptors_|.
+  bool AddDescriptor(std::unique_ptr<BluetoothRemoteGattDescriptor> descriptor);
+
+  // Descriptors owned by the chracteristic. The descriptors' identifiers serve
+  // as keys.
+  base::flat_map<std::string, std::unique_ptr<BluetoothRemoteGattDescriptor>>
+      descriptors_;
+
  private:
   friend class BluetoothGattNotifySession;
 
diff --git a/device/bluetooth/bluetooth_remote_gatt_characteristic_android.cc b/device/bluetooth/bluetooth_remote_gatt_characteristic_android.cc
index 787307a8..175a79e 100644
--- a/device/bluetooth/bluetooth_remote_gatt_characteristic_android.cc
+++ b/device/bluetooth/bluetooth_remote_gatt_characteristic_android.cc
@@ -106,20 +106,21 @@
 std::vector<BluetoothRemoteGattDescriptor*>
 BluetoothRemoteGattCharacteristicAndroid::GetDescriptors() const {
   EnsureDescriptorsCreated();
-  std::vector<BluetoothRemoteGattDescriptor*> descriptors;
-  for (const auto& map_iter : descriptors_)
-    descriptors.push_back(map_iter.second.get());
-  return descriptors;
+  return BluetoothRemoteGattCharacteristic::GetDescriptors();
 }
 
 BluetoothRemoteGattDescriptor*
 BluetoothRemoteGattCharacteristicAndroid::GetDescriptor(
     const std::string& identifier) const {
   EnsureDescriptorsCreated();
-  const auto& iter = descriptors_.find(identifier);
-  if (iter == descriptors_.end())
-    return nullptr;
-  return iter->second.get();
+  return BluetoothRemoteGattCharacteristic::GetDescriptor(identifier);
+}
+
+std::vector<BluetoothRemoteGattDescriptor*>
+BluetoothRemoteGattCharacteristicAndroid::GetDescriptorsByUUID(
+    const BluetoothUUID& uuid) const {
+  EnsureDescriptorsCreated();
+  return BluetoothRemoteGattCharacteristic::GetDescriptorsByUUID(uuid);
 }
 
 void BluetoothRemoteGattCharacteristicAndroid::ReadRemoteCharacteristic(
@@ -236,10 +237,9 @@
       base::android::ConvertJavaStringToUTF8(env, instanceId);
 
   DCHECK(!base::ContainsKey(descriptors_, instanceIdString));
-
-  descriptors_[instanceIdString] = BluetoothRemoteGattDescriptorAndroid::Create(
+  AddDescriptor(BluetoothRemoteGattDescriptorAndroid::Create(
       instanceIdString, bluetooth_gatt_descriptor_wrapper,
-      chrome_bluetooth_device);
+      chrome_bluetooth_device));
 }
 
 void BluetoothRemoteGattCharacteristicAndroid::SubscribeToNotifications(
diff --git a/device/bluetooth/bluetooth_remote_gatt_characteristic_android.h b/device/bluetooth/bluetooth_remote_gatt_characteristic_android.h
index a51ffd6..4ee9306 100644
--- a/device/bluetooth/bluetooth_remote_gatt_characteristic_android.h
+++ b/device/bluetooth/bluetooth_remote_gatt_characteristic_android.h
@@ -8,7 +8,8 @@
 #include <stdint.h>
 
 #include <memory>
-#include <unordered_map>
+#include <string>
+#include <vector>
 
 #include "base/android/jni_android.h"
 #include "base/android/scoped_java_ref.h"
@@ -19,7 +20,6 @@
 namespace device {
 
 class BluetoothAdapterAndroid;
-class BluetoothRemoteGattDescriptorAndroid;
 class BluetoothRemoteGattServiceAndroid;
 
 // BluetoothRemoteGattCharacteristicAndroid along with its owned Java class
@@ -61,6 +61,8 @@
   std::vector<BluetoothRemoteGattDescriptor*> GetDescriptors() const override;
   BluetoothRemoteGattDescriptor* GetDescriptor(
       const std::string& identifier) const override;
+  std::vector<BluetoothRemoteGattDescriptor*> GetDescriptorsByUUID(
+      const BluetoothUUID& uuid) const override;
   void ReadRemoteCharacteristic(const ValueCallback& callback,
                                 const ErrorCallback& error_callback) override;
   void WriteRemoteCharacteristic(const std::vector<uint8_t>& value,
@@ -138,11 +140,6 @@
 
   std::vector<uint8_t> value_;
 
-  // Map of descriptors, keyed by descriptor identifier.
-  std::unordered_map<std::string,
-                     std::unique_ptr<BluetoothRemoteGattDescriptorAndroid>>
-      descriptors_;
-
   DISALLOW_COPY_AND_ASSIGN(BluetoothRemoteGattCharacteristicAndroid);
 };
 
diff --git a/device/bluetooth/bluetooth_remote_gatt_characteristic_mac.h b/device/bluetooth/bluetooth_remote_gatt_characteristic_mac.h
index 744e8aa9..6a53225 100644
--- a/device/bluetooth/bluetooth_remote_gatt_characteristic_mac.h
+++ b/device/bluetooth/bluetooth_remote_gatt_characteristic_mac.h
@@ -8,7 +8,9 @@
 #include "device/bluetooth/bluetooth_remote_gatt_characteristic.h"
 
 #import <CoreBluetooth/CoreBluetooth.h>
-#include <unordered_map>
+#include <string>
+#include <utility>
+#include <vector>
 
 #include "base/mac/scoped_nsobject.h"
 #include "base/memory/weak_ptr.h"
@@ -39,9 +41,6 @@
   const std::vector<uint8_t>& GetValue() const override;
   BluetoothRemoteGattService* GetService() const override;
   bool IsNotifying() const override;
-  std::vector<BluetoothRemoteGattDescriptor*> GetDescriptors() const override;
-  BluetoothRemoteGattDescriptor* GetDescriptor(
-      const std::string& identifier) const override;
   void ReadRemoteCharacteristic(const ValueCallback& callback,
                                 const ErrorCallback& error_callback) override;
   void WriteRemoteCharacteristic(const std::vector<uint8_t>& value,
@@ -49,8 +48,6 @@
                                  const ErrorCallback& error_callback) override;
   bool WriteWithoutResponse(base::span<const uint8_t> value) override;
 
-  DISALLOW_COPY_AND_ASSIGN(BluetoothRemoteGattCharacteristicMac);
-
  protected:
   void SubscribeToNotifications(BluetoothRemoteGattDescriptor* ccc_descriptor,
                                 const base::Closure& callback,
@@ -104,10 +101,10 @@
       CBDescriptor* cb_descriptor) const;
   bool HasPendingRead() const {
     return !read_characteristic_value_callbacks_.first.is_null();
-  };
+  }
   bool HasPendingWrite() const {
     return !write_characteristic_value_callbacks_.first.is_null();
-  };
+  }
   // Is true if the characteristic has been discovered with all its descriptors
   // and discovery_pending_count_ is 0.
   bool is_discovery_complete_;
@@ -135,12 +132,10 @@
   PendingNotifyCallbacks subscribe_to_notification_callbacks_;
   // Stores UnsubscribeFromNotifications request callbacks.
   PendingNotifyCallbacks unsubscribe_from_notification_callbacks_;
-  // Map of descriptors, keyed by descriptor identifier.
-  std::unordered_map<std::string,
-                     std::unique_ptr<BluetoothRemoteGattDescriptorMac>>
-      gatt_descriptor_macs_;
 
   base::WeakPtrFactory<BluetoothRemoteGattCharacteristicMac> weak_ptr_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(BluetoothRemoteGattCharacteristicMac);
 };
 
 // Stream operator for logging.
diff --git a/device/bluetooth/bluetooth_remote_gatt_characteristic_mac.mm b/device/bluetooth/bluetooth_remote_gatt_characteristic_mac.mm
index c2c2ee0..2e91b58f 100644
--- a/device/bluetooth/bluetooth_remote_gatt_characteristic_mac.mm
+++ b/device/bluetooth/bluetooth_remote_gatt_characteristic_mac.mm
@@ -129,28 +129,6 @@
   return [cb_characteristic_ isNotifying] == YES;
 }
 
-std::vector<BluetoothRemoteGattDescriptor*>
-BluetoothRemoteGattCharacteristicMac::GetDescriptors() const {
-  std::vector<BluetoothRemoteGattDescriptor*> gatt_descriptors;
-  for (const auto& iter : gatt_descriptor_macs_) {
-    BluetoothRemoteGattDescriptor* gatt_descriptor =
-        static_cast<BluetoothRemoteGattDescriptor*>(iter.second.get());
-    gatt_descriptors.push_back(gatt_descriptor);
-  }
-  return gatt_descriptors;
-}
-
-BluetoothRemoteGattDescriptor*
-BluetoothRemoteGattCharacteristicMac::GetDescriptor(
-    const std::string& identifier) const {
-  auto searched_pair = gatt_descriptor_macs_.find(identifier);
-  if (searched_pair == gatt_descriptor_macs_.end()) {
-    return nullptr;
-  }
-  return static_cast<BluetoothRemoteGattDescriptor*>(
-      searched_pair->second.get());
-}
-
 void BluetoothRemoteGattCharacteristicMac::ReadRemoteCharacteristic(
     const ValueCallback& callback,
     const ErrorCallback& error_callback) {
@@ -389,7 +367,7 @@
   VLOG(1) << *this << ": Did discover descriptors.";
   --discovery_pending_count_;
   std::unordered_set<std::string> descriptor_identifier_to_remove;
-  for (const auto& iter : gatt_descriptor_macs_) {
+  for (const auto& iter : descriptors_) {
     descriptor_identifier_to_remove.insert(iter.first);
   }
 
@@ -404,21 +382,19 @@
     }
     gatt_descriptor_mac =
         new BluetoothRemoteGattDescriptorMac(this, cb_descriptor);
-    const std::string& identifier = gatt_descriptor_mac->GetIdentifier();
-    auto result_iter = gatt_descriptor_macs_.insert(
-        {identifier, base::WrapUnique(gatt_descriptor_mac)});
-    DCHECK(result_iter.second);
+    bool result = AddDescriptor(base::WrapUnique(gatt_descriptor_mac));
+    DCHECK(result);
     GetMacAdapter()->NotifyGattDescriptorAdded(gatt_descriptor_mac);
     VLOG(1) << *gatt_descriptor_mac << ": New descriptor.";
   }
 
   for (const std::string& identifier : descriptor_identifier_to_remove) {
-    auto pair_to_remove = gatt_descriptor_macs_.find(identifier);
-    std::unique_ptr<BluetoothRemoteGattDescriptorMac> descriptor_to_remove;
-    VLOG(1) << *descriptor_to_remove << ": Removed descriptor.";
-    pair_to_remove->second.swap(descriptor_to_remove);
-    gatt_descriptor_macs_.erase(pair_to_remove);
-    GetMacAdapter()->NotifyGattDescriptorRemoved(descriptor_to_remove.get());
+    auto iter = descriptors_.find(identifier);
+    auto pair = std::move(*iter);
+    VLOG(1) << static_cast<BluetoothRemoteGattDescriptorMac&>(*pair.second)
+            << ": Removed descriptor.";
+    descriptors_.erase(iter);
+    GetMacAdapter()->NotifyGattDescriptorRemoved(pair.second.get());
   }
   is_discovery_complete_ = discovery_pending_count_ == 0;
 }
@@ -471,19 +447,14 @@
 BluetoothRemoteGattDescriptorMac*
 BluetoothRemoteGattCharacteristicMac::GetBluetoothRemoteGattDescriptorMac(
     CBDescriptor* cb_descriptor) const {
-  auto found = std::find_if(
-      gatt_descriptor_macs_.begin(), gatt_descriptor_macs_.end(),
-      [cb_descriptor](
-          const std::pair<const std::string,
-                          std::unique_ptr<BluetoothRemoteGattDescriptorMac>>&
-              pair) {
-        return pair.second->GetCBDescriptor() == cb_descriptor;
-      });
-  if (found == gatt_descriptor_macs_.end()) {
-    return nullptr;
-  } else {
-    return found->second.get();
+  for (const auto& pair : descriptors_) {
+    auto* descriptor_mac =
+        static_cast<BluetoothRemoteGattDescriptorMac*>(pair.second.get());
+    if (descriptor_mac->GetCBDescriptor() == cb_descriptor)
+      return descriptor_mac;
   }
+
+  return nullptr;
 }
 
 DEVICE_BLUETOOTH_EXPORT std::ostream& operator<<(
diff --git a/device/bluetooth/bluetooth_remote_gatt_characteristic_win.cc b/device/bluetooth/bluetooth_remote_gatt_characteristic_win.cc
index bca5dd4..53945e4 100644
--- a/device/bluetooth/bluetooth_remote_gatt_characteristic_win.cc
+++ b/device/bluetooth/bluetooth_remote_gatt_characteristic_win.cc
@@ -20,10 +20,10 @@
 BluetoothRemoteGattCharacteristicWin::BluetoothRemoteGattCharacteristicWin(
     BluetoothRemoteGattServiceWin* parent_service,
     BTH_LE_GATT_CHARACTERISTIC* characteristic_info,
-    scoped_refptr<base::SequencedTaskRunner>& ui_task_runner)
+    scoped_refptr<base::SequencedTaskRunner> ui_task_runner)
     : parent_service_(parent_service),
       characteristic_info_(characteristic_info),
-      ui_task_runner_(ui_task_runner),
+      ui_task_runner_(std::move(ui_task_runner)),
       characteristic_added_notified_(false),
       characteristic_value_read_or_write_in_progress_(false),
       gatt_event_handle_(nullptr),
@@ -135,23 +135,6 @@
   return gatt_event_handle_ != nullptr;
 }
 
-std::vector<BluetoothRemoteGattDescriptor*>
-BluetoothRemoteGattCharacteristicWin::GetDescriptors() const {
-  std::vector<BluetoothRemoteGattDescriptor*> descriptors;
-  for (const auto& descriptor : included_descriptors_)
-    descriptors.push_back(descriptor.second.get());
-  return descriptors;
-}
-
-BluetoothRemoteGattDescriptor*
-BluetoothRemoteGattCharacteristicWin::GetDescriptor(
-    const std::string& identifier) const {
-  GattDescriptorMap::const_iterator it = included_descriptors_.find(identifier);
-  if (it != included_descriptors_.end())
-    return it->second.get();
-  return nullptr;
-}
-
 void BluetoothRemoteGattCharacteristicWin::ReadRemoteCharacteristic(
     const ValueCallback& callback,
     const ErrorCallback& error_callback) {
@@ -264,23 +247,26 @@
     PBTH_LE_GATT_DESCRIPTOR descriptors,
     uint16_t num) {
   if (num == 0) {
-    included_descriptors_.clear();
+    descriptors_.clear();
     return;
   }
 
   // First, remove descriptors that no longer exist.
   std::vector<std::string> to_be_removed;
-  for (const auto& d : included_descriptors_) {
-    if (!DoesDescriptorExist(descriptors, num, d.second.get()))
+  for (const auto& d : descriptors_) {
+    if (!DoesDescriptorExist(
+            descriptors, num,
+            static_cast<BluetoothRemoteGattDescriptorWin*>(d.second.get())))
       to_be_removed.push_back(d.second->GetIdentifier());
   }
-  for (auto id : to_be_removed) {
-    included_descriptors_[id].reset();
-    included_descriptors_.erase(id);
+  for (const auto& id : to_be_removed) {
+    auto iter = descriptors_.find(id);
+    auto pair = std::move(*iter);
+    descriptors_.erase(iter);
   }
 
   // Return if no new descriptors have been added.
-  if (included_descriptors_.size() == num)
+  if (descriptors_.size() == num)
     return;
 
   // Add new descriptors.
@@ -293,20 +279,21 @@
       BluetoothRemoteGattDescriptorWin* descriptor =
           new BluetoothRemoteGattDescriptorWin(this, win_descriptor_info,
                                                ui_task_runner_);
-      included_descriptors_[descriptor->GetIdentifier()] =
-          base::WrapUnique(descriptor);
+      AddDescriptor(base::WrapUnique(descriptor));
     }
   }
 }
 
 bool BluetoothRemoteGattCharacteristicWin::IsDescriptorDiscovered(
-    BTH_LE_UUID& uuid,
+    const BTH_LE_UUID& uuid,
     uint16_t attribute_handle) {
   BluetoothUUID bt_uuid =
       BluetoothTaskManagerWin::BluetoothLowEnergyUuidToBluetoothUuid(uuid);
-  for (const auto& d : included_descriptors_) {
+  for (const auto& d : descriptors_) {
     if (bt_uuid == d.second->GetUUID() &&
-        attribute_handle == d.second->GetAttributeHandle()) {
+        attribute_handle ==
+            static_cast<BluetoothRemoteGattDescriptorWin*>(d.second.get())
+                ->GetAttributeHandle()) {
       return true;
     }
   }
@@ -409,9 +396,7 @@
 void BluetoothRemoteGattCharacteristicWin::ClearIncludedDescriptors() {
   // Explicitly reset to null to ensure that calling GetDescriptor() on the
   // removed descriptor in GattDescriptorRemoved() returns null.
-  for (auto& entry : included_descriptors_)
-    entry.second.reset();
-  included_descriptors_.clear();
+  std::exchange(descriptors_, {});
 }
 
 }  // namespace device.
diff --git a/device/bluetooth/bluetooth_remote_gatt_characteristic_win.h b/device/bluetooth/bluetooth_remote_gatt_characteristic_win.h
index 8936119..54d10ae 100644
--- a/device/bluetooth/bluetooth_remote_gatt_characteristic_win.h
+++ b/device/bluetooth/bluetooth_remote_gatt_characteristic_win.h
@@ -6,7 +6,9 @@
 #define DEVICE_BLUETOOTH_BLUETOOTH_REMOTE_GATT_CHARACTERISTIC_WIN_H_
 
 #include <memory>
-#include <unordered_map>
+#include <string>
+#include <utility>
+#include <vector>
 
 #include "base/memory/weak_ptr.h"
 #include "base/sequenced_task_runner.h"
@@ -29,7 +31,7 @@
   BluetoothRemoteGattCharacteristicWin(
       BluetoothRemoteGattServiceWin* parent_service,
       BTH_LE_GATT_CHARACTERISTIC* characteristic_info,
-      scoped_refptr<base::SequencedTaskRunner>& ui_task_runner);
+      scoped_refptr<base::SequencedTaskRunner> ui_task_runner);
   ~BluetoothRemoteGattCharacteristicWin() override;
 
   // Override BluetoothRemoteGattCharacteristic interfaces.
@@ -40,9 +42,6 @@
   Properties GetProperties() const override;
   Permissions GetPermissions() const override;
   bool IsNotifying() const override;
-  std::vector<BluetoothRemoteGattDescriptor*> GetDescriptors() const override;
-  BluetoothRemoteGattDescriptor* GetDescriptor(
-      const std::string& identifier) const override;
   void ReadRemoteCharacteristic(const ValueCallback& callback,
                                 const ErrorCallback& error_callback) override;
   void WriteRemoteCharacteristic(const std::vector<uint8_t>& value,
@@ -73,7 +72,8 @@
 
   // Checks if the descriptor with |uuid| and |attribute_handle| has already
   // been discovered as included descriptor.
-  bool IsDescriptorDiscovered(BTH_LE_UUID& uuid, uint16_t attribute_handle);
+  bool IsDescriptorDiscovered(const BTH_LE_UUID& uuid,
+                              uint16_t attribute_handle);
 
   // Checks if |descriptor| still exists in this characteristic according to
   // newly discovered |num| of |descriptors|.
@@ -104,13 +104,6 @@
   std::vector<uint8_t> characteristic_value_;
   std::string characteristic_identifier_;
 
-  // The key of GattDescriptorMap is the identitfier of
-  // BluetoothRemoteGattDescriptorWin instance.
-  typedef std::unordered_map<std::string,
-                             std::unique_ptr<BluetoothRemoteGattDescriptorWin>>
-      GattDescriptorMap;
-  GattDescriptorMap included_descriptors_;
-
   // Flag indicates if characteristic added notification of this characteristic
   // has been sent out to avoid duplicate notification.
   bool characteristic_added_notified_;
diff --git a/device/bluetooth/bluetooth_remote_gatt_characteristic_winrt.cc b/device/bluetooth/bluetooth_remote_gatt_characteristic_winrt.cc
index 69562d1..93166b8b 100644
--- a/device/bluetooth/bluetooth_remote_gatt_characteristic_winrt.cc
+++ b/device/bluetooth/bluetooth_remote_gatt_characteristic_winrt.cc
@@ -48,19 +48,6 @@
   return nullptr;
 }
 
-std::vector<BluetoothRemoteGattDescriptor*>
-BluetoothRemoteGattCharacteristicWinrt::GetDescriptors() const {
-  NOTIMPLEMENTED();
-  return {};
-}
-
-BluetoothRemoteGattDescriptor*
-BluetoothRemoteGattCharacteristicWinrt::GetDescriptor(
-    const std::string& identifier) const {
-  NOTIMPLEMENTED();
-  return nullptr;
-}
-
 void BluetoothRemoteGattCharacteristicWinrt::ReadRemoteCharacteristic(
     const ValueCallback& callback,
     const ErrorCallback& error_callback) {
diff --git a/device/bluetooth/bluetooth_remote_gatt_characteristic_winrt.h b/device/bluetooth/bluetooth_remote_gatt_characteristic_winrt.h
index 0c5de24..ca1b3c02 100644
--- a/device/bluetooth/bluetooth_remote_gatt_characteristic_winrt.h
+++ b/device/bluetooth/bluetooth_remote_gatt_characteristic_winrt.h
@@ -36,9 +36,6 @@
   // BluetoothRemoteGattCharacteristic:
   const std::vector<uint8_t>& GetValue() const override;
   BluetoothRemoteGattService* GetService() const override;
-  std::vector<BluetoothRemoteGattDescriptor*> GetDescriptors() const override;
-  BluetoothRemoteGattDescriptor* GetDescriptor(
-      const std::string& identifier) const override;
   void ReadRemoteCharacteristic(const ValueCallback& callback,
                                 const ErrorCallback& error_callback) override;
   void WriteRemoteCharacteristic(const std::vector<uint8_t>& value,
diff --git a/device/bluetooth/bluetooth_remote_gatt_descriptor.h b/device/bluetooth/bluetooth_remote_gatt_descriptor.h
index 34a1928..816d140 100644
--- a/device/bluetooth/bluetooth_remote_gatt_descriptor.h
+++ b/device/bluetooth/bluetooth_remote_gatt_descriptor.h
@@ -29,6 +29,8 @@
 class DEVICE_BLUETOOTH_EXPORT BluetoothRemoteGattDescriptor
     : public virtual BluetoothGattDescriptor {
  public:
+  ~BluetoothRemoteGattDescriptor() override;
+
   // The ValueCallback is used to return the value of a remote characteristic
   // descriptor upon a read request.
   typedef base::Callback<void(const std::vector<uint8_t>&)> ValueCallback;
@@ -60,7 +62,6 @@
 
  protected:
   BluetoothRemoteGattDescriptor();
-  ~BluetoothRemoteGattDescriptor() override;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(BluetoothRemoteGattDescriptor);
diff --git a/device/bluetooth/bluez/bluetooth_remote_gatt_characteristic_bluez.cc b/device/bluetooth/bluez/bluetooth_remote_gatt_characteristic_bluez.cc
index 99afb03..1bbc2b7 100644
--- a/device/bluetooth/bluez/bluetooth_remote_gatt_characteristic_bluez.cc
+++ b/device/bluetooth/bluez/bluetooth_remote_gatt_characteristic_bluez.cc
@@ -155,21 +155,6 @@
   return has_notify_session_ && properties->notifying.value();
 }
 
-std::vector<device::BluetoothRemoteGattDescriptor*>
-BluetoothRemoteGattCharacteristicBlueZ::GetDescriptors() const {
-  std::vector<device::BluetoothRemoteGattDescriptor*> descriptors;
-  for (const auto& descriptor : descriptors_)
-    descriptors.push_back(descriptor.second.get());
-  return descriptors;
-}
-
-device::BluetoothRemoteGattDescriptor*
-BluetoothRemoteGattCharacteristicBlueZ::GetDescriptor(
-    const std::string& identifier) const {
-  auto iter = descriptors_.find(dbus::ObjectPath(identifier));
-  return iter != descriptors_.end() ? iter->second.get() : nullptr;
-}
-
 void BluetoothRemoteGattCharacteristicBlueZ::ReadRemoteCharacteristic(
     const ValueCallback& callback,
     const ErrorCallback& error_callback) {
@@ -262,7 +247,7 @@
 
 void BluetoothRemoteGattCharacteristicBlueZ::GattDescriptorAdded(
     const dbus::ObjectPath& object_path) {
-  if (descriptors_.find(object_path) != descriptors_.end()) {
+  if (descriptors_.find(object_path.value()) != descriptors_.end()) {
     VLOG(1) << "Remote GATT characteristic descriptor already exists: "
             << object_path.value();
     return;
@@ -284,7 +269,7 @@
   // NOTE: Can't use std::make_unique due to private constructor.
   BluetoothRemoteGattDescriptorBlueZ* descriptor =
       new BluetoothRemoteGattDescriptorBlueZ(this, object_path);
-  descriptors_.emplace(object_path, base::WrapUnique(descriptor));
+  AddDescriptor(base::WrapUnique(descriptor));
   DCHECK(descriptor->GetIdentifier() == object_path.value());
   DCHECK(descriptor->GetUUID().IsValid());
   DCHECK(service_);
@@ -295,7 +280,7 @@
 
 void BluetoothRemoteGattCharacteristicBlueZ::GattDescriptorRemoved(
     const dbus::ObjectPath& object_path) {
-  DescriptorMap::iterator iter = descriptors_.find(object_path);
+  auto iter = descriptors_.find(object_path.value());
   if (iter == descriptors_.end()) {
     VLOG(2) << "Unknown descriptor removed: " << object_path.value();
     return;
@@ -305,19 +290,21 @@
           << GetIdentifier() << ", UUID: " << GetUUID().canonical_value();
 
   auto descriptor = std::move(iter->second);
-  DCHECK(descriptor->object_path() == object_path);
+  auto* descriptor_bluez =
+      static_cast<BluetoothRemoteGattDescriptorBlueZ*>(descriptor.get());
+  DCHECK(descriptor_bluez->object_path() == object_path);
   descriptors_.erase(iter);
 
   DCHECK(service_);
   static_cast<BluetoothRemoteGattServiceBlueZ*>(service_)
-      ->NotifyDescriptorAddedOrRemoved(this, descriptor.get(),
+      ->NotifyDescriptorAddedOrRemoved(this, descriptor_bluez,
                                        false /* added */);
 }
 
 void BluetoothRemoteGattCharacteristicBlueZ::GattDescriptorPropertyChanged(
     const dbus::ObjectPath& object_path,
     const std::string& property_name) {
-  DescriptorMap::iterator iter = descriptors_.find(object_path);
+  auto iter = descriptors_.find(object_path.value());
   if (iter == descriptors_.end()) {
     VLOG(2) << "Unknown descriptor removed: " << object_path.value();
     return;
@@ -335,8 +322,10 @@
 
   DCHECK(service_);
   static_cast<BluetoothRemoteGattServiceBlueZ*>(service_)
-      ->NotifyDescriptorValueChanged(this, iter->second.get(),
-                                     properties->value.value());
+      ->NotifyDescriptorValueChanged(
+          this,
+          static_cast<BluetoothRemoteGattDescriptorBlueZ*>(iter->second.get()),
+          properties->value.value());
 }
 
 void BluetoothRemoteGattCharacteristicBlueZ::OnStartNotifySuccess(
diff --git a/device/bluetooth/bluez/bluetooth_remote_gatt_characteristic_bluez.h b/device/bluetooth/bluez/bluetooth_remote_gatt_characteristic_bluez.h
index e02fab6d..4d252cf 100644
--- a/device/bluetooth/bluez/bluetooth_remote_gatt_characteristic_bluez.h
+++ b/device/bluetooth/bluez/bluetooth_remote_gatt_characteristic_bluez.h
@@ -33,7 +33,6 @@
 
 namespace bluez {
 
-class BluetoothRemoteGattDescriptorBlueZ;
 class BluetoothRemoteGattServiceBlueZ;
 
 // The BluetoothRemoteGattCharacteristicBlueZ class implements
@@ -55,10 +54,6 @@
   const std::vector<uint8_t>& GetValue() const override;
   device::BluetoothRemoteGattService* GetService() const override;
   bool IsNotifying() const override;
-  std::vector<device::BluetoothRemoteGattDescriptor*> GetDescriptors()
-      const override;
-  device::BluetoothRemoteGattDescriptor* GetDescriptor(
-      const std::string& identifier) const override;
   void ReadRemoteCharacteristic(const ValueCallback& callback,
                                 const ErrorCallback& error_callback) override;
   void WriteRemoteCharacteristic(const std::vector<uint8_t>& value,
@@ -137,16 +132,6 @@
   // True, if there exists a Bluez notify session.
   bool has_notify_session_;
 
-  using DescriptorMap =
-      std::map<dbus::ObjectPath,
-               std::unique_ptr<BluetoothRemoteGattDescriptorBlueZ>>;
-
-  // Mapping from GATT descriptor object paths to descriptor objects owned by
-  // this characteristic. Since the BlueZ implementation uses object paths
-  // as unique identifiers, we also use this mapping to return descriptors by
-  // identifier.
-  DescriptorMap descriptors_;
-
   // The GATT service this GATT characteristic belongs to.
   BluetoothRemoteGattServiceBlueZ* service_;
 
diff --git a/device/bluetooth/cast/bluetooth_remote_gatt_characteristic_cast.cc b/device/bluetooth/cast/bluetooth_remote_gatt_characteristic_cast.cc
index 3876ee9d..9718c43 100644
--- a/device/bluetooth/cast/bluetooth_remote_gatt_characteristic_cast.cc
+++ b/device/bluetooth/cast/bluetooth_remote_gatt_characteristic_cast.cc
@@ -4,6 +4,8 @@
 
 #include "device/bluetooth/cast/bluetooth_remote_gatt_characteristic_cast.h"
 
+#include <memory>
+
 #include "base/bind.h"
 #include "base/callback.h"
 #include "base/callback_forward.h"
@@ -94,7 +96,7 @@
   auto descriptors = remote_characteristic_->GetDescriptors();
   descriptors_.reserve(descriptors.size());
   for (const auto& descriptor : descriptors) {
-    descriptors_.push_back(
+    AddDescriptor(
         std::make_unique<BluetoothRemoteGattDescriptorCast>(this, descriptor));
   }
 }
@@ -130,27 +132,6 @@
   return service_;
 }
 
-std::vector<BluetoothRemoteGattDescriptor*>
-BluetoothRemoteGattCharacteristicCast::GetDescriptors() const {
-  std::vector<BluetoothRemoteGattDescriptor*> descriptors;
-  descriptors.reserve(descriptors_.size());
-  for (auto& descriptor : descriptors_) {
-    descriptors.push_back(descriptor.get());
-  }
-  return descriptors;
-}
-
-BluetoothRemoteGattDescriptor*
-BluetoothRemoteGattCharacteristicCast::GetDescriptor(
-    const std::string& identifier) const {
-  for (auto& descriptor : descriptors_) {
-    if (descriptor->GetIdentifier() == identifier) {
-      return descriptor.get();
-    }
-  }
-  return nullptr;
-}
-
 void BluetoothRemoteGattCharacteristicCast::ReadRemoteCharacteristic(
     const ValueCallback& callback,
     const ErrorCallback& error_callback) {
diff --git a/device/bluetooth/cast/bluetooth_remote_gatt_characteristic_cast.h b/device/bluetooth/cast/bluetooth_remote_gatt_characteristic_cast.h
index 8c5a2e3..0f001b6 100644
--- a/device/bluetooth/cast/bluetooth_remote_gatt_characteristic_cast.h
+++ b/device/bluetooth/cast/bluetooth_remote_gatt_characteristic_cast.h
@@ -9,6 +9,7 @@
 
 #include <set>
 #include <string>
+#include <utility>
 #include <vector>
 
 #include "base/callback.h"
@@ -24,7 +25,6 @@
 
 namespace device {
 
-class BluetoothRemoteGattDescriptorCast;
 class BluetoothRemoteGattServiceCast;
 
 class BluetoothRemoteGattCharacteristicCast
@@ -45,9 +45,6 @@
   // BluetoothRemoteGattCharacteristic implementation:
   const std::vector<uint8_t>& GetValue() const override;
   BluetoothRemoteGattService* GetService() const override;
-  std::vector<BluetoothRemoteGattDescriptor*> GetDescriptors() const override;
-  BluetoothRemoteGattDescriptor* GetDescriptor(
-      const std::string& identifier) const override;
   void ReadRemoteCharacteristic(const ValueCallback& callback,
                                 const ErrorCallback& error_callback) override;
   void WriteRemoteCharacteristic(const std::vector<uint8_t>& value,
@@ -92,7 +89,6 @@
       remote_characteristic_;
   std::vector<uint8_t> value_;
 
-  std::vector<std::unique_ptr<BluetoothRemoteGattDescriptorCast>> descriptors_;
   base::WeakPtrFactory<BluetoothRemoteGattCharacteristicCast> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(BluetoothRemoteGattCharacteristicCast);
@@ -100,4 +96,4 @@
 
 }  // namespace device
 
-#endif  // DEVICE_BLUETOOTH_CAST_BLUETOOTH_REMOTE_GATT_CHARACTERISTIC_CAST_H_
\ No newline at end of file
+#endif  // DEVICE_BLUETOOTH_CAST_BLUETOOTH_REMOTE_GATT_CHARACTERISTIC_CAST_H_
diff --git a/device/bluetooth/test/fake_remote_gatt_characteristic.cc b/device/bluetooth/test/fake_remote_gatt_characteristic.cc
index fede426..39652e8 100644
--- a/device/bluetooth/test/fake_remote_gatt_characteristic.cc
+++ b/device/bluetooth/test/fake_remote_gatt_characteristic.cc
@@ -47,30 +47,20 @@
 
 std::string FakeRemoteGattCharacteristic::AddFakeDescriptor(
     const device::BluetoothUUID& descriptor_uuid) {
-  FakeDescriptorMap::iterator it;
-  bool inserted;
-
   // Attribute instance Ids need to be unique.
   std::string new_descriptor_id = base::StringPrintf(
       "%s_%zu", GetIdentifier().c_str(), ++last_descriptor_id_);
 
-  std::tie(it, inserted) = fake_descriptors_.emplace(
-      new_descriptor_id, std::make_unique<FakeRemoteGattDescriptor>(
-                             new_descriptor_id, descriptor_uuid, this));
+  bool result = AddDescriptor(std::make_unique<FakeRemoteGattDescriptor>(
+      new_descriptor_id, descriptor_uuid, this));
 
-  DCHECK(inserted);
-  return it->second->GetIdentifier();
+  DCHECK(result);
+  return new_descriptor_id;
 }
 
 bool FakeRemoteGattCharacteristic::RemoveFakeDescriptor(
     const std::string& identifier) {
-  auto it = fake_descriptors_.find(identifier);
-  if (it == fake_descriptors_.end()) {
-    return false;
-  }
-
-  fake_descriptors_.erase(it);
-  return true;
+  return descriptors_.erase(identifier) != 0u;
 }
 
 void FakeRemoteGattCharacteristic::SetNextReadResponse(
@@ -103,8 +93,10 @@
   return !next_read_response_ && !next_write_response_ &&
          !next_subscribe_to_notifications_response_ &&
          std::all_of(
-             fake_descriptors_.begin(), fake_descriptors_.end(),
-             [](const auto& e) { return e.second->AllResponsesConsumed(); });
+             descriptors_.begin(), descriptors_.end(), [](const auto& e) {
+               return static_cast<FakeRemoteGattDescriptor*>(e.second.get())
+                   ->AllResponsesConsumed();
+             });
 }
 
 std::string FakeRemoteGattCharacteristic::GetIdentifier() const {
@@ -136,24 +128,6 @@
   return service_;
 }
 
-std::vector<device::BluetoothRemoteGattDescriptor*>
-FakeRemoteGattCharacteristic::GetDescriptors() const {
-  std::vector<device::BluetoothRemoteGattDescriptor*> descriptors;
-  for (const auto& it : fake_descriptors_)
-    descriptors.push_back(it.second.get());
-  return descriptors;
-}
-
-device::BluetoothRemoteGattDescriptor*
-FakeRemoteGattCharacteristic::GetDescriptor(
-    const std::string& identifier) const {
-  const auto& it = fake_descriptors_.find(identifier);
-  if (it == fake_descriptors_.end())
-    return nullptr;
-
-  return it->second.get();
-}
-
 void FakeRemoteGattCharacteristic::ReadRemoteCharacteristic(
     const ValueCallback& callback,
     const ErrorCallback& error_callback) {
diff --git a/device/bluetooth/test/fake_remote_gatt_characteristic.h b/device/bluetooth/test/fake_remote_gatt_characteristic.h
index da6cd55..cb311c50 100644
--- a/device/bluetooth/test/fake_remote_gatt_characteristic.h
+++ b/device/bluetooth/test/fake_remote_gatt_characteristic.h
@@ -83,10 +83,6 @@
   // device::BluetoothRemoteGattCharacteristic overrides:
   const std::vector<uint8_t>& GetValue() const override;
   device::BluetoothRemoteGattService* GetService() const override;
-  std::vector<device::BluetoothRemoteGattDescriptor*> GetDescriptors()
-      const override;
-  device::BluetoothRemoteGattDescriptor* GetDescriptor(
-      const std::string& identifier) const override;
   void ReadRemoteCharacteristic(const ValueCallback& callback,
                                 const ErrorCallback& error_callback) override;
   void WriteRemoteCharacteristic(const std::vector<uint8_t>& value,
@@ -160,10 +156,6 @@
 
   size_t last_descriptor_id_;
 
-  using FakeDescriptorMap =
-      std::map<std::string, std::unique_ptr<FakeRemoteGattDescriptor>>;
-  FakeDescriptorMap fake_descriptors_;
-
   base::WeakPtrFactory<FakeRemoteGattCharacteristic> weak_ptr_factory_;
 };
 
diff --git a/device/bluetooth/test/mock_bluetooth_gatt_characteristic.cc b/device/bluetooth/test/mock_bluetooth_gatt_characteristic.cc
index 390b9e5..6367639 100644
--- a/device/bluetooth/test/mock_bluetooth_gatt_characteristic.cc
+++ b/device/bluetooth/test/mock_bluetooth_gatt_characteristic.cc
@@ -3,9 +3,13 @@
 // found in the LICENSE file.
 
 #include "device/bluetooth/test/mock_bluetooth_gatt_characteristic.h"
+
+#include <utility>
+
 #include "device/bluetooth/test/mock_bluetooth_gatt_descriptor.h"
 #include "device/bluetooth/test/mock_bluetooth_gatt_service.h"
 
+using testing::Invoke;
 using testing::Return;
 using testing::ReturnRefOfCopy;
 using testing::_;
@@ -28,35 +32,20 @@
   ON_CALL(*this, GetProperties()).WillByDefault(Return(properties));
   ON_CALL(*this, GetPermissions()).WillByDefault(Return(permissions));
   ON_CALL(*this, IsNotifying()).WillByDefault(Return(false));
-  ON_CALL(*this, GetDescriptors())
-      .WillByDefault(Return(std::vector<BluetoothRemoteGattDescriptor*>()));
+  ON_CALL(*this, GetDescriptors()).WillByDefault(Invoke([this] {
+    return BluetoothRemoteGattCharacteristic::GetDescriptors();
+  }));
+  ON_CALL(*this, GetDescriptor(_))
+      .WillByDefault(Invoke([this](const std::string& id) {
+        return BluetoothRemoteGattCharacteristic::GetDescriptor(id);
+      }));
 }
 
 MockBluetoothGattCharacteristic::~MockBluetoothGattCharacteristic() = default;
 
 void MockBluetoothGattCharacteristic::AddMockDescriptor(
     std::unique_ptr<MockBluetoothGattDescriptor> mock_descriptor) {
-  mock_descriptors_.push_back(std::move(mock_descriptor));
-}
-
-std::vector<BluetoothRemoteGattDescriptor*>
-MockBluetoothGattCharacteristic::GetMockDescriptors() const {
-  std::vector<BluetoothRemoteGattDescriptor*> descriptors;
-  for (auto& descriptor : mock_descriptors_) {
-    descriptors.push_back(descriptor.get());
-  }
-  return descriptors;
-}
-
-BluetoothRemoteGattDescriptor*
-MockBluetoothGattCharacteristic::GetMockDescriptor(
-    const std::string& identifier) const {
-  for (auto& descriptor : mock_descriptors_) {
-    if (descriptor->GetIdentifier() == identifier) {
-      return descriptor.get();
-    }
-  }
-  return nullptr;
+  AddDescriptor(std::move(mock_descriptor));
 }
 
 }  // namespace device
diff --git a/device/bluetooth/test/mock_bluetooth_gatt_characteristic.h b/device/bluetooth/test/mock_bluetooth_gatt_characteristic.h
index 0be00280..cc52b56 100644
--- a/device/bluetooth/test/mock_bluetooth_gatt_characteristic.h
+++ b/device/bluetooth/test/mock_bluetooth_gatt_characteristic.h
@@ -7,6 +7,7 @@
 
 #include <stdint.h>
 
+#include <memory>
 #include <string>
 #include <vector>
 
@@ -47,7 +48,6 @@
                      std::vector<BluetoothRemoteGattDescriptor*>());
   MOCK_CONST_METHOD1(GetDescriptor,
                      BluetoothRemoteGattDescriptor*(const std::string&));
-  MOCK_METHOD1(AddDescriptor, bool(BluetoothRemoteGattDescriptor*));
   MOCK_METHOD1(UpdateValue, bool(const std::vector<uint8_t>&));
 #if defined(OS_CHROMEOS)
   MOCK_METHOD3(StartNotifySession,
@@ -74,9 +74,6 @@
 
   void AddMockDescriptor(
       std::unique_ptr<MockBluetoothGattDescriptor> mock_descriptor);
-  std::vector<BluetoothRemoteGattDescriptor*> GetMockDescriptors() const;
-  BluetoothRemoteGattDescriptor* GetMockDescriptor(
-      const std::string& identifier) const;
 
  protected:
 #if defined(OS_CHROMEOS)
@@ -97,8 +94,6 @@
                     const ErrorCallback&));
 
  private:
-  std::vector<std::unique_ptr<MockBluetoothGattDescriptor>> mock_descriptors_;
-
   DISALLOW_COPY_AND_ASSIGN(MockBluetoothGattCharacteristic);
 };
 
diff --git a/gpu/command_buffer/client/gles2_implementation.cc b/gpu/command_buffer/client/gles2_implementation.cc
index 03c0960..09c5ef3 100644
--- a/gpu/command_buffer/client/gles2_implementation.cc
+++ b/gpu/command_buffer/client/gles2_implementation.cc
@@ -390,6 +390,9 @@
 }
 
 void GLES2Implementation::CallDeferredErrorCallbacks() {
+  if (deferred_error_callbacks_.empty())
+    return;
+
   if (error_message_callback_.is_null()) {
     // User probably cleared this out.
     deferred_error_callbacks_.clear();
diff --git a/gpu/command_buffer/common/context_creation_attribs.cc b/gpu/command_buffer/common/context_creation_attribs.cc
index fae1da2..c8e413aa 100644
--- a/gpu/command_buffer/common/context_creation_attribs.cc
+++ b/gpu/command_buffer/common/context_creation_attribs.cc
@@ -13,6 +13,7 @@
   switch (context_type) {
     case CONTEXT_TYPE_WEBGL1:
     case CONTEXT_TYPE_WEBGL2:
+    case CONTEXT_TYPE_WEBGL2_COMPUTE:
       return true;
     case CONTEXT_TYPE_OPENGLES2:
     case CONTEXT_TYPE_OPENGLES3:
@@ -31,6 +32,7 @@
       return true;
     case CONTEXT_TYPE_WEBGL2:
     case CONTEXT_TYPE_OPENGLES3:
+    case CONTEXT_TYPE_WEBGL2_COMPUTE:
       return false;
   }
 
@@ -46,6 +48,7 @@
       return true;
     case CONTEXT_TYPE_WEBGL1:
     case CONTEXT_TYPE_OPENGLES2:
+    case CONTEXT_TYPE_WEBGL2_COMPUTE:
       return false;
   }
 
diff --git a/gpu/command_buffer/common/context_creation_attribs.h b/gpu/command_buffer/common/context_creation_attribs.h
index dcc680be..a1b8b7f8 100644
--- a/gpu/command_buffer/common/context_creation_attribs.h
+++ b/gpu/command_buffer/common/context_creation_attribs.h
@@ -16,6 +16,7 @@
 enum ContextType {
   CONTEXT_TYPE_WEBGL1,
   CONTEXT_TYPE_WEBGL2,
+  CONTEXT_TYPE_WEBGL2_COMPUTE,
   CONTEXT_TYPE_OPENGLES2,
   CONTEXT_TYPE_OPENGLES3,
   CONTEXT_TYPE_LAST = CONTEXT_TYPE_OPENGLES3
diff --git a/gpu/command_buffer/service/feature_info.cc b/gpu/command_buffer/service/feature_info.cc
index a8ed234..699bbc7 100644
--- a/gpu/command_buffer/service/feature_info.cc
+++ b/gpu/command_buffer/service/feature_info.cc
@@ -815,6 +815,7 @@
         break;
       case CONTEXT_TYPE_WEBGL1:
       case CONTEXT_TYPE_WEBGL2:
+      case CONTEXT_TYPE_WEBGL2_COMPUTE:
         break;
     }
   }
diff --git a/gpu/ipc/service/command_buffer_stub.cc b/gpu/ipc/service/command_buffer_stub.cc
index 3031163..a7bc3518 100644
--- a/gpu/ipc/service/command_buffer_stub.cc
+++ b/gpu/ipc/service/command_buffer_stub.cc
@@ -72,6 +72,7 @@
     switch (context_type_) {                                               \
       case CONTEXT_TYPE_WEBGL1:                                            \
       case CONTEXT_TYPE_WEBGL2:                                            \
+      case CONTEXT_TYPE_WEBGL2_COMPUTE:                                    \
         UMA_HISTOGRAM_MEMORY_LARGE_MB("GPU.ContextMemory.WebGL." category, \
                                       mb_used);                            \
         break;                                                             \
diff --git a/headless/lib/headless_macros.h b/headless/lib/headless_macros.h
index f0dea81..f8d57aee 100644
--- a/headless/lib/headless_macros.h
+++ b/headless/lib/headless_macros.h
@@ -7,8 +7,8 @@
 
 #include "build/build_config.h"
 
-#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_FUCHSIA)
+#if defined(OS_POSIX) && !defined(OS_MACOSX)
 #define HEADLESS_USE_BREAKPAD
-#endif  // defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_FUCHSIA)
+#endif  // defined(OS_POSIX) && !defined(OS_MACOSX)
 
 #endif  // HEADLESS_LIB_HEADLESS_MACROS_H_
diff --git a/ios/chrome/browser/ui/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view_controller.mm
index b8419b3..04839612 100644
--- a/ios/chrome/browser/ui/browser_view_controller.mm
+++ b/ios/chrome/browser/ui/browser_view_controller.mm
@@ -4485,7 +4485,7 @@
                 inBackground:inBackground];
   };
 
-  if (!IsUIRefreshPhase1Enabled() || !inBackground ||
+  if (!IsUIRefreshPhase1Enabled() || !inBackground || [self canShowTabStrip] ||
       CGPointEqualToPoint(originPoint, CGPointZero)) {
     openTab();
   } else {
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_controlling.h b/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_controlling.h
index 3157b38e..01120f6 100644
--- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_controlling.h
+++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_controlling.h
@@ -35,6 +35,9 @@
 // Calls layoutIfNeeded on the header.
 - (void)layoutHeader;
 
+// Update any dynamic constraints.
+- (void)updateConstraints;
+
 // Returns the Y value to use for the scroll view's contentOffset when scrolling
 // the omnibox to the top of the screen.
 - (CGFloat)pinnedOffsetY;
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_synchronizer.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_synchronizer.mm
index 34f76da1..0c8b44f 100644
--- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_synchronizer.mm
+++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_synchronizer.mm
@@ -207,6 +207,10 @@
   }
 }
 
+- (void)updateConstraints {
+  [self.headerController updateConstraints];
+}
+
 - (void)unfocusOmnibox {
   [self.headerController unfocusOmnibox];
 }
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_synchronizing.h b/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_synchronizing.h
index a3686a8..72ea1f4 100644
--- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_synchronizing.h
+++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_synchronizing.h
@@ -21,6 +21,9 @@
 // Unfocuses the omnibox.
 - (void)unfocusOmnibox;
 
+// Update any dynamic constraints.
+- (void)updateConstraints;
+
 // Returns the Y value to use for the scroll view's contentOffset when scrolling
 // the omnibox to the top of the screen.
 - (CGFloat)pinnedOffsetY;
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_view.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_view.mm
index 5ddce8d..ad0ee43c 100644
--- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_view.mm
+++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_view.mm
@@ -81,6 +81,19 @@
 
 #pragma mark - NTPHeaderViewAdapter
 
+- (void)addToolbarView:(UIView*)toolbarView {
+  _toolBarView = toolbarView;
+  [self addSubview:toolbarView];
+  id<LayoutGuideProvider> layoutGuide = SafeAreaLayoutGuideForView(self);
+  [NSLayoutConstraint activateConstraints:@[
+    [toolbarView.leadingAnchor constraintEqualToAnchor:self.leadingAnchor],
+    [toolbarView.topAnchor constraintEqualToAnchor:layoutGuide.topAnchor],
+    [toolbarView.heightAnchor
+        constraintEqualToConstant:ntp_header::ToolbarHeight()],
+    [toolbarView.trailingAnchor constraintEqualToAnchor:self.trailingAnchor]
+  ]];
+}
+
 - (void)addViewsToSearchField:(UIView*)searchField {
   ToolbarButtonFactory* buttonFactory =
       [[ToolbarButtonFactory alloc] initWithStyle:NORMAL];
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_view_controller.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_view_controller.mm
index 08890ead..a1e3a1f 100644
--- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_view_controller.mm
+++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_view_controller.mm
@@ -135,10 +135,7 @@
         if (IsSplitToolbarMode()) {
           [self.toolbarDelegate setScrollProgressForTabletOmnibox:1];
         }
-
-        // Update the doodle top margin to the new -doodleTopMargin value.
-        self.doodleTopMarginConstraint.constant =
-            content_suggestions::doodleTopMargin(YES);
+        [self updateConstraints];
       };
 
   [coordinator animateAlongsideTransition:transition completion:nil];
@@ -198,6 +195,12 @@
   [self.headerView layoutIfNeeded];
 }
 
+// Update the doodle top margin to the new -doodleTopMargin value.
+- (void)updateConstraints {
+  self.doodleTopMarginConstraint.constant =
+      content_suggestions::doodleTopMargin(YES);
+}
+
 - (CGFloat)pinnedOffsetY {
   CGFloat headerHeight = content_suggestions::heightForLogoHeader(
       self.logoIsShowing, self.promoCanShow, YES);
@@ -354,18 +357,7 @@
 - (void)addFakeTapView {
   UIButton* fakeTapButton = [[UIButton alloc] init];
   fakeTapButton.translatesAutoresizingMaskIntoConstraints = NO;
-  [self.headerView addSubview:fakeTapButton];
-  id<LayoutGuideProvider> layoutGuide =
-      SafeAreaLayoutGuideForView(self.headerView);
-  [NSLayoutConstraint activateConstraints:@[
-    [fakeTapButton.leadingAnchor
-        constraintEqualToAnchor:self.headerView.leadingAnchor],
-    [fakeTapButton.topAnchor constraintEqualToAnchor:layoutGuide.topAnchor],
-    [fakeTapButton.heightAnchor
-        constraintEqualToConstant:ntp_header::ToolbarHeight()],
-    [fakeTapButton.trailingAnchor
-        constraintEqualToAnchor:self.headerView.trailingAnchor]
-  ]];
+  [self.headerView addToolbarView:fakeTapButton];
   [fakeTapButton addTarget:self
                     action:@selector(fakeOmniboxTapped:)
           forControlEvents:UIControlEventTouchUpInside];
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm
index e016671..9425ed37 100644
--- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm
+++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm
@@ -193,6 +193,7 @@
       updateMostVisitedForSize:self.collectionView.bounds.size];
   [self.headerSynchronizer
       updateFakeOmniboxOnNewWidth:self.collectionView.bounds.size.width];
+  [self.headerSynchronizer updateConstraints];
   [self.collectionView reloadData];
   if (ShouldCellsBeFullWidth(
           [UIApplication sharedApplication].keyWindow.traitCollection)) {
diff --git a/ios/chrome/browser/ui/location_bar/BUILD.gn b/ios/chrome/browser/ui/location_bar/BUILD.gn
index 26b8aea8..5082fa0 100644
--- a/ios/chrome/browser/ui/location_bar/BUILD.gn
+++ b/ios/chrome/browser/ui/location_bar/BUILD.gn
@@ -57,6 +57,7 @@
     "//ios/chrome/browser/ui/omnibox:omnibox_internal",
     "//ios/chrome/browser/ui/omnibox:omnibox_util",
     "//ios/chrome/browser/ui/omnibox/popup",
+    "//ios/chrome/browser/ui/orchestrator:orchestrator",
     "//ios/chrome/browser/ui/qr_scanner/requirements",
     "//ios/chrome/browser/ui/toolbar/buttons",
     "//ios/chrome/browser/ui/toolbar/keyboard_assist:keyboard_assist",
diff --git a/ios/chrome/browser/ui/location_bar/location_bar_coordinator.h b/ios/chrome/browser/ui/location_bar/location_bar_coordinator.h
index 0979f96..1109848 100644
--- a/ios/chrome/browser/ui/location_bar/location_bar_coordinator.h
+++ b/ios/chrome/browser/ui/location_bar/location_bar_coordinator.h
@@ -9,6 +9,7 @@
 
 // Location bar coordinator for the UI Refresh location bar.
 @interface LocationBarCoordinator : NSObject<LocationBarGenericCoordinator>
+
 @end
 
 #endif  // IOS_CHROME_BROWSER_UI_LOCATION_BAR_LOCATION_BAR_COORDINATOR_H_
diff --git a/ios/chrome/browser/ui/location_bar/location_bar_coordinator.mm b/ios/chrome/browser/ui/location_bar/location_bar_coordinator.mm
index c991db2a..92060a1 100644
--- a/ios/chrome/browser/ui/location_bar/location_bar_coordinator.mm
+++ b/ios/chrome/browser/ui/location_bar/location_bar_coordinator.mm
@@ -129,6 +129,7 @@
       setEditView:self.omniboxCoordinator.managedViewController.view];
   [self.omniboxCoordinator.managedViewController
       didMoveToParentViewController:self.viewController];
+  self.viewController.offsetProvider = [self.omniboxCoordinator offsetProvider];
 
   self.omniboxPopupCoordinator =
       [self.omniboxCoordinator createPopupCoordinator:self.popupPositioner];
@@ -171,6 +172,10 @@
   return [self.omniboxCoordinator isOmniboxFirstResponder];
 }
 
+- (id<LocationBarAnimatee>)locationBarAnimatee {
+  return self.viewController;
+}
+
 #pragma mark - LoadQueryCommands
 
 - (void)loadQuery:(NSString*)query immediately:(BOOL)immediately {
@@ -223,7 +228,6 @@
 }
 
 - (void)focusOmnibox {
-  [self.viewController switchToEditing:YES];
   [self.omniboxCoordinator focusOmnibox];
 }
 
@@ -239,7 +243,6 @@
 
 - (void)locationBarHasResignedFirstResponder {
   [self.delegate locationBarDidResignFirstResponder];
-  [self.viewController switchToEditing:NO];
 }
 
 - (void)locationBarBeganEdit {
diff --git a/ios/chrome/browser/ui/location_bar/location_bar_generic_coordinator.h b/ios/chrome/browser/ui/location_bar/location_bar_generic_coordinator.h
index 5ee70e8..a87640c 100644
--- a/ios/chrome/browser/ui/location_bar/location_bar_generic_coordinator.h
+++ b/ios/chrome/browser/ui/location_bar/location_bar_generic_coordinator.h
@@ -18,6 +18,7 @@
 @class CommandDispatcher;
 @protocol ApplicationCommands;
 @protocol BrowserCommands;
+@protocol LocationBarAnimatee;
 @protocol OmniboxPopupPositioner;
 @protocol ToolbarCoordinatorDelegate;
 @protocol UrlLoader;
@@ -58,6 +59,13 @@
 // Indicates when the omnibox is the first responder.
 - (BOOL)isOmniboxFirstResponder;
 
+// TODO(crbug.com/831506): Once legacy location bar is deleted, remove the
+// @optional label and matching respondsToSelector: calls.
+@optional
+
+// Returns the animatee.
+- (id<LocationBarAnimatee>)locationBarAnimatee;
+
 @end
 
 #endif  // IOS_CHROME_BROWSER_UI_LOCATION_BAR_LOCATION_BAR_GENERIC_COORDINATOR_H_
diff --git a/ios/chrome/browser/ui/location_bar/location_bar_view_controller.h b/ios/chrome/browser/ui/location_bar/location_bar_view_controller.h
index d6d99c85..440cbde0 100644
--- a/ios/chrome/browser/ui/location_bar/location_bar_view_controller.h
+++ b/ios/chrome/browser/ui/location_bar/location_bar_view_controller.h
@@ -9,11 +9,13 @@
 
 #import "ios/chrome/browser/ui/fullscreen/fullscreen_ui_element.h"
 #import "ios/chrome/browser/ui/location_bar/location_bar_consumer.h"
+#import "ios/chrome/browser/ui/orchestrator/location_bar_animatee.h"
 
 @class OmniboxTextFieldIOS;
 @protocol ActivityServiceCommands;
-@protocol BrowserCommands;
 @protocol ApplicationCommands;
+@protocol BrowserCommands;
+@protocol LocationBarOffsetProvider;
 @protocol LoadQueryCommands;
 
 @protocol LocationBarViewControllerDelegate<NSObject>
@@ -30,7 +32,8 @@
 // the omnibox - the editing and the non-editing states. In the editing state,
 // the omnibox textfield is displayed; in the non-editing state, the current
 // location is displayed.
-@interface LocationBarViewController : UIViewController<FullscreenUIElement>
+@interface LocationBarViewController
+    : UIViewController<FullscreenUIElement, LocationBarAnimatee>
 
 // Sets the edit view to use in the editing state. This must be set before the
 // view of this view controller is initialized. This must only be called once.
@@ -48,6 +51,9 @@
 // Delegate for this location bar view controller.
 @property(nonatomic, weak) id<LocationBarViewControllerDelegate> delegate;
 
+// The offset provider for the edit/steady transition animation.
+@property(nonatomic, weak) id<LocationBarOffsetProvider> offsetProvider;
+
 // Switches between the two states of the location bar:
 // - editing state, with the textfield;
 // - non-editing state, with location icon and text.
diff --git a/ios/chrome/browser/ui/location_bar/location_bar_view_controller.mm b/ios/chrome/browser/ui/location_bar/location_bar_view_controller.mm
index 09928dff..e0a17dc 100644
--- a/ios/chrome/browser/ui/location_bar/location_bar_view_controller.mm
+++ b/ios/chrome/browser/ui/location_bar/location_bar_view_controller.mm
@@ -11,6 +11,7 @@
 #import "ios/chrome/browser/ui/commands/load_query_commands.h"
 #import "ios/chrome/browser/ui/fullscreen/fullscreen_animator.h"
 #include "ios/chrome/browser/ui/location_bar/location_bar_steady_view.h"
+#import "ios/chrome/browser/ui/orchestrator/location_bar_offset_provider.h"
 #import "ios/chrome/browser/ui/util/named_guide.h"
 #import "ios/chrome/common/ui_util/constraints_ui_util.h"
 #import "ios/chrome/grit/ios_strings.h"
@@ -63,6 +64,7 @@
 @synthesize trailingButtonState = _trailingButtonState;
 @synthesize hideShareButtonWhileOnIncognitoNTP =
     _hideShareButtonWhileOnIncognitoNTP;
+@synthesize offsetProvider = _offsetProvider;
 
 #pragma mark - public
 
@@ -231,6 +233,69 @@
   self.hideShareButtonWhileOnIncognitoNTP = isNTP;
 }
 
+#pragma mark - LocationBarAnimatee
+
+- (void)offsetEditViewToMatchSteadyView {
+  CGAffineTransform offsetTransform =
+      CGAffineTransformMakeTranslation([self targetOffset], 0);
+  self.editView.transform = offsetTransform;
+}
+
+- (void)resetEditViewOffsetAndOffsetSteadyViewToMatch {
+  self.locationBarSteadyView.transform =
+      CGAffineTransformMakeTranslation(-self.editView.transform.tx, 0);
+  self.editView.transform = CGAffineTransformIdentity;
+}
+
+- (void)offsetSteadyViewToMatchEditView {
+  CGAffineTransform offsetTransform =
+      CGAffineTransformMakeTranslation(-[self targetOffset], 0);
+  self.locationBarSteadyView.transform = offsetTransform;
+}
+
+- (void)resetSteadyViewOffsetAndOffsetEditViewToMatch {
+  self.editView.transform = CGAffineTransformMakeTranslation(
+      -self.locationBarSteadyView.transform.tx, 0);
+  self.locationBarSteadyView.transform = CGAffineTransformIdentity;
+}
+
+- (void)setSteadyViewFaded:(BOOL)hidden {
+  self.locationBarSteadyView.alpha = hidden ? 0 : 1;
+}
+
+- (void)setEditViewFaded:(BOOL)hidden {
+  self.editView.alpha = hidden ? 0 : 1;
+}
+
+- (void)setEditViewHidden:(BOOL)hidden {
+  self.editView.hidden = hidden;
+}
+- (void)setSteadyViewHidden:(BOOL)hidden {
+  self.locationBarSteadyView.hidden = hidden;
+}
+
+- (void)resetTransforms {
+  self.editView.transform = CGAffineTransformIdentity;
+  self.locationBarSteadyView.transform = CGAffineTransformIdentity;
+}
+
+#pragma mark animation helpers
+
+// Computes the target offset for the focus/defocus animation that allows to
+// visually match the position of edit and steady views.
+- (CGFloat)targetOffset {
+  CGFloat offset = [self.offsetProvider
+      xOffsetForString:self.locationBarSteadyView.locationLabel.text];
+
+  CGRect labelRect = [self.view
+      convertRect:self.locationBarSteadyView.locationLabel.frame
+         fromView:self.locationBarSteadyView.locationLabel.superview];
+  CGRect textFieldRect = self.editView.frame;
+
+  CGFloat targetOffset = labelRect.origin.x - textFieldRect.origin.x - offset;
+  return targetOffset;
+}
+
 #pragma mark - private
 
 - (void)locationBarSteadyViewTapped {
diff --git a/ios/chrome/browser/ui/omnibox/BUILD.gn b/ios/chrome/browser/ui/omnibox/BUILD.gn
index caaf302..e566691 100644
--- a/ios/chrome/browser/ui/omnibox/BUILD.gn
+++ b/ios/chrome/browser/ui/omnibox/BUILD.gn
@@ -122,6 +122,7 @@
     "//ios/chrome/browser/ui/fullscreen",
     "//ios/chrome/browser/ui/location_bar:constants",
     "//ios/chrome/browser/ui/omnibox/popup",
+    "//ios/chrome/browser/ui/orchestrator:orchestrator",
     "//ios/chrome/browser/ui/toolbar/buttons",
     "//ios/chrome/browser/ui/toolbar/public",
     "//ios/chrome/browser/ui/toolbar/public:feature_flags",
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_coordinator.h b/ios/chrome/browser/ui/omnibox/omnibox_coordinator.h
index 4146be3..86bac19 100644
--- a/ios/chrome/browser/ui/omnibox/omnibox_coordinator.h
+++ b/ios/chrome/browser/ui/omnibox/omnibox_coordinator.h
@@ -14,6 +14,7 @@
 @class CommandDispatcher;
 @class OmniboxPopupCoordinator;
 @class OmniboxTextFieldIOS;
+@protocol LocationBarOffsetProvider;
 @protocol OmniboxPopupPositioner;
 
 // The coordinator for the omnibox.
@@ -30,6 +31,9 @@
 // coordinator is expected to add it to the responder chain.
 - (UIViewController*)managedViewController;
 
+// Offset provider for location bar animations.
+- (id<LocationBarOffsetProvider>)offsetProvider;
+
 // Start this coordinator. When it starts, it expects to have |textField| and
 // |editController|.
 - (void)start;
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_coordinator.mm b/ios/chrome/browser/ui/omnibox/omnibox_coordinator.mm
index d9ee8a0..5296341 100644
--- a/ios/chrome/browser/ui/omnibox/omnibox_coordinator.mm
+++ b/ios/chrome/browser/ui/omnibox/omnibox_coordinator.mm
@@ -128,13 +128,16 @@
   return coordinator;
 }
 
-#pragma mark - private
-
-// Getter with proper type.
 - (UIViewController*)managedViewController {
   return self.viewController;
 }
 
+- (id<LocationBarOffsetProvider>)offsetProvider {
+  return self.viewController;
+}
+
+#pragma mark - private
+
 // Convenience accessor.
 - (OmniboxTextFieldIOS*)textField {
   return self.viewController.textField;
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_text_field_ios.h b/ios/chrome/browser/ui/omnibox/omnibox_text_field_ios.h
index eb4de1f..421f858 100644
--- a/ios/chrome/browser/ui/omnibox/omnibox_text_field_ios.h
+++ b/ios/chrome/browser/ui/omnibox/omnibox_text_field_ios.h
@@ -95,6 +95,11 @@
                 completionAnimator:(UIViewPropertyAnimator*)completionAnimator;
 - (void)addContractOmniboxAnimations:(UIViewPropertyAnimator*)animator;
 
+// Returns an x offset for a given string. If no such string is found, returns
+// some default offset.
+// Used for focus/defocus animation.
+- (CGFloat)offsetForString:(NSString*)string;
+
 // Initial touch on the Omnibox triggers a "pre-edit" state. The current
 // URL is shown without any insertion point. First character typed replaces
 // the URL. A second touch turns on the insertion point. |preEditStaticLabel|
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_text_field_ios.mm b/ios/chrome/browser/ui/omnibox/omnibox_text_field_ios.mm
index 2b4172e..fdeb4f36 100644
--- a/ios/chrome/browser/ui/omnibox/omnibox_text_field_ios.mm
+++ b/ios/chrome/browser/ui/omnibox/omnibox_text_field_ios.mm
@@ -360,6 +360,27 @@
   }];
 }
 
+#pragma mark - UI Refresh animation public helpers
+
+- (CGFloat)offsetForString:(NSString*)string {
+  // Sometimes |string| is not contained in self.text, for example for
+  // https://en.m.wikipedia.org/foo the |string| might be "en.wikipedia.org" if
+  // the scheme and the "m." trivial subdomain are stripped. In this case,
+  // default to a reasonable prefix string to give a plausible offset.
+  NSString* prefixString = @"https://";
+
+  if ([self.text containsString:string]) {
+    NSRange range = [self.text rangeOfString:string];
+    NSRange prefixRange = NSMakeRange(0, range.location);
+    prefixString = [self.text substringWithRange:prefixRange];
+  }
+
+  return [prefixString
+             sizeWithAttributes:@{NSFontAttributeName : self.currentFont}]
+             .width +
+         self.preEditStaticLabel.frame.origin.x;
+}
+
 #pragma mark pre-edit
 
 // Creates a UILabel based on the current dimension of the text field and
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_view_controller.h b/ios/chrome/browser/ui/omnibox/omnibox_view_controller.h
index 950b8ef..540a6f6 100644
--- a/ios/chrome/browser/ui/omnibox/omnibox_view_controller.h
+++ b/ios/chrome/browser/ui/omnibox/omnibox_view_controller.h
@@ -9,9 +9,11 @@
 
 #import "ios/chrome/browser/ui/omnibox/omnibox_consumer.h"
 #import "ios/chrome/browser/ui/omnibox/omnibox_text_field_ios.h"
+#import "ios/chrome/browser/ui/orchestrator/location_bar_offset_provider.h"
 
 // The view controller managing the omnibox textfield and its container view.
-@interface OmniboxViewController : UIViewController<OmniboxConsumer>
+@interface OmniboxViewController
+    : UIViewController<LocationBarOffsetProvider, OmniboxConsumer>
 
 // The textfield used by this view controller.
 @property(nonatomic, readonly, strong) OmniboxTextFieldIOS* textField;
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_view_controller.mm b/ios/chrome/browser/ui/omnibox/omnibox_view_controller.mm
index 4d85fe2..1be003e 100644
--- a/ios/chrome/browser/ui/omnibox/omnibox_view_controller.mm
+++ b/ios/chrome/browser/ui/omnibox/omnibox_view_controller.mm
@@ -94,6 +94,12 @@
   [self.view setLeadingImage:icon];
 }
 
+#pragma mark - LocationBarOffsetProvider
+
+- (CGFloat)xOffsetForString:(NSString*)string {
+  return [self.textField offsetForString:string];
+}
+
 #pragma mark - private
 
 - (void)updateLeadingImageVisibility {
diff --git a/ios/chrome/browser/ui/orchestrator/BUILD.gn b/ios/chrome/browser/ui/orchestrator/BUILD.gn
index 732d3f0d..fe13e73 100644
--- a/ios/chrome/browser/ui/orchestrator/BUILD.gn
+++ b/ios/chrome/browser/ui/orchestrator/BUILD.gn
@@ -5,6 +5,8 @@
 source_set("orchestrator") {
   configs += [ "//build/config/compiler:enable_arc" ]
   sources = [
+    "location_bar_animatee.h",
+    "location_bar_offset_provider.h",
     "omnibox_focus_orchestrator.h",
     "omnibox_focus_orchestrator.mm",
     "toolbar_animatee.h",
diff --git a/ios/chrome/browser/ui/orchestrator/location_bar_animatee.h b/ios/chrome/browser/ui/orchestrator/location_bar_animatee.h
new file mode 100644
index 0000000..31fdb489
--- /dev/null
+++ b/ios/chrome/browser/ui/orchestrator/location_bar_animatee.h
@@ -0,0 +1,38 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_UI_ORCHESTRATOR_LOCATION_BAR_ANIMATEE_H_
+#define IOS_CHROME_BROWSER_UI_ORCHESTRATOR_LOCATION_BAR_ANIMATEE_H_
+
+#import <Foundation/Foundation.h>
+
+// Protocol defining an interface to trigger changes on the location bar.
+// Calling those methods should not start any animation.
+@protocol LocationBarAnimatee<NSObject>
+
+// Moves the edit view to a position where the text in it visually overlays the
+// text in steady view.
+- (void)offsetEditViewToMatchSteadyView;
+// Call this after calling -offsetEditViewToMatchSteadyView. Moves the edit view
+// to its normal position and offsets the steady view to match the normal edit
+// view position, so that the text in it visually overlaying the text in edit
+// view.
+- (void)resetEditViewOffsetAndOffsetSteadyViewToMatch;
+
+// See comment for -offsetEditViewToMatchSteadyView.
+- (void)offsetSteadyViewToMatchEditView;
+// See comment for -resetEditViewOffsetAndOffsetSteadyViewToMatch.
+- (void)resetSteadyViewOffsetAndOffsetEditViewToMatch;
+
+- (void)setSteadyViewFaded:(BOOL)hidden;
+- (void)setEditViewFaded:(BOOL)hidden;
+- (void)setEditViewHidden:(BOOL)hidden;
+- (void)setSteadyViewHidden:(BOOL)hidden;
+
+// Resets tranforms of edit and steady view. Used for post-animation cleanup.
+- (void)resetTransforms;
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_UI_ORCHESTRATOR_LOCATION_BAR_ANIMATEE_H_
diff --git a/ios/chrome/browser/ui/orchestrator/location_bar_offset_provider.h b/ios/chrome/browser/ui/orchestrator/location_bar_offset_provider.h
new file mode 100644
index 0000000..649f006
--- /dev/null
+++ b/ios/chrome/browser/ui/orchestrator/location_bar_offset_provider.h
@@ -0,0 +1,20 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_UI_ORCHESTRATOR_LOCATION_BAR_OFFSET_PROVIDER_H_
+#define IOS_CHROME_BROWSER_UI_ORCHESTRATOR_LOCATION_BAR_OFFSET_PROVIDER_H_
+
+#import <Foundation/Foundation.h>
+
+// Protocol for vending an x offset for a string.
+@protocol LocationBarOffsetProvider<NSObject>
+
+// Provides an offset for a given string in the callee's coordinates, if any.
+// Returns a default value (based on callee's font) if the |string| is not a
+// substring of the string displayed by callee.
+- (CGFloat)xOffsetForString:(NSString*)string;
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_UI_ORCHESTRATOR_LOCATION_BAR_OFFSET_PROVIDER_H_
diff --git a/ios/chrome/browser/ui/orchestrator/omnibox_focus_orchestrator.h b/ios/chrome/browser/ui/orchestrator/omnibox_focus_orchestrator.h
index 2a31ac0..5a78f880 100644
--- a/ios/chrome/browser/ui/orchestrator/omnibox_focus_orchestrator.h
+++ b/ios/chrome/browser/ui/orchestrator/omnibox_focus_orchestrator.h
@@ -7,6 +7,7 @@
 
 #import <UIKit/UIKit.h>
 
+@protocol LocationBarAnimatee;
 @protocol ToolbarAnimatee;
 
 // Orchestrator for the animation occuring when the omnibox is
@@ -16,6 +17,8 @@
 // Toolbar animatee, orchestrated by this object.
 @property(nonatomic, weak) id<ToolbarAnimatee> toolbarAnimatee;
 
+@property(nonatomic, weak) id<LocationBarAnimatee> locationBarAnimatee;
+
 // Updates the UI elements orchestrated by this object to reflect the
 // |omniboxFocused| state, and the |toolbarExpanded| state, |animated| or not.
 - (void)transitionToStateOmniboxFocused:(BOOL)omniboxFocused
diff --git a/ios/chrome/browser/ui/orchestrator/omnibox_focus_orchestrator.mm b/ios/chrome/browser/ui/orchestrator/omnibox_focus_orchestrator.mm
index 7dd2446..5f60b0d3 100644
--- a/ios/chrome/browser/ui/orchestrator/omnibox_focus_orchestrator.mm
+++ b/ios/chrome/browser/ui/orchestrator/omnibox_focus_orchestrator.mm
@@ -4,6 +4,7 @@
 
 #import "ios/chrome/browser/ui/orchestrator/omnibox_focus_orchestrator.h"
 
+#import "ios/chrome/browser/ui/orchestrator/location_bar_animatee.h"
 #import "ios/chrome/browser/ui/orchestrator/toolbar_animatee.h"
 #import "ios/chrome/common/material_timing.h"
 
@@ -14,20 +15,143 @@
 @implementation OmniboxFocusOrchestrator
 
 @synthesize toolbarAnimatee = _toolbarAnimatee;
+@synthesize locationBarAnimatee = _locationBarAnimatee;
 
 - (void)transitionToStateOmniboxFocused:(BOOL)omniboxFocused
                         toolbarExpanded:(BOOL)toolbarExpanded
                                animated:(BOOL)animated {
-  // TODO(crbug.com/805485): manage the changes in the location bar.
   if (toolbarExpanded) {
     [self updateUIToExpandedState:animated];
   } else {
     [self updateUIToContractedState:animated];
   }
+
+  // Make the rest of the animation happen on the next runloop when this
+  // animation have calculated the final frame for the location bar.
+  // This is necessary because expanding/contracting the toolbar is actually
+  // changing the view layout. Therefore, the expand/contract animations are
+  // actually moving views (through modifying the constraints). At the same time
+  // the focus/defocus animation don't actually modify the view position, the
+  // views remain in place, so it's better to animate them with transforms.
+  // The cleanest way to compute and perform the transform animation together
+  // with a constraint animation seems to be to let the constraint animation
+  // start and compute the final frames, then perform the transform animation.
+  dispatch_async(dispatch_get_main_queue(), ^{
+    if (omniboxFocused) {
+      [self focusOmniboxAnimated:animated];
+    } else {
+      [self defocusOmniboxAnimated:animated];
+    }
+  });
 }
 
 #pragma mark - Private
 
+- (void)focusOmniboxAnimated:(BOOL)animated {
+  // Cleans up after the animation.
+  // The argument is necessary as this is used as |completion| in UIView
+  // animateWithBlock: call.
+  auto cleanup = ^(BOOL __unused complete) {
+    [self.locationBarAnimatee setEditViewHidden:NO];
+    [self.locationBarAnimatee setSteadyViewHidden:YES];
+    [self.locationBarAnimatee resetTransforms];
+  };
+
+  if (animated) {
+    // Prepare for animation.
+    [self.locationBarAnimatee offsetEditViewToMatchSteadyView];
+    // Make edit view transparent, but not hidden.
+    [self.locationBarAnimatee setEditViewHidden:NO];
+    [self.locationBarAnimatee setEditViewFaded:YES];
+
+    CGFloat duration = ios::material::kDuration1;
+
+    [UIView animateWithDuration:duration
+                          delay:0
+                        options:UIViewAnimationCurveEaseInOut
+                     animations:^{
+                       [self.locationBarAnimatee
+                               resetEditViewOffsetAndOffsetSteadyViewToMatch];
+                     }
+                     completion:cleanup];
+
+    // Fading the views happens with a different timing for a better visual
+    // effect. The steady view looks like an ordinary label, and it fades before
+    // the animation is complete. The edit view will be in pre-edit state, so it
+    // looks like selected text. Since the selection is blue, it looks
+    // overwhelming if faded in at the same time as the steady view. So it fades
+    // in faster and later into the animation to look better.
+    [UIView animateWithDuration:duration * 0.8
+                          delay:duration * 0.1
+                        options:UIViewAnimationCurveEaseInOut
+                     animations:^{
+                       [self.locationBarAnimatee setSteadyViewFaded:YES];
+                     }
+                     completion:nil];
+
+    [UIView animateWithDuration:duration * 0.6
+                          delay:duration * 0.4
+                        options:UIViewAnimationCurveEaseInOut
+                     animations:^{
+                       [self.locationBarAnimatee setEditViewFaded:NO];
+                     }
+                     completion:nil];
+  } else {
+    cleanup(YES);
+  }
+}
+
+- (void)defocusOmniboxAnimated:(BOOL)animated {
+  // Cleans up after the animation.
+  // The argument is necessary as this is used as |completion| in UIView
+  // animateWithBlock: call.
+  void (^cleanup)(BOOL _) = ^(BOOL _) {
+    [self.locationBarAnimatee setEditViewHidden:YES];
+    [self.locationBarAnimatee setSteadyViewHidden:NO];
+    [self.locationBarAnimatee resetTransforms];
+  };
+
+  if (animated) {
+    // Prepare for animation.
+    [self.locationBarAnimatee offsetSteadyViewToMatchEditView];
+    // Make steady view transparent, but not hidden.
+    [self.locationBarAnimatee setSteadyViewHidden:NO];
+    [self.locationBarAnimatee setSteadyViewFaded:YES];
+
+    CGFloat duration = ios::material::kDuration1;
+
+    [UIView animateWithDuration:duration
+                          delay:0
+                        options:UIViewAnimationCurveEaseInOut
+                     animations:^{
+                       [self.locationBarAnimatee
+                               resetSteadyViewOffsetAndOffsetEditViewToMatch];
+                     }
+                     completion:cleanup];
+
+    // These timings are explained in a comment in
+    // focusOmniboxAnimated:shouldExpand:.
+    [UIView animateWithDuration:duration * 0.8
+                          delay:duration * 0.1
+                        options:UIViewAnimationCurveEaseInOut
+                     animations:^{
+                       [self.locationBarAnimatee setEditViewFaded:YES];
+                     }
+                     completion:nil];
+
+    [UIView animateWithDuration:duration * 0.6
+                          delay:duration * 0.4
+                        options:UIViewAnimationCurveEaseInOut
+                     animations:^{
+                       [self.locationBarAnimatee setSteadyViewFaded:NO];
+                     }
+                     completion:nil];
+
+  } else {
+    cleanup(YES);
+  }
+}
+
 // Updates the UI elements reflect the toolbar expanded state, |animated| or
 // not.
 - (void)updateUIToExpandedState:(BOOL)animated {
@@ -41,7 +165,7 @@
   };
 
   if (animated) {
-    // Use UIView animatieWithDuration instead of UIViewPropertyAnimator to
+    // Use UIView animateWithDuration instead of UIViewPropertyAnimator to
     // avoid UIKit bug. See https://crbug.com/856155.
     [UIView animateWithDuration:ios::material::kDuration1
                           delay:0
@@ -76,7 +200,7 @@
   };
 
   if (animated) {
-    // Use UIView animatieWithDuration instead of UIViewPropertyAnimator to
+    // Use UIView animateWithDuration instead of UIViewPropertyAnimator to
     // avoid UIKit bug. See https://crbug.com/856155.
     CGFloat totalDuration =
         ios::material::kDuration1 + ios::material::kDuration2;
diff --git a/ios/chrome/browser/ui/tab_grid/grid/grid_cell.mm b/ios/chrome/browser/ui/tab_grid/grid/grid_cell.mm
index 6078c52..5d148b1 100644
--- a/ios/chrome/browser/ui/tab_grid/grid/grid_cell.mm
+++ b/ios/chrome/browser/ui/tab_grid/grid/grid_cell.mm
@@ -15,7 +15,33 @@
 #error "This file requires ARC support."
 #endif
 
+namespace {
+// Frame-based layout utilities for GridTransitionCell.
+// Scales the size of |view|'s frame by |factor| in both height and width. This
+// scaling is done by changing the frame size without changing its origin,
+// unlike a scale transform which scales around the view's center.
+void ScaleView(UIView* view, CGFloat factor) {
+  if (!view)
+    return;
+  CGRect frame = view.frame;
+  frame.size.width *= factor;
+  frame.size.height *= factor;
+  view.frame = frame;
+}
+
+// Positions |view| by setting its frame's origin to |point|.
+void PositionView(UIView* view, CGPoint point) {
+  if (!view)
+    return;
+  CGRect frame = view.frame;
+  frame.origin = point;
+  view.frame = frame;
+}
+}  // namespace
+
 @interface GridCell ()
+// Header height of the cell.
+@property(nonatomic, strong) NSLayoutConstraint* topBarHeight;
 // Visual components of the cell.
 @property(nonatomic, weak) UIView* topBar;
 @property(nonatomic, weak) UIImageView* iconView;
@@ -36,8 +62,9 @@
 @synthesize icon = _icon;
 @synthesize snapshot = _snapshot;
 @synthesize title = _title;
-@synthesize topBar = _topBar;
 // Private properties.
+@synthesize topBarHeight = _topBarHeight;
+@synthesize topBar = _topBar;
 @synthesize iconView = _iconView;
 @synthesize snapshotView = _snapshotView;
 @synthesize titleLabel = _titleLabel;
@@ -74,12 +101,15 @@
     _snapshotView = snapshotView;
     _closeTapTargetButton = closeTapTargetButton;
 
+    _topBarHeight =
+        [topBar.heightAnchor constraintEqualToConstant:kGridCellHeaderHeight];
+
     NSArray* constraints = @[
       [topBar.topAnchor constraintEqualToAnchor:contentView.topAnchor],
       [topBar.leadingAnchor constraintEqualToAnchor:contentView.leadingAnchor],
       [topBar.trailingAnchor
           constraintEqualToAnchor:contentView.trailingAnchor],
-      [topBar.heightAnchor constraintEqualToConstant:kGridCellHeaderHeight],
+      _topBarHeight,
       [snapshotView.topAnchor constraintEqualToAnchor:topBar.bottomAnchor],
       [snapshotView.leadingAnchor
           constraintEqualToAnchor:contentView.leadingAnchor],
@@ -303,7 +333,15 @@
 
 @end
 
-@implementation GridTransitionCell
+@implementation GridTransitionCell {
+  // Previous tab view width, used to scale the tab views.
+  CGFloat _previousTabViewWidth;
+}
+
+// Synthesis of GridToTabTransitionView properties.
+@synthesize topTabView = _topTabView;
+@synthesize mainTabView = _mainTabView;
+@synthesize bottomTabView = _bottomTabView;
 
 + (instancetype)transitionCellFromCell:(GridCell*)cell {
   GridTransitionCell* proxy = [[self alloc] initWithFrame:cell.bounds];
@@ -314,11 +352,10 @@
   proxy.title = cell.title;
   return proxy;
 }
-
-#pragma mark - GridToTabTransitionView
+#pragma mark - GridToTabTransitionView properties.
 
 - (void)setTopCellView:(UIView*)topCellView {
-  // The top cell is the top bar and can't be changed.
+  // The top cell view is |topBar| and can't be changed.
   NOTREACHED();
 }
 
@@ -326,6 +363,37 @@
   return self.topBar;
 }
 
+- (void)setTopTabView:(UIView*)topTabView {
+  DCHECK(!_topTabView) << "topTabView should only be set once.";
+  if (!topTabView.superview)
+    [self.contentView addSubview:topTabView];
+  _topTabView = topTabView;
+}
+
+- (void)setMainCellView:(UIView*)mainCellView {
+  // The main cell view is the snapshot view and can't be changed.
+  NOTREACHED();
+}
+
+- (UIView*)mainCellView {
+  return self.snapshotView;
+}
+
+- (void)setMainTabView:(UIView*)mainTabView {
+  DCHECK(!_mainTabView) << "mainTabView should only be set once.";
+  if (!mainTabView.superview)
+    [self.contentView addSubview:mainTabView];
+  _previousTabViewWidth = mainTabView.frame.size.width;
+  _mainTabView = mainTabView;
+}
+
+- (void)setBottomTabView:(UIView*)bottomTabView {
+  DCHECK(!_bottomTabView) << "bottomTabView should only be set once.";
+  if (!bottomTabView.superview)
+    [self.contentView addSubview:bottomTabView];
+  _bottomTabView = bottomTabView;
+}
+
 - (CGFloat)cornerRadius {
   return self.contentView.layer.cornerRadius;
 }
@@ -334,4 +402,58 @@
   self.contentView.layer.cornerRadius = radius;
 }
 
+#pragma mark - GridToTabTransitionView methods
+
+- (void)positionTabViews {
+  [self scaleTabViews];
+  self.topBarHeight.constant = self.topTabView.frame.size.height;
+  [self setNeedsUpdateConstraints];
+  [self layoutIfNeeded];
+  PositionView(self.topTabView, CGPointMake(0, 0));
+  // Position the main view so it's top-aligned with the main cell view.
+  PositionView(self.mainTabView, self.mainCellView.frame.origin);
+  if (!self.bottomTabView)
+    return;
+
+  // Position the bottom tab view at the bottom.
+  CGFloat yPosition = CGRectGetMaxY(self.contentView.bounds) -
+                      self.bottomTabView.frame.size.height;
+  PositionView(self.bottomTabView, CGPointMake(0, yPosition));
+}
+
+- (void)positionCellViews {
+  [self scaleTabViews];
+  self.topBarHeight.constant = kGridCellHeaderHeight;
+  [self setNeedsUpdateConstraints];
+  [self layoutIfNeeded];
+  CGFloat yOffset = kGridCellHeaderHeight - self.topTabView.frame.size.height;
+  PositionView(self.topTabView, CGPointMake(0, yOffset));
+  // Position the main view so it's top-aligned with the main cell view.
+  PositionView(self.mainTabView, self.mainCellView.frame.origin);
+  if (!self.bottomTabView)
+    return;
+
+  if (self.bottomTabView.frame.origin.y > 0) {
+    // Position the bottom tab so it's equivalently located.
+    CGFloat scale = self.bounds.size.width / _previousTabViewWidth;
+    PositionView(self.bottomTabView,
+                 CGPointMake(0, self.bottomTabView.frame.origin.y * scale));
+  } else {
+    // Position the bottom tab view below the main content view.
+    CGFloat yOffset = CGRectGetMaxY(self.mainCellView.frame);
+    PositionView(self.bottomTabView, CGPointMake(0, yOffset));
+  }
+}
+
+#pragma mark - Private helper methods
+
+// Scales the tab views relative to the current width of the cell.
+- (void)scaleTabViews {
+  CGFloat scale = self.bounds.size.width / _previousTabViewWidth;
+  ScaleView(self.topTabView, scale);
+  ScaleView(self.mainTabView, scale);
+  ScaleView(self.bottomTabView, scale);
+  _previousTabViewWidth = self.mainTabView.frame.size.width;
+}
+
 @end
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm
index b4f39b46..224674f 100644
--- a/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm
+++ b/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm
@@ -4,6 +4,8 @@
 
 #import "ios/chrome/browser/ui/tab_grid/tab_grid_coordinator.h"
 
+#include "base/mac/bundle_locations.h"
+#include "base/mac/foundation_util.h"
 #include "base/metrics/user_metrics.h"
 #include "base/metrics/user_metrics_action.h"
 #include "ios/chrome/browser/chrome_url_constants.h"
@@ -33,6 +35,9 @@
                                  RecentTabsHandsetViewControllerCommand>
 // Superclass property specialized for the class that this coordinator uses.
 @property(nonatomic, weak) TabGridViewController* mainViewController;
+// Pointer to the masking view used to prevent the main view controller from
+// being shown at launch.
+@property(nonatomic, strong) UIView* launchMaskView;
 // Commad dispatcher used while this coordinator's view controller is active.
 // (for compatibility with the TabSwitcher protocol).
 @property(nonatomic, strong) CommandDispatcher* dispatcher;
@@ -64,6 +69,7 @@
 @synthesize regularTabModel = _regularTabModel;
 @synthesize incognitoTabModel = _incognitoTabModel;
 // Private properties.
+@synthesize launchMaskView = _launchMaskView;
 @synthesize dispatcher = _dispatcher;
 @synthesize adaptor = _adaptor;
 @synthesize bvcContainer = _bvcContainer;
@@ -203,6 +209,17 @@
   mainViewController.remoteTabsViewController.loader = self.URLLoader;
   mainViewController.remoteTabsViewController.presentationDelegate = self;
 
+  // Insert the launch screen view in front of this view to hide it until after
+  // launch. This should happen before |mainViewController| is made the window's
+  // root view controller.
+  NSBundle* mainBundle = base::mac::FrameworkBundle();
+  NSArray* topObjects =
+      [mainBundle loadNibNamed:@"LaunchScreen" owner:self options:nil];
+  UIViewController* launchScreenController =
+      base::mac::ObjCCastStrict<UIViewController>([topObjects lastObject]);
+  self.launchMaskView = launchScreenController.view;
+  [mainViewController.view addSubview:self.launchMaskView];
+
   // TODO(crbug.com/850387) : Currently, consumer calls from the mediator
   // prematurely loads the view in |RecentTabsTableViewController|. Fix this so
   // that the view is loaded only by an explicit placement in the view
@@ -296,16 +313,22 @@
   self.bvcContainer.currentBVC = viewController;
   self.bvcContainer.transitioningDelegate = self.transitionHandler;
   BOOL animated = !self.animationsDisabledForTesting;
+  // Never animate if the launch mask is in place.
+  if (self.launchMaskView)
+    animated = NO;
 
-  // Extened |completion| to also signal the tab switcher delegate
+  // Extened |completion| to signal the tab switcher delegate
   // that the animated "tab switcher dismissal" (that is, presenting something
   // on top of the tab switcher) transition has completed.
+  // Finally, the launch mask view should be removed.
   ProceduralBlock extendedCompletion = ^{
     [self.tabSwitcher.delegate
         tabSwitcherDismissTransitionDidEnd:self.tabSwitcher];
     if (completion) {
       completion();
     }
+    [self.launchMaskView removeFromSuperview];
+    self.launchMaskView = nil;
   };
 
   [self.mainViewController presentViewController:self.bvcContainer
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm
index 4a284ca..b997181 100644
--- a/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm
+++ b/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm
@@ -137,6 +137,10 @@
   [self setupTopToolbar];
   [self setupBottomToolbar];
   [self setupFloatingButton];
+
+  // Hide the toolbars and the floating button, so they can fade in the first
+  // time there's a transition into this view controller.
+  [self hideToolbars];
 }
 
 - (void)viewWillAppear:(BOOL)animated {
@@ -702,18 +706,20 @@
       kTabGridCloseAllButtonIdentifier;
 }
 
-// Shows (by setting the alpha to 1.0) the two toolbar views. Suitable for use
-// in animations.
+// Shows (by setting the alpha to 1.0) the two toolbar views and the floating
+// button. Suitable for use in animations.
 - (void)showToolbars {
   self.topToolbar.alpha = 1.0;
   self.bottomToolbar.alpha = 1.0;
+  self.floatingButton.alpha = 1.0;
 }
 
-// Hides (by setting the alpha to 0.0) the two toolbar views. Suitable for use
-// in animations.
+// Hides (by setting the alpha to 0.0) the two toolbar views and the floating
+// button. Suitable for use in animations.
 - (void)hideToolbars {
   self.topToolbar.alpha = 0.0;
   self.bottomToolbar.alpha = 0.0;
+  self.floatingButton.alpha = 0.0;
 }
 
 // Translates the toolbar views offscreen and then animates them back in using
diff --git a/ios/chrome/browser/ui/tab_grid/transitions/grid_to_tab_transition_view.h b/ios/chrome/browser/ui/tab_grid/transitions/grid_to_tab_transition_view.h
index c556d5e..0e2fe39 100644
--- a/ios/chrome/browser/ui/tab_grid/transitions/grid_to_tab_transition_view.h
+++ b/ios/chrome/browser/ui/tab_grid/transitions/grid_to_tab_transition_view.h
@@ -7,18 +7,36 @@
 
 #import <UIKit/UIKit.h>
 
-// A protocol to be adopted by a view that will be provided for the transition
-// animation. This view will need to be animated between 'cell' and 'tab'
-// states, and will need to have a number of properties available for that
-// purpose.
+// An collection of properties and methods a view must support in order to be
+// used to animate the transition between a grid cell and a browser tab.
 @protocol GridToTabTransitionView
 
 // The subview at the top of the view in 'cell' state.
 @property(nonatomic, strong) UIView* topCellView;
 
+// The subview at the top of the view in 'tab' state.
+@property(nonatomic, strong) UIView* topTabView;
+
+// The subview containing the main content in 'cell' state.
+@property(nonatomic, strong) UIView* mainCellView;
+
+// The subview containing the main content in 'tab' state.
+@property(nonatomic, strong) UIView* mainTabView;
+
+// The subview at the bottom of the view in 'tab' state.
+@property(nonatomic, strong) UIView* bottomTabView;
+
 // The corner radius of the view.
 @property(nonatomic) CGFloat cornerRadius;
 
+// Tells the view to scale and position its subviews for the "tab" layout. This
+// must be able to be called inside an animation block.
+- (void)positionTabViews;
+
+// Tells the view to scale and position its subviews for the "cell" layout. This
+// must be able to be called inside an animation block.
+- (void)positionCellViews;
+
 @end
 
 #endif  // IOS_CHROME_BROWSER_UI_TAB_GRID_TRANSITIONS_GRID_TO_TAB_TRANSITION_VIEW_H_
diff --git a/ios/chrome/browser/ui/tab_grid/transitions/grid_to_visible_tab_animator.mm b/ios/chrome/browser/ui/tab_grid/transitions/grid_to_visible_tab_animator.mm
index 630e6460..00b3d68 100644
--- a/ios/chrome/browser/ui/tab_grid/transitions/grid_to_visible_tab_animator.mm
+++ b/ios/chrome/browser/ui/tab_grid/transitions/grid_to_visible_tab_animator.mm
@@ -85,8 +85,12 @@
   CGRect finalRect =
       [NamedGuide guideWithName:kContentAreaGuide view:viewWithNamedGuides]
           .layoutFrame;
-  layout.expandedRect =
-      [proxyContainer convertRect:finalRect fromView:viewWithNamedGuides];
+
+  [layout.activeItem populateWithSnapshotsFromView:viewWithNamedGuides
+                                        middleRect:finalRect];
+
+  layout.expandedRect = [proxyContainer convertRect:viewWithNamedGuides.frame
+                                           fromView:presentedView];
 
   NSTimeInterval duration = [self transitionDuration:transitionContext];
   // Create the animation view and insert it.
diff --git a/ios/chrome/browser/ui/tab_grid/transitions/grid_transition_animation.mm b/ios/chrome/browser/ui/tab_grid/transitions/grid_transition_animation.mm
index 826ae52..92f5a505 100644
--- a/ios/chrome/browser/ui/tab_grid/transitions/grid_transition_animation.mm
+++ b/ios/chrome/browser/ui/tab_grid/transitions/grid_transition_animation.mm
@@ -90,7 +90,7 @@
 #pragma mark - Private methods
 
 - (void)buildContractingAnimations {
-  // The transition is structured as two or four separate animations. They are
+  // The transition is structured as three or five separate animations. They are
   // timed based on various sub-durations and delays which are expressed as
   // fractions of the overall animation duration.
   CGFloat partialDuration = 0.6;
@@ -100,11 +100,11 @@
 
   // If there's only one cell, the animation has two parts.
   //   (A) Zooming the active cell into position.
-  //   (B) Fading in the active cell's auxilliary view.
+  //   (B) Crossfading from the tab to cell top view.
   //   (C) Rounding the corners of the active cell.
   //
   //  {0%}------------------[A]----------{60%}
-  //                 {40%}--[B]---------------{70%}
+  //                                {50%}---[B]---{80%}
   //  {0%}---[C]---{30%}
 
   // If there's more than once cell, the animation adds two more parts:
@@ -113,16 +113,24 @@
   // The overall timing is as follows:
   //
   //  {0%}------------------[A]----------{60%}
-  //                 {40%}--[B]---------------{70%}
+  //                                {50%}---[B]---{80%}
   //  {0%}---[C]---{30%}
-  //           {20%}--[D]-------------------------{100%}
-  //           {20%}--[E]----------------------{80%}
+  //           {20%}--[D]-----------------------------{100%}
+  //           {20%}--[E]-------------------------{80%}
   //
   // All animations are timed ease-in (so more motion happens later), except
-  // for C which is relatively small in space and short in duration; it has
-  // linear timing so it doesn't seem instantaneous.
+  // for B and C. B is a crossfade timed ease in/out, and C is relatively small
+  // in space and short in duration; it has linear timing so it doesn't seem
+  // instantaneous.
   // (Changing the timing constants above will change the timing % values)
 
+  UIView<GridToTabTransitionView>* activeCell = self.layout.activeItem.cell;
+  // The final cell snapshot exactly matches the main tab view of the cell, so
+  // it can have an alpha of 0 for the whole animation.
+  activeCell.mainTabView.alpha = 0.0;
+  // The final cell header starts at 0 alpha and is cross-faded in.
+  activeCell.topCellView.alpha = 0.0;
+
   // A: Zoom the active cell into position.
   auto zoomActiveCellAnimation = ^{
     [self positionAndScaleActiveItemInGrid];
@@ -137,17 +145,17 @@
             animations:zoomActiveCellKeyframeAnimation];
   [self.animations addAnimator:zoomActiveCell];
 
-  // B: Fade in the active cell's auxillary view
-  UIView* auxillaryView = self.layout.activeItem.cell.topCellView;
+  // B: Fade in the active cell top cell view, fade out the active cell's
+  // top tab view.
   auto fadeInAuxillaryKeyframeAnimation =
-      [self keyframeAnimationWithRelativeStart:delay
-                              relativeDuration:briefDuration
-                                    animations:^{
-                                      auxillaryView.alpha = 1.0;
-                                    }];
+      [self keyframeAnimationFadingView:activeCell.topTabView
+                          throughToView:activeCell.topCellView
+                          relativeStart:0.5
+                       relativeDuration:briefDuration];
+
   UIViewPropertyAnimator* fadeInAuxillary = [[UIViewPropertyAnimator alloc]
       initWithDuration:self.duration
-                 curve:UIViewAnimationCurveEaseIn
+                 curve:UIViewAnimationCurveEaseInOut
             animations:fadeInAuxillaryKeyframeAnimation];
   [self.animations addAnimator:fadeInAuxillary];
 
@@ -207,36 +215,53 @@
 }
 
 - (void)buildExpandingAnimations {
-  // The transition is structured as two or four separate animations. They are
+  // The transition is structured as four or six separate animations. They are
   // timed based on two sub-durations which are expressed as fractions of the
   // overall animation duration.
   CGFloat partialDuration = 0.66;
-  CGFloat briefDuration = 0.23;
+  CGFloat briefDuration = 0.3;
+  CGFloat veryBriefDuration = 0.2;
+  CGFloat delay = (1.0 - veryBriefDuration) / 2.0;
 
   // If there's only one cell, the animation has three parts:
   //   (A) Zooming the active cell out into the expanded position.
-  //   (B) Fading out the active cell's auxilliary view.
+  //   (B) Crossfading the active cell's top views.
   //   (C) Squaring the corners of the active cell.
+  //   (D) Fading out the main cell view and fading in the main tab view.
   // These parts are timed over |duration| like this:
   //
   //  {0%}--[A]-----------------------------------{100%}
-  //  {0%}--[B]--{23%}
-  //                                {77%}---[C]---{100%}
+  //  {0%}--[B]---{30%}
+  //                               {70%}----[C]---{100%}
+  //                   {40%}-[D]-{60%}
 
   // If there's more than once cell, the animation adds:
-  //   (C) Scaling the inactive cells to 95%
-  //   (D) Fading out the inactive cells.
+  //   (E) Scaling the inactive cells to 95%
+  //   (F) Fading out the inactive cells.
   // The overall timing is as follows:
   //
   //  {0%}--[A]-----------------------------------{100%}
-  //  {0%}--[B]--{23%}
-  //                                {77%}---[C]---{100%}
-  //  {0%}--[D]-----------------------------------{100%}
-  //  {0%}--[E]-----------------{66%}
+  //  {0%}--[B]---{30%}
+  //                               {70%}----[C]---{100%}
+  //                   {40%}-[D]-{60%}
+  //  {0%}--[E]-----------------------------------{100%}
+  //  {0%}--[F]-------------------{66%}
   //
   // All animations are timed ease-out (so more motion happens sooner), except
-  // for C which is relatively small in space and short in duration; it has
-  // linear timing so it doesn't seem instantaneous.
+  // for B, C and D. B is a crossfade and eases in/out. C and D are relatively
+  // short in duration; they have linear timing so they doesn't seem
+  // instantaneous, and D is also linear so that identical views animate
+  // smoothly.
+  //
+  // Animation D is necessary because the cell content and the tab content may
+  // no longer match in aspect ratio; a quick cross-fade in mid-transition
+  // prevents an abrupt jump when the transition ends and the "real" tab content
+  // is shown.
+
+  UIView<GridToTabTransitionView>* activeCell = self.layout.activeItem.cell;
+  // The top and main tab views start at zero alpha but are crossfaded in.
+  activeCell.mainTabView.alpha = 0.0;
+  activeCell.topTabView.alpha = 0.0;
 
   // A: Zoom the active cell into position.
   UIViewPropertyAnimator* zoomActiveCell = [[UIViewPropertyAnimator alloc]
@@ -247,17 +272,15 @@
             }];
   [self.animations addAnimator:zoomActiveCell];
 
-  // B: Fade out the active cell's auxillary view.
-  UIView* auxillaryView = self.layout.activeItem.cell.topCellView;
+  // B: Crossfade the top views.
   auto fadeOutAuxilliaryAnimation =
-      [self keyframeAnimationWithRelativeStart:0
-                              relativeDuration:briefDuration
-                                    animations:^{
-                                      auxillaryView.alpha = 0.0;
-                                    }];
+      [self keyframeAnimationFadingView:activeCell.topCellView
+                          throughToView:activeCell.topTabView
+                          relativeStart:0
+                       relativeDuration:briefDuration];
   UIViewPropertyAnimator* fadeOutAuxilliary = [[UIViewPropertyAnimator alloc]
       initWithDuration:self.duration
-                 curve:UIViewAnimationCurveEaseOut
+                 curve:UIViewAnimationCurveEaseInOut
             animations:fadeOutAuxilliaryAnimation];
   [self.animations addAnimator:fadeOutAuxilliary];
 
@@ -276,12 +299,31 @@
             animations:squareCornersKeyframeAnimation];
   [self.animations addAnimator:squareCorners];
 
+  // D: crossfade the main cell content.
+  // Two notes on this transition. (1) In cases where the cell and tab views are
+  // the same, having both alphas change at the same time means the overall
+  // transition is seamless. (2) using a linear animation curve means that the
+  // sum of the opacities is contstant though the animation, which will help it
+  // seem less abrupt by keeping a relatively constant brightness.
+  auto crossfadeContentAnimation =
+      [self keyframeAnimationWithRelativeStart:delay
+                              relativeDuration:veryBriefDuration
+                                    animations:^{
+                                      activeCell.mainCellView.alpha = 0;
+                                      activeCell.mainTabView.alpha = 1.0;
+                                    }];
+  UIViewPropertyAnimator* crossfadeContent = [[UIViewPropertyAnimator alloc]
+      initWithDuration:self.duration
+                 curve:UIViewAnimationCurveLinear
+            animations:crossfadeContentAnimation];
+  [self.animations addAnimator:crossfadeContent];
+
   // If there's only a single cell, that's all.
   if (self.layout.inactiveItems.count == 0)
     return;
 
   // Additional animations for multiple cells.
-  // D: Scale down inactive cells.
+  // E: Scale down inactive cells.
   auto scaleDownCellsAnimation = ^{
     for (GridTransitionItem* item in self.layout.inactiveItems) {
       item.cell.transform = CGAffineTransformScale(
@@ -294,7 +336,7 @@
             animations:scaleDownCellsAnimation];
   [self.animations addAnimator:scaleDownCells];
 
-  // E: Fade out inactive cells.
+  // F: Fade out inactive cells.
   auto fadeOutCellsAnimation = ^{
     for (GridTransitionItem* item in self.layout.inactiveItems) {
       item.cell.alpha = 0.0;
@@ -329,18 +371,8 @@
 // radius and a 0% opacity auxilliary view.
 - (void)positionExpandedActiveItem {
   UIView<GridToTabTransitionView>* cell = self.layout.activeItem.cell;
-  // Ensure that the cell's subviews are correctly positioned.
-  [cell layoutIfNeeded];
-  // Position the cell frame so so that the area below the aux view matches the
-  // expanded rect.
-  // Easiest way to do this is to set the frame to the expanded rect and then
-  // add height to it to include the aux view height.
-  CGFloat auxHeight = cell.topCellView.frame.size.height;
-  CGRect cellFrame = self.layout.expandedRect;
-  cellFrame.size.height += auxHeight;
-  cellFrame.origin.y -= auxHeight;
-  cell.frame = cellFrame;
-  cell.topCellView.alpha = 0.0;
+  cell.frame = self.layout.expandedRect;
+  [cell positionTabViews];
 }
 
 // Positions all of the inactive items in their grid positions.
@@ -358,12 +390,13 @@
 // Positions the active item in the regular grid position with its final
 // corner radius.
 - (void)positionAndScaleActiveItemInGrid {
-  UIView* cell = self.layout.activeItem.cell;
+  UIView<GridToTabTransitionView>* cell = self.layout.activeItem.cell;
   cell.transform = CGAffineTransformIdentity;
   CGRect frame = cell.frame;
   frame.size = self.layout.activeItem.size;
   cell.frame = frame;
   [self positionItemInGrid:self.layout.activeItem];
+  [cell positionCellViews];
 }
 
 // Prepares all of the items for an expansion anumation.
@@ -372,6 +405,7 @@
     [self positionItemInGrid:item];
   }
   [self positionItemInGrid:self.layout.activeItem];
+  [self.layout.activeItem.cell positionCellViews];
   [self positionItemInGrid:self.layout.selectionItem];
 }
 
@@ -404,4 +438,38 @@
   };
 }
 
+// Returns a cross-fade keyframe animation between two views.
+// |startView| should have an alpha of 1; |endView| should have an alpha of 0.
+// |start| and |duration| are in the [0.0]-[1.0] interval and represent timing
+// relative to |self.duration|.
+// The animation returned by this method will fade |startView| to 0 over the
+// first half of |duration|, and then fade |endView| to 1.0 over the second
+// half, preventing any blurred frames showing both views. For best results, the
+// animation curev should be EaseInEaseOut.
+- (void (^)(void))keyframeAnimationFadingView:(UIView*)startView
+                                throughToView:(UIView*)endView
+                                relativeStart:(double)start
+                             relativeDuration:(double)duration {
+  CGFloat halfDuration = duration / 2;
+  auto keyframes = ^{
+    [UIView addKeyframeWithRelativeStartTime:start
+                            relativeDuration:halfDuration
+                                  animations:^{
+                                    startView.alpha = 0.0;
+                                  }];
+    [UIView addKeyframeWithRelativeStartTime:start + halfDuration
+                            relativeDuration:halfDuration
+                                  animations:^{
+                                    endView.alpha = 1.0;
+                                  }];
+  };
+  return ^{
+    [UIView animateKeyframesWithDuration:self.duration
+                                   delay:0
+                                 options:UIViewAnimationOptionLayoutSubviews
+                              animations:keyframes
+                              completion:nil];
+  };
+}
+
 @end
diff --git a/ios/chrome/browser/ui/tab_grid/transitions/grid_transition_layout.h b/ios/chrome/browser/ui/tab_grid/transitions/grid_transition_layout.h
index 1306473..c596ca8 100644
--- a/ios/chrome/browser/ui/tab_grid/transitions/grid_transition_layout.h
+++ b/ios/chrome/browser/ui/tab_grid/transitions/grid_transition_layout.h
@@ -76,6 +76,11 @@
                       center:(CGPoint)center
                         size:(CGSize)size;
 
+// Populate the |cell| view of the reciever by extracting snapshots from |view|,
+// using |rect| to define (in |view|'s coordinates) the main tab view, with any
+// space above and below |rect| being the top and bottom tab views.
+- (void)populateWithSnapshotsFromView:(UIView*)view middleRect:(CGRect)rect;
+
 @end
 
 #endif  // IOS_CHROME_BROWSER_UI_TAB_GRID_TRANSITIONS_GRID_TRANSITION_LAYOUT_H_
diff --git a/ios/chrome/browser/ui/tab_grid/transitions/grid_transition_layout.mm b/ios/chrome/browser/ui/tab_grid/transitions/grid_transition_layout.mm
index 12a452a..eb036dc 100644
--- a/ios/chrome/browser/ui/tab_grid/transitions/grid_transition_layout.mm
+++ b/ios/chrome/browser/ui/tab_grid/transitions/grid_transition_layout.mm
@@ -4,6 +4,8 @@
 
 #import "ios/chrome/browser/ui/tab_grid/transitions/grid_transition_layout.h"
 
+#import "ios/chrome/browser/ui/tab_grid/transitions/grid_to_tab_transition_view.h"
+
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
 #endif
@@ -71,4 +73,32 @@
   return item;
 }
 
+- (void)populateWithSnapshotsFromView:(UIView*)view middleRect:(CGRect)rect {
+  self.cell.mainTabView = [view resizableSnapshotViewFromRect:rect
+                                           afterScreenUpdates:YES
+                                                withCapInsets:UIEdgeInsetsZero];
+  CGSize viewSize = view.bounds.size;
+  if (rect.origin.y > 0) {
+    // |rect| starts below the top of |view|, so section off the top part of
+    // |view|.
+    CGRect topRect = CGRectMake(0, 0, viewSize.width, rect.origin.y);
+    self.cell.topTabView =
+        [view resizableSnapshotViewFromRect:topRect
+                         afterScreenUpdates:YES
+                              withCapInsets:UIEdgeInsetsZero];
+  }
+  CGFloat middleRectBottom = CGRectGetMaxY(rect);
+  if (middleRectBottom < viewSize.height) {
+    // |rect| ends above the bottom of |view|, so section off the bottom part of
+    // |view|.
+    CGFloat bottomHeight = viewSize.height - middleRectBottom;
+    CGRect bottomRect =
+        CGRectMake(0, middleRectBottom, viewSize.width, bottomHeight);
+    self.cell.bottomTabView =
+        [view resizableSnapshotViewFromRect:bottomRect
+                         afterScreenUpdates:YES
+                              withCapInsets:UIEdgeInsetsZero];
+  }
+}
+
 @end
diff --git a/ios/chrome/browser/ui/tab_grid/transitions/reduced_motion_animator.mm b/ios/chrome/browser/ui/tab_grid/transitions/reduced_motion_animator.mm
index 438d170..9a6e1fd 100644
--- a/ios/chrome/browser/ui/tab_grid/transitions/reduced_motion_animator.mm
+++ b/ios/chrome/browser/ui/tab_grid/transitions/reduced_motion_animator.mm
@@ -49,25 +49,34 @@
   UIView* animatingView;
   CGFloat finalAnimatingViewAlpha;
   CGAffineTransform finalAnimatingViewTransform;
+  CGFloat finalAnimatingCornerRadius;
 
   if (self.presenting) {
     // If presenting, the appearing view (the tab view) animates in from 0%
-    // opacity and an 80% scale transform.
+    // opacity, 75% scale transform, and a 13px corner radius
     animatingView = appearingView;
     finalAnimatingViewAlpha = animatingView.alpha;
     animatingView.alpha = 0;
     finalAnimatingViewTransform = animatingView.transform;
     animatingView.transform =
-        CGAffineTransformScale(finalAnimatingViewTransform, 0.8, 0.8);
+        CGAffineTransformScale(finalAnimatingViewTransform, 0.75, 0.75);
+    finalAnimatingCornerRadius = 0;
+    animatingView.layer.cornerRadius = 26.0;
   } else {
     // If dismissing, the disappearing view (the tab view) animates out
-    // to 0% opacity and 80% scale.
+    // to 0% opacity, 75% scale, and 13px corner radius.
     animatingView = disappearingView;
     finalAnimatingViewAlpha = 0;
     finalAnimatingViewTransform =
-        CGAffineTransformScale(animatingView.transform, 0.8, 0.8);
+        CGAffineTransformScale(animatingView.transform, 0.75, 0.75);
+    finalAnimatingCornerRadius = 26.0;
   }
 
+  // Set clipsToBounds on the animating view so its corner radius will look
+  // right.
+  BOOL oldClipsToBounds = animatingView.clipsToBounds;
+  animatingView.clipsToBounds = YES;
+
   // Animate the animating view to final properties, then clean up by removing
   // the disappearing view.
   [UIView animateWithDuration:[self transitionDuration:transitionContext]
@@ -76,8 +85,11 @@
       animations:^{
         animatingView.alpha = finalAnimatingViewAlpha;
         animatingView.transform = finalAnimatingViewTransform;
+        animatingView.layer.cornerRadius = finalAnimatingCornerRadius;
       }
       completion:^(BOOL finished) {
+        // Restore clipping state.
+        animatingView.clipsToBounds = oldClipsToBounds;
         // If the transition was cancelled, remove the disappearing view.
         // If not, remove the appearing view.
         if (transitionContext.transitionWasCancelled) {
diff --git a/ios/chrome/browser/ui/tab_grid/transitions/tab_to_grid_animator.mm b/ios/chrome/browser/ui/tab_grid/transitions/tab_to_grid_animator.mm
index 6f440bf..f27be999 100644
--- a/ios/chrome/browser/ui/tab_grid/transitions/tab_to_grid_animator.mm
+++ b/ios/chrome/browser/ui/tab_grid/transitions/tab_to_grid_animator.mm
@@ -87,8 +87,12 @@
   CGRect initialRect =
       [NamedGuide guideWithName:kContentAreaGuide view:viewWithNamedGuides]
           .layoutFrame;
-  layout.expandedRect =
-      [proxyContainer convertRect:initialRect fromView:viewWithNamedGuides];
+
+  [layout.activeItem populateWithSnapshotsFromView:viewWithNamedGuides
+                                        middleRect:initialRect];
+
+  layout.expandedRect = [proxyContainer convertRect:viewWithNamedGuides.frame
+                                           fromView:dismissingView];
 
   NSTimeInterval duration = [self transitionDuration:transitionContext];
   // Create the animation view and insert it.
diff --git a/ios/chrome/browser/ui/toolbar/adaptive/primary_toolbar_coordinator.mm b/ios/chrome/browser/ui/toolbar/adaptive/primary_toolbar_coordinator.mm
index ae6a658..d6159c73 100644
--- a/ios/chrome/browser/ui/toolbar/adaptive/primary_toolbar_coordinator.mm
+++ b/ios/chrome/browser/ui/toolbar/adaptive/primary_toolbar_coordinator.mm
@@ -79,6 +79,11 @@
 
   [self setUpLocationBar];
   self.viewController.locationBarView = self.locationBarCoordinator.view;
+  if ([self.locationBarCoordinator
+          respondsToSelector:@selector(locationBarAnimatee)]) {
+    self.orchestrator.locationBarAnimatee =
+        [self.locationBarCoordinator locationBarAnimatee];
+  }
   [super start];
 
   _fullscreenObserver =
diff --git a/ios/web_view/test/BUILD.gn b/ios/web_view/test/BUILD.gn
index d87efc4..3e646ac6 100644
--- a/ios/web_view/test/BUILD.gn
+++ b/ios/web_view/test/BUILD.gn
@@ -13,6 +13,7 @@
     "web_view_autofill_inttest.mm",
     "web_view_int_test.h",
     "web_view_int_test.mm",
+    "web_view_inttest.mm",
     "web_view_kvo_inttest.mm",
     "web_view_restorable_state_inttest.mm",
     "web_view_script_command_inttest.mm",
diff --git a/ios/web_view/test/web_view_autofill_inttest.mm b/ios/web_view/test/web_view_autofill_inttest.mm
index be8cea4..e9537a2 100644
--- a/ios/web_view/test/web_view_autofill_inttest.mm
+++ b/ios/web_view/test/web_view_autofill_inttest.mm
@@ -11,6 +11,7 @@
 #import "ios/web_view/test/web_view_int_test.h"
 #import "ios/web_view/test/web_view_test_util.h"
 #import "net/base/mac/url_conversions.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
 #include "testing/gtest_mac.h"
 #import "third_party/ocmock/OCMock/OCMock.h"
 #include "url/gurl.h"
@@ -97,6 +98,7 @@
 
 // Tests that CWVAutofillControllerDelegate receives callbacks.
 TEST_F(WebViewAutofillTest, TestDelegateCallbacks) {
+  ASSERT_TRUE(test_server_->Start());
   ASSERT_TRUE(LoadTestPage());
   ASSERT_TRUE(SetFormFieldValue(kTestFieldValue));
 
@@ -166,6 +168,7 @@
 
 // Tests that CWVAutofillController can fetch, fill, and clear suggestions.
 TEST_F(WebViewAutofillTest, TestSuggestionFetchFillClear) {
+  ASSERT_TRUE(test_server_->Start());
   ASSERT_TRUE(LoadTestPage());
   ASSERT_TRUE(SetFormFieldValue(kTestFieldValue));
   ASSERT_TRUE(SubmitForm());
@@ -218,6 +221,7 @@
 
 // Tests that CWVAutofillController can remove a suggestion.
 TEST_F(WebViewAutofillTest, TestSuggestionFetchRemoveFetch) {
+  ASSERT_TRUE(test_server_->Start());
   ASSERT_TRUE(LoadTestPage());
   ASSERT_TRUE(SetFormFieldValue(kTestFieldValue));
   ASSERT_TRUE(SubmitForm());
diff --git a/ios/web_view/test/web_view_int_test.h b/ios/web_view/test/web_view_int_test.h
index 580f7b5c..39c9e68 100644
--- a/ios/web_view/test/web_view_int_test.h
+++ b/ios/web_view/test/web_view_int_test.h
@@ -34,19 +34,22 @@
   ~WebViewIntTest() override;
 
   // Returns URL to an html page with title set to |title|.
+  //
+  // Call ASSERT_TRUE(test_server_->Start()) before accessing the returned URL.
   GURL GetUrlForPageWithTitle(const std::string& title);
 
   // Returns URL to an html page with |html| within page's body tags.
+  //
+  // Call ASSERT_TRUE(test_server_->Start()) before accessing the returned URL.
   GURL GetUrlForPageWithHtmlBody(const std::string& html);
 
   // Returns URL to an html page with title set to |title| and |body| within
   // the page's body tags.
+  //
+  // Call ASSERT_TRUE(test_server_->Start()) before accessing the returned URL.
   GURL GetUrlForPageWithTitleAndBody(const std::string& title,
                                      const std::string& body);
 
-  // PlatformTest methods.
-  void SetUp() override;
-
   // CWVWebView created with default configuration and frame equal to screen
   // bounds.
   CWVWebView* web_view_;
diff --git a/ios/web_view/test/web_view_int_test.mm b/ios/web_view/test/web_view_int_test.mm
index e1bf3a01..59a7e194c 100644
--- a/ios/web_view/test/web_view_int_test.mm
+++ b/ios/web_view/test/web_view_int_test.mm
@@ -105,11 +105,6 @@
 
 WebViewIntTest::~WebViewIntTest() = default;
 
-void WebViewIntTest::SetUp() {
-  PlatformTest::SetUp();
-  ASSERT_TRUE(test_server_->Start());
-}
-
 GURL WebViewIntTest::GetUrlForPageWithTitle(const std::string& title) {
   return GetUrlForPageWithTitleAndBody(title, std::string());
 }
diff --git a/ios/web_view/test/web_view_inttest.mm b/ios/web_view/test/web_view_inttest.mm
new file mode 100644
index 0000000..8d56fca
--- /dev/null
+++ b/ios/web_view/test/web_view_inttest.mm
@@ -0,0 +1,65 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import <ChromeWebView/ChromeWebView.h>
+#import <Foundation/Foundation.h>
+
+#import "ios/web_view/test/web_view_int_test.h"
+#import "ios/web_view/test/web_view_test_util.h"
+#import "net/base/mac/url_conversions.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "net/test/embedded_test_server/http_request.h"
+#include "net/test/embedded_test_server/http_response.h"
+#include "testing/gtest_mac.h"
+#include "url/gurl.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+namespace ios_web_view {
+
+// Tests public methods in CWVWebView.
+class WebViewTest : public ios_web_view::WebViewIntTest {
+ public:
+  std::unique_ptr<net::test_server::HttpResponse> TestRequestHandler(
+      const net::test_server::HttpRequest& request) {
+    last_request_ = request;
+    return nullptr;
+  }
+
+  net::test_server::HttpRequest last_request_;
+};
+
+// Tests +[CWVWebView setUserAgentProduct] and +[CWVWebView userAgentProduct].
+TEST_F(WebViewTest, UserAgentProduct) {
+  // Registers a custom handler to capture HTTP headers.
+  // /echoheader?User-Agent provided by EmbeddedTestServer cannot be used here
+  // because it returns content with type text/plain, but we cannot extract the
+  // content using test::WaitForWebViewContainingTextOrTimeout() because
+  // JavaScript cannot be executed on text/plain content.
+  test_server_->RegisterRequestHandler(base::BindRepeating(
+      &WebViewTest::TestRequestHandler, base::Unretained(this)));
+  ASSERT_TRUE(test_server_->Start());
+
+  [CWVWebView setUserAgentProduct:@"MyUserAgentProduct"];
+  ASSERT_NSEQ(@"MyUserAgentProduct", [CWVWebView userAgentProduct]);
+
+  // Cannot use existing |web_view_| here because the change above may only
+  // affect web views created after the change.
+  CWVWebView* web_view = test::CreateWebView();
+  GURL url = test_server_->GetURL("/");
+  ASSERT_TRUE(test::LoadUrl(web_view, net::NSURLWithGURL(url)));
+
+  // Tests that the web view has sent User-Agent HTTP header with the specified
+  // product name.
+  auto user_agent_it = last_request_.headers.find("User-Agent");
+  ASSERT_NE(last_request_.headers.end(), user_agent_it);
+  EXPECT_NE(std::string::npos,
+            user_agent_it->second.find("MyUserAgentProduct"));
+}
+
+// TODO(crbug.com/862537): Write more tests.
+
+}  // namespace ios_web_view
diff --git a/ios/web_view/test/web_view_kvo_inttest.mm b/ios/web_view/test/web_view_kvo_inttest.mm
index 76eaf609..645f42b 100644
--- a/ios/web_view/test/web_view_kvo_inttest.mm
+++ b/ios/web_view/test/web_view_kvo_inttest.mm
@@ -11,6 +11,7 @@
 #import "ios/web_view/test/web_view_int_test.h"
 #import "ios/web_view/test/web_view_test_util.h"
 #import "net/base/mac/url_conversions.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
 #include "testing/gtest_mac.h"
 #include "url/gurl.h"
 
@@ -26,6 +27,8 @@
 
 // Tests that CWVWebView correctly reports |canGoBack| and |canGoForward| state.
 TEST_F(WebViewKvoTest, CanGoBackForward) {
+  ASSERT_TRUE(test_server_->Start());
+
   Observer* back_observer = [[Observer alloc] init];
   [back_observer setObservedObject:web_view_ keyPath:@"canGoBack"];
 
@@ -89,6 +92,8 @@
 
 // Tests that CWVWebView correctly reports current |title|.
 TEST_F(WebViewKvoTest, Title) {
+  ASSERT_TRUE(test_server_->Start());
+
   Observer* observer = [[Observer alloc] init];
   [observer setObservedObject:web_view_ keyPath:@"title"];
 
@@ -120,6 +125,8 @@
 
 // Tests that CWVWebView correctly reports |isLoading| value.
 TEST_F(WebViewKvoTest, Loading) {
+  ASSERT_TRUE(test_server_->Start());
+
   Observer* observer = [[Observer alloc] init];
   [observer setObservedObject:web_view_ keyPath:@"loading"];
 
@@ -150,6 +157,8 @@
 
 // Tests that CWVWebView correctly reports |visibleURL| and |lastCommittedURL|.
 TEST_F(WebViewKvoTest, URLs) {
+  ASSERT_TRUE(test_server_->Start());
+
   Observer* last_committed_url_observer = [[Observer alloc] init];
   [last_committed_url_observer setObservedObject:web_view_
                                          keyPath:@"lastCommittedURL"];
diff --git a/ios/web_view/test/web_view_script_command_inttest.mm b/ios/web_view/test/web_view_script_command_inttest.mm
index 153f840c..97322319 100644
--- a/ios/web_view/test/web_view_script_command_inttest.mm
+++ b/ios/web_view/test/web_view_script_command_inttest.mm
@@ -9,6 +9,7 @@
 #import "ios/web_view/test/web_view_int_test.h"
 #import "ios/web_view/test/web_view_test_util.h"
 #import "net/base/mac/url_conversions.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
 #include "testing/gtest_mac.h"
 #include "url/gurl.h"
 
@@ -47,6 +48,7 @@
 // Tests that a handler added by -[CWVWebView
 // addScriptCommandHandler:commandPrefix] is invoked by JavaScript.
 TEST_F(WebViewScriptCommandTest, TestScriptCommand) {
+  ASSERT_TRUE(test_server_->Start());
   CWVFakeScriptCommandHandler* handler =
       [[CWVFakeScriptCommandHandler alloc] init];
   [web_view_ addScriptCommandHandler:handler commandPrefix:@"test"];
@@ -83,6 +85,7 @@
 // Tests that added script commands are still valid after state restoration.
 // Tests the same thing as TestScriptCommand() after state restoration.
 TEST_F(WebViewScriptCommandTest, TestScriptCommandAfterStateRestoration) {
+  ASSERT_TRUE(test_server_->Start());
   CWVFakeScriptCommandHandler* handler =
       [[CWVFakeScriptCommandHandler alloc] init];
   [web_view_ addScriptCommandHandler:handler commandPrefix:@"test"];
diff --git a/media/base/BUILD.gn b/media/base/BUILD.gn
index 6a1e9c2..ac60e933 100644
--- a/media/base/BUILD.gn
+++ b/media/base/BUILD.gn
@@ -266,6 +266,8 @@
     "video_decoder_config.h",
     "video_frame.cc",
     "video_frame.h",
+    "video_frame_layout.cc",
+    "video_frame_layout.h",
     "video_frame_metadata.cc",
     "video_frame_metadata.h",
     "video_frame_pool.cc",
@@ -514,6 +516,7 @@
     "video_codecs_unittest.cc",
     "video_color_space_unittest.cc",
     "video_decoder_config_unittest.cc",
+    "video_frame_layout_unittest.cc",
     "video_frame_pool_unittest.cc",
     "video_frame_unittest.cc",
     "video_util_unittest.cc",
diff --git a/media/base/bind_to_current_loop.h b/media/base/bind_to_current_loop.h
index de69a63a..8c07621 100644
--- a/media/base/bind_to_current_loop.h
+++ b/media/base/bind_to_current_loop.h
@@ -13,22 +13,18 @@
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
 
-// This is a helper utility for base::Bind()ing callbacks to a given
-// TaskRunner. The typical use is when |a| (of class |A|) wants to hand a
+// This is a helper utility for base::Bind()ing callbacks to the current
+// MessageLoop. The typical use is when |a| (of class |A|) wants to hand a
 // callback such as base::Bind(&A::AMethod, a) to |b|, but needs to ensure that
-// when |b| executes the callback, it does so on |a|'s task_runner's
-// MessageLoop.
+// when |b| executes the callback, it does so on |a|'s current MessageLoop.
 //
 // Typical usage: request to be called back on the current thread:
 // other->StartAsyncProcessAndCallMeBack(
-//    media::BindToLoop(task_runner, base::BindOnce(&MyClass::MyMethod, this)));
+//    media::BindToCurrentLoop(base::BindOnce(&MyClass::MyMethod, this)));
 //
-// media::BindToLoop returns the same type of callback to the given
+// media::BindToCurrentLoop returns the same type of callback to the given
 // callback. I.e. it returns a RepeatingCallback for a given RepeatingCallback,
 // and returns OnceCallback for a given OnceCallback.
-//
-// The function BindToCurrentLoop is shorthand to bind to the calling function's
-// current MessageLoop.
 
 namespace media {
 namespace internal {
@@ -85,8 +81,7 @@
 }  // namespace internal
 
 template <typename... Args>
-inline base::RepeatingCallback<void(Args...)> BindToLoop(
-    scoped_refptr<base::SequencedTaskRunner> task_runner,
+inline base::RepeatingCallback<void(Args...)> BindToCurrentLoop(
     base::RepeatingCallback<void(Args...)> cb) {
   using CallbackType = base::RepeatingCallback<void(Args...)>;
   using Helper = internal::TrampolineHelper<CallbackType>;
@@ -94,12 +89,12 @@
   RunnerType run = &Helper::Run;
   // TODO(tzik): Propagate FROM_HERE from the caller.
   return base::BindRepeating(
-      run, std::make_unique<Helper>(FROM_HERE, task_runner, std::move(cb)));
+      run, std::make_unique<Helper>(
+               FROM_HERE, base::ThreadTaskRunnerHandle::Get(), std::move(cb)));
 }
 
 template <typename... Args>
-inline base::OnceCallback<void(Args...)> BindToLoop(
-    scoped_refptr<base::SequencedTaskRunner> task_runner,
+inline base::OnceCallback<void(Args...)> BindToCurrentLoop(
     base::OnceCallback<void(Args...)> cb) {
   using CallbackType = base::OnceCallback<void(Args...)>;
   using Helper = internal::TrampolineHelper<CallbackType>;
@@ -107,19 +102,8 @@
   RunnerType run = &Helper::Run;
   // TODO(tzik): Propagate FROM_HERE from the caller.
   return base::BindOnce(
-      run, std::make_unique<Helper>(FROM_HERE, task_runner, std::move(cb)));
-}
-
-template <typename... Args>
-inline base::RepeatingCallback<void(Args...)> BindToCurrentLoop(
-    base::RepeatingCallback<void(Args...)> cb) {
-  return BindToLoop(base::ThreadTaskRunnerHandle::Get(), std::move(cb));
-}
-
-template <typename... Args>
-inline base::OnceCallback<void(Args...)> BindToCurrentLoop(
-    base::OnceCallback<void(Args...)> cb) {
-  return BindToLoop(base::ThreadTaskRunnerHandle::Get(), std::move(cb));
+      run, std::make_unique<Helper>(
+               FROM_HERE, base::ThreadTaskRunnerHandle::Get(), std::move(cb)));
 }
 
 }  // namespace media
diff --git a/media/base/video_frame_layout.cc b/media/base/video_frame_layout.cc
new file mode 100644
index 0000000..43ac1a09
--- /dev/null
+++ b/media/base/video_frame_layout.cc
@@ -0,0 +1,57 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "media/base/video_frame_layout.h"
+
+#include <numeric>
+#include <sstream>
+
+namespace {
+
+template <class T>
+std::string VectorToString(const std::vector<T>& vec) {
+  std::ostringstream result;
+  std::string delim;
+  result << "[";
+  for (auto v : vec) {
+    result << delim << v;
+    if (delim.size() == 0)
+      delim = ", ";
+  }
+  result << "]";
+  return result.str();
+}
+
+}  // namespace
+
+namespace media {
+
+VideoFrameLayout::VideoFrameLayout(VideoPixelFormat format,
+                                   const gfx::Size& coded_size,
+                                   std::vector<int32_t> strides,
+                                   std::vector<size_t> buffer_sizes)
+    : format_(format),
+      coded_size_(coded_size),
+      strides_(std::move(strides)),
+      buffer_sizes_(std::move(buffer_sizes)) {}
+
+VideoFrameLayout::VideoFrameLayout(const VideoFrameLayout& layout) = default;
+VideoFrameLayout::~VideoFrameLayout() = default;
+
+size_t VideoFrameLayout::GetTotalBufferSize() const {
+  return std::accumulate(buffer_sizes_.begin(), buffer_sizes_.end(), 0u);
+}
+
+std::string VideoFrameLayout::ToString() const {
+  std::ostringstream s;
+  s << "VideoFrameLayout format:" << VideoPixelFormatToString(format_)
+    << " coded_size:" << coded_size_.ToString()
+    << " num_buffers:" << num_buffers()
+    << " buffer_sizes:" << VectorToString(buffer_sizes_)
+    << " num_strides:" << num_strides()
+    << " strides:" << VectorToString(strides_);
+  return s.str();
+}
+
+}  // namespace media
diff --git a/media/base/video_frame_layout.h b/media/base/video_frame_layout.h
new file mode 100644
index 0000000..4eafad5
--- /dev/null
+++ b/media/base/video_frame_layout.h
@@ -0,0 +1,88 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MEDIA_BASE_VIDEO_FRAME_LAYOUT_H_
+#define MEDIA_BASE_VIDEO_FRAME_LAYOUT_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "media/base/media_export.h"
+#include "media/base/video_types.h"
+#include "ui/gfx/geometry/size.h"
+
+namespace media {
+
+// A class to describes how physical buffer is allocated for video frame.
+// In stores format, coded size of the frame and size of physical buffers
+// which can be used to allocate buffer(s) hardware expected.
+// Also, it stores stride (bytes per line) per color plane to calculate each
+// color plane's size (note that a buffer may contains multiple color planes.)
+class MEDIA_EXPORT VideoFrameLayout {
+ public:
+  // Constructor with strides and buffers' size.
+  VideoFrameLayout(VideoPixelFormat format,
+                   const gfx::Size& coded_size,
+                   std::vector<int32_t> strides = std::vector<int32_t>(),
+                   std::vector<size_t> buffer_sizes = std::vector<size_t>());
+
+  VideoFrameLayout(const VideoFrameLayout& layout);
+
+  ~VideoFrameLayout();
+
+  VideoPixelFormat format() const { return format_; }
+  const gfx::Size& coded_size() const { return coded_size_; }
+
+  // Return number of buffers. Note that num_strides >= num_buffers.
+  size_t num_buffers() const { return buffer_sizes_.size(); }
+
+  // Returns number of strides. Note that num_strides >= num_buffers.
+  size_t num_strides() const { return strides_.size(); }
+
+  const std::vector<int32_t>& strides() const { return strides_; }
+  const std::vector<size_t>& buffer_sizes() const { return buffer_sizes_; }
+
+  // Sets strides.
+  void set_strides(std::vector<int32_t> strides) {
+    strides_ = std::move(strides);
+  }
+
+  // Sets buffer_sizes.
+  void set_buffer_sizes(std::vector<size_t> buffer_sizes) {
+    buffer_sizes_ = std::move(buffer_sizes);
+  }
+
+  // Returns sum of bytes of all buffers.
+  size_t GetTotalBufferSize() const;
+
+  // Composes VideoFrameLayout as human readable string.
+  std::string ToString() const;
+
+ private:
+  const VideoPixelFormat format_;
+
+  // Width and height of the video frame in pixels. This must include pixel
+  // data for the whole image; i.e. for YUV formats with subsampled chroma
+  // planes, in the case that the visible portion of the image does not line up
+  // on a sample boundary, |coded_size_| must be rounded up appropriately and
+  // the pixel data provided for the odd pixels.
+  const gfx::Size coded_size_;
+
+  // Vector of strides for each buffer, typically greater or equal to the
+  // width of the surface divided by the horizontal sampling period. Note that
+  // strides can be negative if the image layout is bottom-up.
+  std::vector<int32_t> strides_;
+
+  // Vector of sizes for each buffer, typically greater or equal to the area of
+  // |coded_size_|.
+  std::vector<size_t> buffer_sizes_;
+};
+
+}  // namespace media
+
+#endif  // MEDIA_BASE_VIDEO_FRAME_LAYOUT_H_
diff --git a/media/base/video_frame_layout_unittest.cc b/media/base/video_frame_layout_unittest.cc
new file mode 100644
index 0000000..b15707f0
--- /dev/null
+++ b/media/base/video_frame_layout_unittest.cc
@@ -0,0 +1,113 @@
+// Copyright (c) 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "media/base/video_frame_layout.h"
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <string>
+#include <utility>
+
+#include "media/base/video_types.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/geometry/size.h"
+
+namespace media {
+
+TEST(VideoFrameLayout, Constructor) {
+  gfx::Size coded_size = gfx::Size(320, 180);
+  std::vector<int32_t> strides = {384, 192, 192};
+  std::vector<size_t> buffer_sizes = {73728, 18432, 18432};
+  VideoFrameLayout layout(PIXEL_FORMAT_I420, coded_size, strides, buffer_sizes);
+
+  EXPECT_EQ(layout.format(), PIXEL_FORMAT_I420);
+  EXPECT_EQ(layout.coded_size(), coded_size);
+  EXPECT_EQ(layout.num_strides(), 3u);
+  EXPECT_EQ(layout.num_buffers(), 3u);
+  EXPECT_EQ(layout.GetTotalBufferSize(), 110592u);
+  for (size_t i = 0; i < 3; ++i) {
+    EXPECT_EQ(layout.strides()[i], strides[i]);
+    EXPECT_EQ(layout.buffer_sizes()[i], buffer_sizes[i]);
+  }
+}
+
+TEST(VideoFrameLayout, ConstructorNoStrideBufferSize) {
+  gfx::Size coded_size = gfx::Size(320, 180);
+  VideoFrameLayout layout(PIXEL_FORMAT_I420, coded_size);
+
+  EXPECT_EQ(layout.format(), PIXEL_FORMAT_I420);
+  EXPECT_EQ(layout.coded_size(), coded_size);
+  EXPECT_EQ(layout.GetTotalBufferSize(), 0u);
+  EXPECT_EQ(layout.num_strides(), 0u);
+  EXPECT_EQ(layout.num_buffers(), 0u);
+}
+
+TEST(VideoFrameLayout, CopyConstructor) {
+  gfx::Size coded_size = gfx::Size(320, 180);
+  std::vector<int32_t> strides = {384, 192, 192};
+  std::vector<size_t> buffer_sizes = {73728, 18432, 18432};
+  VideoFrameLayout layout(PIXEL_FORMAT_I420, coded_size, strides, buffer_sizes);
+
+  VideoFrameLayout layout_copy(layout);
+
+  EXPECT_EQ(layout_copy.format(), PIXEL_FORMAT_I420);
+  EXPECT_EQ(layout_copy.coded_size(), coded_size);
+  EXPECT_EQ(layout_copy.num_strides(), 3u);
+  EXPECT_EQ(layout_copy.num_buffers(), 3u);
+  EXPECT_EQ(layout_copy.GetTotalBufferSize(), 110592u);
+  for (size_t i = 0; i < 3; ++i) {
+    EXPECT_EQ(layout_copy.strides()[i], strides[i]);
+    EXPECT_EQ(layout_copy.buffer_sizes()[i], buffer_sizes[i]);
+  }
+}
+
+TEST(VideoFrameLayout, ToString) {
+  gfx::Size coded_size = gfx::Size(320, 180);
+  std::vector<int32_t> strides = {384, 192, 192};
+  std::vector<size_t> buffer_sizes = {73728, 18432, 18432};
+  VideoFrameLayout layout(PIXEL_FORMAT_I420, coded_size, strides, buffer_sizes);
+
+  EXPECT_EQ(layout.ToString(),
+            "VideoFrameLayout format:PIXEL_FORMAT_I420 coded_size:320x180 "
+            "num_buffers:3 buffer_sizes:[73728, 18432, 18432] num_strides:3 "
+            "strides:[384, 192, 192]");
+}
+
+TEST(VideoFrameLayout, ToStringOneBuffer) {
+  gfx::Size coded_size = gfx::Size(320, 180);
+  std::vector<int32_t> strides = {384};
+  std::vector<size_t> buffer_sizes = {122880};
+  VideoFrameLayout layout(PIXEL_FORMAT_NV12, coded_size, strides, buffer_sizes);
+
+  EXPECT_EQ(layout.ToString(),
+            "VideoFrameLayout format:PIXEL_FORMAT_NV12 coded_size:320x180 "
+            "num_buffers:1 buffer_sizes:[122880] num_strides:1 strides:[384]");
+}
+
+TEST(VideoFrameLayout, ToStringNoBufferInfo) {
+  gfx::Size coded_size = gfx::Size(320, 180);
+  VideoFrameLayout layout(PIXEL_FORMAT_NV12, coded_size);
+
+  EXPECT_EQ(layout.ToString(),
+            "VideoFrameLayout format:PIXEL_FORMAT_NV12 coded_size:320x180 "
+            "num_buffers:0 buffer_sizes:[] num_strides:0 strides:[]");
+}
+
+TEST(VideoFrameLayout, SetStrideBufferSize) {
+  gfx::Size coded_size = gfx::Size(320, 180);
+  VideoFrameLayout layout(PIXEL_FORMAT_NV12, coded_size);
+
+  std::vector<int32_t> strides = {384, 192, 192};
+  layout.set_strides(std::move(strides));
+  std::vector<size_t> buffer_sizes = {122880};
+  layout.set_buffer_sizes(std::move(buffer_sizes));
+
+  EXPECT_EQ(layout.ToString(),
+            "VideoFrameLayout format:PIXEL_FORMAT_NV12 coded_size:320x180 "
+            "num_buffers:1 buffer_sizes:[122880] num_strides:3 "
+            "strides:[384, 192, 192]");
+}
+
+}  // namespace media
diff --git a/media/blink/DEPS b/media/blink/DEPS
index efda6347..c30001fa 100644
--- a/media/blink/DEPS
+++ b/media/blink/DEPS
@@ -1,6 +1,5 @@
 include_rules = [
   "+cc/layers/layer.h",
-  "+cc/layers/surface_layer.h",
   "+cc/layers/video_frame_provider.h",
   "+cc/layers/video_layer.h",
   "+components/scheduler",  # Only allowed in tests.
diff --git a/media/blink/video_frame_compositor.cc b/media/blink/video_frame_compositor.cc
index 6b25bcb0..99c2fb99 100644
--- a/media/blink/video_frame_compositor.cc
+++ b/media/blink/video_frame_compositor.cc
@@ -9,7 +9,6 @@
 #include "base/time/default_tick_clock.h"
 #include "base/trace_event/auto_open_close_event.h"
 #include "base/trace_event/trace_event.h"
-#include "media/base/bind_to_current_loop.h"
 #include "media/base/media_switches.h"
 #include "media/base/video_frame.h"
 #include "media/blink/webmediaplayer_params.h"
@@ -47,23 +46,9 @@
     task_runner_->PostTask(
         FROM_HERE, base::Bind(&VideoFrameCompositor::InitializeSubmitter,
                               weak_ptr_factory_.GetWeakPtr()));
-    update_submission_state_callback_ = media::BindToLoop(
-        task_runner_,
-        base::BindRepeating(&VideoFrameCompositor::UpdateSubmissionState,
-                            weak_ptr_factory_.GetWeakPtr()));
   }
 }
 
-cc::UpdateSubmissionStateCB
-VideoFrameCompositor::GetUpdateSubmissionStateCallback() {
-  return update_submission_state_callback_;
-}
-
-void VideoFrameCompositor::UpdateSubmissionState(bool state) {
-  DCHECK(task_runner_->BelongsToCurrentThread());
-  submitter_->UpdateSubmissionState(state);
-}
-
 void VideoFrameCompositor::InitializeSubmitter() {
   DCHECK(task_runner_->BelongsToCurrentThread());
   submitter_->Initialize(this);
@@ -78,7 +63,7 @@
 }
 
 void VideoFrameCompositor::EnableSubmission(
-    const viz::SurfaceId& id,
+    const viz::FrameSinkId& id,
     media::VideoRotation rotation,
     blink::WebFrameSinkDestroyedCallback frame_sink_destroyed_callback) {
   DCHECK(task_runner_->BelongsToCurrentThread());
diff --git a/media/blink/video_frame_compositor.h b/media/blink/video_frame_compositor.h
index f3959f8..f0b49b5 100644
--- a/media/blink/video_frame_compositor.h
+++ b/media/blink/video_frame_compositor.h
@@ -15,7 +15,6 @@
 #include "base/time/tick_clock.h"
 #include "base/time/time.h"
 #include "base/timer/timer.h"
-#include "cc/layers/surface_layer.h"
 #include "cc/layers/video_frame_provider.h"
 #include "media/base/video_renderer_sink.h"
 #include "media/blink/media_blink_export.h"
@@ -30,7 +29,7 @@
 }
 
 namespace viz {
-class SurfaceId;
+class FrameSinkId;
 }
 
 namespace media {
@@ -77,13 +76,10 @@
   // called before destruction starts.
   ~VideoFrameCompositor() override;
 
-  // Can be called from any thread.
-  cc::UpdateSubmissionStateCB GetUpdateSubmissionStateCallback();
-
   // Signals the VideoFrameSubmitter to prepare to receive BeginFrames and
   // submit video frames given by VideoFrameCompositor.
   virtual void EnableSubmission(
-      const viz::SurfaceId& id,
+      const viz::FrameSinkId& id,
       media::VideoRotation rotation,
       blink::WebFrameSinkDestroyedCallback frame_sink_destroyed_callback);
 
@@ -154,10 +150,9 @@
   // Ran on the |task_runner_| to initalize |submitter_|;
   void InitializeSubmitter();
 
-  // Signals the VideoFrameSubmitter to stop submitting frames.
-  void UpdateSubmissionState(bool);
-
   // Indicates whether the endpoint for the VideoFrame exists.
+  // TODO(lethalantidote): Update this function to read creation/destruction
+  // signals of the SurfaceLayerImpl.
   bool IsClientSinkAvailable();
 
   // Called on the compositor thread in response to Start() or Stop() calls;
@@ -206,7 +201,6 @@
   base::TimeDelta last_interval_;
   base::TimeTicks last_background_render_;
   OnNewProcessedFrameCB new_processed_frame_cb_;
-  cc::UpdateSubmissionStateCB update_submission_state_callback_;
 
   // Set on the compositor thread, but also read on the media thread.
   base::Lock current_frame_lock_;
diff --git a/media/blink/video_frame_compositor_unittest.cc b/media/blink/video_frame_compositor_unittest.cc
index 237be8d..8585ce9 100644
--- a/media/blink/video_frame_compositor_unittest.cc
+++ b/media/blink/video_frame_compositor_unittest.cc
@@ -28,12 +28,11 @@
   // blink::WebVideoFrameSubmitter implementation.
   void StopUsingProvider() override {}
   MOCK_METHOD2(EnableSubmission,
-               void(viz::SurfaceId, blink::WebFrameSinkDestroyedCallback));
+               void(viz::FrameSinkId, blink::WebFrameSinkDestroyedCallback));
   MOCK_METHOD0(StartRendering, void());
   MOCK_METHOD0(StopRendering, void());
   MOCK_METHOD1(Initialize, void(cc::VideoFrameProvider*));
   MOCK_METHOD1(SetRotation, void(media::VideoRotation));
-  MOCK_METHOD1(UpdateSubmissionState, void(bool));
   void DidReceiveFrame() override { ++did_receive_frame_count_; }
 
   int did_receive_frame_count() { return did_receive_frame_count_; }
@@ -70,8 +69,8 @@
       base::RunLoop().RunUntilIdle();
       EXPECT_CALL(*submitter_,
                   SetRotation(Eq(media::VideoRotation::VIDEO_ROTATION_90)));
-      EXPECT_CALL(*submitter_, EnableSubmission(Eq(viz::SurfaceId()), _));
-      compositor_->EnableSubmission(viz::SurfaceId(),
+      EXPECT_CALL(*submitter_, EnableSubmission(Eq(viz::FrameSinkId(1, 1)), _));
+      compositor_->EnableSubmission(viz::FrameSinkId(1, 1),
                                     media::VideoRotation::VIDEO_ROTATION_90,
                                     base::BindRepeating([] {}));
     }
diff --git a/media/blink/webmediaplayer_impl.cc b/media/blink/webmediaplayer_impl.cc
index 49b1395..d1a69db 100644
--- a/media/blink/webmediaplayer_impl.cc
+++ b/media/blink/webmediaplayer_impl.cc
@@ -1630,15 +1630,13 @@
     } else {
       DCHECK(!bridge_);
 
-      bridge_ = std::move(create_bridge_callback_)
-                    .Run(this, compositor_->GetUpdateSubmissionStateCallback());
+      bridge_ = std::move(create_bridge_callback_).Run(this);
       bridge_->CreateSurfaceLayer();
-
       vfc_task_runner_->PostTask(
           FROM_HERE,
           base::BindOnce(
               &VideoFrameCompositor::EnableSubmission,
-              base::Unretained(compositor_.get()), bridge_->GetSurfaceId(),
+              base::Unretained(compositor_.get()), bridge_->GetFrameSinkId(),
               pipeline_metadata_.video_decoder_config.video_rotation(),
               BindToCurrentLoop(base::BindRepeating(
                   &WebMediaPlayerImpl::OnFrameSinkDestroyed, AsWeakPtr()))));
diff --git a/media/blink/webmediaplayer_impl.h b/media/blink/webmediaplayer_impl.h
index 5af1fefd..3872617 100644
--- a/media/blink/webmediaplayer_impl.h
+++ b/media/blink/webmediaplayer_impl.h
@@ -24,7 +24,6 @@
 #include "base/timer/elapsed_timer.h"
 #include "base/timer/timer.h"
 #include "build/build_config.h"
-#include "cc/layers/surface_layer.h"
 #include "components/viz/common/gpu/context_provider.h"
 #include "media/base/media_observer.h"
 #include "media/base/media_tracks.h"
@@ -867,8 +866,7 @@
   bool surface_layer_for_video_enabled_ = false;
 
   base::OnceCallback<std::unique_ptr<blink::WebSurfaceLayerBridge>(
-      blink::WebSurfaceLayerBridgeObserver*,
-      cc::UpdateSubmissionStateCB)>
+      blink::WebSurfaceLayerBridgeObserver*)>
       create_bridge_callback_;
 
   base::CancelableOnceCallback<void(base::TimeTicks)> frame_time_report_cb_;
diff --git a/media/blink/webmediaplayer_impl_unittest.cc b/media/blink/webmediaplayer_impl_unittest.cc
index eb1bbe3..5d59dba 100644
--- a/media/blink/webmediaplayer_impl_unittest.cc
+++ b/media/blink/webmediaplayer_impl_unittest.cc
@@ -294,10 +294,10 @@
  public:
   MOCK_CONST_METHOD0(GetCcLayer, cc::Layer*());
   MOCK_CONST_METHOD0(GetFrameSinkId, const viz::FrameSinkId&());
-  MOCK_CONST_METHOD0(GetSurfaceId, const viz::SurfaceId&());
   MOCK_METHOD0(ClearSurfaceId, void());
   MOCK_METHOD1(SetContentsOpaque, void(bool));
   MOCK_METHOD0(CreateSurfaceLayer, void());
+  MOCK_CONST_METHOD0(GetSurfaceId, const viz::SurfaceId&());
 };
 
 class MockVideoFrameCompositor : public VideoFrameCompositor {
@@ -311,7 +311,7 @@
   void SetOnNewProcessedFrameCallback(OnNewProcessedFrameCB cb) override {}
   MOCK_METHOD0(GetCurrentFrameAndUpdateIfStale, scoped_refptr<VideoFrame>());
   MOCK_METHOD3(EnableSubmission,
-               void(const viz::SurfaceId&,
+               void(const viz::FrameSinkId&,
                     media::VideoRotation,
                     blink::WebFrameSinkDestroyedCallback));
 };
@@ -379,8 +379,9 @@
         kMaxKeyframeDistanceToDisableBackgroundVideo,
         kMaxKeyframeDistanceToDisableBackgroundVideoMSE, false, false,
         std::move(provider),
-        base::BindOnce(&WebMediaPlayerImplTest::CreateMockSurfaceLayerBridge,
-                       base::Unretained(this)),
+        base::BindRepeating(
+            &WebMediaPlayerImplTest::CreateMockSurfaceLayerBridge,
+            base::Unretained(this)),
         viz::TestContextProvider::Create(),
         base::FeatureList::IsEnabled(media::kUseSurfaceLayerForVideo));
 
@@ -415,8 +416,7 @@
 
  protected:
   std::unique_ptr<blink::WebSurfaceLayerBridge> CreateMockSurfaceLayerBridge(
-      blink::WebSurfaceLayerBridgeObserver*,
-      cc::UpdateSubmissionStateCB) {
+      blink::WebSurfaceLayerBridgeObserver*) {
     return std::move(surface_layer_bridge_);
   }
 
@@ -768,8 +768,8 @@
   if (base::FeatureList::IsEnabled(kUseSurfaceLayerForVideo)) {
     EXPECT_CALL(*surface_layer_bridge_ptr_, CreateSurfaceLayer());
     EXPECT_CALL(client_, SetCcLayer(_)).Times(0);
-    EXPECT_CALL(*surface_layer_bridge_ptr_, GetSurfaceId())
-        .WillOnce(ReturnRef(surface_id_));
+    EXPECT_CALL(*surface_layer_bridge_ptr_, GetFrameSinkId())
+        .WillOnce(ReturnRef(frame_sink_id_));
     EXPECT_CALL(*compositor_, EnableSubmission(_, _, _));
     EXPECT_CALL(*surface_layer_bridge_ptr_, SetContentsOpaque(false));
   }
@@ -1166,7 +1166,7 @@
 
   if (base::FeatureList::IsEnabled(media::kUseSurfaceLayerForVideo)) {
     EXPECT_CALL(*surface_layer_bridge_ptr_, CreateSurfaceLayer()).Times(0);
-    EXPECT_CALL(*surface_layer_bridge_ptr_, GetSurfaceId()).Times(0);
+    EXPECT_CALL(*surface_layer_bridge_ptr_, GetFrameSinkId()).Times(0);
     EXPECT_CALL(*compositor_, EnableSubmission(_, _, _)).Times(0);
   }
 
@@ -1184,8 +1184,8 @@
   if (base::FeatureList::IsEnabled(kUseSurfaceLayerForVideo)) {
     EXPECT_CALL(*surface_layer_bridge_ptr_, CreateSurfaceLayer());
     EXPECT_CALL(client_, SetCcLayer(_)).Times(0);
-    EXPECT_CALL(*surface_layer_bridge_ptr_, GetSurfaceId())
-        .WillOnce(ReturnRef(surface_id_));
+    EXPECT_CALL(*surface_layer_bridge_ptr_, GetFrameSinkId())
+        .WillOnce(ReturnRef(frame_sink_id_));
     EXPECT_CALL(*compositor_, EnableSubmission(_, _, _));
     EXPECT_CALL(*surface_layer_bridge_ptr_, SetContentsOpaque(false));
   } else {
@@ -1211,8 +1211,8 @@
   if (base::FeatureList::IsEnabled(kUseSurfaceLayerForVideo)) {
     EXPECT_CALL(client_, SetCcLayer(_)).Times(0);
     EXPECT_CALL(*surface_layer_bridge_ptr_, CreateSurfaceLayer());
-    EXPECT_CALL(*surface_layer_bridge_ptr_, GetSurfaceId())
-        .WillOnce(ReturnRef(surface_id_));
+    EXPECT_CALL(*surface_layer_bridge_ptr_, GetFrameSinkId())
+        .WillOnce(ReturnRef(frame_sink_id_));
     EXPECT_CALL(*compositor_, EnableSubmission(_, _, _));
     EXPECT_CALL(*surface_layer_bridge_ptr_, SetContentsOpaque(false));
   } else {
@@ -1239,8 +1239,8 @@
   if (base::FeatureList::IsEnabled(kUseSurfaceLayerForVideo)) {
     EXPECT_CALL(client_, SetCcLayer(_)).Times(0);
     EXPECT_CALL(*surface_layer_bridge_ptr_, CreateSurfaceLayer());
-    EXPECT_CALL(*surface_layer_bridge_ptr_, GetSurfaceId())
-        .WillOnce(ReturnRef(surface_id_));
+    EXPECT_CALL(*surface_layer_bridge_ptr_, GetFrameSinkId())
+        .WillOnce(ReturnRef(frame_sink_id_));
     EXPECT_CALL(*compositor_, EnableSubmission(_, _, _));
     EXPECT_CALL(*surface_layer_bridge_ptr_, SetContentsOpaque(false));
   } else {
@@ -1315,8 +1315,8 @@
   if (base::FeatureList::IsEnabled(kUseSurfaceLayerForVideo)) {
     EXPECT_CALL(client_, SetCcLayer(_)).Times(0);
     EXPECT_CALL(*surface_layer_bridge_ptr_, CreateSurfaceLayer());
-    EXPECT_CALL(*surface_layer_bridge_ptr_, GetSurfaceId())
-        .WillOnce(ReturnRef(surface_id_));
+    EXPECT_CALL(*surface_layer_bridge_ptr_, GetFrameSinkId())
+        .WillOnce(ReturnRef(frame_sink_id_));
     EXPECT_CALL(*compositor_, EnableSubmission(_, _, _));
     EXPECT_CALL(*surface_layer_bridge_ptr_, SetContentsOpaque(false));
   } else {
@@ -1353,8 +1353,8 @@
 
   EXPECT_CALL(client_, SetCcLayer(_)).Times(0);
   EXPECT_CALL(*surface_layer_bridge_ptr_, CreateSurfaceLayer());
-  EXPECT_CALL(*surface_layer_bridge_ptr_, GetSurfaceId())
-      .WillOnce(ReturnRef(surface_id_));
+  EXPECT_CALL(*surface_layer_bridge_ptr_, GetFrameSinkId())
+      .WillOnce(ReturnRef(frame_sink_id_));
   EXPECT_CALL(*surface_layer_bridge_ptr_, SetContentsOpaque(false));
   EXPECT_CALL(*compositor_, EnableSubmission(_, _, _));
 
@@ -1392,8 +1392,10 @@
   InitializeWebMediaPlayerImpl();
 
   EXPECT_CALL(*surface_layer_bridge_ptr_, CreateSurfaceLayer());
+  EXPECT_CALL(*surface_layer_bridge_ptr_, GetFrameSinkId())
+      .WillOnce(ReturnRef(frame_sink_id_));
   EXPECT_CALL(*surface_layer_bridge_ptr_, GetSurfaceId())
-      .WillRepeatedly(ReturnRef(surface_id_));
+      .WillOnce(ReturnRef(surface_id_));
   EXPECT_CALL(*compositor_, EnableSubmission(_, _, _));
   EXPECT_CALL(*surface_layer_bridge_ptr_, SetContentsOpaque(false));
 
diff --git a/media/blink/webmediaplayer_params.cc b/media/blink/webmediaplayer_params.cc
index 0436885..9b6a730 100644
--- a/media/blink/webmediaplayer_params.cc
+++ b/media/blink/webmediaplayer_params.cc
@@ -29,8 +29,7 @@
     bool embedded_media_experience_enabled,
     mojom::MediaMetricsProviderPtr metrics_provider,
     base::OnceCallback<std::unique_ptr<blink::WebSurfaceLayerBridge>(
-        blink::WebSurfaceLayerBridgeObserver*,
-        cc::UpdateSubmissionStateCB)> create_bridge_callback,
+        blink::WebSurfaceLayerBridgeObserver*)> create_bridge_callback,
     scoped_refptr<viz::ContextProvider> context_provider,
     bool use_surface_layer_for_video)
     : defer_load_cb_(defer_load_cb),
diff --git a/media/blink/webmediaplayer_params.h b/media/blink/webmediaplayer_params.h
index 0793f19..256532d80 100644
--- a/media/blink/webmediaplayer_params.h
+++ b/media/blink/webmediaplayer_params.h
@@ -13,7 +13,6 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
 #include "base/time/time.h"
-#include "cc/layers/surface_layer.h"
 #include "components/viz/common/gpu/context_provider.h"
 #include "media/base/media_log.h"
 #include "media/base/media_observer.h"
@@ -82,8 +81,7 @@
       bool embedded_media_experience_enabled,
       mojom::MediaMetricsProviderPtr metrics_provider,
       base::OnceCallback<std::unique_ptr<blink::WebSurfaceLayerBridge>(
-          blink::WebSurfaceLayerBridgeObserver*,
-          cc::UpdateSubmissionStateCB)> bridge_callback,
+          blink::WebSurfaceLayerBridgeObserver*)> bridge_callback,
       scoped_refptr<viz::ContextProvider> context_provider,
       bool use_surface_layer_for_video);
 
@@ -154,8 +152,7 @@
   }
 
   base::OnceCallback<std::unique_ptr<blink::WebSurfaceLayerBridge>(
-      blink::WebSurfaceLayerBridgeObserver*,
-      cc::UpdateSubmissionStateCB)>
+      blink::WebSurfaceLayerBridgeObserver*)>
   create_bridge_callback() {
     return std::move(create_bridge_callback_);
   }
@@ -188,8 +185,7 @@
   const bool embedded_media_experience_enabled_;
   mojom::MediaMetricsProviderPtr metrics_provider_;
   base::OnceCallback<std::unique_ptr<blink::WebSurfaceLayerBridge>(
-      blink::WebSurfaceLayerBridgeObserver*,
-      cc::UpdateSubmissionStateCB)>
+      blink::WebSurfaceLayerBridgeObserver*)>
       create_bridge_callback_;
   scoped_refptr<viz::ContextProvider> context_provider_;
   bool use_surface_layer_for_video_;
diff --git a/media/gpu/v4l2/v4l2_video_encode_accelerator.cc b/media/gpu/v4l2/v4l2_video_encode_accelerator.cc
index 0ca8450..425022e5 100644
--- a/media/gpu/v4l2/v4l2_video_encode_accelerator.cc
+++ b/media/gpu/v4l2/v4l2_video_encode_accelerator.cc
@@ -738,11 +738,13 @@
 
     child_task_runner_->PostTask(
         FROM_HERE,
-        base::Bind(
-            &Client::BitstreamBufferReady, client_, bitstream_buffer_id,
-            BitstreamBufferMetadata(
-                output_data_size, key_frame,
-                base::Time::FromTimeVal(dqbuf.timestamp).since_origin())));
+        base::Bind(&Client::BitstreamBufferReady, client_, bitstream_buffer_id,
+                   BitstreamBufferMetadata(
+                       output_data_size, key_frame,
+                       base::TimeDelta::FromMicroseconds(
+                           dqbuf.timestamp.tv_usec +
+                           dqbuf.timestamp.tv_sec *
+                               base::Time::kMicrosecondsPerSecond))));
     if ((encoder_state_ == kFlushing) && (dqbuf.flags & V4L2_BUF_FLAG_LAST)) {
       // Notify client that flush has finished successfully. The flush callback
       // should be called after notifying the last buffer is ready.
diff --git a/mojo/core/core.cc b/mojo/core/core.cc
index b8a2607..8422ec2 100644
--- a/mojo/core/core.cc
+++ b/mojo/core/core.cc
@@ -682,7 +682,7 @@
   // consumer of this pipe, and it would be impossible to support such access
   // control on Android anyway.
   auto writable_region_handle = ring_buffer_region.PassPlatformHandle();
-#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_FUCHSIA) && \
+#if defined(OS_POSIX) && !defined(OS_ANDROID) && \
     (!defined(OS_MACOSX) || defined(OS_IOS))
   // This isn't strictly necessary, but it does make the handle configuration
   // consistent with regular UnsafeSharedMemoryRegions.
@@ -1045,7 +1045,7 @@
     MojoHandle* mojo_handle) {
   DCHECK(size);
 
-#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_FUCHSIA) && \
+#if defined(OS_POSIX) && !defined(OS_ANDROID) && \
     (!defined(OS_MACOSX) || defined(OS_IOS))
   if (access_mode == MOJO_PLATFORM_SHARED_MEMORY_REGION_ACCESS_MODE_WRITABLE) {
     if (num_platform_handles != 2)
@@ -1167,7 +1167,7 @@
   if (available_handle_storage_slots < 1)
     return MOJO_RESULT_RESOURCE_EXHAUSTED;
   *num_platform_handles = 1;
-#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_FUCHSIA) && \
+#if defined(OS_POSIX) && !defined(OS_ANDROID) && \
     (!defined(OS_MACOSX) || defined(OS_IOS))
   if (region.GetMode() ==
       base::subtle::PlatformSharedMemoryRegion::Mode::kWritable) {
@@ -1338,7 +1338,7 @@
     return MOJO_RESULT_INVALID_ARGUMENT;
 
   ConnectionParams connection_params;
-#if defined(OS_WIN) || (defined(OS_POSIX) && !defined(OS_FUCHSIA))
+#if defined(OS_WIN) || defined(OS_POSIX)
   if (transport_endpoint->type ==
       MOJO_INVITATION_TRANSPORT_TYPE_CHANNEL_SERVER) {
     connection_params =
@@ -1431,7 +1431,7 @@
   }
 
   ConnectionParams connection_params;
-#if defined(OS_WIN) || (defined(OS_POSIX) && !defined(OS_FUCHSIA))
+#if defined(OS_WIN) || defined(OS_POSIX)
   if (transport_endpoint->type ==
       MOJO_INVITATION_TRANSPORT_TYPE_CHANNEL_SERVER) {
     connection_params =
diff --git a/mojo/core/shared_buffer_dispatcher.cc b/mojo/core/shared_buffer_dispatcher.cc
index 34ebf613..8a0026a 100644
--- a/mojo/core/shared_buffer_dispatcher.cc
+++ b/mojo/core/shared_buffer_dispatcher.cc
@@ -141,7 +141,7 @@
     return nullptr;
 
   PlatformHandle handles[2];
-#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_FUCHSIA) && \
+#if defined(OS_POSIX) && !defined(OS_ANDROID) && \
     (!defined(OS_MACOSX) || defined(OS_IOS))
   if (serialized_state->access_mode ==
       MOJO_PLATFORM_SHARED_MEMORY_REGION_ACCESS_MODE_WRITABLE) {
@@ -251,7 +251,7 @@
     } else if (region_.GetMode() ==
                base::subtle::PlatformSharedMemoryRegion::Mode::kWritable) {
       auto handle = region_.PassPlatformHandle();
-#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_FUCHSIA) && \
+#if defined(OS_POSIX) && !defined(OS_ANDROID) && \
     (!defined(OS_MACOSX) || defined(OS_IOS))
       // On POSIX systems excluding Android, Fuchsia, and OSX, we explicitly
       // wipe out the secondary (read-only) FD from the platform handle to
@@ -312,7 +312,7 @@
   *num_bytes = sizeof(SerializedState);
   *num_ports = 0;
   *num_platform_handles = 1;
-#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_FUCHSIA) && \
+#if defined(OS_POSIX) && !defined(OS_ANDROID) && \
     (!defined(OS_MACOSX) || defined(OS_IOS))
   if (region_.GetMode() ==
       base::subtle::PlatformSharedMemoryRegion::Mode::kWritable) {
@@ -352,7 +352,7 @@
   serialized_state->padding = 0;
 
   auto region = std::move(region_);
-#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_FUCHSIA) && \
+#if defined(OS_POSIX) && !defined(OS_ANDROID) && \
     (!defined(OS_MACOSX) || defined(OS_IOS))
   if (region.GetMode() ==
       base::subtle::PlatformSharedMemoryRegion::Mode::kWritable) {
diff --git a/net/disk_cache/disk_cache_perftest.cc b/net/disk_cache/disk_cache_perftest.cc
index 1ed73d43..5df49f48 100644
--- a/net/disk_cache/disk_cache_perftest.cc
+++ b/net/disk_cache/disk_cache_perftest.cc
@@ -53,7 +53,7 @@
 const int kMaxParallelOperations = 10;
 
 void MaybeIncreaseFdLimitTo(unsigned int max_descriptors) {
-#if defined(OS_POSIX) && !defined(OS_FUCHSIA)
+#if defined(OS_POSIX)
   base::IncreaseFdLimitTo(max_descriptors);
 #endif
 }
diff --git a/net/disk_cache/simple/simple_backend_impl.cc b/net/disk_cache/simple/simple_backend_impl.cc
index dd942d46..028f2edf 100644
--- a/net/disk_cache/simple/simple_backend_impl.cc
+++ b/net/disk_cache/simple/simple_backend_impl.cc
@@ -9,7 +9,7 @@
 #include <functional>
 #include <limits>
 
-#if defined(OS_POSIX) && !defined(OS_FUCHSIA)
+#if defined(OS_POSIX)
 #include <sys/resource.h>
 #endif
 
@@ -78,7 +78,7 @@
   int soft_fd_limit = 0;
   int hard_fd_limit = 0;
 
-#if defined(OS_POSIX) && !defined(OS_FUCHSIA)
+#if defined(OS_POSIX)
   struct rlimit nofile;
   if (!getrlimit(RLIMIT_NOFILE, &nofile)) {
     soft_fd_limit = nofile.rlim_cur;
diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc
index ec987ea..478e912 100644
--- a/net/url_request/url_request_unittest.cc
+++ b/net/url_request/url_request_unittest.cc
@@ -1190,7 +1190,7 @@
   }
 }
 
-#if defined(OS_POSIX) && !defined(OS_FUCHSIA)  // Because of symbolic links.
+#if defined(OS_POSIX)  // Because of symbolic links.
 
 TEST_F(URLRequestTest, SymlinksToFiles) {
   ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
@@ -1312,7 +1312,7 @@
   }
 }
 
-#endif  // defined(OS_POSIX) && !defined(OS_FUCHSIA)
+#endif  // defined(OS_POSIX)
 
 TEST_F(URLRequestTest, FileDirCancelTest) {
   // Put in mock resource provider.
diff --git a/net/websockets/websocket_basic_stream.cc b/net/websockets/websocket_basic_stream.cc
index 31267ba..d9d45b65 100644
--- a/net/websockets/websocket_basic_stream.cc
+++ b/net/websockets/websocket_basic_stream.cc
@@ -115,55 +115,21 @@
 
 int WebSocketBasicStream::ReadFrames(
     std::vector<std::unique_ptr<WebSocketFrame>>* frames,
-    const CompletionCallback& callback) {
-  DCHECK(frames->empty());
-  // If there is data left over after parsing the HTTP headers, attempt to parse
-  // it as WebSocket frames.
-  if (http_read_buffer_.get()) {
-    DCHECK_GE(http_read_buffer_->offset(), 0);
-    // We cannot simply copy the data into read_buffer_, as it might be too
-    // large.
-    scoped_refptr<GrowableIOBuffer> buffered_data;
-    buffered_data.swap(http_read_buffer_);
-    DCHECK(!http_read_buffer_);
-    std::vector<std::unique_ptr<WebSocketFrameChunk>> frame_chunks;
-    if (!parser_.Decode(buffered_data->StartOfBuffer(),
-                        buffered_data->offset(),
-                        &frame_chunks))
-      return WebSocketErrorToNetError(parser_.websocket_error());
-    if (!frame_chunks.empty()) {
-      int result = ConvertChunksToFrames(&frame_chunks, frames);
-      if (result != ERR_IO_PENDING)
-        return result;
-    }
-  }
+    CompletionOnceCallback callback) {
+  read_callback_ = std::move(callback);
 
-  // Run until socket stops giving us data or we get some frames.
-  while (true) {
-    // base::Unretained(this) here is safe because net::Socket guarantees not to
-    // call any callbacks after Disconnect(), which we call from the
-    // destructor. The caller of ReadFrames() is required to keep |frames|
-    // valid.
-    int result = connection_->Read(
-        read_buffer_.get(), read_buffer_->size(),
-        base::Bind(&WebSocketBasicStream::OnReadComplete,
-                   base::Unretained(this), base::Unretained(frames), callback));
-    if (result == ERR_IO_PENDING)
-      return result;
-    result = HandleReadResult(result, frames);
-    if (result != ERR_IO_PENDING)
-      return result;
-    DCHECK(frames->empty());
-  }
+  return ReadEverything(frames);
 }
 
 int WebSocketBasicStream::WriteFrames(
     std::vector<std::unique_ptr<WebSocketFrame>>* frames,
-    const CompletionCallback& callback) {
+    CompletionOnceCallback callback) {
   // This function always concatenates all frames into a single buffer.
   // TODO(ricea): Investigate whether it would be better in some cases to
   // perform multiple writes with smaller buffers.
-  //
+
+  write_callback_ = std::move(callback);
+
   // First calculate the size of the buffer we need to allocate.
   int total_size = CalculateSerializedSizeAndTurnOnMaskBit(frames);
   auto combined_buffer = base::MakeRefCounted<IOBufferWithSize>(total_size);
@@ -196,7 +162,7 @@
                                << remaining_size << " bytes left over.";
   auto drainable_buffer = base::MakeRefCounted<DrainableIOBuffer>(
       combined_buffer.get(), total_size);
-  return WriteEverything(drainable_buffer, callback);
+  return WriteEverything(drainable_buffer);
 }
 
 void WebSocketBasicStream::Close() {
@@ -225,17 +191,68 @@
   return stream;
 }
 
+int WebSocketBasicStream::ReadEverything(
+    std::vector<std::unique_ptr<WebSocketFrame>>* frames) {
+  DCHECK(frames->empty());
+
+  // If there is data left over after parsing the HTTP headers, attempt to parse
+  // it as WebSocket frames.
+  if (http_read_buffer_.get()) {
+    DCHECK_GE(http_read_buffer_->offset(), 0);
+    // We cannot simply copy the data into read_buffer_, as it might be too
+    // large.
+    scoped_refptr<GrowableIOBuffer> buffered_data;
+    buffered_data.swap(http_read_buffer_);
+    DCHECK(!http_read_buffer_);
+    std::vector<std::unique_ptr<WebSocketFrameChunk>> frame_chunks;
+    if (!parser_.Decode(buffered_data->StartOfBuffer(), buffered_data->offset(),
+                        &frame_chunks))
+      return WebSocketErrorToNetError(parser_.websocket_error());
+    if (!frame_chunks.empty()) {
+      int result = ConvertChunksToFrames(&frame_chunks, frames);
+      if (result != ERR_IO_PENDING)
+        return result;
+    }
+  }
+
+  // Run until socket stops giving us data or we get some frames.
+  while (true) {
+    // base::Unretained(this) here is safe because net::Socket guarantees not to
+    // call any callbacks after Disconnect(), which we call from the destructor.
+    // The caller of ReadEverything() is required to keep |frames| valid.
+    int result = connection_->Read(
+        read_buffer_.get(), read_buffer_->size(),
+        base::BindOnce(&WebSocketBasicStream::OnReadComplete,
+                       base::Unretained(this), base::Unretained(frames)));
+    if (result == ERR_IO_PENDING)
+      return result;
+    result = HandleReadResult(result, frames);
+    if (result != ERR_IO_PENDING)
+      return result;
+    DCHECK(frames->empty());
+  }
+}
+
+void WebSocketBasicStream::OnReadComplete(
+    std::vector<std::unique_ptr<WebSocketFrame>>* frames,
+    int result) {
+  result = HandleReadResult(result, frames);
+  if (result == ERR_IO_PENDING)
+    result = ReadEverything(frames);
+  if (result != ERR_IO_PENDING)
+    std::move(read_callback_).Run(result);
+}
+
 int WebSocketBasicStream::WriteEverything(
-    const scoped_refptr<DrainableIOBuffer>& buffer,
-    const CompletionCallback& callback) {
+    const scoped_refptr<DrainableIOBuffer>& buffer) {
   while (buffer->BytesRemaining() > 0) {
     // The use of base::Unretained() here is safe because on destruction we
     // disconnect the socket, preventing any further callbacks.
-    int result =
-        connection_->Write(buffer.get(), buffer->BytesRemaining(),
-                           base::Bind(&WebSocketBasicStream::OnWriteComplete,
-                                      base::Unretained(this), buffer, callback),
-                           kTrafficAnnotation);
+    int result = connection_->Write(
+        buffer.get(), buffer->BytesRemaining(),
+        base::BindOnce(&WebSocketBasicStream::OnWriteComplete,
+                       base::Unretained(this), buffer),
+        kTrafficAnnotation);
     if (result > 0) {
       UMA_HISTOGRAM_COUNTS_100000("Net.WebSocket.DataUse.Upstream", result);
       buffer->DidConsume(result);
@@ -248,11 +265,10 @@
 
 void WebSocketBasicStream::OnWriteComplete(
     const scoped_refptr<DrainableIOBuffer>& buffer,
-    const CompletionCallback& callback,
     int result) {
   if (result < 0) {
     DCHECK_NE(ERR_IO_PENDING, result);
-    callback.Run(result);
+    std::move(write_callback_).Run(result);
     return;
   }
 
@@ -260,9 +276,9 @@
   UMA_HISTOGRAM_COUNTS_100000("Net.WebSocket.DataUse.Upstream", result);
 
   buffer->DidConsume(result);
-  result = WriteEverything(buffer, callback);
+  result = WriteEverything(buffer);
   if (result != ERR_IO_PENDING)
-    callback.Run(result);
+    std::move(write_callback_).Run(result);
 }
 
 int WebSocketBasicStream::HandleReadResult(
@@ -441,15 +457,4 @@
   incomplete_control_frame_body_->set_offset(new_offset);
 }
 
-void WebSocketBasicStream::OnReadComplete(
-    std::vector<std::unique_ptr<WebSocketFrame>>* frames,
-    const CompletionCallback& callback,
-    int result) {
-  result = HandleReadResult(result, frames);
-  if (result == ERR_IO_PENDING)
-    result = ReadFrames(frames, callback);
-  if (result != ERR_IO_PENDING)
-    callback.Run(result);
-}
-
 }  // namespace net
diff --git a/net/websockets/websocket_basic_stream.h b/net/websockets/websocket_basic_stream.h
index 54e7a8e..05d2696 100644
--- a/net/websockets/websocket_basic_stream.h
+++ b/net/websockets/websocket_basic_stream.h
@@ -10,7 +10,6 @@
 #include <vector>
 
 #include "base/memory/scoped_refptr.h"
-#include "net/base/completion_callback.h"
 #include "net/base/completion_once_callback.h"
 #include "net/base/net_export.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
@@ -68,10 +67,10 @@
 
   // WebSocketStream implementation.
   int ReadFrames(std::vector<std::unique_ptr<WebSocketFrame>>* frames,
-                 const CompletionCallback& callback) override;
+                 CompletionOnceCallback callback) override;
 
   int WriteFrames(std::vector<std::unique_ptr<WebSocketFrame>>* frames,
-                  const CompletionCallback& callback) override;
+                  CompletionOnceCallback callback) override;
 
   void Close() override;
 
@@ -91,14 +90,24 @@
       WebSocketMaskingKeyGeneratorFunction key_generator_function);
 
  private:
-  // Returns OK or calls |callback| when the |buffer| is fully drained or
-  // something has failed.
-  int WriteEverything(const scoped_refptr<DrainableIOBuffer>& buffer,
-                      const CompletionCallback& callback);
+  // Reads until socket read returns asynchronously or returns error.
+  // If returns ERR_IO_PENDING, then |read_callback_| will be called with result
+  // later.
+  int ReadEverything(std::vector<std::unique_ptr<WebSocketFrame>>* frames);
 
-  // Wraps the |callback| to continue writing until everything has been written.
+  // Called when a read completes. Parses the result, tries to read more.
+  // Might call |read_callback_|.
+  void OnReadComplete(std::vector<std::unique_ptr<WebSocketFrame>>* frames,
+                      int result);
+
+  // Writes until |buffer| is fully drained (in which case returns OK) or a
+  // socket write returns asynchronously or returns an error.  If returns
+  // ERR_IO_PENDING, then |write_callback_| will be called with result later.
+  int WriteEverything(const scoped_refptr<DrainableIOBuffer>& buffer);
+
+  // Called when a write completes.  Tries to write more.
+  // Might call |write_callback_|.
   void OnWriteComplete(const scoped_refptr<DrainableIOBuffer>& buffer,
-                       const CompletionCallback& callback,
                        int result);
 
   // Attempts to parse the output of a read as WebSocket frames. On success,
@@ -138,12 +147,6 @@
   void AddToIncompleteControlFrameBody(
       const scoped_refptr<IOBufferWithSize>& data_buffer);
 
-  // Called when a read completes. Parses the result and (unless no complete
-  // header has been received) calls |callback|.
-  void OnReadComplete(std::vector<std::unique_ptr<WebSocketFrame>>* frames,
-                      const CompletionCallback& callback,
-                      int result);
-
   // Storage for pending reads. All active WebSockets spend all the time with a
   // call to ReadFrames() pending, so there is no benefit in trying to share
   // this between sockets.
@@ -185,6 +188,10 @@
   // use a Callback here because a function pointer is faster and good enough
   // for our purposes.
   WebSocketMaskingKeyGeneratorFunction generate_websocket_masking_key_;
+
+  // User callback saved for asynchronous writes and reads.
+  CompletionOnceCallback write_callback_;
+  CompletionOnceCallback read_callback_;
 };
 
 }  // namespace net
diff --git a/net/websockets/websocket_channel_test.cc b/net/websockets/websocket_channel_test.cc
index 5ca42dc..90259e3 100644
--- a/net/websockets/websocket_channel_test.cc
+++ b/net/websockets/websocket_channel_test.cc
@@ -18,6 +18,7 @@
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/callback.h"
+#include "base/callback_helpers.h"
 #include "base/location.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
@@ -25,6 +26,7 @@
 #include "base/single_thread_task_runner.h"
 #include "base/strings/string_piece.h"
 #include "base/threading/thread_task_runner_handle.h"
+#include "net/base/completion_once_callback.h"
 #include "net/base/net_errors.h"
 #include "net/base/test_completion_callback.h"
 #include "net/http/http_request_headers.h"
@@ -271,12 +273,12 @@
       : protocol_(protocol), extensions_(extensions) {}
 
   int ReadFrames(std::vector<std::unique_ptr<WebSocketFrame>>* frames,
-                 const CompletionCallback& callback) override {
+                 CompletionOnceCallback callback) override {
     return ERR_IO_PENDING;
   }
 
   int WriteFrames(std::vector<std::unique_ptr<WebSocketFrame>>* frames,
-                  const CompletionCallback& callback) override {
+                  CompletionOnceCallback callback) override {
     return ERR_IO_PENDING;
   }
 
@@ -505,15 +507,16 @@
   }
 
   int ReadFrames(std::vector<std::unique_ptr<WebSocketFrame>>* frames,
-                 const CompletionCallback& callback) override {
+                 CompletionOnceCallback callback) override {
     CHECK(!read_frames_pending_);
     if (index_ >= responses_.size())
       return ERR_IO_PENDING;
     if (responses_[index_]->async == ASYNC) {
       read_frames_pending_ = true;
       base::ThreadTaskRunnerHandle::Get()->PostTask(
-          FROM_HERE, base::Bind(&ReadableFakeWebSocketStream::DoCallback,
-                                base::Unretained(this), frames, callback));
+          FROM_HERE,
+          base::BindOnce(&ReadableFakeWebSocketStream::DoCallback,
+                         base::Unretained(this), frames, std::move(callback)));
       return ERR_IO_PENDING;
     } else {
       frames->swap(responses_[index_]->frames);
@@ -523,10 +526,10 @@
 
  private:
   void DoCallback(std::vector<std::unique_ptr<WebSocketFrame>>* frames,
-                  const CompletionCallback& callback) {
+                  CompletionOnceCallback callback) {
     read_frames_pending_ = false;
     frames->swap(responses_[index_]->frames);
-    callback.Run(responses_[index_++]->error);
+    std::move(callback).Run(responses_[index_++]->error);
     return;
   }
 
@@ -561,7 +564,7 @@
 class WriteableFakeWebSocketStream : public FakeWebSocketStream {
  public:
   int WriteFrames(std::vector<std::unique_ptr<WebSocketFrame>>* frames,
-                  const CompletionCallback& callback) override {
+                  CompletionOnceCallback callback) override {
     return OK;
   }
 };
@@ -570,7 +573,7 @@
 class UnWriteableFakeWebSocketStream : public FakeWebSocketStream {
  public:
   int WriteFrames(std::vector<std::unique_ptr<WebSocketFrame>>* frames,
-                  const CompletionCallback& callback) override {
+                  CompletionOnceCallback callback) override {
     return ERR_CONNECTION_RESET;
   }
 };
@@ -586,7 +589,7 @@
   EchoeyFakeWebSocketStream() : read_frames_(nullptr), done_(false) {}
 
   int WriteFrames(std::vector<std::unique_ptr<WebSocketFrame>>* frames,
-                  const CompletionCallback& callback) override {
+                  CompletionOnceCallback callback) override {
     stored_frames_.insert(stored_frames_.end(),
                           std::make_move_iterator(frames->begin()),
                           std::make_move_iterator(frames->end()));
@@ -598,8 +601,8 @@
   }
 
   int ReadFrames(std::vector<std::unique_ptr<WebSocketFrame>>* frames,
-                 const CompletionCallback& callback) override {
-    read_callback_ = callback;
+                 CompletionOnceCallback callback) override {
+    read_callback_ = std::move(callback);
     read_frames_ = frames;
     if (done_)
       PostCallback();
@@ -615,11 +618,11 @@
 
   void DoCallback() {
     if (done_) {
-      read_callback_.Run(ERR_CONNECTION_CLOSED);
+      std::move(read_callback_).Run(ERR_CONNECTION_CLOSED);
     } else if (!stored_frames_.empty()) {
       done_ = MoveFrames(read_frames_);
       read_frames_ = nullptr;
-      read_callback_.Run(OK);
+      std::move(read_callback_).Run(OK);
     }
   }
 
@@ -639,7 +642,7 @@
   }
 
   std::vector<std::unique_ptr<WebSocketFrame>> stored_frames_;
-  CompletionCallback read_callback_;
+  CompletionOnceCallback read_callback_;
   // Owned by the caller of ReadFrames().
   std::vector<std::unique_ptr<WebSocketFrame>>* read_frames_;
   // True if we should close the connection.
@@ -658,35 +661,37 @@
   ResetOnWriteFakeWebSocketStream() : closed_(false), weak_ptr_factory_(this) {}
 
   int WriteFrames(std::vector<std::unique_ptr<WebSocketFrame>>* frames,
-                  const CompletionCallback& callback) override {
+                  CompletionOnceCallback callback) override {
     base::ThreadTaskRunnerHandle::Get()->PostTask(
         FROM_HERE,
-        base::Bind(&ResetOnWriteFakeWebSocketStream::CallCallbackUnlessClosed,
-                   weak_ptr_factory_.GetWeakPtr(), callback,
-                   ERR_CONNECTION_RESET));
+        base::BindOnce(
+            &ResetOnWriteFakeWebSocketStream::CallCallbackUnlessClosed,
+            weak_ptr_factory_.GetWeakPtr(), std::move(callback),
+            ERR_CONNECTION_RESET));
     base::ThreadTaskRunnerHandle::Get()->PostTask(
         FROM_HERE,
-        base::Bind(&ResetOnWriteFakeWebSocketStream::CallCallbackUnlessClosed,
-                   weak_ptr_factory_.GetWeakPtr(), read_callback_,
-                   ERR_CONNECTION_RESET));
+        base::BindOnce(
+            &ResetOnWriteFakeWebSocketStream::CallCallbackUnlessClosed,
+            weak_ptr_factory_.GetWeakPtr(), std::move(read_callback_),
+            ERR_CONNECTION_RESET));
     return ERR_IO_PENDING;
   }
 
   int ReadFrames(std::vector<std::unique_ptr<WebSocketFrame>>* frames,
-                 const CompletionCallback& callback) override {
-    read_callback_ = callback;
+                 CompletionOnceCallback callback) override {
+    read_callback_ = std::move(callback);
     return ERR_IO_PENDING;
   }
 
   void Close() override { closed_ = true; }
 
  private:
-  void CallCallbackUnlessClosed(const CompletionCallback& callback, int value) {
+  void CallCallbackUnlessClosed(CompletionOnceCallback callback, int value) {
     if (!closed_)
-      callback.Run(value);
+      std::move(callback).Run(value);
   }
 
-  CompletionCallback read_callback_;
+  CompletionOnceCallback read_callback_;
   bool closed_;
   // An IO error can result in the socket being deleted, so we use weak pointers
   // to ensure correct behaviour in that case.
@@ -697,12 +702,29 @@
 // the extent that they are implemented in WebSocketCommon).
 class MockWebSocketStream : public WebSocketStream {
  public:
-  MOCK_METHOD2(ReadFrames,
-               int(std::vector<std::unique_ptr<WebSocketFrame>>* frames,
-                   const CompletionCallback& callback));
-  MOCK_METHOD2(WriteFrames,
-               int(std::vector<std::unique_ptr<WebSocketFrame>>* frames,
-                   const CompletionCallback& callback));
+  // GMock cannot save or forward move-only types like CompletionOnceCallback,
+  // therefore they have to be converted into a copyable type like
+  // CompletionRepeatingCallback.
+  int ReadFrames(std::vector<std::unique_ptr<WebSocketFrame>>* frames,
+                 CompletionOnceCallback callback) {
+    return ReadFramesInternal(
+        frames, callback ? base::AdaptCallbackForRepeating(std::move(callback))
+                         : CompletionRepeatingCallback());
+  }
+  int WriteFrames(std::vector<std::unique_ptr<WebSocketFrame>>* frames,
+                  CompletionOnceCallback callback) {
+    return WriteFramesInternal(
+        frames, callback ? base::AdaptCallbackForRepeating(std::move(callback))
+                         : CompletionRepeatingCallback());
+  }
+
+  MOCK_METHOD2(ReadFramesInternal,
+               int(std::vector<std::unique_ptr<WebSocketFrame>>*,
+                   const CompletionRepeatingCallback&));
+  MOCK_METHOD2(WriteFramesInternal,
+               int(std::vector<std::unique_ptr<WebSocketFrame>>*,
+                   const CompletionRepeatingCallback&));
+
   MOCK_METHOD0(Close, void());
   MOCK_CONST_METHOD0(GetSubProtocol, std::string());
   MOCK_CONST_METHOD0(GetExtensions, std::string());
@@ -1815,7 +1837,7 @@
   {
     InSequence s;
     EXPECT_CALL(checkpoint, Call(1));
-    EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
+    EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
         .WillOnce(Return(ERR_IO_PENDING));
     EXPECT_CALL(checkpoint, Call(2));
   }
@@ -1840,7 +1862,7 @@
   {
     InSequence s;
     EXPECT_CALL(checkpoint, Call(1));
-    EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
+    EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
         .WillOnce(Return(ERR_IO_PENDING));
     EXPECT_CALL(checkpoint, Call(2));
   }
@@ -1860,7 +1882,7 @@
 
   EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
   EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
-  EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
+  EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
       .WillOnce(ReturnFrames(&frames));
 
   set_stream(std::move(mock_stream_));
@@ -1879,10 +1901,10 @@
   EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
   {
     InSequence s;
-    EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
+    EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
         .WillOnce(ReturnFrames(&frames));
     EXPECT_CALL(checkpoint, Call(1));
-    EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
+    EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
         .WillOnce(Return(ERR_IO_PENDING));
   }
 
@@ -1905,11 +1927,11 @@
   EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
   {
     InSequence s;
-    EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
+    EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
         .WillOnce(ReturnFrames(&frames));
     EXPECT_CALL(checkpoint, Call(1));
     EXPECT_CALL(checkpoint, Call(2));
-    EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
+    EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
         .WillOnce(Return(ERR_IO_PENDING));
   }
 
@@ -2164,8 +2186,9 @@
        MASKED,      "NEEDS MASKING"}};
   EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
   EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
-  EXPECT_CALL(*mock_stream_, ReadFrames(_, _)).WillOnce(Return(ERR_IO_PENDING));
-  EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
+  EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
+      .WillOnce(Return(ERR_IO_PENDING));
+  EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected), _))
       .WillOnce(Return(OK));
 
   CreateChannelAndConnectSuccessfully();
@@ -2181,8 +2204,9 @@
        MASKED,      CLOSE_DATA(NORMAL_CLOSURE, "Success")}};
   EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
   EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
-  EXPECT_CALL(*mock_stream_, ReadFrames(_, _)).WillOnce(Return(ERR_IO_PENDING));
-  EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
+  EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
+      .WillOnce(Return(ERR_IO_PENDING));
+  EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected), _))
       .WillOnce(Return(OK));
 
   CreateChannelAndConnectSuccessfully();
@@ -2202,10 +2226,10 @@
        MASKED,      CLOSE_DATA(NORMAL_CLOSURE, "Close")}};
   EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
   EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
-  EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
+  EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
       .WillOnce(ReturnFrames(&frames))
       .WillRepeatedly(Return(ERR_IO_PENDING));
-  EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
+  EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected), _))
       .WillOnce(Return(OK));
 
   CreateChannelAndConnectSuccessfully();
@@ -2223,7 +2247,7 @@
 
   // We store the parameters that were passed to ReadFrames() so that we can
   // call them explicitly later.
-  CompletionCallback read_callback;
+  CompletionOnceCallback read_callback;
   std::vector<std::unique_ptr<WebSocketFrame>>* frames = nullptr;
 
   // These are not interesting.
@@ -2234,15 +2258,14 @@
   Checkpoint checkpoint;
   {
     InSequence s;
-    EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
-        .WillOnce(DoAll(SaveArg<0>(&frames),
-                        SaveArg<1>(&read_callback),
+    EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
+        .WillOnce(DoAll(SaveArg<0>(&frames), SaveArg<1>(&read_callback),
                         Return(ERR_IO_PENDING)));
     EXPECT_CALL(checkpoint, Call(1));
-    EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
+    EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected), _))
         .WillOnce(Return(OK));
     EXPECT_CALL(checkpoint, Call(2));
-    EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
+    EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
         .WillOnce(Return(ERR_IO_PENDING));
     EXPECT_CALL(checkpoint, Call(3));
     // WriteFrames() must not be called again. GoogleMock will ensure that the
@@ -2256,7 +2279,7 @@
   checkpoint.Call(2);
 
   *frames = CreateFrameVector(frames_init);
-  read_callback.Run(OK);
+  std::move(read_callback).Run(OK);
   checkpoint.Call(3);
 }
 
@@ -2268,10 +2291,10 @@
 
   EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
   EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
-  EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
+  EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
       .WillOnce(Return(ERR_IO_PENDING));
 
-  EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _));
+  EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected), _));
 
   CreateChannelAndConnectSuccessfully();
   ASSERT_EQ(CHANNEL_ALIVE, channel_->StartClosingHandshake(999, ""));
@@ -2286,10 +2309,10 @@
 
   EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
   EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
-  EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
+  EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
       .WillOnce(Return(ERR_IO_PENDING));
 
-  EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _));
+  EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected), _));
 
   CreateChannelAndConnectSuccessfully();
   ASSERT_EQ(CHANNEL_ALIVE,
@@ -2308,10 +2331,10 @@
       {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, MASKED, ""}};
   EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
   EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
-  EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
+  EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
       .WillOnce(ReturnFrames(&frames))
       .WillRepeatedly(Return(ERR_IO_PENDING));
-  EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
+  EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected), _))
       .WillOnce(Return(OK));
 
   CreateChannelAndConnectSuccessfully();
@@ -2324,10 +2347,10 @@
       {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, MASKED, ""}};
   EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
   EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
-  EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
+  EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
       .WillOnce(ReturnFrames(&frames))
       .WillRepeatedly(Return(ERR_IO_PENDING));
-  EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
+  EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected), _))
       .WillOnce(Return(OK));
 
   CreateChannelAndConnectSuccessfully();
@@ -2345,10 +2368,10 @@
 
   EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
   EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
-  EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
+  EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
       .WillOnce(ReturnFrames(&frames))
       .WillRepeatedly(Return(ERR_IO_PENDING));
-  EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
+  EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected), _))
       .WillOnce(Return(OK));
   EXPECT_CALL(*mock_stream_, Close());
 
@@ -2369,10 +2392,10 @@
        MASKED,      "Application data"}};
   EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
   EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
-  EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
+  EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
       .WillOnce(ReturnFrames(&frames))
       .WillRepeatedly(Return(ERR_IO_PENDING));
-  EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
+  EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected), _))
       .WillOnce(Return(OK));
 
   CreateChannelAndConnectSuccessfully();
@@ -2387,10 +2410,10 @@
       {FINAL_FRAME, WebSocketFrameHeader::kOpCodePong, MASKED, nullptr}};
   EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
   EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
-  EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
+  EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
       .WillOnce(ReturnFrames(&frames))
       .WillRepeatedly(Return(ERR_IO_PENDING));
-  EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
+  EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected), _))
       .WillOnce(Return(OK));
 
   CreateChannelAndConnectSuccessfully();
@@ -2409,22 +2432,21 @@
       {FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
        MASKED,      "World"}};
   std::vector<std::unique_ptr<WebSocketFrame>>* read_frames;
-  CompletionCallback read_callback;
+  CompletionOnceCallback read_callback;
   EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
   EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
-  EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
-      .WillOnce(DoAll(SaveArg<0>(&read_frames),
-                      SaveArg<1>(&read_callback),
+  EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
+      .WillOnce(DoAll(SaveArg<0>(&read_frames), SaveArg<1>(&read_callback),
                       Return(ERR_IO_PENDING)))
       .WillRepeatedly(Return(ERR_IO_PENDING));
   {
     InSequence s;
 
-    EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected1), _))
+    EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected1), _))
         .WillOnce(Return(OK));
-    EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected2), _))
+    EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected2), _))
         .WillOnce(Return(OK));
-    EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected3), _))
+    EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected3), _))
         .WillOnce(Return(OK));
   }
 
@@ -2432,7 +2454,7 @@
   channel_->SendFrame(false, WebSocketFrameHeader::kOpCodeText,
                       AsIOBuffer("Hello "), 6U);
   *read_frames = CreateFrameVector(frames);
-  read_callback.Run(OK);
+  std::move(read_callback).Run(OK);
   channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeContinuation,
                       AsIOBuffer("World"), 5U);
 }
@@ -2444,19 +2466,20 @@
       {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "Hello "}};
   static const InitFrame expected2[] = {
       {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "World"}};
-  CompletionCallback write_callback;
+  CompletionOnceCallback write_callback;
   Checkpoint checkpoint;
 
   EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
   EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
-  EXPECT_CALL(*mock_stream_, ReadFrames(_, _)).WillOnce(Return(ERR_IO_PENDING));
+  EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
+      .WillOnce(Return(ERR_IO_PENDING));
   {
     InSequence s;
     EXPECT_CALL(checkpoint, Call(1));
-    EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected1), _))
+    EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected1), _))
         .WillOnce(DoAll(SaveArg<1>(&write_callback), Return(ERR_IO_PENDING)));
     EXPECT_CALL(checkpoint, Call(2));
-    EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected2), _))
+    EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected2), _))
         .WillOnce(Return(ERR_IO_PENDING));
     EXPECT_CALL(checkpoint, Call(3));
   }
@@ -2468,7 +2491,7 @@
   channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText,
                       AsIOBuffer("World"), 5U);
   checkpoint.Call(2);
-  write_callback.Run(OK);
+  std::move(write_callback).Run(OK);
   checkpoint.Call(3);
 }
 
@@ -2484,16 +2507,17 @@
       {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "l"},
       {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "l"},
       {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "o"}};
-  CompletionCallback write_callback;
+  CompletionOnceCallback write_callback;
 
   EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
   EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
-  EXPECT_CALL(*mock_stream_, ReadFrames(_, _)).WillOnce(Return(ERR_IO_PENDING));
+  EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
+      .WillOnce(Return(ERR_IO_PENDING));
   {
     InSequence s;
-    EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected1), _))
+    EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected1), _))
         .WillOnce(DoAll(SaveArg<1>(&write_callback), Return(ERR_IO_PENDING)));
-    EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected2), _))
+    EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected2), _))
         .WillOnce(Return(ERR_IO_PENDING));
   }
 
@@ -2502,7 +2526,7 @@
     channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText,
                         AsIOBuffer(std::string(1, input_letters[i])), 1U);
   }
-  write_callback.Run(OK);
+  std::move(write_callback).Run(OK);
 }
 
 // When the renderer sends more on a channel than it has quota for, we send the
@@ -2513,8 +2537,9 @@
        MASKED,      CLOSE_DATA(GOING_AWAY, "")}};
   EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
   EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
-  EXPECT_CALL(*mock_stream_, ReadFrames(_, _)).WillOnce(Return(ERR_IO_PENDING));
-  EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
+  EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
+      .WillOnce(Return(ERR_IO_PENDING));
+  EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected), _))
       .WillOnce(Return(OK));
   EXPECT_CALL(*mock_stream_, Close());
 
@@ -2532,8 +2557,9 @@
 
   EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
   EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
-  EXPECT_CALL(*mock_stream_, ReadFrames(_, _)).WillOnce(Return(ERR_IO_PENDING));
-  EXPECT_CALL(*mock_stream_, WriteFrames(_, _))
+  EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
+      .WillOnce(Return(ERR_IO_PENDING));
+  EXPECT_CALL(*mock_stream_, WriteFramesInternal(_, _))
       .WillOnce(DoAll(SaveArg<0>(&frames), Return(ERR_IO_PENDING)));
 
   CreateChannelAndConnectSuccessfully();
@@ -2696,9 +2722,9 @@
                                         MASKED, CLOSE_DATA(GOING_AWAY, "")}};
   EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
   EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
-  EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
+  EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
       .WillRepeatedly(Return(ERR_IO_PENDING));
-  EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
+  EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected), _))
       .WillOnce(Return(OK));
   EXPECT_CALL(*mock_stream_, Close()).Times(1);
 
@@ -2721,10 +2747,10 @@
        CLOSE_DATA(PROTOCOL_ERROR, "Invalid UTF-8 in text frame")}};
   {
     InSequence s;
-    EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
+    EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
         .WillOnce(ReturnFrames(&frames))
         .WillRepeatedly(Return(ERR_IO_PENDING));
-    EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
+    EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected), _))
         .WillOnce(Return(OK));
     EXPECT_CALL(*mock_stream_, Close()).Times(1);
   }
@@ -2740,10 +2766,10 @@
   static const InitFrame expected[] = {
       {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, MASKED,
        CLOSE_DATA(PROTOCOL_ERROR, "Invalid UTF-8 in text frame")}};
-  EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
+  EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
       .WillOnce(ReturnFrames(&frames))
       .WillRepeatedly(Return(ERR_IO_PENDING));
-  EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
+  EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected), _))
       .WillOnce(Return(OK));
   EXPECT_CALL(*mock_stream_, Close()).Times(1);
 
@@ -2754,7 +2780,7 @@
 TEST_F(WebSocketChannelReceiveUtf8Test, IncompleteCharacterIncompleteMessage) {
   static const InitFrame frames[] = {
       {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "\xc2"}};
-  EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
+  EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
       .WillOnce(ReturnFrames(&frames))
       .WillRepeatedly(Return(ERR_IO_PENDING));
 
@@ -2769,10 +2795,10 @@
   static const InitFrame expected[] = {
       {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, MASKED,
        CLOSE_DATA(PROTOCOL_ERROR, "Invalid UTF-8 in text frame")}};
-  EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
+  EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
       .WillOnce(ReturnFrames(&frames))
       .WillRepeatedly(Return(ERR_IO_PENDING));
-  EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
+  EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected), _))
       .WillOnce(Return(OK));
   EXPECT_CALL(*mock_stream_, Close()).Times(1);
 
@@ -2786,7 +2812,7 @@
       {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "\xf1"},
       {FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
        NOT_MASKED,  "\x80\xa0\xbf"}};
-  EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
+  EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
       .WillOnce(ReturnFrames(&frames))
       .WillRepeatedly(Return(ERR_IO_PENDING));
 
@@ -2802,10 +2828,10 @@
   static const InitFrame expected[] = {
       {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, MASKED,
        CLOSE_DATA(PROTOCOL_ERROR, "Invalid UTF-8 in text frame")}};
-  EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
+  EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
       .WillOnce(ReturnFrames(&frames))
       .WillRepeatedly(Return(ERR_IO_PENDING));
-  EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
+  EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected), _))
       .WillOnce(Return(OK));
   EXPECT_CALL(*mock_stream_, Close()).Times(1);
 
@@ -2823,10 +2849,10 @@
   static const InitFrame expected[] = {
       {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, MASKED,
        CLOSE_DATA(PROTOCOL_ERROR, "Invalid UTF-8 in text frame")}};
-  EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
+  EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
       .WillOnce(ReturnFrames(&frames))
       .WillRepeatedly(Return(ERR_IO_PENDING));
-  EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
+  EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected), _))
       .WillOnce(Return(OK));
   EXPECT_CALL(*mock_stream_, Close()).Times(1);
 
@@ -2841,7 +2867,7 @@
        NOT_MASKED,      "bar"},
       {FINAL_FRAME,     WebSocketFrameHeader::kOpCodeContinuation,
        NOT_MASKED,      "\xff"}};
-  EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
+  EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
       .WillOnce(ReturnFrames(&frames))
       .WillRepeatedly(Return(ERR_IO_PENDING));
 
@@ -2853,7 +2879,7 @@
   static const InitFrame frames[] = {
       {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "foo"},
       {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "bar"}};
-  EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
+  EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
       .WillOnce(ReturnFrames(&frames))
       .WillRepeatedly(Return(ERR_IO_PENDING));
 
@@ -2975,7 +3001,7 @@
        MASKED,      CLOSE_DATA(NORMAL_CLOSURE, "OK")}};
   EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
   EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
-  EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
+  EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
       .WillOnce(ReturnFrames(&frames))
       .WillRepeatedly(Return(ERR_IO_PENDING));
   {
@@ -2984,7 +3010,7 @@
     // frame before calling ReadFrames() again, but that is an implementation
     // detail and better not to consider required behaviour.
     InSequence s;
-    EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
+    EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected), _))
         .WillOnce(Return(OK));
     EXPECT_CALL(*mock_stream_, Close()).Times(1);
   }
@@ -3000,9 +3026,9 @@
        MASKED,      CLOSE_DATA(PROTOCOL_ERROR, "WebSocket Protocol Error")}};
   EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
   EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
-  EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
+  EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
       .WillOnce(Return(ERR_WS_PROTOCOL_ERROR));
-  EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
+  EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected), _))
       .WillOnce(Return(OK));
   EXPECT_CALL(*mock_stream_, Close());
 
@@ -3041,14 +3067,14 @@
        MASKED,      CLOSE_DATA(NORMAL_CLOSURE, "OK")}};
   EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
   EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
-  EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
+  EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
       .WillOnce(ReturnFrames(&frames))
       .WillRepeatedly(Return(ERR_IO_PENDING));
   Checkpoint checkpoint;
   TestClosure completion;
   {
     InSequence s;
-    EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
+    EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected), _))
         .WillOnce(Return(OK));
     EXPECT_CALL(checkpoint, Call(1));
     EXPECT_CALL(*mock_stream_, Close())
@@ -3070,12 +3096,12 @@
        MASKED,      CLOSE_DATA(NORMAL_CLOSURE, "OK")}};
   EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
   EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
-  EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
+  EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
       .WillRepeatedly(Return(ERR_IO_PENDING));
   TestClosure completion;
   {
     InSequence s;
-    EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
+    EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected), _))
         .WillOnce(Return(OK));
     EXPECT_CALL(*mock_stream_, Close())
         .WillOnce(InvokeClosure(completion.closure()));
@@ -3102,23 +3128,22 @@
   EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
   TestClosure completion;
   std::vector<std::unique_ptr<WebSocketFrame>>* read_frames = nullptr;
-  CompletionCallback read_callback;
+  CompletionOnceCallback read_callback;
   {
     InSequence s;
     // Copy the arguments to ReadFrames so that the test can call the callback
     // after it has send the close message.
-    EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
-        .WillOnce(DoAll(SaveArg<0>(&read_frames),
-                        SaveArg<1>(&read_callback),
+    EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
+        .WillOnce(DoAll(SaveArg<0>(&read_frames), SaveArg<1>(&read_callback),
                         Return(ERR_IO_PENDING)));
     // The first real event that happens is the client sending the Close
     // message.
-    EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
+    EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected), _))
         .WillOnce(Return(OK));
     // The |read_frames| callback is called (from this test case) at this
     // point. ReadFrames is called again by WebSocketChannel, waiting for
     // ERR_CONNECTION_CLOSED.
-    EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
+    EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
         .WillOnce(Return(ERR_IO_PENDING));
     // The timeout happens and so WebSocketChannel closes the stream.
     EXPECT_CALL(*mock_stream_, Close())
@@ -3131,7 +3156,7 @@
   ASSERT_TRUE(read_frames);
   // Provide the "Close" message from the server.
   *read_frames = CreateFrameVector(frames);
-  read_callback.Run(OK);
+  std::move(read_callback).Run(OK);
   completion.WaitForResult();
 }
 
diff --git a/net/websockets/websocket_deflate_stream.cc b/net/websockets/websocket_deflate_stream.cc
index dd048a8..ac20c1b 100644
--- a/net/websockets/websocket_deflate_stream.cc
+++ b/net/websockets/websocket_deflate_stream.cc
@@ -14,7 +14,6 @@
 #include "base/bind.h"
 #include "base/logging.h"
 #include "base/memory/scoped_refptr.h"
-#include "net/base/completion_callback.h"
 #include "net/base/io_buffer.h"
 #include "net/base/net_errors.h"
 #include "net/websockets/websocket_deflate_parameters.h"
@@ -63,30 +62,28 @@
 
 int WebSocketDeflateStream::ReadFrames(
     std::vector<std::unique_ptr<WebSocketFrame>>* frames,
-    const CompletionCallback& callback) {
+    CompletionOnceCallback callback) {
+  read_callback_ = std::move(callback);
   int result = stream_->ReadFrames(
-      frames,
-      base::Bind(&WebSocketDeflateStream::OnReadComplete,
-                 base::Unretained(this),
-                 base::Unretained(frames),
-                 callback));
+      frames, base::BindOnce(&WebSocketDeflateStream::OnReadComplete,
+                             base::Unretained(this), base::Unretained(frames)));
   if (result < 0)
     return result;
   DCHECK_EQ(OK, result);
   DCHECK(!frames->empty());
 
-  return InflateAndReadIfNecessary(frames, callback);
+  return InflateAndReadIfNecessary(frames);
 }
 
 int WebSocketDeflateStream::WriteFrames(
     std::vector<std::unique_ptr<WebSocketFrame>>* frames,
-    const CompletionCallback& callback) {
+    CompletionOnceCallback callback) {
   int result = Deflate(frames);
   if (result != OK)
     return result;
   if (frames->empty())
     return OK;
-  return stream_->WriteFrames(frames, callback);
+  return stream_->WriteFrames(frames, std::move(callback));
 }
 
 void WebSocketDeflateStream::Close() { stream_->Close(); }
@@ -101,17 +98,16 @@
 
 void WebSocketDeflateStream::OnReadComplete(
     std::vector<std::unique_ptr<WebSocketFrame>>* frames,
-    const CompletionCallback& callback,
     int result) {
   if (result != OK) {
     frames->clear();
-    callback.Run(result);
+    std::move(read_callback_).Run(result);
     return;
   }
 
-  int r = InflateAndReadIfNecessary(frames, callback);
+  int r = InflateAndReadIfNecessary(frames);
   if (r != ERR_IO_PENDING)
-    callback.Run(r);
+    std::move(read_callback_).Run(r);
 }
 
 int WebSocketDeflateStream::Deflate(
@@ -375,18 +371,15 @@
 }
 
 int WebSocketDeflateStream::InflateAndReadIfNecessary(
-    std::vector<std::unique_ptr<WebSocketFrame>>* frames,
-    const CompletionCallback& callback) {
+    std::vector<std::unique_ptr<WebSocketFrame>>* frames) {
   int result = Inflate(frames);
   while (result == ERR_IO_PENDING) {
     DCHECK(frames->empty());
 
     result = stream_->ReadFrames(
         frames,
-        base::Bind(&WebSocketDeflateStream::OnReadComplete,
-                   base::Unretained(this),
-                   base::Unretained(frames),
-                   callback));
+        base::BindOnce(&WebSocketDeflateStream::OnReadComplete,
+                       base::Unretained(this), base::Unretained(frames)));
     if (result < 0)
       break;
     DCHECK_EQ(OK, result);
diff --git a/net/websockets/websocket_deflate_stream.h b/net/websockets/websocket_deflate_stream.h
index a68d512..1bd85bd9 100644
--- a/net/websockets/websocket_deflate_stream.h
+++ b/net/websockets/websocket_deflate_stream.h
@@ -12,7 +12,7 @@
 #include <vector>
 
 #include "base/macros.h"
-#include "net/base/completion_callback.h"
+#include "net/base/completion_once_callback.h"
 #include "net/base/net_export.h"
 #include "net/websockets/websocket_deflater.h"
 #include "net/websockets/websocket_frame.h"
@@ -47,9 +47,9 @@
 
   // WebSocketStream functions.
   int ReadFrames(std::vector<std::unique_ptr<WebSocketFrame>>* frames,
-                 const CompletionCallback& callback) override;
+                 CompletionOnceCallback callback) override;
   int WriteFrames(std::vector<std::unique_ptr<WebSocketFrame>>* frames,
-                  const CompletionCallback& callback) override;
+                  CompletionOnceCallback callback) override;
   void Close() override;
   std::string GetSubProtocol() const override;
   std::string GetExtensions() const override;
@@ -70,7 +70,6 @@
 
   // Handles asynchronous completion of ReadFrames() call on |stream_|.
   void OnReadComplete(std::vector<std::unique_ptr<WebSocketFrame>>* frames,
-                      const CompletionCallback& callback,
                       int result);
 
   // This function deflates |frames| and stores the result to |frames| itself.
@@ -89,8 +88,7 @@
   int Inflate(std::vector<std::unique_ptr<WebSocketFrame>>* frames);
 
   int InflateAndReadIfNecessary(
-      std::vector<std::unique_ptr<WebSocketFrame>>* frames,
-      const CompletionCallback& callback);
+      std::vector<std::unique_ptr<WebSocketFrame>>* frames);
 
   const std::unique_ptr<WebSocketStream> stream_;
   WebSocketDeflater deflater_;
@@ -101,6 +99,9 @@
   WebSocketFrameHeader::OpCode current_writing_opcode_;
   std::unique_ptr<WebSocketDeflatePredictor> predictor_;
 
+  // User callback saved for asynchronous reads.
+  CompletionOnceCallback read_callback_;
+
   DISALLOW_COPY_AND_ASSIGN(WebSocketDeflateStream);
 };
 
diff --git a/net/websockets/websocket_deflate_stream_fuzzer.cc b/net/websockets/websocket_deflate_stream_fuzzer.cc
index 8c766c1..b18b7306 100644
--- a/net/websockets/websocket_deflate_stream_fuzzer.cc
+++ b/net/websockets/websocket_deflate_stream_fuzzer.cc
@@ -13,7 +13,6 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_piece.h"
 #include "base/test/fuzzed_data_provider.h"
-#include "net/base/completion_callback.h"
 #include "net/base/io_buffer.h"
 #include "net/base/net_errors.h"
 #include "net/websockets/websocket_deflate_parameters.h"
@@ -48,7 +47,7 @@
       : fuzzed_data_provider_(fuzzed_data_provider) {}
 
   int ReadFrames(std::vector<std::unique_ptr<WebSocketFrame>>* frames,
-                 const CompletionCallback& callback) override {
+                 CompletionOnceCallback callback) override {
     if (fuzzed_data_provider_->remaining_bytes() < MIN_BYTES_TO_CREATE_A_FRAME)
       return ERR_CONNECTION_CLOSED;
     while (fuzzed_data_provider_->remaining_bytes() > 0)
@@ -57,7 +56,7 @@
   }
 
   int WriteFrames(std::vector<std::unique_ptr<WebSocketFrame>>* frames,
-                  const CompletionCallback& callback) override {
+                  CompletionOnceCallback callback) override {
     return ERR_FILE_NOT_FOUND;
   }
 
@@ -117,7 +116,7 @@
       std::make_unique<WebSocketFuzzedStream>(&fuzzed_data_provider),
       parameters, std::make_unique<WebSocketDeflatePredictorImpl>());
   std::vector<std::unique_ptr<net::WebSocketFrame>> frames;
-  deflate_stream.ReadFrames(&frames, CompletionCallback());
+  deflate_stream.ReadFrames(&frames, CompletionOnceCallback());
 }
 
 }  // namespace
diff --git a/net/websockets/websocket_deflate_stream_test.cc b/net/websockets/websocket_deflate_stream_test.cc
index b76e5ec..1caa4cd0 100644
--- a/net/websockets/websocket_deflate_stream_test.cc
+++ b/net/websockets/websocket_deflate_stream_test.cc
@@ -13,12 +13,12 @@
 #include <vector>
 
 #include "base/bind.h"
+#include "base/callback_helpers.h"
 #include "base/containers/circular_deque.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/test/mock_callback.h"
-#include "net/base/completion_callback.h"
 #include "net/base/io_buffer.h"
 #include "net/base/net_errors.h"
 #include "net/test/gtest_util.h"
@@ -108,12 +108,29 @@
 
 class MockWebSocketStream : public WebSocketStream {
  public:
-  MOCK_METHOD2(ReadFrames,
+  // GMock cannot save or forward move-only types like CompletionOnceCallback,
+  // therefore they have to be converted into a copyable type like
+  // CompletionRepeatingCallback.
+  int ReadFrames(std::vector<std::unique_ptr<WebSocketFrame>>* frames,
+                 CompletionOnceCallback callback) {
+    return ReadFramesInternal(
+        frames, callback ? base::AdaptCallbackForRepeating(std::move(callback))
+                         : CompletionRepeatingCallback());
+  }
+  int WriteFrames(std::vector<std::unique_ptr<WebSocketFrame>>* frames,
+                  CompletionOnceCallback callback) {
+    return WriteFramesInternal(
+        frames, callback ? base::AdaptCallbackForRepeating(std::move(callback))
+                         : CompletionRepeatingCallback());
+  }
+
+  MOCK_METHOD2(ReadFramesInternal,
                int(std::vector<std::unique_ptr<WebSocketFrame>>*,
-                   const CompletionCallback&));
-  MOCK_METHOD2(WriteFrames,
+                   const CompletionRepeatingCallback&));
+  MOCK_METHOD2(WriteFramesInternal,
                int(std::vector<std::unique_ptr<WebSocketFrame>>*,
-                   const CompletionCallback&));
+                   const CompletionRepeatingCallback&));
+
   MOCK_METHOD0(Close, void());
   MOCK_CONST_METHOD0(GetSubProtocol, std::string());
   MOCK_CONST_METHOD0(GetExtensions, std::string());
@@ -313,7 +330,7 @@
   }
 
   int Call(std::vector<std::unique_ptr<WebSocketFrame>>* frames,
-           const CompletionCallback& callback) {
+           const CompletionRepeatingCallback& callback) {
     DCHECK(frames->empty());
     frames_passed_ = frames;
     callback_ = callback;
@@ -322,14 +339,14 @@
   }
 
   int result() const { return result_; }
-  const CompletionCallback& callback() const { return callback_; }
+  const CompletionRepeatingCallback& callback() const { return callback_; }
   std::vector<std::unique_ptr<WebSocketFrame>>* frames_passed() {
     return frames_passed_;
   }
 
  private:
   int result_;
-  CompletionCallback callback_;
+  CompletionRepeatingCallback callback_;
   std::vector<std::unique_ptr<WebSocketFrame>> frames_to_output_;
   std::vector<std::unique_ptr<WebSocketFrame>>* frames_passed_;
 };
@@ -344,7 +361,7 @@
       : result_(result), predictor_(predictor) {}
 
   int Call(std::vector<std::unique_ptr<WebSocketFrame>>* frames,
-           const CompletionCallback& callback) {
+           const CompletionRepeatingCallback& callback) {
     frames_.insert(frames_.end(), std::make_move_iterator(frames->begin()),
                    std::make_move_iterator(frames->end()));
     frames->clear();
@@ -354,25 +371,24 @@
   }
 
   int result() const { return result_; }
-  const CompletionCallback& callback() const { return callback_; }
+  const CompletionRepeatingCallback& callback() const { return callback_; }
   std::vector<std::unique_ptr<WebSocketFrame>>* frames() { return &frames_; }
 
  private:
   int result_;
-  CompletionCallback callback_;
+  CompletionRepeatingCallback callback_;
   std::vector<std::unique_ptr<WebSocketFrame>> frames_;
   WebSocketDeflatePredictorMock* predictor_;
 };
 
 TEST_F(WebSocketDeflateStreamTest, ReadFailedImmediately) {
   std::vector<std::unique_ptr<WebSocketFrame>> frames;
-  CompletionCallback callback;
   {
     InSequence s;
-    EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
+    EXPECT_CALL(*mock_stream_, ReadFramesInternal(&frames, _))
         .WillOnce(Return(ERR_FAILED));
   }
-  EXPECT_THAT(deflate_stream_->ReadFrames(&frames, callback),
+  EXPECT_THAT(deflate_stream_->ReadFrames(&frames, CompletionOnceCallback()),
               IsError(ERR_FAILED));
 }
 
@@ -387,11 +403,11 @@
 
   {
     InSequence s;
-    EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
+    EXPECT_CALL(*mock_stream_, ReadFramesInternal(&frames, _))
         .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
   }
-  CompletionCallback callback;
-  ASSERT_THAT(deflate_stream_->ReadFrames(&frames, callback), IsOk());
+  ASSERT_THAT(deflate_stream_->ReadFrames(&frames, CompletionOnceCallback()),
+              IsOk());
   ASSERT_EQ(1u, frames.size());
   EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode);
   EXPECT_TRUE(frames[0]->header.final);
@@ -402,12 +418,12 @@
 TEST_F(WebSocketDeflateStreamTest, ReadUncompressedFrameAsync) {
   ReadFramesStub stub(ERR_IO_PENDING);
   std::vector<std::unique_ptr<WebSocketFrame>> frames;
-  base::MockCallback<CompletionCallback> mock_callback;
+  base::MockCallback<CompletionOnceCallback> mock_callback;
   base::MockCallback<base::Closure> checkpoint;
 
   {
     InSequence s;
-    EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
+    EXPECT_CALL(*mock_stream_, ReadFramesInternal(&frames, _))
         .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
     EXPECT_CALL(checkpoint, Run());
     EXPECT_CALL(mock_callback, Run(OK));
@@ -433,12 +449,12 @@
 TEST_F(WebSocketDeflateStreamTest, ReadFailedAsync) {
   ReadFramesStub stub(ERR_IO_PENDING);
   std::vector<std::unique_ptr<WebSocketFrame>> frames;
-  base::MockCallback<CompletionCallback> mock_callback;
+  base::MockCallback<CompletionOnceCallback> mock_callback;
   base::MockCallback<base::Closure> checkpoint;
 
   {
     InSequence s;
-    EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
+    EXPECT_CALL(*mock_stream_, ReadFramesInternal(&frames, _))
         .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
     EXPECT_CALL(checkpoint, Run());
     EXPECT_CALL(mock_callback, Run(ERR_FAILED));
@@ -464,14 +480,14 @@
            kFinal | kReserved1,
            std::string("\xf2\x48\xcd\xc9\xc9\x07\x00", 7));
   ReadFramesStub stub(OK, &frames_to_output);
-  CompletionCallback callback;
   std::vector<std::unique_ptr<WebSocketFrame>> frames;
   {
     InSequence s;
-    EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
+    EXPECT_CALL(*mock_stream_, ReadFramesInternal(&frames, _))
         .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
   }
-  ASSERT_THAT(deflate_stream_->ReadFrames(&frames, callback), IsOk());
+  ASSERT_THAT(deflate_stream_->ReadFrames(&frames, CompletionOnceCallback()),
+              IsOk());
   ASSERT_EQ(1u, frames.size());
   EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode);
   EXPECT_TRUE(frames[0]->header.final);
@@ -482,12 +498,12 @@
 TEST_F(WebSocketDeflateStreamTest, ReadCompressedFrameAsync) {
   ReadFramesStub stub(ERR_IO_PENDING);
 
-  base::MockCallback<CompletionCallback> mock_callback;
+  base::MockCallback<CompletionOnceCallback> mock_callback;
   base::MockCallback<base::Closure> checkpoint;
   std::vector<std::unique_ptr<WebSocketFrame>> frames;
   {
     InSequence s;
-    EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
+    EXPECT_CALL(*mock_stream_, ReadFramesInternal(&frames, _))
         .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
     EXPECT_CALL(checkpoint, Run());
     EXPECT_CALL(mock_callback, Run(OK));
@@ -520,13 +536,13 @@
            kReserved1,
            data1);
   ReadFramesStub stub1(OK, &frames_to_output), stub2(ERR_IO_PENDING);
-  base::MockCallback<CompletionCallback> mock_callback;
+  base::MockCallback<CompletionOnceCallback> mock_callback;
   base::MockCallback<base::Closure> checkpoint;
   std::vector<std::unique_ptr<WebSocketFrame>> frames;
 
   {
     InSequence s;
-    EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
+    EXPECT_CALL(*mock_stream_, ReadFramesInternal(&frames, _))
         .WillOnce(Invoke(&stub1, &ReadFramesStub::Call))
         .WillOnce(Invoke(&stub2, &ReadFramesStub::Call));
     EXPECT_CALL(checkpoint, Run());
@@ -559,16 +575,15 @@
            kFinal | kReserved1,
            data);
   ReadFramesStub stub(OK, &frames_to_output);
-  CompletionCallback callback;
   std::vector<std::unique_ptr<WebSocketFrame>> frames;
 
   {
     InSequence s;
-    EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
+    EXPECT_CALL(*mock_stream_, ReadFramesInternal(&frames, _))
         .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
   }
   ASSERT_EQ(ERR_WS_PROTOCOL_ERROR,
-            deflate_stream_->ReadFrames(&frames, callback));
+            deflate_stream_->ReadFrames(&frames, CompletionOnceCallback()));
   ASSERT_EQ(0u, frames.size());
 }
 
@@ -585,15 +600,15 @@
            kFinal,
            data2);
   ReadFramesStub stub(OK, &frames_to_output);
-  CompletionCallback callback;
   std::vector<std::unique_ptr<WebSocketFrame>> frames;
 
   {
     InSequence s;
-    EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
+    EXPECT_CALL(*mock_stream_, ReadFramesInternal(&frames, _))
         .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
   }
-  ASSERT_THAT(deflate_stream_->ReadFrames(&frames, callback), IsOk());
+  ASSERT_THAT(deflate_stream_->ReadFrames(&frames, CompletionOnceCallback()),
+              IsOk());
   ASSERT_EQ(1u, frames.size());
   EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode);
   EXPECT_TRUE(frames[0]->header.final);
@@ -610,15 +625,15 @@
            WebSocketFrameHeader::kOpCodeContinuation,
            kFinal);
   ReadFramesStub stub(OK, &frames_to_output);
-  CompletionCallback callback;
   std::vector<std::unique_ptr<WebSocketFrame>> frames;
 
   {
     InSequence s;
-    EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
+    EXPECT_CALL(*mock_stream_, ReadFramesInternal(&frames, _))
         .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
   }
-  ASSERT_THAT(deflate_stream_->ReadFrames(&frames, callback), IsOk());
+  ASSERT_THAT(deflate_stream_->ReadFrames(&frames, CompletionOnceCallback()),
+              IsOk());
   ASSERT_EQ(2u, frames.size());
   EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode);
   EXPECT_FALSE(frames[0]->header.final);
@@ -641,15 +656,15 @@
            WebSocketFrameHeader::kOpCodeContinuation,
            kFinal);
   ReadFramesStub stub(OK, &frames_to_output);
-  CompletionCallback callback;
   std::vector<std::unique_ptr<WebSocketFrame>> frames;
 
   {
     InSequence s;
-    EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
+    EXPECT_CALL(*mock_stream_, ReadFramesInternal(&frames, _))
         .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
   }
-  ASSERT_THAT(deflate_stream_->ReadFrames(&frames, callback), IsOk());
+  ASSERT_THAT(deflate_stream_->ReadFrames(&frames, CompletionOnceCallback()),
+              IsOk());
   ASSERT_EQ(1u, frames.size());
   EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode);
   EXPECT_TRUE(frames[0]->header.final);
@@ -669,15 +684,15 @@
            WebSocketFrameHeader::kOpCodeContinuation,
            kFinal);
   ReadFramesStub stub(OK, &frames_to_output);
-  CompletionCallback callback;
   std::vector<std::unique_ptr<WebSocketFrame>> frames;
 
   {
     InSequence s;
-    EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
+    EXPECT_CALL(*mock_stream_, ReadFramesInternal(&frames, _))
         .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
   }
-  ASSERT_THAT(deflate_stream_->ReadFrames(&frames, callback), IsOk());
+  ASSERT_THAT(deflate_stream_->ReadFrames(&frames, CompletionOnceCallback()),
+              IsOk());
   ASSERT_EQ(1u, frames.size());
   EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode);
   EXPECT_TRUE(frames[0]->header.final);
@@ -696,15 +711,15 @@
   AppendTo(&frames_to_output, WebSocketFrameHeader::kOpCodePing, kFinal);
   AppendTo(&frames_to_output, WebSocketFrameHeader::kOpCodeText, kFinal, data2);
   ReadFramesStub stub(OK, &frames_to_output);
-  CompletionCallback callback;
   std::vector<std::unique_ptr<WebSocketFrame>> frames;
 
   {
     InSequence s;
-    EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
+    EXPECT_CALL(*mock_stream_, ReadFramesInternal(&frames, _))
         .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
   }
-  ASSERT_THAT(deflate_stream_->ReadFrames(&frames, callback), IsOk());
+  ASSERT_THAT(deflate_stream_->ReadFrames(&frames, CompletionOnceCallback()),
+              IsOk());
   ASSERT_EQ(2u, frames.size());
   EXPECT_EQ(WebSocketFrameHeader::kOpCodePing, frames[0]->header.opcode);
   EXPECT_TRUE(frames[0]->header.final);
@@ -730,15 +745,15 @@
            ToString(deflater.GetOutput(deflater.CurrentOutputSize())));
 
   ReadFramesStub stub(OK, &frames_to_output);
-  CompletionCallback callback;
   std::vector<std::unique_ptr<WebSocketFrame>> frames;
   {
     InSequence s;
-    EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
+    EXPECT_CALL(*mock_stream_, ReadFramesInternal(&frames, _))
         .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
   }
 
-  ASSERT_THAT(deflate_stream_->ReadFrames(&frames, callback), IsOk());
+  ASSERT_THAT(deflate_stream_->ReadFrames(&frames, CompletionOnceCallback()),
+              IsOk());
   ASSERT_EQ(3u, frames.size());
   EXPECT_EQ(WebSocketFrameHeader::kOpCodeBinary, frames[0]->header.opcode);
   EXPECT_FALSE(frames[0]->header.final);
@@ -776,15 +791,15 @@
            "");
 
   ReadFramesStub stub(OK, &frames_to_output);
-  CompletionCallback callback;
   std::vector<std::unique_ptr<WebSocketFrame>> frames;
   {
     InSequence s;
-    EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
+    EXPECT_CALL(*mock_stream_, ReadFramesInternal(&frames, _))
         .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
   }
 
-  ASSERT_THAT(deflate_stream_->ReadFrames(&frames, callback), IsOk());
+  ASSERT_THAT(deflate_stream_->ReadFrames(&frames, CompletionOnceCallback()),
+              IsOk());
   ASSERT_EQ(2u, frames.size());
   EXPECT_EQ(WebSocketFrameHeader::kOpCodeBinary, frames[0]->header.opcode);
   EXPECT_FALSE(frames[0]->header.final);
@@ -813,16 +828,15 @@
            kFinal | kReserved1,
            data2);
   ReadFramesStub stub(OK, &frames_to_output);
-  CompletionCallback callback;
   std::vector<std::unique_ptr<WebSocketFrame>> frames;
 
   {
     InSequence s;
-    EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
+    EXPECT_CALL(*mock_stream_, ReadFramesInternal(&frames, _))
         .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
   }
   ASSERT_EQ(ERR_WS_PROTOCOL_ERROR,
-            deflate_stream_->ReadFrames(&frames, callback));
+            deflate_stream_->ReadFrames(&frames, CompletionOnceCallback()));
 }
 
 TEST_F(WebSocketDeflateStreamTest,
@@ -837,16 +851,15 @@
            kFinal | kReserved1,
            "world");
   ReadFramesStub stub(OK, &frames_to_output);
-  CompletionCallback callback;
   std::vector<std::unique_ptr<WebSocketFrame>> frames;
 
   {
     InSequence s;
-    EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
+    EXPECT_CALL(*mock_stream_, ReadFramesInternal(&frames, _))
         .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
   }
   ASSERT_EQ(ERR_WS_PROTOCOL_ERROR,
-            deflate_stream_->ReadFrames(&frames, callback));
+            deflate_stream_->ReadFrames(&frames, CompletionOnceCallback()));
 }
 
 TEST_F(WebSocketDeflateStreamTest, ReadCompressedMessages) {
@@ -861,15 +874,15 @@
            kFinal | kReserved1,
            std::string("\x4a\x86\x33\x8d\x00\x00", 6));
   ReadFramesStub stub(OK, &frames_to_output);
-  CompletionCallback callback;
   std::vector<std::unique_ptr<WebSocketFrame>> frames;
 
   {
     InSequence s;
-    EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
+    EXPECT_CALL(*mock_stream_, ReadFramesInternal(&frames, _))
         .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
   }
-  ASSERT_THAT(deflate_stream_->ReadFrames(&frames, callback), IsOk());
+  ASSERT_THAT(deflate_stream_->ReadFrames(&frames, CompletionOnceCallback()),
+              IsOk());
   ASSERT_EQ(2u, frames.size());
   EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode);
   EXPECT_TRUE(frames[0]->header.final);
@@ -892,15 +905,15 @@
            kFinal,
            "uncompressed2");
   ReadFramesStub stub(OK, &frames_to_output);
-  CompletionCallback callback;
   std::vector<std::unique_ptr<WebSocketFrame>> frames;
 
   {
     InSequence s;
-    EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
+    EXPECT_CALL(*mock_stream_, ReadFramesInternal(&frames, _))
         .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
   }
-  ASSERT_THAT(deflate_stream_->ReadFrames(&frames, callback), IsOk());
+  ASSERT_THAT(deflate_stream_->ReadFrames(&frames, CompletionOnceCallback()),
+              IsOk());
   ASSERT_EQ(2u, frames.size());
   EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode);
   EXPECT_TRUE(frames[0]->header.final);
@@ -925,15 +938,15 @@
            kFinal,
            "uncompressed");
   ReadFramesStub stub(OK, &frames_to_output);
-  CompletionCallback callback;
   std::vector<std::unique_ptr<WebSocketFrame>> frames;
 
   {
     InSequence s;
-    EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
+    EXPECT_CALL(*mock_stream_, ReadFramesInternal(&frames, _))
         .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
   }
-  ASSERT_THAT(deflate_stream_->ReadFrames(&frames, callback), IsOk());
+  ASSERT_THAT(deflate_stream_->ReadFrames(&frames, CompletionOnceCallback()),
+              IsOk());
   ASSERT_EQ(2u, frames.size());
   EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode);
   EXPECT_TRUE(frames[0]->header.final);
@@ -958,15 +971,15 @@
            std::string(
                "\x4a\xce\xcf\x2d\x28\x4a\x2d\x2e\x4e\x4d\x01\x00", 12));
   ReadFramesStub stub(OK, &frames_to_output);
-  CompletionCallback callback;
   std::vector<std::unique_ptr<WebSocketFrame>> frames;
 
   {
     InSequence s;
-    EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
+    EXPECT_CALL(*mock_stream_, ReadFramesInternal(&frames, _))
         .WillOnce(Invoke(&stub, &ReadFramesStub::Call));
   }
-  ASSERT_THAT(deflate_stream_->ReadFrames(&frames, callback), IsOk());
+  ASSERT_THAT(deflate_stream_->ReadFrames(&frames, CompletionOnceCallback()),
+              IsOk());
   ASSERT_EQ(2u, frames.size());
   EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode);
   EXPECT_TRUE(frames[0]->header.final);
@@ -983,15 +996,15 @@
   std::vector<std::unique_ptr<ReadFramesStub>> stub_vector;
   stub_vector.push_back(std::make_unique<ReadFramesStub>(ERR_IO_PENDING));
   stub_vector.push_back(std::make_unique<ReadFramesStub>(ERR_IO_PENDING));
-  base::MockCallback<CompletionCallback> mock_callback;
+  base::MockCallback<CompletionOnceCallback> mock_callback;
   std::vector<std::unique_ptr<WebSocketFrame>> frames;
 
   {
     InSequence s;
-    EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
+    EXPECT_CALL(*mock_stream_, ReadFramesInternal(&frames, _))
         .WillOnce(Invoke(stub_vector[0].get(), &ReadFramesStub::Call));
 
-    EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _))
+    EXPECT_CALL(*mock_stream_, ReadFramesInternal(&frames, _))
         .WillOnce(Invoke(stub_vector[1].get(), &ReadFramesStub::Call));
 
     EXPECT_CALL(mock_callback, Run(OK));
@@ -1016,42 +1029,41 @@
 
 TEST_F(WebSocketDeflateStreamTest, WriteEmpty) {
   std::vector<std::unique_ptr<WebSocketFrame>> frames;
-  CompletionCallback callback;
   {
     InSequence s;
-    EXPECT_CALL(*mock_stream_, WriteFrames(&frames, _)).Times(0);
+    EXPECT_CALL(*mock_stream_, WriteFramesInternal(&frames, _)).Times(0);
   }
-  EXPECT_THAT(deflate_stream_->WriteFrames(&frames, callback), IsOk());
+  EXPECT_THAT(deflate_stream_->WriteFrames(&frames, CompletionOnceCallback()),
+              IsOk());
 }
 
 TEST_F(WebSocketDeflateStreamTest, WriteFailedImmediately) {
   std::vector<std::unique_ptr<WebSocketFrame>> frames;
-  CompletionCallback callback;
   {
     InSequence s;
-    EXPECT_CALL(*mock_stream_, WriteFrames(&frames, _))
+    EXPECT_CALL(*mock_stream_, WriteFramesInternal(&frames, _))
         .WillOnce(Return(ERR_FAILED));
   }
 
   AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kFinal, "hello");
   predictor_->AddFramesToBeInput(frames);
-  EXPECT_THAT(deflate_stream_->WriteFrames(&frames, callback),
+  EXPECT_THAT(deflate_stream_->WriteFrames(&frames, CompletionOnceCallback()),
               IsError(ERR_FAILED));
   predictor_->Clear();
 }
 
 TEST_F(WebSocketDeflateStreamTest, WriteFrameImmediately) {
   std::vector<std::unique_ptr<WebSocketFrame>> frames;
-  CompletionCallback callback;
   WriteFramesStub stub(predictor_, OK);
   AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kFinal, "Hello");
   predictor_->AddFramesToBeInput(frames);
   {
     InSequence s;
-    EXPECT_CALL(*mock_stream_, WriteFrames(_, _))
+    EXPECT_CALL(*mock_stream_, WriteFramesInternal(_, _))
         .WillOnce(Invoke(&stub, &WriteFramesStub::Call));
   }
-  ASSERT_THAT(deflate_stream_->WriteFrames(&frames, callback), IsOk());
+  ASSERT_THAT(deflate_stream_->WriteFrames(&frames, CompletionOnceCallback()),
+              IsOk());
   const std::vector<std::unique_ptr<WebSocketFrame>>& frames_passed =
       *stub.frames();
   ASSERT_EQ(1u, frames_passed.size());
@@ -1064,12 +1076,12 @@
 
 TEST_F(WebSocketDeflateStreamTest, WriteFrameAsync) {
   WriteFramesStub stub(predictor_, ERR_IO_PENDING);
-  base::MockCallback<CompletionCallback> mock_callback;
+  base::MockCallback<CompletionOnceCallback> mock_callback;
   base::MockCallback<base::Closure> checkpoint;
   std::vector<std::unique_ptr<WebSocketFrame>> frames;
   {
     InSequence s;
-    EXPECT_CALL(*mock_stream_, WriteFrames(&frames, _))
+    EXPECT_CALL(*mock_stream_, WriteFramesInternal(&frames, _))
         .WillOnce(Invoke(&stub, &WriteFramesStub::Call));
     EXPECT_CALL(checkpoint, Run());
     EXPECT_CALL(mock_callback, Run(OK));
@@ -1099,14 +1111,14 @@
   AppendTo(&frames, WebSocketFrameHeader::kOpCodeContinuation, kFinal, "lo");
   predictor_->AddFramesToBeInput(frames);
   WriteFramesStub stub(predictor_, OK);
-  CompletionCallback callback;
 
   {
     InSequence s;
-    EXPECT_CALL(*mock_stream_, WriteFrames(&frames, _))
+    EXPECT_CALL(*mock_stream_, WriteFramesInternal(&frames, _))
         .WillOnce(Invoke(&stub, &WriteFramesStub::Call));
   }
-  ASSERT_THAT(deflate_stream_->WriteFrames(&frames, callback), IsOk());
+  ASSERT_THAT(deflate_stream_->WriteFrames(&frames, CompletionOnceCallback()),
+              IsOk());
   const std::vector<std::unique_ptr<WebSocketFrame>>& frames_passed =
       *stub.frames();
   ASSERT_EQ(2u, frames_passed.size());
@@ -1125,14 +1137,14 @@
   AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kFinal);
   predictor_->AddFramesToBeInput(frames);
   WriteFramesStub stub(predictor_, OK);
-  CompletionCallback callback;
 
   {
     InSequence s;
-    EXPECT_CALL(*mock_stream_, WriteFrames(&frames, _))
+    EXPECT_CALL(*mock_stream_, WriteFramesInternal(&frames, _))
         .WillOnce(Invoke(&stub, &WriteFramesStub::Call));
   }
-  ASSERT_THAT(deflate_stream_->WriteFrames(&frames, callback), IsOk());
+  ASSERT_THAT(deflate_stream_->WriteFrames(&frames, CompletionOnceCallback()),
+              IsOk());
   const std::vector<std::unique_ptr<WebSocketFrame>>& frames_passed =
       *stub.frames();
   ASSERT_EQ(1u, frames_passed.size());
@@ -1148,16 +1160,16 @@
   AppendTo(&frames, WebSocketFrameHeader::kOpCodeContinuation, kFinal, "AAA");
   predictor_->AddFramesToBeInput(frames);
   WriteFramesStub stub(predictor_, OK);
-  CompletionCallback callback;
 
   predictor_->set_result(WebSocketDeflatePredictor::DO_NOT_DEFLATE);
 
   {
     InSequence s;
-    EXPECT_CALL(*mock_stream_, WriteFrames(&frames, _))
+    EXPECT_CALL(*mock_stream_, WriteFramesInternal(&frames, _))
         .WillOnce(Invoke(&stub, &WriteFramesStub::Call));
   }
-  ASSERT_THAT(deflate_stream_->WriteFrames(&frames, callback), IsOk());
+  ASSERT_THAT(deflate_stream_->WriteFrames(&frames, CompletionOnceCallback()),
+              IsOk());
   const std::vector<std::unique_ptr<WebSocketFrame>>& frames_passed =
       *stub.frames();
   ASSERT_EQ(2u, frames_passed.size());
@@ -1176,12 +1188,11 @@
   WebSocketDeflater deflater(WebSocketDeflater::TAKE_OVER_CONTEXT);
   LinearCongruentialGenerator lcg(133);
   WriteFramesStub stub(predictor_, OK);
-  CompletionCallback callback;
   const size_t size = 1024;
 
   {
     InSequence s;
-    EXPECT_CALL(*mock_stream_, WriteFrames(_, _))
+    EXPECT_CALL(*mock_stream_, WriteFramesInternal(_, _))
         .WillRepeatedly(Invoke(&stub, &WriteFramesStub::Call));
   }
   std::vector<std::unique_ptr<WebSocketFrame>> total_compressed_frames;
@@ -1197,7 +1208,8 @@
     FrameFlag flag = is_final ? kFinal : kNoFlag;
     AppendTo(&frames, WebSocketFrameHeader::kOpCodeBinary, flag, data);
     predictor_->AddFramesToBeInput(frames);
-    ASSERT_THAT(deflate_stream_->WriteFrames(&frames, callback), IsOk());
+    ASSERT_THAT(deflate_stream_->WriteFrames(&frames, CompletionOnceCallback()),
+                IsOk());
     total_compressed_frames.insert(
         total_compressed_frames.end(),
         std::make_move_iterator(stub.frames()->begin()),
@@ -1234,14 +1246,14 @@
   AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kFinal, "Hello");
   predictor_->AddFramesToBeInput(frames);
   WriteFramesStub stub(predictor_, OK);
-  CompletionCallback callback;
 
   {
     InSequence s;
-    EXPECT_CALL(*mock_stream_, WriteFrames(&frames, _))
+    EXPECT_CALL(*mock_stream_, WriteFramesInternal(&frames, _))
         .WillOnce(Invoke(&stub, &WriteFramesStub::Call));
   }
-  ASSERT_THAT(deflate_stream_->WriteFrames(&frames, callback), IsOk());
+  ASSERT_THAT(deflate_stream_->WriteFrames(&frames, CompletionOnceCallback()),
+              IsOk());
   const std::vector<std::unique_ptr<WebSocketFrame>>& frames_passed =
       *stub.frames();
   ASSERT_EQ(2u, frames_passed.size());
@@ -1263,14 +1275,14 @@
   AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kFinal, "Hello");
   predictor_->AddFramesToBeInput(frames);
   WriteFramesStub stub(predictor_, OK);
-  CompletionCallback callback;
 
   {
     InSequence s;
-    EXPECT_CALL(*mock_stream_, WriteFrames(&frames, _))
+    EXPECT_CALL(*mock_stream_, WriteFramesInternal(&frames, _))
         .WillOnce(Invoke(&stub, &WriteFramesStub::Call));
   }
-  ASSERT_THAT(deflate_stream_->WriteFrames(&frames, callback), IsOk());
+  ASSERT_THAT(deflate_stream_->WriteFrames(&frames, CompletionOnceCallback()),
+              IsOk());
   const std::vector<std::unique_ptr<WebSocketFrame>>& frames_passed =
       *stub.frames();
   ASSERT_EQ(2u, frames_passed.size());
@@ -1299,15 +1311,15 @@
   AppendTo(&frames, WebSocketFrameHeader::kOpCodeContinuation, kFinal, "YY");
   predictor_->AddFramesToBeInput(frames);
   WriteFramesStub stub(predictor_, OK);
-  CompletionCallback callback;
   predictor_->set_result(WebSocketDeflatePredictor::TRY_DEFLATE);
 
   {
     InSequence s;
-    EXPECT_CALL(*mock_stream_, WriteFrames(&frames, _))
+    EXPECT_CALL(*mock_stream_, WriteFramesInternal(&frames, _))
         .WillOnce(Invoke(&stub, &WriteFramesStub::Call));
   }
-  ASSERT_THAT(deflate_stream_->WriteFrames(&frames, callback), IsOk());
+  ASSERT_THAT(deflate_stream_->WriteFrames(&frames, CompletionOnceCallback()),
+              IsOk());
   const std::vector<std::unique_ptr<WebSocketFrame>>& frames_passed =
       *stub.frames();
   ASSERT_EQ(5u, frames_passed.size());
@@ -1342,15 +1354,15 @@
 // This is based on the similar test from websocket_deflater_test.cc
 TEST_F(WebSocketDeflateStreamWithClientWindowBitsTest, WindowBits8) {
   SetUpWithWindowBits(8);
-  CompletionCallback callback;
   AddCompressibleFrameString();
   WriteFramesStub stub(predictor_, OK);
   {
     InSequence s;
-    EXPECT_CALL(*mock_stream_, WriteFrames(_, _))
+    EXPECT_CALL(*mock_stream_, WriteFramesInternal(_, _))
         .WillOnce(Invoke(&stub, &WriteFramesStub::Call));
   }
-  ASSERT_THAT(deflate_stream_->WriteFrames(&frames_, callback), IsOk());
+  ASSERT_THAT(deflate_stream_->WriteFrames(&frames_, CompletionOnceCallback()),
+              IsOk());
   const std::vector<std::unique_ptr<WebSocketFrame>>& frames_passed =
       *stub.frames();
   ASSERT_EQ(1u, frames_passed.size());
@@ -1362,15 +1374,15 @@
 // The same input with window_bits=10 returns smaller output.
 TEST_F(WebSocketDeflateStreamWithClientWindowBitsTest, WindowBits10) {
   SetUpWithWindowBits(10);
-  CompletionCallback callback;
   AddCompressibleFrameString();
   WriteFramesStub stub(predictor_, OK);
   {
     InSequence s;
-    EXPECT_CALL(*mock_stream_, WriteFrames(_, _))
+    EXPECT_CALL(*mock_stream_, WriteFramesInternal(_, _))
         .WillOnce(Invoke(&stub, &WriteFramesStub::Call));
   }
-  ASSERT_THAT(deflate_stream_->WriteFrames(&frames_, callback), IsOk());
+  ASSERT_THAT(deflate_stream_->WriteFrames(&frames_, CompletionOnceCallback()),
+              IsOk());
   const std::vector<std::unique_ptr<WebSocketFrame>>& frames_passed =
       *stub.frames();
   ASSERT_EQ(1u, frames_passed.size());
diff --git a/net/websockets/websocket_stream.h b/net/websockets/websocket_stream.h
index 52054170..aa7585e8 100644
--- a/net/websockets/websocket_stream.h
+++ b/net/websockets/websocket_stream.h
@@ -14,7 +14,7 @@
 #include "base/memory/scoped_refptr.h"
 #include "base/optional.h"
 #include "base/time/time.h"
-#include "net/base/completion_callback.h"
+#include "net/base/completion_once_callback.h"
 #include "net/base/net_export.h"
 #include "net/websockets/websocket_event_interface.h"
 #include "net/websockets/websocket_handshake_request_info.h"
@@ -223,7 +223,7 @@
   // set correctly. If the reserved header bits are set incorrectly, it is okay
   // to leave it to the caller to report the error.
   virtual int ReadFrames(std::vector<std::unique_ptr<WebSocketFrame>>* frames,
-                         const CompletionCallback& callback) = 0;
+                         CompletionOnceCallback callback) = 0;
 
   // Writes WebSocket frame data.
   //
@@ -240,7 +240,7 @@
   // this. This generally means returning to the event loop immediately after
   // calling the callback.
   virtual int WriteFrames(std::vector<std::unique_ptr<WebSocketFrame>>* frames,
-                          const CompletionCallback& callback) = 0;
+                          CompletionOnceCallback callback) = 0;
 
   // Closes the stream. All pending I/O operations (if any) are cancelled
   // at this point, so |frames| can be freed.
diff --git a/services/audio/BUILD.gn b/services/audio/BUILD.gn
index 66a3f4b..98822642 100644
--- a/services/audio/BUILD.gn
+++ b/services/audio/BUILD.gn
@@ -51,6 +51,12 @@
     "input_sync_writer.h",
     "local_muter.cc",
     "local_muter.h",
+    "log_adapter.cc",
+    "log_adapter.h",
+    "log_factory_adapter.cc",
+    "log_factory_adapter.h",
+    "log_factory_manager.cc",
+    "log_factory_manager.h",
     "loopback_stream.cc",
     "loopback_stream.h",
     "output_controller.cc",
@@ -104,6 +110,7 @@
     "input_stream_unittest.cc",
     "input_sync_writer_unittest.cc",
     "local_muter_unittest.cc",
+    "log_factory_manager_unittest.cc",
     "loopback_stream_unittest.cc",
     "output_controller_unittest.cc",
     "output_stream_unittest.cc",
diff --git a/services/audio/in_process_audio_manager_accessor.cc b/services/audio/in_process_audio_manager_accessor.cc
index 8924538..4f889fe 100644
--- a/services/audio/in_process_audio_manager_accessor.cc
+++ b/services/audio/in_process_audio_manager_accessor.cc
@@ -27,4 +27,9 @@
   return audio_manager_;
 }
 
+void InProcessAudioManagerAccessor::SetAudioLogFactory(
+    media::AudioLogFactory* factory) {
+  NOTREACHED();
+}
+
 }  // namespace audio
diff --git a/services/audio/in_process_audio_manager_accessor.h b/services/audio/in_process_audio_manager_accessor.h
index f5146a0..4ef021a 100644
--- a/services/audio/in_process_audio_manager_accessor.h
+++ b/services/audio/in_process_audio_manager_accessor.h
@@ -10,6 +10,7 @@
 
 namespace media {
 class AudioManager;
+class AudioLogFactory;
 }
 
 namespace audio {
@@ -25,6 +26,9 @@
   void Shutdown() final {}  // AudioManager must be shut down by its owner.
   media::AudioManager* GetAudioManager() final;
 
+  // Should not be called on this implementation.
+  void SetAudioLogFactory(media::AudioLogFactory* factory) final;
+
  private:
   media::AudioManager* const audio_manager_;
   DISALLOW_COPY_AND_ASSIGN(InProcessAudioManagerAccessor);
diff --git a/services/audio/log_adapter.cc b/services/audio/log_adapter.cc
new file mode 100644
index 0000000..239becc0
--- /dev/null
+++ b/services/audio/log_adapter.cc
@@ -0,0 +1,45 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "services/audio/log_adapter.h"
+
+#include <utility>
+
+namespace audio {
+
+LogAdapter::LogAdapter(media::mojom::AudioLogPtr audio_log)
+    : audio_log_(std::move(audio_log)) {}
+
+LogAdapter::~LogAdapter() = default;
+
+void LogAdapter::OnCreated(const media::AudioParameters& params,
+                           const std::string& device_id) {
+  audio_log_->OnCreated(params, device_id);
+}
+
+void LogAdapter::OnStarted() {
+  audio_log_->OnStarted();
+}
+
+void LogAdapter::OnStopped() {
+  audio_log_->OnStopped();
+}
+
+void LogAdapter::OnClosed() {
+  audio_log_->OnClosed();
+}
+
+void LogAdapter::OnError() {
+  audio_log_->OnError();
+}
+
+void LogAdapter::OnSetVolume(double volume) {
+  audio_log_->OnSetVolume(volume);
+}
+
+void LogAdapter::OnLogMessage(const std::string& message) {
+  audio_log_->OnLogMessage(message);
+}
+
+}  // namespace audio
diff --git a/services/audio/log_adapter.h b/services/audio/log_adapter.h
new file mode 100644
index 0000000..1727540
--- /dev/null
+++ b/services/audio/log_adapter.h
@@ -0,0 +1,43 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SERVICES_AUDIO_LOG_ADAPTER_H_
+#define SERVICES_AUDIO_LOG_ADAPTER_H_
+
+#include <string>
+
+#include "media/audio/audio_logging.h"
+#include "media/mojo/interfaces/audio_logging.mojom.h"
+
+namespace media {
+class AudioParameters;
+}
+
+namespace audio {
+
+// This class wraps a media::mojom::AudioLogPtr into a media::AudioLog.
+class LogAdapter : public media::AudioLog {
+ public:
+  explicit LogAdapter(media::mojom::AudioLogPtr audio_log);
+  ~LogAdapter() override;
+
+  // media::AudioLog implementation.
+  void OnCreated(const media::AudioParameters& params,
+                 const std::string& device_id) override;
+  void OnStarted() override;
+  void OnStopped() override;
+  void OnClosed() override;
+  void OnError() override;
+  void OnSetVolume(double volume) override;
+  void OnLogMessage(const std::string& message) override;
+
+ private:
+  media::mojom::AudioLogPtr audio_log_;
+
+  DISALLOW_COPY_AND_ASSIGN(LogAdapter);
+};
+
+}  // namespace audio
+
+#endif  // SERVICES_AUDIO_LOG_ADAPTER_H_
diff --git a/services/audio/log_factory_adapter.cc b/services/audio/log_factory_adapter.cc
new file mode 100644
index 0000000..f4ca809b
--- /dev/null
+++ b/services/audio/log_factory_adapter.cc
@@ -0,0 +1,75 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "services/audio/log_factory_adapter.h"
+
+#include <utility>
+
+#include "services/audio/log_adapter.h"
+
+namespace audio {
+
+const int kMaxPendingLogRequests = 500;
+
+struct LogFactoryAdapter::PendingLogRequest {
+  PendingLogRequest(media::mojom::AudioLogComponent component,
+                    int component_id,
+                    media::mojom::AudioLogRequest request)
+      : component(component),
+        component_id(component_id),
+        request(std::move(request)) {}
+  PendingLogRequest(PendingLogRequest&& other) = default;
+  PendingLogRequest& operator=(PendingLogRequest&& other) = default;
+  PendingLogRequest(const PendingLogRequest& other) = delete;
+  PendingLogRequest& operator=(const PendingLogRequest& other) = delete;
+  ~PendingLogRequest() = default;
+
+  media::mojom::AudioLogComponent component;
+  int component_id;
+  media::mojom::AudioLogRequest request;
+};
+
+LogFactoryAdapter::LogFactoryAdapter() = default;
+LogFactoryAdapter::~LogFactoryAdapter() = default;
+
+void LogFactoryAdapter::SetLogFactory(
+    media::mojom::AudioLogFactoryPtr log_factory) {
+  if (log_factory_) {
+    LOG(WARNING) << "Attempting to set log factory more than once. Ignoring "
+                    "request.";
+    return;
+  }
+
+  log_factory_ = std::move(log_factory);
+  while (!pending_requests_.empty()) {
+    auto& front = pending_requests_.front();
+    log_factory_->CreateAudioLog(front.component, front.component_id,
+                                 std::move(front.request));
+    pending_requests_.pop();
+  }
+}
+
+std::unique_ptr<media::AudioLog> LogFactoryAdapter::CreateAudioLog(
+    AudioComponent component,
+    int component_id) {
+  media::mojom::AudioLogPtr audio_log_ptr;
+  media::mojom::AudioLogRequest audio_log_request =
+      mojo::MakeRequest(&audio_log_ptr);
+  media::mojom::AudioLogComponent mojo_component =
+      static_cast<media::mojom::AudioLogComponent>(component);
+  if (log_factory_) {
+    log_factory_->CreateAudioLog(mojo_component, component_id,
+                                 std::move(audio_log_request));
+  } else if (pending_requests_.size() >= kMaxPendingLogRequests) {
+    LOG(WARNING) << "Maximum number of queued log requests exceeded. Fulfilling"
+                    " request with fake log.";
+    return fake_log_factory_.CreateAudioLog(component, component_id);
+  } else {
+    pending_requests_.emplace(mojo_component, component_id,
+                              std::move(audio_log_request));
+  }
+  return std::make_unique<LogAdapter>(std::move(audio_log_ptr));
+}
+
+}  // namespace audio
diff --git a/services/audio/log_factory_adapter.h b/services/audio/log_factory_adapter.h
new file mode 100644
index 0000000..c55edef
--- /dev/null
+++ b/services/audio/log_factory_adapter.h
@@ -0,0 +1,47 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SERVICES_AUDIO_LOG_FACTORY_ADAPTER_H_
+#define SERVICES_AUDIO_LOG_FACTORY_ADAPTER_H_
+
+#include <memory>
+
+#include "base/containers/queue.h"
+#include "media/audio/audio_logging.h"
+#include "media/audio/fake_audio_log_factory.h"
+#include "services/audio/public/mojom/log_factory_manager.mojom.h"
+
+namespace media {
+class AudioLogFactory;
+}  // namespace media
+
+namespace audio {
+
+// This class allows setting a mojo audio log factory to create audio logs
+// in the audio service. It also acts as a media::AudioLogFactory to interface
+// with AudioManager.
+class LogFactoryAdapter final : public media::AudioLogFactory {
+ public:
+  LogFactoryAdapter();
+  ~LogFactoryAdapter() final;
+
+  void SetLogFactory(media::mojom::AudioLogFactoryPtr log_factory);
+
+  // media::AudioLogFactory implementation
+  std::unique_ptr<media::AudioLog> CreateAudioLog(AudioComponent component,
+                                                  int component_id) override;
+
+ private:
+  struct PendingLogRequest;
+
+  media::mojom::AudioLogFactoryPtr log_factory_;
+  base::queue<PendingLogRequest> pending_requests_;
+  media::FakeAudioLogFactory fake_log_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(LogFactoryAdapter);
+};
+
+}  // namespace audio
+
+#endif  // SERVICES_AUDIO_LOG_FACTORY_ADAPTER_H_
diff --git a/services/audio/log_factory_manager.cc b/services/audio/log_factory_manager.cc
new file mode 100644
index 0000000..de29b59
--- /dev/null
+++ b/services/audio/log_factory_manager.cc
@@ -0,0 +1,36 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "services/audio/log_factory_manager.h"
+
+#include <utility>
+
+#include "services/service_manager/public/cpp/service_context_ref.h"
+
+namespace audio {
+
+LogFactoryManager::LogFactoryManager() {}
+
+LogFactoryManager::~LogFactoryManager() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+}
+
+void LogFactoryManager::Bind(mojom::LogFactoryManagerRequest request,
+                             TracedServiceRef context_ref) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+  bindings_.AddBinding(this, std::move(request), std::move(context_ref));
+}
+
+void LogFactoryManager::SetLogFactory(
+    media::mojom::AudioLogFactoryPtr log_factory) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+  log_factory_adapter_.SetLogFactory(std::move(log_factory));
+}
+
+media::AudioLogFactory* LogFactoryManager::GetLogFactory() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+  return &log_factory_adapter_;
+}
+
+}  // namespace audio
diff --git a/services/audio/log_factory_manager.h b/services/audio/log_factory_manager.h
new file mode 100644
index 0000000..bd587841
--- /dev/null
+++ b/services/audio/log_factory_manager.h
@@ -0,0 +1,46 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SERVICES_AUDIO_LOG_FACTORY_MANAGER_H_
+#define SERVICES_AUDIO_LOG_FACTORY_MANAGER_H_
+
+#include <memory>
+
+#include "mojo/public/cpp/bindings/binding_set.h"
+#include "services/audio/log_factory_adapter.h"
+#include "services/audio/public/mojom/log_factory_manager.mojom.h"
+#include "services/audio/traced_service_ref.h"
+
+namespace media {
+class AudioLogFactory;
+}
+
+namespace audio {
+
+// This class is used to provide the LogFactoryManager interface. It will
+// typically be instantiated when needed and remain for the lifetime of the
+// service.
+class LogFactoryManager final : public mojom::LogFactoryManager {
+ public:
+  LogFactoryManager();
+  ~LogFactoryManager() final;
+
+  void Bind(mojom::LogFactoryManagerRequest request,
+            TracedServiceRef context_ref);
+
+  // LogFactoryManager implementation.
+  void SetLogFactory(media::mojom::AudioLogFactoryPtr log_factory) final;
+  media::AudioLogFactory* GetLogFactory();
+
+ private:
+  mojo::BindingSet<mojom::LogFactoryManager, TracedServiceRef> bindings_;
+  LogFactoryAdapter log_factory_adapter_;
+  SEQUENCE_CHECKER(owning_sequence_);
+
+  DISALLOW_COPY_AND_ASSIGN(LogFactoryManager);
+};
+
+}  // namespace audio
+
+#endif  // SERVICES_AUDIO_LOG_FACTORY_MANAGER_H_
diff --git a/services/audio/log_factory_manager_unittest.cc b/services/audio/log_factory_manager_unittest.cc
new file mode 100644
index 0000000..9a47a44
--- /dev/null
+++ b/services/audio/log_factory_manager_unittest.cc
@@ -0,0 +1,168 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "services/audio/log_factory_manager.h"
+
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "base/memory/ptr_util.h"
+#include "base/test/scoped_task_environment.h"
+#include "media/mojo/interfaces/audio_logging.mojom.h"
+#include "mojo/public/cpp/bindings/strong_binding.h"
+#include "services/audio/traced_service_ref.h"
+#include "services/service_manager/public/cpp/service_context_ref.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace audio {
+
+using testing::_;
+using testing::SaveArg;
+
+namespace {
+
+class MockAudioLog : public media::mojom::AudioLog {
+ public:
+  MockAudioLog() {}
+  MOCK_METHOD2(OnCreated,
+               void(const media::AudioParameters& params,
+                    const std::string& device_id));
+
+  MOCK_METHOD0(OnStarted, void());
+  MOCK_METHOD0(OnStopped, void());
+  MOCK_METHOD0(OnClosed, void());
+  MOCK_METHOD0(OnError, void());
+  MOCK_METHOD1(OnSetVolume, void(double));
+  MOCK_METHOD1(OnLogMessage, void(const std::string&));
+};
+
+class MockAudioLogFactory : public media::mojom::AudioLogFactory {
+ public:
+  MockAudioLogFactory(media::mojom::AudioLogFactoryRequest request,
+                      size_t num_mock_logs)
+      : binding_(this, std::move(request)) {
+    for (size_t i = 0; i < num_mock_logs; ++i)
+      mock_logs_.push_back(new MockAudioLog());
+  }
+
+  MOCK_METHOD2(MockCreateAudioLog,
+               void(media::mojom::AudioLogComponent, int32_t));
+
+  void CreateAudioLog(
+      media::mojom::AudioLogComponent component,
+      int32_t component_id,
+      media::mojom::AudioLogRequest audio_log_request) override {
+    MockCreateAudioLog(component, component_id);
+    mojo::MakeStrongBinding(base::WrapUnique(mock_logs_[current_mock_log_++]),
+                            std::move(audio_log_request));
+  };
+
+  MockAudioLog* GetMockLog(size_t index) { return mock_logs_[index]; }
+
+ private:
+  mojo::Binding<media::mojom::AudioLogFactory> binding_;
+  size_t current_mock_log_ = 0;
+  std::vector<MockAudioLog*> mock_logs_;
+  DISALLOW_COPY_AND_ASSIGN(MockAudioLogFactory);
+};
+
+}  // namespace
+
+class LogFactoryManagerTest : public ::testing::Test {
+ public:
+  LogFactoryManagerTest()
+      : service_ref_factory_(
+            base::BindRepeating(&LogFactoryManagerTest::OnNoServiceRefs,
+                                base::Unretained(this))) {}
+
+ protected:
+  MOCK_METHOD0(OnNoServiceRefs, void());
+
+  void CreateLogFactoryManager() {
+    log_factory_manager_ = std::make_unique<LogFactoryManager>();
+    log_factory_manager_->Bind(
+        mojo::MakeRequest(&log_factory_manager_ptr_),
+        TracedServiceRef(service_ref_factory_.CreateRef(),
+                         "audio::LogFactoryManager Binding"));
+    EXPECT_FALSE(service_ref_factory_.HasNoRefs());
+  }
+
+  void DestroyLogFactoryManager() {
+    log_factory_manager_ptr_.reset();
+    scoped_task_environment_.RunUntilIdle();
+    EXPECT_TRUE(service_ref_factory_.HasNoRefs());
+  }
+
+  base::test::ScopedTaskEnvironment scoped_task_environment_;
+  mojom::LogFactoryManagerPtr log_factory_manager_ptr_;
+  std::unique_ptr<LogFactoryManager> log_factory_manager_;
+
+ private:
+  service_manager::ServiceContextRefFactory service_ref_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(LogFactoryManagerTest);
+};
+
+TEST_F(LogFactoryManagerTest, LogFactoryManagerQueuesRequestsAndSetsFactory) {
+  EXPECT_CALL(*this, OnNoServiceRefs());
+  CreateLogFactoryManager();
+
+  // Create a log before setting the log factory.
+  const int kComponentId1 = 1;
+  const double kVolume1 = 0.5;
+  media::AudioLogFactory* log_factory = log_factory_manager_->GetLogFactory();
+  std::unique_ptr<media::AudioLog> log1 = log_factory->CreateAudioLog(
+      media::AudioLogFactory::AUDIO_OUTPUT_STREAM, kComponentId1);
+  log1->OnStarted();
+  log1->OnSetVolume(kVolume1);
+  log1->OnStopped();
+  log1->OnClosed();
+
+  // Set the factory.
+  media::mojom::AudioLogFactoryPtr log_factory_ptr;
+  MockAudioLogFactory mock_factory(mojo::MakeRequest(&log_factory_ptr), 2);
+  MockAudioLog* mock_log1 = mock_factory.GetMockLog(0);
+  testing::InSequence s;
+
+  // Set the factory and expect that queued operations run.
+  EXPECT_CALL(mock_factory,
+              MockCreateAudioLog(media::mojom::AudioLogComponent::kOutputStream,
+                                 kComponentId1));
+  EXPECT_CALL(*mock_log1, OnStarted());
+  EXPECT_CALL(*mock_log1, OnSetVolume(kVolume1));
+  EXPECT_CALL(*mock_log1, OnStopped());
+  EXPECT_CALL(*mock_log1, OnClosed());
+  log_factory_manager_ptr_->SetLogFactory(std::move(log_factory_ptr));
+  scoped_task_environment_.RunUntilIdle();
+
+  // Create another log after the factory is already set.
+  const int kComponentId2 = 2;
+  const double kVolume2 = 0.1;
+  EXPECT_CALL(
+      mock_factory,
+      MockCreateAudioLog(media::mojom::AudioLogComponent::kInputController,
+                         kComponentId2));
+  MockAudioLog* mock_log2 = mock_factory.GetMockLog(1);
+  EXPECT_CALL(*mock_log2, OnStarted());
+  EXPECT_CALL(*mock_log2, OnSetVolume(kVolume2));
+  EXPECT_CALL(*mock_log2, OnStopped());
+  EXPECT_CALL(*mock_log2, OnClosed());
+
+  std::unique_ptr<media::AudioLog> log2 = log_factory->CreateAudioLog(
+      media::AudioLogFactory::AUDIO_INPUT_CONTROLLER, 2);
+  log2->OnStarted();
+  log2->OnSetVolume(kVolume2);
+  log2->OnStopped();
+  log2->OnClosed();
+
+  // Ensure all mock objects are released.
+  log1.reset();
+  log2.reset();
+  DestroyLogFactoryManager();
+}
+
+}  // namespace audio
diff --git a/services/audio/manifest.json b/services/audio/manifest.json
index 2c2640d8..25f50db 100644
--- a/services/audio/manifest.json
+++ b/services/audio/manifest.json
@@ -9,6 +9,7 @@
         "debug_recording": [ "audio.mojom.DebugRecording" ],
         "stream_factory": [ "audio.mojom.StreamFactory" ],
         "device_notifier": [ "audio.mojom.DeviceNotifier" ],
+        "log_factory_manager": [ "audio.mojom.LogFactoryManager" ],
         "testing_api": [ "audio.mojom.TestingApi" ]
       },
       "requires": {
diff --git a/services/audio/owning_audio_manager_accessor.cc b/services/audio/owning_audio_manager_accessor.cc
index fa80463..f0f22d0 100644
--- a/services/audio/owning_audio_manager_accessor.cc
+++ b/services/audio/owning_audio_manager_accessor.cc
@@ -90,12 +90,10 @@
   if (!audio_manager_) {
     TRACE_EVENT0("audio", "AudioManager creation");
     DCHECK(audio_manager_factory_cb_);
+    DCHECK(log_factory_);
     base::TimeTicks creation_start_time = base::TimeTicks::Now();
-
-    // TODO(http://crbug/812557): pass AudioLogFactory (needed for output
-    // streams).
     audio_manager_ = std::move(audio_manager_factory_cb_)
-                         .Run(std::make_unique<MainThread>(), &log_factory_);
+                         .Run(std::make_unique<MainThread>(), log_factory_);
     DCHECK(audio_manager_);
     UMA_HISTOGRAM_TIMES("Media.AudioService.AudioManagerStartupTime",
                         base::TimeTicks::Now() - creation_start_time);
@@ -104,6 +102,11 @@
   return audio_manager_.get();
 }
 
+void OwningAudioManagerAccessor::SetAudioLogFactory(
+    media::AudioLogFactory* log_factory) {
+  log_factory_ = log_factory;
+}
+
 void OwningAudioManagerAccessor::Shutdown() {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   if (audio_manager_)
diff --git a/services/audio/owning_audio_manager_accessor.h b/services/audio/owning_audio_manager_accessor.h
index d978eff..11abdf4d 100644
--- a/services/audio/owning_audio_manager_accessor.h
+++ b/services/audio/owning_audio_manager_accessor.h
@@ -10,7 +10,6 @@
 #include "base/macros.h"
 #include "base/threading/thread_checker.h"
 #include "build/build_config.h"
-#include "media/audio/fake_audio_log_factory.h"
 #include "services/audio/service.h"
 
 #if defined(OS_WIN)
@@ -40,6 +39,7 @@
   ~OwningAudioManagerAccessor() override;
 
   media::AudioManager* GetAudioManager() final;
+  void SetAudioLogFactory(media::AudioLogFactory* factory) final;
   void Shutdown() final;
 
  private:
@@ -49,10 +49,7 @@
 #endif
   AudioManagerFactoryCallback audio_manager_factory_cb_;
   std::unique_ptr<media::AudioManager> audio_manager_;
-
-  // TODO(http://crbug/812557): Use a real AudioLogFactory (needed for output
-  // streams).
-  media::FakeAudioLogFactory log_factory_;
+  media::AudioLogFactory* log_factory_ = nullptr;  // not owned.
 
   THREAD_CHECKER(thread_checker_);
   DISALLOW_COPY_AND_ASSIGN(OwningAudioManagerAccessor);
diff --git a/services/audio/public/mojom/BUILD.gn b/services/audio/public/mojom/BUILD.gn
index a208e05..aae3f53 100644
--- a/services/audio/public/mojom/BUILD.gn
+++ b/services/audio/public/mojom/BUILD.gn
@@ -9,6 +9,7 @@
     "audio_device_description.mojom",
     "debug_recording.mojom",
     "device_notifications.mojom",
+    "log_factory_manager.mojom",
     "stream_factory.mojom",
     "system_info.mojom",
     "testing_api.mojom",
diff --git a/services/audio/public/mojom/log_factory_manager.mojom b/services/audio/public/mojom/log_factory_manager.mojom
new file mode 100644
index 0000000..10365c21
--- /dev/null
+++ b/services/audio/public/mojom/log_factory_manager.mojom
@@ -0,0 +1,16 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module audio.mojom;
+
+import "media/mojo/interfaces/audio_logging.mojom";
+
+// This interface is exposed by the audio service to allow trusted clients
+// (like the browser process) to set a factory for creating audio logs.
+interface LogFactoryManager {
+
+  // Sets the factory for creating audio logs. If a previous factory exists,
+  // the request is ignored.
+  SetLogFactory(media.mojom.AudioLogFactory factory);
+};
diff --git a/services/audio/service.cc b/services/audio/service.cc
index ab30f45..ea7aef6 100644
--- a/services/audio/service.cc
+++ b/services/audio/service.cc
@@ -15,6 +15,7 @@
 #include "media/audio/audio_manager.h"
 #include "services/audio/debug_recording.h"
 #include "services/audio/device_notifier.h"
+#include "services/audio/log_factory_manager.h"
 #include "services/audio/service_metrics.h"
 #include "services/audio/system_info.h"
 #include "services/service_manager/public/cpp/service_context.h"
@@ -28,15 +29,22 @@
 
 Service::Service(std::unique_ptr<AudioManagerAccessor> audio_manager_accessor,
                  base::TimeDelta quit_timeout,
-                 bool device_notifier_enabled,
+                 bool enable_remote_client_support,
                  std::unique_ptr<service_manager::BinderRegistry> registry)
     : quit_timeout_(quit_timeout),
       audio_manager_accessor_(std::move(audio_manager_accessor)),
-      device_notifier_enabled_(device_notifier_enabled),
+      enable_remote_client_support_(enable_remote_client_support),
       registry_(std::move(registry)) {
   DCHECK(audio_manager_accessor_);
-  if (!device_notifier_enabled)
+  if (enable_remote_client_support_) {
+    log_factory_manager_ = std::make_unique<LogFactoryManager>();
+    audio_manager_accessor_->SetAudioLogFactory(
+        log_factory_manager_->GetLogFactory());
+  } else {
+    // Start device monitoring explicitly if no mojo device notifier will be
+    // created. This is required for in-process device notifications.
     InitializeDeviceMonitor();
+  }
 }
 
 Service::~Service() {
@@ -77,9 +85,11 @@
       &Service::BindDebugRecordingRequest, base::Unretained(this)));
   registry_->AddInterface<mojom::StreamFactory>(base::BindRepeating(
       &Service::BindStreamFactoryRequest, base::Unretained(this)));
-  if (device_notifier_enabled_) {
+  if (enable_remote_client_support_) {
     registry_->AddInterface<mojom::DeviceNotifier>(base::BindRepeating(
         &Service::BindDeviceNotifierRequest, base::Unretained(this)));
+    registry_->AddInterface<mojom::LogFactoryManager>(base::BindRepeating(
+        &Service::BindLogFactoryManagerRequest, base::Unretained(this)));
   }
 }
 
@@ -160,7 +170,7 @@
 void Service::BindDeviceNotifierRequest(mojom::DeviceNotifierRequest request) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   DCHECK(ref_factory_);
-  DCHECK(device_notifier_enabled_);
+  DCHECK(enable_remote_client_support_);
 
   if (!system_monitor_) {
     CHECK(!base::SystemMonitor::Get());
@@ -174,6 +184,17 @@
                                           "audio::DeviceNotifier Binding"));
 }
 
+void Service::BindLogFactoryManagerRequest(
+    mojom::LogFactoryManagerRequest request) {
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  DCHECK(ref_factory_);
+  DCHECK(log_factory_manager_);
+  DCHECK(enable_remote_client_support_);
+  log_factory_manager_->Bind(
+      std::move(request), TracedServiceRef(ref_factory_->CreateRef(),
+                                           "audio::LogFactoryManager Binding"));
+}
+
 void Service::MaybeRequestQuitDelayed() {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   metrics_->HasNoConnections();
diff --git a/services/audio/service.h b/services/audio/service.h
index fd8223f..7451c600 100644
--- a/services/audio/service.h
+++ b/services/audio/service.h
@@ -16,6 +16,7 @@
 #include "build/build_config.h"
 #include "services/audio/public/mojom/debug_recording.mojom.h"
 #include "services/audio/public/mojom/device_notifications.mojom.h"
+#include "services/audio/public/mojom/log_factory_manager.mojom.h"
 #include "services/audio/public/mojom/stream_factory.mojom.h"
 #include "services/audio/public/mojom/system_info.mojom.h"
 #include "services/audio/stream_factory.h"
@@ -29,6 +30,7 @@
 namespace media {
 class AudioDeviceListenerMac;
 class AudioManager;
+class AudioLogFactory;
 }  // namespace media
 
 namespace service_manager {
@@ -38,6 +40,7 @@
 namespace audio {
 class DebugRecording;
 class DeviceNotifier;
+class LogFactoryManager;
 class ServiceMetrics;
 class SystemInfo;
 
@@ -55,16 +58,22 @@
 
     // Returns a pointer to AudioManager.
     virtual media::AudioManager* GetAudioManager() = 0;
+
+    // Attempts to associate |factory| with the audio manager.
+    // |factory| must outlive the audio manager.
+    // It only makes sense to call this method before GetAudioManager().
+    virtual void SetAudioLogFactory(media::AudioLogFactory* factory) = 0;
   };
 
   // Service will attempt to quit if there are no connections to it within
   // |quit_timeout| interval. If |quit_timeout| is base::TimeDelta() the
-  // service never quits. If |device_notifier_enabled| is true, the service
+  // service never quits. If |enable_remote_client_support| is true, the service
   // will make available a DeviceNotifier object that allows clients to
-  // subscribe to notifications about device changes.
+  // subscribe to notifications about device changes and a LogFactoryManager
+  // object that allows clients to set a factory for audio logs.
   Service(std::unique_ptr<AudioManagerAccessor> audio_manager_accessor,
           base::TimeDelta quit_timeout,
-          bool device_notifier_enabled,
+          bool enable_remote_client_support,
           std::unique_ptr<service_manager::BinderRegistry> registry);
   ~Service() final;
 
@@ -82,6 +91,7 @@
   void BindDebugRecordingRequest(mojom::DebugRecordingRequest request);
   void BindStreamFactoryRequest(mojom::StreamFactoryRequest request);
   void BindDeviceNotifierRequest(mojom::DeviceNotifierRequest request);
+  void BindLogFactoryManagerRequest(mojom::LogFactoryManagerRequest request);
 
   void MaybeRequestQuitDelayed();
   void MaybeRequestQuit();
@@ -103,7 +113,7 @@
   base::OneShotTimer quit_timer_;
 
   std::unique_ptr<AudioManagerAccessor> audio_manager_accessor_;
-  const bool device_notifier_enabled_;
+  const bool enable_remote_client_support_;
   std::unique_ptr<base::SystemMonitor> system_monitor_;
 #if defined(OS_MACOSX)
   std::unique_ptr<media::AudioDeviceListenerMac> audio_device_listener_mac_;
@@ -112,6 +122,7 @@
   std::unique_ptr<DebugRecording> debug_recording_;
   base::Optional<StreamFactory> stream_factory_;
   std::unique_ptr<DeviceNotifier> device_notifier_;
+  std::unique_ptr<LogFactoryManager> log_factory_manager_;
   std::unique_ptr<ServiceMetrics> metrics_;
 
   std::unique_ptr<service_manager::BinderRegistry> registry_;
diff --git a/services/audio/service_factory.cc b/services/audio/service_factory.cc
index 9d82e25..09a64d7a 100644
--- a/services/audio/service_factory.cc
+++ b/services/audio/service_factory.cc
@@ -69,7 +69,7 @@
   return std::make_unique<Service>(
       std::make_unique<audio::OwningAudioManagerAccessor>(
           base::BindOnce(&media::AudioManager::Create)),
-      GetQuitTimeout(), true /* enable_device_notifications */,
+      GetQuitTimeout(), true /* enable_remote_client_support */,
       std::move(registry));
 }
 
diff --git a/services/network/cors/cors_url_loader.cc b/services/network/cors/cors_url_loader.cc
index f292b5fbf..fad59f1 100644
--- a/services/network/cors/cors_url_loader.cc
+++ b/services/network/cors/cors_url_loader.cc
@@ -17,8 +17,10 @@
 namespace {
 
 bool CalculateCORSFlag(const ResourceRequest& request) {
-  if (request.fetch_request_mode == mojom::FetchRequestMode::kNavigate)
+  if (request.fetch_request_mode == mojom::FetchRequestMode::kNavigate ||
+      request.fetch_request_mode == mojom::FetchRequestMode::kNoCORS) {
     return false;
+  }
   url::Origin url_origin = url::Origin::Create(request.url);
   if (!request.request_initiator.has_value())
     return true;
@@ -335,7 +337,12 @@
 }
 
 void CORSURLLoader::StartRequest() {
-  if (fetch_cors_flag_) {
+  // If the CORS flag is set, |httpRequest|’s method is neither `GET` nor
+  // `HEAD`, or |httpRequest|’s mode is "websocket", then append
+  // `Origin`/the result of serializing a request origin with |httpRequest|, to
+  // |httpRequest|’s header list.
+  if (fetch_cors_flag_ ||
+      (request_.method != "GET" && request_.method != "HEAD")) {
     request_.headers.SetHeader(
         net::HttpRequestHeaders::kOrigin,
         (tainted_ ? url::Origin() : *request_.request_initiator).Serialize());
diff --git a/services/network/cors/cors_url_loader_unittest.cc b/services/network/cors/cors_url_loader_unittest.cc
index bc0c680..a8dfc41 100644
--- a/services/network/cors/cors_url_loader_unittest.cc
+++ b/services/network/cors/cors_url_loader_unittest.cc
@@ -279,6 +279,35 @@
   EXPECT_TRUE(client().has_received_response());
   EXPECT_TRUE(client().has_received_completion());
   EXPECT_EQ(net::OK, client().completion_status().error_code);
+  EXPECT_FALSE(
+      GetRequest().headers.HasHeader(net::HttpRequestHeaders::kOrigin));
+}
+
+TEST_F(CORSURLLoaderTest, CrossOriginRequestWithNoCORSModeAndPatchMethod) {
+  const GURL origin("http://example.com");
+  const GURL url("http://other.com/foo.png");
+  ResourceRequest request;
+  request.fetch_request_mode = mojom::FetchRequestMode::kNoCORS;
+  request.fetch_credentials_mode = mojom::FetchCredentialsMode::kOmit;
+  request.method = "PATCH";
+  request.url = url;
+  request.request_initiator = url::Origin::Create(origin);
+  CreateLoaderAndStart(request);
+
+  NotifyLoaderClientOnReceiveResponse();
+  NotifyLoaderClientOnComplete(net::OK);
+
+  RunUntilComplete();
+
+  EXPECT_TRUE(IsNetworkLoaderStarted());
+  EXPECT_FALSE(client().has_received_redirect());
+  EXPECT_TRUE(client().has_received_response());
+  EXPECT_TRUE(client().has_received_completion());
+  EXPECT_EQ(net::OK, client().completion_status().error_code);
+  std::string origin_header;
+  EXPECT_TRUE(GetRequest().headers.GetHeader(net::HttpRequestHeaders::kOrigin,
+                                             &origin_header));
+  EXPECT_EQ(origin_header, "http://example.com");
 }
 
 TEST_F(CORSURLLoaderTest, CrossOriginRequestFetchRequestModeSameOrigin) {
@@ -310,6 +339,10 @@
   RunUntilComplete();
 
   EXPECT_TRUE(IsNetworkLoaderStarted());
+  std::string origin_header;
+  EXPECT_TRUE(GetRequest().headers.GetHeader(net::HttpRequestHeaders::kOrigin,
+                                             &origin_header));
+  EXPECT_EQ(origin_header, "http://example.com");
   EXPECT_FALSE(client().has_received_redirect());
   EXPECT_FALSE(client().has_received_response());
   EXPECT_EQ(net::ERR_FAILED, client().completion_status().error_code);
diff --git a/services/preferences/pref_service_factory_unittest.cc b/services/preferences/pref_service_factory_unittest.cc
index 78de917..38332a2d 100644
--- a/services/preferences/pref_service_factory_unittest.cc
+++ b/services/preferences/pref_service_factory_unittest.cc
@@ -613,16 +613,16 @@
         base::MakeRefCounted<InMemoryPrefStore>();
     scoped_refptr<PersistentPrefStore> underlay =
         base::MakeRefCounted<InMemoryPrefStore>();
-    const auto overlay_pref_names = GetOverlayPrefNames();
-    delegate->InitIncognitoUserPrefs(overlay, underlay, overlay_pref_names);
+    const auto persistent_pref_names = GetPersistentPrefNames();
+    delegate->InitIncognitoUserPrefs(overlay, underlay, persistent_pref_names);
     auto overlay_pref_store = base::MakeRefCounted<OverlayUserPrefStore>(
         overlay.get(), underlay.get());
-    for (auto* overlay_pref_name : overlay_pref_names)
-      overlay_pref_store->RegisterOverlayPref(overlay_pref_name);
+    for (auto* persistent_pref_name : persistent_pref_names)
+      overlay_pref_store->RegisterPersistentPref(persistent_pref_name);
     factory->set_user_prefs(std::move(overlay_pref_store));
   }
 
-  std::vector<const char*> GetOverlayPrefNames() {
+  std::vector<const char*> GetPersistentPrefNames() {
     if (GetParam())
       return {kInitialKey, kOtherInitialKey, kKey};
     return {};
diff --git a/services/preferences/pref_store_manager_impl.cc b/services/preferences/pref_store_manager_impl.cc
index 19a0b36..b9f3365 100644
--- a/services/preferences/pref_store_manager_impl.cc
+++ b/services/preferences/pref_store_manager_impl.cc
@@ -44,7 +44,7 @@
       if (owner_->incognito_persistent_pref_store_underlay_->initialized()) {
         connection->ProvideIncognitoPersistentPrefStoreUnderlay(
             owner_->incognito_persistent_pref_store_underlay_.get(),
-            owner_->overlay_pref_names_);
+            owner_->persistent_perf_names_);
       } else {
         owner_->pending_persistent_incognito_connections_.push_back(connection);
       }
@@ -66,7 +66,7 @@
     PersistentPrefStore* incognito_user_prefs_underlay,
     PrefStore* recommended_prefs,
     PrefRegistry* pref_registry,
-    std::vector<const char*> overlay_pref_names)
+    std::vector<const char*> persistent_perf_names)
     : shared_pref_registry_(std::make_unique<SharedPrefRegistry>(
           base::WrapRefCounted(pref_registry))),
       weak_factory_(this) {
@@ -85,9 +85,9 @@
             base::BindOnce(
                 &PrefStoreManagerImpl::OnIncognitoPersistentPrefStoreReady,
                 base::Unretained(this)));
-    overlay_pref_names_ = std::move(overlay_pref_names);
+    persistent_perf_names_ = std::move(persistent_perf_names);
   } else {
-    DCHECK(overlay_pref_names.empty());
+    DCHECK(persistent_perf_names.empty());
   }
   RegisterPrefStore(PrefValueStore::MANAGED_STORE, managed_prefs);
   RegisterPrefStore(PrefValueStore::SUPERVISED_USER_STORE,
@@ -133,7 +133,8 @@
   DVLOG(1) << "Incognito PersistentPrefStore ready";
   for (const auto& connection : pending_persistent_connections_)
     connection->ProvideIncognitoPersistentPrefStoreUnderlay(
-        incognito_persistent_pref_store_underlay_.get(), overlay_pref_names_);
+        incognito_persistent_pref_store_underlay_.get(),
+        persistent_perf_names_);
   pending_persistent_incognito_connections_.clear();
 }
 
diff --git a/services/preferences/pref_store_manager_impl.h b/services/preferences/pref_store_manager_impl.h
index bca15cb..2ffcc84d 100644
--- a/services/preferences/pref_store_manager_impl.h
+++ b/services/preferences/pref_store_manager_impl.h
@@ -46,7 +46,7 @@
                        PersistentPrefStore* incognito_user_prefs_underlay,
                        PrefStore* recommended_prefs,
                        PrefRegistry* pref_registry,
-                       std::vector<const char*> overlay_pref_names);
+                       std::vector<const char*> persistent_perf_names);
   ~PrefStoreManagerImpl() override;
 
   base::OnceClosure ShutDownClosure();
@@ -79,7 +79,7 @@
   std::unique_ptr<PersistentPrefStoreImpl> persistent_pref_store_;
   std::unique_ptr<PersistentPrefStoreImpl>
       incognito_persistent_pref_store_underlay_;
-  std::vector<const char*> overlay_pref_names_;
+  std::vector<const char*> persistent_perf_names_;
 
   const std::unique_ptr<SharedPrefRegistry> shared_pref_registry_;
 
diff --git a/services/preferences/public/cpp/in_process_service_factory.cc b/services/preferences/public/cpp/in_process_service_factory.cc
index 865d4c9..9779be5 100644
--- a/services/preferences/public/cpp/in_process_service_factory.cc
+++ b/services/preferences/public/cpp/in_process_service_factory.cc
@@ -57,11 +57,11 @@
   void InitIncognitoUserPrefs(
       scoped_refptr<PersistentPrefStore> incognito_user_prefs_overlay,
       scoped_refptr<PersistentPrefStore> incognito_user_prefs_underlay,
-      const std::vector<const char*>& overlay_pref_names) override {
+      const std::vector<const char*>& persistent_perf_names) override {
     factory_->user_prefs_ = std::move(incognito_user_prefs_overlay);
     factory_->incognito_user_prefs_underlay_ =
         std::move(incognito_user_prefs_underlay);
-    factory_->overlay_pref_names_ = overlay_pref_names;
+    factory_->persistent_perf_names_ = persistent_perf_names;
   }
 
   void InitPrefRegistry(PrefRegistry* pref_registry) override {
@@ -104,7 +104,7 @@
       managed_prefs_.get(), supervised_user_prefs_.get(),
       extension_prefs_.get(), command_line_prefs_.get(), user_prefs_.get(),
       incognito_user_prefs_underlay_.get(), recommended_prefs_.get(),
-      pref_registry_.get(), std::move(overlay_pref_names_));
+      pref_registry_.get(), std::move(persistent_perf_names_));
   quit_closure_ = std::move(result.second);
   return std::move(result.first);
 }
diff --git a/services/preferences/public/cpp/in_process_service_factory.h b/services/preferences/public/cpp/in_process_service_factory.h
index 16b81fd3..9b85966c 100644
--- a/services/preferences/public/cpp/in_process_service_factory.h
+++ b/services/preferences/public/cpp/in_process_service_factory.h
@@ -43,7 +43,7 @@
   scoped_refptr<PersistentPrefStore> incognito_user_prefs_underlay_;
   scoped_refptr<PrefStore> recommended_prefs_;
   scoped_refptr<PrefRegistry> pref_registry_;
-  std::vector<const char*> overlay_pref_names_;
+  std::vector<const char*> persistent_perf_names_;
 
   base::OnceClosure quit_closure_;
 
diff --git a/services/preferences/public/cpp/pref_service_factory.cc b/services/preferences/public/cpp/pref_service_factory.cc
index 2440909..1a22c8df 100644
--- a/services/preferences/public/cpp/pref_service_factory.cc
+++ b/services/preferences/public/cpp/pref_service_factory.cc
@@ -104,9 +104,9 @@
         persistent_pref_store.get(),
         new PersistentPrefStoreClient(
             std::move(incognito_connection->pref_store_connection)));
-    for (const auto& overlay_pref_name :
-         incognito_connection->overlay_pref_names) {
-      overlay_pref_store->RegisterOverlayPref(overlay_pref_name);
+    for (const auto& persistent_pref_name :
+         incognito_connection->persistent_pref_names) {
+      overlay_pref_store->RegisterPersistentPref(persistent_pref_name);
     }
     persistent_pref_store = overlay_pref_store;
   }
diff --git a/services/preferences/public/cpp/pref_service_main.cc b/services/preferences/public/cpp/pref_service_main.cc
index 500dcec2..c3d24082 100644
--- a/services/preferences/public/cpp/pref_service_main.cc
+++ b/services/preferences/public/cpp/pref_service_main.cc
@@ -18,11 +18,11 @@
                   PersistentPrefStore* incognito_user_prefs_underlay,
                   PrefStore* recommended_prefs,
                   PrefRegistry* pref_registry,
-                  std::vector<const char*> overlay_pref_names) {
+                  std::vector<const char*> persistent_perf_names) {
   auto service = std::make_unique<PrefStoreManagerImpl>(
       managed_prefs, supervised_user_prefs, extension_prefs, command_line_prefs,
       user_prefs, incognito_user_prefs_underlay, recommended_prefs,
-      pref_registry, std::move(overlay_pref_names));
+      pref_registry, std::move(persistent_perf_names));
   auto quit_closure = service->ShutDownClosure();
   return std::make_pair(std::move(service), std::move(quit_closure));
 }
diff --git a/services/preferences/public/mojom/preferences.mojom b/services/preferences/public/mojom/preferences.mojom
index 6da05831..3231dd0 100644
--- a/services/preferences/public/mojom/preferences.mojom
+++ b/services/preferences/public/mojom/preferences.mojom
@@ -79,7 +79,7 @@
 
 struct IncognitoPersistentPrefStoreConnection {
   PersistentPrefStoreConnection pref_store_connection;
-  array<string> overlay_pref_names;
+  array<string> persistent_pref_names;
 };
 
 // Allows connections to pref stores registered with |PrefStoreRegistry|.
diff --git a/services/preferences/scoped_pref_connection_builder.cc b/services/preferences/scoped_pref_connection_builder.cc
index f154b9b..656b33c 100644
--- a/services/preferences/scoped_pref_connection_builder.cc
+++ b/services/preferences/scoped_pref_connection_builder.cc
@@ -42,17 +42,17 @@
 
 void ScopedPrefConnectionBuilder::ProvideIncognitoPersistentPrefStoreUnderlay(
     PersistentPrefStoreImpl* persistent_pref_store,
-    const std::vector<const char*>& overlay_pref_names) {
+    const std::vector<const char*>& persistent_perf_names) {
   PersistentPrefStoreImpl::ObservedPrefs observed_prefs(observed_prefs_.begin(),
                                                         observed_prefs_.end());
-  std::vector<std::string> filtered_overlay_pref_names;
-  for (const char* overlay_pref_name : overlay_pref_names) {
-    if (base::ContainsKey(observed_prefs, overlay_pref_name))
-      filtered_overlay_pref_names.emplace_back(overlay_pref_name);
+  std::vector<std::string> filtered_persistent_perf_names;
+  for (const char* persistent_perf_name : persistent_perf_names) {
+    if (base::ContainsKey(observed_prefs, persistent_perf_name))
+      filtered_persistent_perf_names.emplace_back(persistent_perf_name);
   }
   incognito_connection_ = mojom::IncognitoPersistentPrefStoreConnection::New(
       persistent_pref_store->CreateConnection(std::move(observed_prefs)),
-      std::move(filtered_overlay_pref_names));
+      std::move(filtered_persistent_perf_names));
 }
 
 void ScopedPrefConnectionBuilder::ProvideDefaults(
diff --git a/services/service_manager/embedder/main.cc b/services/service_manager/embedder/main.cc
index 3480d43..ac130bf4 100644
--- a/services/service_manager/embedder/main.cc
+++ b/services/service_manager/embedder/main.cc
@@ -104,7 +104,7 @@
   DISALLOW_COPY_AND_ASSIGN(ServiceProcessLauncherDelegateImpl);
 };
 
-#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_FUCHSIA)
+#if defined(OS_POSIX) && !defined(OS_ANDROID)
 
 // Setup signal-handling state: resanitize most signals, ignore SIGPIPE.
 void SetupSignalHandlers() {
@@ -155,7 +155,7 @@
   }
 }
 
-#endif  // defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_FUCHSIA)
+#endif  // defined(OS_POSIX) && !defined(OS_ANDROID)
 
 void CommonSubprocessInit() {
 #if defined(OS_WIN)
@@ -374,7 +374,7 @@
 
 // On Android setlocale() is not supported, and we don't override the signal
 // handlers so we can get a stack trace when crashing.
-#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_FUCHSIA)
+#if defined(OS_POSIX) && !defined(OS_ANDROID)
     // Set C library locale to make sure CommandLine can parse argument values
     // in the correct encoding.
     setlocale(LC_ALL, "");
diff --git a/services/shape_detection/detection_utils_mac.h b/services/shape_detection/detection_utils_mac.h
index 2e5abab..6f46bc5 100644
--- a/services/shape_detection/detection_utils_mac.h
+++ b/services/shape_detection/detection_utils_mac.h
@@ -6,8 +6,13 @@
 #define SERVICES_SHAPE_DETECTION_DETECTION_UTILS_MAC_H_
 
 #import <CoreImage/CoreImage.h>
+#include <memory>
 
+#include "base/callback.h"
+#include "base/mac/availability.h"
 #include "base/mac/scoped_nsobject.h"
+#include "base/mac/sdk_forward_declarations.h"
+#include "base/macros.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "ui/gfx/geometry/rect_f.h"
 
@@ -20,6 +25,36 @@
 
 gfx::RectF ConvertCGToGfxCoordinates(CGRect bounds, int height);
 
+// This class submits an image analysis request for asynchronous execution on a
+// dispatch queue with default priority.
+class API_AVAILABLE(macos(10.13)) VisionAPIAsyncRequestMac {
+ public:
+  // A callback run when the asynchronous execution completes. The callback is
+  // repeating for the instance.
+  using Callback =
+      base::RepeatingCallback<void(VNRequest* request, NSError* error)>;
+
+  ~VisionAPIAsyncRequestMac();
+
+  // Creates an VisionAPIAsyncRequestMac instance which sets |callback| to be
+  // called when the asynchronous action completes.
+  static std::unique_ptr<VisionAPIAsyncRequestMac> Create(Class request_class,
+                                                          Callback callback);
+
+  // Processes asynchronously an image analysis request and returns results with
+  // |callback_| when the asynchronous request completes, the callers should
+  // only enqueue one request at a timer.
+  bool PerformRequest(const SkBitmap& bitmap);
+
+ private:
+  VisionAPIAsyncRequestMac(Callback callback, Class request_class);
+
+  base::scoped_nsobject<VNRequest> request_;
+  const Callback callback_;
+
+  DISALLOW_COPY_AND_ASSIGN(VisionAPIAsyncRequestMac);
+};
+
 }  // namespace shape_detection
 
 #endif  // SERVICES_SHAPE_DETECTION_DETECTION_UTILS_MAC_H_
diff --git a/services/shape_detection/detection_utils_mac.mm b/services/shape_detection/detection_utils_mac.mm
index 778ddb6..27bd523 100644
--- a/services/shape_detection/detection_utils_mac.mm
+++ b/services/shape_detection/detection_utils_mac.mm
@@ -4,8 +4,16 @@
 
 #include "services/shape_detection/detection_utils_mac.h"
 
+#include <vector>
+
+#include "base/bind.h"
+#include "base/logging.h"
 #include "base/mac/scoped_cftyperef.h"
+#include "base/memory/ptr_util.h"
 #include "base/numerics/checked_math.h"
+#include "base/sequenced_task_runner.h"
+#include "base/strings/sys_string_conversions.h"
+#include "base/threading/sequenced_task_runner_handle.h"
 #include "third_party/skia/include/utils/mac/SkCGUtils.h"
 
 namespace shape_detection {
@@ -46,4 +54,63 @@
                     bounds.size.width, bounds.size.height);
 }
 
+// static
+// Creates an VisionAPIAsyncRequestMac instance which sets |callback| to be
+// called when the asynchronous action completes.
+std::unique_ptr<VisionAPIAsyncRequestMac> VisionAPIAsyncRequestMac::Create(
+    Class request_class,
+    Callback callback) {
+  return base::WrapUnique(
+      new VisionAPIAsyncRequestMac(std::move(callback), request_class));
+}
+
+VisionAPIAsyncRequestMac::VisionAPIAsyncRequestMac(Callback callback,
+                                                   Class request_class)
+    : callback_(std::move(callback)) {
+  DCHECK(callback_);
+
+  scoped_refptr<base::SequencedTaskRunner> task_runner =
+      base::SequencedTaskRunnerHandle::Get();
+
+  const auto handler = ^(VNRequest* request, NSError* error) {
+    task_runner->PostTask(FROM_HERE, base::BindOnce(callback_, request, error));
+  };
+
+  request_.reset([[request_class alloc] initWithCompletionHandler:handler]);
+}
+
+VisionAPIAsyncRequestMac::~VisionAPIAsyncRequestMac() = default;
+
+// Processes asynchronously an image analysis request and returns results with
+// |callback_| when the asynchronous request completes.
+bool VisionAPIAsyncRequestMac::PerformRequest(const SkBitmap& bitmap) {
+  Class image_handler_class = NSClassFromString(@"VNImageRequestHandler");
+  if (!image_handler_class) {
+    DLOG(ERROR) << "Failed to load VNImageRequestHandler class";
+    return false;
+  }
+
+  base::scoped_nsobject<CIImage> ci_image = CreateCIImageFromSkBitmap(bitmap);
+  if (!ci_image) {
+    DLOG(ERROR) << "Failed to create image from SkBitmap";
+    return false;
+  }
+
+  base::scoped_nsobject<VNImageRequestHandler> image_handler(
+      [[image_handler_class alloc] initWithCIImage:ci_image options:@{}]);
+  if (!image_handler) {
+    DLOG(ERROR) << "Failed to create image request handler";
+    return false;
+  }
+
+  dispatch_async(
+      dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
+        NSError* ns_error = nil;
+        if ([image_handler performRequests:@[ request_ ] error:&ns_error])
+          return;
+        DLOG(ERROR) << base::SysNSStringToUTF8([ns_error localizedDescription]);
+      });
+  return true;
+}
+
 }  // namespace shape_detection
diff --git a/services/shape_detection/face_detection_impl_mac_vision.h b/services/shape_detection/face_detection_impl_mac_vision.h
index 088117e..c66be68 100644
--- a/services/shape_detection/face_detection_impl_mac_vision.h
+++ b/services/shape_detection/face_detection_impl_mac_vision.h
@@ -9,11 +9,11 @@
 #include <utility>
 
 #include "base/mac/availability.h"
-#include "base/mac/scoped_nsobject.h"
 #include "base/mac/sdk_forward_declarations.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "mojo/public/cpp/bindings/strong_binding.h"
+#include "services/shape_detection/detection_utils_mac.h"
 #include "services/shape_detection/public/mojom/facedetection.mojom.h"
 
 class SkBitmap;
@@ -36,7 +36,6 @@
   }
 
  private:
-  class VisionAPIAsyncRequestMac;
   void OnFacesDetected(VNRequest* request, NSError* error);
 
   CGSize image_size_;
diff --git a/services/shape_detection/face_detection_impl_mac_vision.mm b/services/shape_detection/face_detection_impl_mac_vision.mm
index ca546eb..52bef29e 100644
--- a/services/shape_detection/face_detection_impl_mac_vision.mm
+++ b/services/shape_detection/face_detection_impl_mac_vision.mm
@@ -7,12 +7,8 @@
 #include <vector>
 
 #include "base/bind.h"
-#include "base/callback.h"
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
-#include "base/sequenced_task_runner.h"
-#include "base/strings/sys_string_conversions.h"
-#include "services/shape_detection/detection_utils_mac.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 
 namespace shape_detection {
@@ -37,81 +33,6 @@
 }
 }
 
-// The VisionAPIAsyncRequestMac class submits an image analysis request for
-// asynchronous execution on a dispatch queue with default priority.
-class API_AVAILABLE(macos(10.13))
-    FaceDetectionImplMacVision::VisionAPIAsyncRequestMac {
- public:
-  // A callback run when the asynchronous execution completes. The callback is
-  // repeating for the instance.
-  using Callback =
-      base::RepeatingCallback<void(VNRequest* request, NSError* error)>;
-
-  ~VisionAPIAsyncRequestMac() = default;
-
-  // Creates an VisionAPIAsyncRequestMac instance which sets |callback| to be
-  // called when the asynchronous action completes.
-  static std::unique_ptr<VisionAPIAsyncRequestMac> Create(Class request_class,
-                                                          Callback callback) {
-    return base::WrapUnique(
-        new VisionAPIAsyncRequestMac(std::move(callback), request_class));
-  }
-
-  // Processes asynchronously an image analysis request and returns results with
-  // |callback_| when the asynchronous request completes.
-  bool PerformRequest(const SkBitmap& bitmap) {
-    Class image_handler_class = NSClassFromString(@"VNImageRequestHandler");
-    if (!image_handler_class) {
-      DLOG(ERROR) << "Failed to load VNImageRequestHandler class";
-      return false;
-    }
-
-    base::scoped_nsobject<CIImage> ci_image = CreateCIImageFromSkBitmap(bitmap);
-    if (!ci_image) {
-      DLOG(ERROR) << "Failed to create image from SkBitmap";
-      return false;
-    }
-
-    base::scoped_nsobject<VNImageRequestHandler> image_handler(
-        [[image_handler_class alloc] initWithCIImage:ci_image options:@{}]);
-    if (!image_handler) {
-      DLOG(ERROR) << "Failed to create image request handler";
-      return false;
-    }
-
-    dispatch_async(
-        dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
-          NSError* ns_error = nil;
-          if ([image_handler performRequests:@[ request_ ] error:&ns_error])
-            return;
-          DLOG(ERROR) << base::SysNSStringToUTF8(
-              [ns_error localizedDescription]);
-        });
-    return true;
-  }
-
- private:
-  VisionAPIAsyncRequestMac(Callback callback, Class request_class)
-      : callback_(std::move(callback)) {
-    DCHECK(callback_);
-
-    scoped_refptr<base::SequencedTaskRunner> task_runner =
-        base::SequencedTaskRunnerHandle::Get();
-
-    const auto handler = ^(VNRequest* request, NSError* error) {
-      task_runner->PostTask(FROM_HERE,
-                            base::BindOnce(callback_, request, error));
-    };
-
-    request_.reset([[request_class alloc] initWithCompletionHandler:handler]);
-  }
-
-  base::scoped_nsobject<VNRequest> request_;
-  const Callback callback_;
-
-  DISALLOW_COPY_AND_ASSIGN(VisionAPIAsyncRequestMac);
-};
-
 FaceDetectionImplMacVision::FaceDetectionImplMacVision() : weak_factory_(this) {
   Class request_class = NSClassFromString(@"VNDetectFaceLandmarksRequest");
   if (!request_class) {
diff --git a/skia/BUILD.gn b/skia/BUILD.gn
index 4ef625e5..453133c2 100644
--- a/skia/BUILD.gn
+++ b/skia/BUILD.gn
@@ -238,6 +238,13 @@
     ]
   }
 
+  # LLVM automatically sets the equivalent of GCC's -mfp16-format=ieee on ARM
+  # builds by default, while GCC itself does not. We need it to enable support
+  # for half-precision floating point data types used by SKCMS on ARM.
+  if (is_linux && !is_clang && current_cpu == "arm") {
+    cflags += [ "-mfp16-format=ieee" ]
+  }
+
   public = [
     "//third_party/skia/third_party/skcms/skcms.h",
   ]
diff --git a/sql/connection_unittest.cc b/sql/connection_unittest.cc
index 7fd8995..d357bdc 100644
--- a/sql/connection_unittest.cc
+++ b/sql/connection_unittest.cc
@@ -907,7 +907,7 @@
 }
 
 // This test manually sets on disk permissions, these don't exist on Fuchsia.
-#if defined(OS_POSIX) && !defined(OS_FUCHSIA)
+#if defined(OS_POSIX)
 // Test that set_restrict_to_user() trims database permissions so that
 // only the owner (and root) can read.
 TEST_F(SQLConnectionTest, UserPermission) {
@@ -971,7 +971,7 @@
   EXPECT_TRUE(base::GetPosixFilePermissions(journal, &mode));
   ASSERT_EQ((mode & base::FILE_PERMISSION_USER_MASK), mode);
 }
-#endif  // defined(OS_POSIX) && !defined(OS_FUCHSIA)
+#endif  // defined(OS_POSIX)
 
 // Test that errors start happening once Poison() is called.
 TEST_F(SQLConnectionTest, Poison) {
diff --git a/storage/browser/fileapi/dragged_file_util_unittest.cc b/storage/browser/fileapi/dragged_file_util_unittest.cc
index 2fb301ac..7f0f5fe 100644
--- a/storage/browser/fileapi/dragged_file_util_unittest.cc
+++ b/storage/browser/fileapi/dragged_file_util_unittest.cc
@@ -380,7 +380,7 @@
       entry.name = current.BaseName();
       expected_entry_map[entry.name.value()] = entry;
 
-#if defined(OS_POSIX) && !defined(OS_FUCHSIA)
+#if defined(OS_POSIX)
       // Creates a symlink for each file/directory.
       // They should be ignored by ReadDirectory, so we don't add them
       // to expected_entry_map.
diff --git a/storage/browser/fileapi/local_file_util_unittest.cc b/storage/browser/fileapi/local_file_util_unittest.cc
index 936d8b1..8a3bc288 100644
--- a/storage/browser/fileapi/local_file_util_unittest.cc
+++ b/storage/browser/fileapi/local_file_util_unittest.cc
@@ -142,7 +142,7 @@
 }
 
 // base::CreateSymbolicLink is supported on most POSIX, but not on Fuchsia.
-#if defined(OS_POSIX) && !defined(OS_FUCHSIA)
+#if defined(OS_POSIX)
 TEST_F(LocalFileUtilTest, CreateFailForSymlink) {
   // Create symlink target file.
   const char *target_name = "symlink_target";
diff --git a/testing/buildbot/chromium.perf.fyi.json b/testing/buildbot/chromium.perf.fyi.json
index 96b01b32..f532c1c 100644
--- a/testing/buildbot/chromium.perf.fyi.json
+++ b/testing/buildbot/chromium.perf.fyi.json
@@ -7,7 +7,7 @@
           "--browser=android-chromium",
           "--upload-results",
           "--run-ref-build",
-          "--test-shard-map-filename=android_go_14_shard_map.json"
+          "--test-shard-map-filename=android_go_shard_map.json"
         ],
         "isolate_name": "performance_test_suite",
         "merge": {
@@ -36,7 +36,7 @@
           "hard_timeout": 25200,
           "ignore_task_failure": false,
           "io_timeout": 1800,
-          "shards": 14,
+          "shards": 19,
           "upload_test_results": true
         },
         "trigger_script": {
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
index 9b5217e..2f44e68 100644
--- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
+++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
@@ -22,7 +22,7 @@
 crbug.com/591099 fast/block/marquee-width-shrinks-to-fit-in-fixed-size-container.html [ Failure ]
 
 # Whitespace differences only
-crbug.com/854889 accessibility/canvas-fallback-content-2.html [ Failure Timeout ]
+crbug.com/854889 accessibility/canvas-fallback-content-2.html [ Timeout ]
 crbug.com/854889 accessibility/css-generated-content.html [ Failure ]
 crbug.com/854889 accessibility/css-styles.html [ Failure ]
 
@@ -174,13 +174,15 @@
 crbug.com/591099 external/wpt/css/css-text/line-breaking/line-breaking-011.html [ Pass ]
 crbug.com/591099 external/wpt/css/css-text/line-breaking/line-breaking-ic-002.html [ Pass ]
 crbug.com/591099 external/wpt/css/css-text/line-breaking/line-breaking-ic-003.html [ Pass ]
+crbug.com/591099 external/wpt/css/css-text/overflow-wrap/overflow-wrap-break-word-004.html [ Failure ]
 crbug.com/591099 external/wpt/css/css-text/white-space/pre-wrap-002.html [ Pass ]
 crbug.com/40634 external/wpt/css/css-text/white-space/trailing-space-before-br-001.html [ Pass ]
 crbug.com/591099 external/wpt/css/css-text/word-break/word-break-break-all-004.html [ Pass ]
 crbug.com/591099 external/wpt/css/css-text/word-break/word-break-break-all-008.html [ Failure ]
+crbug.com/591099 external/wpt/css/css-text/word-break/word-break-break-all-011.html [ Failure ]
 crbug.com/591099 external/wpt/css/css-transforms/transform-box/view-box-mutation.html [ Failure ]
 crbug.com/591099 external/wpt/css/css-transforms/transform-transformed-tr-percent-height-child.html [ Failure ]
-crbug.com/591099 external/wpt/css/css-transitions/properties-value-003.html [ Failure Pass ]
+crbug.com/591099 external/wpt/css/css-transitions/properties-value-003.html [ Pass ]
 crbug.com/591099 external/wpt/css/css-transitions/properties-value-implicit-001.html [ Pass ]
 crbug.com/591099 external/wpt/css/css-transitions/transitions-animatable-properties-01.html [ Timeout ]
 crbug.com/591099 external/wpt/css/css-ui/box-sizing-015.html [ Failure ]
@@ -301,7 +303,6 @@
 crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/counter-styles-3/redefine-attr-mapping.html [ Failure ]
 crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-align-content-vert-001a.xhtml [ Failure ]
 crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-align-content-vert-001b.xhtml [ Failure ]
-crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-baseline-multi-item-vert-001b.html [ Pass ]
 crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-collapsed-item-baseline-001.html [ Failure ]
 crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-collapsed-item-horiz-001.html [ Failure ]
 crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-column-row-gap-002.html [ Failure ]
@@ -410,10 +411,7 @@
 crbug.com/591099 external/wpt/payment-request/payment-disabled-by-feature-policy.https.sub.html [ Pass ]
 crbug.com/591099 external/wpt/performance-timeline/po-observe.html [ Timeout ]
 crbug.com/591099 external/wpt/pointerevents/pointerevent_click_during_capture-manual.html [ Crash Timeout ]
-crbug.com/591099 external/wpt/pointerevents/pointerevent_touch-action-inherit_child-auto-child-none_touch-manual.html [ Pass Timeout ]
-crbug.com/591099 external/wpt/pointerevents/pointerevent_touch-action-inherit_parent-none_touch-manual.html [ Pass Timeout ]
 crbug.com/591099 external/wpt/quirks/line-height-calculation.html [ Failure ]
-crbug.com/591099 external/wpt/requestidlecallback/callback-exception.html [ Pass Timeout ]
 crbug.com/591099 external/wpt/requestidlecallback/callback-iframe.html [ Pass Timeout ]
 crbug.com/591099 external/wpt/requestidlecallback/callback-timeout-when-busy.html [ Timeout ]
 crbug.com/591099 external/wpt/requestidlecallback/callback-timeout.html [ Timeout ]
@@ -578,7 +576,6 @@
 crbug.com/591099 fast/lists/001-vertical.html [ Failure ]
 crbug.com/591099 fast/lists/003-vertical.html [ Failure ]
 crbug.com/591099 fast/lists/004.html [ Failure ]
-crbug.com/591099 fast/lists/list-item-line-height.html [ Failure ]
 crbug.com/860415 fast/multicol/out-of-flow/abspos-auto-position-on-line-rtl.html [ Failure ]
 crbug.com/591099 fast/overflow/overflow-update-transform.html [ Failure ]
 crbug.com/591099 fast/overflow/recompute-overflow-of-layout-root-container.html [ Failure ]
@@ -604,7 +601,7 @@
 crbug.com/591099 fast/table/fixed-table-layout/table-with-percent-width.html [ Failure ]
 crbug.com/591099 fast/table/height-percent-test-vertical.html [ Failure ]
 crbug.com/591099 fast/table/percent-height-overflow-auto-content-in-cell.html [ Failure Pass ]
-crbug.com/591099 fast/table/percent-height-overflow-scroll-content-in-cell.html [ Failure Pass ]
+crbug.com/591099 fast/table/percent-height-overflow-scroll-content-in-cell.html [ Failure ]
 crbug.com/591099 fast/table/percent-height-replaced-content-in-cell.html [ Failure ]
 crbug.com/858998 fast/table/table-continuation-outline-paint-crash.html [ Failure ]
 crbug.com/591099 fast/table/table-display-types-vertical.html [ Failure ]
@@ -651,7 +648,7 @@
 crbug.com/591099 http/tests/csspaint/invalidation-border-image.html [ Timeout ]
 crbug.com/591099 http/tests/csspaint/invalidation-content-image.html [ Timeout ]
 crbug.com/591099 http/tests/devtools/console-resource-errors.js [ Failure Pass ]
-crbug.com/591099 http/tests/devtools/console/console-search.js [ Timeout ]
+crbug.com/591099 http/tests/devtools/console/console-search.js [ Pass Timeout ]
 crbug.com/591099 http/tests/devtools/persistence/persistence-merge-editor-tabs.js [ Failure ]
 crbug.com/591099 http/tests/devtools/tracing/timeline-misc/timeline-grouped-invalidations.js [ Failure ]
 crbug.com/591099 http/tests/devtools/tracing/timeline-paint/timeline-paint-and-multiple-style-invalidations.js [ Failure ]
@@ -672,14 +669,13 @@
 crbug.com/591099 http/tests/navigation/form-targets-cross-site-frame-no-referrer.html [ Failure ]
 crbug.com/591099 http/tests/navigation/form-targets-cross-site-frame-post.html [ Failure ]
 crbug.com/591099 http/tests/navigation/form-with-enctype-targets-cross-site-frame.html [ Failure ]
-crbug.com/591099 http/tests/permissions/test-api-surface.html [ Pass ]
 crbug.com/591099 http/tests/preload/dynamic_remove_preload_href.html [ Failure Pass ]
 crbug.com/591099 http/tests/security/cors-rfc1918/addressspace-document-appcache.https.html [ Crash Failure ]
 crbug.com/591099 http/tests/security/cors-rfc1918/addressspace-document-csp-appcache.https.html [ Crash Failure Pass ]
 crbug.com/591099 http/tests/security/setDomainRelaxationForbiddenForURLScheme.html [ Crash ]
 crbug.com/591099 http/tests/security/xssAuditor/block-does-not-leak-location.html [ Failure ]
 crbug.com/591099 http/tests/websocket/invalid-subprotocol-characters.html [ Pass Timeout ]
-crbug.com/591099 idle-callback/test-runner-run-idle-tasks.html [ Pass ]
+crbug.com/591099 idle-callback/test-runner-run-idle-tasks.html [ Crash Pass Timeout ]
 crbug.com/714962 images/color-profile-background-clip-text.html [ Failure ]
 crbug.com/591099 images/color-profile-image-filter-all.html [ Failure ]
 crbug.com/714962 inspector-protocol/css/css-get-platform-fonts.js [ Failure ]
@@ -860,9 +856,8 @@
 crbug.com/591099 printing/absolute-position-headers-and-footers.html [ Failure ]
 crbug.com/591099 printing/iframe-svg-in-object-print.html [ Failure ]
 crbug.com/591099 scrollbars/auto-scrollbar-fit-content.html [ Failure ]
-crbug.com/591099 shapedetection/detection-HTMLVideoElement.html [ Pass ]
 crbug.com/591099 storage/indexeddb/cursor-continue-validity.html [ Timeout ]
-crbug.com/591099 storage/indexeddb/index-cursor.html [ Pass Timeout ]
+crbug.com/591099 storage/indexeddb/index-cursor.html [ Timeout ]
 crbug.com/591099 storage/indexeddb/mozilla/indexes.html [ Timeout ]
 crbug.com/591099 storage/indexeddb/mozilla/test_objectStore_openKeyCursor.html [ Timeout ]
 crbug.com/591099 storage/indexeddb/objectstore-cursor.html [ Pass ]
@@ -898,7 +893,7 @@
 crbug.com/591099 virtual/android/ [ Skip ]
 crbug.com/591099 virtual/exotic-color-space/ [ Skip ]
 crbug.com/591099 virtual/feature-policy-vibrate/ [ Skip ]
-crbug.com/591099 virtual/gpu-rasterization/images/color-profile-image-filter-all.html [ Failure Timeout ]
+crbug.com/591099 virtual/gpu-rasterization/images/color-profile-image-filter-all.html [ Failure ]
 crbug.com/591099 virtual/layout_ng/ [ Skip ]
 crbug.com/824918 virtual/layout_ng_experimental/ [ Skip ]
 crbug.com/591099 virtual/mojo-blob-urls/external/wpt/FileAPI/url/sandboxed-iframe.html [ Pass ]
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index c3e6976..646ea653 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -2657,6 +2657,8 @@
 crbug.com/849859 external/wpt/web-animations/timing-model/animations/pausing-an-animation.html [ Failure ]
 
 # ====== New tests from wpt-importer added here ======
+crbug.com/626703 external/wpt/css/css-text/overflow-wrap/overflow-wrap-min-content-size-002.html [ Failure ]
+crbug.com/626703 external/wpt/content-security-policy/securitypolicyviolation/targeting.html [ Timeout ]
 crbug.com/626703 external/wpt/css/css-text/white-space/break-spaces-003.html [ Failure ]
 crbug.com/626703 external/wpt/css/css-text/white-space/textarea-break-spaces-001.html [ Failure ]
 crbug.com/626703 external/wpt/css/css-text/white-space/textarea-break-spaces-003.html [ Failure ]
@@ -4610,7 +4612,6 @@
 
 # Sheriff 2018-7-12
 crbug.com/863067 [ Win10 ] virtual/user-activation-v2/fast/dom/Window/window-focus-self.html [ Failure Pass ]
-crbug.com/863160 [ Mac ] virtual/service-worker-servicification/external/wpt/service-workers/service-worker/fetch-event.https.html [ Pass Timeout ]
 
 # Sheriff 2018-7-13
 crbug.com/863599 [ Linux Debug ] external/wpt/requestidlecallback/callback-iframe.html [ Pass Timeout ]
@@ -4630,4 +4631,4 @@
 crbug.com/860706 [ Mac ] virtual/gpu/fast/canvas/color-space/canvas-createImageBitmap-rec2020.html [ Timeout Pass ]
 crbug.com/860706 [ Mac ] virtual/gpu/fast/canvas/canvas-blending-color-over-pattern.html [ Timeout Pass ]
 crbug.com/860706 [ Mac ] virtual/gpu/fast/canvas/canvas-blending-pattern-over-pattern.html [ Timeout Pass ]
-crbug.com/860706 [ Mac ] virtual/gpu/fast/canvas/canvas-shadow-source-in.html [ Timeout Pass ]
\ No newline at end of file
+crbug.com/860706 [ Mac ] virtual/gpu/fast/canvas/canvas-shadow-source-in.html [ Timeout Pass ]
diff --git a/third_party/WebKit/LayoutTests/bindings/idl-dictionary-unittest-expected.txt b/third_party/WebKit/LayoutTests/bindings/idl-dictionary-unittest-expected.txt
index 9390306..39ec385 100644
--- a/third_party/WebKit/LayoutTests/bindings/idl-dictionary-unittest-expected.txt
+++ b/third_party/WebKit/LayoutTests/bindings/idl-dictionary-unittest-expected.txt
@@ -1,4 +1,4 @@
-CONSOLE WARNING: line 270: 'window.webkitStorageInfo' is deprecated. Please use 'navigator.webkitTemporaryStorage' or 'navigator.webkitPersistentStorage' instead.
+CONSOLE WARNING: line 269: 'window.webkitStorageInfo' is deprecated. Please use 'navigator.webkitTemporaryStorage' or 'navigator.webkitPersistentStorage' instead.
 IDL dictionary unittest
 
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
@@ -20,7 +20,7 @@
 PASS dict.stringSequenceMemberWithDefault is []
 PASS dict.stringSequenceOrNullMember is null
 PASS dict.elementMember is undefined.
-PASS dict.elementOrNullMember is null
+PASS dict.elementOrNullMember is undefined.
 PASS dict.enumMember is undefined.
 PASS dict.enumMemberWithDefault is "foo"
 PASS dict.enumOrNullMember is null
@@ -47,7 +47,7 @@
 PASS dict.stringSequenceMemberWithDefault is []
 PASS dict.stringSequenceOrNullMember is null
 PASS dict.elementMember is undefined.
-PASS dict.elementOrNullMember is null
+PASS dict.elementOrNullMember is undefined.
 PASS dict.objectMember is undefined.
 PASS dict.objectOrNullMemberWithDefault is null
 PASS dict.eventTargetOrNullMember is null
@@ -176,7 +176,7 @@
 PASS derived.stringSequenceMemberWithDefault is []
 PASS derived.stringSequenceOrNullMember is null
 PASS derived.elementMember is undefined.
-PASS derived.elementOrNullMember is null
+PASS derived.elementOrNullMember is undefined.
 PASS derived.enumMember is undefined.
 PASS derived.enumMemberWithDefault is "foo"
 PASS derived.enumOrNullMember is null
diff --git a/third_party/WebKit/LayoutTests/bindings/idl-dictionary-unittest.html b/third_party/WebKit/LayoutTests/bindings/idl-dictionary-unittest.html
index cb14984c..c38c0a5 100644
--- a/third_party/WebKit/LayoutTests/bindings/idl-dictionary-unittest.html
+++ b/third_party/WebKit/LayoutTests/bindings/idl-dictionary-unittest.html
@@ -27,7 +27,7 @@
     shouldBe('dict.stringSequenceMemberWithDefault', '[]');
     shouldBeNull('dict.stringSequenceOrNullMember');
     shouldBeUndefined('dict.elementMember');
-    shouldBeNull('dict.elementOrNullMember');
+    shouldBeUndefined('dict.elementOrNullMember');
     shouldBeUndefined('dict.enumMember');
     shouldBeEqualToString('dict.enumMemberWithDefault', 'foo');
     shouldBeNull('dict.enumOrNullMember');
@@ -57,7 +57,7 @@
     shouldBe('dict.stringSequenceMemberWithDefault', '[]');
     shouldBeNull('dict.stringSequenceOrNullMember');
     shouldBeUndefined('dict.elementMember');
-    shouldBeNull('dict.elementOrNullMember');
+    shouldBeUndefined('dict.elementOrNullMember');
     shouldBeUndefined('dict.objectMember');
     shouldBeNull('dict.objectOrNullMemberWithDefault');
     shouldBeNull('dict.eventTargetOrNullMember');
@@ -111,7 +111,6 @@
     shouldBe('dict.stringSequenceMemberWithDefault', '["foo", "bar", "baz"]');
     shouldBe('dict.stringSequenceOrNullMember', '[]');
     shouldBe('dict.elementMember', 'element1');
-    // This will be undefined as the spec says
     shouldBeNull('dict.elementOrNullMember');
     shouldBeEqualToString('dict.enumMember', 'foo');
     shouldBeEqualToString('dict.enumMemberWithDefault', 'bar');
@@ -326,7 +325,7 @@
     shouldBe('derived.stringSequenceMemberWithDefault', '[]');
     shouldBeNull('derived.stringSequenceOrNullMember');
     shouldBeUndefined('derived.elementMember');
-    shouldBeNull('derived.elementOrNullMember');
+    shouldBeUndefined('derived.elementOrNullMember');
     shouldBeUndefined('derived.enumMember');
     shouldBeEqualToString('derived.enumMemberWithDefault', 'foo');
     shouldBeNull('derived.enumOrNullMember');
diff --git a/third_party/WebKit/LayoutTests/editing/deleting/delete-last-char-in-table-expected.txt b/third_party/WebKit/LayoutTests/editing/deleting/delete-last-char-in-table-expected.txt
index e78d010..96847f2 100644
--- a/third_party/WebKit/LayoutTests/editing/deleting/delete-last-char-in-table-expected.txt
+++ b/third_party/WebKit/LayoutTests/editing/deleting/delete-last-char-in-table-expected.txt
@@ -2,4 +2,4 @@
 
 
 PASS
-execDeleteCommand: <br>
+execDeleteCommand: <table style="border-collapse:collapse"><tbody><tr><td id="cursor"><br></td></tr></tbody></table>
diff --git a/third_party/WebKit/LayoutTests/editing/unsupported-content/table-delete-002.html b/third_party/WebKit/LayoutTests/editing/unsupported-content/table-delete-002.html
new file mode 100644
index 0000000..bef7a36
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/editing/unsupported-content/table-delete-002.html
@@ -0,0 +1,117 @@
+<!doctype html>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script src="../assert_selection.js"></script>
+<script>
+selection_test(
+  [
+    '<div contenteditable>',
+      '<div>',
+        'before',
+        '<table><tbody>',
+          '<tr><td>1|</td></tr>',
+        '</tbody></table>',
+        'after',
+      '</div>',
+    '</div>',
+  ],
+  'delete',
+  [
+    '<div contenteditable>',
+      'before',
+      '<table><tbody>',
+        '<tr><td>|<br></td></tr>',
+      '</tbody></table>',
+      'after',
+    '</div>',
+  ],
+  '1. Delete the last character in a single-cell table.');
+
+selection_test(
+  [
+    '<div contenteditable>',
+      '<div>',
+        'before',
+        '<table><tbody>',
+          '<tr><td>|1</td></tr>',
+        '</tbody></table>',
+        'after',
+      '</div>',
+    '</div>',
+  ],
+  'ForwardDelete',
+  [
+    '<div contenteditable>',
+      'before',
+      '<table><tbody>',
+        '<tr><td>|<br></td></tr>',
+      '</tbody></table>',
+      'after',
+    '</div>',
+  ],
+  '2. forward-delete the last character in a single-cell table.');
+
+selection_test(
+  [
+    '<div contenteditable>',
+      '<div>',
+        'before',
+        '<table><tbody>',
+          '<tr><td>|1^</td></tr>',
+        '</tbody></table>',
+        'after',
+      '</div>',
+    '</div>',
+  ],
+  'delete',
+  '<div contenteditable>before<br>|after</div>',
+  '3. Select and delete last character in a single-cell table.');
+
+selection_test(
+  [
+    '<div contenteditable>',
+      '<div>',
+        'before',
+        '<table><tbody>',
+          '<tr><td>1|</td><td></td></tr>',
+        '</tbody></table>',
+        'after',
+      '</div>',
+    '</div>',
+  ],
+  'delete',
+  [
+    '<div contenteditable>',
+      'before',
+      '<table><tbody>',
+        '<tr><td>|<br></td><td></td></tr>',
+      '</tbody></table>',
+      'after',
+    '</div>',
+  ],
+  '4. Delete the last character in a multiple-cell table.');
+
+selection_test(
+  [
+    '<div contenteditable>',
+      '<div>',
+        'before',
+        '<table><tbody>',
+          '<tr><td>|1^</td><td></td></tr>',
+        '</tbody></table>',
+        'after',
+      '</div>',
+    '</div>',
+  ],
+  'delete',
+  [
+    '<div contenteditable>',
+      'before',
+      '<table><tbody>',
+        '<tr><td>|<br></td><td></td></tr>',
+      '</tbody></table>',
+      'after',
+    '</div>',
+  ],
+  '5. Select and delete the last character in a multiple-cell table.');
+</script>
diff --git a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
index 58a2271..0c1c11b 100644
--- a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
+++ b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
@@ -36155,6 +36155,18 @@
      {}
     ]
    ],
+   "css/css-content/pseudo-element-inline-box.html": [
+    [
+     "/css/css-content/pseudo-element-inline-box.html",
+     [
+      [
+       "/css/css-content/pseudo-element-inline-box-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
    "css/css-display/display-contents-alignment-001.html": [
     [
      "/css/css-display/display-contents-alignment-001.html",
@@ -57547,6 +57559,18 @@
      {}
     ]
    ],
+   "css/css-text/overflow-wrap/overflow-wrap-min-content-size-002.html": [
+    [
+     "/css/css-text/overflow-wrap/overflow-wrap-min-content-size-002.html",
+     [
+      [
+       "/css/css-text/overflow-wrap/reference/overflow-wrap-min-content-size-002-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
    "css/css-text/overflow-wrap/word-wrap-001.html": [
     [
      "/css/css-text/overflow-wrap/word-wrap-001.html",
@@ -112527,6 +112551,11 @@
      {}
     ]
    ],
+   "css/css-content/pseudo-element-inline-box-ref.html": [
+    [
+     {}
+    ]
+   ],
    "css/css-content/resources/blank.html": [
     [
      {}
@@ -127392,6 +127421,11 @@
      {}
     ]
    ],
+   "css/css-text/overflow-wrap/reference/overflow-wrap-min-content-size-002-ref.html": [
+    [
+     {}
+    ]
+   ],
    "css/css-text/support/1x1-green.png": [
     [
      {}
@@ -130562,11 +130596,6 @@
      {}
     ]
    ],
-   "css/css-typed-om/the-stylepropertymap/properties/text-underline-position-expected.txt": [
-    [
-     {}
-    ]
-   ],
    "css/css-typed-om/the-stylepropertymap/properties/transform-box-expected.txt": [
     [
      {}
@@ -158207,6 +158236,11 @@
      {}
     ]
    ],
+   "interfaces/CSP.idl": [
+    [
+     {}
+    ]
+   ],
    "interfaces/DOM-Parsing.idl": [
     [
      {}
@@ -187236,9 +187270,9 @@
      {}
     ]
    ],
-   "content-security-policy/securitypolicyviolation/idl.html": [
+   "content-security-policy/securitypolicyviolation/idlharness.window.js": [
     [
-     "/content-security-policy/securitypolicyviolation/idl.html",
+     "/content-security-policy/securitypolicyviolation/idlharness.window.html",
      {}
     ]
    ],
@@ -278383,8 +278417,8 @@
    "ff8d1c26701d15164bcb549d42937825e1f0edd0",
    "testharness"
   ],
-  "content-security-policy/securitypolicyviolation/idl.html": [
-   "266180135d8167bc47d6c7a73798e87aa1082bee",
+  "content-security-policy/securitypolicyviolation/idlharness.window.js": [
+   "f2a3d55d5fcaa14ee93d78b7f1bc4bc8ea5a9017",
    "testharness"
   ],
   "content-security-policy/securitypolicyviolation/img-src-redirect-upgrade-reporting.https.html": [
@@ -278452,7 +278486,7 @@
    "support"
   ],
   "content-security-policy/securitypolicyviolation/targeting.html": [
-   "44a9c8d566dd2532d09972df3b5745db671ed8dc",
+   "37de17c9e37399f17662798d46970eafa2e946ec",
    "testharness"
   ],
   "content-security-policy/securitypolicyviolation/upgrade-insecure-requests-reporting.https.html": [
@@ -299999,6 +300033,14 @@
    "f491ddf2b3062ea2f9b616c968c88b9cc95f22eb",
    "reftest"
   ],
+  "css/css-content/pseudo-element-inline-box-ref.html": [
+   "9dac06a226bb54ce2c735bfb00aca30d204b2dfd",
+   "support"
+  ],
+  "css/css-content/pseudo-element-inline-box.html": [
+   "af67630b8d0f14c2a3512c942c1f8b487388ee69",
+   "reftest"
+  ],
   "css/css-content/resources/blank.html": [
    "d96d45f3a57b58460787fcde5fd15ccb324b123c",
    "support"
@@ -322763,6 +322805,10 @@
    "5858dbb88a775bb8975f338d866b6fc837485364",
    "reftest"
   ],
+  "css/css-text/overflow-wrap/overflow-wrap-min-content-size-002.html": [
+   "ae7abc617493b9e2c9313215a3f38b77c37d9450",
+   "reftest"
+  ],
   "css/css-text/overflow-wrap/reference/overflow-wrap-break-word-001-ref.html": [
    "0b16a0bdb25ddd647ad96dd82e3430274667ee87",
    "support"
@@ -322783,6 +322829,10 @@
    "f3e09183b565f71e38158cc5cd4d96ab5fbf25d4",
    "support"
   ],
+  "css/css-text/overflow-wrap/reference/overflow-wrap-min-content-size-002-ref.html": [
+   "3686ae6a0e278a970b861c165f0f840df302db70",
+   "support"
+  ],
   "css/css-text/overflow-wrap/word-wrap-001.html": [
    "8bafc4d48bbfee1e6c465a95b29792ba33c30346",
    "reftest"
@@ -332159,10 +332209,6 @@
    "53f0482b667f049170dcdfb5de29dedc6897d09a",
    "testharness"
   ],
-  "css/css-typed-om/the-stylepropertymap/properties/text-underline-position-expected.txt": [
-   "fe6dbaa0d03b38ff711eccc3b7d882fce2dc2096",
-   "support"
-  ],
   "css/css-typed-om/the-stylepropertymap/properties/text-underline-position.html": [
    "1ac67f9d349955181bb8f9ccff7c236bde9cfb26",
    "testharness"
@@ -377439,6 +377485,10 @@
    "3f9bbca50917a8a3e27d4983fa792b6d2686552e",
    "support"
   ],
+  "interfaces/CSP.idl": [
+   "d16c0274f51864f1fd689e3908a72391131f5921",
+   "support"
+  ],
   "interfaces/DOM-Parsing.idl": [
    "b24ce10738d8bf36b5a3ed6679b2e4b8d0fb34e5",
    "support"
@@ -378124,47 +378174,47 @@
    "testharness"
   ],
   "longtask-timing/longtask-attributes.html": [
-   "369f14a02d0f0786e4ec77e06274b228c55f7492",
+   "e3cc0bea49c14221c358246b60d4669e664daeff",
    "testharness"
   ],
   "longtask-timing/longtask-in-childiframe-crossorigin.html": [
-   "170372fb04c14f5b6e6c0b30e30737f1158c9ff4",
+   "394b4e3311a0fb212373b99f25dc77f49b5141a8",
    "testharness"
   ],
   "longtask-timing/longtask-in-childiframe.html": [
-   "ad63bddbeb55436c858b10ad3b0ce1f7a6c2ea39",
+   "25895063252e10e42de7f21285198eb51671e044",
    "testharness"
   ],
   "longtask-timing/longtask-in-externalscript.html": [
-   "794cba444a30f2d3ec29515818124d287069e82f",
+   "0c9cf5404186156119f16bd4ca5826f6703f6c1b",
    "testharness"
   ],
   "longtask-timing/longtask-in-parentiframe.html": [
-   "e37a81a1ac16962e6b7f1d7418c7d8b6480dbc71",
+   "28d8d7267760d23e5869fa2206275df69d065b2f",
    "testharness"
   ],
   "longtask-timing/longtask-in-raf.html": [
-   "ff32730af645cf3e7cdb39897608345ad6ebe378",
+   "8f4c904ab5af0138126ba0ae1d184034d614abbe",
    "testharness"
   ],
   "longtask-timing/longtask-in-sibling-iframe-crossorigin.html": [
-   "2e871622c6408d37bd950e5693b8415b534d4235",
+   "200324a1d086040741c9e48bee07a69dc2e7e6c6",
    "testharness"
   ],
   "longtask-timing/longtask-in-sibling-iframe.html": [
-   "7be941548fd4c33613e64e0accfe29cba9124206",
+   "a78658595305f87e8014a85edc3a8279cf2b071d",
    "testharness"
   ],
   "longtask-timing/longtask-tojson.html": [
-   "53007661d565d53bf608833520d1249af6a5d1ac",
+   "1755e11bdb5468754077d0096eaf8b606a2136ea",
    "testharness"
   ],
   "longtask-timing/resources/makelongtask.js": [
-   "64401c9b936a3a1bb43744d821258d43628819ca",
+   "e9f806fdf06f30fa3d7352534a39bd4fcd228b9c",
    "support"
   ],
   "longtask-timing/resources/raflongtask.js": [
-   "fd669203f66e5878150acf603610f2efdca51f33",
+   "61789053acfcbe4453803c2dee1fd21d14eddbb8",
    "support"
   ],
   "longtask-timing/resources/subframe-observing-longtask.html": [
@@ -378172,15 +378222,15 @@
    "support"
   ],
   "longtask-timing/resources/subframe-with-longtask.html": [
-   "07726af74120e3f066e8fd8f4988616984793428",
+   "bda4495e3a0249c111b2beb9184da52364eccc1b",
    "support"
   ],
   "longtask-timing/shared-renderer/longtask-in-new-window.html": [
-   "b8920073df5682c60b1b66d1025093f93816b36e",
+   "1f1754daaf75260d5ed706b05084e4e3edb258e5",
    "testharness"
   ],
   "longtask-timing/shared-renderer/resources/frame-with-longtask.html": [
-   "2901b02184fb36d620782fb7fd4a565124580e81",
+   "616a69279d1825f87b4e8133a17afdda21c438d4",
    "support"
   ],
   "magnetometer/META.yml": [
@@ -388484,7 +388534,7 @@
    "support"
   ],
   "picture-in-picture/idlharness.window.js": [
-   "0fecf6b24a57f6ae7ca605782fdd9bc66e3fa562",
+   "a2a5c08651d42ef14d4ffd1ac0fa0c56a7a2eb37",
    "testharness"
   ],
   "picture-in-picture/leave-picture-in-picture.html": [
diff --git a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/securitypolicyviolation/idl.html b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/securitypolicyviolation/idl.html
deleted file mode 100644
index 1849abc..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/securitypolicyviolation/idl.html
+++ /dev/null
@@ -1,54 +0,0 @@
-<!DOCTYPE html>
-<script src=/resources/testharness.js></script>
-<script src=/resources/testharnessreport.js></script>
-<script src=/resources/WebIDLParser.js></script>
-<script src=/resources/idlharness.js></script>
-<script type="text/plain" id="untested">
-  enum SecurityPolicyViolationEventDisposition {
-    "enforce", "report"
-  };
-
-  dictionary SecurityPolicyViolationEventInit : EventInit {
-      DOMString      documentURI;
-      DOMString      referrer;
-      DOMString      blockedURI;
-      DOMString      violatedDirective;
-      DOMString      effectiveDirective;
-      DOMString      originalPolicy;
-      DOMString      sourceFile;
-      SecurityPolicyViolationEventDisposition      disposition;
-      unsigned short statusCode;
-      long           lineNumber;
-      long           columnNumber;
-  };
-</script>
-<script type="text/plain" id="tested">
-  [Constructor(DOMString type, optional SecurityPolicyViolationEventInit eventInitDict)]
-  interface SecurityPolicyViolationEvent : Event {
-      readonly    attribute DOMString      documentURI;
-      readonly    attribute DOMString      referrer;
-      readonly    attribute DOMString      blockedURI;
-      readonly    attribute DOMString      violatedDirective;
-      readonly    attribute DOMString      effectiveDirective;
-      readonly    attribute DOMString      originalPolicy;
-      readonly    attribute DOMString      sourceFile;
-      readonly    attribute SecurityPolicyViolationEventDisposition      disposition;
-      readonly    attribute unsigned short statusCode;
-      readonly    attribute long           lineNumber;
-      readonly    attribute long           columnNumber;
-  };
-</script>
-<script>
-  promise_test(async function() {
-    const dom = await fetch('/interfaces/dom.idl').then(r => r.text());
-
-    const idl_array = new IdlArray();
-    idl_array.add_untested_idls(document.querySelector('#untested').textContent);
-    idl_array.add_untested_idls(dom, { only: ['Event', 'EventInit'] });
-    idl_array.add_idls(document.querySelector('#tested').textContent);
-    idl_array.add_objects({
-      SecurityPolicyViolationEvent: ['new SecurityPolicyViolationEvent({})']
-    });
-    idl_array.test();
-  })
-</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/securitypolicyviolation/idlharness.window.js b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/securitypolicyviolation/idlharness.window.js
new file mode 100644
index 0000000..361282a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/securitypolicyviolation/idlharness.window.js
@@ -0,0 +1,19 @@
+// META: script=/resources/WebIDLParser.js
+// META: script=/resources/idlharness.js
+
+// https://w3c.github.io/webappsec-csp/
+
+'use strict';
+
+idl_test(
+  ['CSP'],
+  ['dom'],
+  idl_array => {
+    idl_array.add_objects({
+      SecurityPolicyViolationEvent: [
+        'new SecurityPolicyViolationEvent("securitypolicyviolation")'
+      ]
+    })
+  },
+  'Test Content Security Policy IDL implementation'
+);
diff --git a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/securitypolicyviolation/targeting.html b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/securitypolicyviolation/targeting.html
index d27cc00..10b96e9 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/securitypolicyviolation/targeting.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/content-security-policy/securitypolicyviolation/targeting.html
@@ -35,23 +35,30 @@
             }))
             .then(t.step_func(e => {
                 assert_equals(e.blockedURI, "inline");
-                assert_equals(e.lineNumber, 135);
-                assert_equals(e.columnNumber, 7);
-                assert_equals(e.target, document, "Disconnected elements target the document");
+                assert_equals(e.lineNumber, 118);
+                assert_equals(e.columnNumber, 4);
+                assert_equals(e.target, document, "Elements created in this document, but pushed into a same-origin frame trigger on that frame's document, not on this frame's document.");
                 return watcher.wait_for('securitypolicyviolation');
             }))
             .then(t.step_func(e => {
                 assert_equals(e.blockedURI, "inline");
-                assert_equals(e.lineNumber, 146);
-                assert_equals(e.columnNumber, 7);
-                assert_equals(e.target, document, "Elements disconnected after triggering target the document.");
+                assert_equals(e.lineNumber, 131);
+                assert_equals(e.columnNumber, 4);
+                assert_equals(e.target, document, "Elements created in this document, but pushed into a same-origin frame trigger on that frame's document, not on this frame's document.");
                 return watcher.wait_for('securitypolicyviolation');
             }))
             .then(t.step_func(e => {
                 assert_equals(e.blockedURI, "inline");
-                assert_equals(e.lineNumber, 160);
-                assert_equals(e.columnNumber, 7);
-                assert_equals(e.target, document, "Elements in DocumentFragments target the document");
+                assert_equals(e.lineNumber, 139);
+                assert_equals(e.columnNumber, 4);
+                assert_equals(e.target, document, "Inline event handlers for disconnected elements target the document.");
+                return watcher.wait_for('securitypolicyviolation');
+            }))
+            .then(t.step_func(e => {
+                assert_equals(e.blockedURI, "inline");
+                assert_equals(e.lineNumber, 0);
+                assert_equals(e.columnNumber, 0);
+                assert_equals(e.target, document, "Inline event handlers for elements disconnected after triggering target the document.");
             }))
             .then(t.step_func_done(_ => {
                 unexecuted_test.done();
@@ -122,7 +129,6 @@
       assert_equals(events, 2);
     }));
     document.querySelector('#block6').contentDocument.body.appendChild(d);
-    d.click();
   }, "Elements created in this document, but pushed into a same-origin frame trigger on that frame's document, not on this frame's document.");
 </script>
 
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-content/pseudo-element-inline-box-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-content/pseudo-element-inline-box-ref.html
new file mode 100644
index 0000000..8294ae67
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-content/pseudo-element-inline-box-ref.html
@@ -0,0 +1,8 @@
+<!doctype html>
+<title>CSS Test Reference</title>
+<p>Should see a green image with a blue border</p>
+<div>
+  <span style="border: 10px solid blue">
+    <img src="resources/rect.svg">
+  </span>
+</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-content/pseudo-element-inline-box.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-content/pseudo-element-inline-box.html
new file mode 100644
index 0000000..5c16662
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-content/pseudo-element-inline-box.html
@@ -0,0 +1,15 @@
+<!doctype html>
+<title>CSS Test: content: url() on pseudo-elements is under a non-replaced box.</title>
+<link rel="match" href="pseudo-element-inline-box-ref.html">
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
+<link rel="author" title="Boris Zbarsky" href="mailto:bzbarsky@mit.edu">
+<link rel="help" href="https://drafts.csswg.org/css-content/#typedef-content-content-list">
+<style>
+  div::before {
+    border: 10px solid blue;
+    content: url(resources/rect.svg);
+    display: inline;
+  }
+</style>
+<p>Should see a green image with a blue border</p>
+<div></div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/overflow-wrap/overflow-wrap-break-word-004.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/overflow-wrap/overflow-wrap-break-word-004.html
new file mode 100644
index 0000000..560ef63
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/overflow-wrap/overflow-wrap-break-word-004.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Text Test: overflow-wrap: break-word</title>
+<link rel="author" title="Javier Fernandez Garcia-Boente" href="mailto:jfernandez@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/css-text-3/#valdef-overflow-wrap-break-word">
+<meta name="flags" content="ahem">
+<link rel="match" href="reference/overflow-wrap-break-word-001-ref.html">
+<meta name="assert" content="A Single leading white-space constitutes a soft breaking opportunity, honoring the 'white-space: pre-wrap' property, that must prevent the word to be broken.">
+<style>
+div {
+   position: relative;
+   font-size: 20px;
+   font-family: Ahem;
+}
+.red {
+  position: absolute;
+  background: green;
+  color: red;
+  width: 100px;
+  height: 100px;
+  z-index: -1;
+}
+.test {
+  color: green;
+  line-height: 1em;
+  width: 5ch;
+
+  white-space: pre-wrap;
+  overflow-wrap: break-word;
+}
+</style>
+<body>
+  <p>Test passes if there is a <strong>filled green square</strong> and <strong>no red</strong>.</p>
+  <div class="red"><br>XXXXX</div>
+  <div class="test"> XXXXX </div>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/overflow-wrap/overflow-wrap-min-content-size-002.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/overflow-wrap/overflow-wrap-min-content-size-002.html
new file mode 100644
index 0000000..5b3b1f1
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/overflow-wrap/overflow-wrap-min-content-size-002.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Text Test: overflow-wrap: break-word and intrinsic sizing</title>
+<link rel="author" title="Xidorn Quan" href="https://www.upsuper.org/">
+<link rel="author" title="Mozilla" href="https://www.mozilla.org/">
+<link rel="help" href="https://drafts.csswg.org/css-text-3/#overflow-wrap-property">
+<meta name="flags" content="">
+<link rel="match" href="reference/overflow-wrap-min-content-size-002-ref.html">
+<meta name="assert" content="overflow-wrap:break-word doesn't break grapheme cluster and min-content intrinsic size should take that into account.">
+<style>
+#wrapper {
+  width: 0px;
+  overflow-wrap: break-word;
+}
+#test {
+  float: left;
+  border: 2px solid blue;
+}
+</style>
+
+<p>Test passes if the glyphs are completely inside the blue box.
+<div id="wrapper">
+  <div id="test">&#x0ba8;&#x0bbf;&#x0bbf;&#x0bbf;&#x0bbf;&#x0ba8;&#x0bbf;&#x0bbf;&#x0bbf;&#x0bbf;</div>
+</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/overflow-wrap/reference/overflow-wrap-min-content-size-002-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/overflow-wrap/reference/overflow-wrap-min-content-size-002-ref.html
new file mode 100644
index 0000000..055ffbf3
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/overflow-wrap/reference/overflow-wrap-min-content-size-002-ref.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Text Test reference</title>
+<link rel="author" title="Xidorn Quan" href="https://www.upsuper.org/">
+<link rel="author" title="Mozilla" href="https://www.mozilla.org/">
+<style>
+#test {
+  float: left;
+  border: 2px solid blue;
+}
+</style>
+
+<p>Test passes if the glyphs are completely inside the blue box.
+<div id="wrapper">
+  <div id="test">&#x0ba8;&#x0bbf;&#x0bbf;&#x0bbf;&#x0bbf;<br>&#x0ba8;&#x0bbf;&#x0bbf;&#x0bbf;&#x0bbf;</div>
+</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/word-break/reference/word-break-break-all-010-ref.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/word-break/reference/word-break-break-all-010-ref.html
new file mode 100644
index 0000000..0e0300a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/word-break/reference/word-break-break-all-010-ref.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Text Reference File</title>
+<link rel="author" title="Florian Rivoal" href="http://florian.rivoal.net/">
+<style>
+div {
+  position: relative;
+  width: 100px;
+  height: 100px;
+  background: green;
+}
+</style>
+<body>
+  <p>Test passes if there is a <strong>filled green square</strong> and <strong>no red</strong>.</p>
+  <div></div>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/word-break/word-break-break-all-010.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/word-break/word-break-break-all-010.html
new file mode 100644
index 0000000..1ab97fb1
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/word-break/word-break-break-all-010.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Text Test: overflow-wrap: break-word</title>
+<link rel="author" title="Javier Fernandez Garcia-Boente" href="mailto:jfernandez@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/css-text-3/#valdef-word-break-break-all">
+<meta name="flags" content="ahem">
+<link rel="match" href="reference/word-break-break-all-010-ref.html">
+<meta name="assert" content="The word is broken even if pre-wrap provides a former breaking opportunity in leading white-space.">
+<style>
+div {
+   position: relative;
+   font-size: 20px;
+   font-family: Ahem;
+}
+.red {
+  position: absolute;
+  white-space: pre;
+  background: green;
+  color: red;
+  width: 100px;
+  height: 100px;
+  z-index: -1;
+}
+.test {
+  color: green;
+  line-height: 1em;
+  width: 5ch;
+
+  white-space: pre-wrap;
+  word-break: break-all;
+}
+</style>
+<body>
+  <p>Test passes if there is a <strong>filled green square</strong> and <strong>no red</strong>.</p>
+  <div class="red"> XXXX<br>X</div>
+  <div class="test"> XXXXX</div>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-text/word-break/word-break-break-all-011.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/word-break/word-break-break-all-011.html
new file mode 100644
index 0000000..ed07aeb7
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-text/word-break/word-break-break-all-011.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Text Test: overflow-wrap: break-word</title>
+<link rel="author" title="Javier Fernandez Garcia-Boente" href="mailto:jfernandez@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/css-text-3/#valdef-word-break-break-all">
+<meta name="flags" content="ahem">
+<link rel="match" href="reference/word-break-break-all-010-ref.html">
+<meta name="assert" content="A single leading white-space should account as soft breaking opportunity, honoring the 'white-space: pre-wrap', on top to the ones provided by 'word-break: break-all'.">
+<style>
+div {
+   position: relative;
+   font-size: 20px;
+   font-family: Ahem;
+}
+.red {
+  position: absolute;
+  background: green;
+  color: red;
+  width: 100px;
+  height: 100px;
+  z-index: -1;
+}
+.test {
+  color: green;
+  background: green;
+  line-height: 1em;
+  width: 1ch;
+  white-space: pre-wrap;
+  word-break: break-all;
+}
+</style>
+<body>
+  <p>Test passes if there is a <strong>filled green square</strong> and <strong>no red</strong>.</p>
+  <div class="red">X<br>X<br>X</div>
+  <div class="test"> XX</div>
+</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/text-underline-position-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/text-underline-position-expected.txt
deleted file mode 100644
index eb460df..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/text-underline-position-expected.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-This is a testharness.js-based test.
-PASS Can set 'text-underline-position' to CSS-wide keywords
-PASS Can set 'text-underline-position' to var() references
-PASS Can set 'text-underline-position' to the 'auto' keyword
-PASS Can set 'text-underline-position' to the 'under' keyword
-FAIL Can set 'text-underline-position' to the 'left' keyword Failed to execute 'set' on 'StylePropertyMap': Invalid type for property
-FAIL Can set 'text-underline-position' to the 'right' keyword Failed to execute 'set' on 'StylePropertyMap': Invalid type for property
-PASS Setting 'text-underline-position' to a length throws TypeError
-PASS Setting 'text-underline-position' to a percent throws TypeError
-PASS Setting 'text-underline-position' to a time throws TypeError
-PASS Setting 'text-underline-position' to an angle throws TypeError
-PASS Setting 'text-underline-position' to a flexible length throws TypeError
-PASS Setting 'text-underline-position' to a number throws TypeError
-PASS Setting 'text-underline-position' to a position throws TypeError
-PASS Setting 'text-underline-position' to a URL throws TypeError
-PASS Setting 'text-underline-position' to a transform throws TypeError
-FAIL 'text-underline-position' does not supported 'under left' assert_not_equals: Unsupported value must not be null got disallowed value null
-FAIL 'text-underline-position' does not supported 'right under' assert_not_equals: Unsupported value must not be null got disallowed value null
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/editing/data/delete.js b/third_party/WebKit/LayoutTests/external/wpt/editing/data/delete.js
index 8a2bd70..e5ca838 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/editing/data/delete.js
+++ b/third_party/WebKit/LayoutTests/external/wpt/editing/data/delete.js
@@ -520,6 +520,11 @@
     "<div style=\"white-space:nowrap\">foo[]bar</div>",
     [true],
     {"delete":[false,false,"",false,false,""]}],
+["foo<table><tr><td>b[]</table>baz",
+    [["delete",""]],
+    "foo<table><tbody><tr><td>[]<br></td></tr></tbody></table>baz",
+    [true],
+    {"delete":[false,false,"",false,false,""]}],
 ["foo<table><tr><td>[]bar</table>baz",
     [["delete",""]],
     "foo<table><tbody><tr><td>[]bar</td></tr></tbody></table>baz",
diff --git a/third_party/WebKit/LayoutTests/external/wpt/editing/data/forwarddelete.js b/third_party/WebKit/LayoutTests/external/wpt/editing/data/forwarddelete.js
index eb8d14ee..bbc2b11a 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/editing/data/forwarddelete.js
+++ b/third_party/WebKit/LayoutTests/external/wpt/editing/data/forwarddelete.js
@@ -215,6 +215,11 @@
     "foo{}",
     [true,true],
     {"defaultparagraphseparator":[false,false,"div",false,false,"p"],"forwarddelete":[false,false,"",false,false,""]}],
+["<table><tr><td>[]b</table>foo",
+    [["forwarddelete",""]],
+    "<table><tbody><tr><td>[]<br></td></tr></tbody></table>foo",
+    [true],
+    {"forwarddelete":[false,false,"",false,false,""]}],
 ["<table><tr><td>{}</table>foo",
     [["forwarddelete",""]],
     "<table><tbody><tr><td>{}</td></tr></tbody></table>foo",
diff --git a/third_party/WebKit/LayoutTests/external/wpt/editing/run/delete-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/editing/run/delete-expected.txt
index f1f3dfc..ca99aaf 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/editing/run/delete-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/editing/run/delete-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 6742 tests; 6568 PASS, 174 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 6751 tests; 6577 PASS, 174 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS [["delete",""]] "foo[]bar": execCommand("delete", false, "") return value
 PASS [["delete",""]] "foo[]bar" checks for modifications to non-editable content
 PASS [["delete",""]] "foo[]bar" compare innerHTML
@@ -1118,6 +1118,15 @@
 PASS [["delete",""]] "<div style=white-space:nowrap>foo  []bar</div>" queryCommandIndeterm("delete") after
 PASS [["delete",""]] "<div style=white-space:nowrap>foo  []bar</div>" queryCommandState("delete") after
 PASS [["delete",""]] "<div style=white-space:nowrap>foo  []bar</div>" queryCommandValue("delete") after
+PASS [["delete",""]] "foo<table><tr><td>b[]</table>baz": execCommand("delete", false, "") return value
+PASS [["delete",""]] "foo<table><tr><td>b[]</table>baz" checks for modifications to non-editable content
+PASS [["delete",""]] "foo<table><tr><td>b[]</table>baz" compare innerHTML
+PASS [["delete",""]] "foo<table><tr><td>b[]</table>baz" queryCommandIndeterm("delete") before
+PASS [["delete",""]] "foo<table><tr><td>b[]</table>baz" queryCommandState("delete") before
+PASS [["delete",""]] "foo<table><tr><td>b[]</table>baz" queryCommandValue("delete") before
+PASS [["delete",""]] "foo<table><tr><td>b[]</table>baz" queryCommandIndeterm("delete") after
+PASS [["delete",""]] "foo<table><tr><td>b[]</table>baz" queryCommandState("delete") after
+PASS [["delete",""]] "foo<table><tr><td>b[]</table>baz" queryCommandValue("delete") after
 PASS [["delete",""]] "foo<table><tr><td>[]bar</table>baz": execCommand("delete", false, "") return value
 PASS [["delete",""]] "foo<table><tr><td>[]bar</table>baz" checks for modifications to non-editable content
 PASS [["delete",""]] "foo<table><tr><td>[]bar</table>baz" compare innerHTML
diff --git a/third_party/WebKit/LayoutTests/external/wpt/editing/run/forwarddelete-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/editing/run/forwarddelete-expected.txt
index 8ffcaa04..ae737fe 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/editing/run/forwarddelete-expected.txt
+++ b/third_party/WebKit/LayoutTests/external/wpt/editing/run/forwarddelete-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 6409 tests; 6277 PASS, 132 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 6418 tests; 6286 PASS, 132 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS [["forwarddelete",""]] "foo[]": execCommand("forwarddelete", false, "") return value
 PASS [["forwarddelete",""]] "foo[]" checks for modifications to non-editable content
 PASS [["forwarddelete",""]] "foo[]" compare innerHTML
@@ -555,6 +555,15 @@
 PASS [["defaultparagraphseparator","p"],["forwarddelete",""]] "foo{}<p>" queryCommandIndeterm("forwarddelete") after
 PASS [["defaultparagraphseparator","p"],["forwarddelete",""]] "foo{}<p>" queryCommandState("forwarddelete") after
 PASS [["defaultparagraphseparator","p"],["forwarddelete",""]] "foo{}<p>" queryCommandValue("forwarddelete") after
+PASS [["forwarddelete",""]] "<table><tr><td>[]b</table>foo": execCommand("forwarddelete", false, "") return value
+PASS [["forwarddelete",""]] "<table><tr><td>[]b</table>foo" checks for modifications to non-editable content
+PASS [["forwarddelete",""]] "<table><tr><td>[]b</table>foo" compare innerHTML
+PASS [["forwarddelete",""]] "<table><tr><td>[]b</table>foo" queryCommandIndeterm("forwarddelete") before
+PASS [["forwarddelete",""]] "<table><tr><td>[]b</table>foo" queryCommandState("forwarddelete") before
+PASS [["forwarddelete",""]] "<table><tr><td>[]b</table>foo" queryCommandValue("forwarddelete") before
+PASS [["forwarddelete",""]] "<table><tr><td>[]b</table>foo" queryCommandIndeterm("forwarddelete") after
+PASS [["forwarddelete",""]] "<table><tr><td>[]b</table>foo" queryCommandState("forwarddelete") after
+PASS [["forwarddelete",""]] "<table><tr><td>[]b</table>foo" queryCommandValue("forwarddelete") after
 PASS [["forwarddelete",""]] "<table><tr><td>{}</table>foo": execCommand("forwarddelete", false, "") return value
 PASS [["forwarddelete",""]] "<table><tr><td>{}</table>foo" checks for modifications to non-editable content
 PASS [["forwarddelete",""]] "<table><tr><td>{}</table>foo" compare innerHTML
diff --git a/third_party/WebKit/LayoutTests/external/wpt/interfaces/CSP.idl b/third_party/WebKit/LayoutTests/external/wpt/interfaces/CSP.idl
new file mode 100644
index 0000000..03d4306e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/interfaces/CSP.idl
@@ -0,0 +1,39 @@
+// GENERATED CONTENT - DO NOT EDIT
+// Content of this file was automatically extracted from the
+// "Content Security Policy Level 3" spec.
+// See: https://w3c.github.io/webappsec-csp/
+
+enum SecurityPolicyViolationEventDisposition {
+  "enforce", "report"
+};
+
+[Constructor(DOMString type, optional SecurityPolicyViolationEventInit eventInitDict)]
+interface SecurityPolicyViolationEvent : Event {
+    readonly    attribute USVString      documentURI;
+    readonly    attribute USVString      referrer;
+    readonly    attribute USVString      blockedURI;
+    readonly    attribute DOMString      violatedDirective;
+    readonly    attribute DOMString      effectiveDirective;
+    readonly    attribute DOMString      originalPolicy;
+    readonly    attribute USVString      sourceFile;
+    readonly    attribute DOMString      sample;
+    readonly    attribute SecurityPolicyViolationEventDisposition      disposition;
+    readonly    attribute unsigned short statusCode;
+    readonly    attribute unsigned long  lineNumber;
+    readonly    attribute unsigned long  columnNumber;
+};
+
+dictionary SecurityPolicyViolationEventInit : EventInit {
+    required USVString      documentURI;
+             USVString      referrer = "";
+             USVString      blockedURI = "";
+    required DOMString      violatedDirective;
+    required DOMString      effectiveDirective;
+    required DOMString      originalPolicy;
+             USVString      sourceFile = "";
+             DOMString      sample = "";
+    required SecurityPolicyViolationEventDisposition disposition;
+    required unsigned short statusCode;
+             unsigned long  lineNumber = 0;
+             unsigned long  columnNumber = 0;
+};
diff --git a/third_party/WebKit/LayoutTests/external/wpt/picture-in-picture/idlharness.window.js b/third_party/WebKit/LayoutTests/external/wpt/picture-in-picture/idlharness.window.js
index e10bc05..6ada0fe 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/picture-in-picture/idlharness.window.js
+++ b/third_party/WebKit/LayoutTests/external/wpt/picture-in-picture/idlharness.window.js
@@ -1,5 +1,7 @@
 // META: script=/resources/WebIDLParser.js
 // META: script=/resources/idlharness.js
+// META: script=/resources/testdriver.js
+// META: script=/resources/testdriver-vendor.js
 // META: script=resources/picture-in-picture-helpers.js
 
 'use strict';
@@ -8,10 +10,8 @@
 
 promise_test(async () => {
   try {
-    const video = await loadVideo();
-    document.body.appendChild(video);
-    self.video = video;
-    self.pipw = await video.requestPictureInPicture();
+    self.video = await loadVideo();
+    self.pipw = await requestPictureInPictureWithTrustedClick(video);
   } catch (e) {
     // Will be surfaced when video/pipw are undefined below.
   }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/fetch-event.https.html b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/fetch-event.https.html
index ecb1c1422..78e099b8 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/fetch-event.https.html
+++ b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/fetch-event.https.html
@@ -1,4 +1,5 @@
 <!DOCTYPE html>
+<meta name=timeout content=long>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script src="/common/get-host-info.sub.js"></script>
diff --git a/third_party/WebKit/LayoutTests/fast/css/CSSStyleSheet-constructable.html b/third_party/WebKit/LayoutTests/fast/css/CSSStyleSheet-constructable.html
index 429ba344..1dc3810 100644
--- a/third_party/WebKit/LayoutTests/fast/css/CSSStyleSheet-constructable.html
+++ b/third_party/WebKit/LayoutTests/fast/css/CSSStyleSheet-constructable.html
@@ -9,8 +9,7 @@
 const redStyleTexts = [".red { color: red; }", ".red + span + span { color: red; }"];
 
 test(() => {
-  // Style sheets can be created
-const sheet = new CSSStyleSheet({title: "Red", disabled: true, media: "screen, print"});
+  const sheet = new CSSStyleSheet({title: "Red", disabled: true, media: "screen, print"});
   assert_equals(sheet.title, "Red");
   assert_equals(sheet.ownerNode, null);
   assert_equals(sheet.ownerRule, null);
@@ -28,4 +27,24 @@
   assert_equals(sheet.cssRules.length, 2);
   assert_equals(sheet.cssRules[0].cssText, redStyleTexts[1]);
 }, 'Empty CSSStyleSheet can be constructed using script');
+
+promise_test(() => {
+  const promise_sheet = document.createCSSStyleSheet(redStyleTexts[0], {title: "Red", disabled: true, media: "screen, print"});
+  return promise_sheet.then(function(sheet) {
+    assert_equals(sheet.title, "Red");
+    assert_equals(sheet.ownerNode, null);
+    assert_equals(sheet.ownerRule, null);
+    assert_equals(sheet.media.length, 2);
+    assert_equals(sheet.media.item(0), "screen");
+    assert_equals(sheet.media.item(1), "print");
+    assert_true(sheet.disabled);
+    assert_equals(sheet.cssRules.length, 1);
+    assert_equals(sheet.cssRules[0].cssText, redStyleTexts[0]);
+
+    sheet.insertRule(redStyleTexts[1]);
+    assert_equals(sheet.cssRules.length, 2);
+    assert_equals(sheet.cssRules[0].cssText, redStyleTexts[1]);
+  });
+}, 'Document.createCSSStyleSheet produces Promise<CSSStyleSheet>');
+
 </script>
diff --git a/third_party/WebKit/LayoutTests/fast/css3-text/css3-text-decoration/getComputedStyle/getComputedStyle-text-underline-position-expected.txt b/third_party/WebKit/LayoutTests/fast/css3-text/css3-text-decoration/getComputedStyle/getComputedStyle-text-underline-position-expected.txt
index 4fdb7a7..e34d7d3 100644
--- a/third_party/WebKit/LayoutTests/fast/css3-text/css3-text-decoration/getComputedStyle/getComputedStyle-text-underline-position-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/css3-text/css3-text-decoration/getComputedStyle/getComputedStyle-text-underline-position-expected.txt
@@ -23,6 +23,22 @@
 PASS e.style.textUnderlinePosition is "under"
 PASS computedStyle.textUnderlinePosition is "under"
 
+Value 'left':
+PASS e.style.textUnderlinePosition is "left"
+PASS computedStyle.textUnderlinePosition is "left"
+
+Value 'right':
+PASS e.style.textUnderlinePosition is "right"
+PASS computedStyle.textUnderlinePosition is "right"
+
+Value 'under left':
+PASS e.style.textUnderlinePosition is "under left"
+PASS computedStyle.textUnderlinePosition is "under left"
+
+Value 'right under':
+PASS e.style.textUnderlinePosition is "under right"
+PASS computedStyle.textUnderlinePosition is "under right"
+
 Ancestor inherits values from parent:
 PASS e.style.textUnderlinePosition is ""
 PASS computedStyle.textUnderlinePosition is "under"
@@ -31,10 +47,22 @@
 PASS e.style.textUnderlinePosition is ""
 PASS computedStyle.textUnderlinePosition is "under"
 
+Value 'auto left':
+PASS e.style.textUnderlinePosition is ""
+PASS computedStyle.textUnderlinePosition is "under"
+
+Value 'right auto':
+PASS e.style.textUnderlinePosition is ""
+PASS computedStyle.textUnderlinePosition is "under"
+
 Value 'under under':
 PASS e.style.textUnderlinePosition is ""
 PASS computedStyle.textUnderlinePosition is "under"
 
+Value 'left right':
+PASS e.style.textUnderlinePosition is ""
+PASS computedStyle.textUnderlinePosition is "under"
+
 Value 'auto alphabetic under':
 PASS e.style.textUnderlinePosition is ""
 PASS computedStyle.textUnderlinePosition is "under"
diff --git a/third_party/WebKit/LayoutTests/fast/css3-text/css3-text-decoration/getComputedStyle/script-tests/getComputedStyle-text-underline-position.js b/third_party/WebKit/LayoutTests/fast/css3-text/css3-text-decoration/getComputedStyle/script-tests/getComputedStyle-text-underline-position.js
index 9c97358..da85461a 100644
--- a/third_party/WebKit/LayoutTests/fast/css3-text/css3-text-decoration/getComputedStyle/script-tests/getComputedStyle-text-underline-position.js
+++ b/third_party/WebKit/LayoutTests/fast/css3-text/css3-text-decoration/getComputedStyle/script-tests/getComputedStyle-text-underline-position.js
@@ -36,6 +36,18 @@
 debug("Value 'under':");
 test("under", "under", "under");
 
+debug("Value 'left':");
+test("left", "left", "left");
+
+debug("Value 'right':");
+test("right", "right", "right");
+
+debug("Value 'under left':");
+test("under left", "under left", "under left");
+
+debug("Value 'right under':");
+test("right under", "under right", "under right");
+
 testContainer.innerHTML = '<div id="test-parent" style="text-underline-position: under;">hello <span id="test-ancestor">world</span></div>';
 debug("Ancestor inherits values from parent:");
 e = document.getElementById('test-ancestor');
@@ -44,9 +56,18 @@
 debug("Value 'auto under':");
 test("auto under", "", "under");
 
+debug("Value 'auto left':");
+test("auto left", "", "under");
+
+debug("Value 'right auto':");
+test("right auto", "", "under");
+
 debug("Value 'under under':");
 test("under under", "", "under");
 
+debug("Value 'left right':");
+test("left right", "", "under");
+
 debug("Value 'auto alphabetic under':");
 test("auto alphabetic under", "", "under");
 
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/unsupported-content/table-delete-002-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/unsupported-content/table-delete-002-expected.png
deleted file mode 100644
index 1aa6a67..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/unsupported-content/table-delete-002-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/unsupported-content/table-delete-002-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/unsupported-content/table-delete-002-expected.txt
deleted file mode 100644
index cd673a0..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/unsupported-content/table-delete-002-expected.txt
+++ /dev/null
@@ -1,61 +0,0 @@
-EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
-layer at (0,0) size 800x600
-  LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x600
-  LayoutNGBlockFlow {HTML} at (0,0) size 800x600
-    LayoutNGBlockFlow {BODY} at (8,8) size 784x584
-      LayoutNGBlockFlow {DIV} at (0,0) size 784x241 [border: (4px solid #0000FF)]
-        LayoutNGBlockFlow {DIV} at (20,20) size 744x69
-          LayoutText {#text} at (0,0) size 59x26
-            text run at (0,0) width 59: "Tests:"
-          LayoutBR {BR} at (59,0) size 0x0
-          LayoutText {#text} at (0,27) size 657x20
-            text run at (0,27) width 657: "Our ability to \"edit around\" content the HTML editing code does not yet handle very well."
-          LayoutBR {BR} at (657,27) size 0x0
-          LayoutInline {I} at (0,0) size 99x20
-            LayoutText {#text} at (0,48) size 99x20
-              text run at (0,48) width 99: "For this test: "
-          LayoutText {#text} at (99,48) size 405x20
-            text run at (99,48) width 405: "Select and delete a table and some surrounding content."
-        LayoutNGBlockFlow (anonymous) at (20,89) size 744x21
-          LayoutBR {BR} at (0,0) size 0x0
-        LayoutNGBlockFlow {DIV} at (20,110) size 744x111
-          LayoutText {#text} at (0,0) size 183x26
-            text run at (0,0) width 183: "Expected Results:"
-          LayoutBR {BR} at (183,0) size 0x0
-          LayoutText {#text} at (0,27) size 709x41
-            text run at (0,27) width 709: "The content in the red box must exactly match the content in the green box (except for the border"
-            text run at (0,48) width 48: "color)."
-          LayoutBR {BR} at (48,48) size 0x0
-          LayoutInline {I} at (0,0) size 99x20
-            LayoutText {#text} at (0,69) size 99x20
-              text run at (0,69) width 99: "For this test: "
-          LayoutText {#text} at (99,69) size 744x41
-            text run at (99,69) width 645: "Only selected content should get deleted. Surrounding content that is not selected should"
-            text run at (0,90) width 201: "(obviously) not be affected."
-      LayoutNGBlockFlow {DIV} at (0,251) size 784x32 [border: (2px solid #008000)]
-        LayoutText {#text} at (2,2) size 62x27
-          text run at (2,2) width 62: "before"
-      LayoutBlockFlow {DIV} at (0,293) size 784x32
-        LayoutBlockFlow {DIV} at (0,0) size 784x32 [border: (2px solid #FF0000)]
-          LayoutText {#text} at (2,2) size 62x27
-            text run at (2,2) width 62: "before"
-caret: position 7 of child 0 {#text} of child 1 {DIV} of child 5 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/unsupported-content/table-delete-003-expected.png b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/unsupported-content/table-delete-003-expected.png
deleted file mode 100644
index 2b22f73..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/unsupported-content/table-delete-003-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/unsupported-content/table-delete-003-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/unsupported-content/table-delete-003-expected.txt
deleted file mode 100644
index 720b4a9..0000000
--- a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-features=LayoutNG/editing/unsupported-content/table-delete-003-expected.txt
+++ /dev/null
@@ -1,70 +0,0 @@
-EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
-EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
-layer at (0,0) size 800x600
-  LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x600
-  LayoutNGBlockFlow {HTML} at (0,0) size 800x600
-    LayoutNGBlockFlow {BODY} at (8,8) size 784x584
-      LayoutNGBlockFlow {DIV} at (0,0) size 784x262 [border: (4px solid #0000FF)]
-        LayoutNGBlockFlow {DIV} at (20,20) size 744x69
-          LayoutText {#text} at (0,0) size 59x26
-            text run at (0,0) width 59: "Tests:"
-          LayoutBR {BR} at (59,0) size 0x0
-          LayoutText {#text} at (0,27) size 657x20
-            text run at (0,27) width 657: "Our ability to \"edit around\" content the HTML editing code does not yet handle very well."
-          LayoutBR {BR} at (657,27) size 0x0
-          LayoutInline {I} at (0,0) size 99x20
-            LayoutText {#text} at (0,48) size 99x20
-              text run at (0,48) width 99: "For this test: "
-          LayoutText {#text} at (99,48) size 392x20
-            text run at (99,48) width 392: "Select and delete a list and some surrounding content."
-        LayoutNGBlockFlow (anonymous) at (20,89) size 744x21
-          LayoutBR {BR} at (0,0) size 0x0
-        LayoutNGBlockFlow {DIV} at (20,110) size 744x132
-          LayoutText {#text} at (0,0) size 183x26
-            text run at (0,0) width 183: "Expected Results:"
-          LayoutBR {BR} at (183,0) size 0x0
-          LayoutText {#text} at (0,27) size 709x41
-            text run at (0,27) width 709: "The content in the red box must exactly match the content in the green box (except for the border"
-            text run at (0,48) width 48: "color)."
-          LayoutBR {BR} at (48,48) size 0x0
-          LayoutInline {I} at (0,0) size 99x20
-            LayoutText {#text} at (0,69) size 99x20
-              text run at (0,69) width 99: "For this test: "
-          LayoutText {#text} at (99,69) size 744x41
-            text run at (99,69) width 645: "Only selected content should get deleted. Surrounding content that is not selected should"
-            text run at (0,90) width 201: "(obviously) not be affected."
-          LayoutBR {BR} at (201,90) size 0x0
-          LayoutInline {B} at (0,0) size 718x20
-            LayoutText {#text} at (0,111) size 718x20
-              text run at (0,111) width 718: "There is a bug: the caret ends up in the wrong position, it should be in the empty paragraph."
-        LayoutNGBlockFlow (anonymous) at (20,242) size 744x0
-          LayoutInline {B} at (0,0) size 0x0
-            LayoutText {#text} at (0,0) size 0x0
-      LayoutNGBlockFlow (anonymous) at (0,272) size 784x0
-        LayoutInline {B} at (0,0) size 0x0
-          LayoutText {#text} at (0,0) size 0x0
-      LayoutNGBlockFlow (anonymous) at (0,272) size 784x126
-        LayoutNGBlockFlow {DIV} at (0,0) size 784x58 [border: (2px solid #008000)]
-          LayoutBR {BR} at (2,2) size 0x0
-          LayoutText {#text} at (2,29) size 50x26
-            text run at (2,29) width 50: "after"
-        LayoutBlockFlow {DIV} at (0,68) size 784x58
-          LayoutBlockFlow {DIV} at (0,0) size 784x58 [border: (2px solid #FF0000)]
-            LayoutBR {BR} at (2,2) size 0x26
-            LayoutText {#text} at (2,29) size 50x26
-              text run at (2,29) width 50: "after"
-      LayoutNGBlockFlow (anonymous) at (0,398) size 784x0
-        LayoutInline {B} at (0,0) size 0x0
-caret: position 0 of child 1 {#text} of child 1 {DIV} of child 3 {DIV} of child 2 {B} of body
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/overflow/image-selection-highlight-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/fast/overflow/image-selection-highlight-expected.txt
new file mode 100644
index 0000000..f2c5242
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/overflow/image-selection-highlight-expected.txt
@@ -0,0 +1,49 @@
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  LayoutBlockFlow {HTML} at (0,0) size 800x600
+    LayoutBlockFlow {BODY} at (8,8) size 784x584
+      LayoutBlockFlow {P} at (0,0) size 784x40
+        LayoutText {#text} at (0,0) size 212x19
+          text run at (0,0) width 212: "This tests for a regression against "
+        LayoutInline {I} at (0,0) size 767x39
+          LayoutInline {A} at (0,0) size 348x19 [color=#0000EE]
+            LayoutText {#text} at (212,0) size 348x19
+              text run at (212,0) width 348: "http://bugzilla.opendarwin.org/show_bug.cgi?id=6673"
+          LayoutText {#text} at (559,0) size 767x39
+            text run at (559,0) width 5: " "
+            text run at (563,0) width 204: "Selection highlight doesn't scroll"
+            text run at (0,20) width 369: "along with an image contained in an overflow:scroll block"
+        LayoutText {#text} at (368,20) size 5x19
+          text run at (368,20) width 5: "."
+      LayoutBlockFlow {P} at (0,56) size 784x40
+        LayoutText {#text} at (0,0) size 748x39
+          text run at (0,0) width 412: "There should be one contiguous highlight from \x{201C}elit\x{201D} to \x{201C}Etiam\x{201D}, "
+          text run at (412,0) width 336: "including the orange square, and no other highlighted"
+          text run at (0,20) width 36: "areas."
+      LayoutBlockFlow {HR} at (0,112) size 784x2 [border: (1px inset #EEEEEE)]
+layer at (8,130) size 100x200 clip at (8,130) size 85x200 scrollY 40.00 scrollHeight 320
+  LayoutBlockFlow {DIV} at (0,122) size 100x200
+    LayoutText {#text} at (0,0) size 84x119
+      text run at (0,0) width 84: "Lorem ipsum"
+      text run at (0,20) width 51: "dolor sit"
+      text run at (0,40) width 34: "amet,"
+      text run at (0,60) width 78: "consectetuer"
+      text run at (0,80) width 64: "adipiscing"
+      text run at (0,100) width 27: "elit. "
+    LayoutImage {IMG} at (27,105) size 10x10
+    LayoutText {#text} at (37,100) size 83x219
+      text run at (37,100) width 4: " "
+      text run at (41,100) width 37: "Etiam"
+      text run at (0,120) width 57: "et ipsum."
+      text run at (0,140) width 31: "Nam"
+      text run at (0,160) width 78: "consectetuer"
+      text run at (0,180) width 81: "mi eget velit."
+      text run at (0,200) width 83: "Sed nec risus"
+      text run at (0,220) width 60: "vitae felis"
+      text run at (0,240) width 39: "auctor"
+      text run at (0,260) width 53: "ultricies."
+      text run at (0,280) width 79: "Pellentesque"
+      text run at (0,300) width 54: "aliquet..."
+selection start: position 58 of child 0 {#text} of child 7 {DIV} of body
+selection end:   position 11 of child 2 {#text} of child 7 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/text/selection/atsui-partial-selection-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/fast/text/selection/atsui-partial-selection-expected.txt
new file mode 100644
index 0000000..49b33e9
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/text/selection/atsui-partial-selection-expected.txt
@@ -0,0 +1,32 @@
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  LayoutBlockFlow {HTML} at (0,0) size 800x600
+    LayoutBlockFlow {BODY} at (8,8) size 784x576
+      LayoutBlockFlow {P} at (0,0) size 784x40
+        LayoutText {#text} at (0,0) size 52x19
+          text run at (0,0) width 52: "Test for "
+        LayoutInline {I} at (0,0) size 749x39
+          LayoutInline {A} at (0,0) size 299x19 [color=#0000EE]
+            LayoutText {#text} at (51,0) size 299x19
+              text run at (51,0) width 299: "http://bugs.webkit.org/show_bug.cgi?id=11124"
+          LayoutText {#text} at (349,0) size 749x39
+            text run at (349,0) width 5: " "
+            text run at (353,0) width 396: "REGRESSION (r14297): No drag image for partially-selected"
+            text run at (0,20) width 79: "complex text"
+        LayoutText {#text} at (79,20) size 4x19
+          text run at (79,20) width 4: "."
+      LayoutBlockFlow {P} at (0,56) size 784x20
+        LayoutText {#text} at (0,0) size 144x19
+          text run at (0,0) width 144: "This should look like \x{201C}"
+        LayoutInline {SPAN} at (0,0) size 84x19 [color=#008000]
+          LayoutText {#text} at (144,0) size 84x19
+            text run at (144,0) width 84: "Lore\x{300}m ipsum"
+        LayoutText {#text} at (228,0) size 15x19
+          text run at (228,0) width 15: "\x{201D}: "
+        LayoutInline {SPAN} at (0,0) size 88x19
+          LayoutText {#text} at (243,0) size 88x19
+            text run at (243,0) width 88: " Lore\x{300}m ipsum"
+        LayoutText {#text} at (0,0) size 0x0
+selection start: position 1 of child 0 {#text} of child 3 {SPAN} of child 2 {P} of body
+selection end:   position 13 of child 0 {#text} of child 3 {SPAN} of child 2 {P} of body
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/text/selection/emphasis-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/fast/text/selection/emphasis-expected.txt
new file mode 100644
index 0000000..f6f6e42
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/text/selection/emphasis-expected.txt
@@ -0,0 +1,198 @@
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x554
+  LayoutBlockFlow {HTML} at (0,0) size 800x554
+    LayoutBlockFlow {BODY} at (8,8) size 784x538
+      LayoutBlockFlow {DIV} at (4,4) size 366x146 [border: (3px solid #000000)]
+        LayoutText {#text} at (3,3) size 270x27
+          text run at (3,3) width 270: "Lorem ipsum dolor sit amet,"
+        LayoutInline {SPAN} at (0,0) size 213x27
+          LayoutText {#text} at (3,45) size 213x27
+            text run at (3,45) width 213: "consectetur adipiscing"
+        LayoutText {#text} at (216,45) size 130x27
+          text run at (216,45) width 6: " "
+          text run at (222,45) width 124: "elit. Aliquam"
+        LayoutInline {SPAN} at (0,0) size 109x27
+          LayoutText {#text} at (3,73) size 109x27
+            text run at (3,73) width 109: "odio sapien"
+        LayoutText {#text} at (112,73) size 330x69
+          text run at (112,73) width 12: ", "
+          text run at (124,73) width 209: "lobortis eu iaculis vel,"
+          text run at (3,115) width 207: "scelerisque nec dolor."
+      LayoutText {#text} at (374,119) size 6x27
+        text run at (374,119) width 6: " "
+      LayoutBlockFlow {DIV} at (384,4) size 366x146 [border: (3px solid #000000)]
+        LayoutText {#text} at (3,3) size 270x27
+          text run at (3,3) width 270: "Lorem ipsum dolor sit amet,"
+        LayoutInline {SPAN} at (0,0) size 213x27
+          LayoutText {#text} at (3,45) size 213x27
+            text run at (3,45) width 213: "consectetur adipiscing"
+        LayoutText {#text} at (216,45) size 130x27
+          text run at (216,45) width 6: " "
+          text run at (222,45) width 124: "elit. Aliquam"
+        LayoutInline {SPAN} at (0,0) size 109x27
+          LayoutText {#text} at (3,73) size 109x27
+            text run at (3,73) width 109: "odio sa\x{300}pien"
+        LayoutText {#text} at (112,73) size 330x69
+          text run at (112,73) width 12: ", "
+          text run at (124,73) width 209: "lobortis eu iaculis vel,"
+          text run at (3,115) width 207: "scelerisque nec dolor."
+      LayoutText {#text} at (0,0) size 0x0
+      LayoutBlockFlow {DIV} at (4,167) size 366x161 [border: (3px solid #000000)]
+        LayoutText {#text} at (3,18) size 70x27
+          text run at (3,18) width 70: "Lorem "
+        LayoutInline {SPAN} at (0,0) size 57x27
+          LayoutText {#text} at (73,18) size 57x27
+            text run at (73,18) width 57: "ipsum"
+        LayoutText {#text} at (130,18) size 6x27
+          text run at (130,18) width 6: " "
+        LayoutInline {SPAN} at (0,0) size 50x27
+          LayoutText {#text} at (136,18) size 50x27
+            text run at (136,18) width 50: "dolor"
+        LayoutText {#text} at (186,18) size 6x27
+          text run at (186,18) width 6: " "
+        LayoutInline {SPAN} at (0,0) size 22x27
+          LayoutText {#text} at (192,18) size 22x27
+            text run at (192,18) width 22: "sit"
+        LayoutText {#text} at (214,18) size 6x27
+          text run at (214,18) width 6: " "
+        LayoutInline {SPAN} at (0,0) size 47x27
+          LayoutText {#text} at (220,18) size 47x27
+            text run at (220,18) width 47: "amet"
+        LayoutText {#text} at (267,18) size 6x27
+          text run at (267,18) width 6: ","
+        LayoutInline {SPAN} at (0,0) size 111x27
+          LayoutText {#text} at (3,60) size 111x27
+            text run at (3,60) width 111: "consectetur"
+        LayoutText {#text} at (114,60) size 6x27
+          text run at (114,60) width 6: " "
+        LayoutInline {SPAN} at (0,0) size 96x27
+          LayoutText {#text} at (120,60) size 96x27
+            text run at (120,60) width 96: "adipiscing"
+        LayoutText {#text} at (216,60) size 6x27
+          text run at (216,60) width 6: " "
+        LayoutInline {SPAN} at (0,0) size 30x27
+          LayoutText {#text} at (222,60) size 30x27
+            text run at (222,60) width 30: "elit"
+        LayoutText {#text} at (252,60) size 12x27
+          text run at (252,60) width 12: ". "
+        LayoutInline {SPAN} at (0,0) size 82x27
+          LayoutText {#text} at (264,60) size 82x27
+            text run at (264,60) width 82: "Aliquam"
+        LayoutText {#text} at (346,60) size 6x27
+          text run at (346,60) width 6: ","
+        LayoutInline {SPAN} at (0,0) size 42x27
+          LayoutText {#text} at (3,102) size 42x27
+            text run at (3,102) width 42: "odio"
+        LayoutText {#text} at (45,102) size 6x27
+          text run at (45,102) width 6: " "
+        LayoutInline {SPAN} at (0,0) size 61x27
+          LayoutText {#text} at (51,102) size 61x27
+            text run at (51,102) width 61: "sapien"
+        LayoutText {#text} at (112,102) size 12x27
+          text run at (112,102) width 12: ", "
+        LayoutInline {SPAN} at (0,0) size 72x27
+          LayoutText {#text} at (124,102) size 72x27
+            text run at (124,102) width 72: "lobortis"
+        LayoutText {#text} at (196,102) size 330x55
+          text run at (196,102) width 6: " "
+          text run at (202,102) width 131: "eu iaculis vel,"
+          text run at (3,130) width 207: "scelerisque nec dolor."
+      LayoutText {#text} at (374,297) size 6x27
+        text run at (374,297) width 6: " "
+      LayoutBlockFlow {DIV} at (384,158) size 366x156 [border: (3px solid #000000)]
+        LayoutText {#text} at (18,3) size 27x70
+          text run at (18,3) width 70: "Lorem "
+        LayoutInline {SPAN} at (0,0) size 27x57
+          LayoutText {#text} at (18,73) size 27x57
+            text run at (18,73) width 57: "ipsum"
+        LayoutText {#text} at (0,0) size 0x0
+        LayoutInline {SPAN} at (0,0) size 27x50
+          LayoutText {#text} at (60,3) size 27x50
+            text run at (60,3) width 50: "dolor"
+        LayoutText {#text} at (60,53) size 27x6
+          text run at (60,53) width 6: " "
+        LayoutInline {SPAN} at (0,0) size 27x22
+          LayoutText {#text} at (60,59) size 27x22
+            text run at (60,59) width 22: "sit"
+        LayoutText {#text} at (60,81) size 27x6
+          text run at (60,81) width 6: " "
+        LayoutInline {SPAN} at (0,0) size 27x47
+          LayoutText {#text} at (60,87) size 27x47
+            text run at (60,87) width 47: "amet"
+        LayoutText {#text} at (60,134) size 27x6
+          text run at (60,134) width 6: ","
+        LayoutInline {SPAN} at (0,0) size 27x111
+          LayoutText {#text} at (99,3) size 27x111
+            text run at (99,3) width 111: "consectetur"
+        LayoutText {#text} at (0,0) size 0x0
+        LayoutInline {SPAN} at (0,0) size 27x96
+          LayoutText {#text} at (141,3) size 27x96
+            text run at (141,3) width 96: "adipiscing"
+        LayoutText {#text} at (141,99) size 27x6
+          text run at (141,99) width 6: " "
+        LayoutInline {SPAN} at (0,0) size 27x30
+          LayoutText {#text} at (141,105) size 27x30
+            text run at (141,105) width 30: "elit"
+        LayoutText {#text} at (141,135) size 27x6
+          text run at (141,135) width 6: "."
+        LayoutInline {SPAN} at (0,0) size 27x82
+          LayoutText {#text} at (183,3) size 27x82
+            text run at (183,3) width 82: "Aliquam"
+        LayoutText {#text} at (183,85) size 27x12
+          text run at (183,85) width 12: ", "
+        LayoutInline {SPAN} at (0,0) size 27x42
+          LayoutText {#text} at (183,97) size 27x42
+            text run at (183,97) width 42: "odio"
+        LayoutText {#text} at (0,0) size 0x0
+        LayoutInline {SPAN} at (0,0) size 27x61
+          LayoutText {#text} at (225,3) size 27x61
+            text run at (225,3) width 61: "sapien"
+        LayoutText {#text} at (225,64) size 27x12
+          text run at (225,64) width 12: ", "
+        LayoutInline {SPAN} at (0,0) size 27x72
+          LayoutText {#text} at (225,76) size 27x72
+            text run at (225,76) width 72: "lobortis"
+        LayoutText {#text} at (253,3) size 83x146
+          text run at (253,3) width 131: "eu iaculis vel,"
+          text run at (281,3) width 146: "scelerisque nec"
+          text run at (309,3) width 55: "dolor."
+      LayoutText {#text} at (0,0) size 0x0
+      LayoutBlockFlow {DIV} at (4,336) size 366x198 [border: (3px solid #000000)]
+        LayoutText {#text} at (3,13) size 270x27
+          text run at (3,13) width 270: "Lorem ipsum dolor sit amet,"
+        LayoutInline {SPAN} at (0,0) size 213x27
+          LayoutText {#text} at (3,61) size 213x27
+            text run at (3,61) width 213: "consectetur adipiscing"
+        LayoutText {#text} at (216,61) size 130x27
+          text run at (216,61) width 6: " "
+          text run at (222,61) width 124: "elit. Aliquam"
+        LayoutInline {SPAN} at (0,0) size 109x27
+          LayoutText {#text} at (3,109) size 109x27
+            text run at (3,109) width 109: "odio sapien"
+        LayoutText {#text} at (112,109) size 330x75
+          text run at (112,109) width 12: ", "
+          text run at (124,109) width 209: "lobortis eu iaculis vel,"
+          text run at (3,157) width 207: "scelerisque nec dolor."
+      LayoutText {#text} at (374,493) size 6x27
+        text run at (374,493) width 6: " "
+      LayoutBlockFlow {DIV} at (384,378) size 366x146 [border: (3px solid #000000)]
+        LayoutText {#text} at (3,3) size 270x27
+          text run at (3,3) width 270: "Lorem ipsum dolor sit amet,"
+        LayoutInline {SPAN} at (0,0) size 213x27
+          LayoutText {#text} at (3,45) size 213x27
+            text run at (3,45) width 213: "consectetur adipiscing"
+        LayoutText {#text} at (216,45) size 130x27
+          text run at (216,45) width 6: " "
+          text run at (222,45) width 124: "elit. Aliquam"
+        LayoutInline {SPAN} at (0,0) size 109x27
+          LayoutText {#text} at (3,73) size 109x27
+            text run at (3,73) width 109: "odio sapien"
+        LayoutText {#text} at (112,73) size 330x69
+          text run at (112,73) width 12: ", "
+          text run at (124,73) width 209: "lobortis eu iaculis vel,"
+          text run at (3,115) width 207: "scelerisque nec dolor."
+      LayoutText {#text} at (0,0) size 0x0
+      LayoutText {#text} at (0,0) size 0x0
+selection start: position 10 of child 0 {#text} of child 1 {SPAN} of child 10 {DIV} of body
+selection end:   position 7 of child 0 {#text} of child 3 {SPAN} of child 10 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/text/selection/justified-selection-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/fast/text/selection/justified-selection-expected.txt
new file mode 100644
index 0000000..d7f8b8e8
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/text/selection/justified-selection-expected.txt
@@ -0,0 +1,33 @@
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  LayoutBlockFlow {HTML} at (0,0) size 800x600
+    LayoutBlockFlow {BODY} at (8,8) size 784x584
+      LayoutBlockFlow {P} at (0,0) size 784x20
+        LayoutText {#text} at (0,0) size 106x19
+          text run at (0,0) width 106: "Test for revision "
+        LayoutInline {A} at (0,0) size 49x19 [color=#0000EE]
+          LayoutText {#text} at (105,0) size 49x19
+            text run at (105,0) width 49: "#20574"
+        LayoutText {#text} at (153,0) size 5x19
+          text run at (153,0) width 5: "."
+      LayoutBlockFlow {P} at (0,36) size 784x20
+        LayoutText {#text} at (0,0) size 251x19
+          text run at (0,0) width 251: "The two blue boxes should be identical."
+      LayoutBlockFlow {DIV} at (0,72) size 106x46 [border: (3px solid #0000FF)]
+        LayoutText {#text} at (3,3) size 10x19
+          text run at (3,3) width 10: "L"
+        LayoutInline {SPAN} at (0,0) size 40x19 [color=#008000] [bgcolor=#FFFF00]
+          LayoutText {#text} at (13,3) size 40x19
+            text run at (13,3) width 40: "o r"
+        LayoutText {#text} at (53,3) size 100x39
+          text run at (53,3) width 50: "e mi"
+          text run at (3,23) width 67: "psumdolor"
+      LayoutBlockFlow (anonymous) at (0,118) size 784x20
+        LayoutBR {BR} at (0,0) size 0x19
+      LayoutBlockFlow {DIV} at (0,138) size 106x46 [border: (3px solid #0000FF)]
+        LayoutText {#text} at (3,3) size 100x39
+          text run at (3,3) width 100: "Lo re mi"
+          text run at (3,23) width 67: "psumdolor"
+selection start: position 1 of child 0 {#text} of child 8 {DIV} of body
+selection end:   position 4 of child 0 {#text} of child 8 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/text/selection/selection-multiple-runs-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/fast/text/selection/selection-multiple-runs-expected.txt
new file mode 100644
index 0000000..2cc01c4e
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/text/selection/selection-multiple-runs-expected.txt
@@ -0,0 +1,21 @@
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x244
+  LayoutBlockFlow {HTML} at (0,0) size 800x244
+    LayoutBlockFlow {BODY} at (8,30) size 784x206
+      LayoutBlockFlow {P} at (0,0) size 784x70
+        LayoutText {#text} at (0,0) size 766x69
+          text run at (0,0) width 766: "The selection should be painted correctly from and including \x{732B}"
+          text run at (0,35) width 579: "until and including C, then from right to left for "
+          text run at (579,35) width 39 RTL: "\x{627}\x{644}\x{639}\x{631}"
+          text run at (618,35) width 8: "."
+      LayoutBlockFlow {DIV} at (0,100) size 784x53
+        LayoutText {#text} at (0,7) size 415x34
+          text run at (0,7) width 351: "\x{543E}\x{8F29}\x{306F}\x{732B}\x{3067} \x{92E}\x{93E}\x{928}\x{915} \x{939}\x{93F}\x{928}\x{94D}\x{926}\x{940}ABC"
+          text run at (351,7) width 64 RTL: "\x{627}\x{644}\x{639}\x{631}\x{628}\x{64A}\x{629}"
+      LayoutBlockFlow {DIV} at (0,153) size 784x53
+        LayoutText {#text} at (0,7) size 415x34
+          text run at (0,7) width 351: "\x{543E}\x{8F29}\x{306F}\x{732B}\x{3067} \x{92E}\x{93E}\x{928}\x{915} \x{939}\x{93F}\x{928}\x{94D}\x{926}\x{940}ABC"
+          text run at (351,7) width 64 RTL: "\x{627}\x{644}\x{639}\x{631}\x{628}\x{64A}\x{629}"
+selection start: position 3 of child 0 {#text} of child 5 {DIV} of body
+selection end:   position 24 of child 0 {#text} of child 5 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/text/selection/should-use-atsui-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/fast/text/selection/should-use-atsui-expected.txt
new file mode 100644
index 0000000..f199fc6
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/text/selection/should-use-atsui-expected.txt
@@ -0,0 +1,25 @@
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  LayoutBlockFlow {HTML} at (0,0) size 800x600
+    LayoutBlockFlow {BODY} at (8,8) size 784x584
+      LayoutBlockFlow {P} at (0,0) size 784x40
+        LayoutText {#text} at (0,0) size 52x19
+          text run at (0,0) width 52: "Test for "
+        LayoutInline {I} at (0,0) size 734x39
+          LayoutText {#text} at (51,0) size 734x39
+            text run at (51,0) width 683: "http://bugzilla.opendarwin.org/show_bug.cgi?id=6132 Incorrect selection highlighting for ATSUI text when"
+            text run at (0,20) width 176: "selected range is \"CG-safe\""
+        LayoutText {#text} at (176,20) size 4x19
+          text run at (176,20) width 4: "."
+      LayoutBlockFlow {P} at (0,56) size 784x20
+        LayoutText {#text} at (0,0) size 708x19
+          text run at (0,0) width 708: "The word \x{201C}dolor\x{201D} below should be highlighted in its entirety. The highlight should not extend beyond that word."
+      LayoutBlockFlow {HR} at (0,92) size 784x2 [border: (1px inset #EEEEEE)]
+      LayoutBlockFlow (anonymous) at (0,102) size 784x20
+        LayoutInline {SPAN} at (0,0) size 173x19
+          LayoutText {#text} at (0,0) size 173x19
+            text run at (0,0) width 173: "Lo\x{308}re\x{300}m ipsum dolor sit amet"
+        LayoutText {#text} at (0,0) size 0x0
+selection start: position 14 of child 0 {#text} of child 7 {SPAN} of body
+selection end:   position 19 of child 0 {#text} of child 7 {SPAN} of body
diff --git a/third_party/WebKit/LayoutTests/platform/linux/fast/writing-mode/japanese-rl-selection-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/fast/writing-mode/japanese-rl-selection-expected.txt
new file mode 100644
index 0000000..7cc5f34e61
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/platform/linux/fast/writing-mode/japanese-rl-selection-expected.txt
@@ -0,0 +1,23 @@
+layer at (0,0) size 800x600
+  LayoutView at (0,0) size 800x600
+layer at (418,0) size 382x600
+  LayoutBlockFlow {HTML} at (0,0) size 382x600 [border: (10px solid #800000)]
+    LayoutBlockFlow {BODY} at (18,18) size 346x564 [border: (5px solid #000000)]
+      LayoutBlockFlow {DIV} at (5,105) size 336x400
+        LayoutText {#text} at (0,0) size 335x399
+          text run at (0,0) width 399: "\x{305B}\x{3063}\x{304B}\x{304F}\x{898B}\x{3064}\x{3051}\x{305F}\x{3059}\x{3070}\x{3089}\x{3057}\x{3044}\x{8A18}\x{4E8B}\x{304C}\x{3069}\x{3053}\x{306B}"
+          text run at (24,0) width 399: "\x{3042}\x{3063}\x{305F}\x{304B}\x{5FD8}\x{308C}\x{3066}\x{3057}\x{307E}\x{3063}\x{305F}\x{7D4C}\x{9A13}\x{306F}\x{3042}\x{308A}\x{307E}\x{3059}\x{304B}"
+          text run at (48,0) width 399: "\x{306A}\x{3089}\x{30BF}\x{30A4}\x{30C8}\x{30EB}\x{3068}\x{30A2}\x{30C9}\x{30EC}\x{30B9}\x{3060}\x{3051}\x{3067}\x{306A}\x{304F}\x{3001}\x{8A2A}\x{554F}"
+          text run at (72,0) width 399: "\x{3057}\x{305F}\x{30A6}\x{30A7}\x{30D6}\x{30DA}\x{30FC}\x{30B8}\x{306E}\x{30B3}\x{30F3}\x{30C6}\x{30F3}\x{30C4}\x{304B}\x{3089}\x{3082}\x{691C}\x{7D22}"
+          text run at (96,0) width 399: "\x{3059}\x{308B}\x{3053}\x{3068}\x{304C}\x{3067}\x{304D}\x{307E}\x{3059}\x{3002}\x{305B}\x{3063}\x{304B}\x{304F}\x{898B}\x{3064}\x{3051}\x{305F}\x{3059}"
+          text run at (120,0) width 399: "\x{3070}\x{3089}\x{3057}\x{3044}\x{8A18}\x{4E8B}\x{304C}\x{3069}\x{3053}\x{306B}\x{3042}\x{3063}\x{305F}\x{304B}\x{5FD8}\x{308C}\x{3066}\x{3057}\x{307E}"
+          text run at (144,0) width 383: "\x{3063}\x{305F}\x{7D4C}\x{9A13}\x{306F}\x{3042}\x{308A}\x{307E}\x{3059}\x{304B} \x{306A}\x{3089}\x{30BF}\x{30A4}\x{30C8}\x{30EB}\x{3068}\x{30A2}"
+          text run at (168,0) width 399: "\x{30C9}\x{30EC}\x{30B9}\x{3060}\x{3051}\x{3067}\x{306A}\x{304F}\x{3001}\x{8A2A}\x{554F}\x{3057}\x{305F}\x{30A6}\x{30A7}\x{30D6}\x{30DA}\x{30FC}\x{30B8}"
+          text run at (192,0) width 399: "\x{306E}\x{30B3}\x{30F3}\x{30C6}\x{30F3}\x{30C4}\x{304B}\x{3089}\x{3082}\x{691C}\x{7D22}\x{3059}\x{308B}\x{3053}\x{3068}\x{304C}\x{3067}\x{304D}\x{307E}"
+          text run at (216,0) width 399: "\x{3059}\x{3002}\x{8A2A}\x{554F}\x{3057}\x{305F}\x{30A6}\x{30A7}\x{30D6}\x{30DA}\x{30FC}\x{30B8}\x{306E}\x{30B3}\x{30F3}\x{30C6}\x{30F3}\x{30C4}\x{304B}"
+          text run at (240,0) width 399: "\x{3089}\x{3082}\x{691C}\x{7D22}\x{3059}\x{308B}\x{3053}\x{3068}\x{304C}\x{3067}\x{304D}\x{307E}\x{3059}\x{3002}\x{305B}\x{3063}\x{304B}\x{304F}\x{898B}"
+          text run at (264,0) width 399: "\x{3064}\x{3051}\x{305F}\x{3059}\x{3070}\x{3089}\x{3057}\x{3044}\x{8A18}\x{4E8B}\x{304C}\x{3069}\x{3053}\x{306B}\x{3042}\x{3063}\x{305F}\x{304B}\x{5FD8}"
+          text run at (288,0) width 383: "\x{308C}\x{3066}\x{3057}\x{307E}\x{3063}\x{305F}\x{7D4C}\x{9A13}\x{306F}\x{3042}\x{308A}\x{307E}\x{3059}\x{304B} \x{306A}\x{3089}\x{30BF}\x{30A4}"
+          text run at (312,0) width 315: "\x{30C8}\x{30EB}\x{3068}\x{30A2}\x{30C9}\x{30EC}\x{30B9}\x{3060}\x{3051}\x{3067}\x{306A}\x{304F}\x{3001}\x{8A2A}\x{554F}"
+selection start: position 5 of child 0 {#text} of child 1 {DIV} of body
+selection end:   position 252 of child 0 {#text} of child 1 {DIV} of body
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.11/editing/selection/modify-up-on-rtl-wrapping-text-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/editing/selection/modify-up-on-rtl-wrapping-text-expected.txt
deleted file mode 100644
index 3caa47b..0000000
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.11/editing/selection/modify-up-on-rtl-wrapping-text-expected.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-This tests clicking on the left of RTL text puts the caret at the end of the line.
-
-PASS: on ך לכ, caret is at 4 initially
-PASS: on ך לכ, caret is at 2 after moving upwards once
-PASS: on ×› ×›×› ×›×›×›, caret is at 8 initially
-PASS: on ×› ×›×› ×›×›×›, caret is at 5 after moving upwards once
-PASS: on ×› ×›×› ×›×›×›, caret is at 2 after moving upwards twice
-PASS: on ×’×› ×™×’×› ×™×’×› ×™×’×› ×™×’×›, caret is at 18 initially
-PASS: on ×’×› ×™×’×› ×™×’×› ×™×’×› ×™×’×›, caret is at 14 after moving upwards once
-PASS: on ×’×› ×™×’×› ×™×’×› ×™×’×› ×™×’×›, caret is at 10 after moving upwards twice
-PASS: on ×’×› ×™×’×› ×™×’×› ×™×’×› ×™×’×›, caret is at 6 after moving upwards 3 times
-PASS: on ×’×› ×™×’×› ×™×’×› ×™×’×› ×™×’×›, caret is at 3 after moving upwards 4 times
-
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.11/editing/selection/offset-from-point-complex-scripts-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/editing/selection/offset-from-point-complex-scripts-expected.txt
deleted file mode 100644
index e4ad1bd..0000000
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.11/editing/selection/offset-from-point-complex-scripts-expected.txt
+++ /dev/null
@@ -1 +0,0 @@
-0 4 3 2 6
diff --git a/third_party/WebKit/LayoutTests/platform/win7/paint/color-emoji-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/text/color-emoji-expected.png
similarity index 100%
rename from third_party/WebKit/LayoutTests/platform/win7/paint/color-emoji-expected.png
rename to third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/text/color-emoji-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/paint/complex-preferred-logical-widths-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/text/complex-preferred-logical-widths-expected.png
similarity index 100%
rename from third_party/WebKit/LayoutTests/platform/win7/paint/complex-preferred-logical-widths-expected.png
rename to third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/text/complex-preferred-logical-widths-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/paint/drawBidiText-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/text/drawBidiText-expected.png
similarity index 100%
rename from third_party/WebKit/LayoutTests/platform/win7/paint/drawBidiText-expected.png
rename to third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/text/drawBidiText-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/paint/drawBidiText-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/text/drawBidiText-expected.txt
similarity index 100%
rename from third_party/WebKit/LayoutTests/platform/win7/paint/drawBidiText-expected.txt
rename to third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/text/drawBidiText-expected.txt
diff --git a/third_party/WebKit/LayoutTests/platform/win7/paint/emoticons-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/text/emoticons-expected.png
similarity index 100%
rename from third_party/WebKit/LayoutTests/platform/win7/paint/emoticons-expected.png
rename to third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/text/emoticons-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/paint/emphasis-complex-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/text/emphasis-complex-expected.png
similarity index 100%
rename from third_party/WebKit/LayoutTests/platform/win7/paint/emphasis-complex-expected.png
rename to third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/text/emphasis-complex-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/paint/fallback-traits-fixup-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/text/fallback-traits-fixup-expected.png
similarity index 100%
rename from third_party/WebKit/LayoutTests/platform/win7/paint/fallback-traits-fixup-expected.png
rename to third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/text/fallback-traits-fixup-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/paint/font-fallback-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/text/font-fallback-expected.png
similarity index 100%
rename from third_party/WebKit/LayoutTests/platform/win7/paint/font-fallback-expected.png
rename to third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/text/font-fallback-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/paint/font-fallback-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/text/font-fallback-expected.txt
similarity index 100%
rename from third_party/WebKit/LayoutTests/platform/win7/paint/font-fallback-expected.txt
rename to third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/text/font-fallback-expected.txt
diff --git a/third_party/WebKit/LayoutTests/platform/win7/paint/international/bidi-listbox-atsui-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/text/international/bidi-listbox-atsui-expected.png
similarity index 100%
rename from third_party/WebKit/LayoutTests/platform/win7/paint/international/bidi-listbox-atsui-expected.png
rename to third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/text/international/bidi-listbox-atsui-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/paint/international/bidi-listbox-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/text/international/bidi-listbox-expected.png
similarity index 100%
rename from third_party/WebKit/LayoutTests/platform/win7/paint/international/bidi-listbox-expected.png
rename to third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/text/international/bidi-listbox-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/paint/international/hindi-spacing-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/text/international/hindi-spacing-expected.png
similarity index 100%
rename from third_party/WebKit/LayoutTests/platform/win7/paint/international/hindi-spacing-expected.png
rename to third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/text/international/hindi-spacing-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/paint/international/lang-glyph-cache-separation-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/text/international/lang-glyph-cache-separation-expected.png
similarity index 100%
rename from third_party/WebKit/LayoutTests/platform/win7/paint/international/lang-glyph-cache-separation-expected.png
rename to third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/text/international/lang-glyph-cache-separation-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/paint/international/unicode-bidi-plaintext-in-textarea-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/text/international/unicode-bidi-plaintext-in-textarea-expected.png
similarity index 100%
rename from third_party/WebKit/LayoutTests/platform/win7/paint/international/unicode-bidi-plaintext-in-textarea-expected.png
rename to third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/text/international/unicode-bidi-plaintext-in-textarea-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/paint/justify-ideograph-complex-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/text/justify-ideograph-complex-expected.png
similarity index 100%
rename from third_party/WebKit/LayoutTests/platform/win7/paint/justify-ideograph-complex-expected.png
rename to third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/text/justify-ideograph-complex-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/paint/justify-ideograph-simple-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/text/justify-ideograph-simple-expected.png
similarity index 100%
rename from third_party/WebKit/LayoutTests/platform/win7/paint/justify-ideograph-simple-expected.png
rename to third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/text/justify-ideograph-simple-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/paint/justify-ideograph-vertical-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/text/justify-ideograph-vertical-expected.png
similarity index 100%
rename from third_party/WebKit/LayoutTests/platform/win7/paint/justify-ideograph-vertical-expected.png
rename to third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/text/justify-ideograph-vertical-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/paint/mac-system-ui-trak-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/text/mac-system-ui-trak-expected.txt
similarity index 100%
rename from third_party/WebKit/LayoutTests/platform/win7/paint/mac-system-ui-trak-expected.txt
rename to third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/text/mac-system-ui-trak-expected.txt
diff --git a/third_party/WebKit/LayoutTests/platform/win7/paint/midword-break-before-surrogate-pair-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/text/midword-break-before-surrogate-pair-expected.png
similarity index 100%
rename from third_party/WebKit/LayoutTests/platform/win7/paint/midword-break-before-surrogate-pair-expected.png
rename to third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/text/midword-break-before-surrogate-pair-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/paint/selection/flexbox-selection-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/text/selection/flexbox-selection-expected.png
similarity index 100%
rename from third_party/WebKit/LayoutTests/platform/win7/paint/selection/flexbox-selection-expected.png
rename to third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/text/selection/flexbox-selection-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/paint/selection/flexbox-selection-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/text/selection/flexbox-selection-expected.txt
similarity index 100%
rename from third_party/WebKit/LayoutTests/platform/win7/paint/selection/flexbox-selection-expected.txt
rename to third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/text/selection/flexbox-selection-expected.txt
diff --git a/third_party/WebKit/LayoutTests/platform/win7/paint/selection/flexbox-selection-nested-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/text/selection/flexbox-selection-nested-expected.png
similarity index 100%
rename from third_party/WebKit/LayoutTests/platform/win7/paint/selection/flexbox-selection-nested-expected.png
rename to third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/text/selection/flexbox-selection-nested-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/paint/selection/flexbox-selection-nested-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/text/selection/flexbox-selection-nested-expected.txt
similarity index 100%
rename from third_party/WebKit/LayoutTests/platform/win7/paint/selection/flexbox-selection-nested-expected.txt
rename to third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/text/selection/flexbox-selection-nested-expected.txt
diff --git a/third_party/WebKit/LayoutTests/platform/win7/paint/selection/khmer-selection-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/text/selection/khmer-selection-expected.png
similarity index 100%
rename from third_party/WebKit/LayoutTests/platform/win7/paint/selection/khmer-selection-expected.png
rename to third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/text/selection/khmer-selection-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/paint/selection/mixed-directionality-selection-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/text/selection/mixed-directionality-selection-expected.png
similarity index 100%
rename from third_party/WebKit/LayoutTests/platform/win7/paint/selection/mixed-directionality-selection-expected.png
rename to third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/text/selection/mixed-directionality-selection-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/text/selection/selection-painted-separately-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/text/selection/selection-painted-separately-expected.png
deleted file mode 100644
index ab30ea5..0000000
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/text/selection/selection-painted-separately-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/paint/textIteratorNilRenderer-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/text/textIteratorNilRenderer-expected.png
similarity index 100%
rename from third_party/WebKit/LayoutTests/platform/win7/paint/textIteratorNilRenderer-expected.png
rename to third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/text/textIteratorNilRenderer-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/paint/textIteratorNilRenderer-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/text/textIteratorNilRenderer-expected.txt
similarity index 100%
rename from third_party/WebKit/LayoutTests/platform/win7/paint/textIteratorNilRenderer-expected.txt
rename to third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/text/textIteratorNilRenderer-expected.txt
diff --git a/third_party/WebKit/LayoutTests/platform/win7/paint/unicode-fallback-font-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/text/unicode-fallback-font-expected.png
similarity index 100%
rename from third_party/WebKit/LayoutTests/platform/win7/paint/unicode-fallback-font-expected.png
rename to third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/text/unicode-fallback-font-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/paint/unicode-fallback-font-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/text/unicode-fallback-font-expected.txt
similarity index 100%
rename from third_party/WebKit/LayoutTests/platform/win7/paint/unicode-fallback-font-expected.txt
rename to third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/text/unicode-fallback-font-expected.txt
diff --git a/third_party/WebKit/LayoutTests/platform/win7/paint/updateNewFont-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/text/updateNewFont-expected.png
similarity index 100%
rename from third_party/WebKit/LayoutTests/platform/win7/paint/updateNewFont-expected.png
rename to third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/text/updateNewFont-expected.png
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/paint/updateNewFont-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/text/updateNewFont-expected.txt
similarity index 100%
rename from third_party/WebKit/LayoutTests/platform/win7/paint/updateNewFont-expected.txt
rename to third_party/WebKit/LayoutTests/platform/mac-mac10.11/fast/text/updateNewFont-expected.txt
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.12/editing/selection/modify-up-on-rtl-wrapping-text-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mac10.12/editing/selection/modify-up-on-rtl-wrapping-text-expected.txt
deleted file mode 100644
index a16d129..0000000
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.12/editing/selection/modify-up-on-rtl-wrapping-text-expected.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-This tests clicking on the left of RTL text puts the caret at the end of the line.
-
-PASS: on ך לכ, caret is at 4 initially
-PASS: on ך לכ, caret is at 2 after moving upwards once
-PASS: on ×› ×›×› ×›×›×›, caret is at 8 initially
-PASS: on ×› ×›×› ×›×›×›, caret is at 5 after moving upwards once
-PASS: on ×› ×›×› ×›×›×›, caret is at 2 after moving upwards twice
-PASS: on ×’×› ×™×’×› ×™×’×› ×™×’×› ×™×’×›, caret is at 18 initially
-FAIL: on ×’×› ×™×’×› ×™×’×› ×™×’×› ×™×’×›, caret is at 15 after moving upwards once but expected at 14
-
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.12/editing/selection/offset-from-point-complex-scripts-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-mac10.12/editing/selection/offset-from-point-complex-scripts-expected.txt
deleted file mode 100644
index 50a789e..0000000
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.12/editing/selection/offset-from-point-complex-scripts-expected.txt
+++ /dev/null
@@ -1 +0,0 @@
-0 5 4 3 2 6
diff --git a/third_party/WebKit/LayoutTests/platform/mac-mac10.12/fast/text/selection/selection-painted-separately-expected.png b/third_party/WebKit/LayoutTests/platform/mac-mac10.12/fast/text/selection/selection-painted-separately-expected.png
deleted file mode 100644
index e64b0af..0000000
--- a/third_party/WebKit/LayoutTests/platform/mac-mac10.12/fast/text/selection/selection-painted-separately-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-retina/editing/selection/modify-up-on-rtl-wrapping-text-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-retina/editing/selection/modify-up-on-rtl-wrapping-text-expected.txt
deleted file mode 100644
index 3caa47b..0000000
--- a/third_party/WebKit/LayoutTests/platform/mac-retina/editing/selection/modify-up-on-rtl-wrapping-text-expected.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-This tests clicking on the left of RTL text puts the caret at the end of the line.
-
-PASS: on ך לכ, caret is at 4 initially
-PASS: on ך לכ, caret is at 2 after moving upwards once
-PASS: on ×› ×›×› ×›×›×›, caret is at 8 initially
-PASS: on ×› ×›×› ×›×›×›, caret is at 5 after moving upwards once
-PASS: on ×› ×›×› ×›×›×›, caret is at 2 after moving upwards twice
-PASS: on ×’×› ×™×’×› ×™×’×› ×™×’×› ×™×’×›, caret is at 18 initially
-PASS: on ×’×› ×™×’×› ×™×’×› ×™×’×› ×™×’×›, caret is at 14 after moving upwards once
-PASS: on ×’×› ×™×’×› ×™×’×› ×™×’×› ×™×’×›, caret is at 10 after moving upwards twice
-PASS: on ×’×› ×™×’×› ×™×’×› ×™×’×› ×™×’×›, caret is at 6 after moving upwards 3 times
-PASS: on ×’×› ×™×’×› ×™×’×› ×™×’×› ×™×’×›, caret is at 3 after moving upwards 4 times
-
diff --git a/third_party/WebKit/LayoutTests/platform/mac-retina/editing/selection/offset-from-point-complex-scripts-expected.txt b/third_party/WebKit/LayoutTests/platform/mac-retina/editing/selection/offset-from-point-complex-scripts-expected.txt
deleted file mode 100644
index e4ad1bd..0000000
--- a/third_party/WebKit/LayoutTests/platform/mac-retina/editing/selection/offset-from-point-complex-scripts-expected.txt
+++ /dev/null
@@ -1 +0,0 @@
-0 4 3 2 6
diff --git a/third_party/WebKit/LayoutTests/platform/mac-retina/fast/text/selection/atsui-partial-selection-expected.png b/third_party/WebKit/LayoutTests/platform/mac-retina/fast/text/selection/atsui-partial-selection-expected.png
deleted file mode 100644
index 6e90dbd..0000000
--- a/third_party/WebKit/LayoutTests/platform/mac-retina/fast/text/selection/atsui-partial-selection-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-retina/fast/text/selection/emphasis-expected.png b/third_party/WebKit/LayoutTests/platform/mac-retina/fast/text/selection/emphasis-expected.png
deleted file mode 100644
index af48c0db..0000000
--- a/third_party/WebKit/LayoutTests/platform/mac-retina/fast/text/selection/emphasis-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-retina/fast/text/selection/justified-selection-at-edge-expected.png b/third_party/WebKit/LayoutTests/platform/mac-retina/fast/text/selection/justified-selection-at-edge-expected.png
deleted file mode 100644
index 0254daf..0000000
--- a/third_party/WebKit/LayoutTests/platform/mac-retina/fast/text/selection/justified-selection-at-edge-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-retina/fast/text/selection/justified-selection-expected.png b/third_party/WebKit/LayoutTests/platform/mac-retina/fast/text/selection/justified-selection-expected.png
deleted file mode 100644
index ead45108..0000000
--- a/third_party/WebKit/LayoutTests/platform/mac-retina/fast/text/selection/justified-selection-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-retina/fast/text/selection/selection-multiple-runs-expected.png b/third_party/WebKit/LayoutTests/platform/mac-retina/fast/text/selection/selection-multiple-runs-expected.png
deleted file mode 100644
index 831359be..0000000
--- a/third_party/WebKit/LayoutTests/platform/mac-retina/fast/text/selection/selection-multiple-runs-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/mac-retina/fast/text/selection/selection-painted-separately-expected.png b/third_party/WebKit/LayoutTests/platform/mac-retina/fast/text/selection/selection-painted-separately-expected.png
deleted file mode 100644
index ab30ea5..0000000
--- a/third_party/WebKit/LayoutTests/platform/mac-retina/fast/text/selection/selection-painted-separately-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/paint/invalidation/selection/selection-within-composited-scroller-expected.txt b/third_party/WebKit/LayoutTests/platform/win/paint/invalidation/selection/selection-within-composited-scroller-expected.txt
similarity index 100%
rename from third_party/WebKit/LayoutTests/paint/invalidation/selection/selection-within-composited-scroller-expected.txt
rename to third_party/WebKit/LayoutTests/platform/win/paint/invalidation/selection/selection-within-composited-scroller-expected.txt
diff --git a/third_party/WebKit/LayoutTests/platform/win7/editing/selection/replaced-boundaries-1-expected.png b/third_party/WebKit/LayoutTests/platform/win7/editing/selection/replaced-boundaries-1-expected.png
deleted file mode 100644
index 1b850154..0000000
--- a/third_party/WebKit/LayoutTests/platform/win7/editing/selection/replaced-boundaries-1-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/paint/selection/atsui-partial-selection-expected.png b/third_party/WebKit/LayoutTests/platform/win7/paint/selection/atsui-partial-selection-expected.png
deleted file mode 100644
index 6e90dbd..0000000
--- a/third_party/WebKit/LayoutTests/platform/win7/paint/selection/atsui-partial-selection-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/paint/selection/emphasis-expected.png b/third_party/WebKit/LayoutTests/platform/win7/paint/selection/emphasis-expected.png
deleted file mode 100644
index af48c0db..0000000
--- a/third_party/WebKit/LayoutTests/platform/win7/paint/selection/emphasis-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/paint/selection/justified-selection-at-edge-expected.png b/third_party/WebKit/LayoutTests/platform/win7/paint/selection/justified-selection-at-edge-expected.png
deleted file mode 100644
index 0254daf..0000000
--- a/third_party/WebKit/LayoutTests/platform/win7/paint/selection/justified-selection-at-edge-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/paint/selection/justified-selection-expected.png b/third_party/WebKit/LayoutTests/platform/win7/paint/selection/justified-selection-expected.png
deleted file mode 100644
index ead45108..0000000
--- a/third_party/WebKit/LayoutTests/platform/win7/paint/selection/justified-selection-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/paint/selection/selection-multiple-runs-expected.png b/third_party/WebKit/LayoutTests/platform/win7/paint/selection/selection-multiple-runs-expected.png
deleted file mode 100644
index 831359be..0000000
--- a/third_party/WebKit/LayoutTests/platform/win7/paint/selection/selection-multiple-runs-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/paint/selection/text-selection-inline-block-expected.png b/third_party/WebKit/LayoutTests/platform/win7/paint/selection/text-selection-inline-block-expected.png
deleted file mode 100644
index 9bb2c7a..0000000
--- a/third_party/WebKit/LayoutTests/platform/win7/paint/selection/text-selection-inline-block-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/paint/selection/text-selection-inline-block-rtl-expected.png b/third_party/WebKit/LayoutTests/platform/win7/paint/selection/text-selection-inline-block-rtl-expected.png
deleted file mode 100644
index 656183c..0000000
--- a/third_party/WebKit/LayoutTests/platform/win7/paint/selection/text-selection-inline-block-rtl-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/WebKit/LayoutTests/shadow-dom/query-selector.html b/third_party/WebKit/LayoutTests/shadow-dom/query-selector.html
index e9baa4a..f67bd66 100644
--- a/third_party/WebKit/LayoutTests/shadow-dom/query-selector.html
+++ b/third_party/WebKit/LayoutTests/shadow-dom/query-selector.html
@@ -2,13 +2,12 @@
 <script src="../resources/testharness.js"></script>
 <script src="../resources/testharnessreport.js"></script>
 <script src="resources/shadow-dom.js"></script>
-<div id="x"><span>test1</span></div>
-<div id="x"><span>test2</span></div>
+<div id="x"><span></span></div>
+<div id="x"><span></span></div>
 <div id="host">
   <template data-mode="open">
     <div id="y"><span></span></div>
     <div id="y"><span></span></div>
-    <div><span id="x" class="y">Can you find this?</span></div>
   </template>
 </div>
 <script>
@@ -22,17 +21,4 @@
   assert_equals(host.shadowRoot.querySelectorAll('#y').length, 2);
   assert_equals(host.shadowRoot.querySelectorAll('#y span').length, 2);
 }, 'querySelectorAll for multiple #Ids in a shadow tree');
-
-test(() => {
-  var spans = document.querySelectorAll('body >>> #x');
-  assert_equals(spans.length, 3);
-  assert_equals(spans[0].textContent, 'test1');
-  assert_equals(spans[1].textContent, 'test2');
-  assert_equals(spans[2].textContent, 'Can you find this?');
-}, 'deep combinator >>> should work for querySelectorAll.');
-
-test(() => {
-  var span = document.querySelector('body >>> .y');
-  assert_equals(span.textContent, 'Can you find this?');
-}, 'deep combinator >>> should work for querySelector');
 </script>
diff --git a/third_party/WebKit/LayoutTests/shadow-dom/shadow-piercing-descendant-combinator-in-static-profile.html b/third_party/WebKit/LayoutTests/shadow-dom/shadow-piercing-descendant-combinator-in-static-profile.html
deleted file mode 100644
index a2b83644..0000000
--- a/third_party/WebKit/LayoutTests/shadow-dom/shadow-piercing-descendant-combinator-in-static-profile.html
+++ /dev/null
@@ -1,26 +0,0 @@
-<!DOCTYPE html>
-<script src="../resources/testharness.js"></script>
-<script src="../resources/testharnessreport.js"></script>
-<script src="resources/shadow-dom.js"></script>
-<style>
-body >>> #x { color: red; }
-</style>
-<div id="host">
-  <template data-mode="open">
-    <div><span id="x">In the shadow tree.</span></div>
-  </template>
-</div>
-<script>
-convertTemplatesToShadowRootsWithin(host);
-test(() => {
-  var span = document.querySelector('body >>> #x');
-  assert_equals(span.textContent, 'In the shadow tree.',
-                '>>> should work in static profile.');
-
-  var stylesheet = document.styleSheets[0];
-  assert_equals(stylesheet.cssRules.length, 0,
-      'A selector containing >>> should be discarded in dynamic profile.');
-  assert_equals(window.getComputedStyle(span).color, 'rgb(0, 0, 0)',
-                '>>> in dynamic profile should not match.');
-}, 'deep descendant combinator >>> should work only in static profile.');
-</script>
diff --git a/third_party/WebKit/LayoutTests/shadow-dom/shadow-piercing-descendant-combinator.html b/third_party/WebKit/LayoutTests/shadow-dom/shadow-piercing-descendant-combinator.html
deleted file mode 100644
index 5f209b38..0000000
--- a/third_party/WebKit/LayoutTests/shadow-dom/shadow-piercing-descendant-combinator.html
+++ /dev/null
@@ -1,107 +0,0 @@
-<!DOCTYPE html>
-<script src="../resources/testharness.js"></script>
-<script src="../resources/testharnessreport.js"></script>
-<script src="resources/shadow-dom.js"></script>
-<body>
-
-  <div id="testroot">
-    <div id="openhost">
-      <template data-mode="open">
-        <div id="inner-open"></div>
-      </template>
-    </div>
-    <div id="closedhost">
-      <template data-mode="closed">
-        <div id="inner-closed"></div>
-      </template>
-    </div>
-    <div id="v0host">
-      <template data-mode="v0">
-        <div id="inner-v0"></div>
-      </template>
-    </div>
-    <div id="nestedhost">
-      <template data-mode="open" data-expose-as="nestedRoot">
-        <div id="inner-div">
-          <div>
-            <template data-mode="open">
-              <div id="inner-nested-open"></div>
-            </template>
-          </div>
-          <div>
-            <template data-mode="closed">
-              <div id="inner-nested-closed"></div>
-            </template>
-          </div>
-          <div>
-            <template data-mode="v0">
-              <div id="inner-nested-v0"></div>
-            </template>
-          </div>
-        </div>
-      </template>
-    </div>
-  </div>
-
-  <div id="testroot2">
-    <template data-mode="open">
-      <div id="div1">
-        <template data-mode="open">
-          <div id="div2">
-            <template data-mode="open">
-              <div id="div3">
-                <template data-mode="open" data-expose-as="deepestRoot">
-                  <div id="div4">
-                  </div>
-                </template>
-              </div>
-            </template>
-          </div>
-        </template>
-      </div>
-    </template>
-  </div>
-
-</body>
-<script>
-'use strict';
-
-convertTemplatesToShadowRootsWithin(testroot);
-test(() => {
-  assert_equals(document.querySelectorAll('body >>> #inner-open').length, 1);
-  assert_equals(document.querySelectorAll('body >>> #inner-closed').length, 0);
-  assert_equals(document.querySelectorAll('body >>> #inner-v0').length, 0);
-  assert_equals(document.querySelectorAll('body >>> #inner-nested-open').length, 1);
-  assert_equals(document.querySelectorAll('body >>> #inner-nested-closed').length, 0);
-  assert_equals(document.querySelectorAll('body >>> #inner-nested-v0').length, 0);
-}, '>>> should match only through open shadow roots.');
-
-test(() => {
-  let innerDiv = nestedRoot.querySelector('#inner-div');
-  assert_equals(innerDiv.querySelectorAll('body >>> #inner-nested-open').length, 0);
-  assert_equals(innerDiv.querySelectorAll('body >>> #inner-nested-closed').length, 0);
-  assert_equals(innerDiv.querySelectorAll('body >>> #inner-nested-v0').length, 0);
-  assert_equals(innerDiv.querySelectorAll('#inner-div >>> #inner-nested-open').length, 1);
-  assert_equals(innerDiv.querySelectorAll('#inner-div >>> #inner-nested-closed').length, 0);
-  assert_equals(innerDiv.querySelectorAll('#inner-div >>> #inner-nested-v0').length, 0);
-}, 'leftmost compound should match an element in the same node tree as context object.');
-
-test(() => {
-  assert_equals(document.querySelector('#testroot >>> #openhost').id, 'openhost');
-  assert_equals(document.querySelector('#testroot >>> #closedhost').id, 'closedhost');
-  assert_equals(document.querySelector('#testroot >>> #v0host').id, 'v0host');
-}, '>>> should match without piercing through shadow roots.');
-
-test(() => {
-  convertTemplatesToShadowRootsWithin(testroot2);
-  let div4 = deepestRoot.querySelector('#div4');
-
-  assert_equals(document.querySelector('body >>> #div1 >>> #div2 >>> #div3 >>> #div4'), div4);
-  assert_equals(document.querySelector('body >>> #div1 >>> #div2 >>> #div4'), div4);
-  assert_equals(document.querySelector('body >>> #div1 >>> #div3 >>> #div4'), div4);
-  assert_equals(document.querySelector('body >>> #div1 >>> #div4'), div4);
-  assert_equals(document.querySelector('body >>> #div2 >>> #div4'), div4);
-  assert_equals(document.querySelector('#div1 >>> #div2 >>> #div3 >>> #div4'), null,
-      'leftmost compound should match an element in the same node tree as context object.');
-}, 'Multiple >>>s in a selector should work.');
-</script>
diff --git a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/nonstable-css-properties-expected.txt b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/nonstable-css-properties-expected.txt
index 3e5c942..86e7a29 100644
--- a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/nonstable-css-properties-expected.txt
+++ b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/nonstable-css-properties-expected.txt
@@ -63,6 +63,22 @@
 el.style.getPropertyValue('text-justify') is 
 getComputedStyle(el).getPropertyValue('text-justify') is 
 
+el.style.setProperty('text-underline-position', 'left')
+el.style.getPropertyValue('text-underline-position') is 
+getComputedStyle(el).getPropertyValue('text-underline-position') is auto
+
+el.style.setProperty('text-underline-position', 'right')
+el.style.getPropertyValue('text-underline-position') is 
+getComputedStyle(el).getPropertyValue('text-underline-position') is auto
+
+el.style.setProperty('text-underline-position', 'under left')
+el.style.getPropertyValue('text-underline-position') is 
+getComputedStyle(el).getPropertyValue('text-underline-position') is auto
+
+el.style.setProperty('text-underline-position', 'right under')
+el.style.getPropertyValue('text-underline-position') is 
+getComputedStyle(el).getPropertyValue('text-underline-position') is auto
+
 PASS successfullyParsed is true
 
 TEST COMPLETE
diff --git a/third_party/WebKit/LayoutTests/virtual/video-surface-layer/external/wpt/picture-in-picture/idlharness.window-expected.txt b/third_party/WebKit/LayoutTests/virtual/video-surface-layer/external/wpt/picture-in-picture/idlharness.window-expected.txt
new file mode 100644
index 0000000..f7f27aa
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/virtual/video-surface-layer/external/wpt/picture-in-picture/idlharness.window-expected.txt
@@ -0,0 +1,47 @@
+This is a testharness.js-based test.
+PASS idlharness
+PASS picture-in-picture interfaces.
+PASS Partial interface HTMLVideoElement: original interface defined
+PASS Partial interface Document: original interface defined
+PASS Partial interface DocumentOrShadowRoot: original interface defined
+FAIL PictureInPictureWindow interface: existence and properties of interface object assert_equals: prototype of self's property "PictureInPictureWindow" is not Function.prototype expected function "function () { [native code] }" but got function "function EventTarget() { [native code] }"
+PASS PictureInPictureWindow interface object length
+PASS PictureInPictureWindow interface object name
+FAIL PictureInPictureWindow interface: existence and properties of interface prototype object assert_equals: prototype of PictureInPictureWindow.prototype is not Object.prototype expected object "[object Object]" but got object "[object EventTarget]"
+PASS PictureInPictureWindow interface: existence and properties of interface prototype object's "constructor" property
+PASS PictureInPictureWindow interface: existence and properties of interface prototype object's @@unscopables property
+PASS PictureInPictureWindow interface: attribute width
+PASS Unscopable handled correctly for width property on PictureInPictureWindow
+PASS PictureInPictureWindow interface: attribute height
+PASS Unscopable handled correctly for height property on PictureInPictureWindow
+PASS PictureInPictureWindow interface: attribute onresize
+PASS Unscopable handled correctly for onresize property on PictureInPictureWindow
+PASS PictureInPictureWindow must be primary interface of pipw
+PASS Stringification of pipw
+PASS PictureInPictureWindow interface: pipw must inherit property "width" with the proper type
+PASS PictureInPictureWindow interface: pipw must inherit property "height" with the proper type
+PASS PictureInPictureWindow interface: pipw must inherit property "onresize" with the proper type
+PASS HTMLVideoElement interface: operation requestPictureInPicture()
+PASS Unscopable handled correctly for requestPictureInPicture() on HTMLVideoElement
+PASS HTMLVideoElement interface: attribute onenterpictureinpicture
+PASS Unscopable handled correctly for onenterpictureinpicture property on HTMLVideoElement
+PASS HTMLVideoElement interface: attribute onleavepictureinpicture
+PASS Unscopable handled correctly for onleavepictureinpicture property on HTMLVideoElement
+PASS HTMLVideoElement interface: attribute disablePictureInPicture
+PASS Unscopable handled correctly for disablePictureInPicture property on HTMLVideoElement
+PASS HTMLVideoElement interface: video must inherit property "requestPictureInPicture()" with the proper type
+PASS HTMLVideoElement interface: video must inherit property "onenterpictureinpicture" with the proper type
+PASS HTMLVideoElement interface: video must inherit property "onleavepictureinpicture" with the proper type
+PASS HTMLVideoElement interface: video must inherit property "disablePictureInPicture" with the proper type
+PASS DocumentOrShadowRoot interface: document must inherit property "pictureInPictureElement" with the proper type
+PASS Document interface: attribute pictureInPictureEnabled
+PASS Unscopable handled correctly for pictureInPictureEnabled property on Document
+PASS Document interface: operation exitPictureInPicture()
+PASS Unscopable handled correctly for exitPictureInPicture() on Document
+PASS Document interface: attribute pictureInPictureElement
+PASS Unscopable handled correctly for pictureInPictureElement property on Document
+PASS Document interface: document must inherit property "pictureInPictureEnabled" with the proper type
+PASS Document interface: document must inherit property "exitPictureInPicture()" with the proper type
+PASS Document interface: document must inherit property "pictureInPictureElement" with the proper type
+Harness: the test ran to completion.
+
diff --git a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
index 541998aad..3e98e1c 100644
--- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
+++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
@@ -1629,6 +1629,7 @@
     method createAttribute
     method createAttributeNS
     method createCDATASection
+    method createCSSStyleSheet
     method createComment
     method createDocumentFragment
     method createElement
diff --git a/third_party/WebKit/LayoutTests/webexposed/nonstable-css-properties-expected.txt b/third_party/WebKit/LayoutTests/webexposed/nonstable-css-properties-expected.txt
index f61be19..3694492b 100644
--- a/third_party/WebKit/LayoutTests/webexposed/nonstable-css-properties-expected.txt
+++ b/third_party/WebKit/LayoutTests/webexposed/nonstable-css-properties-expected.txt
@@ -63,6 +63,22 @@
 el.style.getPropertyValue('text-justify') is distribute
 getComputedStyle(el).getPropertyValue('text-justify') is distribute
 
+el.style.setProperty('text-underline-position', 'left')
+el.style.getPropertyValue('text-underline-position') is left
+getComputedStyle(el).getPropertyValue('text-underline-position') is left
+
+el.style.setProperty('text-underline-position', 'right')
+el.style.getPropertyValue('text-underline-position') is right
+getComputedStyle(el).getPropertyValue('text-underline-position') is right
+
+el.style.setProperty('text-underline-position', 'under left')
+el.style.getPropertyValue('text-underline-position') is under left
+getComputedStyle(el).getPropertyValue('text-underline-position') is under left
+
+el.style.setProperty('text-underline-position', 'right under')
+el.style.getPropertyValue('text-underline-position') is under right
+getComputedStyle(el).getPropertyValue('text-underline-position') is under right
+
 PASS successfullyParsed is true
 
 TEST COMPLETE
diff --git a/third_party/WebKit/LayoutTests/webexposed/nonstable-css-properties.html b/third_party/WebKit/LayoutTests/webexposed/nonstable-css-properties.html
index 90f6d54..27dc3b1 100644
--- a/third_party/WebKit/LayoutTests/webexposed/nonstable-css-properties.html
+++ b/third_party/WebKit/LayoutTests/webexposed/nonstable-css-properties.html
@@ -38,6 +38,11 @@
 ['grid-template-areas', '"test"'],
 
 ['text-justify', 'distribute'],
+
+['text-underline-position', 'left'],
+['text-underline-position', 'right'],
+['text-underline-position', 'under left'],
+['text-underline-position', 'right under'],
 ];
 
 properties.forEach(function(args) {
diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc
index 39c13644..65454b60 100644
--- a/third_party/blink/common/features.cc
+++ b/third_party/blink/common/features.cc
@@ -7,6 +7,12 @@
 namespace blink {
 namespace features {
 
+// Enable eagerly setting up a CacheStorage interface pointer and
+// passing it to service workers on startup as an optimization.
+const base::Feature kEagerCacheStorageSetupForServiceWorkers{
+    "EagerCacheStorageSetupForServiceWorkers",
+    base::FEATURE_ENABLED_BY_DEFAULT};
+
 // Enable LayoutNG.
 const base::Feature kLayoutNG{"LayoutNG", base::FEATURE_DISABLED_BY_DEFAULT};
 
diff --git a/third_party/blink/public/common/features.h b/third_party/blink/public/common/features.h
index 8cf2b2c..33175f7 100644
--- a/third_party/blink/public/common/features.h
+++ b/third_party/blink/public/common/features.h
@@ -11,6 +11,8 @@
 namespace blink {
 namespace features {
 
+BLINK_COMMON_EXPORT extern const base::Feature
+    kEagerCacheStorageSetupForServiceWorkers;
 BLINK_COMMON_EXPORT extern const base::Feature kLayoutNG;
 BLINK_COMMON_EXPORT extern const base::Feature kMojoBlobURLs;
 BLINK_COMMON_EXPORT extern const base::Feature kServiceWorkerServicification;
diff --git a/third_party/blink/public/platform/platform.h b/third_party/blink/public/platform/platform.h
index 27c4bdc..141cafd 100644
--- a/third_party/blink/public/platform/platform.h
+++ b/third_party/blink/public/platform/platform.h
@@ -490,8 +490,10 @@
   enum ContextType {
     kWebGL1ContextType,  // WebGL 1.0 context, use only for WebGL canvases
     kWebGL2ContextType,  // WebGL 2.0 context, use only for WebGL canvases
-    kGLES2ContextType,   // GLES 2.0 context, default, good for using skia
-    kGLES3ContextType,   // GLES 3.0 context
+    kWebGL2ComputeContextType,  // WebGL 2.0 Compute context, use only for WebGL
+                                // canvases
+    kGLES2ContextType,  // GLES 2.0 context, default, good for using skia
+    kGLES3ContextType,  // GLES 3.0 context
   };
   struct ContextAttributes {
     bool fail_if_major_performance_caveat = false;
diff --git a/third_party/blink/public/platform/web_feature.mojom b/third_party/blink/public/platform/web_feature.mojom
index 558bb53..a3564c1c 100644
--- a/third_party/blink/public/platform/web_feature.mojom
+++ b/third_party/blink/public/platform/web_feature.mojom
@@ -1191,7 +1191,6 @@
   kV8Document_RootScroller_AttributeSetter = 1688,
   kCustomElementRegistryDefine = 1689,
   kLinkHeaderServiceWorker = 1690,
-  kCSSShadowPiercingDescendantCombinator = 1691,
   // The above items are available in M56 branch.
 
   kCSSFlexibleBox = 1692,
@@ -1968,6 +1967,7 @@
   kDOMNodeRemovedFromDocumentEventListenedAtNonTarget = 2506,
   kCSSFillAvailableLogicalWidth = 2507,
   kCSSFillAvailableLogicalHeight = 2508,
+  kPopupOpenWhileFileChooserOpened = 2509,
 
   // Add new features immediately above this line. Don't change assigned
   // numbers of any item, and don't reuse removed slots.
diff --git a/third_party/blink/public/platform/web_surface_layer_bridge.h b/third_party/blink/public/platform/web_surface_layer_bridge.h
index 2b3d981..ed484b0 100644
--- a/third_party/blink/public/platform/web_surface_layer_bridge.h
+++ b/third_party/blink/public/platform/web_surface_layer_bridge.h
@@ -5,9 +5,6 @@
 #ifndef THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_SURFACE_LAYER_BRIDGE_H_
 #define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_SURFACE_LAYER_BRIDGE_H_
 
-#include <memory>
-
-#include "cc/layers/surface_layer.h"
 #include "components/viz/common/surfaces/surface_id.h"
 #include "third_party/blink/public/platform/web_common.h"
 #include "third_party/blink/public/platform/web_layer_tree_view.h"
@@ -25,7 +22,7 @@
   virtual void UnregisterContentsLayer(cc::Layer*) = 0;
 
   // Called when a SurfaceLayer is activated.
-  virtual void OnSurfaceIdUpdated(viz::SurfaceId surface_id) {}
+  virtual void OnSurfaceIdUpdated(viz::SurfaceId surface_id){};
 };
 
 // Maintains and exposes the SurfaceLayer.
@@ -33,15 +30,14 @@
  public:
   static std::unique_ptr<WebSurfaceLayerBridge> Create(
       WebLayerTreeView*,
-      WebSurfaceLayerBridgeObserver*,
-      cc::UpdateSubmissionStateCB);
+      WebSurfaceLayerBridgeObserver*);
   virtual ~WebSurfaceLayerBridge();
   virtual cc::Layer* GetCcLayer() const = 0;
   virtual const viz::FrameSinkId& GetFrameSinkId() const = 0;
-  virtual const viz::SurfaceId& GetSurfaceId() const = 0;
   virtual void ClearSurfaceId() = 0;
   virtual void SetContentsOpaque(bool) = 0;
   virtual void CreateSurfaceLayer() = 0;
+  virtual const viz::SurfaceId& GetSurfaceId() const = 0;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/public/platform/web_video_frame_submitter.h b/third_party/blink/public/platform/web_video_frame_submitter.h
index b3eb085..6b69062 100644
--- a/third_party/blink/public/platform/web_video_frame_submitter.h
+++ b/third_party/blink/public/platform/web_video_frame_submitter.h
@@ -6,7 +6,7 @@
 #define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_VIDEO_FRAME_SUBMITTER_H_
 
 #include "cc/layers/video_frame_provider.h"
-#include "components/viz/common/surfaces/surface_id.h"
+#include "components/viz/common/surfaces/frame_sink_id.h"
 #include "media/base/video_rotation.h"
 #include "third_party/blink/public/platform/web_common.h"
 
@@ -46,14 +46,10 @@
   virtual void SetRotation(media::VideoRotation) = 0;
 
   // Prepares the compositor frame sink to accept frames by providing
-  // a SurfaceId. The callback is to be used when on context loss to prevent
+  // a FrameSinkId. The callback is to be used when on context loss to prevent
   // the submitter from continuing to submit frames with invalid resources.
-  virtual void EnableSubmission(viz::SurfaceId,
+  virtual void EnableSubmission(viz::FrameSinkId,
                                 WebFrameSinkDestroyedCallback) = 0;
-
-  // Updates whether we should submit frames or not based on whether the video
-  // is visible on screen.
-  virtual void UpdateSubmissionState(bool) = 0;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/bindings/scripts/v8_dictionary.py b/third_party/blink/renderer/bindings/scripts/v8_dictionary.py
index 4fe9206..88c4d22 100644
--- a/third_party/blink/renderer/bindings/scripts/v8_dictionary.py
+++ b/third_party/blink/renderer/bindings/scripts/v8_dictionary.py
@@ -116,6 +116,14 @@
         raise Exception(
             'Required member %s must not have a default value.' % member.name)
 
+    # In most cases, we don't have to distinguish `null` and `not present`,
+    # and use null-states (e.g. nullptr, foo.IsUndefinedOrNull()) to show such
+    # states for some types for memory usage and performance.
+    # For types whose |has_explicit_presence| is True, we provide explicit
+    # states of presence.
+    has_explicit_presence = (
+        idl_type.is_nullable and idl_type.inner_type.is_interface_type)
+
     def default_values():
         if not member.default_value:
             return None, None
@@ -145,6 +153,7 @@
         'enum_type': idl_type.enum_type,
         'enum_values': idl_type.enum_values,
         'getter_name': getter_name,
+        'has_explicit_presence': has_explicit_presence,
         'has_method_name': has_method_name_for_dictionary_member(member),
         'idl_type': idl_type.base_type,
         'is_interface_type': idl_type.is_interface_type and not is_deprecated_dictionary,
diff --git a/third_party/blink/renderer/bindings/templates/dictionary_v8.cpp.tmpl b/third_party/blink/renderer/bindings/templates/dictionary_v8.cpp.tmpl
index 76f577a..20df71d 100644
--- a/third_party/blink/renderer/bindings/templates/dictionary_v8.cpp.tmpl
+++ b/third_party/blink/renderer/bindings/templates/dictionary_v8.cpp.tmpl
@@ -150,7 +150,7 @@
   } else {
     {{member.name}}Value = {{member.v8_default_value}};
     {{member.name}}HasValueOrDefault = true;
-  {% elif member.is_nullable %}
+  {% elif member.is_nullable and not member.has_explicit_presence %}
   } else {
     {{member.name}}Value = v8::Null(isolate);
     {{member.name}}HasValueOrDefault = true;
diff --git a/third_party/blink/renderer/bindings/tests/results/core/v8_test_dictionary.cc b/third_party/blink/renderer/bindings/tests/results/core/v8_test_dictionary.cc
index e9a31dd..3f977ac 100644
--- a/third_party/blink/renderer/bindings/tests/results/core/v8_test_dictionary.cc
+++ b/third_party/blink/renderer/bindings/tests/results/core/v8_test_dictionary.cc
@@ -1170,9 +1170,6 @@
   if (impl.hasElementOrNullMember()) {
     elementOrNullMemberValue = ToV8(impl.elementOrNullMember(), creationContext, isolate);
     elementOrNullMemberHasValueOrDefault = true;
-  } else {
-    elementOrNullMemberValue = v8::Null(isolate);
-    elementOrNullMemberHasValueOrDefault = true;
   }
   if (elementOrNullMemberHasValueOrDefault &&
       !V8CallBoolean(dictionary->CreateDataProperty(context, keys[15].Get(isolate), elementOrNullMemberValue))) {
@@ -1485,9 +1482,6 @@
   if (impl.hasTestInterfaceOrNullMember()) {
     testInterfaceOrNullMemberValue = ToV8(impl.testInterfaceOrNullMember(), creationContext, isolate);
     testInterfaceOrNullMemberHasValueOrDefault = true;
-  } else {
-    testInterfaceOrNullMemberValue = v8::Null(isolate);
-    testInterfaceOrNullMemberHasValueOrDefault = true;
   }
   if (testInterfaceOrNullMemberHasValueOrDefault &&
       !V8CallBoolean(dictionary->CreateDataProperty(context, keys[45].Get(isolate), testInterfaceOrNullMemberValue))) {
diff --git a/third_party/blink/renderer/core/css/CSSProperties.json5 b/third_party/blink/renderer/core/css/CSSProperties.json5
index 2153f56d..fcd5b73a 100644
--- a/third_party/blink/renderer/core/css/CSSProperties.json5
+++ b/third_party/blink/renderer/core/css/CSSProperties.json5
@@ -3189,17 +3189,19 @@
       typedom_types: ["Keyword"],
       default_value: "none",
     },
-    // FIXME: Implement support for 'under left' and 'under right' values.
     {
       name: "text-underline-position",
       property_methods: ["ParseSingleValue", "CSSValueFromComputedStyleInternal"],
       inherited: true,
       field_group: "*",
-      field_template: "keyword",
-      keywords: ["auto", "under"],
-      default_value: "auto",
-      type_name: "TextUnderlinePosition",
-      typedom_types: ["Keyword"]
+      field_size: 3,
+      field_template: "primitive",
+      default_value: "kTextUnderlinePositionAuto",
+      name_for_methods: "TextUnderlinePosition",
+      type_name: "unsigned",
+      converter: "ConvertTextUnderlinePosition",
+      keywords: ["auto", "under", "left", "right"],
+      typedom_types: ["Keyword"],
     },
     {
       name: "top",
diff --git a/third_party/blink/renderer/core/css/css_primitive_value_mappings.h b/third_party/blink/renderer/core/css/css_primitive_value_mappings.h
index 144da32..cc46ccb 100644
--- a/third_party/blink/renderer/core/css/css_primitive_value_mappings.h
+++ b/third_party/blink/renderer/core/css/css_primitive_value_mappings.h
@@ -1982,6 +1982,43 @@
   return kContainsNone;
 }
 
+template <>
+inline CSSIdentifierValue::CSSIdentifierValue(TextUnderlinePosition position)
+    : CSSValue(kIdentifierClass) {
+  switch (position) {
+    case kTextUnderlinePositionAuto:
+      value_id_ = CSSValueAuto;
+      break;
+    case kTextUnderlinePositionUnder:
+      value_id_ = CSSValueUnder;
+      break;
+    case kTextUnderlinePositionLeft:
+      value_id_ = CSSValueLeft;
+      break;
+    case kTextUnderlinePositionRight:
+      value_id_ = CSSValueRight;
+      break;
+  }
+}
+
+template <>
+inline TextUnderlinePosition CSSIdentifierValue::ConvertTo() const {
+  switch (GetValueID()) {
+    case CSSValueAuto:
+      return kTextUnderlinePositionAuto;
+    case CSSValueUnder:
+      return kTextUnderlinePositionUnder;
+    case CSSValueLeft:
+      return kTextUnderlinePositionLeft;
+    case CSSValueRight:
+      return kTextUnderlinePositionRight;
+    default:
+      break;
+  }
+  NOTREACHED();
+  return kTextUnderlinePositionAuto;
+}
+
 }  // namespace blink
 
 #endif
diff --git a/third_party/blink/renderer/core/css/css_selector.cc b/third_party/blink/renderer/core/css/css_selector.cc
index ddeb2a8a..d56a6d22 100644
--- a/third_party/blink/renderer/core/css/css_selector.cc
+++ b/third_party/blink/renderer/core/css/css_selector.cc
@@ -862,9 +862,6 @@
       case kShadowDeepAsDescendant:
         result = " /deep/ " + builder.ToString() + result;
         break;
-      case kShadowPiercingDescendant:
-        result = " >>> " + builder.ToString() + result;
-        break;
       case kDirectAdjacent:
         result = " + " + builder.ToString() + result;
         break;
@@ -1085,7 +1082,6 @@
   return ForAnyInTagHistory(
       [](const CSSSelector& selector) -> bool {
         return selector.Relation() == CSSSelector::kShadowDeep ||
-               selector.Relation() == CSSSelector::kShadowPiercingDescendant ||
                selector.GetPseudoType() == CSSSelector::kPseudoShadow;
       },
       *this);
diff --git a/third_party/blink/renderer/core/css/css_selector.h b/third_party/blink/renderer/core/css/css_selector.h
index b8c1d2c..61b36db 100644
--- a/third_party/blink/renderer/core/css/css_selector.h
+++ b/third_party/blink/renderer/core/css/css_selector.h
@@ -133,7 +133,6 @@
     kDirectAdjacent,    // + combinator
     kIndirectAdjacent,  // ~ combinator
     // Special cases for shadow DOM related selectors.
-    kShadowPiercingDescendant,  // >>> combinator
     kShadowDeep,                // /deep/ combinator
     kShadowDeepAsDescendant,    // /deep/ as an alias for descendant
     kShadowPseudo,              // ::shadow pseudo element
diff --git a/third_party/blink/renderer/core/css/css_style_sheet.h b/third_party/blink/renderer/core/css/css_style_sheet.h
index f67b37a..2a3fd74 100644
--- a/third_party/blink/renderer/core/css/css_style_sheet.h
+++ b/third_party/blink/renderer/core/css/css_style_sheet.h
@@ -204,6 +204,13 @@
   FRIEND_TEST_ALL_PREFIXES(
       CSSStyleSheetTest,
       CSSStyleSheetConstructionWithNonEmptyCSSStyleSheetInit);
+  FRIEND_TEST_ALL_PREFIXES(
+      CSSStyleSheetTest,
+      CreateCSSStyleSheetWithEmptyCSSStyleSheetInitAndText);
+  FRIEND_TEST_ALL_PREFIXES(
+      CSSStyleSheetTest,
+      CreateCSSStyleSheetWithNonEmptyCSSStyleSheetInitAndText);
+
   bool AlternateFromConstructor() const { return alternate_from_constructor_; }
 
   Member<StyleSheetContents> contents_;
diff --git a/third_party/blink/renderer/core/css/css_style_sheet_test.cc b/third_party/blink/renderer/core/css/css_style_sheet_test.cc
index 5011717..d4b1bf77 100644
--- a/third_party/blink/renderer/core/css/css_style_sheet_test.cc
+++ b/third_party/blink/renderer/core/css/css_style_sheet_test.cc
@@ -2,10 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "third_party/blink/renderer/core/css/css_style_sheet.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/renderer/bindings/core/v8/media_list_or_string.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_function.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_css_style_sheet.h"
 #include "third_party/blink/renderer/core/css/css_rule_list.h"
-#include "third_party/blink/renderer/core/css/css_style_sheet.h"
 #include "third_party/blink/renderer/core/css/css_style_sheet_init.h"
 #include "third_party/blink/renderer/core/css/media_list.h"
 #include "third_party/blink/renderer/core/testing/page_test_base.h"
@@ -18,6 +23,27 @@
     PageTestBase::SetUp();
     RuntimeEnabledFeatures::SetConstructableStylesheetsEnabled(true);
   }
+
+  class FunctionForTest : public ScriptFunction {
+   public:
+    static v8::Local<v8::Function> CreateFunction(ScriptState* script_state,
+                                                  ScriptValue* output) {
+      FunctionForTest* self = new FunctionForTest(script_state, output);
+      return self->BindToV8Function();
+    }
+
+   private:
+    FunctionForTest(ScriptState* script_state, ScriptValue* output)
+        : ScriptFunction(script_state), output_(output) {}
+
+    ScriptValue Call(ScriptValue value) override {
+      DCHECK(!value.IsEmpty());
+      *output_ = value;
+      return value;
+    }
+
+    ScriptValue* output_;
+  };
 };
 
 TEST_F(CSSStyleSheetTest, ConstructorWithoutRuntimeFlagThrowsException) {
@@ -67,4 +93,72 @@
   ASSERT_FALSE(exception_state.HadException());
 }
 
+TEST_F(CSSStyleSheetTest,
+       CreateCSSStyleSheetWithEmptyCSSStyleSheetInitAndText) {
+  V8TestingScope scope;
+  DummyExceptionStateForTesting exception_state;
+  ScriptPromise promise = GetDocument().createCSSStyleSheet(
+      scope.GetScriptState(), "", CSSStyleSheetInit(), exception_state);
+  EXPECT_FALSE(promise.IsEmpty());
+  ASSERT_FALSE(exception_state.HadException());
+  ScriptValue on_fulfilled, on_rejected;
+  promise.Then(
+      FunctionForTest::CreateFunction(scope.GetScriptState(), &on_fulfilled),
+      FunctionForTest::CreateFunction(scope.GetScriptState(), &on_rejected));
+
+  v8::MicrotasksScope::PerformCheckpoint(scope.GetIsolate());
+  CSSStyleSheet* sheet = V8CSSStyleSheet::ToImplWithTypeCheck(
+      scope.GetIsolate(), on_fulfilled.V8Value());
+  EXPECT_TRUE(sheet->href().IsNull());
+  EXPECT_EQ(sheet->parentStyleSheet(), nullptr);
+  EXPECT_EQ(sheet->ownerNode(), nullptr);
+  EXPECT_EQ(sheet->ownerRule(), nullptr);
+  EXPECT_EQ(sheet->media()->length(), 0U);
+  EXPECT_EQ(sheet->title(), StringImpl::empty_);
+  EXPECT_FALSE(sheet->AlternateFromConstructor());
+  EXPECT_FALSE(sheet->disabled());
+  EXPECT_EQ(sheet->cssRules(exception_state)->length(), 0U);
+  ASSERT_FALSE(exception_state.HadException());
+}
+
+TEST_F(CSSStyleSheetTest,
+       CreateCSSStyleSheetWithNonEmptyCSSStyleSheetInitAndText) {
+  String styleText[2] = {".red { color: red; }",
+                         ".red + span + span { color: red; }"};
+  CSSStyleSheetInit init;
+  init.setMedia(MediaListOrString::FromString("screen, print"));
+  init.setTitle("test");
+  init.setAlternate(true);
+  init.setDisabled(true);
+  V8TestingScope scope;
+  DummyExceptionStateForTesting exception_state;
+  ScriptPromise promise = GetDocument().createCSSStyleSheet(
+      scope.GetScriptState(), styleText[0] + styleText[1], init,
+      exception_state);
+  EXPECT_FALSE(promise.IsEmpty());
+  ASSERT_FALSE(exception_state.HadException());
+  ScriptValue on_fulfilled, on_rejected;
+  promise.Then(
+      FunctionForTest::CreateFunction(scope.GetScriptState(), &on_fulfilled),
+      FunctionForTest::CreateFunction(scope.GetScriptState(), &on_rejected));
+
+  v8::MicrotasksScope::PerformCheckpoint(scope.GetIsolate());
+  CSSStyleSheet* sheet = V8CSSStyleSheet::ToImplWithTypeCheck(
+      scope.GetIsolate(), on_fulfilled.V8Value());
+
+  EXPECT_TRUE(sheet->href().IsNull());
+  EXPECT_EQ(sheet->parentStyleSheet(), nullptr);
+  EXPECT_EQ(sheet->ownerNode(), nullptr);
+  EXPECT_EQ(sheet->ownerRule(), nullptr);
+  EXPECT_EQ(sheet->media()->length(), 2U);
+  EXPECT_EQ(sheet->media()->mediaText(), init.media().GetAsString());
+  EXPECT_EQ(sheet->title(), init.title());
+  EXPECT_TRUE(sheet->AlternateFromConstructor());
+  EXPECT_TRUE(sheet->disabled());
+  EXPECT_EQ(sheet->cssRules(exception_state)->length(), 2U);
+  EXPECT_EQ(sheet->cssRules(exception_state)->item(0)->cssText(), styleText[0]);
+  EXPECT_EQ(sheet->cssRules(exception_state)->item(1)->cssText(), styleText[1]);
+  ASSERT_FALSE(exception_state.HadException());
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/css/parser/css_selector_parser.cc b/third_party/blink/renderer/core/css/parser/css_selector_parser.cc
index bd4f0d8..0715324 100644
--- a/third_party/blink/renderer/core/css/parser/css_selector_parser.cc
+++ b/third_party/blink/renderer/core/css/parser/css_selector_parser.cc
@@ -662,25 +662,8 @@
       return CSSSelector::kIndirectAdjacent;
 
     case '>':
-      if (!RuntimeEnabledFeatures::
-              ShadowPiercingDescendantCombinatorEnabled() ||
-          context_->IsLiveProfile() ||
-          range.Peek(1).GetType() != kDelimiterToken ||
-          range.Peek(1).Delimiter() != '>') {
-        range.ConsumeIncludingWhitespace();
-        return CSSSelector::kChild;
-      }
-      range.Consume();
-
-      // Check the 3rd '>'.
-      if (range.Peek(1).GetType() != kDelimiterToken ||
-          range.Peek(1).Delimiter() != '>') {
-        // TODO: Treat '>>' as a CSSSelector::kDescendant here.
-        return CSSSelector::kChild;
-      }
-      range.Consume();
       range.ConsumeIncludingWhitespace();
-      return CSSSelector::kShadowPiercingDescendant;
+      return CSSSelector::kChild;
 
     case '/': {
       // Match /deep/
diff --git a/third_party/blink/renderer/core/css/parser/css_selector_parser_test.cc b/third_party/blink/renderer/core/css/parser/css_selector_parser_test.cc
index 18be39b..c67ee0f9 100644
--- a/third_party/blink/renderer/core/css/parser/css_selector_parser_test.cc
+++ b/third_party/blink/renderer/core/css/parser/css_selector_parser_test.cc
@@ -315,68 +315,6 @@
   }
 }
 
-TEST(CSSSelectorParserTest, InvalidDescendantCombinatorInLiveProfile) {
-  const char* test_cases[] = {"div >>>> span", "div >>> span", "div >> span"};
-
-  CSSParserContext* context = CSSParserContext::Create(
-      kHTMLStandardMode, SecureContextMode::kInsecureContext,
-      CSSParserContext::kLiveProfile);
-  StyleSheetContents* sheet = StyleSheetContents::Create(context);
-
-  for (auto* test_case : test_cases) {
-    SCOPED_TRACE(test_case);
-    CSSTokenizer tokenizer(test_case);
-    const auto tokens = tokenizer.TokenizeToEOF();
-    CSSParserTokenRange range(tokens);
-    CSSSelectorList list =
-        CSSSelectorParser::ParseSelector(range, context, sheet);
-    EXPECT_FALSE(list.IsValid());
-  }
-}
-
-TEST(CSSSelectorParserTest, InvalidDescendantCombinatorInSnapshotProfile) {
-  const char* test_cases[] = {"div >>>> span", "div >> span", "div >> > span",
-                              "div > >> span", "div > > > span"};
-
-  CSSParserContext* context = CSSParserContext::Create(
-      kHTMLStandardMode, SecureContextMode::kInsecureContext,
-      CSSParserContext::kSnapshotProfile);
-  StyleSheetContents* sheet = StyleSheetContents::Create(context);
-
-  for (auto* test_case : test_cases) {
-    SCOPED_TRACE(test_case);
-    CSSTokenizer tokenizer(test_case);
-    const auto tokens = tokenizer.TokenizeToEOF();
-    CSSParserTokenRange range(tokens);
-    CSSSelectorList list =
-        CSSSelectorParser::ParseSelector(range, context, sheet);
-    EXPECT_FALSE(list.IsValid());
-  }
-}
-
-TEST(CSSSelectorParserTest, ShadowPiercingCombinatorInSnapshotProfile) {
-  const char* test_cases[][2] = {{"div >>> span", "div >>> span"},
-                                 {"div >>/**/> span", "div >>> span"},
-                                 {"div >/**/>> span", "div >>> span"},
-                                 {"div >/**/>/**/> span", "div >>> span"}};
-
-  CSSParserContext* context = CSSParserContext::Create(
-      kHTMLStandardMode, SecureContextMode::kInsecureContext,
-      CSSParserContext::kSnapshotProfile);
-  StyleSheetContents* sheet = StyleSheetContents::Create(context);
-
-  for (auto** test_case : test_cases) {
-    SCOPED_TRACE(test_case[0]);
-    CSSTokenizer tokenizer(test_case[0]);
-    const auto tokens = tokenizer.TokenizeToEOF();
-    CSSParserTokenRange range(tokens);
-    CSSSelectorList list =
-        CSSSelectorParser::ParseSelector(range, context, sheet);
-    EXPECT_TRUE(list.IsValid());
-    EXPECT_STREQ(test_case[1], list.SelectorsText().Ascii().data());
-  }
-}
-
 TEST(CSSSelectorParserTest, AttributeSelectorUniversalInvalid) {
   const char* test_cases[] = {"[*]", "[*|*]"};
 
diff --git a/third_party/blink/renderer/core/css/properties/longhands/text_underline_position_custom.cc b/third_party/blink/renderer/core/css/properties/longhands/text_underline_position_custom.cc
index 45c9d23..882eb40 100644
--- a/third_party/blink/renderer/core/css/properties/longhands/text_underline_position_custom.cc
+++ b/third_party/blink/renderer/core/css/properties/longhands/text_underline_position_custom.cc
@@ -4,20 +4,43 @@
 
 #include "third_party/blink/renderer/core/css/properties/longhands/text_underline_position.h"
 
+#include "third_party/blink/renderer/core/css/css_identifier_value.h"
+#include "third_party/blink/renderer/core/css/css_value_list.h"
 #include "third_party/blink/renderer/core/css/parser/css_property_parser_helpers.h"
 #include "third_party/blink/renderer/core/style/computed_style.h"
 
 namespace blink {
 namespace CSSLonghand {
 
+// auto | [ under || [ left | right ] ]
 const CSSValue* TextUnderlinePosition::ParseSingleValue(
     CSSParserTokenRange& range,
     const CSSParserContext& context,
     const CSSParserLocalContext&) const {
-  // auto | [ under || [ left | right ] ], but we only support auto | under
-  // for now
-  return CSSPropertyParserHelpers::ConsumeIdent<CSSValueAuto, CSSValueUnder>(
-      range);
+  if (range.Peek().Id() == CSSValueAuto)
+    return CSSPropertyParserHelpers::ConsumeIdent(range);
+
+  CSSIdentifierValue* under_value =
+      CSSPropertyParserHelpers::ConsumeIdent<CSSValueUnder>(range);
+  CSSIdentifierValue* left_or_right_value = nullptr;
+  if (RuntimeEnabledFeatures::TextUnderlinePositionLeftRightEnabled()) {
+    left_or_right_value =
+        CSSPropertyParserHelpers::ConsumeIdent<CSSValueLeft, CSSValueRight>(
+            range);
+    if (left_or_right_value && !under_value) {
+      under_value =
+          CSSPropertyParserHelpers::ConsumeIdent<CSSValueUnder>(range);
+    }
+  }
+  if (!under_value && !left_or_right_value) {
+    return nullptr;
+  }
+  CSSValueList* list = CSSValueList::CreateSpaceSeparated();
+  if (under_value)
+    list->Append(*under_value);
+  if (left_or_right_value)
+    list->Append(*left_or_right_value);
+  return list;
 }
 
 const CSSValue* TextUnderlinePosition::CSSValueFromComputedStyleInternal(
@@ -26,7 +49,25 @@
     const LayoutObject*,
     Node*,
     bool allow_visited_style) const {
-  return CSSIdentifierValue::Create(style.GetTextUnderlinePosition());
+  auto text_underline_position = style.TextUnderlinePosition();
+  if (text_underline_position == kTextUnderlinePositionAuto)
+    return CSSIdentifierValue::Create(CSSValueAuto);
+  if (text_underline_position == kTextUnderlinePositionUnder)
+    return CSSIdentifierValue::Create(CSSValueUnder);
+  if (text_underline_position == kTextUnderlinePositionLeft)
+    return CSSIdentifierValue::Create(CSSValueLeft);
+  if (text_underline_position == kTextUnderlinePositionRight)
+    return CSSIdentifierValue::Create(CSSValueRight);
+
+  CSSValueList* list = CSSValueList::CreateSpaceSeparated();
+  DCHECK(text_underline_position & kTextUnderlinePositionUnder);
+  list->Append(*CSSIdentifierValue::Create(CSSValueUnder));
+  if (text_underline_position & kTextUnderlinePositionLeft)
+    list->Append(*CSSIdentifierValue::Create(CSSValueLeft));
+  if (text_underline_position & kTextUnderlinePositionRight)
+    list->Append(*CSSIdentifierValue::Create(CSSValueRight));
+  DCHECK_EQ(list->length(), 2U);
+  return list;
 }
 
 }  // namespace CSSLonghand
diff --git a/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc b/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc
index d479f409..6d2e327 100644
--- a/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc
+++ b/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc
@@ -1478,6 +1478,26 @@
   return TextSizeAdjust(primitive_value.GetFloatValue() / 100.0f);
 }
 
+TextUnderlinePosition StyleBuilderConverter::ConvertTextUnderlinePosition(
+    StyleResolverState& state,
+    const CSSValue& value) {
+  TextUnderlinePosition flags = kTextUnderlinePositionAuto;
+
+  auto process = [&flags](const CSSValue& identifier) {
+    flags |=
+        ToCSSIdentifierValue(identifier).ConvertTo<TextUnderlinePosition>();
+  };
+
+  if (value.IsValueList()) {
+    for (auto& entry : ToCSSValueList(value)) {
+      process(*entry);
+    }
+  } else {
+    process(value);
+  }
+  return flags;
+}
+
 TransformOperations StyleBuilderConverter::ConvertTransformOperations(
     StyleResolverState& state,
     const CSSValue& value) {
diff --git a/third_party/blink/renderer/core/css/resolver/style_builder_converter.h b/third_party/blink/renderer/core/css/resolver/style_builder_converter.h
index 05d6e16..90e6340 100644
--- a/third_party/blink/renderer/core/css/resolver/style_builder_converter.h
+++ b/third_party/blink/renderer/core/css/resolver/style_builder_converter.h
@@ -204,6 +204,9 @@
   static float ConvertTextStrokeWidth(StyleResolverState&, const CSSValue&);
   static TextSizeAdjust ConvertTextSizeAdjust(StyleResolverState&,
                                               const CSSValue&);
+  static TextUnderlinePosition ConvertTextUnderlinePosition(
+      StyleResolverState& state,
+      const CSSValue& value);
   static TransformOperations ConvertTransformOperations(StyleResolverState&,
                                                         const CSSValue&);
   static TransformOrigin ConvertTransformOrigin(StyleResolverState&,
diff --git a/third_party/blink/renderer/core/css/selector_checker.cc b/third_party/blink/renderer/core/css/selector_checker.cc
index c011f1b..ea861fe 100644
--- a/third_party/blink/renderer/core/css/selector_checker.cc
+++ b/third_party/blink/renderer/core/css/selector_checker.cc
@@ -306,14 +306,6 @@
   return element.ParentOrShadowHostElement();
 }
 
-static inline Element* ParentOrOpenShadowHostElement(const Element& element) {
-  if (element.parentNode() && element.parentNode()->IsShadowRoot()) {
-    if (ToShadowRoot(element.parentNode())->GetType() != ShadowRootType::kOpen)
-      return nullptr;
-  }
-  return element.ParentOrShadowHostElement();
-}
-
 SelectorChecker::MatchStatus SelectorChecker::MatchForRelation(
     const SelectorCheckingContext& context,
     MatchResult& result) const {
@@ -483,28 +475,6 @@
       return kSelectorFailsCompletely;
     }
 
-    case CSSSelector::kShadowPiercingDescendant: {
-      DCHECK_EQ(mode_, kQueryingRules);
-      UseCounter::Count(context.element->GetDocument(),
-                        WebFeature::kCSSShadowPiercingDescendantCombinator);
-      // TODO(kochi): parentOrOpenShadowHostElement() is necessary because
-      // SelectorQuery can pass V0 shadow roots. All closed shadow roots are
-      // already filtered out, thus once V0 is removed this logic can use
-      // parentOrShadowHostElement() instead.
-      for (next_context.element =
-               ParentOrOpenShadowHostElement(*context.element);
-           next_context.element;
-           next_context.element =
-               ParentOrOpenShadowHostElement(*next_context.element)) {
-        MatchStatus match = MatchSelector(next_context, result);
-        if (match == kSelectorMatches || match == kSelectorFailsCompletely)
-          return match;
-        if (NextSelectorExceedsScope(next_context))
-          break;
-      }
-      return kSelectorFailsCompletely;
-    }
-
     case CSSSelector::kShadowSlot: {
       if (ToHTMLSlotElementIfSupportsAssignmentOrNull(*context.element))
         return kSelectorFailsCompletely;
diff --git a/third_party/blink/renderer/core/css/selector_filter.cc b/third_party/blink/renderer/core/css/selector_filter.cc
index f7e93c7..92450b3c 100644
--- a/third_party/blink/renderer/core/css/selector_filter.cc
+++ b/third_party/blink/renderer/core/css/selector_filter.cc
@@ -182,7 +182,6 @@
       case CSSSelector::kShadowPseudo:
       case CSSSelector::kShadowPart:
       case CSSSelector::kShadowDeep:
-      case CSSSelector::kShadowPiercingDescendant:
         skip_over_subselectors = false;
         CollectDescendantSelectorIdentifierHashes(*current, hash);
         break;
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc
index 8cc15976..ec34465 100644
--- a/third_party/blink/renderer/core/dom/document.cc
+++ b/third_party/blink/renderer/core/dom/document.cc
@@ -1117,6 +1117,26 @@
                                                              flags, is);
 }
 
+ScriptPromise Document::createCSSStyleSheet(ScriptState* script_state,
+                                            const String& text,
+                                            ExceptionState& exception_state) {
+  return Document::createCSSStyleSheet(script_state, text, CSSStyleSheetInit(),
+                                       exception_state);
+}
+
+ScriptPromise Document::createCSSStyleSheet(ScriptState* script_state,
+                                            const String& text,
+                                            const CSSStyleSheetInit& options,
+                                            ExceptionState& exception_state) {
+  // Even though this function returns a Promise, it actually does all the work
+  // at once here because CSS parsing is done synchronously on the main thread.
+  // TODO(rakina): Find a way to improve this.
+  CSSStyleSheet* sheet = CSSStyleSheet::Create(*this, options, exception_state);
+  sheet->SetText(text);
+  return ScriptPromise::Cast(script_state,
+                             ScriptValue::From(script_state, sheet));
+}
+
 ScriptValue Document::registerElement(ScriptState* script_state,
                                       const AtomicString& name,
                                       const ElementRegistrationOptions& options,
diff --git a/third_party/blink/renderer/core/dom/document.h b/third_party/blink/renderer/core/dom/document.h
index 33e69a27..a41486e1 100644
--- a/third_party/blink/renderer/core/dom/document.h
+++ b/third_party/blink/renderer/core/dom/document.h
@@ -36,7 +36,10 @@
 #include "base/memory/scoped_refptr.h"
 #include "third_party/blink/public/platform/web_focus_type.h"
 #include "third_party/blink/public/platform/web_insecure_request_policy.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
 #include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/css/css_style_sheet_init.h"
 #include "third_party/blink/renderer/core/dom/container_node.h"
 #include "third_party/blink/renderer/core/dom/create_element_flags.h"
 #include "third_party/blink/renderer/core/dom/document_encoding_data.h"
@@ -358,6 +361,15 @@
   Element* CreateRawElement(const QualifiedName&,
                             const CreateElementFlags = CreateElementFlags());
 
+  ScriptPromise createCSSStyleSheet(ScriptState*,
+                                    const String&,
+                                    ExceptionState&);
+
+  ScriptPromise createCSSStyleSheet(ScriptState*,
+                                    const String&,
+                                    const CSSStyleSheetInit&,
+                                    ExceptionState&);
+
   Element* ElementFromPoint(double x, double y) const;
   HeapVector<Member<Element>> ElementsFromPoint(double x, double y) const;
   Range* caretRangeFromPoint(int x, int y);
diff --git a/third_party/blink/renderer/core/dom/document.idl b/third_party/blink/renderer/core/dom/document.idl
index 8159885..ccda5e64 100644
--- a/third_party/blink/renderer/core/dom/document.idl
+++ b/third_party/blink/renderer/core/dom/document.idl
@@ -75,6 +75,8 @@
 
     [NewObject] Range createRange();
 
+    [CallWith=ScriptState, NewObject, RaisesException, RuntimeEnabled=ConstructableStylesheets] Promise<CSSStyleSheet> createCSSStyleSheet(DOMString text, optional CSSStyleSheetInit options);
+
     // NodeFilter.SHOW_ALL = 0xFFFFFFFF
     [NewObject] NodeIterator createNodeIterator(Node root, optional unsigned long whatToShow = 0xFFFFFFFF, optional NodeFilter? filter = null);
     [NewObject] TreeWalker createTreeWalker(Node root, optional unsigned long whatToShow = 0xFFFFFFFF, optional NodeFilter? filter = null);
diff --git a/third_party/blink/renderer/core/dom/node_rare_data.cc b/third_party/blink/renderer/core/dom/node_rare_data.cc
index 36577db..db3b785 100644
--- a/third_party/blink/renderer/core/dom/node_rare_data.cc
+++ b/third_party/blink/renderer/core/dom/node_rare_data.cc
@@ -47,6 +47,10 @@
   unsigned bitfields_;
 };
 
+NodeMutationObserverData* NodeMutationObserverData::Create() {
+  return new NodeMutationObserverData;
+}
+
 static_assert(sizeof(NodeRareData) == sizeof(SameSizeAsNodeRareData),
               "NodeRareData should stay small");
 
diff --git a/third_party/blink/renderer/core/dom/node_rare_data.h b/third_party/blink/renderer/core/dom/node_rare_data.h
index dd4fd11..6e546271 100644
--- a/third_party/blink/renderer/core/dom/node_rare_data.h
+++ b/third_party/blink/renderer/core/dom/node_rare_data.h
@@ -39,9 +39,7 @@
 class NodeMutationObserverData final
     : public GarbageCollected<NodeMutationObserverData> {
  public:
-  static NodeMutationObserverData* Create() {
-    return new NodeMutationObserverData;
-  }
+  static NodeMutationObserverData* Create();
 
   const HeapVector<TraceWrapperMember<MutationObserverRegistration>>&
   Registry() {
diff --git a/third_party/blink/renderer/core/editing/commands/typing_command.cc b/third_party/blink/renderer/core/editing/commands/typing_command.cc
index a1c0ba2..302caa96 100644
--- a/third_party/blink/renderer/core/editing/commands/typing_command.cc
+++ b/third_party/blink/renderer/core/editing/commands/typing_command.cc
@@ -208,14 +208,19 @@
                                            EditingState* editing_state) {
   if (!selection.IsRange())
     return;
-  ApplyCommandToComposite(DeleteSelectionCommand::Create(
-                              selection, DeleteSelectionOptions::Builder()
-                                             .SetSmartDelete(smart_delete_)
-                                             .SetMergeBlocksAfterDelete(true)
-                                             .SetExpandForSpecialElements(true)
-                                             .SetSanitizeMarkup(true)
-                                             .Build()),
-                          editing_state);
+  // Although the 'selection' to delete is indeed a Range, it may have been
+  // built from a Caret selection; in that case we don't want to expand so that
+  // the table structure is deleted as well.
+  bool expand_for_special = EndingSelection().IsRange();
+  ApplyCommandToComposite(
+      DeleteSelectionCommand::Create(
+          selection, DeleteSelectionOptions::Builder()
+                         .SetSmartDelete(smart_delete_)
+                         .SetMergeBlocksAfterDelete(true)
+                         .SetExpandForSpecialElements(expand_for_special)
+                         .SetSanitizeMarkup(true)
+                         .Build()),
+      editing_state);
 }
 
 void TypingCommand::DeleteKeyPressed(Document& document,
diff --git a/third_party/blink/renderer/core/editing/visible_units.cc b/third_party/blink/renderer/core/editing/visible_units.cc
index 90fcca9..efc60394 100644
--- a/third_party/blink/renderer/core/editing/visible_units.cc
+++ b/third_party/blink/renderer/core/editing/visible_units.cc
@@ -811,6 +811,22 @@
   return MostBackwardCaretPosition<EditingInFlatTreeStrategy>(position, rule);
 }
 
+namespace {
+bool HasInvisibleFirstLetter(const Node* node) {
+  if (!node || !node->IsTextNode())
+    return false;
+  const LayoutTextFragment* remaining_text =
+      ToLayoutTextFragmentOrNull(node->GetLayoutObject());
+  if (!remaining_text || !remaining_text->IsRemainingTextLayoutObject())
+    return false;
+  const LayoutTextFragment* first_letter =
+      ToLayoutTextFragmentOrNull(AssociatedLayoutObjectOf(*node, 0));
+  if (!first_letter || first_letter == remaining_text)
+    return false;
+  return first_letter->StyleRef().Visibility() != EVisibility::kVisible;
+}
+}  // namespace
+
 template <typename Strategy>
 PositionTemplate<Strategy> MostForwardCaretPosition(
     const PositionTemplate<Strategy>& position,
@@ -903,7 +919,8 @@
       continue;
     const unsigned text_start_offset = text_layout_object->TextStartOffset();
     if (current_node != start_node) {
-      DCHECK(current_pos.AtStartOfNode());
+      DCHECK(current_pos.AtStartOfNode() ||
+             HasInvisibleFirstLetter(current_node));
       return PositionTemplate<Strategy>(
           current_node, layout_object->CaretMinOffset() + text_start_offset);
     }
diff --git a/third_party/blink/renderer/core/editing/visible_units_test.cc b/third_party/blink/renderer/core/editing/visible_units_test.cc
index 7c40e3d..cd11696 100644
--- a/third_party/blink/renderer/core/editing/visible_units_test.cc
+++ b/third_party/blink/renderer/core/editing/visible_units_test.cc
@@ -761,5 +761,13 @@
   EXPECT_EQ(Position(text, 2), start);
 }
 
+TEST_F(VisibleUnitsTest, MostForwardCaretPositionWithInvisibleFirstLetter) {
+  InsertStyleElement("div::first-letter{visibility:hidden}");
+  // Use special syntax to set input position DIV@0
+  const Position position = SetCaretTextToBody("<div><!--|-->foo</div>");
+  const Node* foo = GetDocument().QuerySelector("div")->firstChild();
+  EXPECT_EQ(Position(foo, 1), MostForwardCaretPosition(position));
+}
+
 }  // namespace visible_units_test
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/frame/find_in_page.cc b/third_party/blink/renderer/core/frame/find_in_page.cc
index f189e147..c1a4a34c 100644
--- a/third_party/blink/renderer/core/frame/find_in_page.cc
+++ b/third_party/blink/renderer/core/frame/find_in_page.cc
@@ -41,6 +41,22 @@
 
 namespace blink {
 
+FindInPage::FindInPage(WebLocalFrameImpl& frame,
+                       InterfaceRegistry* interface_registry)
+    : ContextLifecycleObserver(
+          frame.GetFrame() ? frame.GetFrame()->GetDocument() : nullptr),
+      frame_(&frame),
+      binding_(this) {
+  // TODO(rakina): Use InterfaceRegistry of |frame| directly rather than passing
+  // both of them.
+  if (!interface_registry)
+    return;
+  // TODO(crbug.com/800641): Use InterfaceValidator when it works for associated
+  // interfaces.
+  interface_registry->AddAssociatedInterface(
+      WTF::BindRepeating(&FindInPage::BindToRequest, WrapWeakPersistent(this)));
+}
+
 void WebLocalFrameImpl::RequestFind(int identifier,
                                     const WebString& search_text,
                                     const WebFindOptions& options) {
@@ -287,4 +303,8 @@
   binding_.Close();
 }
 
+void FindInPage::ContextDestroyed(ExecutionContext* context) {
+  binding_.Close();
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/frame/find_in_page.h b/third_party/blink/renderer/core/frame/find_in_page.h
index e897d38..cd5c66b 100644
--- a/third_party/blink/renderer/core/frame/find_in_page.h
+++ b/third_party/blink/renderer/core/frame/find_in_page.h
@@ -12,6 +12,7 @@
 #include "third_party/blink/public/web/web_local_frame.h"
 #include "third_party/blink/public/web/web_plugin_container.h"
 #include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/dom/context_lifecycle_observer.h"
 #include "third_party/blink/renderer/core/editing/finder/text_finder.h"
 #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
 
@@ -24,6 +25,7 @@
 
 class CORE_EXPORT FindInPage final
     : public GarbageCollectedFinalized<FindInPage>,
+      public ContextLifecycleObserver,
       public mojom::blink::FindInPage {
   USING_PRE_FINALIZER(FindInPage, Dispose);
 
@@ -88,19 +90,16 @@
 
   void Dispose();
 
-  void Trace(blink::Visitor* visitor) {
+  void ContextDestroyed(ExecutionContext*) override;
+
+  void Trace(blink::Visitor* visitor) override {
     visitor->Trace(text_finder_);
     visitor->Trace(frame_);
+    ContextLifecycleObserver::Trace(visitor);
   }
 
  private:
-  FindInPage(WebLocalFrameImpl& frame, InterfaceRegistry* interface_registry)
-      : frame_(&frame), binding_(this) {
-    if (!interface_registry)
-      return;
-    interface_registry->AddAssociatedInterface(WTF::BindRepeating(
-        &FindInPage::BindToRequest, WrapWeakPersistent(this)));
-  }
+  FindInPage(WebLocalFrameImpl& frame, InterfaceRegistry* interface_registry);
 
   // Will be initialized after first call to ensureTextFinder().
   Member<TextFinder> text_finder_;
diff --git a/third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator.cc b/third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator.cc
index 75ec00f9b..f0dc7b1 100644
--- a/third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator.cc
+++ b/third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator.cc
@@ -226,8 +226,7 @@
   // covnert to the requested color space and pixel format.
   if (function_type_ != kHTMLCanvasConvertToBlobPromise) {
     if (skia_image->colorSpace()) {
-      image_ = image_->ConvertToColorSpace(SkColorSpace::MakeSRGB(),
-                                           SkTransferFunctionBehavior::kIgnore);
+      image_ = image_->ConvertToColorSpace(SkColorSpace::MakeSRGB());
       skia_image = image_->PaintImageForCurrentFrame().GetSkImage();
     }
 
@@ -248,8 +247,7 @@
         skia_image = SkImage::MakeFromRaster(src_data_, nullptr, nullptr);
       }
       DCHECK(skia_image->colorSpace());
-      skia_image = skia_image->makeColorSpace(
-          blob_color_space, SkTransferFunctionBehavior::kIgnore);
+      skia_image = skia_image->makeColorSpace(blob_color_space);
       image_ = StaticBitmapImage::Create(skia_image);
     }
 
@@ -330,12 +328,7 @@
   std::unique_ptr<ImageDataBuffer> buffer = ImageDataBuffer::Create(src_data_);
   if (!buffer)
     return false;
-  SkTransferFunctionBehavior transfer_fn_behavior =
-      SkTransferFunctionBehavior::kIgnore;
-  if (function_type_ == kHTMLCanvasConvertToBlobPromise)
-    transfer_fn_behavior = SkTransferFunctionBehavior::kIgnore;
-  return buffer->EncodeImage("image/webp", quality, &encoded_image_,
-                             transfer_fn_behavior);
+  return buffer->EncodeImage("image/webp", quality, &encoded_image_);
 }
 
 void CanvasAsyncBlobCreator::ScheduleAsyncBlobCreation(const double& quality) {
@@ -545,7 +538,6 @@
     SkJpegEncoder::Options options;
     options.fQuality = ImageEncoder::ComputeJpegQuality(quality);
     options.fAlphaOption = SkJpegEncoder::AlphaOption::kBlendOnBlack;
-    options.fBlendBehavior = SkTransferFunctionBehavior::kIgnore;
     if (options.fQuality == 100) {
       options.fDownsample = SkJpegEncoder::Downsample::k444;
     }
@@ -560,7 +552,6 @@
     SkPngEncoder::Options options;
     options.fFilterFlags = SkPngEncoder::FilterFlag::kSub;
     options.fZLibLevel = 3;
-    options.fUnpremulBehavior = SkTransferFunctionBehavior::kIgnore;
     encoder_ = ImageEncoder::Create(&encoded_image_, src_data_, options);
   }
 
@@ -655,8 +646,7 @@
   if (!buffer)
     return false;
   return buffer->EncodeImage(encode_options_.type(), encode_options_.quality(),
-                             &encoded_image_,
-                             SkTransferFunctionBehavior::kIgnore);
+                             &encoded_image_);
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator_test.cc b/third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator_test.cc
index 252f607..e3b52699 100644
--- a/third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator_test.cc
+++ b/third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator_test.cc
@@ -301,8 +301,7 @@
 
           sk_sp<SkImage> ref_image = source_image->makeColorSpace(
               CanvasAsyncBlobCreator::BlobColorSpaceToSkColorSpace(
-                  blob_color_space),
-              SkTransferFunctionBehavior::kIgnore);
+                  blob_color_space));
 
           // Jpeg does not support transparent images.
           bool compare_alpha = (blob_mime_type != "image/jpeg");
diff --git a/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc b/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc
index d22074bd..2478cce 100644
--- a/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc
+++ b/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc
@@ -29,9 +29,7 @@
 
 #include <math.h>
 
-#include <limits>
 #include <memory>
-#include <utility>
 
 #include "base/location.h"
 #include "base/numerics/checked_math.h"
@@ -1429,8 +1427,8 @@
   if (frame) {
     layer_tree_view =
         frame->GetPage()->GetChromeClient().GetWebLayerTreeView(frame);
-    surface_layer_bridge_ = std::make_unique<::blink::SurfaceLayerBridge>(
-        layer_tree_view, this, base::DoNothing());
+    surface_layer_bridge_ =
+        std::make_unique<::blink::SurfaceLayerBridge>(layer_tree_view, this);
     // Creates a placeholder layer first before Surface is created.
     surface_layer_bridge_->CreateSolidColorLayer();
   }
diff --git a/third_party/blink/renderer/core/html/canvas/image_data.cc b/third_party/blink/renderer/core/html/canvas/image_data.cc
index 26e534c..5adf5042 100644
--- a/third_party/blink/renderer/core/html/canvas/image_data.cc
+++ b/third_party/blink/renderer/core/html/canvas/image_data.cc
@@ -367,8 +367,7 @@
     if (!f16_array)
       return nullptr;
     if (!pixmap.readPixels(image_info, f16_array->Data(),
-                           image_info.minRowBytes(), 0, 0,
-                           SkTransferFunctionBehavior::kIgnore)) {
+                           image_info.minRowBytes())) {
       NOTREACHED();
       return nullptr;
     }
diff --git a/third_party/blink/renderer/core/html/forms/file_chooser.cc b/third_party/blink/renderer/core/html/forms/file_chooser.cc
index ebc3146a..bfab0af 100644
--- a/third_party/blink/renderer/core/html/forms/file_chooser.cc
+++ b/third_party/blink/renderer/core/html/forms/file_chooser.cc
@@ -41,6 +41,11 @@
   return chooser_.get();
 }
 
+void FileChooserClient::DisconnectFileChooser() {
+  DCHECK(HasConnectedFileChooser());
+  chooser_->DisconnectClient();
+}
+
 inline FileChooser::FileChooser(FileChooserClient* client,
                                 const WebFileChooserParams& params)
     : client_(client), params_(params) {}
diff --git a/third_party/blink/renderer/core/html/forms/file_chooser.h b/third_party/blink/renderer/core/html/forms/file_chooser.h
index b0d4ce85..879fcd9 100644
--- a/third_party/blink/renderer/core/html/forms/file_chooser.h
+++ b/third_party/blink/renderer/core/html/forms/file_chooser.h
@@ -67,6 +67,10 @@
 
  protected:
   FileChooser* NewFileChooser(const WebFileChooserParams&);
+  bool HasConnectedFileChooser() const { return chooser_.get(); }
+
+  // This should be called if a user chose files or cancel the dialog.
+  void DisconnectFileChooser();
 
  private:
   scoped_refptr<FileChooser> chooser_;
diff --git a/third_party/blink/renderer/core/html/forms/file_input_type.cc b/third_party/blink/renderer/core/html/forms/file_input_type.cc
index 5ce73e4..eb2f443 100644
--- a/third_party/blink/renderer/core/html/forms/file_input_type.cc
+++ b/third_party/blink/renderer/core/html/forms/file_input_type.cc
@@ -171,6 +171,7 @@
                       : WebFeature::kInputTypeFileInsecureOriginOpenChooser);
 
     chrome_client->OpenFileChooser(document.GetFrame(), NewFileChooser(params));
+    chrome_client->RegisterPopupOpeningObserver(this);
   }
   event->SetDefaultHandled();
 }
@@ -348,6 +349,11 @@
 void FileInputType::FilesChosen(const Vector<FileChooserFileInfo>& files) {
   SetFiles(CreateFileList(files,
                           GetElement().FastHasAttribute(webkitdirectoryAttr)));
+  if (HasConnectedFileChooser()) {
+    DisconnectFileChooser();
+    if (auto* chrome_client = GetChromeClient())
+      chrome_client->UnregisterPopupOpeningObserver(this);
+  }
 }
 
 void FileInputType::SetFilesFromDirectory(const String& path) {
@@ -454,4 +460,12 @@
   KeyboardClickableInputTypeView::HandleKeyupEvent(event);
 }
 
+void FileInputType::WillOpenPopup() {
+  // TODO(tkent): Should we disconnect the file chooser? crbug.com/637639
+  if (HasConnectedFileChooser()) {
+    UseCounter::Count(GetElement().GetDocument(),
+                      WebFeature::kPopupOpenWhileFileChooserOpened);
+  }
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/html/forms/file_input_type.h b/third_party/blink/renderer/core/html/forms/file_input_type.h
index 25aa3743..4227f174 100644
--- a/third_party/blink/renderer/core/html/forms/file_input_type.h
+++ b/third_party/blink/renderer/core/html/forms/file_input_type.h
@@ -37,6 +37,7 @@
 #include "third_party/blink/renderer/core/html/forms/file_chooser.h"
 #include "third_party/blink/renderer/core/html/forms/input_type.h"
 #include "third_party/blink/renderer/core/html/forms/keyboard_clickable_input_type_view.h"
+#include "third_party/blink/renderer/core/page/popup_opening_observer.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 
 namespace blink {
@@ -46,7 +47,8 @@
 
 class CORE_EXPORT FileInputType final : public InputType,
                                         public KeyboardClickableInputTypeView,
-                                        private FileChooserClient {
+                                        private FileChooserClient,
+                                        private PopupOpeningObserver {
   USING_GARBAGE_COLLECTED_MIXIN(FileInputType);
 
  public:
@@ -98,6 +100,9 @@
   // FileChooserClient implementation.
   void FilesChosen(const Vector<FileChooserFileInfo>&) override;
 
+  // PopupOpeningObserver implementation.
+  void WillOpenPopup() override;
+
   void SetFilesFromDirectory(const String&);
 
   Member<FileList> file_list_;
diff --git a/third_party/blink/renderer/core/html/html_iframe_element.cc b/third_party/blink/renderer/core/html/html_iframe_element.cc
index 9e1652d..fae0cdf 100644
--- a/third_party/blink/renderer/core/html/html_iframe_element.cc
+++ b/third_party/blink/renderer/core/html/html_iframe_element.cc
@@ -239,44 +239,21 @@
   // If allowfullscreen attribute is present and no fullscreen policy is set,
   // enable the feature for all origins.
   if (AllowFullscreen()) {
-    bool has_fullscreen_policy = false;
-    for (const auto& declaration : container_policy) {
-      if (declaration.feature == mojom::FeaturePolicyFeature::kFullscreen) {
-        has_fullscreen_policy = true;
-        if (messages) {
-          messages->push_back(
-              "allow attribute is overriding 'allowfullscreen'.");
-        }
-        break;
-      }
-    }
-    if (!has_fullscreen_policy) {
-      ParsedFeaturePolicyDeclaration whitelist;
-      whitelist.feature = mojom::FeaturePolicyFeature::kFullscreen;
-      whitelist.matches_all_origins = true;
-      container_policy.push_back(whitelist);
+    bool policy_changed = AllowFeatureEverywhereIfNotPresent(
+        mojom::FeaturePolicyFeature::kFullscreen, container_policy);
+    if (!policy_changed && messages) {
+      messages->push_back(
+          "Allow attribute will take precedence over 'allowfullscreen'.");
     }
   }
   // If the allowpaymentrequest attribute is present and no 'payment' policy is
   // set, enable the feature for all origins.
   if (AllowPaymentRequest()) {
-    bool has_payment_policy = false;
-    for (const auto& declaration : container_policy) {
-      if (declaration.feature == mojom::FeaturePolicyFeature::kPayment) {
-        has_payment_policy = true;
-        if (messages) {
-          messages->push_back(
-              "allow attribute is overriding 'allowpaymentrequest'.");
-        }
-        break;
-      }
-    }
-    if (!has_payment_policy) {
-      ParsedFeaturePolicyDeclaration whitelist;
-      whitelist.feature = mojom::FeaturePolicyFeature::kPayment;
-      whitelist.matches_all_origins = true;
-      whitelist.origins = std::vector<url::Origin>(0UL);
-      container_policy.push_back(whitelist);
+    bool policy_changed = AllowFeatureEverywhereIfNotPresent(
+        mojom::FeaturePolicyFeature::kPayment, container_policy);
+    if (!policy_changed && messages) {
+      messages->push_back(
+          "Allow attribute will take precedence over 'allowpaymentrequest'.");
     }
   }
 
diff --git a/third_party/blink/renderer/core/imagebitmap/image_bitmap.cc b/third_party/blink/renderer/core/imagebitmap/image_bitmap.cc
index 2e0c5c4..0aa57d0a 100644
--- a/third_party/blink/renderer/core/imagebitmap/image_bitmap.cc
+++ b/third_party/blink/renderer/core/imagebitmap/image_bitmap.cc
@@ -447,20 +447,8 @@
 scoped_refptr<StaticBitmapImage> ApplyColorSpaceConversion(
     scoped_refptr<StaticBitmapImage>&& image,
     ImageBitmap::ParsedOptions& options) {
-  SkTransferFunctionBehavior transfer_function_behavior =
-      SkTransferFunctionBehavior::kIgnore;
-  // We normally expect to respect transfer function. However, in two scenarios
-  // we have to ignore the transfer function. First, when the source image is
-  // unpremul. Second, when the source image is drawn using a
-  // SkColorSpaceXformCanvas.
-  sk_sp<SkImage> skia_image = image->PaintImageForCurrentFrame().GetSkImage();
-  if (!skia_image->colorSpace() ||
-      skia_image->alphaType() == kUnpremul_SkAlphaType)
-    transfer_function_behavior = SkTransferFunctionBehavior::kIgnore;
-
   return image->ConvertToColorSpace(
-      options.color_params.GetSkColorSpaceForSkSurfaces(),
-      transfer_function_behavior);
+      options.color_params.GetSkColorSpaceForSkSurfaces());
 }
 
 scoped_refptr<StaticBitmapImage> MakeBlankImage(
diff --git a/third_party/blink/renderer/core/inspector/inspector_audits_agent.cc b/third_party/blink/renderer/core/inspector/inspector_audits_agent.cc
index cd3095a..b413b58 100644
--- a/third_party/blink/renderer/core/inspector/inspector_audits_agent.cc
+++ b/third_party/blink/renderer/core/inspector/inspector_audits_agent.cc
@@ -55,8 +55,7 @@
 
   String mime_type = "image/";
   mime_type.append(encoding);
-  return image_to_encode->EncodeImage(mime_type, quality, output,
-                                      SkTransferFunctionBehavior::kIgnore);
+  return image_to_encode->EncodeImage(mime_type, quality, output);
 }
 
 }  // namespace
diff --git a/third_party/blink/renderer/core/layout/layout_text.cc b/third_party/blink/renderer/core/layout/layout_text.cc
index bb8a4d45..6389fbd 100644
--- a/third_party/blink/renderer/core/layout/layout_text.cc
+++ b/third_party/blink/renderer/core/layout/layout_text.cc
@@ -683,9 +683,7 @@
         if (LineDirectionPointFitsInBox(point_line_direction.ToInt(), box,
                                         should_affinity_be_downstream)) {
           return CreatePositionWithAffinityForBoxAfterAdjustingOffsetForBiDi(
-              box,
-              box->OffsetForPosition(point_line_direction, IncludePartialGlyphs,
-                                     BreakGlyphs),
+              box, box->OffsetForPosition(point_line_direction),
               should_affinity_be_downstream);
         }
       }
@@ -699,9 +697,7 @@
                                 should_affinity_be_downstream);
     return CreatePositionWithAffinityForBoxAfterAdjustingOffsetForBiDi(
         last_box,
-        last_box->OffsetForPosition(point_line_direction, IncludePartialGlyphs,
-                                    BreakGlyphs) +
-            last_box->Start(),
+        last_box->OffsetForPosition(point_line_direction) + last_box->Start(),
         should_affinity_be_downstream);
   }
   return CreatePositionWithAffinity(0);
diff --git a/third_party/blink/renderer/core/layout/line/breaking_context_inline_headers.h b/third_party/blink/renderer/core/layout/line/breaking_context_inline_headers.h
index 9a3994b..c71a4e2 100644
--- a/third_party/blink/renderer/core/layout/line/breaking_context_inline_headers.h
+++ b/third_party/blink/renderer/core/layout/line/breaking_context_inline_headers.h
@@ -824,7 +824,7 @@
   int start = word_measurement.start_offset;
   int end = CanMidWordBreakBefore(text)
                 ? start
-                : break_iterator.NextBreakOpportunity(start + 1);
+                : break_iterator.NextBreakOpportunity(start);
   if (end >= word_measurement.end_offset)
     return false;
 
@@ -866,8 +866,7 @@
   x_pos_to_break += LayoutUnit::Epsilon();
   if (run.Rtl())
     x_pos_to_break = word_measurement.width - x_pos_to_break;
-  len = font.OffsetForPosition(run, x_pos_to_break, OnlyFullGlyphs,
-                               DontBreakGlyphs);
+  len = font.OffsetForPosition(run, x_pos_to_break, false);
   int end = start + len;
   if (len) {
     end = break_iterator.PreviousBreakOpportunity(end, start);
@@ -909,9 +908,8 @@
   TextRun run = ConstructTextRun(font, text, start, len, style);
   run.SetTabSize(!collapse_white_space_, style.GetTabSize());
   run.SetXPos(width_.CurrentWidth());
-  // TODO(fserb): Check if this need to be BreakGlyphs.
-  unsigned max_prefix_length = font.OffsetForPosition(
-      run, max_prefix_width, OnlyFullGlyphs, DontBreakGlyphs);
+  unsigned max_prefix_length =
+      font.OffsetForPosition(run, max_prefix_width, false);
   if (max_prefix_length < Hyphenation::kMinimumPrefixLength)
     return false;
 
@@ -1063,11 +1061,13 @@
                              break_all, next_breakable_position_for_break_all);
     }
 
-    // Determine if we are in the whitespace between words.
+    // Determine if we are in the whitespace between words or in a leading
+    // whitespace.
     int next_breakable_position = current_.NextBreakablePosition();
     bool between_words =
         c == kNewlineCharacter ||
-        (curr_ws_ != EWhiteSpace::kPre && !at_start_ &&
+        (curr_ws_ != EWhiteSpace::kPre &&
+         (!at_start_ || current_character_is_space_) &&
          layout_text_info_.line_break_iterator_.IsBreakable(
              current_.Offset(), next_breakable_position, line_break_type) &&
          (!disable_soft_hyphen ||
@@ -1211,7 +1211,8 @@
     }
 
     // Auto-wrapping text should not wrap in the middle of a word once it has
-    // had an opportunity to break after a word.
+    // had an opportunity to break after a word or before, at a leading
+    // white-space.
     if (auto_wrap_ && between_words) {
       width_.Commit();
       width_from_last_breaking_opportunity = 0;
diff --git a/third_party/blink/renderer/core/layout/line/inline_text_box.cc b/third_party/blink/renderer/core/layout/line/inline_text_box.cc
index 80dca35b5..17d3cca7 100644
--- a/third_party/blink/renderer/core/layout/line/inline_text_box.cc
+++ b/third_party/blink/renderer/core/layout/line/inline_text_box.cc
@@ -424,10 +424,7 @@
     // more accurate position in rtl text.
     // TODO(crbug.com/722043: This doesn't always give the best results.
     bool ltr = IsLeftToRightDirection();
-    int offset = OffsetForPosition(ellipsis_x,
-                                   ltr ? OnlyFullGlyphs : IncludePartialGlyphs,
-                                   DontBreakGlyphs);
-
+    int offset = OffsetForPosition(ellipsis_x, !ltr);
     // Full truncation is only necessary when we're flowing left-to-right.
     if (flow_is_ltr && offset == 0 && ltr == flow_is_ltr) {
       // No characters should be laid out.  Set ourselves to full truncation and
@@ -628,8 +625,7 @@
 }
 
 int InlineTextBox::OffsetForPosition(LayoutUnit line_offset,
-                                     IncludePartialGlyphsOption partial_glyphs,
-                                     BreakGlyphsOption break_glyphs) const {
+                                     bool include_partial_glyphs) const {
   if (IsLineBreak())
     return 0;
 
@@ -643,7 +639,7 @@
   const Font& font = style.GetFont();
   return font.OffsetForPosition(ConstructTextRun(style),
                                 (line_offset - LogicalLeft()).ToFloat(),
-                                partial_glyphs, break_glyphs);
+                                include_partial_glyphs);
 }
 
 LayoutUnit InlineTextBox::PositionForOffset(int offset) const {
diff --git a/third_party/blink/renderer/core/layout/line/inline_text_box.h b/third_party/blink/renderer/core/layout/line/inline_text_box.h
index fb34617..cace2c5 100644
--- a/third_party/blink/renderer/core/layout/line/inline_text_box.h
+++ b/third_party/blink/renderer/core/layout/line/inline_text_box.h
@@ -206,8 +206,7 @@
 
  public:
   virtual int OffsetForPosition(LayoutUnit x,
-                                IncludePartialGlyphsOption,
-                                BreakGlyphsOption) const;
+                                bool include_partial_glyphs = true) const;
   virtual LayoutUnit PositionForOffset(int offset) const;
 
   // Returns false for offset after line break.
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.cc
index 5b21a32..1fcf1133 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm.cc
@@ -188,6 +188,12 @@
   NGInlineBoxState* box =
       box_states_->OnBeginPlaceItems(&line_style, baseline_type_, quirks_mode_);
 
+  // In order to match other browsers when list-style-type: none, pretend
+  // there's an invisible marker here.
+  if (line_style.Display() == EDisplay::kListItem &&
+      line_style.ListStyleType() == EListStyleType::kNone)
+    box->ComputeTextMetrics(line_style, baseline_type_);
+
   for (NGInlineItemResult& item_result : *line_items) {
     DCHECK(item_result.item);
     const NGInlineItem& item = *item_result.item;
@@ -671,11 +677,12 @@
                                                  line_block_size, block_delta);
 
     NGLineInfo line_info;
-    NGLineBreaker line_breaker(
-        Node(), NGLineBreakerMode::kContent, constraint_space_,
-        &positioned_floats, &unpositioned_floats_, &container_builder_,
-        exclusion_space.get(), handled_item_index, break_token);
-    line_breaker.NextLine(line_opportunity, &line_info);
+    NGLineBreaker line_breaker(Node(), NGLineBreakerMode::kContent,
+                               constraint_space_, &positioned_floats,
+                               &unpositioned_floats_, &container_builder_,
+                               exclusion_space.get(), handled_item_index,
+                               line_opportunity, break_token);
+    line_breaker.NextLine(&line_info);
 
     // If this fragment will be larger than the inline-size of the opportunity,
     // *and* the opportunity is smaller than the available inline-size, and the
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.cc
index f016403..10757f3 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.cc
@@ -678,11 +678,11 @@
     unpositioned_floats.clear();
 
     NGLineInfo line_info;
-    NGLineBreaker line_breaker(node, mode, *space, &positioned_floats,
-                               &unpositioned_floats,
-                               nullptr /* container_builder */,
-                               &empty_exclusion_space, 0u, break_token.get());
-    line_breaker.NextLine(line_opportunity, &line_info);
+    NGLineBreaker line_breaker(
+        node, mode, *space, &positioned_floats, &unpositioned_floats,
+        nullptr /* container_builder */, &empty_exclusion_space, 0u,
+        line_opportunity, break_token.get());
+    line_breaker.NextLine(&line_info);
 
     if (line_info.Results().IsEmpty())
       break;
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.cc
index 2593375..9b25d3e3 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.cc
@@ -40,16 +40,6 @@
 
 }  // namespace
 
-NGLineBreaker::LineData::LineData(NGInlineNode node,
-                                  const NGInlineBreakToken* break_token) {
-  is_first_formatted_line = (!break_token || (!break_token->ItemIndex() &&
-                                              !break_token->TextOffset())) &&
-                            node.CanContainFirstFormattedLine();
-  use_first_line_style =
-      is_first_formatted_line &&
-      node.GetLayoutBox()->GetDocument().GetStyleEngine().UsesFirstLineRules();
-}
-
 NGLineBreaker::NGLineBreaker(
     NGInlineNode node,
     NGLineBreakerMode mode,
@@ -59,10 +49,19 @@
     NGContainerFragmentBuilder* container_builder,
     NGExclusionSpace* exclusion_space,
     unsigned handled_float_index,
+    const NGLineLayoutOpportunity& line_opportunity,
     const NGInlineBreakToken* break_token)
-    : line_(node, break_token),
-      node_(node),
-      items_data_(node.ItemsData(line_.use_first_line_style)),
+    : node_(node),
+      is_first_formatted_line_((!break_token || (!break_token->ItemIndex() &&
+                                                 !break_token->TextOffset())) &&
+                               node.CanContainFirstFormattedLine()),
+      use_first_line_style_(is_first_formatted_line_ &&
+                            node.GetLayoutBox()
+                                ->GetDocument()
+                                .GetStyleEngine()
+                                .UsesFirstLineRules()),
+      in_line_height_quirks_mode_(node.InLineHeightQuirksMode()),
+      items_data_(node.ItemsData(use_first_line_style_)),
       mode_(mode),
       constraint_space_(space),
       positioned_floats_(positioned_floats),
@@ -73,8 +72,8 @@
       shaper_(items_data_.text_content),
       spacing_(items_data_.text_content),
       handled_floats_end_item_index_(handled_float_index),
-      base_direction_(node_.BaseDirection()),
-      in_line_height_quirks_mode_(node.InLineHeightQuirksMode()) {
+      line_opportunity_(line_opportunity),
+      base_direction_(node_.BaseDirection()) {
   break_iterator_.SetBreakSpace(BreakSpaceType::kBeforeSpaceRun);
 
   if (break_token) {
@@ -115,11 +114,11 @@
       IsHorizontalWritingMode(constraint_space_.GetWritingMode());
   if (line_info->LineEndFragment()) {
     const NGPhysicalSize& size = line_info->LineEndFragment()->Size();
-    line_.position -= is_horizontal ? size.width : size.height;
+    position_ -= is_horizontal ? size.width : size.height;
   }
   if (fragment) {
     const NGPhysicalSize& size = fragment->Size();
-    line_.position += is_horizontal ? size.width : size.height;
+    position_ += is_horizontal ? size.width : size.height;
   }
   line_info->SetLineEndFragment(std::move(fragment));
 }
@@ -161,40 +160,32 @@
 }
 
 // Initialize internal states for the next line.
-void NGLineBreaker::PrepareNextLine(
-    const NGLineLayoutOpportunity& line_opportunity,
-    NGLineInfo* line_info) {
+void NGLineBreaker::PrepareNextLine(NGLineInfo* line_info) {
   // NGLineInfo is not supposed to be re-used becase it's not much gain and to
   // avoid rare code path.
   DCHECK(line_info->Results().IsEmpty());
 
   line_info->SetStartOffset(offset_);
-  line_info->SetLineStyle(
-      node_, items_data_, constraint_space_, line_.is_first_formatted_line,
-      line_.use_first_line_style, previous_line_had_forced_break_);
+  line_info->SetLineStyle(node_, items_data_, constraint_space_,
+                          is_first_formatted_line_, use_first_line_style_,
+                          previous_line_had_forced_break_);
   // Set the initial style of this line from the break token. Example:
   //   <p>...<span>....</span></p>
   // When the line wraps in <span>, the 2nd line needs to start with the style
   // of the <span>.
-  override_break_anywhere_ = false;
   SetCurrentStyle(current_style_ ? *current_style_ : line_info->LineStyle());
   ComputeBaseDirection(*line_info);
   line_info->SetBaseDirection(base_direction_);
 
-  line_.is_after_forced_break = false;
-
   // Use 'text-indent' as the initial position. This lets tab positions to align
   // regardless of 'text-indent'.
-  line_.position = line_info->TextIndent();
-
-  line_.line_opportunity = line_opportunity;
+  position_ = line_info->TextIndent();
 }
 
-void NGLineBreaker::NextLine(const NGLineLayoutOpportunity& line_opportunity,
-                             NGLineInfo* line_info) {
-  PrepareNextLine(line_opportunity, line_info);
+void NGLineBreaker::NextLine(NGLineInfo* line_info) {
+  PrepareNextLine(line_info);
   BreakLine(line_info);
-  if (!line_.trailing_spaces_collapsed)
+  if (!trailing_spaces_collapsed_)
     RemoveTrailingCollapsibleSpace(line_info);
 
 #if DCHECK_IS_ON()
@@ -226,7 +217,8 @@
     // Check overflow even if |item_index_| is at the end of the block, because
     // the last item of the block may have caused overflow. In that case,
     // |HandleOverflow| will rewind |item_index_|.
-    if (state == LineBreakState::kContinue && auto_wrap_ && !line_.CanFit()) {
+    if (state == LineBreakState::kContinue && auto_wrap_ &&
+        position_ > AvailableWidthToFit()) {
       state = HandleOverflow(line_info);
     }
 
@@ -305,19 +297,19 @@
 // The current position is usually updated as NGLineBreaker builds
 // NGInlineItemResults. This function re-computes it when it was lost.
 void NGLineBreaker::UpdatePosition(const NGLineInfo& line_info) {
-  line_.position = line_info.ComputeWidth();
+  position_ = line_info.ComputeWidth();
 }
 
 void NGLineBreaker::ComputeLineLocation(NGLineInfo* line_info) const {
-  LayoutUnit bfc_line_offset = line_.line_opportunity.line_left_offset;
-  LayoutUnit available_width = line_.AvailableWidth();
-  DCHECK_EQ(line_.position, line_info->ComputeWidth());
+  LayoutUnit bfc_line_offset = line_opportunity_.line_left_offset;
+  LayoutUnit available_width = AvailableWidth();
+  DCHECK_EQ(position_, line_info->ComputeWidth());
 
   // Negative margins can make the position negative, but the inline size is
   // always positive or 0.
   line_info->SetLineBfcOffset(
-      {bfc_line_offset, line_.line_opportunity.bfc_block_offset},
-      available_width, line_.position.ClampNegativeToZero());
+      {bfc_line_offset, line_opportunity_.bfc_block_offset}, available_width,
+      position_.ClampNegativeToZero());
 }
 
 NGLineBreaker::LineBreakState NGLineBreaker::HandleText(
@@ -353,11 +345,11 @@
 
   NGInlineItemResult* item_result = AddItem(item, item_results);
   item_result->should_create_line_box = true;
-  LayoutUnit available_width = line_.AvailableWidthToFit();
+  LayoutUnit available_width = AvailableWidthToFit();
 
   if (auto_wrap_) {
     // Try to break inside of this text item.
-    BreakText(item_result, item, available_width - line_.position, line_info);
+    BreakText(item_result, item, available_width - position_, line_info);
 
     if (item.IsSymbolMarker()) {
       LayoutUnit symbol_width = LayoutListMarker::WidthOfSymbol(*item.Style());
@@ -365,10 +357,10 @@
         item_result->inline_size = symbol_width;
     }
 
-    LayoutUnit next_position = line_.position + item_result->inline_size;
+    LayoutUnit next_position = position_ + item_result->inline_size;
     bool is_overflow = next_position > available_width;
     DCHECK(is_overflow || item_result->shape_result);
-    line_.position = next_position;
+    position_ = next_position;
     item_result->may_break_inside = !is_overflow;
     MoveToNextOf(*item_result);
 
@@ -402,7 +394,7 @@
   DCHECK_EQ(item_result->end_offset, item.EndOffset());
   DCHECK(!item_result->may_break_inside);
   item_result->can_break_after = false;
-  line_.position += item_result->inline_size;
+  position_ += item_result->inline_size;
   MoveToNextOf(item);
   return state;
 }
@@ -541,7 +533,7 @@
     // Skipping one whitespace removes all collapsible spaces because
     // collapsible spaces are collapsed to single space in NGInlineItemBuilder.
     offset_++;
-    line_.trailing_spaces_collapsed = true;
+    trailing_spaces_collapsed_ = true;
 
     // Make the last item breakable after, even if it was nowrap.
     DCHECK(!item_results->IsEmpty());
@@ -550,7 +542,7 @@
     // Find the end of the run of space characters in this item.
     // Other white space characters (e.g., tab) are not included in this item.
     DCHECK(style.BreakOnlyAfterWhiteSpace());
-    line_.trailing_spaces_collapsed = true;
+    trailing_spaces_collapsed_ = true;
     unsigned end = offset_;
     while (end < item.EndOffset() && text[end] == kSpaceCharacter)
       end++;
@@ -561,7 +553,7 @@
     item_result->has_only_trailing_spaces = true;
     item_result->shape_result = item.TextShapeResult();
     TruncateTextEnd(item_result);
-    line_.position += item_result->inline_size;
+    position_ += item_result->inline_size;
     item_result->can_break_after =
         end < text.length() && !IsBreakableSpace(text[end]);
     offset_ = end;
@@ -579,8 +571,8 @@
 // Remove trailing collapsible spaces in |line_info|.
 // https://drafts.csswg.org/css-text-3/#white-space-phase-2
 void NGLineBreaker::RemoveTrailingCollapsibleSpace(NGLineInfo* line_info) {
-  DCHECK(!line_.trailing_spaces_collapsed);
-  line_.trailing_spaces_collapsed = true;
+  DCHECK(!trailing_spaces_collapsed_);
+  trailing_spaces_collapsed_ = true;
 
   NGInlineItemResults* item_results = &line_info->Results();
   if (item_results->IsEmpty())
@@ -602,14 +594,14 @@
       return;
 
     // We have a trailing collapsible space. Remove it.
-    line_.position -= item_result.inline_size;
+    position_ -= item_result.inline_size;
     --item_result.end_offset;
     if (item_result.end_offset == item_result.start_offset) {
       unsigned index = std::distance(item_results->begin(), &item_result);
       item_results->EraseAt(index);
     } else {
       TruncateTextEnd(&item_result);
-      line_.position += item_result.inline_size;
+      position_ += item_result.inline_size;
     }
     return;
   }
@@ -644,7 +636,7 @@
       NGInlineItemResult* item_result = AddItem(item, &line_info->Results());
       item_result->should_create_line_box = true;
       item_result->has_only_trailing_spaces = true;
-      line_.is_after_forced_break = true;
+      is_after_forced_break_ = true;
       line_info->SetIsLastLine(true);
       state = LineBreakState::kDone;
       break;
@@ -655,9 +647,8 @@
       DCHECK(item.Style());
       const ComputedStyle& style = *item.Style();
       const Font& font = style.GetFont();
-      item_result->inline_size =
-          font.TabWidth(style.GetTabSize(), line_.position);
-      line_.position += item_result->inline_size;
+      item_result->inline_size = font.TabWidth(style.GetTabSize(), position_);
+      position_ += item_result->inline_size;
       item_result->has_only_trailing_spaces =
           state == LineBreakState::kTrailing;
       ComputeCanBreakAfter(item_result);
@@ -764,7 +755,7 @@
       ComputePadding(constraint_space_, style), is_flipped_lines);
   item_result->inline_size += item_result->margins.InlineSum();
 
-  line_.position += item_result->inline_size;
+  position_ += item_result->inline_size;
   ComputeCanBreakAfter(item_result);
   MoveToNextOf(item);
 }
@@ -804,7 +795,7 @@
   // into the current line or to the next line. Remove trailing spaces if this
   // float is trailing, because whitespace should be collapsed across floats,
   // and this logic requires the width after trailing spaces are collapsed.
-  if (IsTrailing(item, *line_info) && !line_.trailing_spaces_collapsed)
+  if (IsTrailing(item, *line_info) && !trailing_spaces_collapsed_)
     RemoveTrailingCollapsibleSpace(line_info);
 
   NGBlockNode node(ToLayoutBox(item.GetLayoutObject()));
@@ -829,7 +820,11 @@
        margins.InlineSum())
           .ClampNegativeToZero();
 
-  LayoutUnit bfc_block_offset = line_.line_opportunity.bfc_block_offset;
+  LayoutUnit bfc_block_offset = line_opportunity_.bfc_block_offset;
+
+  bool can_fit_float =
+      position_ + inline_margin_size <=
+      line_opportunity_.AvailableFloatInlineSize().AddEpsilon();
 
   // The float should be positioned after the current line if:
   //  - It can't fit within the non-shape area. (Assuming the current position
@@ -840,7 +835,7 @@
   //    unpositioned_floats to manually adjust the min/max-content size after
   //    the line breaker has run).
   bool float_after_line =
-      !line_.CanFloatFit(inline_margin_size) ||
+      !can_fit_float ||
       exclusion_space_->LastFloatBlockStart() > bfc_block_offset ||
       exclusion_space_->ClearanceOffset(float_style.Clear()) >
           bfc_block_offset ||
@@ -866,11 +861,10 @@
 
     DCHECK_EQ(bfc_block_offset, opportunity.rect.BlockStartOffset());
 
-    line_.line_opportunity = opportunity.ComputeLineLayoutOpportunity(
-        constraint_space_, line_.line_opportunity.line_block_size,
-        LayoutUnit());
+    line_opportunity_ = opportunity.ComputeLineLayoutOpportunity(
+        constraint_space_, line_opportunity_.line_block_size, LayoutUnit());
 
-    DCHECK_GE(line_.AvailableWidth(), LayoutUnit());
+    DCHECK_GE(AvailableWidth(), LayoutUnit());
   }
 }
 
@@ -911,7 +905,7 @@
   DCHECK(!item_result->can_break_after);
 
   if (ComputeOpenTagResult(item, constraint_space_, item_result)) {
-    line_.position += item_result->inline_size;
+    position_ += item_result->inline_size;
 
     // While the spec defines "non-zero margins, padding, or borders" prevents
     // line boxes to be zero-height, tests indicate that only inline direction
@@ -943,7 +937,7 @@
     NGBoxStrut paddings = ComputePadding(constraint_space_, style);
     item_result->inline_size = item_result->margins.inline_end +
                                borders.inline_end + paddings.inline_end;
-    line_.position += item_result->inline_size;
+    position_ += item_result->inline_size;
 
     if (!item_result->should_create_line_box &&
         (item_result->inline_size ||
@@ -990,14 +984,14 @@
 // are no break opportunities in item_results.back().
 NGLineBreaker::LineBreakState NGLineBreaker::HandleOverflow(
     NGLineInfo* line_info) {
-  return HandleOverflow(line_info, line_.AvailableWidthToFit());
+  return HandleOverflow(line_info, AvailableWidthToFit());
 }
 
 NGLineBreaker::LineBreakState NGLineBreaker::HandleOverflow(
     NGLineInfo* line_info,
     LayoutUnit available_width) {
   NGInlineItemResults* item_results = &line_info->Results();
-  LayoutUnit width_to_rewind = line_.position - available_width;
+  LayoutUnit width_to_rewind = position_ - available_width;
   DCHECK_GT(width_to_rewind, 0);
   bool position_maybe_changed = false;
 
@@ -1011,7 +1005,7 @@
     // Try to break after this item.
     if (i < item_results->size() - 1 && item_result->can_break_after) {
       if (width_to_rewind <= 0) {
-        line_.position = available_width + width_to_rewind;
+        position_ = available_width + width_to_rewind;
         Rewind(line_info, i + 1);
         return LineBreakState::kTrailing;
       }
@@ -1040,11 +1034,11 @@
         DCHECK_LE(i + 1, item_results->size());
         if (i + 1 == item_results->size()) {
           // If this is the last item, adjust states to accomodate the change.
-          line_.position =
+          position_ =
               available_width + next_width_to_rewind + item_result->inline_size;
           if (line_info->LineEndFragment())
             SetLineEndFragment(nullptr, line_info);
-          DCHECK_EQ(line_.position, line_info->ComputeWidth());
+          DCHECK_EQ(position_, line_info->ComputeWidth());
           item_index_ = item_result->item_index;
           offset_ = item_result->end_offset;
           items_data_.AssertOffset(item_index_, offset_);
@@ -1211,7 +1205,7 @@
     return NGInlineBreakToken::Create(node_);
   return NGInlineBreakToken::Create(
       node_, current_style_.get(), item_index_, offset_,
-      ((line_.is_after_forced_break ? NGInlineBreakToken::kIsForcedBreak : 0) |
+      ((is_after_forced_break_ ? NGInlineBreakToken::kIsForcedBreak : 0) |
        (line_info.UseFirstLineStyle() ? NGInlineBreakToken::kUseFirstLineStyle
                                       : 0)),
       std::move(state_stack));
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.h b/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.h
index d223f4d..f3575c1 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.h
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.h
@@ -43,12 +43,13 @@
                 NGContainerFragmentBuilder* container_builder,
                 NGExclusionSpace*,
                 unsigned handled_float_index,
+                const NGLineLayoutOpportunity&,
                 const NGInlineBreakToken* = nullptr);
   ~NGLineBreaker();
 
   // Compute the next line break point and produces NGInlineItemResults for
   // the line.
-  void NextLine(const NGLineLayoutOpportunity& line_opportunity, NGLineInfo*);
+  void NextLine(NGLineInfo*);
 
   // Create an NGInlineBreakToken for the last line returned by NextLine().
   scoped_refptr<NGInlineBreakToken> CreateBreakToken(
@@ -62,47 +63,6 @@
                                    NGInlineItemResult*);
 
  private:
-  // This struct holds information for the current line.
-  struct LineData {
-    STACK_ALLOCATED();
-
-    LineData(NGInlineNode node, const NGInlineBreakToken* break_token);
-
-    // The current position from inline_start. Unlike NGInlineLayoutAlgorithm
-    // that computes position in visual order, this position in logical order.
-    LayoutUnit position;
-
-    NGLineLayoutOpportunity line_opportunity;
-
-    // True if this line is the "first formatted line".
-    // https://www.w3.org/TR/CSS22/selector.html#first-formatted-line
-    bool is_first_formatted_line;
-
-    bool use_first_line_style;
-
-    // Set when the line ended with a forced break. Used to setup the states for
-    // the next line.
-    bool is_after_forced_break = false;
-
-    // True if trailing collapsible spaces have been collapsed.
-    bool trailing_spaces_collapsed = false;
-
-    LayoutUnit AvailableWidth() const {
-      return line_opportunity.AvailableInlineSize();
-    }
-    LayoutUnit AvailableWidthToFit() const {
-      return AvailableWidth().AddEpsilon();
-    }
-    bool CanFit() const { return position <= AvailableWidthToFit(); }
-    bool CanFit(LayoutUnit extra) const {
-      return position + extra <= AvailableWidthToFit();
-    }
-    bool CanFloatFit(LayoutUnit extra) const {
-      return position + extra <=
-             line_opportunity.AvailableFloatInlineSize().AddEpsilon();
-    }
-  };
-
   const String& Text() const { return items_data_.text_content; }
   const Vector<NGInlineItem>& Items() const { return items_data_.items; }
 
@@ -115,7 +75,7 @@
 
   void BreakLine(NGLineInfo*);
 
-  void PrepareNextLine(const NGLineLayoutOpportunity&, NGLineInfo*);
+  void PrepareNextLine(NGLineInfo*);
 
   void UpdatePosition(const NGLineInfo&);
   void ComputeLineLocation(NGLineInfo*) const;
@@ -175,33 +135,20 @@
   void ComputeBaseDirection(const NGLineInfo&);
   bool IsTrailing(const NGInlineItem&, const NGLineInfo&) const;
 
-  LineData line_;
+  LayoutUnit AvailableWidth() const {
+    return line_opportunity_.AvailableInlineSize();
+  }
+  LayoutUnit AvailableWidthToFit() const {
+    return AvailableWidth().AddEpsilon();
+  }
+
   NGInlineNode node_;
-  const NGInlineItemsData& items_data_;
 
-  NGLineBreakerMode mode_;
-  const NGConstraintSpace& constraint_space_;
-  Vector<NGPositionedFloat>* positioned_floats_;
-  Vector<scoped_refptr<NGUnpositionedFloat>>* unpositioned_floats_;
-  NGContainerFragmentBuilder* container_builder_; /* May be nullptr */
-  NGExclusionSpace* exclusion_space_;
-  scoped_refptr<const ComputedStyle> current_style_;
+  // True if this line is the "first formatted line".
+  // https://www.w3.org/TR/CSS22/selector.html#first-formatted-line
+  bool is_first_formatted_line_ = false;
 
-  unsigned item_index_ = 0;
-  unsigned offset_ = 0;
-  LazyLineBreakIterator break_iterator_;
-  HarfBuzzShaper shaper_;
-  ShapeResultSpacing<String> spacing_;
-  bool previous_line_had_forced_break_ = false;
-  const Hyphenation* hyphenation_ = nullptr;
-
-  // Keep track of handled float items. See HandleFloat().
-  unsigned handled_floats_end_item_index_;
-
-  // The current base direction for the bidi algorithm.
-  // This is copied from NGInlineNode, then updated after each forced line break
-  // if 'unicode-bidi: plaintext'.
-  TextDirection base_direction_;
+  bool use_first_line_style_ = false;
 
   // True when current box allows line wrapping.
   bool auto_wrap_ = false;
@@ -224,7 +171,46 @@
   // True when the line we are breaking has a list marker.
   bool has_list_marker_ = false;
 
+  // True if trailing collapsible spaces have been collapsed.
+  bool trailing_spaces_collapsed_ = false;
+
+  // Set when the line ended with a forced break. Used to setup the states for
+  // the next line.
+  bool is_after_forced_break_ = false;
+
   bool ignore_floats_ = false;
+
+  const NGInlineItemsData& items_data_;
+
+  NGLineBreakerMode mode_;
+  const NGConstraintSpace& constraint_space_;
+  Vector<NGPositionedFloat>* positioned_floats_;
+  Vector<scoped_refptr<NGUnpositionedFloat>>* unpositioned_floats_;
+  NGContainerFragmentBuilder* container_builder_; /* May be nullptr */
+  NGExclusionSpace* exclusion_space_;
+  scoped_refptr<const ComputedStyle> current_style_;
+
+  unsigned item_index_ = 0;
+  unsigned offset_ = 0;
+  LazyLineBreakIterator break_iterator_;
+  HarfBuzzShaper shaper_;
+  ShapeResultSpacing<String> spacing_;
+  bool previous_line_had_forced_break_ = false;
+  const Hyphenation* hyphenation_ = nullptr;
+
+  // The current position from inline_start. Unlike NGInlineLayoutAlgorithm
+  // that computes position in visual order, this position in logical order.
+  LayoutUnit position_;
+
+  // Keep track of handled float items. See HandleFloat().
+  unsigned handled_floats_end_item_index_;
+
+  NGLineLayoutOpportunity line_opportunity_;
+
+  // The current base direction for the bidi algorithm.
+  // This is copied from NGInlineNode, then updated after each forced line break
+  // if 'unicode-bidi: plaintext'.
+  TextDirection base_direction_;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker_test.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker_test.cc
index c1cd68e..1a6baf2 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker_test.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker_test.cc
@@ -53,8 +53,9 @@
       NGLineBreaker line_breaker(node, NGLineBreakerMode::kContent, *space,
                                  &positioned_floats, &unpositioned_floats,
                                  /* container_builder */ nullptr,
-                                 &exclusion_space, 0u, break_token.get());
-      line_breaker.NextLine(line_opportunity, &line_info);
+                                 &exclusion_space, 0u, line_opportunity,
+                                 break_token.get());
+      line_breaker.NextLine(&line_info);
 
       if (line_info.Results().IsEmpty())
         break;
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_physical_text_fragment.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_physical_text_fragment.cc
index 7c70596..3ded252 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_physical_text_fragment.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_physical_text_fragment.cc
@@ -192,9 +192,9 @@
   DCHECK(TextShapeResult());
   const LayoutUnit& point_in_line_direction =
       Style().IsHorizontalWritingMode() ? point.left : point.top;
+  const bool include_partial_glyphs = true;
   return TextShapeResult()->OffsetForPosition(point_in_line_direction.ToFloat(),
-                                              IncludePartialGlyphs,
-                                              BreakGlyphs) +
+                                              include_partial_glyphs) +
          StartOffset();
 }
 
diff --git a/third_party/blink/renderer/core/layout/svg/line/svg_inline_text_box.cc b/third_party/blink/renderer/core/layout/svg/line/svg_inline_text_box.cc
index 6965c06..dfaacf6 100644
--- a/third_party/blink/renderer/core/layout/svg/line/svg_inline_text_box.cc
+++ b/third_party/blink/renderer/core/layout/svg/line/svg_inline_text_box.cc
@@ -57,9 +57,7 @@
     next_box->DirtyLineBoxes();
 }
 
-int SVGInlineTextBox::OffsetForPosition(LayoutUnit,
-                                        IncludePartialGlyphsOption,
-                                        BreakGlyphsOption) const {
+int SVGInlineTextBox::OffsetForPosition(LayoutUnit, bool) const {
   // SVG doesn't use the standard offset <-> position selection system, as it's
   // not suitable for SVGs complex needs. Vertical text selection, inline boxes
   // spanning multiple lines (contrary to HTML, etc.)
@@ -82,10 +80,11 @@
   if (fragment.AffectedByTextLength())
     position /= fragment.length_adjust_scale;
 
+  const bool include_partial_glyphs = true;
   TextRun text_run = ConstructTextRun(line_layout_item.StyleRef(), fragment);
   return fragment.character_offset - Start() +
          line_layout_item.ScaledFont().OffsetForPosition(
-             text_run, position, IncludePartialGlyphs, BreakGlyphs);
+             text_run, position, include_partial_glyphs);
 }
 
 LayoutUnit SVGInlineTextBox::PositionForOffset(int) const {
diff --git a/third_party/blink/renderer/core/layout/svg/line/svg_inline_text_box.h b/third_party/blink/renderer/core/layout/svg/line/svg_inline_text_box.h
index 00cbed81..ced60f1 100644
--- a/third_party/blink/renderer/core/layout/svg/line/svg_inline_text_box.h
+++ b/third_party/blink/renderer/core/layout/svg/line/svg_inline_text_box.h
@@ -39,8 +39,7 @@
   void SetLogicalHeight(LayoutUnit height) { logical_height_ = height; }
 
   int OffsetForPosition(LayoutUnit x,
-                        IncludePartialGlyphsOption,
-                        BreakGlyphsOption) const override;
+                        bool include_partial_glyphs = true) const override;
   LayoutUnit PositionForOffset(int offset) const override;
 
   void Paint(const PaintInfo&,
diff --git a/third_party/blink/renderer/core/messaging/blink_transferable_message_struct_traits.cc b/third_party/blink/renderer/core/messaging/blink_transferable_message_struct_traits.cc
index de03fcb..a223c52 100644
--- a/third_party/blink/renderer/core/messaging/blink_transferable_message_struct_traits.cc
+++ b/third_party/blink/renderer/core/messaging/blink_transferable_message_struct_traits.cc
@@ -26,8 +26,7 @@
 
   SkImageInfo info = sk_bitmap.info();
   if (!sk_bitmap.readPixels(info, array_buffer_contents.Data(),
-                            info.minRowBytes(), 0, 0,
-                            SkTransferFunctionBehavior::kIgnore))
+                            info.minRowBytes(), 0, 0))
     return nullptr;
 
   return blink::StaticBitmapImage::Create(array_buffer_contents, info);
diff --git a/third_party/blink/renderer/core/page/chrome_client_impl.cc b/third_party/blink/renderer/core/page/chrome_client_impl.cc
index e8dffb2..ee3858dd 100644
--- a/third_party/blink/renderer/core/page/chrome_client_impl.cc
+++ b/third_party/blink/renderer/core/page/chrome_client_impl.cc
@@ -266,6 +266,7 @@
   if (!frame->GetPage() || frame->GetPage()->Paused())
     return nullptr;
 
+  NotifyPopupOpeningObservers();
   const AtomicString& frame_name =
       !EqualIgnoringASCIICase(r.FrameName(), "_blank") ? r.FrameName()
                                                        : g_empty_atom;
diff --git a/third_party/blink/renderer/core/paint/text_painter_base.cc b/third_party/blink/renderer/core/paint/text_painter_base.cc
index 965ced5..80a5e07 100644
--- a/third_party/blink/renderer/core/paint/text_painter_base.cc
+++ b/third_party/blink/renderer/core/paint/text_painter_base.cc
@@ -288,13 +288,11 @@
   // vertical text.
   switch (baseline_type) {
     case kAlphabeticBaseline:
-      switch (style.GetTextUnderlinePosition()) {
-        case TextUnderlinePosition::kAuto:
-          return ResolvedUnderlinePosition::kRoman;
-        case TextUnderlinePosition::kUnder:
-          return ResolvedUnderlinePosition::kUnder;
+      if (style.TextUnderlinePosition() == kTextUnderlinePositionAuto) {
+        return ResolvedUnderlinePosition::kRoman;
       }
-      break;
+      // TODO(https://crbug.com/313888) Support left, right.
+      return ResolvedUnderlinePosition::kUnder;
     case kIdeographicBaseline:
       // Compute language-appropriate default underline position.
       // https://drafts.csswg.org/css-text-decor-3/#default-stylesheet
diff --git a/third_party/blink/renderer/core/style/computed_style_constants.h b/third_party/blink/renderer/core/style/computed_style_constants.h
index 69060c9..c9ea1e2 100644
--- a/third_party/blink/renderer/core/style/computed_style_constants.h
+++ b/third_party/blink/renderer/core/style/computed_style_constants.h
@@ -192,6 +192,22 @@
   return a = a | b;
 }
 
+static const size_t kTextUnderlinePositionBits = 3;
+enum TextUnderlinePosition {
+  kTextUnderlinePositionAuto = 0x0,
+  kTextUnderlinePositionUnder = 0x1,
+  kTextUnderlinePositionLeft = 0x2,
+  kTextUnderlinePositionRight = 0x4
+};
+inline TextUnderlinePosition operator|(TextUnderlinePosition a,
+                                       TextUnderlinePosition b) {
+  return TextUnderlinePosition(int(a) | int(b));
+}
+inline TextUnderlinePosition& operator|=(TextUnderlinePosition& a,
+                                         TextUnderlinePosition b) {
+  return a = a | b;
+}
+
 enum class ItemPosition : unsigned {
   kLegacy,
   kAuto,
diff --git a/third_party/blink/renderer/core/testing/dictionary_test.cc b/third_party/blink/renderer/core/testing/dictionary_test.cc
index 5c6926c..0c32750 100644
--- a/third_party/blink/renderer/core/testing/dictionary_test.cc
+++ b/third_party/blink/renderer/core/testing/dictionary_test.cc
@@ -141,8 +141,8 @@
   result.setEnumOrNullMember(enum_or_null_member_);
   if (element_member_)
     result.setElementMember(element_member_);
-  if (element_or_null_member_)
-    result.setElementOrNullMember(element_or_null_member_);
+  if (element_or_null_member_.has_value())
+    result.setElementOrNullMember(element_or_null_member_.value());
   result.setObjectMember(object_member_);
   result.setObjectOrNullMemberWithDefault(object_or_null_member_with_default_);
   if (!double_or_string_member_.IsNull())
@@ -246,7 +246,7 @@
   enum_member_with_default_ = String();
   enum_or_null_member_ = String();
   element_member_ = nullptr;
-  element_or_null_member_ = nullptr;
+  element_or_null_member_.reset();
   object_member_ = ScriptValue();
   object_or_null_member_with_default_ = ScriptValue();
   double_or_string_member_ = DoubleOrString();
diff --git a/third_party/blink/renderer/core/testing/dictionary_test.h b/third_party/blink/renderer/core/testing/dictionary_test.h
index 98da87d..34157aa 100644
--- a/third_party/blink/renderer/core/testing/dictionary_test.h
+++ b/third_party/blink/renderer/core/testing/dictionary_test.h
@@ -79,7 +79,7 @@
   String enum_member_with_default_;
   String enum_or_null_member_;
   Member<Element> element_member_;
-  Member<Element> element_or_null_member_;
+  base::Optional<Member<Element>> element_or_null_member_;
   ScriptValue object_member_;
   ScriptValue object_or_null_member_with_default_;
   DoubleOrString double_or_string_member_;
diff --git a/third_party/blink/renderer/devtools/front_end/console/consoleView.css b/third_party/blink/renderer/devtools/front_end/console/consoleView.css
index 4e15b50..ecc4303 100644
--- a/third_party/blink/renderer/devtools/front_end/console/consoleView.css
+++ b/third_party/blink/renderer/devtools/front_end/console/consoleView.css
@@ -34,6 +34,7 @@
 
 .console-toolbar-container {
     display: flex;
+    flex: none;
 }
 
 .console-main-toolbar {
diff --git a/third_party/blink/renderer/devtools/front_end/elements/ComputedStyleWidget.js b/third_party/blink/renderer/devtools/front_end/elements/ComputedStyleWidget.js
index ae3fe2b8..231a28b 100644
--- a/third_party/blink/renderer/devtools/front_end/elements/ComputedStyleWidget.js
+++ b/third_party/blink/renderer/devtools/front_end/elements/ComputedStyleWidget.js
@@ -144,8 +144,10 @@
     this._propertiesOutline.removeChildren();
     this._linkifier.reset();
     const cssModel = this._computedStyleModel.cssModel();
-    if (!nodeStyle || !matchedStyles || !cssModel)
+    if (!nodeStyle || !matchedStyles || !cssModel) {
+      this._noMatchesElement.classList.remove('hidden');
       return;
+    }
 
     const uniqueProperties = nodeStyle.computedStyle.keysArray();
     uniqueProperties.sort(propertySorter);
diff --git a/third_party/blink/renderer/devtools/front_end/elements/StylesSidebarPane.js b/third_party/blink/renderer/devtools/front_end/elements/StylesSidebarPane.js
index 2845ba43..b199ff8cf 100644
--- a/third_party/blink/renderer/devtools/front_end/elements/StylesSidebarPane.js
+++ b/third_party/blink/renderer/devtools/front_end/elements/StylesSidebarPane.js
@@ -432,8 +432,10 @@
     this._sectionBlocks = [];
 
     const node = this.node();
-    if (!matchedStyles || !node)
+    if (!matchedStyles || !node) {
+      this._noMatchesElement.classList.remove('hidden');
       return;
+    }
 
     this._sectionBlocks =
         await this._rebuildSectionsForMatchedStyleRules(/** @type {!SDK.CSSMatchedStyles} */ (matchedStyles));
@@ -476,6 +478,8 @@
 
     if (this._filterRegex)
       this._updateFilter();
+    else
+      this._noMatchesElement.classList.toggle('hidden', this._sectionBlocks.length > 0);
 
     this._nodeStylesUpdatedForTest(/** @type {!SDK.DOMNode} */ (node), true);
     if (this._decorator) {
diff --git a/third_party/blink/renderer/devtools/front_end/timeline/timelinePanel.css b/third_party/blink/renderer/devtools/front_end/timeline/timelinePanel.css
index e9349e6..24a3e64 100644
--- a/third_party/blink/renderer/devtools/front_end/timeline/timelinePanel.css
+++ b/third_party/blink/renderer/devtools/front_end/timeline/timelinePanel.css
@@ -29,6 +29,7 @@
 
 .timeline-toolbar-container {
     display: flex;
+    flex: none;
 }
 
 .timeline-toolbar-container > .toolbar {
diff --git a/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context.cc b/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context.cc
index d0c9a45..0e65481 100644
--- a/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context.cc
+++ b/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context.cc
@@ -63,13 +63,8 @@
     const CanvasContextCreationAttributesCore& attrs) {
   bool using_gpu_compositing;
   std::unique_ptr<WebGraphicsContext3DProvider> context_provider(
-      // TODO(jiajia.qin@intel.com): Add a new ContextType
-      // 'kWebGL2ComputeContextType' to
-      // src/third_party/blink/public/platform/platform.h and use ContextType
-      // instead of 'unsigned web_gl_version' as the argument of
-      // CreateWebGraphicsContext3DProvider so that the correct OpenGL ES 3.1
-      // context underneath can be allocated.
-      CreateWebGraphicsContext3DProvider(host, attrs, 2,
+      CreateWebGraphicsContext3DProvider(host, attrs,
+                                         Platform::kWebGL2ComputeContextType,
                                          &using_gpu_compositing));
   if (!ShouldCreateWebGL2ComputeContext(context_provider.get(), host))
     return nullptr;
diff --git a/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context.h b/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context.h
index e6b1a08..2b830351 100644
--- a/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context.h
+++ b/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context.h
@@ -73,16 +73,15 @@
   Member<WebGLLoseContext> webgl_lose_context_;
 };
 
-// TODO(jiajia.qin@intel.com): Change these comparisons by using ContextType
-// instead of unsigned int version number.
 DEFINE_TYPE_CASTS(WebGL2ComputeRenderingContext,
                   CanvasRenderingContext,
                   context,
                   context->Is3d() &&
-                      WebGLRenderingContextBase::GetWebGLVersion(context) == 2,
+                      WebGLRenderingContextBase::GetWebGLVersion(context) ==
+                          Platform::kWebGL2ComputeContextType,
                   context.Is3d() &&
                       WebGLRenderingContextBase::GetWebGLVersion(&context) ==
-                          2);
+                          Platform::kWebGL2ComputeContextType);
 
 }  // namespace blink
 
diff --git a/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.cc b/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.cc
index b79daee..ffb32f1 100644
--- a/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.cc
+++ b/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.cc
@@ -16,7 +16,8 @@
     : WebGL2RenderingContextBase(host,
                                  std::move(context_provider),
                                  using_gpu_compositing,
-                                 requested_attributes) {}
+                                 requested_attributes,
+                                 Platform::kWebGL2ComputeContextType) {}
 
 void WebGL2ComputeRenderingContextBase::DestroyContext() {
   WebGL2RenderingContextBase::DestroyContext();
diff --git a/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.h b/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.h
index 4c7c5fa4c..3339f9c 100644
--- a/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.h
+++ b/third_party/blink/renderer/modules/webgl/webgl2_compute_rendering_context_base.h
@@ -46,16 +46,15 @@
       const CanvasContextCreationAttributesCore& requested_attributes);
 };
 
-// TODO(jiajia.qin@intel.com): Change these comparisons by using ContextType
-// instead of unsigned int version number.
 DEFINE_TYPE_CASTS(WebGL2ComputeRenderingContextBase,
                   CanvasRenderingContext,
                   context,
                   context->Is3d() &&
-                      WebGLRenderingContextBase::GetWebGLVersion(context) >= 2,
+                      WebGLRenderingContextBase::GetWebGLVersion(context) ==
+                          Platform::kWebGL2ComputeContextType,
                   context.Is3d() &&
-                      WebGLRenderingContextBase::GetWebGLVersion(&context) >=
-                          2);
+                      WebGLRenderingContextBase::GetWebGLVersion(&context) ==
+                          Platform::kWebGL2ComputeContextType);
 
 }  // namespace blink
 
diff --git a/third_party/blink/renderer/modules/webgl/webgl2_rendering_context.cc b/third_party/blink/renderer/modules/webgl/webgl2_rendering_context.cc
index f1c6c0f..274e3c8 100644
--- a/third_party/blink/renderer/modules/webgl/webgl2_rendering_context.cc
+++ b/third_party/blink/renderer/modules/webgl/webgl2_rendering_context.cc
@@ -62,8 +62,8 @@
     const CanvasContextCreationAttributesCore& attrs) {
   bool using_gpu_compositing;
   std::unique_ptr<WebGraphicsContext3DProvider> context_provider(
-      CreateWebGraphicsContext3DProvider(host, attrs, 2,
-                                         &using_gpu_compositing));
+      CreateWebGraphicsContext3DProvider(
+          host, attrs, Platform::kWebGL2ContextType, &using_gpu_compositing));
   if (!ShouldCreateContext(context_provider.get(), host))
     return nullptr;
   WebGL2RenderingContext* rendering_context = new WebGL2RenderingContext(
@@ -96,7 +96,8 @@
     : WebGL2RenderingContextBase(host,
                                  std::move(context_provider),
                                  using_gpu_compositing,
-                                 requested_attributes) {}
+                                 requested_attributes,
+                                 Platform::kWebGL2ContextType) {}
 
 void WebGL2RenderingContext::SetCanvasGetContextResult(
     RenderingContext& result) {
diff --git a/third_party/blink/renderer/modules/webgl/webgl2_rendering_context.h b/third_party/blink/renderer/modules/webgl/webgl2_rendering_context.h
index c39a3e1..db77f15 100644
--- a/third_party/blink/renderer/modules/webgl/webgl2_rendering_context.h
+++ b/third_party/blink/renderer/modules/webgl/webgl2_rendering_context.h
@@ -75,10 +75,11 @@
                   CanvasRenderingContext,
                   context,
                   context->Is3d() &&
-                      WebGLRenderingContextBase::GetWebGLVersion(context) == 2,
+                      WebGLRenderingContextBase::GetWebGLVersion(context) ==
+                          Platform::kWebGL2ContextType,
                   context.Is3d() &&
                       WebGLRenderingContextBase::GetWebGLVersion(&context) ==
-                          2);
+                          Platform::kWebGL2ContextType);
 
 }  // namespace blink
 
diff --git a/third_party/blink/renderer/modules/webgl/webgl2_rendering_context_base.cc b/third_party/blink/renderer/modules/webgl/webgl2_rendering_context_base.cc
index 3c4b43949..2f4376a 100644
--- a/third_party/blink/renderer/modules/webgl/webgl2_rendering_context_base.cc
+++ b/third_party/blink/renderer/modules/webgl/webgl2_rendering_context_base.cc
@@ -139,12 +139,13 @@
     CanvasRenderingContextHost* host,
     std::unique_ptr<WebGraphicsContext3DProvider> context_provider,
     bool using_gpu_compositing,
-    const CanvasContextCreationAttributesCore& requested_attributes)
+    const CanvasContextCreationAttributesCore& requested_attributes,
+    Platform::ContextType context_type)
     : WebGLRenderingContextBase(host,
                                 std::move(context_provider),
                                 using_gpu_compositing,
                                 requested_attributes,
-                                2) {
+                                context_type) {
   supported_internal_formats_storage_.insert(
       kSupportedInternalFormatsStorage,
       kSupportedInternalFormatsStorage +
diff --git a/third_party/blink/renderer/modules/webgl/webgl2_rendering_context_base.h b/third_party/blink/renderer/modules/webgl/webgl2_rendering_context_base.h
index 05319f5..7ef3f4cf 100644
--- a/third_party/blink/renderer/modules/webgl/webgl2_rendering_context_base.h
+++ b/third_party/blink/renderer/modules/webgl/webgl2_rendering_context_base.h
@@ -981,7 +981,8 @@
       CanvasRenderingContextHost*,
       std::unique_ptr<WebGraphicsContext3DProvider>,
       bool using_gpu_compositing,
-      const CanvasContextCreationAttributesCore& requested_attributes);
+      const CanvasContextCreationAttributesCore& requested_attributes,
+      Platform::ContextType context_type);
 
   // DrawingBuffer::Client implementation.
   void DrawingBufferClientRestorePixelUnpackBufferBinding() override;
@@ -1148,10 +1149,11 @@
                   CanvasRenderingContext,
                   context,
                   context->Is3d() &&
-                      WebGLRenderingContextBase::GetWebGLVersion(context) >= 2,
+                      WebGLRenderingContextBase::GetWebGLVersion(context) ==
+                          Platform::kWebGL2ContextType,
                   context.Is3d() &&
-                      WebGLRenderingContextBase::GetWebGLVersion(&context) >=
-                          2);
+                      WebGLRenderingContextBase::GetWebGLVersion(&context) ==
+                          Platform::kWebGL2ContextType);
 
 }  // namespace blink
 
diff --git a/third_party/blink/renderer/modules/webgl/webgl_context_attribute_helpers.cc b/third_party/blink/renderer/modules/webgl/webgl_context_attribute_helpers.cc
index 7274af5..3846b2a 100644
--- a/third_party/blink/renderer/modules/webgl/webgl_context_attribute_helpers.cc
+++ b/third_party/blink/renderer/modules/webgl/webgl_context_attribute_helpers.cc
@@ -27,13 +27,12 @@
 
 Platform::ContextAttributes ToPlatformContextAttributes(
     const CanvasContextCreationAttributesCore& attrs,
-    unsigned web_gl_version,
+    Platform::ContextType context_type,
     bool support_own_offscreen_surface) {
   Platform::ContextAttributes result;
   result.fail_if_major_performance_caveat =
       attrs.fail_if_major_performance_caveat;
-  result.context_type = web_gl_version == 2 ? Platform::kWebGL2ContextType
-                                            : Platform::kWebGL1ContextType;
+  result.context_type = context_type;
   if (support_own_offscreen_surface) {
     // Only ask for alpha/depth/stencil/antialias if we may be using the default
     // framebuffer. They are not needed for standard offscreen rendering.
diff --git a/third_party/blink/renderer/modules/webgl/webgl_context_attribute_helpers.h b/third_party/blink/renderer/modules/webgl/webgl_context_attribute_helpers.h
index 3791d41..d1cbf48 100644
--- a/third_party/blink/renderer/modules/webgl/webgl_context_attribute_helpers.h
+++ b/third_party/blink/renderer/modules/webgl/webgl_context_attribute_helpers.h
@@ -18,7 +18,7 @@
 // Platform API.
 Platform::ContextAttributes ToPlatformContextAttributes(
     const CanvasContextCreationAttributesCore&,
-    unsigned web_gl_version,
+    Platform::ContextType context_type,
     bool support_own_offscreen_surface);
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/webgl/webgl_rendering_context.cc b/third_party/blink/renderer/modules/webgl/webgl_rendering_context.cc
index 5a8e295..0e87448 100644
--- a/third_party/blink/renderer/modules/webgl/webgl_rendering_context.cc
+++ b/third_party/blink/renderer/modules/webgl/webgl_rendering_context.cc
@@ -92,8 +92,8 @@
     const CanvasContextCreationAttributesCore& attrs) {
   bool using_gpu_compositing;
   std::unique_ptr<WebGraphicsContext3DProvider> context_provider(
-      CreateWebGraphicsContext3DProvider(host, attrs, 1,
-                                         &using_gpu_compositing));
+      CreateWebGraphicsContext3DProvider(
+          host, attrs, Platform::kWebGL1ContextType, &using_gpu_compositing));
   if (!ShouldCreateContext(context_provider.get()))
     return nullptr;
 
@@ -126,7 +126,7 @@
                                 std::move(context_provider),
                                 using_gpu_compositing,
                                 requested_attributes,
-                                1) {}
+                                Platform::kWebGL1ContextType) {}
 
 void WebGLRenderingContext::SetCanvasGetContextResult(
     RenderingContext& result) {
diff --git a/third_party/blink/renderer/modules/webgl/webgl_rendering_context.h b/third_party/blink/renderer/modules/webgl/webgl_rendering_context.h
index 984a5052..5d13ec8 100644
--- a/third_party/blink/renderer/modules/webgl/webgl_rendering_context.h
+++ b/third_party/blink/renderer/modules/webgl/webgl_rendering_context.h
@@ -123,10 +123,11 @@
                   CanvasRenderingContext,
                   context,
                   context->Is3d() &&
-                      WebGLRenderingContextBase::GetWebGLVersion(context) == 1,
+                      WebGLRenderingContextBase::GetWebGLVersion(context) ==
+                          Platform::kWebGL1ContextType,
                   context.Is3d() &&
                       WebGLRenderingContextBase::GetWebGLVersion(&context) ==
-                          1);
+                          Platform::kWebGL1ContextType);
 
 }  // namespace blink
 
diff --git a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc
index b499306..72ed4311 100644
--- a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc
+++ b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc
@@ -663,15 +663,14 @@
 WebGLRenderingContextBase::CreateContextProviderInternal(
     CanvasRenderingContextHost* host,
     const CanvasContextCreationAttributesCore& attributes,
-    unsigned web_gl_version,
+    Platform::ContextType context_type,
     bool* using_gpu_compositing) {
   DCHECK(host);
   ExecutionContext* execution_context = host->GetTopExecutionContext();
   DCHECK(execution_context);
 
   Platform::ContextAttributes context_attributes = ToPlatformContextAttributes(
-      attributes, web_gl_version,
-      SupportOwnOffscreenSurface(execution_context));
+      attributes, context_type, SupportOwnOffscreenSurface(execution_context));
 
   Platform::GraphicsInfo gl_info;
   std::unique_ptr<WebGraphicsContext3DProvider> context_provider;
@@ -714,7 +713,7 @@
 WebGLRenderingContextBase::CreateWebGraphicsContext3DProvider(
     CanvasRenderingContextHost* host,
     const CanvasContextCreationAttributesCore& attributes,
-    unsigned webgl_version,
+    Platform::ContextType context_type,
     bool* using_gpu_compositing) {
   // The host might block creation of a new WebGL context despite the
   // page settings; in particular, if WebGL contexts were lost one or
@@ -726,15 +725,19 @@
         "Web page caused context loss and was blocked"));
     return nullptr;
   }
-  if ((webgl_version == 1 && !host->IsWebGL1Enabled()) ||
-      (webgl_version == 2 && !host->IsWebGL2Enabled())) {
+  if ((context_type == Platform::kWebGL1ContextType &&
+       !host->IsWebGL1Enabled()) ||
+      (context_type == Platform::kWebGL2ContextType &&
+       !host->IsWebGL2Enabled()) ||
+      (context_type == Platform::kWebGL2ComputeContextType &&
+       !host->IsWebGL2Enabled())) {
     host->HostDispatchEvent(WebGLContextEvent::Create(
         EventTypeNames::webglcontextcreationerror,
         "disabled by enterprise policy or commandline switch"));
     return nullptr;
   }
 
-  return CreateContextProviderInternal(host, attributes, webgl_version,
+  return CreateContextProviderInternal(host, attributes, context_type,
                                        using_gpu_compositing);
 }
 
@@ -985,7 +988,7 @@
     std::unique_ptr<WebGraphicsContext3DProvider> context_provider,
     bool using_gpu_compositing,
     const CanvasContextCreationAttributesCore& requested_attributes,
-    unsigned version)
+    Platform::ContextType version)
     : WebGLRenderingContextBase(
           host,
           host->GetTopExecutionContext()->GetTaskRunner(TaskType::kWebGL),
@@ -1000,7 +1003,7 @@
     std::unique_ptr<WebGraphicsContext3DProvider> context_provider,
     bool using_gpu_compositing,
     const CanvasContextCreationAttributesCore& requested_attributes,
-    unsigned version)
+    Platform::ContextType context_type)
     : CanvasRenderingContext(host, requested_attributes),
       context_group_(new WebGLContextGroup()),
       is_hidden_(false),
@@ -1027,7 +1030,7 @@
       is_web_gl_depth_texture_formats_types_added_(false),
       is_ext_srgb_formats_types_added_(false),
       is_ext_color_buffer_float_formats_added_(false),
-      version_(version) {
+      context_type_(context_type) {
   DCHECK(context_provider);
 
   Host()->RegisterContextToDispatch(this);
@@ -1093,10 +1096,12 @@
       CreationAttributes().preserve_drawing_buffer ? DrawingBuffer::kPreserve
                                                    : DrawingBuffer::kDiscard;
   DrawingBuffer::WebGLVersion web_gl_version = DrawingBuffer::kWebGL1;
-  if (Version() == 1) {
+  if (context_type_ == Platform::kWebGL1ContextType) {
     web_gl_version = DrawingBuffer::kWebGL1;
-  } else if (Version() == 2) {
+  } else if (context_type_ == Platform::kWebGL2ContextType) {
     web_gl_version = DrawingBuffer::kWebGL2;
+  } else if (context_type_ == Platform::kWebGL2ComputeContextType) {
+    web_gl_version = DrawingBuffer::kWebGL2Compute;
   } else {
     NOTREACHED();
   }
@@ -1291,7 +1296,7 @@
     const CanvasRenderingContext* context) {
   if (!context->Is3d())
     return 0;
-  return static_cast<const WebGLRenderingContextBase*>(context)->Version();
+  return static_cast<const WebGLRenderingContextBase*>(context)->ContextType();
 }
 
 WebGLRenderingContextBase::~WebGLRenderingContextBase() {
@@ -7639,8 +7644,11 @@
       return;
 
     Settings* settings = frame->GetSettings();
-    if (settings && ((version_ == 1 && !settings->GetWebGL1Enabled()) ||
-                     (version_ == 2 && !settings->GetWebGL2Enabled()))) {
+    if (settings && ((context_type_ == Platform::kWebGL1ContextType &&
+                      !settings->GetWebGL1Enabled()) ||
+                     ((context_type_ == Platform::kWebGL2ContextType ||
+                       context_type_ == Platform::kWebGL2ComputeContextType) &&
+                      !settings->GetWebGL2Enabled()))) {
       return;
     }
   }
@@ -7651,7 +7659,7 @@
 
   auto* execution_context = Host()->GetTopExecutionContext();
   Platform::ContextAttributes attributes = ToPlatformContextAttributes(
-      CreationAttributes(), Version(),
+      CreationAttributes(), context_type_,
       SupportOwnOffscreenSurface(execution_context));
   Platform::GraphicsInfo gl_info;
   std::unique_ptr<WebGraphicsContext3DProvider> context_provider;
diff --git a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h
index fd3534a1..abdc7a28 100644
--- a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h
+++ b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h
@@ -144,11 +144,11 @@
   static std::unique_ptr<WebGraphicsContext3DProvider>
   CreateWebGraphicsContext3DProvider(CanvasRenderingContextHost*,
                                      const CanvasContextCreationAttributesCore&,
-                                     unsigned web_gl_version,
+                                     Platform::ContextType context_type,
                                      bool* using_gpu_compositing);
   static void ForceNextWebGLContextCreationToFail();
 
-  unsigned Version() const { return version_; }
+  Platform::ContextType ContextType() const { return context_type_; }
 
   int drawingBufferWidth() const;
   int drawingBufferHeight() const;
@@ -595,7 +595,10 @@
   scoped_refptr<StaticBitmapImage> GetImage(
       AccelerationHint = kPreferAcceleration) const override;
   void SetFilterQuality(SkFilterQuality) override;
-  bool IsWebGL2OrHigher() { return Version() >= 2; }
+  bool IsWebGL2OrHigher() {
+    return context_type_ == Platform::kWebGL2ContextType ||
+           context_type_ == Platform::kWebGL2ComputeContextType;
+  }
 
   void getHTMLOrOffscreenCanvas(HTMLCanvasElementOrOffscreenCanvas&) const;
 
@@ -639,7 +642,7 @@
                             std::unique_ptr<WebGraphicsContext3DProvider>,
                             bool using_gpu_compositing,
                             const CanvasContextCreationAttributesCore&,
-                            unsigned);
+                            Platform::ContextType);
   scoped_refptr<DrawingBuffer> CreateDrawingBuffer(
       std::unique_ptr<WebGraphicsContext3DProvider>,
       bool using_gpu_compositing);
@@ -1677,12 +1680,12 @@
                             std::unique_ptr<WebGraphicsContext3DProvider>,
                             bool using_gpu_compositing,
                             const CanvasContextCreationAttributesCore&,
-                            unsigned);
+                            Platform::ContextType);
   static bool SupportOwnOffscreenSurface(ExecutionContext*);
   static std::unique_ptr<WebGraphicsContext3DProvider>
   CreateContextProviderInternal(CanvasRenderingContextHost*,
                                 const CanvasContextCreationAttributesCore&,
-                                unsigned web_gl_version,
+                                Platform::ContextType context_type,
                                 bool* using_gpu_compositing);
   void TexImageCanvasByGPU(TexImageFunctionID,
                            HTMLCanvasElement*,
@@ -1698,7 +1701,7 @@
                            GLint,
                            const IntRect&);
 
-  const unsigned version_;
+  const Platform::ContextType context_type_;
 
   bool IsPaintable() const final { return GetDrawingBuffer(); }
 
diff --git a/third_party/blink/renderer/modules/xr/xr_webgl_layer.cc b/third_party/blink/renderer/modules/xr/xr_webgl_layer.cc
index 69bde9c..0971d900 100644
--- a/third_party/blink/renderer/modules/xr/xr_webgl_layer.cc
+++ b/third_party/blink/renderer/modules/xr/xr_webgl_layer.cc
@@ -142,7 +142,7 @@
 
 void XRWebGLLayer::getXRWebGLRenderingContext(
     WebGLRenderingContextOrWebGL2RenderingContext& result) const {
-  if (webgl_context_->Version() == 2) {
+  if (webgl_context_->ContextType() == Platform::kWebGL2ContextType) {
     result.SetWebGL2RenderingContext(
         static_cast<WebGL2RenderingContext*>(webgl_context_.Get()));
   } else {
diff --git a/third_party/blink/renderer/platform/BUILD.gn b/third_party/blink/renderer/platform/BUILD.gn
index ee19530..45fc93c 100644
--- a/third_party/blink/renderer/platform/BUILD.gn
+++ b/third_party/blink/renderer/platform/BUILD.gn
@@ -1732,7 +1732,6 @@
     "feature_policy/feature_policy_test.cc",
     "fonts/android/font_cache_android_test.cc",
     "fonts/bitmap_glyphs_blacklist_test.cc",
-    "fonts/cursor_position_test.cc",
     "fonts/font_cache_test.cc",
     "fonts/font_description_test.cc",
     "fonts/font_family_test.cc",
@@ -1973,7 +1972,6 @@
     "testing/blink_perf_test_suite.cc",
     "testing/blink_perf_test_suite.h",
     "testing/run_all_perf_tests.cc",
-    "testing/shape_result_perf_test.cc",
     "testing/shaping_line_breaker_perf_test.cc",
   ]
 
diff --git a/third_party/blink/renderer/platform/exported/OWNERS b/third_party/blink/renderer/platform/exported/OWNERS
new file mode 100644
index 0000000..fa50614
--- /dev/null
+++ b/third_party/blink/renderer/platform/exported/OWNERS
@@ -0,0 +1 @@
+per-file web_rtc_*=hbos@chromium.org
diff --git a/third_party/blink/renderer/platform/exported/web_font.cc b/third_party/blink/renderer/platform/exported/web_font.cc
index 4e1dd3c..1d1c3d7 100644
--- a/third_party/blink/renderer/platform/exported/web_font.cc
+++ b/third_party/blink/renderer/platform/exported/web_font.cc
@@ -108,8 +108,7 @@
 }
 
 int WebFont::OffsetForPosition(const WebTextRun& run, float position) const {
-  return private_->GetFont().OffsetForPosition(
-      run, position, IncludePartialGlyphs, DontBreakGlyphs);
+  return private_->GetFont().OffsetForPosition(run, position, true);
 }
 
 WebFloatRect WebFont::SelectionRectForText(const WebTextRun& run,
diff --git a/third_party/blink/renderer/platform/exported/web_surface_layer_bridge.cc b/third_party/blink/renderer/platform/exported/web_surface_layer_bridge.cc
index 8910562d..e434b44 100644
--- a/third_party/blink/renderer/platform/exported/web_surface_layer_bridge.cc
+++ b/third_party/blink/renderer/platform/exported/web_surface_layer_bridge.cc
@@ -11,10 +11,8 @@
 
 std::unique_ptr<WebSurfaceLayerBridge> WebSurfaceLayerBridge::Create(
     WebLayerTreeView* layer_tree_view,
-    WebSurfaceLayerBridgeObserver* observer,
-    cc::UpdateSubmissionStateCB update_submission_state_callback) {
-  return std::make_unique<SurfaceLayerBridge>(
-      layer_tree_view, observer, std::move(update_submission_state_callback));
+    WebSurfaceLayerBridgeObserver* observer) {
+  return std::make_unique<SurfaceLayerBridge>(layer_tree_view, observer);
 }
 
 WebSurfaceLayerBridge::~WebSurfaceLayerBridge() = default;
diff --git a/third_party/blink/renderer/platform/feature_policy/feature_policy.cc b/third_party/blink/renderer/platform/feature_policy/feature_policy.cc
index dbcf678..a9a0e41a 100644
--- a/third_party/blink/renderer/platform/feature_policy/feature_policy.cc
+++ b/third_party/blink/renderer/platform/feature_policy/feature_policy.cc
@@ -3,6 +3,8 @@
 
 #include "third_party/blink/renderer/platform/feature_policy/feature_policy.h"
 
+#include <algorithm>
+
 #include "third_party/blink/renderer/platform/json/json_values.h"
 #include "third_party/blink/renderer/platform/network/http_parsers.h"
 #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
@@ -135,6 +137,62 @@
   return allowlists;
 }
 
+bool IsFeatureDeclared(mojom::FeaturePolicyFeature feature,
+                       const ParsedFeaturePolicy& policy) {
+  return std::any_of(policy.begin(), policy.end(),
+                     [feature](const auto& declaration) {
+                       return declaration.feature == feature;
+                     });
+}
+
+bool RemoveFeatureIfPresent(mojom::FeaturePolicyFeature feature,
+                            ParsedFeaturePolicy& policy) {
+  auto new_end = std::remove_if(policy.begin(), policy.end(),
+                                [feature](const auto& declaration) {
+                                  return declaration.feature == feature;
+                                });
+  if (new_end == policy.end())
+    return false;
+  policy.erase(new_end, policy.end());
+  return true;
+}
+
+bool DisallowFeatureIfNotPresent(mojom::FeaturePolicyFeature feature,
+                                 ParsedFeaturePolicy& policy) {
+  if (IsFeatureDeclared(feature, policy))
+    return false;
+  ParsedFeaturePolicyDeclaration allowlist;
+  allowlist.feature = feature;
+  allowlist.matches_all_origins = false;
+  allowlist.matches_opaque_src = false;
+  policy.push_back(allowlist);
+  return true;
+}
+
+bool AllowFeatureEverywhereIfNotPresent(mojom::FeaturePolicyFeature feature,
+                                        ParsedFeaturePolicy& policy) {
+  if (IsFeatureDeclared(feature, policy))
+    return false;
+  ParsedFeaturePolicyDeclaration allowlist;
+  allowlist.feature = feature;
+  allowlist.matches_all_origins = true;
+  allowlist.matches_opaque_src = true;
+  policy.push_back(allowlist);
+  return true;
+}
+
+void DisallowFeature(mojom::FeaturePolicyFeature feature,
+                     ParsedFeaturePolicy& policy) {
+  RemoveFeatureIfPresent(feature, policy);
+  DisallowFeatureIfNotPresent(feature, policy);
+}
+
+void AllowFeatureEverywhere(mojom::FeaturePolicyFeature feature,
+                            ParsedFeaturePolicy& policy) {
+  RemoveFeatureIfPresent(feature, policy);
+  AllowFeatureEverywhereIfNotPresent(feature, policy);
+}
+
 // This method defines the feature names which will be recognized by the parser
 // for the Feature-Policy HTTP header and the <iframe> "allow" attribute, as
 // well as the features which will be recognized by the document or iframe
diff --git a/third_party/blink/renderer/platform/feature_policy/feature_policy.h b/third_party/blink/renderer/platform/feature_policy/feature_policy.h
index 289b3b2..05c3737 100644
--- a/third_party/blink/renderer/platform/feature_policy/feature_policy.h
+++ b/third_party/blink/renderer/platform/feature_policy/feature_policy.h
@@ -58,6 +58,38 @@
                    Vector<String>* messages,
                    const FeatureNameMap& feature_names);
 
+// Returns true iff any declaration in the policy is for the given feature.
+PLATFORM_EXPORT bool IsFeatureDeclared(mojom::FeaturePolicyFeature,
+                                       const ParsedFeaturePolicy&);
+
+// Removes any declaration in the policy for the given feature. Returns true if
+// the policy was modified.
+PLATFORM_EXPORT bool RemoveFeatureIfPresent(mojom::FeaturePolicyFeature,
+                                            ParsedFeaturePolicy&);
+
+// If no declaration in the policy exists already for the feature, adds a
+// declaration which disallows the feature in all origins. Returns true if the
+// policy was modified.
+PLATFORM_EXPORT bool DisallowFeatureIfNotPresent(mojom::FeaturePolicyFeature,
+                                                 ParsedFeaturePolicy&);
+
+// If no declaration in the policy exists already for the feature, adds a
+// declaration which allows the feature in all origins. Returns true if the
+// policy was modified.
+PLATFORM_EXPORT bool AllowFeatureEverywhereIfNotPresent(
+    mojom::FeaturePolicyFeature,
+    ParsedFeaturePolicy&);
+
+// Replaces any existing declarations in the policy for the given feature with
+// a declaration which disallows the feature in all origins.
+PLATFORM_EXPORT void DisallowFeature(mojom::FeaturePolicyFeature,
+                                     ParsedFeaturePolicy&);
+
+// Replaces any existing declarations in the policy for the given feature with
+// a declaration which allows the feature in all origins.
+PLATFORM_EXPORT void AllowFeatureEverywhere(mojom::FeaturePolicyFeature,
+                                            ParsedFeaturePolicy&);
+
 }  // namespace blink
 
 #endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_FEATURE_POLICY_FEATURE_POLICY_H_
diff --git a/third_party/blink/renderer/platform/feature_policy/feature_policy_test.cc b/third_party/blink/renderer/platform/feature_policy/feature_policy_test.cc
index cf572f81..9234b33 100644
--- a/third_party/blink/renderer/platform/feature_policy/feature_policy_test.cc
+++ b/third_party/blink/renderer/platform/feature_policy/feature_policy_test.cc
@@ -56,11 +56,11 @@
 
 }  // namespace
 
-class FeaturePolicyTest : public testing::Test {
+class FeaturePolicyParserTest : public testing::Test {
  protected:
-  FeaturePolicyTest() = default;
+  FeaturePolicyParserTest() = default;
 
-  ~FeaturePolicyTest() override = default;
+  ~FeaturePolicyParserTest() override = default;
 
   scoped_refptr<const SecurityOrigin> origin_a_ =
       SecurityOrigin::CreateFromString(ORIGIN_A);
@@ -79,7 +79,7 @@
       {"geolocation", blink::mojom::FeaturePolicyFeature::kGeolocation}};
 };
 
-TEST_F(FeaturePolicyTest, ParseValidPolicy) {
+TEST_F(FeaturePolicyParserTest, ParseValidPolicy) {
   Vector<String> messages;
   for (const char* policy_string : kValidPolicies) {
     messages.clear();
@@ -89,7 +89,7 @@
   }
 }
 
-TEST_F(FeaturePolicyTest, ParseInvalidPolicy) {
+TEST_F(FeaturePolicyParserTest, ParseInvalidPolicy) {
   Vector<String> messages;
   for (const char* policy_string : kInvalidPolicies) {
     messages.clear();
@@ -99,7 +99,7 @@
   }
 }
 
-TEST_F(FeaturePolicyTest, PolicyParsedCorrectly) {
+TEST_F(FeaturePolicyParserTest, PolicyParsedCorrectly) {
   Vector<String> messages;
 
   // Empty policy.
@@ -212,7 +212,7 @@
       parsed_policy[2].origins[0].IsSameOriginWith(expected_url_origin_a_));
 }
 
-TEST_F(FeaturePolicyTest, PolicyParsedCorrectlyForOpaqueOrigins) {
+TEST_F(FeaturePolicyParserTest, PolicyParsedCorrectlyForOpaqueOrigins) {
   Vector<String> messages;
 
   scoped_refptr<SecurityOrigin> opaque_origin =
@@ -291,4 +291,212 @@
       parsed_policy[0].origins[0].IsSameOriginWith(expected_url_origin_b_));
 }
 
+// Test policy mutation methods
+class FeaturePolicyMutationTest : public testing::Test {
+ protected:
+  FeaturePolicyMutationTest() = default;
+
+  ~FeaturePolicyMutationTest() override = default;
+
+  url::Origin url_origin_a_ = url::Origin::Create(GURL(ORIGIN_A));
+  url::Origin url_origin_b_ = url::Origin::Create(GURL(ORIGIN_B));
+  url::Origin url_origin_c_ = url::Origin::Create(GURL(ORIGIN_C));
+
+  // Returns true if the policy contains a declaration for the feature which
+  // allows it in all origins.
+  bool IsFeatureAllowedEverywhere(mojom::FeaturePolicyFeature feature,
+                                  const ParsedFeaturePolicy& policy) {
+    const auto& result = std::find_if(policy.begin(), policy.end(),
+                                      [feature](const auto& declaration) {
+                                        return declaration.feature == feature;
+                                      });
+    if (result == policy.end())
+      return false;
+
+    return result->feature == feature && result->matches_all_origins &&
+           result->matches_opaque_src && result->origins.empty();
+  }
+
+  // Returns true if the policy contains a declaration for the feature which
+  // disallows it in all origins.
+  bool IsFeatureDisallowedEverywhere(mojom::FeaturePolicyFeature feature,
+                                     const ParsedFeaturePolicy& policy) {
+    const auto& result = std::find_if(policy.begin(), policy.end(),
+                                      [feature](const auto& declaration) {
+                                        return declaration.feature == feature;
+                                      });
+    if (result == policy.end())
+      return false;
+
+    return result->feature == feature && !result->matches_all_origins &&
+           !result->matches_opaque_src && result->origins.empty();
+  }
+
+  ParsedFeaturePolicy test_policy = {{mojom::FeaturePolicyFeature::kFullscreen,
+                                      false,
+                                      false,
+                                      {url_origin_a_, url_origin_b_}},
+                                     {mojom::FeaturePolicyFeature::kGeolocation,
+                                      false,
+                                      false,
+                                      {url_origin_a_}}};
+  ParsedFeaturePolicy empty_policy = {};
+};
+TEST_F(FeaturePolicyMutationTest, TestIsFeatureDeclared) {
+  EXPECT_TRUE(
+      IsFeatureDeclared(mojom::FeaturePolicyFeature::kFullscreen, test_policy));
+  EXPECT_TRUE(IsFeatureDeclared(mojom::FeaturePolicyFeature::kGeolocation,
+                                test_policy));
+  EXPECT_FALSE(
+      IsFeatureDeclared(mojom::FeaturePolicyFeature::kUsb, test_policy));
+  EXPECT_FALSE(
+      IsFeatureDeclared(mojom::FeaturePolicyFeature::kNotFound, test_policy));
+}
+
+TEST_F(FeaturePolicyMutationTest, TestIsFeatureDeclaredWithEmptyPolicy) {
+  EXPECT_FALSE(IsFeatureDeclared(mojom::FeaturePolicyFeature::kFullscreen,
+                                 empty_policy));
+  EXPECT_FALSE(
+      IsFeatureDeclared(mojom::FeaturePolicyFeature::kNotFound, empty_policy));
+}
+
+TEST_F(FeaturePolicyMutationTest, TestRemoveAbsentFeature) {
+  ASSERT_EQ(2UL, test_policy.size());
+  EXPECT_FALSE(
+      IsFeatureDeclared(mojom::FeaturePolicyFeature::kPayment, test_policy));
+  EXPECT_FALSE(RemoveFeatureIfPresent(mojom::FeaturePolicyFeature::kPayment,
+                                      test_policy));
+  ASSERT_EQ(2UL, test_policy.size());
+  EXPECT_FALSE(
+      IsFeatureDeclared(mojom::FeaturePolicyFeature::kPayment, test_policy));
+}
+
+TEST_F(FeaturePolicyMutationTest, TestRemoveFromEmptyPolicy) {
+  ASSERT_EQ(0UL, empty_policy.size());
+  EXPECT_FALSE(RemoveFeatureIfPresent(mojom::FeaturePolicyFeature::kPayment,
+                                      test_policy));
+  ASSERT_EQ(0UL, empty_policy.size());
+}
+
+TEST_F(FeaturePolicyMutationTest, TestRemoveFeatureIfPresent) {
+  ASSERT_EQ(2UL, test_policy.size());
+  EXPECT_TRUE(
+      IsFeatureDeclared(mojom::FeaturePolicyFeature::kFullscreen, test_policy));
+  EXPECT_TRUE(RemoveFeatureIfPresent(mojom::FeaturePolicyFeature::kFullscreen,
+                                     test_policy));
+  EXPECT_EQ(1UL, test_policy.size());
+  EXPECT_FALSE(
+      IsFeatureDeclared(mojom::FeaturePolicyFeature::kFullscreen, test_policy));
+
+  // Attempt to remove the feature again
+  EXPECT_FALSE(RemoveFeatureIfPresent(mojom::FeaturePolicyFeature::kFullscreen,
+                                      test_policy));
+  EXPECT_EQ(1UL, test_policy.size());
+  EXPECT_FALSE(
+      IsFeatureDeclared(mojom::FeaturePolicyFeature::kFullscreen, test_policy));
+}
+
+TEST_F(FeaturePolicyMutationTest, TestRemoveFeatureIfPresentOnSecondFeature) {
+  ASSERT_EQ(2UL, test_policy.size());
+  EXPECT_TRUE(IsFeatureDeclared(mojom::FeaturePolicyFeature::kGeolocation,
+                                test_policy));
+  EXPECT_TRUE(RemoveFeatureIfPresent(mojom::FeaturePolicyFeature::kGeolocation,
+                                     test_policy));
+  ASSERT_EQ(1UL, test_policy.size());
+  EXPECT_FALSE(IsFeatureDeclared(mojom::FeaturePolicyFeature::kGeolocation,
+                                 test_policy));
+
+  // Attempt to remove the feature again
+  EXPECT_FALSE(RemoveFeatureIfPresent(mojom::FeaturePolicyFeature::kGeolocation,
+                                      test_policy));
+  EXPECT_EQ(1UL, test_policy.size());
+  EXPECT_FALSE(IsFeatureDeclared(mojom::FeaturePolicyFeature::kGeolocation,
+                                 test_policy));
+}
+
+TEST_F(FeaturePolicyMutationTest, TestRemoveAllFeatures) {
+  ASSERT_EQ(2UL, test_policy.size());
+  EXPECT_TRUE(RemoveFeatureIfPresent(mojom::FeaturePolicyFeature::kFullscreen,
+                                     test_policy));
+  EXPECT_TRUE(RemoveFeatureIfPresent(mojom::FeaturePolicyFeature::kGeolocation,
+                                     test_policy));
+  EXPECT_EQ(0UL, test_policy.size());
+  EXPECT_FALSE(
+      IsFeatureDeclared(mojom::FeaturePolicyFeature::kFullscreen, test_policy));
+  EXPECT_FALSE(IsFeatureDeclared(mojom::FeaturePolicyFeature::kGeolocation,
+                                 test_policy));
+}
+
+TEST_F(FeaturePolicyMutationTest, TestDisallowIfNotPresent) {
+  ParsedFeaturePolicy copy = test_policy;
+  // Try to disallow a feature which already exists
+  EXPECT_FALSE(DisallowFeatureIfNotPresent(
+      mojom::FeaturePolicyFeature::kFullscreen, copy));
+  ASSERT_EQ(copy, test_policy);
+
+  // Disallow a new feature
+  EXPECT_TRUE(
+      DisallowFeatureIfNotPresent(mojom::FeaturePolicyFeature::kPayment, copy));
+  EXPECT_EQ(3UL, copy.size());
+  // Verify that the feature is, in fact, now disallowed everywhere
+  EXPECT_TRUE(IsFeatureDisallowedEverywhere(
+      mojom::FeaturePolicyFeature::kPayment, copy));
+}
+
+TEST_F(FeaturePolicyMutationTest, TestAllowEverywhereIfNotPresent) {
+  ParsedFeaturePolicy copy = test_policy;
+  // Try to allow a feature which already exists
+  EXPECT_FALSE(AllowFeatureEverywhereIfNotPresent(
+      mojom::FeaturePolicyFeature::kFullscreen, copy));
+  ASSERT_EQ(copy, test_policy);
+
+  // Allow a new feature
+  EXPECT_TRUE(AllowFeatureEverywhereIfNotPresent(
+      mojom::FeaturePolicyFeature::kPayment, copy));
+  EXPECT_EQ(3UL, copy.size());
+  // Verify that the feature is, in fact, allowed everywhere
+  EXPECT_TRUE(
+      IsFeatureAllowedEverywhere(mojom::FeaturePolicyFeature::kPayment, copy));
+}
+
+TEST_F(FeaturePolicyMutationTest, TestDisallowUnconditionally) {
+  // Try to disallow a feature which already exists
+  DisallowFeature(mojom::FeaturePolicyFeature::kFullscreen, test_policy);
+  // Should not have changed the number of declarations
+  EXPECT_EQ(2UL, test_policy.size());
+  // Verify that the feature is, in fact, now disallowed everywhere
+  EXPECT_TRUE(IsFeatureDisallowedEverywhere(
+      mojom::FeaturePolicyFeature::kFullscreen, test_policy));
+}
+
+TEST_F(FeaturePolicyMutationTest, TestDisallowNewFeatureUnconditionally) {
+  // Try to disallow a feature which does not yet exist
+  DisallowFeature(mojom::FeaturePolicyFeature::kPayment, test_policy);
+  // Should have added a new declaration
+  EXPECT_EQ(3UL, test_policy.size());
+  // Verify that the feature is, in fact, now disallowed everywhere
+  EXPECT_TRUE(IsFeatureDisallowedEverywhere(
+      mojom::FeaturePolicyFeature::kPayment, test_policy));
+}
+
+TEST_F(FeaturePolicyMutationTest, TestAllowUnconditionally) {
+  // Try to allow a feature which already exists
+  AllowFeatureEverywhere(mojom::FeaturePolicyFeature::kFullscreen, test_policy);
+  // Should not have changed the number of declarations
+  EXPECT_EQ(2UL, test_policy.size());
+  // Verify that the feature is, in fact, now allowed everywhere
+  EXPECT_TRUE(IsFeatureAllowedEverywhere(
+      mojom::FeaturePolicyFeature::kFullscreen, test_policy));
+}
+
+TEST_F(FeaturePolicyMutationTest, TestAllowNewFeatureUnconditionally) {
+  // Try to allow a feature which does not yet exist
+  AllowFeatureEverywhere(mojom::FeaturePolicyFeature::kPayment, test_policy);
+  // Should have added a new declaration
+  EXPECT_EQ(3UL, test_policy.size());
+  // Verify that the feature is, in fact, now allowed everywhere
+  EXPECT_TRUE(IsFeatureAllowedEverywhere(mojom::FeaturePolicyFeature::kPayment,
+                                         test_policy));
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/fonts/cursor_position_test.cc b/third_party/blink/renderer/platform/fonts/cursor_position_test.cc
deleted file mode 100644
index 2ffd9a8..0000000
--- a/third_party/blink/renderer/platform/fonts/cursor_position_test.cc
+++ /dev/null
@@ -1,457 +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 "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/platform/file_path_conversion.h"
-#include "third_party/blink/public/platform/web_string.h"
-#include "third_party/blink/renderer/platform/fonts/font.h"
-#include "third_party/blink/renderer/platform/fonts/font_description.h"
-#include "third_party/blink/renderer/platform/testing/font_test_helpers.h"
-#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
-
-using blink::test::CreateTestFont;
-
-namespace blink {
-
-class CursorPositionTest : public ::testing::Test {
- public:
-  enum FontName {
-    ahem,
-    amiri,
-    megalopolis,
-    roboto,
-  };
-
-  float GetWidth(FontName font_name,
-                 const String& text,
-                 bool ltr,
-                 int start = 0,
-                 int end = -1) {
-    FontDescription::VariantLigatures ligatures(
-        FontDescription::kEnabledLigaturesState);
-    Font font = CreateTestFont("TestFont",
-                               test::PlatformTestDataPath(font_path[font_name]),
-                               100, &ligatures);
-    TextRun text_run(
-        text, /* xpos */ 0, /* expansion */ 0,
-        TextRun::kAllowTrailingExpansion | TextRun::kForbidLeadingExpansion,
-        ltr ? TextDirection::kLtr : TextDirection::kRtl, false);
-
-    if (end == -1)
-      end = text_run.length();
-    DCHECK_GE(start, 0);
-    DCHECK_LE(start, static_cast<int>(text_run.length()));
-    DCHECK_GE(end, -1);
-    DCHECK_LE(end, static_cast<int>(text_run.length()));
-    FloatRect rect =
-        font.SelectionRectForText(text_run, FloatPoint(), 12, start, end);
-    return rect.Width();
-  }
-
-  int GetCharacter(FontName font_name,
-                   const String& text,
-                   bool ltr,
-                   float position,
-                   bool partial) {
-    FontDescription::VariantLigatures ligatures(
-        FontDescription::kEnabledLigaturesState);
-    Font font = CreateTestFont("TestFont",
-                               test::PlatformTestDataPath(font_path[font_name]),
-                               100, &ligatures);
-    TextRun text_run(
-        text, /* xpos */ 0, /* expansion */ 0,
-        TextRun::kAllowTrailingExpansion | TextRun::kForbidLeadingExpansion,
-        ltr ? TextDirection::kLtr : TextDirection::kRtl, false);
-
-    return font.OffsetForPosition(
-        text_run, position, partial ? IncludePartialGlyphs : OnlyFullGlyphs,
-        BreakGlyphs);
-  }
-
- private:
-  std::map<FontName, String> font_path = {
-      {ahem, "Ahem.woff"},
-      {amiri, "third_party/Amiri/amiri_arabic.woff2"},
-      {megalopolis, "third_party/MEgalopolis/MEgalopolisExtra.woff"},
-      {roboto, "third_party/Roboto/roboto-regular.woff2"},
-  };
-};
-
-TEST_F(CursorPositionTest, LTRMouse) {
-  EXPECT_EQ(GetCharacter(ahem, "X", true, 0, false), 0);
-  EXPECT_EQ(GetCharacter(ahem, "X", true, 0, true), 0);
-  EXPECT_EQ(GetCharacter(ahem, "X", true, 10, false), 0);
-  EXPECT_EQ(GetCharacter(ahem, "X", true, 10, true), 0);
-  EXPECT_EQ(GetCharacter(ahem, "X", true, 60, false), 0);
-  EXPECT_EQ(GetCharacter(ahem, "X", true, 60, true), 1);
-  EXPECT_EQ(GetCharacter(ahem, "X", true, 100, false), 1);
-  EXPECT_EQ(GetCharacter(ahem, "X", true, 100, true), 1);
-
-  EXPECT_EQ(GetCharacter(ahem, "XXX", true, 10, false), 0);
-  EXPECT_EQ(GetCharacter(ahem, "XXX", true, 10, true), 0);
-  EXPECT_EQ(GetCharacter(ahem, "XXX", true, 60, false), 0);
-  EXPECT_EQ(GetCharacter(ahem, "XXX", true, 60, true), 1);
-  EXPECT_EQ(GetCharacter(ahem, "XXX", true, 100, true), 1);
-  EXPECT_EQ(GetCharacter(ahem, "XXX", true, 100, false), 1);
-  EXPECT_EQ(GetCharacter(ahem, "XXX", true, 125, true), 1);
-  EXPECT_EQ(GetCharacter(ahem, "XXX", true, 125, true), 1);
-  EXPECT_EQ(GetCharacter(ahem, "XXX", true, 151, false), 1);
-  EXPECT_EQ(GetCharacter(ahem, "XXX", true, 151, true), 2);
-  EXPECT_EQ(GetCharacter(ahem, "XXX", true, 175, false), 1);
-  EXPECT_EQ(GetCharacter(ahem, "XXX", true, 175, true), 2);
-}
-
-TEST_F(CursorPositionTest, LTRLigatureMouse) {
-  const float kFUWidth = GetWidth(megalopolis, "FU", true);
-  const float kRAWidth = GetWidth(megalopolis, "RA", true);
-
-  EXPECT_EQ(GetCharacter(megalopolis, "FURA", true, kFUWidth / 4 - 1, false),
-            0);
-  EXPECT_EQ(GetCharacter(megalopolis, "FURA", true, kFUWidth / 4 - 1, true), 0);
-  EXPECT_EQ(GetCharacter(megalopolis, "FURA", true, kFUWidth / 4 + 1, false),
-            0);
-  EXPECT_EQ(GetCharacter(megalopolis, "FURA", true, kFUWidth / 4 + 1, true), 1);
-
-  EXPECT_EQ(GetCharacter(megalopolis, "FURA", true, kFUWidth / 2 - 1, false),
-            0);
-  EXPECT_EQ(GetCharacter(megalopolis, "FURA", true, kFUWidth / 2 - 1, true), 1);
-  EXPECT_EQ(GetCharacter(megalopolis, "FURA", true, kFUWidth / 2 + 1, false),
-            1);
-  EXPECT_EQ(GetCharacter(megalopolis, "FURA", true, kFUWidth / 2 + 1, true), 1);
-
-  EXPECT_EQ(
-      GetCharacter(megalopolis, "FURA", true, kFUWidth * 3 / 4 - 1, false), 1);
-  EXPECT_EQ(GetCharacter(megalopolis, "FURA", true, kFUWidth * 3 / 4 - 1, true),
-            1);
-  EXPECT_EQ(
-      GetCharacter(megalopolis, "FURA", true, kFUWidth * 3 / 4 + 1, false), 1);
-  EXPECT_EQ(GetCharacter(megalopolis, "FURA", true, kFUWidth * 3 / 4 + 1, true),
-            2);
-
-  EXPECT_EQ(GetCharacter(megalopolis, "FURA", true, kFUWidth - 1, false), 1);
-  EXPECT_EQ(GetCharacter(megalopolis, "FURA", true, kFUWidth - 1, true), 2);
-  EXPECT_EQ(GetCharacter(megalopolis, "FURA", true, kFUWidth + 1, false), 2);
-  EXPECT_EQ(GetCharacter(megalopolis, "FURA", true, kFUWidth + 1, true), 2);
-
-  EXPECT_EQ(GetCharacter(megalopolis, "FURA", true, kFUWidth + kRAWidth / 4 - 1,
-                         false),
-            2);
-  EXPECT_EQ(GetCharacter(megalopolis, "FURA", true, kFUWidth + kRAWidth / 4 - 1,
-                         true),
-            2);
-  EXPECT_EQ(GetCharacter(megalopolis, "FURA", true, kFUWidth + kRAWidth / 4 + 1,
-                         false),
-            2);
-  EXPECT_EQ(GetCharacter(megalopolis, "FURA", true, kFUWidth + kRAWidth / 4 + 1,
-                         true),
-            3);
-
-  EXPECT_EQ(GetCharacter(megalopolis, "FURA", true, kFUWidth + kRAWidth / 2 - 1,
-                         false),
-            2);
-  EXPECT_EQ(GetCharacter(megalopolis, "FURA", true, kFUWidth + kRAWidth / 2 - 1,
-                         true),
-            3);
-  EXPECT_EQ(GetCharacter(megalopolis, "FURA", true, kFUWidth + kRAWidth / 2 + 1,
-                         false),
-            3);
-  EXPECT_EQ(GetCharacter(megalopolis, "FURA", true, kFUWidth + kRAWidth / 2 + 1,
-                         true),
-            3);
-
-  EXPECT_EQ(GetCharacter(megalopolis, "FURA", true,
-                         kFUWidth + kRAWidth * 3 / 4 - 1, false),
-            3);
-  EXPECT_EQ(GetCharacter(megalopolis, "FURA", true,
-                         kFUWidth + kRAWidth * 3 / 4 - 1, true),
-            3);
-  EXPECT_EQ(GetCharacter(megalopolis, "FURA", true,
-                         kFUWidth + kRAWidth * 3 / 4 + 1, false),
-            3);
-  EXPECT_EQ(GetCharacter(megalopolis, "FURA", true,
-                         kFUWidth + kRAWidth * 3 / 4 + 1, true),
-            4);
-
-  EXPECT_EQ(
-      GetCharacter(megalopolis, "FURA", true, kFUWidth + kRAWidth - 1, false),
-      3);
-  EXPECT_EQ(
-      GetCharacter(megalopolis, "FURA", true, kFUWidth + kRAWidth - 1, true),
-      4);
-  EXPECT_EQ(
-      GetCharacter(megalopolis, "FURA", true, kFUWidth + kRAWidth + 1, false),
-      4);
-  EXPECT_EQ(
-      GetCharacter(megalopolis, "FURA", true, kFUWidth + kRAWidth + 1, true),
-      4);
-}
-
-TEST_F(CursorPositionTest, RTLMouse) {
-  // The widths below are from the final shaped version, not from the single
-  // characters. They were extracted with "hb-shape --font-size=100"
-
-  EXPECT_EQ(GetCharacter(ahem, "X", false, 0, false), 1);
-  EXPECT_EQ(GetCharacter(ahem, "X", false, 0, true), 1);
-  EXPECT_EQ(GetCharacter(ahem, "X", false, 10, false), 0);
-  EXPECT_EQ(GetCharacter(ahem, "X", false, 10, true), 1);
-  EXPECT_EQ(GetCharacter(ahem, "X", false, 49, false), 0);
-  EXPECT_EQ(GetCharacter(ahem, "X", false, 49, true), 1);
-  EXPECT_EQ(GetCharacter(ahem, "X", false, 51, false), 0);
-  EXPECT_EQ(GetCharacter(ahem, "X", false, 51, true), 0);
-  EXPECT_EQ(GetCharacter(ahem, "X", false, 60, false), 0);
-  EXPECT_EQ(GetCharacter(ahem, "X", false, 60, true), 0);
-  EXPECT_EQ(GetCharacter(ahem, "X", false, 100, false), 0);
-  EXPECT_EQ(GetCharacter(ahem, "X", false, 100, true), 0);
-
-  const float kAloneTaWidth = GetWidth(amiri, u"ت", false);
-  EXPECT_EQ(GetCharacter(amiri, u"ت", false, 0, false), 1);
-  EXPECT_EQ(GetCharacter(amiri, u"ت", false, 0, true), 1);
-  EXPECT_EQ(GetCharacter(amiri, u"ت", false, kAloneTaWidth / 4, false), 0);
-  EXPECT_EQ(GetCharacter(amiri, u"ت", false, kAloneTaWidth / 4, true), 1);
-  EXPECT_EQ(GetCharacter(amiri, u"ت", false, kAloneTaWidth * 2 / 3, false), 0);
-  EXPECT_EQ(GetCharacter(amiri, u"ت", false, kAloneTaWidth * 2 / 3, true), 0);
-  EXPECT_EQ(GetCharacter(amiri, u"ت", false, 2 * kAloneTaWidth, false), 0);
-  EXPECT_EQ(GetCharacter(amiri, u"ت", false, 2 * kAloneTaWidth, true), 0);
-
-  const float kAboveTaWidth = 10;
-  const float kAboveKhaWidth = 55;
-  EXPECT_EQ(GetCharacter(amiri, u"تخ", false, 0, false), 2);
-  EXPECT_EQ(GetCharacter(amiri, u"تخ", false, 0, true), 2);
-  EXPECT_EQ(GetCharacter(amiri, u"تخ", false, kAboveTaWidth / 4, false), 1);
-  EXPECT_EQ(GetCharacter(amiri, u"تخ", false, kAboveTaWidth / 4, true), 2);
-  EXPECT_EQ(GetCharacter(amiri, u"تخ", false, kAboveTaWidth * 2 / 3, false), 1);
-  EXPECT_EQ(GetCharacter(amiri, u"تخ", false, kAboveTaWidth * 2 / 3, true), 1);
-  EXPECT_EQ(GetCharacter(amiri, u"تخ", false, kAboveTaWidth + 1, false), 0);
-  EXPECT_EQ(GetCharacter(amiri, u"تخ", false, kAboveTaWidth + 1, true), 1);
-  EXPECT_EQ(GetCharacter(amiri, u"تخ", false,
-                         kAboveTaWidth + kAboveKhaWidth / 4, false),
-            0);
-  EXPECT_EQ(GetCharacter(amiri, u"تخ", false,
-                         kAboveTaWidth + kAboveKhaWidth / 4, true),
-            1);
-  EXPECT_EQ(GetCharacter(amiri, u"تخ", false,
-                         kAboveTaWidth + kAboveKhaWidth * 2 / 3, false),
-            0);
-  EXPECT_EQ(GetCharacter(amiri, u"تخ", false,
-                         kAboveTaWidth + kAboveKhaWidth * 2 / 3, true),
-            0);
-  EXPECT_EQ(GetCharacter(amiri, u"تخ", false,
-                         kAboveTaWidth + kAboveKhaWidth + 1, false),
-            0);
-  EXPECT_EQ(GetCharacter(amiri, u"تخ", false,
-                         kAboveTaWidth + kAboveKhaWidth + 1, true),
-            0);
-  EXPECT_EQ(GetCharacter(amiri, u"تخ", false,
-                         2 * (kAboveTaWidth + kAboveKhaWidth), false),
-            0);
-  EXPECT_EQ(GetCharacter(amiri, u"تخ", false,
-                         2 * (kAboveTaWidth + kAboveKhaWidth), true),
-            0);
-}
-
-TEST_F(CursorPositionTest, RTLLigatureMouse) {
-  const float kFUWidth = GetWidth(megalopolis, "FU", true);
-  const float kRAWidth = GetWidth(megalopolis, "RA", true);
-
-  EXPECT_EQ(GetCharacter(megalopolis, "ARUF", false, kFUWidth / 4 - 1, false),
-            3);
-  EXPECT_EQ(GetCharacter(megalopolis, "ARUF", false, kFUWidth / 4 - 1, true),
-            4);
-  EXPECT_EQ(GetCharacter(megalopolis, "ARUF", false, kFUWidth / 4 + 1, false),
-            3);
-  EXPECT_EQ(GetCharacter(megalopolis, "ARUF", false, kFUWidth / 4 + 1, true),
-            3);
-
-  EXPECT_EQ(GetCharacter(megalopolis, "ARUF", false, kFUWidth / 2 - 1, false),
-            3);
-  EXPECT_EQ(GetCharacter(megalopolis, "ARUF", false, kFUWidth / 2 - 1, true),
-            3);
-  EXPECT_EQ(GetCharacter(megalopolis, "ARUF", false, kFUWidth / 2 + 1, false),
-            2);
-  EXPECT_EQ(GetCharacter(megalopolis, "ARUF", false, kFUWidth / 2 + 1, true),
-            3);
-
-  EXPECT_EQ(
-      GetCharacter(megalopolis, "ARUF", false, kFUWidth * 3 / 4 - 1, false), 2);
-  EXPECT_EQ(
-      GetCharacter(megalopolis, "ARUF", false, kFUWidth * 3 / 4 - 1, true), 3);
-  EXPECT_EQ(
-      GetCharacter(megalopolis, "ARUF", false, kFUWidth * 3 / 4 + 1, false), 2);
-  EXPECT_EQ(
-      GetCharacter(megalopolis, "ARUF", false, kFUWidth * 3 / 4 + 1, true), 2);
-
-  EXPECT_EQ(GetCharacter(megalopolis, "ARUF", false, kFUWidth - 1, false), 2);
-  EXPECT_EQ(GetCharacter(megalopolis, "ARUF", false, kFUWidth - 1, true), 2);
-  EXPECT_EQ(GetCharacter(megalopolis, "ARUF", false, kFUWidth + 1, false), 1);
-  EXPECT_EQ(GetCharacter(megalopolis, "ARUF", false, kFUWidth + 1, true), 2);
-
-  EXPECT_EQ(GetCharacter(megalopolis, "ARUF", false,
-                         kFUWidth + kRAWidth / 4 - 1, false),
-            1);
-  EXPECT_EQ(GetCharacter(megalopolis, "ARUF", false,
-                         kFUWidth + kRAWidth / 4 - 1, true),
-            2);
-  EXPECT_EQ(GetCharacter(megalopolis, "ARUF", false,
-                         kFUWidth + kRAWidth / 4 + 1, false),
-            1);
-  EXPECT_EQ(GetCharacter(megalopolis, "ARUF", false,
-                         kFUWidth + kRAWidth / 4 + 1, true),
-            1);
-
-  EXPECT_EQ(GetCharacter(megalopolis, "ARUF", false,
-                         kFUWidth + kRAWidth / 2 - 1, false),
-            1);
-  EXPECT_EQ(GetCharacter(megalopolis, "ARUF", false,
-                         kFUWidth + kRAWidth / 2 - 1, true),
-            1);
-  EXPECT_EQ(GetCharacter(megalopolis, "ARUF", false,
-                         kFUWidth + kRAWidth / 2 + 1, false),
-            0);
-  EXPECT_EQ(GetCharacter(megalopolis, "ARUF", false,
-                         kFUWidth + kRAWidth / 2 + 1, true),
-            1);
-
-  EXPECT_EQ(GetCharacter(megalopolis, "ARUF", false,
-                         kFUWidth + kRAWidth * 3 / 4 - 1, false),
-            0);
-  EXPECT_EQ(GetCharacter(megalopolis, "ARUF", false,
-                         kFUWidth + kRAWidth * 3 / 4 - 1, true),
-            1);
-  EXPECT_EQ(GetCharacter(megalopolis, "ARUF", false,
-                         kFUWidth + kRAWidth * 3 / 4 + 1, false),
-            0);
-  EXPECT_EQ(GetCharacter(megalopolis, "ARUF", false,
-                         kFUWidth + kRAWidth * 3 / 4 + 1, true),
-            0);
-
-  EXPECT_EQ(
-      GetCharacter(megalopolis, "ARUF", false, kFUWidth + kRAWidth - 1, false),
-      0);
-  EXPECT_EQ(
-      GetCharacter(megalopolis, "ARUF", false, kFUWidth + kRAWidth - 1, true),
-      0);
-  EXPECT_EQ(
-      GetCharacter(megalopolis, "ARUF", false, kFUWidth + kRAWidth + 1, false),
-      0);
-  EXPECT_EQ(
-      GetCharacter(megalopolis, "ARUF", false, kFUWidth + kRAWidth + 1, true),
-      0);
-}
-
-TEST_F(CursorPositionTest, LTRText) {
-  EXPECT_EQ(GetWidth(ahem, "X", true, 0, 1), 100);
-
-  EXPECT_EQ(GetWidth(ahem, "XXX", true, 0, 1), 100);
-  EXPECT_EQ(GetWidth(ahem, "XXX", true, 0, 2), 200);
-  EXPECT_EQ(GetWidth(ahem, "XXX", true, 0, 3), 300);
-  EXPECT_EQ(GetWidth(ahem, "XXX", true, 1, 2), 100);
-  EXPECT_EQ(GetWidth(ahem, "XXX", true, 1, 3), 200);
-  EXPECT_EQ(GetWidth(ahem, "XXX", true, 2, 3), 100);
-}
-
-TEST_F(CursorPositionTest, LTRLigature) {
-  const float kFUWidth = GetWidth(megalopolis, "FU", true);
-  const float kRAWidth = GetWidth(megalopolis, "RA", true);
-
-  EXPECT_NEAR(GetWidth(megalopolis, "FURA", true, 0, 1), kFUWidth / 2, 1.0);
-  EXPECT_NEAR(GetWidth(megalopolis, "FURA", true, 0, 2), kFUWidth, 1.0);
-  EXPECT_NEAR(GetWidth(megalopolis, "FURA", true, 0, 3),
-              kFUWidth + kRAWidth / 2, 1.0);
-  EXPECT_NEAR(GetWidth(megalopolis, "FURA", true, 0, 4), kFUWidth + kRAWidth,
-              1.0);
-
-  EXPECT_NEAR(GetWidth(megalopolis, "FURA", true, 1, 2), kFUWidth / 2, 1.0);
-  EXPECT_NEAR(GetWidth(megalopolis, "FURA", true, 1, 3),
-              kFUWidth / 2 + kRAWidth / 2, 1.0);
-  EXPECT_NEAR(GetWidth(megalopolis, "FURA", true, 1, 4),
-              kFUWidth / 2 + kRAWidth, 1.0);
-
-  EXPECT_NEAR(GetWidth(megalopolis, "FURA", true, 2, 3), kRAWidth / 2, 1.0);
-  EXPECT_NEAR(GetWidth(megalopolis, "FURA", true, 2, 4), kRAWidth, 1.0);
-
-  EXPECT_NEAR(GetWidth(megalopolis, "FURA", true, 3, 4), kRAWidth / 2, 1.0);
-
-  const float kFFIWidth = GetWidth(roboto, "ffi", true);
-  const float kFFWidth = GetWidth(roboto, "ff", true);
-  const float kIWidth = GetWidth(roboto, u"î", true);
-
-  EXPECT_NEAR(GetWidth(roboto, "ffi", true, 0, 1), kFFIWidth / 3.0, 1.0);
-  EXPECT_NEAR(GetWidth(roboto, "ffi", true, 0, 2), kFFIWidth * 2.0 / 3.0, 1.0);
-  EXPECT_NEAR(GetWidth(roboto, "ffi", true, 0, 3), kFFIWidth, 1.0);
-  EXPECT_NEAR(GetWidth(roboto, "ffi", true, 1, 2), kFFIWidth / 3.0, 1.0);
-  EXPECT_NEAR(GetWidth(roboto, "ffi", true, 1, 3), kFFIWidth * 2.0 / 3.0, 1.0);
-  EXPECT_NEAR(GetWidth(roboto, "ffi", true, 2, 3), kFFIWidth / 3.0, 1.0);
-
-  EXPECT_NEAR(GetWidth(roboto, u"ffî", true, 0, 1), kFFWidth / 2.0, 1.0);
-  EXPECT_NEAR(GetWidth(roboto, u"ffî", true, 0, 2), kFFWidth, 1.0);
-  EXPECT_NEAR(GetWidth(roboto, u"ffî", true, 0, 3), kFFWidth + kIWidth, 1.0);
-  EXPECT_NEAR(GetWidth(roboto, u"ffî", true, 1, 2), kFFWidth / 2.0, 1.0);
-  EXPECT_NEAR(GetWidth(roboto, u"ffî", true, 1, 3), kFFWidth / 2.0 + kIWidth,
-              1.0);
-  EXPECT_NEAR(GetWidth(roboto, u"ffî", true, 2, 3), kIWidth, 1.0);
-}
-
-TEST_F(CursorPositionTest, RTLText) {
-  // The widths below are from the final shaped version, not from the single
-  // characters. They were extracted with "hb-shape --font-size=100"
-
-  EXPECT_EQ(GetWidth(amiri, u"ت", false, 0, 1), 93);
-
-  const float kAboveKhaWidth = 55;
-  const float kAboveTaWidth = 10;
-  EXPECT_NEAR(GetWidth(amiri, u"تخ", false, 0, 1), kAboveKhaWidth, 1.0);
-  EXPECT_NEAR(GetWidth(amiri, u"تخ", false, 0, 2),
-              kAboveKhaWidth + kAboveTaWidth, 1.0);
-  EXPECT_NEAR(GetWidth(amiri, u"تخ", false, 1, 2), kAboveTaWidth, 1.0);
-
-  const float kTaWidth = 75;
-  const float kKhaWidth = 7;
-  const float kLamWidth = 56;
-  const float kAlifWidth = 22;
-  EXPECT_NEAR(GetWidth(amiri, u"الخط", false, 0, 1), kAlifWidth, 1.0);
-  EXPECT_NEAR(GetWidth(amiri, u"الخط", false, 0, 2), kAlifWidth + kLamWidth,
-              1.0);
-  EXPECT_NEAR(GetWidth(amiri, u"الخط", false, 0, 3),
-              kAlifWidth + kLamWidth + kKhaWidth, 1.0);
-  EXPECT_NEAR(GetWidth(amiri, u"الخط", false, 0, 4),
-              kAlifWidth + kLamWidth + kKhaWidth + kTaWidth, 1.0);
-  EXPECT_NEAR(GetWidth(amiri, u"الخط", false, 1, 2), kLamWidth, 1.0);
-  EXPECT_NEAR(GetWidth(amiri, u"الخط", false, 1, 3), kLamWidth + kKhaWidth,
-              1.0);
-  EXPECT_NEAR(GetWidth(amiri, u"الخط", false, 1, 4),
-              kLamWidth + kKhaWidth + kTaWidth, 1.0);
-  EXPECT_NEAR(GetWidth(amiri, u"الخط", false, 2, 3), kKhaWidth, 1.0);
-  EXPECT_NEAR(GetWidth(amiri, u"الخط", false, 2, 4), kKhaWidth + kTaWidth, 1.0);
-  EXPECT_NEAR(GetWidth(amiri, u"الخط", false, 3, 4), kTaWidth, 1.0);
-
-  const float kMeemWidth = GetWidth(amiri, u"Ù…", false);
-  EXPECT_EQ(GetWidth(amiri, u"Ù…ÙŽ", false, 0, 1), kMeemWidth);
-  EXPECT_EQ(GetWidth(amiri, u"Ù…ÙŽ", false, 0, 2), kMeemWidth);
-  EXPECT_EQ(GetWidth(amiri, u"Ù…ÙŽ", false, 1, 2), kMeemWidth);
-}
-
-TEST_F(CursorPositionTest, RTLLigature) {
-  const float kFUWidth = GetWidth(megalopolis, "FU", true);
-  const float kRAWidth = GetWidth(megalopolis, "RA", true);
-
-  EXPECT_NEAR(GetWidth(megalopolis, "ARUF", false, 0, 1), kRAWidth / 2, 1.0);
-  EXPECT_NEAR(GetWidth(megalopolis, "ARUF", false, 0, 2), kRAWidth, 1.0);
-  EXPECT_NEAR(GetWidth(megalopolis, "ARUF", false, 0, 3),
-              kRAWidth + kFUWidth / 2, 1.0);
-  EXPECT_NEAR(GetWidth(megalopolis, "ARUF", false, 0, 4), kRAWidth + kFUWidth,
-              1.0);
-
-  EXPECT_NEAR(GetWidth(megalopolis, "ARUF", false, 1, 2), kRAWidth / 2, 1.0);
-  EXPECT_NEAR(GetWidth(megalopolis, "ARUF", false, 1, 3),
-              kRAWidth / 2 + kFUWidth / 2, 1.0);
-  EXPECT_NEAR(GetWidth(megalopolis, "ARUF", false, 1, 4),
-              kRAWidth / 2 + kFUWidth, 1.0);
-
-  EXPECT_NEAR(GetWidth(megalopolis, "ARUF", false, 2, 3), kFUWidth / 2, 1.0);
-  EXPECT_NEAR(GetWidth(megalopolis, "ARUF", false, 2, 4), kFUWidth, 1.0);
-
-  EXPECT_NEAR(GetWidth(megalopolis, "ARUF", false, 3, 4), kFUWidth / 2, 1.0);
-}
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/platform/fonts/font.cc b/third_party/blink/renderer/platform/fonts/font.cc
index 140c9e34..6c1378c 100644
--- a/third_party/blink/renderer/platform/fonts/font.cc
+++ b/third_party/blink/renderer/platform/fonts/font.cc
@@ -390,11 +390,10 @@
 
 int Font::OffsetForPosition(const TextRun& run,
                             float x_float,
-                            IncludePartialGlyphsOption partial_glyphs,
-                            BreakGlyphsOption break_glyphs) const {
+                            bool include_partial_glyphs) const {
   FontCachePurgePreventer purge_preventer;
   CachingWordShaper shaper(*this);
-  return shaper.OffsetForPosition(run, x_float, partial_glyphs, break_glyphs);
+  return shaper.OffsetForPosition(run, x_float, include_partial_glyphs);
 }
 
 ShapeCache* Font::GetShapeCache() const {
diff --git a/third_party/blink/renderer/platform/fonts/font.h b/third_party/blink/renderer/platform/fonts/font.h
index de3a27c..d2fad11 100644
--- a/third_party/blink/renderer/platform/fonts/font.h
+++ b/third_party/blink/renderer/platform/fonts/font.h
@@ -143,8 +143,7 @@
 
   int OffsetForPosition(const TextRun&,
                         float position,
-                        IncludePartialGlyphsOption,
-                        BreakGlyphsOption) const;
+                        bool include_partial_glyphs) const;
   FloatRect SelectionRectForText(const TextRun&,
                                  const FloatPoint&,
                                  int h,
diff --git a/third_party/blink/renderer/platform/fonts/shaping/caching_word_shaper.cc b/third_party/blink/renderer/platform/fonts/shaping/caching_word_shaper.cc
index 41f5fa9c..0006c16d 100644
--- a/third_party/blink/renderer/platform/fonts/shaping/caching_word_shaper.cc
+++ b/third_party/blink/renderer/platform/fonts/shaping/caching_word_shaper.cc
@@ -80,15 +80,13 @@
   return total_width;
 }
 
-int CachingWordShaper::OffsetForPosition(
-    const TextRun& run,
-    float target_x,
-    IncludePartialGlyphsOption partial_glyphs,
-    BreakGlyphsOption break_glyphs) {
+int CachingWordShaper::OffsetForPosition(const TextRun& run,
+                                         float target_x,
+                                         bool include_partial_glyphs) {
   ShapeResultBuffer buffer;
   ShapeResultsForRun(GetShapeCache(), &font_, run, &buffer);
 
-  return buffer.OffsetForPosition(run, target_x, partial_glyphs, break_glyphs);
+  return buffer.OffsetForPosition(run, target_x, include_partial_glyphs);
 }
 
 void CachingWordShaper::FillResultBuffer(const TextRunPaintInfo& run_info,
@@ -103,7 +101,7 @@
   ShapeResultBuffer buffer;
   float total_width = ShapeResultsForRun(GetShapeCache(), &font_, run, &buffer);
 
-  return buffer.GetCharacterRange(total_width, run.Direction(), from, to);
+  return buffer.GetCharacterRange(run.Direction(), total_width, from, to);
 }
 
 Vector<CharacterRange> CachingWordShaper::IndividualCharacterRanges(
diff --git a/third_party/blink/renderer/platform/fonts/shaping/caching_word_shaper.h b/third_party/blink/renderer/platform/fonts/shaping/caching_word_shaper.h
index 1adfe22..ab719be 100644
--- a/third_party/blink/renderer/platform/fonts/shaping/caching_word_shaper.h
+++ b/third_party/blink/renderer/platform/fonts/shaping/caching_word_shaper.h
@@ -55,8 +55,7 @@
               FloatRect* glyph_bounds);
   int OffsetForPosition(const TextRun&,
                         float target_x,
-                        IncludePartialGlyphsOption,
-                        BreakGlyphsOption);
+                        bool include_partial_glyphs);
 
   void FillResultBuffer(const TextRunPaintInfo&, ShapeResultBuffer*);
   CharacterRange GetCharacterRange(const TextRun&, unsigned from, unsigned to);
diff --git a/third_party/blink/renderer/platform/fonts/shaping/harf_buzz_shaper.cc b/third_party/blink/renderer/platform/fonts/shaping/harf_buzz_shaper.cc
index f9e4c5c..0a23914 100644
--- a/third_party/blink/renderer/platform/fonts/shaping/harf_buzz_shaper.cc
+++ b/third_party/blink/renderer/platform/fonts/shaping/harf_buzz_shaper.cc
@@ -48,7 +48,6 @@
 #include "third_party/blink/renderer/platform/fonts/shaping/shape_result_inline_headers.h"
 #include "third_party/blink/renderer/platform/fonts/small_caps_iterator.h"
 #include "third_party/blink/renderer/platform/fonts/utf16_text_iterator.h"
-#include "third_party/blink/renderer/platform/text/text_break_iterator.h"
 #include "third_party/blink/renderer/platform/wtf/compiler.h"
 #include "third_party/blink/renderer/platform/wtf/deque.h"
 #include "third_party/blink/renderer/platform/wtf/math_extras.h"
@@ -338,13 +337,10 @@
   // Here we need to specify glyph positions.
   BufferSlice next_slice;
   for (const BufferSlice* current_slice = &slice;;) {
-    Vector<unsigned> graphemes;
-    GraphemesClusterList(text_, current_slice->start_character_index,
-                         current_slice->num_characters, &graphemes);
     ShapeResult::RunInfo* run = new ShapeResult::RunInfo(
         current_font, direction, canvas_rotation, script,
         current_slice->start_character_index, current_slice->num_glyphs,
-        current_slice->num_characters, graphemes);
+        current_slice->num_characters);
     shape_result->InsertRun(base::WrapUnique(run),
                             current_slice->start_glyph_index,
                             current_slice->num_glyphs, range_data->buffer);
diff --git a/third_party/blink/renderer/platform/fonts/shaping/harf_buzz_shaper_test.cc b/third_party/blink/renderer/platform/fonts/shaping/harf_buzz_shaper_test.cc
index 33f63fd..bd338bf0 100644
--- a/third_party/blink/renderer/platform/fonts/shaping/harf_buzz_shaper_test.cc
+++ b/third_party/blink/renderer/platform/fonts/shaping/harf_buzz_shaper_test.cc
@@ -673,24 +673,16 @@
   Font ahem = CreateAhem(10);
   scoped_refptr<ShapeResult> result =
       SplitRun(shaper.Shape(&ahem, TextDirection::kLtr), 2);
-  EXPECT_EQ(data.offset_ltr,
-            result->OffsetForPosition(data.position, OnlyFullGlyphs,
-                                      DontBreakGlyphs));
-  EXPECT_EQ(data.hit_test_ltr,
-            result->OffsetForPosition(data.position, IncludePartialGlyphs,
-                                      DontBreakGlyphs));
+  EXPECT_EQ(data.offset_ltr, result->OffsetForPosition(data.position, false));
+  EXPECT_EQ(data.hit_test_ltr, result->OffsetForPosition(data.position, true));
   EXPECT_EQ(data.fit_ltr_ltr,
             result->OffsetToFit(data.position, TextDirection::kLtr));
   EXPECT_EQ(data.fit_ltr_rtl,
             result->OffsetToFit(data.position, TextDirection::kRtl));
 
   result = SplitRun(shaper.Shape(&ahem, TextDirection::kRtl), 3);
-  EXPECT_EQ(data.offset_rtl,
-            result->OffsetForPosition(data.position, OnlyFullGlyphs,
-                                      DontBreakGlyphs));
-  EXPECT_EQ(data.hit_test_rtl,
-            result->OffsetForPosition(data.position, IncludePartialGlyphs,
-                                      DontBreakGlyphs));
+  EXPECT_EQ(data.offset_rtl, result->OffsetForPosition(data.position, false));
+  EXPECT_EQ(data.hit_test_rtl, result->OffsetForPosition(data.position, true));
   EXPECT_EQ(data.fit_rtl_ltr,
             result->OffsetToFit(data.position, TextDirection::kLtr));
   EXPECT_EQ(data.fit_rtl_rtl,
@@ -736,15 +728,14 @@
 
 // A Value-Parameterized Test class to test OffsetForPosition() with
 // |include_partial_glyphs| parameter.
-class IncludePartialGlyphsTest : public HarfBuzzShaperTest,
-                                 public ::testing::WithParamInterface<bool> {};
+class IncludePartialGlyphs : public HarfBuzzShaperTest,
+                             public testing::WithParamInterface<bool> {};
 
 INSTANTIATE_TEST_CASE_P(OffsetForPositionTest,
-                        IncludePartialGlyphsTest,
-                        ::testing::Bool());
+                        IncludePartialGlyphs,
+                        testing::Bool());
 
-TEST_P(IncludePartialGlyphsTest,
-       OffsetForPositionMatchesPositionForOffsetLatin) {
+TEST_P(IncludePartialGlyphs, OffsetForPositionMatchesPositionForOffsetLatin) {
   String string = To16Bit("Hello World!", 12);
   TextDirection direction = TextDirection::kLtr;
 
@@ -752,39 +743,35 @@
   scoped_refptr<ShapeResult> result = shaper.Shape(&font, direction);
 
   bool include_partial_glyphs = GetParam();
-  IncludePartialGlyphsOption partial =
-      include_partial_glyphs ? IncludePartialGlyphs : OnlyFullGlyphs;
-
-  EXPECT_EQ(0u, result->OffsetForPosition(result->PositionForOffset(0), partial,
-                                          DontBreakGlyphs));
-  EXPECT_EQ(1u, result->OffsetForPosition(result->PositionForOffset(1), partial,
-                                          DontBreakGlyphs));
-  EXPECT_EQ(2u, result->OffsetForPosition(result->PositionForOffset(2), partial,
-                                          DontBreakGlyphs));
-  EXPECT_EQ(3u, result->OffsetForPosition(result->PositionForOffset(3), partial,
-                                          DontBreakGlyphs));
-  EXPECT_EQ(4u, result->OffsetForPosition(result->PositionForOffset(4), partial,
-                                          DontBreakGlyphs));
-  EXPECT_EQ(5u, result->OffsetForPosition(result->PositionForOffset(5), partial,
-                                          DontBreakGlyphs));
-  EXPECT_EQ(6u, result->OffsetForPosition(result->PositionForOffset(6), partial,
-                                          DontBreakGlyphs));
-  EXPECT_EQ(7u, result->OffsetForPosition(result->PositionForOffset(7), partial,
-                                          DontBreakGlyphs));
-  EXPECT_EQ(8u, result->OffsetForPosition(result->PositionForOffset(8), partial,
-                                          DontBreakGlyphs));
-  EXPECT_EQ(9u, result->OffsetForPosition(result->PositionForOffset(9), partial,
-                                          DontBreakGlyphs));
+  EXPECT_EQ(0u, result->OffsetForPosition(result->PositionForOffset(0),
+                                          include_partial_glyphs));
+  EXPECT_EQ(1u, result->OffsetForPosition(result->PositionForOffset(1),
+                                          include_partial_glyphs));
+  EXPECT_EQ(2u, result->OffsetForPosition(result->PositionForOffset(2),
+                                          include_partial_glyphs));
+  EXPECT_EQ(3u, result->OffsetForPosition(result->PositionForOffset(3),
+                                          include_partial_glyphs));
+  EXPECT_EQ(4u, result->OffsetForPosition(result->PositionForOffset(4),
+                                          include_partial_glyphs));
+  EXPECT_EQ(5u, result->OffsetForPosition(result->PositionForOffset(5),
+                                          include_partial_glyphs));
+  EXPECT_EQ(6u, result->OffsetForPosition(result->PositionForOffset(6),
+                                          include_partial_glyphs));
+  EXPECT_EQ(7u, result->OffsetForPosition(result->PositionForOffset(7),
+                                          include_partial_glyphs));
+  EXPECT_EQ(8u, result->OffsetForPosition(result->PositionForOffset(8),
+                                          include_partial_glyphs));
+  EXPECT_EQ(9u, result->OffsetForPosition(result->PositionForOffset(9),
+                                          include_partial_glyphs));
   EXPECT_EQ(10u, result->OffsetForPosition(result->PositionForOffset(10),
-                                           partial, DontBreakGlyphs));
+                                           include_partial_glyphs));
   EXPECT_EQ(11u, result->OffsetForPosition(result->PositionForOffset(11),
-                                           partial, DontBreakGlyphs));
+                                           include_partial_glyphs));
   EXPECT_EQ(12u, result->OffsetForPosition(result->PositionForOffset(12),
-                                           partial, DontBreakGlyphs));
+                                           include_partial_glyphs));
 }
 
-TEST_P(IncludePartialGlyphsTest,
-       OffsetForPositionMatchesPositionForOffsetArabic) {
+TEST_P(IncludePartialGlyphs, OffsetForPositionMatchesPositionForOffsetArabic) {
   UChar arabic_string[] = {0x628, 0x64A, 0x629};
   TextDirection direction = TextDirection::kRtl;
 
@@ -792,43 +779,36 @@
   scoped_refptr<ShapeResult> result = shaper.Shape(&font, direction);
 
   bool include_partial_glyphs = GetParam();
-  IncludePartialGlyphsOption partial =
-      include_partial_glyphs ? IncludePartialGlyphs : OnlyFullGlyphs;
-
-  EXPECT_EQ(0u, result->OffsetForPosition(result->PositionForOffset(0), partial,
-                                          DontBreakGlyphs));
-  EXPECT_EQ(1u, result->OffsetForPosition(result->PositionForOffset(1), partial,
-                                          DontBreakGlyphs));
-  EXPECT_EQ(2u, result->OffsetForPosition(result->PositionForOffset(2), partial,
-                                          DontBreakGlyphs));
-  EXPECT_EQ(3u, result->OffsetForPosition(result->PositionForOffset(3), partial,
-                                          DontBreakGlyphs));
+  EXPECT_EQ(0u, result->OffsetForPosition(result->PositionForOffset(0),
+                                          include_partial_glyphs));
+  EXPECT_EQ(1u, result->OffsetForPosition(result->PositionForOffset(1),
+                                          include_partial_glyphs));
+  EXPECT_EQ(2u, result->OffsetForPosition(result->PositionForOffset(2),
+                                          include_partial_glyphs));
+  EXPECT_EQ(3u, result->OffsetForPosition(result->PositionForOffset(3),
+                                          include_partial_glyphs));
 }
 
-TEST_P(IncludePartialGlyphsTest,
-       OffsetForPositionMatchesPositionForOffsetMixed) {
+TEST_P(IncludePartialGlyphs, OffsetForPositionMatchesPositionForOffsetMixed) {
   UChar mixed_string[] = {0x628, 0x64A, 0x629, 0xE20, 0x65E5, 0x62};
   HarfBuzzShaper shaper(String(mixed_string, 6));
   scoped_refptr<ShapeResult> result = shaper.Shape(&font, TextDirection::kLtr);
 
   bool include_partial_glyphs = GetParam();
-  IncludePartialGlyphsOption partial =
-      include_partial_glyphs ? IncludePartialGlyphs : OnlyFullGlyphs;
-
-  EXPECT_EQ(0u, result->OffsetForPosition(result->PositionForOffset(0), partial,
-                                          DontBreakGlyphs));
-  EXPECT_EQ(1u, result->OffsetForPosition(result->PositionForOffset(1), partial,
-                                          DontBreakGlyphs));
-  EXPECT_EQ(2u, result->OffsetForPosition(result->PositionForOffset(2), partial,
-                                          DontBreakGlyphs));
-  EXPECT_EQ(3u, result->OffsetForPosition(result->PositionForOffset(3), partial,
-                                          DontBreakGlyphs));
-  EXPECT_EQ(4u, result->OffsetForPosition(result->PositionForOffset(4), partial,
-                                          DontBreakGlyphs));
-  EXPECT_EQ(5u, result->OffsetForPosition(result->PositionForOffset(5), partial,
-                                          DontBreakGlyphs));
-  EXPECT_EQ(6u, result->OffsetForPosition(result->PositionForOffset(6), partial,
-                                          DontBreakGlyphs));
+  EXPECT_EQ(0u, result->OffsetForPosition(result->PositionForOffset(0),
+                                          include_partial_glyphs));
+  EXPECT_EQ(1u, result->OffsetForPosition(result->PositionForOffset(1),
+                                          include_partial_glyphs));
+  EXPECT_EQ(2u, result->OffsetForPosition(result->PositionForOffset(2),
+                                          include_partial_glyphs));
+  EXPECT_EQ(3u, result->OffsetForPosition(result->PositionForOffset(3),
+                                          include_partial_glyphs));
+  EXPECT_EQ(4u, result->OffsetForPosition(result->PositionForOffset(4),
+                                          include_partial_glyphs));
+  EXPECT_EQ(5u, result->OffsetForPosition(result->PositionForOffset(5),
+                                          include_partial_glyphs));
+  EXPECT_EQ(6u, result->OffsetForPosition(result->PositionForOffset(6),
+                                          include_partial_glyphs));
 }
 
 TEST_F(HarfBuzzShaperTest, CachedOffsetPositionMappingForOffsetLatin) {
diff --git a/third_party/blink/renderer/platform/fonts/shaping/shape_result.cc b/third_party/blink/renderer/platform/fonts/shaping/shape_result.cc
index 88e9c01..d3316a8 100644
--- a/third_party/blink/renderer/platform/fonts/shaping/shape_result.cc
+++ b/third_party/blink/renderer/platform/fonts/shaping/shape_result.cc
@@ -101,221 +101,90 @@
   return XPositionForOffset(offset, adjust_mid_cluster);
 }
 
-unsigned ShapeResult::RunInfo::NumGraphemes(unsigned start,
-                                            unsigned end) const {
-  if (graphemes_.size() == 0 || start >= num_characters_)
-    return 0;
-  DCHECK_LT(start, end);
-  DCHECK_LE(end, num_characters_);
-  return graphemes_[end - 1] - graphemes_[start] + 1;
-}
-
-// XPositionForOffset returns the X position (in layout space) from the
-// beginning of the run to the beginning of the cluster of glyphs for X
-// character.
-// For RTL, beginning means the right most side of the cluster.
-// Characters may spawn multiple glyphs.
-// In the case that multiple characters form a Unicode grapheme cluster, we
-// distribute the width of the grapheme cluster among the number of cursor
-// positions returned by cursor-based TextBreakIterator.
 float ShapeResult::RunInfo::XPositionForOffset(
     unsigned offset,
     AdjustMidCluster adjust_mid_cluster) const {
   DCHECK_LE(offset, num_characters_);
   const unsigned num_glyphs = glyph_data_.size();
-
-  // In this context, a glyph sequence is a sequence of glyphs that shares the
-  // same character_index and therefore represent the same interval of source
-  // characters. glyph_sequence_start marks the character index at the beginning
-  // of the interval of characters for which this glyph sequence was formed as
-  // the result of shaping; glyph_sequence_end marks the end of the interval of
-  // characters for which this glyph sequence was formed. [glyph_sequence_start,
-  // glyph_sequence_end) is inclusive on the start for the range of characters
-  // of the current sequence we are visiting.
-  unsigned glyph_sequence_start = 0;
-  unsigned glyph_sequence_end = num_characters_;
-  // the advance of the current glyph sequence.
-  float glyph_sequence_advance = 0.0;
-  // the accumulated advance up to the current glyph sequence.
-  float accumulated_position = 0;
-
-  if (!Rtl()) {
-    for (unsigned i = 0; i < num_glyphs; ++i) {
-      unsigned current_glyph_char_index = glyph_data_[i].character_index;
-      // If this glyph is still part of the same glyph sequence for the grapheme
-      // cluster at character index glyph_sequence_start, add its advance to the
-      // glyph_sequence's advance.
-      if (glyph_sequence_start == current_glyph_char_index) {
-        glyph_sequence_advance += glyph_data_[i].advance;
-        continue;
-      }
-
-      // We are about to move out of a glyph sequence that contains offset, so
-      // the current glyph sequence is the one we are looking for.
-      if (glyph_sequence_start <= offset && offset < current_glyph_char_index) {
-        glyph_sequence_end = current_glyph_char_index;
-        break;
-      }
-
-      glyph_sequence_start = current_glyph_char_index;
-      // Since we always update glyph_sequence_end when we break, set this to
-      // last_character in case this is the final iteration of the loop.
-      glyph_sequence_end = num_characters_;
-      accumulated_position += glyph_sequence_advance;
-      glyph_sequence_advance = glyph_data_[i].advance;
-    }
-
-  } else {
-    glyph_sequence_start = glyph_sequence_end = num_characters_;
-
-    for (unsigned i = 0; i < num_glyphs; ++i) {
-      unsigned current_glyph_char_index = glyph_data_[i].character_index;
-      // If this glyph is still part of the same glyph sequence for the grapheme
-      // cluster at character index glyph_sequence_start, add its advance to the
-      // glyph_sequence's advance.
-      if (glyph_sequence_start == current_glyph_char_index) {
-        glyph_sequence_advance += glyph_data_[i].advance;
-        continue;
-      }
-
-      // We are about to move out of a glyph sequence that contains offset, so
-      // the current glyph sequence is the one we are looking for.
-      if (glyph_sequence_start <= offset && offset < glyph_sequence_end) {
-        break;
-      }
-
-      glyph_sequence_end = glyph_sequence_start;
-      glyph_sequence_start = current_glyph_char_index;
-      accumulated_position += glyph_sequence_advance;
-      glyph_sequence_advance = glyph_data_[i].advance;
-    }
-  }
-
-  // This is the character position inside the glyph sequence.
-  unsigned pos = offset - glyph_sequence_start;
-
-  // We calculate the number of Unicode grapheme clusters (actually cursor
-  // position stops) on the subset of characters. We use this to divide
-  // glyph_sequence_advance by the number of unicode grapheme clusters this
-  // glyph sequence was shaped for, and thus linearly interpolate the cursor
-  // position based on accumulated position and a fraction of
-  // glyph_sequence_advance.
-  unsigned graphemes = NumGraphemes(glyph_sequence_start, glyph_sequence_end);
-  if (graphemes > 1) {
-    DCHECK_GE(glyph_sequence_end, glyph_sequence_start);
-    unsigned size = glyph_sequence_end - glyph_sequence_start;
-    unsigned place = graphemes * pos / size;
-    pos -= place;
-    glyph_sequence_advance = glyph_sequence_advance / graphemes;
-    if (Rtl()) {
-      accumulated_position += glyph_sequence_advance * (graphemes - place - 1);
-    } else {
-      accumulated_position += glyph_sequence_advance * place;
-    }
-  }
-
-  // Re-adapt based on adjust_mid_cluster. On LTR, if we want AdjustToEnd and
-  // offset is not at the beginning, we need to jump to the right side of the
-  // grapheme. On RTL, if we want AdjustToStart and offset is not at the end, we
-  // need to jump to the left side of the grapheme.
-  if (!Rtl() && adjust_mid_cluster == AdjustMidCluster::kToEnd && pos != 0) {
-    accumulated_position += glyph_sequence_advance;
-  } else if (Rtl() && adjust_mid_cluster == AdjustMidCluster::kToEnd &&
-             pos != 0) {
-    accumulated_position -= glyph_sequence_advance;
-  }
-
+  unsigned glyph_index = 0;
+  float position = 0;
   if (Rtl()) {
-    // For RTL, we return the right side.
-    accumulated_position += glyph_sequence_advance;
+    while (glyph_index < num_glyphs &&
+           glyph_data_[glyph_index].character_index > offset) {
+      position += glyph_data_[glyph_index].advance;
+      ++glyph_index;
+    }
+    // If |glyph_index| is at the end, the glyph for |offset| is missing, along
+    // with all glyphs before it. We can't adjust position to the start
+    // direction.
+    if (glyph_index == num_glyphs)
+      return position;
+    // Adjust offset if it's not on the cluster boundary. In RTL, this means
+    // that the adjusted position is the left side of the character.
+    if (adjust_mid_cluster == AdjustMidCluster::kToEnd &&
+        glyph_data_[glyph_index].character_index < offset) {
+      return position;
+    }
+    // For RTL, we need to return the right side boundary of the character.
+    // Add advance of glyphs which are part of the character.
+    while (glyph_index < num_glyphs - 1 &&
+           glyph_data_[glyph_index].character_index ==
+               glyph_data_[glyph_index + 1].character_index) {
+      position += glyph_data_[glyph_index].advance;
+      ++glyph_index;
+    }
+    position += glyph_data_[glyph_index].advance;
+  } else {
+    while (glyph_index < num_glyphs &&
+           glyph_data_[glyph_index].character_index < offset) {
+      position += glyph_data_[glyph_index].advance;
+      ++glyph_index;
+    }
+    // Adjust offset if it's not on the cluster boundary.
+    if (adjust_mid_cluster == AdjustMidCluster::kToStart && glyph_index &&
+        (glyph_index < num_glyphs ? glyph_data_[glyph_index].character_index
+                                  : num_characters_) > offset) {
+      offset = glyph_data_[--glyph_index].character_index;
+      for (; glyph_data_[glyph_index].character_index == offset;
+           --glyph_index) {
+        position -= glyph_data_[glyph_index].advance;
+        if (!glyph_index)
+          break;
+      }
+    }
   }
-
-  return accumulated_position;
+  return position;
 }
 
-// In some ways, CharacterIndexForXPosition is the reverse of
-// XPositionForOffset. Given a target pixel distance on screen space, returns a
-// character index for the end of the interval that would be included within
-// that space. @break_glyphs_option controls wether we use grapheme information
-// to break glyphs into grapheme clusters and return character that are a part
-// of a glyph.
 void ShapeResult::RunInfo::CharacterIndexForXPosition(
     float target_x,
-    BreakGlyphsOption break_glyphs_option,
     GlyphIndexResult* result) const {
   DCHECK(target_x >= 0 && target_x <= width_);
   const unsigned num_glyphs = glyph_data_.size();
+  float current_x = 0;
+  unsigned glyph_index = 0;
 
-  result->origin_x = 0;
-  unsigned glyph_sequence_start = 0;
-  unsigned glyph_sequence_end = num_characters_;
-  result->advance = 0.0;
-
-  // on RTL, we start on the last index.
-  if (Rtl()) {
-    glyph_sequence_start = glyph_sequence_end = num_characters_;
-  }
-
-  for (unsigned i = 0; i < num_glyphs; ++i) {
-    unsigned current_glyph_char_index = glyph_data_[i].character_index;
-    // If the glyph is part of the same sequence, we just accumulate the
-    // advance.
-    if (glyph_sequence_start == current_glyph_char_index) {
-      result->advance += glyph_data_[i].advance;
-      continue;
+  while (true) {
+    unsigned current_character_index = glyph_data_[glyph_index].character_index;
+    float current_advance = glyph_data_[glyph_index].advance;
+    unsigned next_glyph_index = glyph_index + 1;
+    while (next_glyph_index < num_glyphs &&
+           current_character_index ==
+               glyph_data_[next_glyph_index].character_index)
+      current_advance += glyph_data_[next_glyph_index++].advance;
+    float next_x = current_x + current_advance;
+    if (target_x < next_x || next_glyph_index == num_glyphs) {
+      result->glyph_index = glyph_index;
+      result->next_glyph_index = next_glyph_index;
+      result->character_index = current_character_index;
+      result->origin_x = current_x;
+      result->advance = current_advance;
+      return;
     }
-
-    // Since we are about to move to the next sequence of glyphs, check if
-    // the target falls inside it, if it does, we found our sequence.
-    if (result->origin_x + result->advance > target_x) {
-      if (!Rtl()) {
-        glyph_sequence_end = current_glyph_char_index;
-      }
-      break;
-    }
-
-    // Move to the next sequence, update accumulated_x.
-    if (Rtl()) {
-      // Notice that on RTL, as we move to our next sequence, we already know
-      // both bounds. Nonetheless, we still need to move forward so we can
-      // capture all glyphs of this sequence.
-      glyph_sequence_end = glyph_sequence_start;
-    }
-    glyph_sequence_start = current_glyph_char_index;
-    result->origin_x += result->advance;
-    result->advance = glyph_data_[i].advance;
+    current_x = next_x;
+    glyph_index = next_glyph_index;
   }
-
-  // At this point, we have [glyph_sequence_start, glyph_sequence_end)
-  // representing a sequence of glyphs, of size glyph_sequence_advance. We
-  // linearly interpolate how much space each character takes, and reduce the
-  // sequence to only match the character size.
-  if (break_glyphs_option == BreakGlyphs) {
-    int graphemes = NumGraphemes(glyph_sequence_start, glyph_sequence_end);
-    if (graphemes > 1) {
-      float unit_size = result->advance / graphemes;
-      unsigned step = floor((target_x - result->origin_x) / unit_size);
-      unsigned glyph_length = glyph_sequence_end - glyph_sequence_start;
-      unsigned final_size = floor(glyph_length / graphemes);
-      result->origin_x += unit_size * step;
-      if (!Rtl()) {
-        glyph_sequence_start += step;
-        glyph_sequence_end = glyph_sequence_start + final_size;
-      } else {
-        glyph_sequence_end -= step;
-        glyph_sequence_start = glyph_sequence_end - final_size;
-      }
-      result->advance = unit_size;
-    }
-  }
-
-  if (!Rtl()) {
-    result->left_character_index = glyph_sequence_start;
-    result->right_character_index = glyph_sequence_end;
-  } else {
-    result->left_character_index = glyph_sequence_end;
-    result->right_character_index = glyph_sequence_start;
-  }
+  NOTREACHED();
 }
 
 void HarfBuzzRunGlyphData::SetGlyphAndPositions(uint16_t glyph_id,
@@ -453,111 +322,107 @@
   return StartIndexForResult();
 }
 
+// Returns the offset of the character of |result| for LTR.
+unsigned ShapeResult::OffsetLtr(const GlyphIndexResult& result) const {
+  DCHECK(IsLtr(Direction()));
+  return result.characters_on_left_runs + result.character_index;
+}
+
+// Returns the offset of the character of |result| for RTL.
+unsigned ShapeResult::OffsetRtl(const GlyphIndexResult& result, float x) const {
+  DCHECK(IsRtl(Direction()));
+  if (!result.IsInRun())
+    return NumCharacters() - result.characters_on_left_runs;
+  // In RTL, the boundary belongs to the left character. This subtle difference
+  // allows round trips between OffsetForPoint and PointForOffset.
+  if (UNLIKELY(x == result.origin_x))
+    return OffsetLeftRtl(result);
+  return NumCharacters() - result.characters_on_left_runs -
+         runs_[result.run_index]->num_characters_ + result.character_index;
+}
+
+// Returns the offset of the character on the right of |result| for LTR.
+unsigned ShapeResult::OffsetRightLtr(const GlyphIndexResult& result) const {
+  DCHECK(IsLtr(Direction()));
+  if (result.run_index >= runs_.size())
+    return NumCharacters();
+  const RunInfo& run = *runs_[result.run_index];
+  return result.characters_on_left_runs +
+         (result.next_glyph_index < run.glyph_data_.size()
+              ? run.glyph_data_[result.next_glyph_index].character_index
+              : run.num_characters_);
+}
+
+// Returns the offset of the character on the left of |result| for RTL.
+unsigned ShapeResult::OffsetLeftRtl(const GlyphIndexResult& result) const {
+  DCHECK(IsRtl(Direction()));
+  if (!result.glyph_index)
+    return NumCharacters() - result.characters_on_left_runs;
+  const RunInfo& run = *runs_[result.run_index];
+  return NumCharacters() - result.characters_on_left_runs -
+         run.num_characters_ +
+         run.glyph_data_[result.glyph_index - 1].character_index;
+}
+
 // If the position is outside of the result, returns the start or the end offset
 // depends on the position.
 void ShapeResult::OffsetForPosition(float target_x,
-                                    BreakGlyphsOption break_glyphs_option,
                                     GlyphIndexResult* result) const {
-  if (target_x <= 0) {
-    if (Rtl()) {
-      result->left_character_index = result->right_character_index =
-          NumCharacters();
-    }
+  if (target_x <= 0)
     return;
-  }
 
-  unsigned characters_so_far = Rtl() ? NumCharacters() : 0;
+  unsigned characters_so_far = 0;
   float current_x = 0;
-
   for (unsigned i = 0; i < runs_.size(); ++i) {
     const RunInfo* run = runs_[i].get();
     if (!run)
       continue;
-    if (Rtl())
-      characters_so_far -= runs_[i]->num_characters_;
     float next_x = current_x + run->width_;
     float offset_for_run = target_x - current_x;
     if (offset_for_run >= 0 && offset_for_run < run->width_) {
       // The x value in question is within this script run.
-      run->CharacterIndexForXPosition(offset_for_run, break_glyphs_option,
-                                      result);
+      run->CharacterIndexForXPosition(offset_for_run, result);
       result->run_index = i;
       result->characters_on_left_runs = characters_so_far;
-      if (Rtl()) {
-        result->left_character_index =
-            characters_so_far + result->left_character_index;
-        result->right_character_index =
-            characters_so_far + result->right_character_index;
-        DCHECK_LE(result->left_character_index, NumCharacters() + 1);
-        DCHECK_LE(result->right_character_index, NumCharacters());
-      } else {
-        result->left_character_index += characters_so_far;
-        result->right_character_index += characters_so_far;
-        DCHECK_LE(result->left_character_index, NumCharacters());
-        DCHECK_LE(result->right_character_index, NumCharacters() + 1);
-      }
       result->origin_x += current_x;
+      DCHECK_LE(result->characters_on_left_runs + result->character_index,
+                NumCharacters());
       return;
     }
-    if (!Rtl())
-      characters_so_far += run->num_characters_;
+    characters_so_far += run->num_characters_;
     current_x = next_x;
   }
 
-  if (Rtl()) {
-    result->left_character_index = 0;
-    result->right_character_index = 0;
-  } else {
-    result->left_character_index += characters_so_far;
-    result->right_character_index += characters_so_far;
-  }
-
-  result->run_index = runs_.size() - 1;
+  result->run_index = runs_.size();
   result->characters_on_left_runs = characters_so_far;
-
-  DCHECK_LE(result->left_character_index, NumCharacters());
-  DCHECK_LE(result->right_character_index, NumCharacters() + 1);
 }
 
-unsigned ShapeResult::OffsetForPosition(
-    float x,
-    BreakGlyphsOption break_glyphs_option) const {
+unsigned ShapeResult::OffsetForPosition(float x) const {
   GlyphIndexResult result;
-  OffsetForPosition(x, break_glyphs_option, &result);
-
-  // For LTR, the offset is always the left one.
-  if (!Rtl())
-    return result.left_character_index;
-
-  // For RTL the offset is the right one, except that the interval is open
-  // on other side. So in case we are exactly at the boundary, we return the
-  // left index.
-  if (x == result.origin_x)
-    return result.left_character_index;
-  return result.right_character_index;
+  OffsetForPosition(x, &result);
+  return IsLtr(Direction()) ? OffsetLtr(result) : OffsetRtl(result, x);
 }
 
-unsigned ShapeResult::OffsetForHitTest(
-    float x,
-    BreakGlyphsOption break_glyphs_option) const {
+unsigned ShapeResult::OffsetForHitTest(float x) const {
   GlyphIndexResult result;
-  OffsetForPosition(x, break_glyphs_option, &result);
-
-  if (x - result.origin_x <= result.advance / 2)
-    return result.left_character_index;
-  return result.right_character_index;
+  OffsetForPosition(x, &result);
+  if (IsLtr(Direction())) {
+    if (result.IsInRun() && x > result.origin_x + result.advance / 2)
+      return OffsetRightLtr(result);
+    return OffsetLtr(result);
+  }
+  if (result.IsInRun() && x <= result.origin_x + result.advance / 2)
+    return OffsetLeftRtl(result);
+  return OffsetRtl(result, x);
 }
 
 unsigned ShapeResult::OffsetToFit(float x, TextDirection line_direction) const {
   GlyphIndexResult result;
-  OffsetForPosition(x, DontBreakGlyphs, &result);
-
-  if (IsLtr(line_direction))
-    return result.left_character_index;
-
-  if (x == result.origin_x && IsRtl(Direction()))
-    return result.left_character_index;
-  return result.right_character_index;
+  OffsetForPosition(x, &result);
+  if (IsLtr(line_direction)) {
+    return IsLtr(Direction()) ? OffsetLtr(result) : OffsetLeftRtl(result);
+  }
+  return IsRtl(Direction()) ? OffsetRtl(result, x) : OffsetRightLtr(result);
 }
 
 float ShapeResult::PositionForOffset(
@@ -934,24 +799,21 @@
 // synthesize a run without glyphs.
 void ShapeResult::InsertRunForIndex(unsigned start_character_index) {
   DCHECK(runs_.IsEmpty());
-  // TODO(fserb): do we need the proper graphemes?
-  Vector<unsigned> graphemes;
   runs_.push_back(std::make_unique<RunInfo>(
       primary_font_.get(), !Rtl() ? HB_DIRECTION_LTR : HB_DIRECTION_RTL,
       CanvasRotationInVertical::kRegular, HB_SCRIPT_UNKNOWN,
-      start_character_index, 0, num_characters_, graphemes));
+      start_character_index, 0, num_characters_));
 }
 
 ShapeResult::RunInfo* ShapeResult::InsertRunForTesting(
     unsigned start_index,
     unsigned num_characters,
     TextDirection direction,
-    Vector<uint16_t> safe_break_offsets,
-    Vector<unsigned> graphemes) {
+    Vector<uint16_t> safe_break_offsets) {
   std::unique_ptr<RunInfo> run = std::make_unique<ShapeResult::RunInfo>(
       nullptr, IsLtr(direction) ? HB_DIRECTION_LTR : HB_DIRECTION_RTL,
       CanvasRotationInVertical::kRegular, HB_SCRIPT_COMMON, start_index,
-      num_characters, num_characters, std::move(graphemes));
+      num_characters, num_characters);
   unsigned i = 0;
   for (auto& glyph_data : run->glyph_data_)
     glyph_data.SetGlyphAndPositions(0, i++, 0, FloatSize(), false);
@@ -1187,12 +1049,9 @@
   const SimpleFontData* font_data = font->PrimaryFont();
   // Tab characters are always LTR or RTL, not TTB, even when
   // isVerticalAnyUpright().
-  // We don't pass proper graphemes for tabulation.
-  Vector<unsigned> graphemes;
   std::unique_ptr<ShapeResult::RunInfo> run = std::make_unique<RunInfo>(
       font_data, text_run.Rtl() ? HB_DIRECTION_RTL : HB_DIRECTION_LTR,
-      CanvasRotationInVertical::kRegular, HB_SCRIPT_COMMON, 0, count, count,
-      graphemes);
+      CanvasRotationInVertical::kRegular, HB_SCRIPT_COMMON, 0, count, count);
   float position = text_run.XPos() + position_offset;
   float start_position = position;
   for (unsigned i = 0; i < count; i++) {
@@ -1354,7 +1213,7 @@
   // TODO(layout-dev): Remove once CharacterPositionData::OffsetForPosition
   // properly supports RTL.
   if (Rtl())
-    return OffsetForPosition(x, DontBreakGlyphs);
+    return OffsetForPosition(x);
 
   DCHECK(character_position_);
   return character_position_->OffsetForPosition(x);
diff --git a/third_party/blink/renderer/platform/fonts/shaping/shape_result.h b/third_party/blink/renderer/platform/fonts/shaping/shape_result.h
index 926faed..0342539 100644
--- a/third_party/blink/renderer/platform/fonts/shaping/shape_result.h
+++ b/third_party/blink/renderer/platform/fonts/shaping/shape_result.h
@@ -67,22 +67,6 @@
   unsigned safe_to_break_before : 1;
 };
 
-// There are two options for how OffsetForPosition behaves:
-// IncludePartialGlyphs - decides what to do when the position hits more than
-// 50% of the glyph. If enabled, we count that glyph, if disable we don't.
-enum IncludePartialGlyphsOption {
-  OnlyFullGlyphs,
-  IncludePartialGlyphs,
-};
-
-// BreakGlyphs - allows OffsetForPosition to consider graphemes separations
-// inside a glyph. It allows the function to return a point inside a glyph when
-// multiple graphemes share a glyph (for example, in a ligature)
-enum BreakGlyphsOption {
-  DontBreakGlyphs,
-  BreakGlyphs,
-};
-
 class PLATFORM_EXPORT ShapeResult : public RefCounted<ShapeResult> {
  public:
   static scoped_refptr<ShapeResult> Create(const Font* font,
@@ -140,21 +124,18 @@
 
   // Returns the offset, relative to StartIndexForResult, whose (origin,
   // origin+advance) contains |x|.
-  unsigned OffsetForPosition(float x, BreakGlyphsOption) const;
+  unsigned OffsetForPosition(float x) const;
+
   // Returns the offset whose glyph boundary is nearest to |x|. Depends on
   // whether |x| is on the left-half or the right-half of the glyph, it
   // determines the left-boundary or the right-boundary, then computes the
   // offset from the bidi direction.
-  unsigned OffsetForHitTest(float x, BreakGlyphsOption) const;
+  unsigned OffsetForHitTest(float x) const;
   // Returns the offset that can fit to between |x| and the left or the right
   // edge. The side of the edge is determined by |line_direction|.
   unsigned OffsetToFit(float x, TextDirection line_direction) const;
-  unsigned OffsetForPosition(float x,
-                             IncludePartialGlyphsOption include_partial_glyphs,
-                             BreakGlyphsOption break_glyphs_option) const {
-    return include_partial_glyphs == OnlyFullGlyphs
-               ? OffsetForPosition(x, break_glyphs_option)
-               : OffsetForHitTest(x, break_glyphs_option);
+  unsigned OffsetForPosition(float x, bool include_partial_glyphs) const {
+    return !include_partial_glyphs ? OffsetForPosition(x) : OffsetForHitTest(x);
   }
 
   // Returns the position for a given offset, relative to StartIndexForResult.
@@ -217,8 +198,7 @@
   RunInfo* InsertRunForTesting(unsigned start_index,
                                unsigned num_characters,
                                TextDirection,
-                               Vector<uint16_t> safe_break_offsets = {},
-                               Vector<unsigned> graphemes = {});
+                               Vector<uint16_t> safe_break_offsets = {});
 #if DCHECK_IS_ON()
   void CheckConsistency() const;
 #endif
@@ -241,21 +221,26 @@
     unsigned run_index = 0;
     // The total number of characters of runs_[0..run_index - 1].
     unsigned characters_on_left_runs = 0;
-
-    // Those are the left and right character indexes of the group of glyphs
-    // that were selected by OffsetForPosition.
-    unsigned left_character_index = 0;
-    unsigned right_character_index = 0;
-
+    unsigned character_index = 0;
+    unsigned glyph_index = 0;
+    // |next_glyph_index| may not be |glyph_index| + 1 when a cluster is of
+    // multiple glyphs; i.e., ligatures or combining glyphs.
+    unsigned next_glyph_index = 0;
     // The glyph origin of the glyph.
     float origin_x = 0;
     // The advance of the glyph.
     float advance = 0;
+
+    // True if the position was found on a run. False otherwise.
+    bool IsInRun() const { return next_glyph_index; }
   };
 
-  void OffsetForPosition(float target_x,
-                         BreakGlyphsOption,
-                         GlyphIndexResult*) const;
+  unsigned OffsetLtr(const GlyphIndexResult&) const;
+  unsigned OffsetRtl(const GlyphIndexResult&, float x) const;
+  unsigned OffsetRightLtr(const GlyphIndexResult&) const;
+  unsigned OffsetLeftRtl(const GlyphIndexResult&) const;
+
+  void OffsetForPosition(float target_x, GlyphIndexResult*) const;
 
   // Helper class storing a map between offsets and x-positions.
   // Unlike the RunInfo and GlyphData structures in ShapeResult, which operates
diff --git a/third_party/blink/renderer/platform/fonts/shaping/shape_result_buffer.cc b/third_party/blink/renderer/platform/fonts/shaping/shape_result_buffer.cc
index 1800d807..4aaab9f3 100644
--- a/third_party/blink/renderer/platform/fonts/shaping/shape_result_buffer.cc
+++ b/third_party/blink/renderer/platform/fonts/shaping/shape_result_buffer.cc
@@ -5,7 +5,6 @@
 #include "third_party/blink/renderer/platform/fonts/shaping/shape_result_buffer.h"
 
 #include "third_party/blink/renderer/platform/fonts/character_range.h"
-#include "third_party/blink/renderer/platform/fonts/shaping/shape_result.h"
 #include "third_party/blink/renderer/platform/fonts/shaping/shape_result_inline_headers.h"
 #include "third_party/blink/renderer/platform/fonts/simple_font_data.h"
 #include "third_party/blink/renderer/platform/geometry/float_point.h"
@@ -28,13 +27,6 @@
   return GetCharacterRangeInternal(results, direction, total_width, from, to);
 }
 
-CharacterRange ShapeResultBuffer::GetCharacterRange(float total_width,
-                                                    TextDirection direction,
-                                                    unsigned from,
-                                                    unsigned to) const {
-  return GetCharacterRangeInternal(results_, direction, total_width, from, to);
-}
-
 CharacterRange ShapeResultBuffer::GetCharacterRangeInternal(
     const Vector<scoped_refptr<const ShapeResult>, 64>& results,
     TextDirection direction,
@@ -131,6 +123,13 @@
   return CharacterRange(to_x, from_x, -min_y, max_y);
 }
 
+CharacterRange ShapeResultBuffer::GetCharacterRange(TextDirection direction,
+                                                    float total_width,
+                                                    unsigned from,
+                                                    unsigned to) const {
+  return GetCharacterRangeInternal(results_, direction, total_width, from, to);
+}
+
 void ShapeResultBuffer::AddRunInfoRanges(const ShapeResult::RunInfo& run_info,
                                          float offset,
                                          Vector<CharacterRange>& ranges) {
@@ -173,11 +172,9 @@
   return ranges;
 }
 
-int ShapeResultBuffer::OffsetForPosition(
-    const TextRun& run,
-    float target_x,
-    IncludePartialGlyphsOption partial_glyphs,
-    BreakGlyphsOption break_glyphs) const {
+int ShapeResultBuffer::OffsetForPosition(const TextRun& run,
+                                         float target_x,
+                                         bool include_partial_glyphs) const {
   unsigned total_offset;
   if (run.Rtl()) {
     total_offset = run.length();
@@ -187,8 +184,8 @@
         continue;
       total_offset -= word_result->NumCharacters();
       if (target_x >= 0 && target_x <= word_result->Width()) {
-        int offset_for_word = word_result->OffsetForPosition(
-            target_x, partial_glyphs, break_glyphs);
+        int offset_for_word =
+            word_result->OffsetForPosition(target_x, include_partial_glyphs);
         return total_offset + offset_for_word;
       }
       target_x -= word_result->Width();
@@ -198,8 +195,8 @@
     for (const auto& word_result : results_) {
       if (!word_result)
         continue;
-      int offset_for_word = word_result->OffsetForPosition(
-          target_x, partial_glyphs, break_glyphs);
+      int offset_for_word =
+          word_result->OffsetForPosition(target_x, include_partial_glyphs);
       DCHECK_GE(offset_for_word, 0);
       total_offset += offset_for_word;
       if (target_x >= 0 && target_x <= word_result->Width())
diff --git a/third_party/blink/renderer/platform/fonts/shaping/shape_result_buffer.h b/third_party/blink/renderer/platform/fonts/shaping/shape_result_buffer.h
index ace7dcd..f1092b5 100644
--- a/third_party/blink/renderer/platform/fonts/shaping/shape_result_buffer.h
+++ b/third_party/blink/renderer/platform/fonts/shaping/shape_result_buffer.h
@@ -33,12 +33,11 @@
 
   bool HasVerticalOffsets() const { return has_vertical_offsets_; }
 
-  int OffsetForPosition(const TextRun& run,
+  int OffsetForPosition(const TextRun&,
                         float target_x,
-                        IncludePartialGlyphsOption,
-                        BreakGlyphsOption) const;
-  CharacterRange GetCharacterRange(float total_width,
-                                   TextDirection,
+                        bool include_partial_glyphs) const;
+  CharacterRange GetCharacterRange(TextDirection,
+                                   float total_width,
                                    unsigned from,
                                    unsigned to) const;
   Vector<CharacterRange> IndividualCharacterRanges(TextDirection,
diff --git a/third_party/blink/renderer/platform/fonts/shaping/shape_result_inline_headers.h b/third_party/blink/renderer/platform/fonts/shaping/shape_result_inline_headers.h
index 3609c766..5d479ea0 100644
--- a/third_party/blink/renderer/platform/fonts/shaping/shape_result_inline_headers.h
+++ b/third_party/blink/renderer/platform/fonts/shaping/shape_result_inline_headers.h
@@ -37,7 +37,6 @@
 #include "third_party/blink/renderer/platform/fonts/shaping/shape_result.h"
 #include "third_party/blink/renderer/platform/wtf/allocator.h"
 #include "third_party/blink/renderer/platform/wtf/noncopyable.h"
-#include "third_party/blink/renderer/platform/wtf/vector.h"
 
 namespace blink {
 
@@ -73,14 +72,12 @@
           hb_script_t script,
           unsigned start_index,
           unsigned num_glyphs,
-          unsigned num_characters,
-          Vector<unsigned> graphemes)
+          unsigned num_characters)
       : font_data_(const_cast<SimpleFontData*>(font)),
         direction_(dir),
         canvas_rotation_(canvas_rotation),
         script_(script),
         glyph_data_(num_glyphs),
-        graphemes_(graphemes),
         start_index_(start_index),
         num_characters_(num_characters),
         width_(0.0f) {}
@@ -91,7 +88,6 @@
         canvas_rotation_(other.canvas_rotation_),
         script_(other.script_),
         glyph_data_(other.glyph_data_),
-        graphemes_(other.graphemes_),
         start_index_(other.start_index_),
         num_characters_(other.num_characters_),
         width_(other.width_) {}
@@ -104,21 +100,12 @@
   unsigned PreviousSafeToBreakOffset(unsigned) const;
   float XPositionForVisualOffset(unsigned, AdjustMidCluster) const;
   float XPositionForOffset(unsigned, AdjustMidCluster) const;
-  void CharacterIndexForXPosition(float,
-                                  BreakGlyphsOption,
-                                  GlyphIndexResult*) const;
-  void SetGlyphAndPositions(unsigned index,
-                            uint16_t glyph_id,
-                            float advance,
-                            float offset_x,
-                            float offset_y);
+  void CharacterIndexForXPosition(float, GlyphIndexResult*) const;
 
   size_t GlyphToCharacterIndex(size_t i) const {
     return start_index_ + glyph_data_[i].character_index;
   }
 
-  unsigned NumGraphemes(unsigned start, unsigned end) const;
-
   // For memory reporting.
   size_t ByteSize() const {
     return sizeof(this) + glyph_data_.size() * sizeof(HarfBuzzRunGlyphData);
@@ -172,18 +159,9 @@
     auto glyphs = FindGlyphDataRange(start, end);
     unsigned number_of_glyphs = std::distance(glyphs.begin, glyphs.end);
 
-    Vector<unsigned> sub_graphemes;
-    if (graphemes_.size()) {
-      sub_graphemes.resize(number_of_characters);
-      for (unsigned i = 0; i < number_of_characters; ++i) {
-        sub_graphemes[i] = graphemes_[start + i];
-      }
-    }
-
     auto run = std::make_unique<RunInfo>(
         font_data_.get(), direction_, canvas_rotation_, script_,
-        start_index_ + start, number_of_glyphs, number_of_characters,
-        std::move(sub_graphemes));
+        start_index_ + start, number_of_glyphs, number_of_characters);
 
     static_assert(base::is_trivially_copyable<HarfBuzzRunGlyphData>::value,
                   "HarfBuzzRunGlyphData should be trivially copyable");
@@ -292,11 +270,6 @@
   CanvasRotationInVertical canvas_rotation_;
   hb_script_t script_;
   Vector<HarfBuzzRunGlyphData> glyph_data_;
-
-  // graphemes_[i] is the number of graphemes up to (and including) the ith
-  // character in the run.
-  Vector<unsigned> graphemes_;
-
   unsigned start_index_;
   unsigned num_characters_;
   float width_;
diff --git a/third_party/blink/renderer/platform/graphics/decoding_image_generator.cc b/third_party/blink/renderer/platform/graphics/decoding_image_generator.cc
index 926f83f..3af4ece 100644
--- a/third_party/blink/renderer/platform/graphics/decoding_image_generator.cc
+++ b/third_party/blink/renderer/platform/graphics/decoding_image_generator.cc
@@ -160,10 +160,7 @@
     TRACE_EVENT0("blink", "DecodingImageGenerator::getPixels - apply xform");
     SkPixmap src(decode_info, pixels, row_bytes);
 
-    // kIgnore ensures that we perform the premultiply (if necessary) in the dst
-    // space.
-    const bool converted = src.readPixels(dst_info, pixels, row_bytes, 0, 0,
-                                          SkTransferFunctionBehavior::kIgnore);
+    const bool converted = src.readPixels(dst_info, pixels, row_bytes);
     DCHECK(converted);
   }
 
diff --git a/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.h b/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.h
index 67a69c9..f65927d 100644
--- a/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.h
+++ b/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.h
@@ -108,6 +108,7 @@
   enum WebGLVersion {
     kWebGL1,
     kWebGL2,
+    kWebGL2Compute,
   };
 
   enum ChromiumImageUsage {
diff --git a/third_party/blink/renderer/platform/graphics/image_data_buffer.cc b/third_party/blink/renderer/platform/graphics/image_data_buffer.cc
index 4e2bc97..c3d7df4 100644
--- a/third_party/blink/renderer/platform/graphics/image_data_buffer.cc
+++ b/third_party/blink/renderer/platform/graphics/image_data_buffer.cc
@@ -117,28 +117,22 @@
   return static_cast<const unsigned char*>(pixmap_.addr());
 }
 
-bool ImageDataBuffer::EncodeImage(
-    const String& mime_type,
-    const double& quality,
-    Vector<unsigned char>* encoded_image,
-    SkTransferFunctionBehavior transfer_fn_behavior) const {
-  return EncodeImageInternal(mime_type, quality, encoded_image, pixmap_,
-                             transfer_fn_behavior);
+bool ImageDataBuffer::EncodeImage(const String& mime_type,
+                                  const double& quality,
+                                  Vector<unsigned char>* encoded_image) const {
+  return EncodeImageInternal(mime_type, quality, encoded_image, pixmap_);
 }
 
-bool ImageDataBuffer::EncodeImageInternal(
-    const String& mime_type,
-    const double& quality,
-    Vector<unsigned char>* encoded_image,
-    const SkPixmap& pixmap,
-    SkTransferFunctionBehavior transfer_fn_behavior) const {
+bool ImageDataBuffer::EncodeImageInternal(const String& mime_type,
+                                          const double& quality,
+                                          Vector<unsigned char>* encoded_image,
+                                          const SkPixmap& pixmap) const {
   DCHECK(is_valid_);
 
   if (mime_type == "image/jpeg") {
     SkJpegEncoder::Options options;
     options.fQuality = ImageEncoder::ComputeJpegQuality(quality);
     options.fAlphaOption = SkJpegEncoder::AlphaOption::kBlendOnBlack;
-    options.fBlendBehavior = transfer_fn_behavior;
     if (options.fQuality == 100) {
       options.fDownsample = SkJpegEncoder::Downsample::k444;
     }
@@ -146,8 +140,7 @@
   }
 
   if (mime_type == "image/webp") {
-    SkWebpEncoder::Options options =
-        ImageEncoder::ComputeWebpOptions(quality, transfer_fn_behavior);
+    SkWebpEncoder::Options options = ImageEncoder::ComputeWebpOptions(quality);
     return ImageEncoder::Encode(encoded_image, pixmap, options);
   }
 
@@ -155,7 +148,6 @@
   SkPngEncoder::Options options;
   options.fFilterFlags = SkPngEncoder::FilterFlag::kSub;
   options.fZLibLevel = 3;
-  options.fUnpremulBehavior = transfer_fn_behavior;
   return ImageEncoder::Encode(encoded_image, pixmap, options);
 }
 
@@ -171,16 +163,14 @@
   if (pixmap.colorSpace()) {
     if (!pixmap.colorSpace()->isSRGB()) {
       skia_image = SkImage::MakeFromRaster(pixmap, nullptr, nullptr);
-      skia_image = skia_image->makeColorSpace(
-          SkColorSpace::MakeSRGB(), SkTransferFunctionBehavior::kIgnore);
+      skia_image = skia_image->makeColorSpace(SkColorSpace::MakeSRGB());
       skia_image->peekPixels(&pixmap);
     }
     pixmap.setColorSpace(nullptr);
   }
 
   Vector<unsigned char> result;
-  if (!EncodeImageInternal(mime_type, quality, &result, pixmap,
-                           SkTransferFunctionBehavior::kIgnore))
+  if (!EncodeImageInternal(mime_type, quality, &result, pixmap))
     return "data:,";
 
   return "data:" + mime_type + ";base64," + Base64Encode(result);
diff --git a/third_party/blink/renderer/platform/graphics/image_data_buffer.h b/third_party/blink/renderer/platform/graphics/image_data_buffer.h
index 48ffa41f..3002ac98 100644
--- a/third_party/blink/renderer/platform/graphics/image_data_buffer.h
+++ b/third_party/blink/renderer/platform/graphics/image_data_buffer.h
@@ -50,8 +50,7 @@
   String ToDataURL(const String& mime_type, const double& quality) const;
   bool EncodeImage(const String& mime_type,
                    const double& quality,
-                   Vector<unsigned char>* encoded_image,
-                   SkTransferFunctionBehavior transfer_fn_behavior) const;
+                   Vector<unsigned char>* encoded_image) const;
 
   const unsigned char* Pixels() const;
   const IntSize& size() const { return size_; }
@@ -67,12 +66,10 @@
 
   bool IsValid() { return is_valid_; }  // Only used by Create()
 
-  bool EncodeImageInternal(
-      const String& mime_type,
-      const double& quality,
-      Vector<unsigned char>* encoded_image,
-      const SkPixmap& pixmap,
-      SkTransferFunctionBehavior transfer_fn_behavior) const;
+  bool EncodeImageInternal(const String& mime_type,
+                           const double& quality,
+                           Vector<unsigned char>* encoded_image,
+                           const SkPixmap& pixmap) const;
 
   sk_sp<SkImage> retained_image_;
   SkPixmap pixmap_;
diff --git a/third_party/blink/renderer/platform/graphics/logging_canvas.cc b/third_party/blink/renderer/platform/graphics/logging_canvas.cc
index 5755e73b..09dbc7eb 100644
--- a/third_party/blink/renderer/platform/graphics/logging_canvas.cc
+++ b/third_party/blink/renderer/platform/graphics/logging_canvas.cc
@@ -273,7 +273,6 @@
   SkPngEncoder::Options options;
   options.fFilterFlags = SkPngEncoder::FilterFlag::kSub;
   options.fZLibLevel = 3;
-  options.fUnpremulBehavior = SkTransferFunctionBehavior::kIgnore;
   if (!ImageEncoder::Encode(&output, src, options)) {
     return nullptr;
   }
diff --git a/third_party/blink/renderer/platform/graphics/picture_snapshot.cc b/third_party/blink/renderer/platform/graphics/picture_snapshot.cc
index 9773f501..20da318 100644
--- a/third_party/blink/renderer/platform/graphics/picture_snapshot.cc
+++ b/third_party/blink/renderer/platform/graphics/picture_snapshot.cc
@@ -123,7 +123,6 @@
   SkPngEncoder::Options options;
   options.fFilterFlags = SkPngEncoder::FilterFlag::kSub;
   options.fZLibLevel = 3;
-  options.fUnpremulBehavior = SkTransferFunctionBehavior::kIgnore;
   if (!ImageEncoder::Encode(
           reinterpret_cast<Vector<unsigned char>*>(&encoded_image), src,
           options)) {
diff --git a/third_party/blink/renderer/platform/graphics/static_bitmap_image.cc b/third_party/blink/renderer/platform/graphics/static_bitmap_image.cc
index 14dc7cf8..e200c1f 100644
--- a/third_party/blink/renderer/platform/graphics/static_bitmap_image.cc
+++ b/third_party/blink/renderer/platform/graphics/static_bitmap_image.cc
@@ -79,8 +79,7 @@
 }
 
 scoped_refptr<StaticBitmapImage> StaticBitmapImage::ConvertToColorSpace(
-    sk_sp<SkColorSpace> target,
-    SkTransferFunctionBehavior transfer_function_behavior) {
+    sk_sp<SkColorSpace> target) {
   sk_sp<SkImage> skia_image = PaintImageForCurrentFrame().GetSkImage();
   sk_sp<SkColorSpace> src_color_space = skia_image->refColorSpace();
   if (!src_color_space.get())
@@ -92,7 +91,7 @@
     return this;
 
   sk_sp<SkImage> converted_skia_image =
-      skia_image->makeColorSpace(dst_color_space, transfer_function_behavior);
+      skia_image->makeColorSpace(dst_color_space);
   DCHECK(converted_skia_image.get());
   DCHECK(skia_image.get() != converted_skia_image.get());
 
diff --git a/third_party/blink/renderer/platform/graphics/static_bitmap_image.h b/third_party/blink/renderer/platform/graphics/static_bitmap_image.h
index fee76571..0f3d63a 100644
--- a/third_party/blink/renderer/platform/graphics/static_bitmap_image.h
+++ b/third_party/blink/renderer/platform/graphics/static_bitmap_image.h
@@ -113,9 +113,7 @@
   // Methods have exactly the same implementation for all sub-classes
   bool OriginClean() const { return is_origin_clean_; }
   void SetOriginClean(bool flag) { is_origin_clean_ = flag; }
-  scoped_refptr<StaticBitmapImage> ConvertToColorSpace(
-      sk_sp<SkColorSpace>,
-      SkTransferFunctionBehavior);
+  scoped_refptr<StaticBitmapImage> ConvertToColorSpace(sk_sp<SkColorSpace>);
 
   static bool ConvertToArrayBufferContents(
       scoped_refptr<StaticBitmapImage> src_image,
diff --git a/third_party/blink/renderer/platform/graphics/surface_layer_bridge.cc b/third_party/blink/renderer/platform/graphics/surface_layer_bridge.cc
index 3aa75b4d..949bcd8 100644
--- a/third_party/blink/renderer/platform/graphics/surface_layer_bridge.cc
+++ b/third_party/blink/renderer/platform/graphics/surface_layer_bridge.cc
@@ -4,8 +4,6 @@
 
 #include "third_party/blink/renderer/platform/graphics/surface_layer_bridge.h"
 
-#include <utility>
-
 #include "base/feature_list.h"
 #include "cc/layers/layer.h"
 #include "cc/layers/solid_color_layer.h"
@@ -23,13 +21,9 @@
 
 namespace blink {
 
-SurfaceLayerBridge::SurfaceLayerBridge(
-    WebLayerTreeView* layer_tree_view,
-    WebSurfaceLayerBridgeObserver* observer,
-    cc::UpdateSubmissionStateCB update_submission_state_callback)
+SurfaceLayerBridge::SurfaceLayerBridge(WebLayerTreeView* layer_tree_view,
+                                       WebSurfaceLayerBridgeObserver* observer)
     : observer_(observer),
-      update_submission_state_callback_(
-          std::move(update_submission_state_callback)),
       binding_(this),
       frame_sink_id_(Platform::Current()->GenerateFrameSinkId()),
       parent_frame_sink_id_(layer_tree_view ? layer_tree_view->GetFrameSinkId()
@@ -124,7 +118,7 @@
 }
 
 void SurfaceLayerBridge::CreateSurfaceLayer() {
-  surface_layer_ = cc::SurfaceLayer::Create(update_submission_state_callback_);
+  surface_layer_ = cc::SurfaceLayer::Create();
 
   // This surface_id is essentially just a placeholder for the real one we will
   // get in OnFirstSurfaceActivation. We need it so that we properly get a
@@ -133,12 +127,8 @@
       frame_sink_id_,
       parent_local_surface_id_allocator_.GetCurrentLocalSurfaceId());
 
-  surface_layer_->SetPrimarySurfaceId(current_surface_id_,
-                                      cc::DeadlinePolicy::UseDefaultDeadline());
-
   surface_layer_->SetStretchContentToFillBounds(true);
   surface_layer_->SetIsDrawable(true);
-  surface_layer_->SetMayContainVideo(true);
 
   if (observer_) {
     observer_->RegisterContentsLayer(surface_layer_.get());
@@ -148,4 +138,8 @@
   surface_layer_->SetContentsOpaque(false);
 }
 
+const viz::SurfaceId& SurfaceLayerBridge::GetSurfaceId() const {
+  return current_surface_id_;
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/graphics/surface_layer_bridge.h b/third_party/blink/renderer/platform/graphics/surface_layer_bridge.h
index 120b32a6..afb53d3 100644
--- a/third_party/blink/renderer/platform/graphics/surface_layer_bridge.h
+++ b/third_party/blink/renderer/platform/graphics/surface_layer_bridge.h
@@ -34,10 +34,7 @@
     : public blink::mojom::blink::EmbeddedFrameSinkClient,
       public WebSurfaceLayerBridge {
  public:
-  SurfaceLayerBridge(
-      WebLayerTreeView*,
-      WebSurfaceLayerBridgeObserver*,
-      cc::UpdateSubmissionStateCB update_submission_state_callback);
+  SurfaceLayerBridge(WebLayerTreeView*, WebSurfaceLayerBridgeObserver*);
   ~SurfaceLayerBridge() override;
 
   void CreateSolidColorLayer();
@@ -51,10 +48,7 @@
   void ClearSurfaceId() override;
   void SetContentsOpaque(bool) override;
   void CreateSurfaceLayer() override;
-
-  const viz::SurfaceId& GetSurfaceId() const override {
-    return current_surface_id_;
-  }
+  const viz::SurfaceId& GetSurfaceId() const override;
 
  private:
   scoped_refptr<cc::SurfaceLayer> surface_layer_;
@@ -62,7 +56,6 @@
 
   // The |observer_| handles unregistering the contents layer on its own.
   WebSurfaceLayerBridgeObserver* observer_;
-  cc::UpdateSubmissionStateCB update_submission_state_callback_;
   viz::ParentLocalSurfaceIdAllocator parent_local_surface_id_allocator_;
   mojo::Binding<blink::mojom::blink::EmbeddedFrameSinkClient> binding_;
 
diff --git a/third_party/blink/renderer/platform/graphics/video_frame_submitter.cc b/third_party/blink/renderer/platform/graphics/video_frame_submitter.cc
index 906e20e..d1a112314 100644
--- a/third_party/blink/renderer/platform/graphics/video_frame_submitter.cc
+++ b/third_party/blink/renderer/platform/graphics/video_frame_submitter.cc
@@ -4,8 +4,6 @@
 
 #include "third_party/blink/renderer/platform/graphics/video_frame_submitter.h"
 
-#include <vector>
-
 #include "base/task_runner.h"
 #include "base/threading/sequenced_task_runner_handle.h"
 #include "base/trace_event/trace_event.h"
@@ -13,6 +11,7 @@
 #include "cc/scheduler/video_frame_controller.h"
 #include "components/viz/common/resources/resource_id.h"
 #include "components/viz/common/resources/returned_resource.h"
+#include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
 #include "media/base/video_frame.h"
 #include "services/ui/public/cpp/gpu/context_provider_command_buffer.h"
 #include "services/viz/public/interfaces/compositing/compositor_frame_sink.mojom-blink.h"
@@ -51,29 +50,16 @@
 }
 
 void VideoFrameSubmitter::EnableSubmission(
-    viz::SurfaceId id,
+    viz::FrameSinkId id,
     WebFrameSinkDestroyedCallback frame_sink_destroyed_callback) {
   // TODO(lethalantidote): Set these fields earlier in the constructor. Will
   // need to construct VideoFrameSubmitter later in order to do this.
-  surface_id_ = id;
+  frame_sink_id_ = id;
   frame_sink_destroyed_callback_ = frame_sink_destroyed_callback;
   if (resource_provider_->IsInitialized())
     StartSubmitting();
 }
 
-void VideoFrameSubmitter::UpdateSubmissionState(bool should_submit) {
-  should_submit_ = should_submit;
-  UpdateSubmissionStateInternal();
-}
-
-void VideoFrameSubmitter::UpdateSubmissionStateInternal() {
-  if (compositor_frame_sink_) {
-    compositor_frame_sink_->SetNeedsBeginFrame(is_rendering_ && should_submit_);
-    if (should_submit_)
-      SubmitSingleFrame();
-  }
-}
-
 void VideoFrameSubmitter::StopUsingProvider() {
   DCHECK_CALLED_ON_VALID_THREAD(media_thread_checker_);
   if (is_rendering_)
@@ -86,8 +72,12 @@
   DCHECK(is_rendering_);
   DCHECK(provider_);
 
+  if (compositor_frame_sink_) {
+    // Push out final frame.
+    SubmitSingleFrame();
+    compositor_frame_sink_->SetNeedsBeginFrame(false);
+  }
   is_rendering_ = false;
-  UpdateSubmissionStateInternal();
 }
 
 void VideoFrameSubmitter::SubmitSingleFrame() {
@@ -99,13 +89,11 @@
   viz::BeginFrameAck current_begin_frame_ack =
       viz::BeginFrameAck::CreateManualAckWithDamage();
   scoped_refptr<media::VideoFrame> video_frame = provider_->GetCurrentFrame();
-  if (video_frame) {
-    base::SequencedTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE, base::BindOnce(&VideoFrameSubmitter::SubmitFrame,
-                                  weak_ptr_factory_.GetWeakPtr(),
-                                  current_begin_frame_ack, video_frame));
-    provider_->PutCurrentFrame();
-  }
+  base::SequencedTaskRunnerHandle::Get()->PostTask(
+      FROM_HERE, base::BindOnce(&VideoFrameSubmitter::SubmitFrame,
+                                weak_ptr_factory_.GetWeakPtr(),
+                                current_begin_frame_ack, video_frame));
+  provider_->PutCurrentFrame();
 }
 
 void VideoFrameSubmitter::DidReceiveFrame() {
@@ -122,10 +110,9 @@
 void VideoFrameSubmitter::StartRendering() {
   DCHECK_CALLED_ON_VALID_THREAD(media_thread_checker_);
   DCHECK(!is_rendering_);
-  is_rendering_ = true;
-
   if (compositor_frame_sink_)
-    compositor_frame_sink_->SetNeedsBeginFrame(is_rendering_ && should_submit_);
+    compositor_frame_sink_->SetNeedsBeginFrame(true);
+  is_rendering_ = true;
 }
 
 void VideoFrameSubmitter::Initialize(cc::VideoFrameProvider* provider) {
@@ -162,13 +149,13 @@
     resource_provider_->Initialize(nullptr, this);
   }
 
-  if (surface_id_.is_valid())
+  if (frame_sink_id_.is_valid())
     StartSubmitting();
 }
 
 void VideoFrameSubmitter::StartSubmitting() {
   DCHECK_CALLED_ON_VALID_THREAD(media_thread_checker_);
-  DCHECK(surface_id_.is_valid());
+  DCHECK(frame_sink_id_.is_valid());
 
   mojom::blink::EmbeddedFrameSinkProviderPtr provider;
   Platform::Current()->GetInterfaceProvider()->GetInterface(
@@ -177,13 +164,25 @@
   viz::mojom::blink::CompositorFrameSinkClientPtr client;
   binding_.Bind(mojo::MakeRequest(&client));
   provider->CreateCompositorFrameSink(
-      surface_id_.frame_sink_id(), std::move(client),
+      frame_sink_id_, std::move(client),
       mojo::MakeRequest(&compositor_frame_sink_));
 
   compositor_frame_sink_.set_connection_error_handler(base::BindOnce(
       &VideoFrameSubmitter::OnContextLost, base::Unretained(this)));
 
-  UpdateSubmissionStateInternal();
+  if (is_rendering_)
+    compositor_frame_sink_->SetNeedsBeginFrame(true);
+
+  scoped_refptr<media::VideoFrame> video_frame = provider_->GetCurrentFrame();
+  if (video_frame) {
+    viz::BeginFrameAck current_begin_frame_ack =
+        viz::BeginFrameAck::CreateManualAckWithDamage();
+    base::SequencedTaskRunnerHandle::Get()->PostTask(
+        FROM_HERE, base::BindOnce(&VideoFrameSubmitter::SubmitFrame,
+                                  weak_ptr_factory_.GetWeakPtr(),
+                                  current_begin_frame_ack, video_frame));
+    provider_->PutCurrentFrame();
+  }
 }
 
 void VideoFrameSubmitter::SubmitFrame(
@@ -191,7 +190,10 @@
     scoped_refptr<media::VideoFrame> video_frame) {
   TRACE_EVENT0("media", "VideoFrameSubmitter::SubmitFrame");
   DCHECK_CALLED_ON_VALID_THREAD(media_thread_checker_);
-  if (!compositor_frame_sink_ || !should_submit_)
+
+  // The context may have been destroyed between the call being scheduled and it
+  // running. The lack of compositor_frame_sink_ is used as a sign.
+  if (!compositor_frame_sink_)
     return;
 
   viz::CompositorFrame compositor_frame;
@@ -217,9 +219,15 @@
                                           &compositor_frame.resource_list);
   compositor_frame.render_pass_list.push_back(std::move(render_pass));
 
+  if (compositor_frame.size_in_pixels() != current_size_in_pixels_) {
+    parent_local_surface_id_allocator_.GenerateId();
+    current_size_in_pixels_ = compositor_frame.size_in_pixels();
+  }
+
   // TODO(lethalantidote): Address third/fourth arg in SubmitCompositorFrame.
   compositor_frame_sink_->SubmitCompositorFrame(
-      surface_id_.local_surface_id(), std::move(compositor_frame), nullptr, 0);
+      parent_local_surface_id_allocator_.GetCurrentLocalSurfaceId(),
+      std::move(compositor_frame), nullptr, 0);
   resource_provider_->ReleaseFrameResources();
 
   waiting_for_compositor_ack_ = true;
@@ -228,8 +236,7 @@
 void VideoFrameSubmitter::OnBeginFrame(const viz::BeginFrameArgs& args) {
   TRACE_EVENT0("media", "VideoFrameSubmitter::OnBeginFrame");
   DCHECK_CALLED_ON_VALID_THREAD(media_thread_checker_);
-  viz::BeginFrameAck current_begin_frame_ack =
-      viz::BeginFrameAck(args.source_id, args.sequence_number, false);
+  viz::BeginFrameAck current_begin_frame_ack(args, false);
   if (args.type == viz::BeginFrameArgs::MISSED) {
     compositor_frame_sink_->DidNotProduceFrame(current_begin_frame_ack);
     return;
@@ -273,18 +280,14 @@
   }
   waiting_for_compositor_ack_ = false;
 
+  resource_provider_->OnContextLost();
+
   // |compositor_frame_sink_| should be reset last.
   compositor_frame_sink_.reset();
 
-  resource_provider_->OnContextLost();
   context_provider_callback_.Run(
       base::BindOnce(&VideoFrameSubmitter::OnReceivedContextProvider,
                      weak_ptr_factory_.GetWeakPtr()));
-
-  // We need to trigger another submit so that surface_id's get propagated
-  // correctly. If we don't, we don't get any more signals to update the
-  // submission state.
-  should_submit_ = true;
 }
 
 void VideoFrameSubmitter::DidReceiveCompositorFrameAck(
diff --git a/third_party/blink/renderer/platform/graphics/video_frame_submitter.h b/third_party/blink/renderer/platform/graphics/video_frame_submitter.h
index aa95cf0..0f8d3934 100644
--- a/third_party/blink/renderer/platform/graphics/video_frame_submitter.h
+++ b/third_party/blink/renderer/platform/graphics/video_frame_submitter.h
@@ -5,14 +5,12 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_VIDEO_FRAME_SUBMITTER_H_
 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_VIDEO_FRAME_SUBMITTER_H_
 
-#include <memory>
-#include <utility>
-
 #include "base/memory/weak_ptr.h"
 #include "base/threading/thread_checker.h"
 #include "components/viz/client/shared_bitmap_reporter.h"
 #include "components/viz/common/gpu/context_provider.h"
 #include "components/viz/common/resources/shared_bitmap.h"
+#include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
 #include "mojo/public/cpp/bindings/binding.h"
 #include "mojo/public/cpp/system/buffer.h"
 #include "services/viz/public/interfaces/compositing/compositor_frame_sink.mojom-blink.h"
@@ -39,7 +37,7 @@
 
   ~VideoFrameSubmitter() override;
 
-  bool Rendering() { return is_rendering_; }
+  bool Rendering() { return is_rendering_; };
   cc::VideoFrameProvider* Provider() { return provider_; }
   mojo::Binding<viz::mojom::blink::CompositorFrameSinkClient>* Binding() {
     return &binding_;
@@ -47,7 +45,6 @@
   void SetSink(viz::mojom::blink::CompositorFrameSinkPtr* sink) {
     compositor_frame_sink_ = std::move(*sink);
   }
-  void SetSurfaceId(viz::SurfaceId id) { surface_id_ = id; }
 
   void OnReceivedContextProvider(
       bool,
@@ -62,8 +59,8 @@
   // WebVideoFrameSubmitter implementation.
   void Initialize(cc::VideoFrameProvider*) override;
   void SetRotation(media::VideoRotation) override;
-  void EnableSubmission(viz::SurfaceId, WebFrameSinkDestroyedCallback) override;
-  void UpdateSubmissionState(bool) override;
+  void EnableSubmission(viz::FrameSinkId,
+                        WebFrameSinkDestroyedCallback) override;
 
   // viz::ContextLostObserver implementation.
   void OnContextLost() override;
@@ -86,11 +83,8 @@
 
  private:
   FRIEND_TEST_ALL_PREFIXES(VideoFrameSubmitterTest, ContextLostDuringSubmit);
-  FRIEND_TEST_ALL_PREFIXES(VideoFrameSubmitterTest,
-                           ShouldSubmitPreventsSubmission);
 
   void StartSubmitting();
-  void UpdateSubmissionStateInternal();
   void SubmitFrame(const viz::BeginFrameAck&, scoped_refptr<media::VideoFrame>);
 
   // Pulls frame and submits it to compositor.
@@ -103,16 +97,16 @@
   scoped_refptr<ui::ContextProviderCommandBuffer> context_provider_;
   viz::mojom::blink::CompositorFrameSinkPtr compositor_frame_sink_;
   mojo::Binding<viz::mojom::blink::CompositorFrameSinkClient> binding_;
+  viz::ParentLocalSurfaceIdAllocator parent_local_surface_id_allocator_;
   WebContextProviderCallback context_provider_callback_;
   std::unique_ptr<VideoFrameResourceProvider> resource_provider_;
   WebFrameSinkDestroyedCallback frame_sink_destroyed_callback_;
-  viz::SurfaceId surface_id_;
+  viz::FrameSinkId frame_sink_id_;
   bool waiting_for_compositor_ack_ = false;
 
   bool is_rendering_;
-  // If we are not on screen, we should not submit.
-  bool should_submit_ = false;
   media::VideoRotation rotation_;
+  gfx::Size current_size_in_pixels_;
 
   THREAD_CHECKER(media_thread_checker_);
 
diff --git a/third_party/blink/renderer/platform/graphics/video_frame_submitter_test.cc b/third_party/blink/renderer/platform/graphics/video_frame_submitter_test.cc
index 4512c5f..addcc897 100644
--- a/third_party/blink/renderer/platform/graphics/video_frame_submitter_test.cc
+++ b/third_party/blink/renderer/platform/graphics/video_frame_submitter_test.cc
@@ -157,15 +157,7 @@
     viz::mojom::blink::CompositorFrameSinkRequest request =
         mojo::MakeRequest(&submitter_sink);
     sink_ = std::make_unique<StrictMock<MockCompositorFrameSink>>(&request);
-
-    // By setting the submission state before we set the sink, we can make
-    // testing easier without having to worry about the first sent frame.
-    submitter_->UpdateSubmissionState(true);
     submitter_->SetSink(&submitter_sink);
-    submitter_->SetSurfaceId(viz::SurfaceId(
-        viz::FrameSinkId(1, 1),
-        viz::LocalSurfaceId(11,
-                            base::UnguessableToken::Deserialize(0x111111, 0))));
   }
 
  protected:
@@ -270,44 +262,6 @@
   scoped_task_environment_.RunUntilIdle();
 }
 
-TEST_F(VideoFrameSubmitterTest, ShouldSubmitPreventsSubmission) {
-  MakeSubmitter();
-  scoped_task_environment_.RunUntilIdle();
-
-  EXPECT_CALL(*sink_, SetNeedsBeginFrame(false));
-  submitter_->UpdateSubmissionState(false);
-  scoped_task_environment_.RunUntilIdle();
-
-  EXPECT_CALL(*sink_, SetNeedsBeginFrame(false));
-  submitter_->StartRendering();
-  scoped_task_environment_.RunUntilIdle();
-
-  EXPECT_CALL(*sink_, SetNeedsBeginFrame(true));
-  EXPECT_CALL(*provider_, GetCurrentFrame())
-      .WillOnce(Return(media::VideoFrame::CreateFrame(
-          media::PIXEL_FORMAT_YV12, gfx::Size(8, 8), gfx::Rect(gfx::Size(8, 8)),
-          gfx::Size(8, 8), base::TimeDelta())));
-  EXPECT_CALL(*sink_, DoSubmitCompositorFrame(_, _));
-  EXPECT_CALL(*provider_, PutCurrentFrame());
-  EXPECT_CALL(*resource_provider_, AppendQuads(_, _, _));
-  EXPECT_CALL(*resource_provider_, PrepareSendToParent(_, _));
-  EXPECT_CALL(*resource_provider_, ReleaseFrameResources());
-  submitter_->UpdateSubmissionState(true);
-  scoped_task_environment_.RunUntilIdle();
-
-  EXPECT_CALL(*sink_, SetNeedsBeginFrame(false));
-  submitter_->UpdateSubmissionState(false);
-  scoped_task_environment_.RunUntilIdle();
-
-  EXPECT_CALL(*provider_, GetCurrentFrame())
-      .WillOnce(Return(media::VideoFrame::CreateFrame(
-          media::PIXEL_FORMAT_YV12, gfx::Size(8, 8), gfx::Rect(gfx::Size(8, 8)),
-          gfx::Size(8, 8), base::TimeDelta())));
-  EXPECT_CALL(*provider_, PutCurrentFrame());
-
-  submitter_->SubmitSingleFrame();
-}
-
 TEST_F(VideoFrameSubmitterTest, RotationInformationPassedToResourceProvider) {
   // Check to see if rotation is communicated pre-rendering.
   MakeSubmitter();
diff --git a/third_party/blink/renderer/platform/heap/heap_allocator.h b/third_party/blink/renderer/platform/heap/heap_allocator.h
index 814264b..67d88e1 100644
--- a/third_party/blink/renderer/platform/heap/heap_allocator.h
+++ b/third_party/blink/renderer/platform/heap/heap_allocator.h
@@ -168,6 +168,10 @@
     return ThreadState::Current()->IsObjectResurrectionForbidden();
   }
 
+  static bool IsSweepForbidden() {
+    return ThreadState::Current()->SweepForbidden();
+  }
+
   template <typename T>
   static bool IsHeapObjectAlive(T* object) {
     return ThreadHeap::IsHeapObjectAlive(object);
diff --git a/third_party/blink/renderer/platform/heap/heap_test.cc b/third_party/blink/renderer/platform/heap/heap_test.cc
index c3d7ad9e..e2b4b38 100644
--- a/third_party/blink/renderer/platform/heap/heap_test.cc
+++ b/third_party/blink/renderer/platform/heap/heap_test.cc
@@ -6882,4 +6882,49 @@
   PreciselyCollectGarbage();
 }
 
+TEST(HeapTest, PromptlyFreeStackAllocatedHeapHashSet) {
+  NormalPageArena* normal_arena = static_cast<NormalPageArena*>(
+      ThreadState::Current()->Heap().Arena(BlinkGC::kHashTableArenaIndex));
+  CHECK(normal_arena);
+  Address before;
+  {
+    HeapHashSet<Member<IntWrapper>> hash_set;
+    hash_set.insert(new IntWrapper(0));
+    before = normal_arena->CurrentAllocationPoint();
+  }
+  Address after = normal_arena->CurrentAllocationPoint();
+  // We check the allocation point to see if promptly freed
+  EXPECT_NE(after, before);
+}
+
+TEST(HeapTest, PromptlyFreeStackAllocatedHeapListHashSet) {
+  NormalPageArena* normal_arena = static_cast<NormalPageArena*>(
+      ThreadState::Current()->Heap().Arena(BlinkGC::kHashTableArenaIndex));
+  CHECK(normal_arena);
+  Address before;
+  {
+    HeapListHashSet<Member<IntWrapper>> list_hash_set;
+    list_hash_set.insert(new IntWrapper(0));
+    before = normal_arena->CurrentAllocationPoint();
+  }
+  Address after = normal_arena->CurrentAllocationPoint();
+  // We check the allocation point to see if promptly freed
+  EXPECT_NE(after, before);
+}
+
+TEST(HeapTest, PromptlyFreeStackAllocatedHeapLinkedHashSet) {
+  NormalPageArena* normal_arena = static_cast<NormalPageArena*>(
+      ThreadState::Current()->Heap().Arena(BlinkGC::kHashTableArenaIndex));
+  CHECK(normal_arena);
+  Address before;
+  {
+    HeapLinkedHashSet<Member<IntWrapper>> linked_hash_set;
+    linked_hash_set.insert(new IntWrapper(0));
+    before = normal_arena->CurrentAllocationPoint();
+  }
+  Address after = normal_arena->CurrentAllocationPoint();
+  // We check the allocation point to see if promptly freed
+  EXPECT_NE(after, before);
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/heap/incremental_marking_test.cc b/third_party/blink/renderer/platform/heap/incremental_marking_test.cc
index 1815ff8..1612347 100644
--- a/third_party/blink/renderer/platform/heap/incremental_marking_test.cc
+++ b/third_party/blink/renderer/platform/heap/incremental_marking_test.cc
@@ -844,10 +844,11 @@
 void Move() {
   Object* obj = Object::Create();
   Container container1;
+  Container container2;
   container1.insert(obj);
   {
     ExpectWriteBarrierFires scope(ThreadState::Current(), {obj});
-    Container container2(std::move(container1));
+    container2 = std::move(container1);
   }
 }
 
diff --git a/third_party/blink/renderer/platform/image-encoders/image_encoder.cc b/third_party/blink/renderer/platform/image-encoders/image_encoder.cc
index 4c450f5d..b564b1cc 100644
--- a/third_party/blink/renderer/platform/image-encoders/image_encoder.cc
+++ b/third_party/blink/renderer/platform/image-encoders/image_encoder.cc
@@ -87,11 +87,8 @@
   return compression_quality;
 }
 
-SkWebpEncoder::Options ImageEncoder::ComputeWebpOptions(
-    double quality,
-    SkTransferFunctionBehavior unpremulBehavior) {
+SkWebpEncoder::Options ImageEncoder::ComputeWebpOptions(double quality) {
   SkWebpEncoder::Options options;
-  options.fUnpremulBehavior = unpremulBehavior;
 
   if (quality == 1.0) {
     // Choose a lossless encode.  When performing a lossless encode, higher
diff --git a/third_party/blink/renderer/platform/image-encoders/image_encoder.h b/third_party/blink/renderer/platform/image-encoders/image_encoder.h
index 4030609..3822c4a8 100644
--- a/third_party/blink/renderer/platform/image-encoders/image_encoder.h
+++ b/third_party/blink/renderer/platform/image-encoders/image_encoder.h
@@ -85,9 +85,7 @@
    *  is out of range, this will perform a lossy encode with the default
    *  value (80).
    */
-  static SkWebpEncoder::Options ComputeWebpOptions(
-      double quality,
-      SkTransferFunctionBehavior unpremulBehavior);
+  static SkWebpEncoder::Options ComputeWebpOptions(double quality);
 
  private:
   ImageEncoder(Vector<unsigned char>* dst) : dst_(dst) {}
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
index 8aaee455..6665dfad 100644
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -1229,6 +1229,10 @@
       status: "test",
     },
     {
+      name: "TextUnderlinePositionLeftRight",
+      status: "experimental",
+    },
+    {
       name: "TimerThrottlingForBackgroundTabs",
       status: "stable",
     },
diff --git a/third_party/blink/renderer/platform/scheduler/util/thread_cpu_throttler.cc b/third_party/blink/renderer/platform/scheduler/util/thread_cpu_throttler.cc
index 20238652..a38dd34 100644
--- a/third_party/blink/renderer/platform/scheduler/util/thread_cpu_throttler.cc
+++ b/third_party/blink/renderer/platform/scheduler/util/thread_cpu_throttler.cc
@@ -11,7 +11,7 @@
 #include "base/threading/platform_thread.h"
 #include "build/build_config.h"
 
-#if defined(OS_POSIX) && !defined(OS_FUCHSIA)
+#if defined(OS_POSIX)
 #include <signal.h>
 #define USE_SIGNALS 1
 #elif defined(OS_WIN)
diff --git a/third_party/blink/renderer/platform/testing/OWNERS b/third_party/blink/renderer/platform/testing/OWNERS
new file mode 100644
index 0000000..7a40d39
--- /dev/null
+++ b/third_party/blink/renderer/platform/testing/OWNERS
@@ -0,0 +1 @@
+per-file testing_platform_support_with_web_rtc.*=hbos@chromium.org
diff --git a/third_party/blink/renderer/platform/testing/shape_result_perf_test.cc b/third_party/blink/renderer/platform/testing/shape_result_perf_test.cc
deleted file mode 100644
index 008e697d..0000000
--- a/third_party/blink/renderer/platform/testing/shape_result_perf_test.cc
+++ /dev/null
@@ -1,170 +0,0 @@
-// Copyright (c) 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/time/time.h"
-#include "cc/base/lap_timer.h"
-
-#include "build/build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/perf/perf_test.h"
-#include "third_party/blink/renderer/platform/fonts/font.h"
-#include "third_party/blink/renderer/platform/fonts/font_description.h"
-#include "third_party/blink/renderer/platform/testing/font_test_helpers.h"
-#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
-
-using blink::test::CreateTestFont;
-
-namespace blink {
-
-static const int kTimeLimitMillis = 3000;
-static const int kWarmupRuns = 10000;
-static const int kTimeCheckInterval = 1000000;
-
-class ShapeResultPerfTest {
- public:
-  enum FontName {
-    ahem,
-    amiri,
-    megalopolis,
-    roboto,
-  };
-
-  ShapeResultPerfTest()
-      : timer(kWarmupRuns,
-              base::TimeDelta::FromMilliseconds(kTimeLimitMillis),
-              kTimeCheckInterval) {}
-
- protected:
-  TextRun SetupFont(FontName font_name, const String& text, bool ltr) {
-    FontDescription::VariantLigatures ligatures(
-        FontDescription::kEnabledLigaturesState);
-    font = CreateTestFont("TestFont",
-                          test::PlatformTestDataPath(font_path[font_name]), 100,
-                          &ligatures);
-
-    return TextRun(
-        text, /* xpos */ 0, /* expansion */ 0,
-        TextRun::kAllowTrailingExpansion | TextRun::kForbidLeadingExpansion,
-        ltr ? TextDirection::kLtr : TextDirection::kRtl, false);
-  }
-
-  Font font;
-
-  std::map<FontName, String> font_path = {
-      {ahem, "Ahem.woff"},
-      {amiri, "third_party/Amiri/amiri_arabic.woff2"},
-      {megalopolis, "third_party/MEgalopolis/MEgalopolisExtra.woff"},
-      {roboto, "third_party/Roboto/roboto-regular.woff2"},
-  };
-
-  cc::LapTimer timer;
-};
-
-class OffsetForPositionPerfTest : public ShapeResultPerfTest,
-                                  public testing::TestWithParam<float> {
- public:
-  void OffsetForPosition(TextRun& run,
-                         IncludePartialGlyphsOption partial,
-                         BreakGlyphsOption breakopt) {
-    timer.Reset();
-    float position = GetParam();
-    do {
-      font.OffsetForPosition(run, position, partial, breakopt);
-      timer.NextLap();
-    } while (!timer.HasTimeLimitExpired());
-  }
-};
-
-class CharacterRangePerfTest : public ShapeResultPerfTest,
-                               public testing::TestWithParam<int> {
- public:
-  void GetCharacter(TextRun& run) {
-    timer.Reset();
-    int endpos = GetParam();
-    do {
-      font.SelectionRectForText(run, FloatPoint(), 100, 0, endpos);
-      timer.NextLap();
-    } while (!timer.HasTimeLimitExpired());
-  }
-};
-
-TEST_P(OffsetForPositionPerfTest, LTROffsetForPositionFullBreak) {
-  TextRun run = SetupFont(ahem, "FURACOLO", true);
-  OffsetForPosition(run, OnlyFullGlyphs, BreakGlyphs);
-  perf_test::PrintResult("OffsetForPositionPerfTest", " LTR full break", "",
-                         timer.LapsPerSecond(), "runs/s", true);
-}
-
-TEST_P(OffsetForPositionPerfTest, LTROffsetForPositionFullDontBreak) {
-  TextRun run = SetupFont(ahem, "FURACOLO", true);
-  OffsetForPosition(run, OnlyFullGlyphs, DontBreakGlyphs);
-  perf_test::PrintResult("OffsetForPositionPerfTest", " LTR full", "",
-                         timer.LapsPerSecond(), "runs/s", true);
-}
-
-TEST_P(OffsetForPositionPerfTest, LTROffsetForPositionIncludePartialBreak) {
-  TextRun run = SetupFont(ahem, "FURACOLO", true);
-  OffsetForPosition(run, IncludePartialGlyphs, BreakGlyphs);
-  perf_test::PrintResult("OffsetForPositionPerfTest", " LTR partial break", "",
-                         timer.LapsPerSecond(), "runs/s", true);
-}
-
-TEST_P(OffsetForPositionPerfTest, LTROffsetForPositionIncludePartialDontBreak) {
-  TextRun run = SetupFont(ahem, "FURACOLO", true);
-  OffsetForPosition(run, IncludePartialGlyphs, DontBreakGlyphs);
-  perf_test::PrintResult("OffsetForPositionPerfTest", " LTR partial", "",
-                         timer.LapsPerSecond(), "runs/s", true);
-}
-
-TEST_P(OffsetForPositionPerfTest, RTLOffsetForPositionFullBreak) {
-  TextRun run = SetupFont(ahem, "OLOCARUF", false);
-  OffsetForPosition(run, OnlyFullGlyphs, BreakGlyphs);
-  perf_test::PrintResult("OffsetForPositionPerfTest", " RTL full break", "",
-                         timer.LapsPerSecond(), "runs/s", true);
-}
-
-TEST_P(OffsetForPositionPerfTest, RTLOffsetForPositionFullDontBreak) {
-  TextRun run = SetupFont(ahem, "OLOCARUF", false);
-  OffsetForPosition(run, OnlyFullGlyphs, DontBreakGlyphs);
-  perf_test::PrintResult("OffsetForPositionPerfTest", " RTL full", "",
-                         timer.LapsPerSecond(), "runs/s", true);
-}
-
-TEST_P(OffsetForPositionPerfTest, RTLOffsetForPositionIncludePartialBreak) {
-  TextRun run = SetupFont(ahem, "OLOCARUF", false);
-  OffsetForPosition(run, IncludePartialGlyphs, BreakGlyphs);
-  perf_test::PrintResult("OffsetForPositionPerfTest", " RTL partial break", "",
-                         timer.LapsPerSecond(), "runs/s", true);
-}
-
-TEST_P(OffsetForPositionPerfTest, RTLOffsetForPositionIncludePartialDontBreak) {
-  TextRun run = SetupFont(ahem, "OLOCARUF", false);
-  OffsetForPosition(run, IncludePartialGlyphs, DontBreakGlyphs);
-  perf_test::PrintResult("OffsetForPositionPerfTest", " RTL partial", "",
-                         timer.LapsPerSecond(), "runs/s", true);
-}
-
-INSTANTIATE_TEST_CASE_P(OffsetForPosition,
-                        OffsetForPositionPerfTest,
-                        testing::Values(0, 10, 60, 100, 200, 350));
-
-TEST_P(CharacterRangePerfTest, LTRCharacterForPosition) {
-  TextRun run = SetupFont(ahem, "FURACOLO", true);
-  GetCharacter(run);
-  perf_test::PrintResult("CharacterRangePerfTest", " LTR", "",
-                         timer.LapsPerSecond(), "runs/s", true);
-}
-
-TEST_P(CharacterRangePerfTest, RTLCharacterForPosition) {
-  TextRun run = SetupFont(ahem, "OLOCARUF", false);
-  GetCharacter(run);
-  perf_test::PrintResult("CharacterRangePerfTest", " RTL", "",
-                         timer.LapsPerSecond(), "runs/s", true);
-}
-
-INSTANTIATE_TEST_CASE_P(CharacterRange,
-                        CharacterRangePerfTest,
-                        testing::Values(0, 1, 2, 4, 8));
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/platform/text/text_break_iterator.cc b/third_party/blink/renderer/platform/text/text_break_iterator.cc
index bc6d101..2373b2f 100644
--- a/third_party/blink/renderer/platform/text/text_break_iterator.cc
+++ b/third_party/blink/renderer/platform/text/text_break_iterator.cc
@@ -53,7 +53,8 @@
   return num;
 }
 
-void GraphemesClusterList(String text,
+void GraphemesClusterList(const UChar* text,
+                          unsigned text_length,
                           unsigned start,
                           unsigned length,
                           Vector<unsigned>* graphemes) {
@@ -61,8 +62,8 @@
   if (!length)
     return;
 
-  String substring = text.Substring(start, length);
-  NonSharedCharacterBreakIterator it(substring);
+  DCHECK_LE(static_cast<unsigned>(start + length), text_length);
+  NonSharedCharacterBreakIterator it(&text[start], length);
 
   int cursor_pos = it.Next();
   unsigned count = 0;
diff --git a/third_party/blink/renderer/platform/text/text_break_iterator.h b/third_party/blink/renderer/platform/text/text_break_iterator.h
index 958e3f8..a578d46 100644
--- a/third_party/blink/renderer/platform/text/text_break_iterator.h
+++ b/third_party/blink/renderer/platform/text/text_break_iterator.h
@@ -365,7 +365,8 @@
 
 // Returns a list of graphemes cluster at each character using character break
 // rules.
-PLATFORM_EXPORT void GraphemesClusterList(String text,
+PLATFORM_EXPORT void GraphemesClusterList(const UChar* text,
+                                          unsigned text_length,
                                           unsigned start,
                                           unsigned length,
                                           Vector<unsigned>* graphemes);
diff --git a/third_party/blink/renderer/platform/text/text_break_iterator_test.cc b/third_party/blink/renderer/platform/text/text_break_iterator_test.cc
index fd23955..1c70153 100644
--- a/third_party/blink/renderer/platform/text/text_break_iterator_test.cc
+++ b/third_party/blink/renderer/platform/text/text_break_iterator_test.cc
@@ -75,7 +75,8 @@
                                         unsigned start,
                                         unsigned length) {
     Vector<unsigned> result;
-    ::blink::GraphemesClusterList(input, start, length, &result);
+    ::blink::GraphemesClusterList(input.Characters16(), input.length(), start,
+                                  length, &result);
     return result;
   }
 
diff --git a/third_party/blink/renderer/platform/wtf/allocator/partition_allocator.h b/third_party/blink/renderer/platform/wtf/allocator/partition_allocator.h
index 590dd0b..cbd0f90 100644
--- a/third_party/blink/renderer/platform/wtf/allocator/partition_allocator.h
+++ b/third_party/blink/renderer/platform/wtf/allocator/partition_allocator.h
@@ -105,6 +105,7 @@
 
   static bool IsAllocationAllowed() { return true; }
   static bool IsObjectResurrectionForbidden() { return false; }
+  static bool IsSweepForbidden() { return false; }
 
   static void EnterGCForbiddenScope() {}
   static void LeaveGCForbiddenScope() {}
diff --git a/third_party/blink/renderer/platform/wtf/hash_table.h b/third_party/blink/renderer/platform/wtf/hash_table.h
index 2bacf9fe..f47d1d6a 100644
--- a/third_party/blink/renderer/platform/wtf/hash_table.h
+++ b/third_party/blink/renderer/platform/wtf/hash_table.h
@@ -29,7 +29,6 @@
 #include "third_party/blink/renderer/platform/wtf/allocator.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/partition_allocator.h"
 #include "third_party/blink/renderer/platform/wtf/assertions.h"
-#include "third_party/blink/renderer/platform/wtf/conditional_destructor.h"
 #include "third_party/blink/renderer/platform/wtf/construct_traits.h"
 #include "third_party/blink/renderer/platform/wtf/hash_traits.h"
 
@@ -691,15 +690,7 @@
           typename Traits,
           typename KeyTraits,
           typename Allocator>
-class HashTable final
-    : public ConditionalDestructor<HashTable<Key,
-                                             Value,
-                                             Extractor,
-                                             HashFunctions,
-                                             Traits,
-                                             KeyTraits,
-                                             Allocator>,
-                                   Allocator::kIsGarbageCollected> {
+class HashTable final {
   DISALLOW_NEW();
 
  public:
@@ -730,10 +721,16 @@
   typedef HashTableAddResult<HashTable, ValueType> AddResult;
 
   HashTable();
-  void Finalize() {
-    DCHECK(!Allocator::kIsGarbageCollected);
+
+  // For design of the destructor, please refer to
+  // [here](https://docs.google.com/document/d/1AoGTvb3tNLx2tD1hNqAfLRLmyM59GM0O-7rCHTT_7_U/)
+  ~HashTable() {
     if (LIKELY(!table_))
       return;
+    // If this is called during sweeping, it must not touch other heap objects
+    // such as the backing.
+    if (Allocator::IsSweepForbidden())
+      return;
     EnterAccessForbiddenScope();
     DeleteAllBucketsAndDeallocate(table_, table_size_);
     LeaveAccessForbiddenScope();
diff --git a/third_party/blink/renderer/platform/wtf/list_hash_set.h b/third_party/blink/renderer/platform/wtf/list_hash_set.h
index 236fb65..ddc89aa 100644
--- a/third_party/blink/renderer/platform/wtf/list_hash_set.h
+++ b/third_party/blink/renderer/platform/wtf/list_hash_set.h
@@ -76,10 +76,7 @@
           typename HashArg = typename DefaultHash<ValueArg>::Hash,
           typename AllocatorArg =
               ListHashSetAllocator<ValueArg, inlineCapacity>>
-class ListHashSet
-    : public ConditionalDestructor<
-          ListHashSet<ValueArg, inlineCapacity, HashArg, AllocatorArg>,
-          AllocatorArg::kIsGarbageCollected> {
+class ListHashSet {
   typedef AllocatorArg Allocator;
   USE_ALLOCATOR(ListHashSet, Allocator);
 
@@ -149,7 +146,7 @@
   ListHashSet(ListHashSet&&);
   ListHashSet& operator=(const ListHashSet&);
   ListHashSet& operator=(ListHashSet&&);
-  void Finalize();
+  ~ListHashSet();
 
   void Swap(ListHashSet&);
 
@@ -798,10 +795,14 @@
   allocator_provider_.Swap(other.allocator_provider_);
 }
 
+// For design of the destructor, please refer to
+// [here](https://docs.google.com/document/d/1AoGTvb3tNLx2tD1hNqAfLRLmyM59GM0O-7rCHTT_7_U/)
 template <typename T, size_t inlineCapacity, typename U, typename V>
-inline void ListHashSet<T, inlineCapacity, U, V>::Finalize() {
-  static_assert(!Allocator::kIsGarbageCollected,
-                "heap allocated ListHashSet should never call finalize()");
+inline ListHashSet<T, inlineCapacity, U, V>::~ListHashSet() {
+  // If this is called during GC sweeping, it must not touch other heap objects
+  // such as the ListHashSetNodes that is touching in DeleteAllNodes().
+  if (Allocator::IsSweepForbidden())
+    return;
   DeleteAllNodes();
   allocator_provider_.ReleaseAllocator();
 }
diff --git a/third_party/blink/renderer/platform/wtf/text/movable_string.cc b/third_party/blink/renderer/platform/wtf/text/movable_string.cc
index c193c423..fdfa440 100644
--- a/third_party/blink/renderer/platform/wtf/text/movable_string.cc
+++ b/third_party/blink/renderer/platform/wtf/text/movable_string.cc
@@ -4,16 +4,13 @@
 
 #include "third_party/blink/renderer/platform/wtf/text/movable_string.h"
 
-#include <string.h>
-
 #include "base/metrics/histogram_macros.h"
 
 namespace WTF {
 
 namespace {
 
-template <typename T>
-bool IsLargeEnough(const T* impl) {
+bool IsLargeEnough(const StringImpl* impl) {
   // Don't attempt to park strings smaller than this size.
   static constexpr unsigned int kSizeThreshold = 10000;
   return impl && impl->length() > kSizeThreshold;
@@ -28,28 +25,18 @@
 MovableStringImpl::MovableStringImpl() = default;
 
 MovableStringImpl::MovableStringImpl(scoped_refptr<StringImpl>&& impl)
-    : is_parked_(false),
-      string_(std::move(impl))
-#if DCHECK_IS_ON()
-      ,
-      parked_string_()
-#endif
-{
-  is_null_ = string_.IsNull();
-  is_8bit_ = is_null_ ? false : string_.Is8Bit();
-  length_ = is_null_ ? 0 : string_.length();
-}
+    : string_(std::move(impl)), is_parked_(false) {}
 
 MovableStringImpl::~MovableStringImpl() {
-  MovableStringTable::Instance().Remove(this, string_.Impl());
+  MovableStringTable::Instance().Remove(string_.Impl());
 }
 
 bool MovableStringImpl::Is8Bit() const {
-  return is_8bit_;
+  return string_.Is8Bit();
 }
 
 bool MovableStringImpl::IsNull() const {
-  return is_null_;
+  return string_.IsNull();
 }
 
 const String& MovableStringImpl::ToString() {
@@ -58,24 +45,13 @@
 }
 
 unsigned MovableStringImpl::CharactersSizeInBytes() const {
-  return length() * (Is8Bit() ? sizeof(LChar) : sizeof(UChar));
+  return string_.CharactersSizeInBytes();
 }
 
 bool MovableStringImpl::Park() {
   // Cannot park strings with several references.
-  if (!is_parked_ && string_.Impl()->HasOneRef()) {
+  if (string_.Impl()->HasOneRef()) {
     RecordParkingAction(ParkingAction::kParkedInBackground);
-#if DCHECK_IS_ON()
-    // Since the copy is done before freeing the original data, the two strings
-    // are guaranteed to not have the same address.
-    parked_string_ = string_.IsolatedCopy();
-    // Poison the previous allocation.
-    // |string_| is kept as is to make sure the memory isn't reused.
-    const void* data = Is8Bit()
-                           ? static_cast<const void*>(string_.Characters8())
-                           : static_cast<const void*>(string_.Characters16());
-    memset(const_cast<void*>(data), 0xcc, string_.CharactersSizeInBytes());
-#endif
     is_parked_ = true;
   }
   return is_parked_;
@@ -89,20 +65,15 @@
   RecordParkingAction(backgrounded ? ParkingAction::kUnparkedInBackground
                                    : ParkingAction::kUnparkedInForeground);
   is_parked_ = false;
-#if DCHECK_IS_ON()
-  // string_'s data has the same address as parked_string_.
-  // This enforces MovableStringImpl.ToString().Characthers{8,16}() returning
-  // a different value after Park() / Unpark().
-  string_ = parked_string_;
-  parked_string_ = String();
-#endif
-  MovableStringTable::Instance().OnUnpark(this, string_.Impl());
 }
 
 MovableString::MovableString(scoped_refptr<StringImpl>&& impl) {
-  impl_ = MovableStringTable::Instance().Add(std::move(impl));
-  if (!impl_)
+  // Don't move small strings.
+  if (IsLargeEnough(impl.get())) {
+    impl_ = MovableStringTable::Instance().Add(std::move(impl));
+  } else {
     impl_ = base::MakeRefCounted<MovableStringImpl>(std::move(impl));
+  }
 }
 
 MovableString::~MovableString() = default;
@@ -127,45 +98,24 @@
 
 scoped_refptr<MovableStringImpl> MovableStringTable::Add(
     scoped_refptr<StringImpl>&& string) {
-  StringImpl* impl = string.get();
-  if (!IsLargeEnough(impl))
-    return nullptr;
-
-  auto it = unparked_strings_.find(impl);
-  if (it != unparked_strings_.end()) {
+  StringImpl* raw_ptr = string.get();
+  auto it = table_.find(raw_ptr);
+  if (it != table_.end()) {
     return it->second;
   }
   auto new_movable_string =
       base::MakeRefCounted<MovableStringImpl>(std::move(string));
-  unparked_strings_.emplace(impl, new_movable_string.get());
+  table_.emplace(raw_ptr, new_movable_string.get());
   return new_movable_string;
 }
 
-void MovableStringTable::OnUnpark(MovableStringImpl* movable_impl,
-                                  StringImpl* impl) {
-  if (!IsLargeEnough(movable_impl))
+void MovableStringTable::Remove(StringImpl* string) {
+  if (!IsLargeEnough(string))
     return;
 
-  auto it = parked_strings_.find(movable_impl);
-  DCHECK(it != parked_strings_.end());
-  parked_strings_.erase(it);
-  unparked_strings_.emplace(impl, movable_impl);
-}
-
-void MovableStringTable::Remove(MovableStringImpl* movable_impl,
-                                StringImpl* string) {
-  if (!IsLargeEnough(movable_impl))
-    return;
-
-  if (movable_impl->is_parked()) {
-    auto it = parked_strings_.find(movable_impl);
-    DCHECK(it != parked_strings_.end());
-    parked_strings_.erase(it);
-  } else {
-    auto it = unparked_strings_.find(string);
-    DCHECK(it != unparked_strings_.end());
-    unparked_strings_.erase(it);
-  }
+  auto it = table_.find(string);
+  DCHECK(it != table_.end());
+  table_.erase(it);
 }
 
 void MovableStringTable::SetRendererBackgrounded(bool backgrounded) {
@@ -181,20 +131,9 @@
     return;
 
   size_t total_size = 0, count = 0;
-  for (auto it = unparked_strings_.begin(); it != unparked_strings_.end();) {
-    MovableStringImpl* str = it->second;
-    bool parked = str->Park();
-    if (parked) {
-      parked_strings_.insert(str);
-      it = unparked_strings_.erase(it);
-    } else {
-      ++it;
-      total_size += str->CharactersSizeInBytes();
-      count += 1;
-    }
-  }
-  for (const auto* str : parked_strings_) {
-    DCHECK(str);
+  for (auto& kv : table_) {
+    MovableStringImpl* str = kv.second;
+    str->Park();
     total_size += str->CharactersSizeInBytes();
     count += 1;
   }
@@ -202,11 +141,7 @@
   size_t total_size_kb = total_size / 1000;
   UMA_HISTOGRAM_COUNTS_100000("Memory.MovableStringsTotalSizeKb",
                               total_size_kb);
-  UMA_HISTOGRAM_COUNTS_1000("Memory.MovableStringsCount", count);
-}
-
-size_t MovableStringTable::Size() const {
-  return parked_strings_.size() + unparked_strings_.size();
+  UMA_HISTOGRAM_COUNTS_1000("Memory.MovableStringsCount", table_.size());
 }
 
 }  // namespace WTF
diff --git a/third_party/blink/renderer/platform/wtf/text/movable_string.h b/third_party/blink/renderer/platform/wtf/text/movable_string.h
index 739de55..7b943e9b 100644
--- a/third_party/blink/renderer/platform/wtf/text/movable_string.h
+++ b/third_party/blink/renderer/platform/wtf/text/movable_string.h
@@ -50,7 +50,7 @@
   // See the matching String methods.
   bool Is8Bit() const;
   bool IsNull() const;
-  unsigned length() const { return length_; }
+  unsigned length() const { return string_.length(); }
   unsigned CharactersSizeInBytes() const;
 
   // A parked string cannot be accessed until it has been |Unpark()|-ed.
@@ -62,15 +62,8 @@
  private:
   void Unpark();
 
-  bool is_null_;
-  bool is_8bit_;
-  bool is_parked_;
-  unsigned length_;
-
   String string_;
-#if DCHECK_IS_ON()
-  String parked_string_;
-#endif
+  bool is_parked_;
 
   DISALLOW_COPY_AND_ASSIGN(MovableStringImpl);
 };
@@ -113,12 +106,11 @@
   }
 
   scoped_refptr<MovableStringImpl> Add(scoped_refptr<StringImpl>&&);
-  void OnUnpark(MovableStringImpl*, StringImpl*);
 
-  // This is for ~MovableStringImpl() to unregister a string before
+  // This is for ~MovableStringImpl to unregister a string before
   // destruction since the table is holding raw pointers. It should not be used
   // directly.
-  void Remove(MovableStringImpl*, StringImpl*);
+  void Remove(StringImpl*);
 
   void SetRendererBackgrounded(bool backgrounded);
   bool IsRendererBackgrounded() const;
@@ -127,17 +119,13 @@
   void MaybeParkAll();
 
  private:
-  size_t Size() const;
-
   bool backgrounded_;
   // Could bet a set where the hashing function is
   // MovableStringImpl::string_.Impl(), but clearer this way.
-  std::map<StringImpl*, MovableStringImpl*> unparked_strings_;
-  std::set<MovableStringImpl*> parked_strings_;
+  std::map<StringImpl*, MovableStringImpl*> table_;
 
   FRIEND_TEST_ALL_PREFIXES(MovableStringTest, TableSimple);
   FRIEND_TEST_ALL_PREFIXES(MovableStringTest, TableMultiple);
-  FRIEND_TEST_ALL_PREFIXES(MovableStringTest, TableDeduplication);
 
   DISALLOW_COPY_AND_ASSIGN(MovableStringTable);
 };
diff --git a/third_party/blink/renderer/platform/wtf/text/movable_string_test.cc b/third_party/blink/renderer/platform/wtf/text/movable_string_test.cc
index 0451bce..6eebafc 100644
--- a/third_party/blink/renderer/platform/wtf/text/movable_string_test.cc
+++ b/third_party/blink/renderer/platform/wtf/text/movable_string_test.cc
@@ -57,22 +57,11 @@
   base::HistogramTester histogram_tester;
 
   MovableString movable(String("abc").Impl());
-  auto before_address =
-      reinterpret_cast<uintptr_t>(movable.ToString().Characters8());
   EXPECT_FALSE(movable.Impl()->is_parked());
   EXPECT_TRUE(movable.Impl()->Park());
   EXPECT_TRUE(movable.Impl()->is_parked());
 
   String unparked = movable.ToString();
-  auto after_address = reinterpret_cast<uintptr_t>(unparked.Characters8());
-#if DCHECK_IS_ON()
-  // See comments in Park() and Unpark() for why the addresses are guaranteed to
-  // be different.
-  EXPECT_NE(before_address, after_address);
-#else
-  // Strings are not actually moved.
-  EXPECT_EQ(before_address, after_address);
-#endif
   EXPECT_EQ(String("abc"), unparked);
   EXPECT_FALSE(movable.Impl()->is_parked());
 
@@ -88,18 +77,16 @@
 TEST_F(MovableStringTest, TableSimple) {
   base::HistogramTester histogram_tester;
 
-  auto& table = MovableStringTable::Instance();
-  EXPECT_EQ(0u, table.Size());
-
   std::vector<char> data(20000, 'a');
   MovableString movable(String(data.data(), data.size()).ReleaseImpl());
   ASSERT_FALSE(movable.Impl()->is_parked());
 
-  EXPECT_EQ(1u, table.Size());
+  auto& table = MovableStringTable::Instance();
+  EXPECT_EQ(1u, table.table_.size());
 
   // Small strings are not in the table.
   MovableString small(String("abc").ReleaseImpl());
-  EXPECT_EQ(1u, table.Size());
+  EXPECT_EQ(1u, table.table_.size());
 
   // No parking as the current state is not "backgrounded".
   table.SetRendererBackgrounded(false);
@@ -154,23 +141,23 @@
   MovableString movable2(String(data.data(), data.size()).ReleaseImpl());
 
   auto& table = MovableStringTable::Instance();
-  EXPECT_EQ(2u, table.Size());
+  EXPECT_EQ(2u, table.table_.size());
 
   movable2 = MovableString();
-  EXPECT_EQ(1u, table.Size());
+  EXPECT_EQ(1u, table.table_.size());
 
   MovableString copy = movable;
   movable = MovableString();
-  EXPECT_EQ(1u, table.Size());
+  EXPECT_EQ(1u, table.table_.size());
   copy = MovableString();
-  EXPECT_EQ(0u, table.Size());
+  EXPECT_EQ(0u, table.table_.size());
 
   String str(data.data(), data.size());
   MovableString movable3(str.Impl());
-  EXPECT_EQ(1u, table.Size());
+  EXPECT_EQ(1u, table.table_.size());
   // De-duplicated.
   MovableString other_movable3(str.Impl());
-  EXPECT_EQ(1u, table.Size());
+  EXPECT_EQ(1u, table.table_.size());
   EXPECT_EQ(movable3.Impl(), other_movable3.Impl());
 
   // If all the references to a string are in the table, park it.
@@ -182,9 +169,9 @@
 
   // Only drop it from the table when the last one is gone.
   movable3 = MovableString();
-  EXPECT_EQ(1u, table.Size());
+  EXPECT_EQ(1u, table.table_.size());
   other_movable3 = MovableString();
-  EXPECT_EQ(0u, table.Size());
+  EXPECT_EQ(0u, table.table_.size());
 
   histogram_tester.ExpectUniqueSample("Memory.MovableStringsCount", 1, 1);
   histogram_tester.ExpectUniqueSample("Memory.MovableStringsTotalSizeKb",
@@ -195,26 +182,4 @@
       MovableStringImpl::ParkingAction::kParkedInBackground, 1);
 }
 
-TEST_F(MovableStringTest, TableDeduplication) {
-  auto& table = MovableStringTable::Instance();
-  size_t size_kb = 20;
-  std::vector<char> data(size_kb * 1000, 'a');
-
-  String a(data.data(), data.size());
-  String b = a;
-  {
-    MovableString movable_a(a.Impl());
-    EXPECT_EQ(1u, table.Size());
-    {
-      MovableString movable_b(b.Impl());
-      // De-duplicated, as a and b share the same |Impl()|.
-      EXPECT_EQ(1u, table.Size());
-      EXPECT_EQ(movable_a.Impl(), movable_b.Impl());
-    }
-    // |movable_a| still in scope.
-    EXPECT_EQ(1u, table.Size());
-  }
-  EXPECT_EQ(0u, table.Size());
-}
-
 }  // namespace WTF
diff --git a/third_party/blink/tools/gdb/blink.py b/third_party/blink/tools/gdb/blink.py
index 4cc2ca6..1534d23 100644
--- a/third_party/blink/tools/gdb/blink.py
+++ b/third_party/blink/tools/gdb/blink.py
@@ -261,28 +261,24 @@
         if ltype == 2:
             return 'Length(%g, Fixed%s)' % (val, quirk)
         if ltype == 3:
-            return 'Length(Intrinsic)'
-        if ltype == 4:
-            return 'Length(MinIntrinsic)'
-        if ltype == 5:
             return 'Length(MinContent)'
-        if ltype == 6:
+        if ltype == 4:
             return 'Length(MaxContent)'
-        if ltype == 7:
+        if ltype == 5:
             return 'Length(FillAvailable)'
-        if ltype == 8:
+        if ltype == 6:
             return 'Length(FitContent)'
-        if ltype == 9:
+        if ltype == 7:
             # Would like to print pixelsAndPercent() but can't call member
             # functions - https://sourceware.org/bugzilla/show_bug.cgi?id=13326
             return 'Length(Calculated)'
-        if ltype == 10:
+        if ltype == 8:
             return 'Length(ExtendToZoom)'
-        if ltype == 11:
+        if ltype == 9:
             return 'Length(DeviceWidth)'
-        if ltype == 12:
+        if ltype == 10:
             return 'Length(DeviceHeight)'
-        if ltype == 13:
+        if ltype == 11:
             return 'Length(MaxSizeNone)'
         return 'Length(unknown type %i)' % ltype
 
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index a5d378e..7432f40 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -19352,6 +19352,7 @@
   <int value="2506" label="DOMNodeRemovedFromDocumentEventListenedAtNonTarget"/>
   <int value="2507" label="CSSFillAvailableLogicalWidth"/>
   <int value="2508" label="CSSFillAvailableLogicalHeight"/>
+  <int value="2509" label="PopupOpenWhileFileChooserOpened"/>
 </enum>
 
 <enum name="FeedbackSource">
@@ -27554,6 +27555,7 @@
   <int value="-1772172557" label="enable-osk-overscroll"/>
   <int value="-1768672408" label="ChromeDuplex:disabled"/>
   <int value="-1767470652" label="out-of-process-pdf"/>
+  <int value="-1758468685" label="DownloadHomeV2:disabled"/>
   <int value="-1755301960" label="ClearOldBrowsingData:enabled"/>
   <int value="-1751928267" label="disable-icon-ntp"/>
   <int value="-1749176684" label="PauseBackgroundTabs:disabled"/>
@@ -28268,6 +28270,7 @@
       label="CrossOriginMediaPlaybackRequiresUserGesture:disabled"/>
   <int value="-290672626" label="enable-asm-wasm"/>
   <int value="-288316828" label="enable-delegated-renderer"/>
+  <int value="-286603268" label="hide-android-files-in-files-app"/>
   <int value="-284547865" label="UnifiedConsent:enabled"/>
   <int value="-283388027" label="ManualFallbacksFilling:disabled"/>
   <int value="-281844827" label="AutofillCreditCardAblationExperiment:enabled"/>
@@ -29131,6 +29134,7 @@
   <int value="1530177325" label="LanguagesPreference:disabled"/>
   <int value="1534222388" label="EnableEphemeralFlashPermission:enabled"/>
   <int value="1536921097" label="NavigationMojoResponse:disabled"/>
+  <int value="1538685213" label="DownloadHomeV2:enabled"/>
   <int value="1538690515" label="OneGoogleBarOnLocalNtp:enabled"/>
   <int value="1541723759" label="ServiceWorkerNavigationPreload:disabled"/>
   <int value="1543027970" label="EnableDisplayZoomSetting:disabled"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 4d1f563..158bda97 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -28033,11 +28033,19 @@
   </summary>
 </histogram>
 
-<histogram name="Extensions.ForceInstalledTimedOutCount">
+<histogram name="Extensions.ForceInstalledTimedOutAndNotInstalledCount">
   <owner>poromov@chromium.org</owner>
   <summary>
     Number of enterprise policy forced extensions that are not installed after 5
-    minutes timeout.
+    minutes if at least one of policy forced extensions is not yet enabled.
+  </summary>
+</histogram>
+
+<histogram name="Extensions.ForceInstalledTimedOutCount">
+  <owner>poromov@chromium.org</owner>
+  <summary>
+    Number of enterprise policy forced extensions that are not enabled after 5
+    minutes timeout, while might be already installed.
   </summary>
 </histogram>
 
@@ -89537,7 +89545,7 @@
     the time for debugging. 3) The request is for New Tab Page. This is because
     it tends to dominate the stats and makes the results largely skewed.
 
-    This isn't recorded when NetS13nSW(https://crbug.com/715640) is disabled.
+    It will be removed after NetS13nSW ships. https://crbug.com/715640
   </summary>
 </histogram>
 
@@ -89550,7 +89558,7 @@
     See details at ServiceWorker.ActivatedWorkerPreparationForMainFrame.Time.
     The suffixed histograms for .Time record the time required for each type.
 
-    This is recorded regardless of whether NetS13nSW(https://crbug.com/715640)
+    This is recorded regardless of whether NetS13nSW (https://crbug.com/715640)
     is enabled or disabled.
   </summary>
 </histogram>
@@ -90209,6 +90217,8 @@
     the same restrictions enumerated 1) through 3) for
     ServiceWorker.ActivatedWorkerPreparationForMainFrame.Time. The sample is
     only recorded to the appropriate suffixed histograms.
+
+    It will be removed after NetS13nSW ships. https://crbug.com/715640
   </summary>
 </histogram>
 
@@ -90222,6 +90232,8 @@
     fetch event, with the same restrictions numbered 1) through 3) for
     ServiceWorker.ActivatedWorkerPreparationForMainFrame.Time. The sample is
     only recorded to the appropriate suffixed histograms.
+
+    It will be removed after NetS13nSW ships. https://crbug.com/715640
   </summary>
 </histogram>
 
@@ -90234,6 +90246,8 @@
     event, with the same restrictions numbered 1) through 3) for
     ServiceWorker.ActivatedWorkerPreparationForMainFrame.Time. The sample is
     only recorded to the appropriate suffixed histograms.
+
+    It will be removed after NetS13nSW ships. https://crbug.com/715640
   </summary>
 </histogram>
 
@@ -90258,6 +90272,8 @@
     other ServiceWorker.NavPreload.* metrics so is more safely comparable to
     them. We could deprecate the Type_NavigationPreloadEnabled histogram if it
     turns out there is no significant difference.
+
+    It will be removed after NetS13nSW ships. https://crbug.com/715640
   </summary>
 </histogram>
 
diff --git a/tools/perf/core/shard_maps/android_go_14_shard_map.json b/tools/perf/core/shard_maps/android_go_14_shard_map.json
deleted file mode 100644
index 704ff65..0000000
--- a/tools/perf/core/shard_maps/android_go_14_shard_map.json
+++ /dev/null
@@ -1,126 +0,0 @@
-{
-    "0": {
-        "benchmarks": {
-            "system_health.common_mobile": {},
-            "start_with_url.warm.startup_pages": {},
-            "start_with_url.cold.startup_pages": {},
-            "system_health.memory_mobile": {},
-            "system_health.webview_startup": {},
-            "power.typical_10_mobile": {
-                "end": 3
-            }
-        }
-    },
-    "1": {
-        "benchmarks": {
-            "power.typical_10_mobile": {
-                "begin": 3,
-                "end": 6
-            }
-        }
-    },
-    "2": {
-        "benchmarks": {
-            "power.typical_10_mobile": {
-                "begin": 6,
-                "end": 9
-            }
-        }
-    },
-    "3": {
-        "benchmarks": {
-            "power.typical_10_mobile": {
-                "begin": 9
-            },
-            "memory.top_10_mobile": {
-                "end": 1
-            }
-        }
-    },
-    "4": {
-        "benchmarks": {
-            "memory.top_10_mobile": {
-                "begin": 1,
-                "end": 3
-            }
-        }
-    },
-    "5": {
-        "benchmarks": {
-            "memory.top_10_mobile": {
-                "begin": 3,
-                "end": 5
-            }
-        }
-    },
-    "6": {
-        "benchmarks": {
-            "memory.top_10_mobile": {
-                "begin": 5,
-                "end": 7
-            }
-        }
-    },
-    "7": {
-        "benchmarks": {
-            "memory.top_10_mobile": {
-                "begin": 7,
-                "end": 9
-            }
-        }
-    },
-    "8": {
-        "benchmarks": {
-            "memory.top_10_mobile": {
-                "begin": 9,
-                "end": 10
-            }
-        }
-    },
-    "9": {
-        "benchmarks": {
-            "memory.top_10_mobile": {
-                "begin": 10,
-                "end": 12
-            }
-        }
-    },
-    "10": {
-        "benchmarks": {
-            "memory.top_10_mobile": {
-                "begin": 12,
-                "end": 14
-            }
-        }
-    },
-    "11": {
-        "benchmarks": {
-            "memory.top_10_mobile": {
-                "begin": 14,
-                "end": 16
-            }
-        }
-    },
-    "12": {
-        "benchmarks": {
-            "memory.top_10_mobile": {
-                "begin": 16,
-                "end": 18
-            }
-        }
-    },
-    "13": {
-        "benchmarks": {
-            "memory.top_10_mobile": {
-                "begin": 18
-            }
-        }
-    },
-    "extra_infos": {
-        "num_stories": 160,
-        "predicted_min_shard_time": 224.836488080808,
-        "predicted_min_shard_index": 8,
-        "predicted_max_shard_time": 599.3532815757576,
-        "predicted_max_shard_index": 3
-    }
-}
diff --git a/tools/perf/core/shard_maps/android_go_shard_map.json b/tools/perf/core/shard_maps/android_go_shard_map.json
new file mode 100644
index 0000000..806331361
--- /dev/null
+++ b/tools/perf/core/shard_maps/android_go_shard_map.json
@@ -0,0 +1,169 @@
+{
+    "0": {
+        "benchmarks": {
+            "system_health.common_mobile": {
+                "end": 15
+            }
+        }
+    },
+    "1": {
+        "benchmarks": {
+            "system_health.common_mobile": {
+                "begin": 15,
+                "end": 27
+            }
+        }
+    },
+    "2": {
+        "benchmarks": {
+            "system_health.common_mobile": {
+                "begin": 27,
+                "end": 53
+            }
+        }
+    },
+    "3": {
+        "benchmarks": {
+            "system_health.common_mobile": {
+                "begin": 53,
+                "end": 61
+            }
+        }
+    },
+    "4": {
+        "benchmarks": {
+            "system_health.common_mobile": {
+                "begin": 61
+            },
+            "start_with_url.warm.startup_pages": {},
+            "start_with_url.cold.startup_pages": {
+                "end": 1
+            }
+        }
+    },
+    "5": {
+        "benchmarks": {
+            "start_with_url.cold.startup_pages": {
+                "begin": 1
+            },
+            "system_health.memory_mobile": {
+                "end": 7
+            }
+        }
+    },
+    "6": {
+        "benchmarks": {
+            "system_health.memory_mobile": {
+                "begin": 7,
+                "end": 14
+            }
+        }
+    },
+    "7": {
+        "benchmarks": {
+            "system_health.memory_mobile": {
+                "begin": 14,
+                "end": 17
+            }
+        }
+    },
+    "8": {
+        "benchmarks": {
+            "system_health.memory_mobile": {
+                "begin": 17,
+                "end": 21
+            }
+        }
+    },
+    "9": {
+        "benchmarks": {
+            "system_health.memory_mobile": {
+                "begin": 21,
+                "end": 29
+            }
+        }
+    },
+    "10": {
+        "benchmarks": {
+            "system_health.memory_mobile": {
+                "begin": 29,
+                "end": 40
+            }
+        }
+    },
+    "11": {
+        "benchmarks": {
+            "system_health.memory_mobile": {
+                "begin": 40,
+                "end": 50
+            }
+        }
+    },
+    "12": {
+        "benchmarks": {
+            "system_health.memory_mobile": {
+                "begin": 50,
+                "end": 53
+            }
+        }
+    },
+    "13": {
+        "benchmarks": {
+            "system_health.memory_mobile": {
+                "begin": 53,
+                "end": 56
+            }
+        }
+    },
+    "14": {
+        "benchmarks": {
+            "system_health.memory_mobile": {
+                "begin": 56,
+                "end": 61
+            }
+        }
+    },
+    "15": {
+        "benchmarks": {
+            "system_health.memory_mobile": {
+                "begin": 61
+            },
+            "system_health.webview_startup": {},
+            "power.typical_10_mobile": {
+                "end": 8
+            }
+        }
+    },
+    "16": {
+        "benchmarks": {
+            "power.typical_10_mobile": {
+                "begin": 8
+            },
+            "memory.top_10_mobile": {
+                "end": 5
+            }
+        }
+    },
+    "17": {
+        "benchmarks": {
+            "memory.top_10_mobile": {
+                "begin": 5,
+                "end": 13
+            }
+        }
+    },
+    "18": {
+        "benchmarks": {
+            "memory.top_10_mobile": {
+                "begin": 13
+            }
+        }
+    },
+    "extra_infos": {
+        "num_stories": 160,
+        "predicted_min_shard_time": 1518.0,
+        "predicted_min_shard_index": 7,
+        "predicted_max_shard_time": 2358.0,
+        "predicted_max_shard_index": 6
+    }
+}
\ No newline at end of file
diff --git a/tools/perf/core/shard_maps/timing_data/android_go_timing.json b/tools/perf/core/shard_maps/timing_data/android_go_timing.json
new file mode 100644
index 0000000..ef23b5a
--- /dev/null
+++ b/tools/perf/core/shard_maps/timing_data/android_go_timing.json
@@ -0,0 +1,5302 @@
+[
+    {
+        "duration": "23.0",
+        "name": "blink_perf.bindings/append-child.html"
+    },
+    {
+        "duration": "17.0",
+        "name": "blink_perf.bindings/create-element.html"
+    },
+    {
+        "duration": "16.0",
+        "name": "blink_perf.bindings/document-implementation.html"
+    },
+    {
+        "duration": "18.0",
+        "name": "blink_perf.bindings/dom-attribute-on-prototoype.html"
+    },
+    {
+        "duration": "16.0",
+        "name": "blink_perf.bindings/first-child.html"
+    },
+    {
+        "duration": "32.0",
+        "name": "blink_perf.bindings/gc-forest.html"
+    },
+    {
+        "duration": "40.0",
+        "name": "blink_perf.bindings/gc-mini-tree.html"
+    },
+    {
+        "duration": "131.0",
+        "name": "blink_perf.bindings/gc-tree.html"
+    },
+    {
+        "duration": "17.0",
+        "name": "blink_perf.bindings/get-attribute-rare.html"
+    },
+    {
+        "duration": "17.0",
+        "name": "blink_perf.bindings/get-attribute.html"
+    },
+    {
+        "duration": "15.0",
+        "name": "blink_perf.bindings/get-element-by-id.html"
+    },
+    {
+        "duration": "15.0",
+        "name": "blink_perf.bindings/get-elements-by-tag-name.html"
+    },
+    {
+        "duration": "16.0",
+        "name": "blink_perf.bindings/id-getter.html"
+    },
+    {
+        "duration": "17.0",
+        "name": "blink_perf.bindings/id-setter.html"
+    },
+    {
+        "duration": "22.0",
+        "name": "blink_perf.bindings/indexed-getter.html"
+    },
+    {
+        "duration": "16.0",
+        "name": "blink_perf.bindings/insert-before.html"
+    },
+    {
+        "duration": "16.0",
+        "name": "blink_perf.bindings/named-property-enumerator.html"
+    },
+    {
+        "duration": "123.0",
+        "name": "blink_perf.bindings/node-list-access.html"
+    },
+    {
+        "duration": "16.0",
+        "name": "blink_perf.bindings/node-type.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.bindings/post-message.html"
+    },
+    {
+        "duration": "17.0",
+        "name": "blink_perf.bindings/sequence-conversion-array.html"
+    },
+    {
+        "duration": "15.0",
+        "name": "blink_perf.bindings/sequence-conversion-custom-iterator.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.bindings/serialize-array.html"
+    },
+    {
+        "duration": "9.0",
+        "name": "blink_perf.bindings/serialize-long-string.html"
+    },
+    {
+        "duration": "23.0",
+        "name": "blink_perf.bindings/serialize-map.html"
+    },
+    {
+        "duration": "9.0",
+        "name": "blink_perf.bindings/serialize-nested-array.html"
+    },
+    {
+        "duration": "16.0",
+        "name": "blink_perf.bindings/set-attribute-rare.html"
+    },
+    {
+        "duration": "16.0",
+        "name": "blink_perf.bindings/set-attribute.html"
+    },
+    {
+        "duration": "380.0",
+        "name": "blink_perf.bindings/structured-clone-json-deserialize.html"
+    },
+    {
+        "duration": "374.0",
+        "name": "blink_perf.bindings/structured-clone-json-serialize.html"
+    },
+    {
+        "duration": "365.0",
+        "name": "blink_perf.bindings/structured-clone-long-string-deserialize.html"
+    },
+    {
+        "duration": "365.0",
+        "name": "blink_perf.bindings/structured-clone-long-string-serialize.html"
+    },
+    {
+        "duration": "17.0",
+        "name": "blink_perf.bindings/typed-array-construct-from-array.html"
+    },
+    {
+        "duration": "19.0",
+        "name": "blink_perf.bindings/typed-array-construct-from-same-type.html"
+    },
+    {
+        "duration": "85.0",
+        "name": "blink_perf.bindings/typed-array-construct-from-typed.html"
+    },
+    {
+        "duration": "16.0",
+        "name": "blink_perf.bindings/typed-array-set-from-typed.html"
+    },
+    {
+        "duration": "16.0",
+        "name": "blink_perf.bindings/undefined-first-child.html"
+    },
+    {
+        "duration": "16.0",
+        "name": "blink_perf.bindings/undefined-get-element-by-id.html"
+    },
+    {
+        "duration": "16.0",
+        "name": "blink_perf.bindings/undefined-id-getter.html"
+    },
+    {
+        "duration": "25.0",
+        "name": "blink_perf.canvas/createImageBitmapFromImageData.html"
+    },
+    {
+        "duration": "51.0",
+        "name": "blink_perf.canvas/draw-dynamic-canvas-2d-to-hw-accelerated-canvas-2d.html"
+    },
+    {
+        "duration": "72.0",
+        "name": "blink_perf.canvas/draw-dynamic-webgl-to-hw-accelerated-canvas-2d.html"
+    },
+    {
+        "duration": "10.0",
+        "name": "blink_perf.canvas/draw-hw-accelerated-canvas-2d-to-sw-canvas-2d.html"
+    },
+    {
+        "duration": "30.0",
+        "name": "blink_perf.canvas/draw-static-canvas-2d-to-hw-accelerated-canvas-2d.html"
+    },
+    {
+        "duration": "44.0",
+        "name": "blink_perf.canvas/draw-static-webgl-to-hw-accelerated-canvas-2d.html"
+    },
+    {
+        "duration": "26.0",
+        "name": "blink_perf.canvas/draw-video-to-hw-accelerated-canvas-2d.html"
+    },
+    {
+        "duration": "19.0",
+        "name": "blink_perf.canvas/drawimage-not-pixelaligned.html"
+    },
+    {
+        "duration": "20.0",
+        "name": "blink_perf.canvas/drawimage.html"
+    },
+    {
+        "duration": "25.0",
+        "name": "blink_perf.canvas/getImageData.html"
+    },
+    {
+        "duration": "23.0",
+        "name": "blink_perf.canvas/getImageDataColorManaged.html"
+    },
+    {
+        "duration": "72.0",
+        "name": "blink_perf.canvas/putImageData.html"
+    },
+    {
+        "duration": "29.0",
+        "name": "blink_perf.canvas/toBlob_duration.html"
+    },
+    {
+        "duration": "22.0",
+        "name": "blink_perf.canvas/toBlob_duration_jpeg.html"
+    },
+    {
+        "duration": "14.0",
+        "name": "blink_perf.canvas/transferFromImageBitmap.html"
+    },
+    {
+        "duration": "51.0",
+        "name": "blink_perf.canvas/upload-canvas-2d-to-texture.html"
+    },
+    {
+        "duration": "19.0",
+        "name": "blink_perf.canvas/upload-video-to-sub-texture.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.canvas/upload-video-to-texture.html"
+    },
+    {
+        "duration": "50.0",
+        "name": "blink_perf.canvas/upload-webgl-to-texture.html"
+    },
+    {
+        "duration": "38.0",
+        "name": "blink_perf.css/AttributeDescendantSelector.html"
+    },
+    {
+        "duration": "19.0",
+        "name": "blink_perf.css/CSSPropertySetterGetter.html"
+    },
+    {
+        "duration": "19.0",
+        "name": "blink_perf.css/CSSPropertySetterGetterMethods.html"
+    },
+    {
+        "duration": "19.0",
+        "name": "blink_perf.css/CSSPropertyUpdateValue.html"
+    },
+    {
+        "duration": "25.0",
+        "name": "blink_perf.css/ChangeStyleChildClassSelector.html"
+    },
+    {
+        "duration": "14.0",
+        "name": "blink_perf.css/ChangeStyleChildElementSelectors.html"
+    },
+    {
+        "duration": "14.0",
+        "name": "blink_perf.css/ChangeStyleElementSelector.html"
+    },
+    {
+        "duration": "14.0",
+        "name": "blink_perf.css/ChangeStyleGrandChildElementSelector.html"
+    },
+    {
+        "duration": "22.0",
+        "name": "blink_perf.css/ChangeStyleMultipleClassSelector.html"
+    },
+    {
+        "duration": "14.0",
+        "name": "blink_perf.css/ChangeStyleMultipleQualifiedDataAttributesWithValuesSelector.html"
+    },
+    {
+        "duration": "13.0",
+        "name": "blink_perf.css/ChangeStyleNestedPseudoSelector.html"
+    },
+    {
+        "duration": "13.0",
+        "name": "blink_perf.css/ChangeStylePairOfNthChildSelector.html"
+    },
+    {
+        "duration": "14.0",
+        "name": "blink_perf.css/ChangeStylePartialAttributeMatchingSelector.html"
+    },
+    {
+        "duration": "14.0",
+        "name": "blink_perf.css/ChangeStyleQualifiedDataAttributeSelector.html"
+    },
+    {
+        "duration": "14.0",
+        "name": "blink_perf.css/ChangeStyleQualifiedDataAttributeWithValueSelector.html"
+    },
+    {
+        "duration": "18.0",
+        "name": "blink_perf.css/ChangeStyleShallowTree.html"
+    },
+    {
+        "duration": "14.0",
+        "name": "blink_perf.css/ChangeStyleSingleClassSelector.html"
+    },
+    {
+        "duration": "14.0",
+        "name": "blink_perf.css/ChangeStyleSingleNthChildSelector.html"
+    },
+    {
+        "duration": "14.0",
+        "name": "blink_perf.css/ChangeStyleSinglePseudoSelector.html"
+    },
+    {
+        "duration": "14.0",
+        "name": "blink_perf.css/ChangeStyleUniversalSelector.html"
+    },
+    {
+        "duration": "14.0",
+        "name": "blink_perf.css/ChangeStyleUnqualifiedDataAttributeSelector.html"
+    },
+    {
+        "duration": "14.0",
+        "name": "blink_perf.css/ChangeStyleUnqualifiedDataAttributeWithValueSelector.html"
+    },
+    {
+        "duration": "38.0",
+        "name": "blink_perf.css/ClassDescendantSelector.html"
+    },
+    {
+        "duration": "24.0",
+        "name": "blink_perf.css/ClassInvalidation.html"
+    },
+    {
+        "duration": "23.0",
+        "name": "blink_perf.css/FocusUpdate.html"
+    },
+    {
+        "duration": "15.0",
+        "name": "blink_perf.css/LoadBootstrapBlog.html"
+    },
+    {
+        "duration": "16.0",
+        "name": "blink_perf.css/LoadMaterializeStarterPage.html"
+    },
+    {
+        "duration": "18.0",
+        "name": "blink_perf.css/LoadSemanticPageExample.html"
+    },
+    {
+        "duration": "20.0",
+        "name": "blink_perf.css/PseudoClassSelectors.html"
+    },
+    {
+        "duration": "18.0",
+        "name": "blink_perf.css/SelectorCountScaling.html"
+    },
+    {
+        "duration": "58.0",
+        "name": "blink_perf.dom/addRange.html"
+    },
+    {
+        "duration": "12.0",
+        "name": "blink_perf.dom/delete-in-password-field.html"
+    },
+    {
+        "duration": "37.0",
+        "name": "blink_perf.dom/div-editable.html"
+    },
+    {
+        "duration": "9.0",
+        "name": "blink_perf.dom/inner_html_with_selection.html"
+    },
+    {
+        "duration": "30.0",
+        "name": "blink_perf.dom/long-sibling-list.html"
+    },
+    {
+        "duration": "21.0",
+        "name": "blink_perf.dom/modify-element-classname.html"
+    },
+    {
+        "duration": "17.0",
+        "name": "blink_perf.dom/modify-element-id.html"
+    },
+    {
+        "duration": "17.0",
+        "name": "blink_perf.dom/modify-element-title.html"
+    },
+    {
+        "duration": "20.0",
+        "name": "blink_perf.dom/move-down-with-hidden-elements.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.dom/move-up-with-hidden-elements.html"
+    },
+    {
+        "duration": "10.0",
+        "name": "blink_perf.dom/remove_child_with_selection.html"
+    },
+    {
+        "duration": "17.0",
+        "name": "blink_perf.dom/select-multiple-add.html"
+    },
+    {
+        "duration": "21.0",
+        "name": "blink_perf.dom/select-single-add.html"
+    },
+    {
+        "duration": "25.0",
+        "name": "blink_perf.dom/select-single-remove.html"
+    },
+    {
+        "duration": "17.0",
+        "name": "blink_perf.dom/textarea-dom.html"
+    },
+    {
+        "duration": "46.0",
+        "name": "blink_perf.dom/textarea-edit.html"
+    },
+    {
+        "duration": "28.0",
+        "name": "blink_perf.events/EventsDispatching.html"
+    },
+    {
+        "duration": "22.0",
+        "name": "blink_perf.events/EventsDispatchingInDeeplyNestedShadowTrees.html"
+    },
+    {
+        "duration": "92.0",
+        "name": "blink_perf.events/EventsDispatchingInShadowTrees.html"
+    },
+    {
+        "duration": "129.0",
+        "name": "blink_perf.events/hit-test-lots-of-layers.html"
+    },
+    {
+        "duration": "69.0",
+        "name": "blink_perf.image_decoder/decode-gif.html"
+    },
+    {
+        "duration": "26.0",
+        "name": "blink_perf.image_decoder/decode-jpeg.html"
+    },
+    {
+        "duration": "63.0",
+        "name": "blink_perf.image_decoder/decode-lossless-webp.html"
+    },
+    {
+        "duration": "19.0",
+        "name": "blink_perf.image_decoder/decode-lossy-webp.html"
+    },
+    {
+        "duration": "34.0",
+        "name": "blink_perf.image_decoder/decode-png-palette-opaque.html"
+    },
+    {
+        "duration": "23.0",
+        "name": "blink_perf.image_decoder/decode-png-palette.html"
+    },
+    {
+        "duration": "51.0",
+        "name": "blink_perf.image_decoder/decode-png.html"
+    },
+    {
+        "duration": "29.0",
+        "name": "blink_perf.layout/ArabicLineLayout.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.layout/Shapes/MultipleShapes.html"
+    },
+    {
+        "duration": "20.0",
+        "name": "blink_perf.layout/SimpleTextPathLineLayout.html"
+    },
+    {
+        "duration": "16.0",
+        "name": "blink_perf.layout/add-remove-inline-floats.html"
+    },
+    {
+        "duration": "19.0",
+        "name": "blink_perf.layout/attach-inlines-2.html"
+    },
+    {
+        "duration": "16.0",
+        "name": "blink_perf.layout/attach-inlines.html"
+    },
+    {
+        "duration": "20.0",
+        "name": "blink_perf.layout/auto-grid-lots-of-data.html"
+    },
+    {
+        "duration": "17.0",
+        "name": "blink_perf.layout/chapter-reflow-once-random.html"
+    },
+    {
+        "duration": "17.0",
+        "name": "blink_perf.layout/chapter-reflow-once.html"
+    },
+    {
+        "duration": "15.0",
+        "name": "blink_perf.layout/chapter-reflow-thrice.html"
+    },
+    {
+        "duration": "16.0",
+        "name": "blink_perf.layout/chapter-reflow-twice.html"
+    },
+    {
+        "duration": "16.0",
+        "name": "blink_perf.layout/chapter-reflow.html"
+    },
+    {
+        "duration": "17.0",
+        "name": "blink_perf.layout/character_fallback.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.layout/character_fallback_aat.html"
+    },
+    {
+        "duration": "21.0",
+        "name": "blink_perf.layout/fixed-grid-lots-of-data.html"
+    },
+    {
+        "duration": "21.0",
+        "name": "blink_perf.layout/fixed-grid-lots-of-stretched-data.html"
+    },
+    {
+        "duration": "29.0",
+        "name": "blink_perf.layout/flexbox-column-nowrap.html"
+    },
+    {
+        "duration": "18.0",
+        "name": "blink_perf.layout/flexbox-column-wrap.html"
+    },
+    {
+        "duration": "18.0",
+        "name": "blink_perf.layout/flexbox-deeply-nested-column-flow.html"
+    },
+    {
+        "duration": "23.0",
+        "name": "blink_perf.layout/flexbox-lots-of-data.html"
+    },
+    {
+        "duration": "18.0",
+        "name": "blink_perf.layout/flexbox-row-nowrap.html"
+    },
+    {
+        "duration": "18.0",
+        "name": "blink_perf.layout/flexbox-row-wrap.html"
+    },
+    {
+        "duration": "15.0",
+        "name": "blink_perf.layout/flexbox-with-stretch-layout.html"
+    },
+    {
+        "duration": "153.0",
+        "name": "blink_perf.layout/floats_100_100.html"
+    },
+    {
+        "duration": "159.0",
+        "name": "blink_perf.layout/floats_100_100_nested.html"
+    },
+    {
+        "duration": "58.0",
+        "name": "blink_perf.layout/floats_10_1000.html"
+    },
+    {
+        "duration": "30.0",
+        "name": "blink_perf.layout/floats_20_100.html"
+    },
+    {
+        "duration": "35.0",
+        "name": "blink_perf.layout/floats_20_100_nested.html"
+    },
+    {
+        "duration": "20.0",
+        "name": "blink_perf.layout/floats_2_100.html"
+    },
+    {
+        "duration": "21.0",
+        "name": "blink_perf.layout/floats_2_100_nested.html"
+    },
+    {
+        "duration": "54.0",
+        "name": "blink_perf.layout/floats_50_100.html"
+    },
+    {
+        "duration": "56.0",
+        "name": "blink_perf.layout/floats_50_100_nested.html"
+    },
+    {
+        "duration": "20.0",
+        "name": "blink_perf.layout/hindi-line-layout.html"
+    },
+    {
+        "duration": "228.0",
+        "name": "blink_perf.layout/large-table-with-collapsed-borders-and-colspans-wider-than-table.html"
+    },
+    {
+        "duration": "229.0",
+        "name": "blink_perf.layout/large-table-with-collapsed-borders-and-colspans.html"
+    },
+    {
+        "duration": "208.0",
+        "name": "blink_perf.layout/large-table-with-collapsed-borders-and-no-colspans.html"
+    },
+    {
+        "duration": "10.0",
+        "name": "blink_perf.layout/latin-complex-text.html"
+    },
+    {
+        "duration": "15.0",
+        "name": "blink_perf.layout/layers_overlap_2d.html"
+    },
+    {
+        "duration": "16.0",
+        "name": "blink_perf.layout/layers_overlap_3d.html"
+    },
+    {
+        "duration": "61.0",
+        "name": "blink_perf.layout/line-layout-line-height.html"
+    },
+    {
+        "duration": "16.0",
+        "name": "blink_perf.layout/line-layout-repeat-append.html"
+    },
+    {
+        "duration": "18.0",
+        "name": "blink_perf.layout/line-layout.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.layout/long-line-nowrap-collapse.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.layout/long-line-nowrap-spans-collapse.html"
+    },
+    {
+        "duration": "29.0",
+        "name": "blink_perf.layout/long-line-nowrap.html"
+    },
+    {
+        "duration": "19.0",
+        "name": "blink_perf.layout/multicol/deeply-nested-tables.html"
+    },
+    {
+        "duration": "23.0",
+        "name": "blink_perf.layout/multicol/fixed-height-with-spanner-and-nested-tables.html"
+    },
+    {
+        "duration": "18.0",
+        "name": "blink_perf.layout/multicol/lots-of-text-autofill.html"
+    },
+    {
+        "duration": "18.0",
+        "name": "blink_perf.layout/multicol/lots-of-text-balanced-orphans-widows.html"
+    },
+    {
+        "duration": "18.0",
+        "name": "blink_perf.layout/multicol/lots-of-text-balanced.html"
+    },
+    {
+        "duration": "40.0",
+        "name": "blink_perf.layout/multicol/tall-content-short-columns-realistic.html"
+    },
+    {
+        "duration": "39.0",
+        "name": "blink_perf.layout/multicol/tall-content-short-columns.html"
+    },
+    {
+        "duration": "19.0",
+        "name": "blink_perf.layout/nested-blocks-with-percent-height-and-max-height.html"
+    },
+    {
+        "duration": "17.0",
+        "name": "blink_perf.layout/nested-grid.html"
+    },
+    {
+        "duration": "17.0",
+        "name": "blink_perf.layout/nested-percent-height-tables.html"
+    },
+    {
+        "duration": "187.0",
+        "name": "blink_perf.layout/subtree-detaching.html"
+    },
+    {
+        "duration": "28.0",
+        "name": "blink_perf.layout/vertical-japanese-kokoro-insert.html"
+    },
+    {
+        "duration": "27.0",
+        "name": "blink_perf.layout/word-break-break-all.html"
+    },
+    {
+        "duration": "27.0",
+        "name": "blink_perf.layout/word-break-break-word.html"
+    },
+    {
+        "duration": "27.0",
+        "name": "blink_perf.layout/word-wrap-break-word.html"
+    },
+    {
+        "duration": "44.0",
+        "name": "blink_perf.owp_storage/blob-perf-files.html"
+    },
+    {
+        "duration": "29.0",
+        "name": "blink_perf.owp_storage/blob-perf-ipc.html"
+    },
+    {
+        "duration": "19.0",
+        "name": "blink_perf.owp_storage/blob-perf-shm.html"
+    },
+    {
+        "duration": "29.0",
+        "name": "blink_perf.owp_storage/blob-perf-tiny.html"
+    },
+    {
+        "duration": "29.0",
+        "name": "blink_perf.owp_storage/idb-load-docs.html"
+    },
+    {
+        "duration": "46.0",
+        "name": "blink_perf.paint/appending-text.html"
+    },
+    {
+        "duration": "98.0",
+        "name": "blink_perf.paint/color-changes.html"
+    },
+    {
+        "duration": "103.0",
+        "name": "blink_perf.paint/complex-content-slow-scroll.html"
+    },
+    {
+        "duration": "90.0",
+        "name": "blink_perf.paint/containment-resize.html"
+    },
+    {
+        "duration": "86.0",
+        "name": "blink_perf.paint/fixed-and-many-layers-scroll.html"
+    },
+    {
+        "duration": "105.0",
+        "name": "blink_perf.paint/large-table-background-change-with-invisible-collapsed-borders.html"
+    },
+    {
+        "duration": "86.0",
+        "name": "blink_perf.paint/large-table-background-change-with-visible-collapsed-borders.html"
+    },
+    {
+        "duration": "111.0",
+        "name": "blink_perf.paint/large-table-background-change-with-zero-width-collapsed-borders.html"
+    },
+    {
+        "duration": "83.0",
+        "name": "blink_perf.paint/large-table-collapsed-border-change-with-backgrounds.html"
+    },
+    {
+        "duration": "93.0",
+        "name": "blink_perf.paint/large-table-collapsed-border-change-with-text.html"
+    },
+    {
+        "duration": "42.0",
+        "name": "blink_perf.paint/large-table-collapsed-border-change.html"
+    },
+    {
+        "duration": "64.0",
+        "name": "blink_perf.paint/large-table-repaint.html"
+    },
+    {
+        "duration": "36.0",
+        "name": "blink_perf.paint/move-text-with-mask.html"
+    },
+    {
+        "duration": "61.0",
+        "name": "blink_perf.paint/paint-offset-changes.html"
+    },
+    {
+        "duration": "79.0",
+        "name": "blink_perf.paint/transform-changes.html"
+    },
+    {
+        "duration": "32.0",
+        "name": "blink_perf.parser/css-parser-yui.html"
+    },
+    {
+        "duration": "253.0",
+        "name": "blink_perf.parser/html-parser-threaded.html"
+    },
+    {
+        "duration": "83.0",
+        "name": "blink_perf.parser/html-parser.html"
+    },
+    {
+        "duration": "269.0",
+        "name": "blink_perf.parser/html5-full-render.html"
+    },
+    {
+        "duration": "16.0",
+        "name": "blink_perf.parser/iframe-append-remove.html"
+    },
+    {
+        "duration": "18.0",
+        "name": "blink_perf.parser/innerHTML-setter-siblings.html"
+    },
+    {
+        "duration": "17.0",
+        "name": "blink_perf.parser/innerHTML-setter.html"
+    },
+    {
+        "duration": "26.0",
+        "name": "blink_perf.parser/query-selector-all-attribute-complex.html"
+    },
+    {
+        "duration": "17.0",
+        "name": "blink_perf.parser/query-selector-all-attribute.html"
+    },
+    {
+        "duration": "19.0",
+        "name": "blink_perf.parser/query-selector-all-class-deep.html"
+    },
+    {
+        "duration": "20.0",
+        "name": "blink_perf.parser/query-selector-all-class-first.html"
+    },
+    {
+        "duration": "18.0",
+        "name": "blink_perf.parser/query-selector-all-class-last.html"
+    },
+    {
+        "duration": "16.0",
+        "name": "blink_perf.parser/query-selector-all-class.html"
+    },
+    {
+        "duration": "17.0",
+        "name": "blink_perf.parser/query-selector-all-deep.html"
+    },
+    {
+        "duration": "19.0",
+        "name": "blink_perf.parser/query-selector-all-first.html"
+    },
+    {
+        "duration": "23.0",
+        "name": "blink_perf.parser/query-selector-all-id-deep.html"
+    },
+    {
+        "duration": "20.0",
+        "name": "blink_perf.parser/query-selector-all-id-first.html"
+    },
+    {
+        "duration": "22.0",
+        "name": "blink_perf.parser/query-selector-all-id-last.html"
+    },
+    {
+        "duration": "17.0",
+        "name": "blink_perf.parser/query-selector-all-last.html"
+    },
+    {
+        "duration": "18.0",
+        "name": "blink_perf.parser/query-selector-deep.html"
+    },
+    {
+        "duration": "20.0",
+        "name": "blink_perf.parser/query-selector-first.html"
+    },
+    {
+        "duration": "20.0",
+        "name": "blink_perf.parser/query-selector-id-deep.html"
+    },
+    {
+        "duration": "24.0",
+        "name": "blink_perf.parser/query-selector-id-last.html"
+    },
+    {
+        "duration": "17.0",
+        "name": "blink_perf.parser/query-selector-last.html"
+    },
+    {
+        "duration": "22.0",
+        "name": "blink_perf.parser/simple-url.html"
+    },
+    {
+        "duration": "20.0",
+        "name": "blink_perf.parser/textarea-parsing.html"
+    },
+    {
+        "duration": "34.0",
+        "name": "blink_perf.parser/tiny-innerHTML.html"
+    },
+    {
+        "duration": "18.0",
+        "name": "blink_perf.parser/url-parser.html"
+    },
+    {
+        "duration": "16.0",
+        "name": "blink_perf.parser/xml-parser.html"
+    },
+    {
+        "duration": "35.0",
+        "name": "blink_perf.shadow_dom/shadow-style-share-attr-selectors.html"
+    },
+    {
+        "duration": "14.0",
+        "name": "blink_perf.shadow_dom/shadow-style-share-media-query.html"
+    },
+    {
+        "duration": "14.0",
+        "name": "blink_perf.shadow_dom/shadow-style-share-with-distribution.html"
+    },
+    {
+        "duration": "10.0",
+        "name": "blink_perf.shadow_dom/shadow-style-share.html"
+    },
+    {
+        "duration": "12.0",
+        "name": "blink_perf.shadow_dom/style-sheet-insert.html"
+    },
+    {
+        "duration": "13.0",
+        "name": "blink_perf.shadow_dom/v0-changing-classname-with-shadow-dom.html"
+    },
+    {
+        "duration": "31.0",
+        "name": "blink_perf.shadow_dom/v0-changing-classname-without-shadow-dom.html"
+    },
+    {
+        "duration": "37.0",
+        "name": "blink_perf.shadow_dom/v0-changing-select-with-shadow-dom.html"
+    },
+    {
+        "duration": "41.0",
+        "name": "blink_perf.shadow_dom/v0-changing-select-without-shadow-dom.html"
+    },
+    {
+        "duration": "12.0",
+        "name": "blink_perf.shadow_dom/v0-content-reprojection.html"
+    },
+    {
+        "duration": "10.0",
+        "name": "blink_perf.shadow_dom/v0-large-distribution-without-layout.html"
+    },
+    {
+        "duration": "10.0",
+        "name": "blink_perf.shadow_dom/v0-multiple-insertion-points.html"
+    },
+    {
+        "duration": "12.0",
+        "name": "blink_perf.shadow_dom/v0-shadow-reprojection.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.shadow_dom/v0-small-distribution-with-layout.html"
+    },
+    {
+        "duration": "100.0",
+        "name": "blink_perf.shadow_dom/v1-distribution-disconnected-and-reconnected.html"
+    },
+    {
+        "duration": "9.0",
+        "name": "blink_perf.shadow_dom/v1-distribution.html"
+    },
+    {
+        "duration": "9.0",
+        "name": "blink_perf.shadow_dom/v1-host-child-append.html"
+    },
+    {
+        "duration": "99.0",
+        "name": "blink_perf.shadow_dom/v1-large-deep-distribution.html"
+    },
+    {
+        "duration": "261.0",
+        "name": "blink_perf.shadow_dom/v1-large-deep-layout.html"
+    },
+    {
+        "duration": "9.0",
+        "name": "blink_perf.shadow_dom/v1-large-shallow-distribution.html"
+    },
+    {
+        "duration": "10.0",
+        "name": "blink_perf.shadow_dom/v1-large-shallow-layout.html"
+    },
+    {
+        "duration": "14.0",
+        "name": "blink_perf.shadow_dom/v1-mutate-deep-tree-then-re-layout.html"
+    },
+    {
+        "duration": "10.0",
+        "name": "blink_perf.shadow_dom/v1-mutate-deep-tree-then-slot-assigned-nodes.html"
+    },
+    {
+        "duration": "10.0",
+        "name": "blink_perf.shadow_dom/v1-mutate-deep-tree-then-slot-flatten.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.shadow_dom/v1-mutate-shallow-tree-then-re-layout.html"
+    },
+    {
+        "duration": "10.0",
+        "name": "blink_perf.shadow_dom/v1-mutate-shallow-tree-then-slot-assigned-nodes.html"
+    },
+    {
+        "duration": "10.0",
+        "name": "blink_perf.shadow_dom/v1-mutate-shallow-tree-then-slot-flatten.html"
+    },
+    {
+        "duration": "9.0",
+        "name": "blink_perf.shadow_dom/v1-slot-append.html"
+    },
+    {
+        "duration": "22.0",
+        "name": "blink_perf.shadow_dom/v1-small-deep-distribution.html"
+    },
+    {
+        "duration": "22.0",
+        "name": "blink_perf.shadow_dom/v1-small-deep-layout.html"
+    },
+    {
+        "duration": "9.0",
+        "name": "blink_perf.shadow_dom/v1-small-shallow-distribution.html"
+    },
+    {
+        "duration": "9.0",
+        "name": "blink_perf.shadow_dom/v1-small-shallow-layout.html"
+    },
+    {
+        "duration": "21.0",
+        "name": "blink_perf.svg/AzLizardBenjiPark.html"
+    },
+    {
+        "duration": "23.0",
+        "name": "blink_perf.svg/Bamboo.html"
+    },
+    {
+        "duration": "12.0",
+        "name": "blink_perf.svg/Cactus.html"
+    },
+    {
+        "duration": "13.0",
+        "name": "blink_perf.svg/Cowboy.html"
+    },
+    {
+        "duration": "14.0",
+        "name": "blink_perf.svg/Cowboy_transform.html"
+    },
+    {
+        "duration": "10.0",
+        "name": "blink_perf.svg/CrawFishGanson.html"
+    },
+    {
+        "duration": "12.0",
+        "name": "blink_perf.svg/Debian.html"
+    },
+    {
+        "duration": "10.0",
+        "name": "blink_perf.svg/DropsOnABlade.html"
+    },
+    {
+        "duration": "10.0",
+        "name": "blink_perf.svg/FlowerFromMyGarden.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.svg/FoodLeifLodahl.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.svg/France.html"
+    },
+    {
+        "duration": "10.0",
+        "name": "blink_perf.svg/FrancoBolloGnomeEzechi.html"
+    },
+    {
+        "duration": "12.0",
+        "name": "blink_perf.svg/GearFlowers.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.svg/HarveyRayner.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.svg/HereGear.html"
+    },
+    {
+        "duration": "33.0",
+        "name": "blink_perf.svg/MtSaintHelens.html"
+    },
+    {
+        "duration": "10.0",
+        "name": "blink_perf.svg/Samurai.html"
+    },
+    {
+        "duration": "360.0",
+        "name": "blink_perf.svg/SierpinskiCarpet.html"
+    },
+    {
+        "duration": "14.0",
+        "name": "blink_perf.svg/SvgCubics.html"
+    },
+    {
+        "duration": "16.0",
+        "name": "blink_perf.svg/SvgHitTesting.html"
+    },
+    {
+        "duration": "23.0",
+        "name": "blink_perf.svg/SvgNestedUse.html"
+    },
+    {
+        "duration": "11.0",
+        "name": "blink_perf.svg/UnderTheSee.html"
+    },
+    {
+        "duration": "13.0",
+        "name": "blink_perf.svg/WorldIso.html"
+    },
+    {
+        "duration": "23.0",
+        "name": "blink_perf.svg/Worldcup.html"
+    },
+    {
+        "duration": "56.0",
+        "name": "dromaeo/http://dromaeo.com?dom-attr"
+    },
+    {
+        "duration": "43.0",
+        "name": "dromaeo/http://dromaeo.com?dom-modify"
+    },
+    {
+        "duration": "56.0",
+        "name": "dromaeo/http://dromaeo.com?dom-query"
+    },
+    {
+        "duration": "36.0",
+        "name": "dromaeo/http://dromaeo.com?dom-traverse"
+    },
+    {
+        "duration": "32.0",
+        "name": "dummy_benchmark.histogram_benchmark_1/dummy_page.html"
+    },
+    {
+        "duration": "31.0",
+        "name": "dummy_benchmark.noisy_benchmark_1/dummy_page.html"
+    },
+    {
+        "duration": "24.0",
+        "name": "dummy_benchmark.stable_benchmark_1/dummy_page.html"
+    },
+    {
+        "duration": "938.0",
+        "name": "jetstream/http://browserbench.org/JetStream/"
+    },
+    {
+        "duration": "317.0",
+        "name": "kraken/http://krakenbenchmark.mozilla.org/kraken-1.1/driver.html"
+    },
+    {
+        "duration": "42.0",
+        "name": "loading.mobile/58Pic"
+    },
+    {
+        "duration": "63.0",
+        "name": "loading.mobile/Amazon"
+    },
+    {
+        "duration": "63.0",
+        "name": "loading.mobile/BOLNoticias"
+    },
+    {
+        "duration": "40.0",
+        "name": "loading.mobile/Baidu"
+    },
+    {
+        "duration": "70.0",
+        "name": "loading.mobile/Baidu_3g"
+    },
+    {
+        "duration": "80.0",
+        "name": "loading.mobile/Bradesco"
+    },
+    {
+        "duration": "58.0",
+        "name": "loading.mobile/Dailymotion"
+    },
+    {
+        "duration": "66.0",
+        "name": "loading.mobile/Dawn"
+    },
+    {
+        "duration": "34.0",
+        "name": "loading.mobile/DevOpera"
+    },
+    {
+        "duration": "80.0",
+        "name": "loading.mobile/Dramaq"
+    },
+    {
+        "duration": "50.0",
+        "name": "loading.mobile/EnquiryIndianRail"
+    },
+    {
+        "duration": "44.0",
+        "name": "loading.mobile/Facebook"
+    },
+    {
+        "duration": "77.0",
+        "name": "loading.mobile/Facebook_3g"
+    },
+    {
+        "duration": "46.0",
+        "name": "loading.mobile/FlipBoard"
+    },
+    {
+        "duration": "55.0",
+        "name": "loading.mobile/FlipKart"
+    },
+    {
+        "duration": "52.0",
+        "name": "loading.mobile/FranceTVInfo"
+    },
+    {
+        "duration": "142.0",
+        "name": "loading.mobile/G1_3g"
+    },
+    {
+        "duration": "128.0",
+        "name": "loading.mobile/GSShop"
+    },
+    {
+        "duration": "36.0",
+        "name": "loading.mobile/GoogleBrazil"
+    },
+    {
+        "duration": "70.0",
+        "name": "loading.mobile/GoogleBrazil_3g"
+    },
+    {
+        "duration": "35.0",
+        "name": "loading.mobile/GoogleIndia"
+    },
+    {
+        "duration": "64.0",
+        "name": "loading.mobile/GoogleIndia_3g"
+    },
+    {
+        "duration": "33.0",
+        "name": "loading.mobile/GoogleIndonesia"
+    },
+    {
+        "duration": "63.0",
+        "name": "loading.mobile/GoogleIndonesia_3g"
+    },
+    {
+        "duration": "48.0",
+        "name": "loading.mobile/GoogleRedirectToGoogleJapan"
+    },
+    {
+        "duration": "89.0",
+        "name": "loading.mobile/GoogleRedirectToGoogleJapan_3g"
+    },
+    {
+        "duration": "63.0",
+        "name": "loading.mobile/Hongkiat"
+    },
+    {
+        "duration": "72.0",
+        "name": "loading.mobile/KapanLagi"
+    },
+    {
+        "duration": "86.0",
+        "name": "loading.mobile/Kaskus"
+    },
+    {
+        "duration": "68.0",
+        "name": "loading.mobile/LocalMoxie"
+    },
+    {
+        "duration": "35.0",
+        "name": "loading.mobile/Locanto"
+    },
+    {
+        "duration": "68.0",
+        "name": "loading.mobile/OLX"
+    },
+    {
+        "duration": "48.0",
+        "name": "loading.mobile/QQNews"
+    },
+    {
+        "duration": "62.0",
+        "name": "loading.mobile/SlideShare"
+    },
+    {
+        "duration": "28.0",
+        "name": "loading.mobile/Suumo"
+    },
+    {
+        "duration": "89.0",
+        "name": "loading.mobile/Thairath"
+    },
+    {
+        "duration": "82.0",
+        "name": "loading.mobile/TheStar"
+    },
+    {
+        "duration": "70.0",
+        "name": "loading.mobile/TribunNews"
+    },
+    {
+        "duration": "51.0",
+        "name": "loading.mobile/Twitter"
+    },
+    {
+        "duration": "40.0",
+        "name": "loading.mobile/VoiceMemos"
+    },
+    {
+        "duration": "55.0",
+        "name": "loading.mobile/Wikipedia"
+    },
+    {
+        "duration": "54.0",
+        "name": "loading.mobile/YahooNews"
+    },
+    {
+        "duration": "102.0",
+        "name": "loading.mobile/YahooNews_3g"
+    },
+    {
+        "duration": "40.0",
+        "name": "loading.mobile/Youtube"
+    },
+    {
+        "duration": "83.0",
+        "name": "loading.mobile/Youtube_3g"
+    },
+    {
+        "duration": "32.0",
+        "name": "media.mobile/mse.html?media=aac_audio.mp4"
+    },
+    {
+        "duration": "42.0",
+        "name": "media.mobile/mse.html?media=aac_audio.mp4,h264_video.mp4"
+    },
+    {
+        "duration": "41.0",
+        "name": "media.mobile/mse.html?media=aac_audio.mp4,h264_video.mp4&waitForPageLoaded=true"
+    },
+    {
+        "duration": "38.0",
+        "name": "media.mobile/mse.html?media=h264_video.mp4"
+    },
+    {
+        "duration": "55.0",
+        "name": "media.mobile/video.html?src=crowd.ogg&type=audio"
+    },
+    {
+        "duration": "41.0",
+        "name": "media.mobile/video.html?src=crowd1080_vp9.webm"
+    },
+    {
+        "duration": "28.0",
+        "name": "media.mobile/video.html?src=crowd1080_vp9.webm&seek"
+    },
+    {
+        "duration": "47.0",
+        "name": "media.mobile/video.html?src=crowd720_vp9.webm"
+    },
+    {
+        "duration": "39.0",
+        "name": "media.mobile/video.html?src=tulip2.m4a&type=audio"
+    },
+    {
+        "duration": "39.0",
+        "name": "media.mobile/video.html?src=tulip2.mp3&type=audio"
+    },
+    {
+        "duration": "19.0",
+        "name": "media.mobile/video.html?src=tulip2.mp3&type=audio&seek"
+    },
+    {
+        "duration": "49.0",
+        "name": "media.mobile/video.html?src=tulip2.mp4"
+    },
+    {
+        "duration": "49.0",
+        "name": "media.mobile/video.html?src=tulip2.mp4&busyjs"
+    },
+    {
+        "duration": "25.0",
+        "name": "media.mobile/video.html?src=tulip2.mp4&seek"
+    },
+    {
+        "duration": "39.0",
+        "name": "media.mobile/video.html?src=tulip2.ogg&type=audio"
+    },
+    {
+        "duration": "19.0",
+        "name": "media.mobile/video.html?src=tulip2.ogg&type=audio&seek"
+    },
+    {
+        "duration": "48.0",
+        "name": "media.mobile/video.html?src=tulip2.vp9.webm"
+    },
+    {
+        "duration": "39.0",
+        "name": "media.mobile/video.html?src=tulip2.vp9.webm&background"
+    },
+    {
+        "duration": "35.0",
+        "name": "media.mobile/video.html?src=tulip2.vp9.webm&seek"
+    },
+    {
+        "duration": "77.0",
+        "name": "media.mobile/video.html?src=tulip2.vp9.webm_Regular-3G"
+    },
+    {
+        "duration": "40.0",
+        "name": "media.mobile/video.html?src=tulip2.wav&type=audio"
+    },
+    {
+        "duration": "20.0",
+        "name": "media.mobile/video.html?src=tulip2.wav&type=audio&seek"
+    },
+    {
+        "duration": "396.0",
+        "name": "memory.long_running_idle_gmail_background_tbmv2/https://mail.google.com/mail/"
+    },
+    {
+        "duration": "351.0",
+        "name": "memory.long_running_idle_gmail_tbmv2/https://mail.google.com/mail/"
+    },
+    {
+        "duration": "24.0",
+        "name": "memory.top_10_mobile/after_http_en_m_wikipedia_org_wiki_Science"
+    },
+    {
+        "duration": "29.0",
+        "name": "memory.top_10_mobile/after_http_m_intl_taobao_com_group_purchase_html"
+    },
+    {
+        "duration": "26.0",
+        "name": "memory.top_10_mobile/after_http_m_youtube_com_results_q_science"
+    },
+    {
+        "duration": "26.0",
+        "name": "memory.top_10_mobile/after_http_search_yahoo_com_search__ylt_p_google"
+    },
+    {
+        "duration": "24.0",
+        "name": "memory.top_10_mobile/after_http_www_amazon_com_gp_aw_s_k_nexus"
+    },
+    {
+        "duration": "27.0",
+        "name": "memory.top_10_mobile/after_http_www_baidu_com_s_word_google"
+    },
+    {
+        "duration": "23.0",
+        "name": "memory.top_10_mobile/after_http_yandex_ru_touchsearch_text_science"
+    },
+    {
+        "duration": "26.0",
+        "name": "memory.top_10_mobile/after_https_m_facebook_com_rihanna"
+    },
+    {
+        "duration": "23.0",
+        "name": "memory.top_10_mobile/after_https_mobile_twitter_com_justinbieber_skip_interstitial_true"
+    },
+    {
+        "duration": "26.0",
+        "name": "memory.top_10_mobile/after_https_www_google_co_uk_hl_en_q_science"
+    },
+    {
+        "duration": "32.0",
+        "name": "memory.top_10_mobile/http_en_m_wikipedia_org_wiki_Science"
+    },
+    {
+        "duration": "28.0",
+        "name": "memory.top_10_mobile/http_m_intl_taobao_com_group_purchase_html"
+    },
+    {
+        "duration": "28.0",
+        "name": "memory.top_10_mobile/http_m_youtube_com_results_q_science"
+    },
+    {
+        "duration": "26.0",
+        "name": "memory.top_10_mobile/http_search_yahoo_com_search__ylt_p_google"
+    },
+    {
+        "duration": "30.0",
+        "name": "memory.top_10_mobile/http_www_amazon_com_gp_aw_s_k_nexus"
+    },
+    {
+        "duration": "29.0",
+        "name": "memory.top_10_mobile/http_www_baidu_com_s_word_google"
+    },
+    {
+        "duration": "30.0",
+        "name": "memory.top_10_mobile/http_yandex_ru_touchsearch_text_science"
+    },
+    {
+        "duration": "28.0",
+        "name": "memory.top_10_mobile/https_m_facebook_com_rihanna"
+    },
+    {
+        "duration": "29.0",
+        "name": "memory.top_10_mobile/https_mobile_twitter_com_justinbieber_skip_interstitial_true"
+    },
+    {
+        "duration": "29.0",
+        "name": "memory.top_10_mobile/https_www_google_co_uk_hl_en_q_science"
+    },
+    {
+        "duration": "562.0",
+        "name": "octane/http://chromium.github.io/octane/index.html?auto=1"
+    },
+    {
+        "duration": "32.0",
+        "name": "oortonline_tbmv2/http://oortonline.gl/#run"
+    },
+    {
+        "duration": "34.0",
+        "name": "power.idle_platform/IdleStory_10s"
+    },
+    {
+        "duration": "131.0",
+        "name": "power.idle_platform/IdleStory_120s"
+    },
+    {
+        "duration": "70.0",
+        "name": "power.idle_platform/IdleStory_60s"
+    },
+    {
+        "duration": "74.0",
+        "name": "power.typical_10_mobile/http://de.m.wikipedia.org/wiki/K%C3%B6lner_Dom"
+    },
+    {
+        "duration": "79.0",
+        "name": "power.typical_10_mobile/http://m.chiebukuro.yahoo.co.jp/detail/q10136829180"
+    },
+    {
+        "duration": "66.0",
+        "name": "power.typical_10_mobile/http://m.ebay.com/itm/351157205404"
+    },
+    {
+        "duration": "90.0",
+        "name": "power.typical_10_mobile/http://m.facebook.com/barackobama"
+    },
+    {
+        "duration": "84.0",
+        "name": "power.typical_10_mobile/http://m.huffpost.com/us/entry/6004486"
+    },
+    {
+        "duration": "77.0",
+        "name": "power.typical_10_mobile/http://m.ynet.co.il"
+    },
+    {
+        "duration": "77.0",
+        "name": "power.typical_10_mobile/http://siriuslymeg.tumblr.com/"
+    },
+    {
+        "duration": "81.0",
+        "name": "power.typical_10_mobile/http://wapbaike.baidu.com/"
+    },
+    {
+        "duration": "74.0",
+        "name": "power.typical_10_mobile/http://www.cnn.com/2014/03/31/showbiz/tv/himym-finale/index.html"
+    },
+    {
+        "duration": "82.0",
+        "name": "power.typical_10_mobile/http://www.rg.ru/2014/10/21/cska-site.html"
+    },
+    {
+        "duration": "76.0",
+        "name": "power.typical_10_mobile/https://en.wikipedia.org/wiki/File:Rotating_earth_(large).gif"
+    },
+    {
+        "duration": "34.0",
+        "name": "rasterize_and_record_micro.partial_invalidation/800_relpos_divs.html"
+    },
+    {
+        "duration": "52.0",
+        "name": "rasterize_and_record_micro.top_25/file://static_top_25/amazon.html"
+    },
+    {
+        "duration": "27.0",
+        "name": "rasterize_and_record_micro.top_25/file://static_top_25/blogger.html"
+    },
+    {
+        "duration": "61.0",
+        "name": "rasterize_and_record_micro.top_25/file://static_top_25/booking.html"
+    },
+    {
+        "duration": "39.0",
+        "name": "rasterize_and_record_micro.top_25/file://static_top_25/cnn.html"
+    },
+    {
+        "duration": "27.0",
+        "name": "rasterize_and_record_micro.top_25/file://static_top_25/ebay.html"
+    },
+    {
+        "duration": "84.0",
+        "name": "rasterize_and_record_micro.top_25/file://static_top_25/espn.html"
+    },
+    {
+        "duration": "31.0",
+        "name": "rasterize_and_record_micro.top_25/file://static_top_25/facebook.html"
+    },
+    {
+        "duration": "57.0",
+        "name": "rasterize_and_record_micro.top_25/file://static_top_25/gmail.html"
+    },
+    {
+        "duration": "49.0",
+        "name": "rasterize_and_record_micro.top_25/file://static_top_25/google.html"
+    },
+    {
+        "duration": "30.0",
+        "name": "rasterize_and_record_micro.top_25/file://static_top_25/googlecalendar.html"
+    },
+    {
+        "duration": "32.0",
+        "name": "rasterize_and_record_micro.top_25/file://static_top_25/googledocs.html"
+    },
+    {
+        "duration": "47.0",
+        "name": "rasterize_and_record_micro.top_25/file://static_top_25/googleimagesearch.html"
+    },
+    {
+        "duration": "62.0",
+        "name": "rasterize_and_record_micro.top_25/file://static_top_25/googleplus.html"
+    },
+    {
+        "duration": "26.0",
+        "name": "rasterize_and_record_micro.top_25/file://static_top_25/linkedin.html"
+    },
+    {
+        "duration": "15.0",
+        "name": "rasterize_and_record_micro.top_25/file://static_top_25/pinterest.html"
+    },
+    {
+        "duration": "68.0",
+        "name": "rasterize_and_record_micro.top_25/file://static_top_25/techcrunch.html"
+    },
+    {
+        "duration": "74.0",
+        "name": "rasterize_and_record_micro.top_25/file://static_top_25/twitter.html"
+    },
+    {
+        "duration": "34.0",
+        "name": "rasterize_and_record_micro.top_25/file://static_top_25/weather.html"
+    },
+    {
+        "duration": "0.0",
+        "name": "rasterize_and_record_micro.top_25/file://static_top_25/wikipedia.html"
+    },
+    {
+        "duration": "28.0",
+        "name": "rasterize_and_record_micro.top_25/file://static_top_25/wordpress.html"
+    },
+    {
+        "duration": "28.0",
+        "name": "rasterize_and_record_micro.top_25/file://static_top_25/yahooanswers.html"
+    },
+    {
+        "duration": "57.0",
+        "name": "rasterize_and_record_micro.top_25/file://static_top_25/yahoogames.html"
+    },
+    {
+        "duration": "145.0",
+        "name": "rasterize_and_record_micro.top_25/file://static_top_25/yahoonews.html"
+    },
+    {
+        "duration": "129.0",
+        "name": "rasterize_and_record_micro.top_25/file://static_top_25/yahoosports.html"
+    },
+    {
+        "duration": "65.0",
+        "name": "rasterize_and_record_micro.top_25/file://static_top_25/youtube.html"
+    },
+    {
+        "duration": "33.0",
+        "name": "rendering.mobile/amazon_pinch"
+    },
+    {
+        "duration": "31.0",
+        "name": "rendering.mobile/amazon_pinch_desktop_gpu_raster"
+    },
+    {
+        "duration": "32.0",
+        "name": "rendering.mobile/analog_clock_svg"
+    },
+    {
+        "duration": "38.0",
+        "name": "rendering.mobile/androidpolice_mobile"
+    },
+    {
+        "duration": "38.0",
+        "name": "rendering.mobile/androidpolice_mobile_sync_scroll"
+    },
+    {
+        "duration": "9.0",
+        "name": "rendering.mobile/animometer_webgl"
+    },
+    {
+        "duration": "9.0",
+        "name": "rendering.mobile/aquarium"
+    },
+    {
+        "duration": "49.0",
+        "name": "rendering.mobile/background_color_animation"
+    },
+    {
+        "duration": "32.0",
+        "name": "rendering.mobile/background_color_animation_with_gradient"
+    },
+    {
+        "duration": "25.0",
+        "name": "rendering.mobile/baidu_mobile"
+    },
+    {
+        "duration": "23.0",
+        "name": "rendering.mobile/baidu_mobile_sync_scroll"
+    },
+    {
+        "duration": "37.0",
+        "name": "rendering.mobile/balls_css_key_frame_animations"
+    },
+    {
+        "duration": "33.0",
+        "name": "rendering.mobile/balls_css_transition_2_properties"
+    },
+    {
+        "duration": "34.0",
+        "name": "rendering.mobile/balls_css_transition_40_properties"
+    },
+    {
+        "duration": "33.0",
+        "name": "rendering.mobile/balls_css_transition_all_properties"
+    },
+    {
+        "duration": "42.0",
+        "name": "rendering.mobile/balls_javascript_canvas"
+    },
+    {
+        "duration": "33.0",
+        "name": "rendering.mobile/balls_javascript_css"
+    },
+    {
+        "duration": "77.0",
+        "name": "rendering.mobile/balls_svg_animations"
+    },
+    {
+        "duration": "23.0",
+        "name": "rendering.mobile/bing_mobile"
+    },
+    {
+        "duration": "22.0",
+        "name": "rendering.mobile/bing_mobile_sync_scroll"
+    },
+    {
+        "duration": "9.0",
+        "name": "rendering.mobile/blob"
+    },
+    {
+        "duration": "46.0",
+        "name": "rendering.mobile/blogspot"
+    },
+    {
+        "duration": "44.0",
+        "name": "rendering.mobile/blogspot_desktop_gpu_raster"
+    },
+    {
+        "duration": "24.0",
+        "name": "rendering.mobile/blogspot_mobile"
+    },
+    {
+        "duration": "22.0",
+        "name": "rendering.mobile/blogspot_mobile_sync_scroll"
+    },
+    {
+        "duration": "52.0",
+        "name": "rendering.mobile/boingboing_mobile"
+    },
+    {
+        "duration": "36.0",
+        "name": "rendering.mobile/booking.com"
+    },
+    {
+        "duration": "34.0",
+        "name": "rendering.mobile/booking.com_desktop_gpu_raster"
+    },
+    {
+        "duration": "34.0",
+        "name": "rendering.mobile/booking.com_mobile"
+    },
+    {
+        "duration": "34.0",
+        "name": "rendering.mobile/booking.com_mobile_sync_scroll"
+    },
+    {
+        "duration": "38.0",
+        "name": "rendering.mobile/booking_pinch"
+    },
+    {
+        "duration": "38.0",
+        "name": "rendering.mobile/booking_pinch_desktop_gpu_raster"
+    },
+    {
+        "duration": "28.0",
+        "name": "rendering.mobile/bouncing_balls_15"
+    },
+    {
+        "duration": "49.0",
+        "name": "rendering.mobile/bouncing_balls_shadow"
+    },
+    {
+        "duration": "33.0",
+        "name": "rendering.mobile/bouncing_clipped_rectangles"
+    },
+    {
+        "duration": "27.0",
+        "name": "rendering.mobile/bouncing_gradient_circles"
+    },
+    {
+        "duration": "21.0",
+        "name": "rendering.mobile/bouncing_png_images"
+    },
+    {
+        "duration": "41.0",
+        "name": "rendering.mobile/bouncing_svg_images"
+    },
+    {
+        "duration": "24.0",
+        "name": "rendering.mobile/canvas_animation_no_clear"
+    },
+    {
+        "duration": "27.0",
+        "name": "rendering.mobile/canvas_arcs"
+    },
+    {
+        "duration": "28.0",
+        "name": "rendering.mobile/canvas_font_cycler"
+    },
+    {
+        "duration": "25.0",
+        "name": "rendering.mobile/canvas_lines"
+    },
+    {
+        "duration": "29.0",
+        "name": "rendering.mobile/canvas_to_blob"
+    },
+    {
+        "duration": "35.0",
+        "name": "rendering.mobile/capitolvolkswagen_mobile"
+    },
+    {
+        "duration": "35.0",
+        "name": "rendering.mobile/capitolvolkswagen_mobile_sync_scroll"
+    },
+    {
+        "duration": "32.0",
+        "name": "rendering.mobile/chip_tune"
+    },
+    {
+        "duration": "53.0",
+        "name": "rendering.mobile/cnn_article_mobile"
+    },
+    {
+        "duration": "53.0",
+        "name": "rendering.mobile/cnn_article_mobile_sync_scroll"
+    },
+    {
+        "duration": "27.0",
+        "name": "rendering.mobile/cnn_mobile"
+    },
+    {
+        "duration": "27.0",
+        "name": "rendering.mobile/cnn_mobile_sync_scroll"
+    },
+    {
+        "duration": "53.0",
+        "name": "rendering.mobile/cnn_pathological"
+    },
+    {
+        "duration": "54.0",
+        "name": "rendering.mobile/cnn_pinch"
+    },
+    {
+        "duration": "54.0",
+        "name": "rendering.mobile/cnn_pinch_desktop_gpu_raster"
+    },
+    {
+        "duration": "31.0",
+        "name": "rendering.mobile/compositor_heavy_animation"
+    },
+    {
+        "duration": "31.0",
+        "name": "rendering.mobile/crafty_mind"
+    },
+    {
+        "duration": "38.0",
+        "name": "rendering.mobile/css_animations_many_keyframes"
+    },
+    {
+        "duration": "36.0",
+        "name": "rendering.mobile/css_animations_simultaneous_inline_style"
+    },
+    {
+        "duration": "38.0",
+        "name": "rendering.mobile/css_animations_simultaneous_new_element"
+    },
+    {
+        "duration": "36.0",
+        "name": "rendering.mobile/css_animations_simultaneous_style_element"
+    },
+    {
+        "duration": "44.0",
+        "name": "rendering.mobile/css_animations_simultaneous_updating_class"
+    },
+    {
+        "duration": "35.0",
+        "name": "rendering.mobile/css_animations_staggered_infinite_iterations"
+    },
+    {
+        "duration": "38.0",
+        "name": "rendering.mobile/css_animations_staggered_inline_style"
+    },
+    {
+        "duration": "40.0",
+        "name": "rendering.mobile/css_animations_staggered_new_element"
+    },
+    {
+        "duration": "44.0",
+        "name": "rendering.mobile/css_animations_staggered_style_element"
+    },
+    {
+        "duration": "39.0",
+        "name": "rendering.mobile/css_animations_staggered_updating_class"
+    },
+    {
+        "duration": "39.0",
+        "name": "rendering.mobile/css_animations_triggered_inline_style"
+    },
+    {
+        "duration": "40.0",
+        "name": "rendering.mobile/css_animations_triggered_new_element"
+    },
+    {
+        "duration": "51.0",
+        "name": "rendering.mobile/css_animations_triggered_style_element"
+    },
+    {
+        "duration": "39.0",
+        "name": "rendering.mobile/css_animations_triggered_updating_class"
+    },
+    {
+        "duration": "36.0",
+        "name": "rendering.mobile/css_transitions_inline_style"
+    },
+    {
+        "duration": "37.0",
+        "name": "rendering.mobile/css_transitions_new_element"
+    },
+    {
+        "duration": "37.0",
+        "name": "rendering.mobile/css_transitions_staggered_inline_style"
+    },
+    {
+        "duration": "37.0",
+        "name": "rendering.mobile/css_transitions_staggered_new_element"
+    },
+    {
+        "duration": "36.0",
+        "name": "rendering.mobile/css_transitions_staggered_style_element"
+    },
+    {
+        "duration": "36.0",
+        "name": "rendering.mobile/css_transitions_staggered_updating_class"
+    },
+    {
+        "duration": "36.0",
+        "name": "rendering.mobile/css_transitions_style_element"
+    },
+    {
+        "duration": "39.0",
+        "name": "rendering.mobile/css_transitions_triggered_inline_style"
+    },
+    {
+        "duration": "39.0",
+        "name": "rendering.mobile/css_transitions_triggered_new_element"
+    },
+    {
+        "duration": "37.0",
+        "name": "rendering.mobile/css_transitions_triggered_style_element"
+    },
+    {
+        "duration": "39.0",
+        "name": "rendering.mobile/css_transitions_triggered_updating_class"
+    },
+    {
+        "duration": "36.0",
+        "name": "rendering.mobile/css_transitions_updating_class"
+    },
+    {
+        "duration": "35.0",
+        "name": "rendering.mobile/css_value_type_color"
+    },
+    {
+        "duration": "50.0",
+        "name": "rendering.mobile/css_value_type_filter"
+    },
+    {
+        "duration": "31.0",
+        "name": "rendering.mobile/css_value_type_length"
+    },
+    {
+        "duration": "34.0",
+        "name": "rendering.mobile/css_value_type_length_complex"
+    },
+    {
+        "duration": "34.0",
+        "name": "rendering.mobile/css_value_type_length_simple"
+    },
+    {
+        "duration": "35.0",
+        "name": "rendering.mobile/css_value_type_path"
+    },
+    {
+        "duration": "32.0",
+        "name": "rendering.mobile/css_value_type_shadow"
+    },
+    {
+        "duration": "31.0",
+        "name": "rendering.mobile/css_value_type_transform_complex"
+    },
+    {
+        "duration": "32.0",
+        "name": "rendering.mobile/css_value_type_transform_simple"
+    },
+    {
+        "duration": "51.0",
+        "name": "rendering.mobile/cuteoverload_mobile"
+    },
+    {
+        "duration": "39.0",
+        "name": "rendering.mobile/deviantart_mobile"
+    },
+    {
+        "duration": "40.0",
+        "name": "rendering.mobile/deviantart_mobile_sync_scroll"
+    },
+    {
+        "duration": "9.0",
+        "name": "rendering.mobile/dynamic_cube_map"
+    },
+    {
+        "duration": "9.0",
+        "name": "rendering.mobile/earth"
+    },
+    {
+        "duration": "25.0",
+        "name": "rendering.mobile/ebay"
+    },
+    {
+        "duration": "23.0",
+        "name": "rendering.mobile/ebay_desktop_gpu_raster"
+    },
+    {
+        "duration": "30.0",
+        "name": "rendering.mobile/ebay_mobile"
+    },
+    {
+        "duration": "29.0",
+        "name": "rendering.mobile/ebay_mobile_sync_scroll"
+    },
+    {
+        "duration": "51.0",
+        "name": "rendering.mobile/ebay_pinch"
+    },
+    {
+        "duration": "49.0",
+        "name": "rendering.mobile/ebay_pinch_desktop_gpu_raster"
+    },
+    {
+        "duration": "36.0",
+        "name": "rendering.mobile/effect_games"
+    },
+    {
+        "duration": "21.0",
+        "name": "rendering.mobile/espn"
+    },
+    {
+        "duration": "19.0",
+        "name": "rendering.mobile/espn_desktop_gpu_raster"
+    },
+    {
+        "duration": "38.0",
+        "name": "rendering.mobile/espn_pathological"
+    },
+    {
+        "duration": "57.0",
+        "name": "rendering.mobile/espn_pinch"
+    },
+    {
+        "duration": "56.0",
+        "name": "rendering.mobile/espn_pinch_desktop_gpu_raster"
+    },
+    {
+        "duration": "38.0",
+        "name": "rendering.mobile/extra_large_texture_uploads"
+    },
+    {
+        "duration": "30.0",
+        "name": "rendering.mobile/facebook"
+    },
+    {
+        "duration": "31.0",
+        "name": "rendering.mobile/facebook_desktop_gpu_raster"
+    },
+    {
+        "duration": "28.0",
+        "name": "rendering.mobile/facebook_mobile"
+    },
+    {
+        "duration": "37.0",
+        "name": "rendering.mobile/facebook_mobile_sync_scroll"
+    },
+    {
+        "duration": "40.0",
+        "name": "rendering.mobile/facebook_pinch"
+    },
+    {
+        "duration": "39.0",
+        "name": "rendering.mobile/facebook_pinch_desktop_gpu_raster"
+    },
+    {
+        "duration": "26.0",
+        "name": "rendering.mobile/fill_shapes"
+    },
+    {
+        "duration": "32.0",
+        "name": "rendering.mobile/filter_terrain_svg"
+    },
+    {
+        "duration": "24.0",
+        "name": "rendering.mobile/geo_apis"
+    },
+    {
+        "duration": "73.0",
+        "name": "rendering.mobile/gmail"
+    },
+    {
+        "duration": "84.0",
+        "name": "rendering.mobile/gmail_desktop_gpu_raster"
+    },
+    {
+        "duration": "64.0",
+        "name": "rendering.mobile/gmail_pinch"
+    },
+    {
+        "duration": "65.0",
+        "name": "rendering.mobile/gmail_pinch_desktop_gpu_raster"
+    },
+    {
+        "duration": "44.0",
+        "name": "rendering.mobile/google_calendar"
+    },
+    {
+        "duration": "44.0",
+        "name": "rendering.mobile/google_calendar_desktop_gpu_raster"
+    },
+    {
+        "duration": "37.0",
+        "name": "rendering.mobile/google_calendar_pinch"
+    },
+    {
+        "duration": "36.0",
+        "name": "rendering.mobile/google_calendar_pinch_desktop_gpu_raster"
+    },
+    {
+        "duration": "70.0",
+        "name": "rendering.mobile/google_docs"
+    },
+    {
+        "duration": "70.0",
+        "name": "rendering.mobile/google_docs_desktop_gpu_raster"
+    },
+    {
+        "duration": "40.0",
+        "name": "rendering.mobile/google_image_pinch"
+    },
+    {
+        "duration": "39.0",
+        "name": "rendering.mobile/google_image_pinch_desktop_gpu_raster"
+    },
+    {
+        "duration": "51.0",
+        "name": "rendering.mobile/google_image_search"
+    },
+    {
+        "duration": "51.0",
+        "name": "rendering.mobile/google_image_search_desktop_gpu_raster"
+    },
+    {
+        "duration": "36.0",
+        "name": "rendering.mobile/google_news_mobile"
+    },
+    {
+        "duration": "36.0",
+        "name": "rendering.mobile/google_news_mobile_sync_scroll"
+    },
+    {
+        "duration": "62.0",
+        "name": "rendering.mobile/google_plus"
+    },
+    {
+        "duration": "62.0",
+        "name": "rendering.mobile/google_plus_desktop_gpu_raster"
+    },
+    {
+        "duration": "31.0",
+        "name": "rendering.mobile/google_plus_mobile"
+    },
+    {
+        "duration": "30.0",
+        "name": "rendering.mobile/google_plus_mobile_sync_scroll"
+    },
+    {
+        "duration": "34.0",
+        "name": "rendering.mobile/google_search_pinch"
+    },
+    {
+        "duration": "34.0",
+        "name": "rendering.mobile/google_search_pinch_desktop_gpu_raster"
+    },
+    {
+        "duration": "26.0",
+        "name": "rendering.mobile/google_web_search"
+    },
+    {
+        "duration": "24.0",
+        "name": "rendering.mobile/google_web_search_desktop_gpu_raster"
+    },
+    {
+        "duration": "25.0",
+        "name": "rendering.mobile/google_web_search_mobile"
+    },
+    {
+        "duration": "24.0",
+        "name": "rendering.mobile/google_web_search_mobile_sync_scroll"
+    },
+    {
+        "duration": "28.0",
+        "name": "rendering.mobile/gsp.ro_mobile"
+    },
+    {
+        "duration": "26.0",
+        "name": "rendering.mobile/gsp.ro_mobile_sync_scroll"
+    },
+    {
+        "duration": "30.0",
+        "name": "rendering.mobile/guardian_pathological"
+    },
+    {
+        "duration": "37.0",
+        "name": "rendering.mobile/guimark_vector_chart"
+    },
+    {
+        "duration": "27.0",
+        "name": "rendering.mobile/gws_boogie_expansion"
+    },
+    {
+        "duration": "27.0",
+        "name": "rendering.mobile/gws_google_expansion"
+    },
+    {
+        "duration": "32.0",
+        "name": "rendering.mobile/hakim"
+    },
+    {
+        "duration": "47.0",
+        "name": "rendering.mobile/ie_chalkboard"
+    },
+    {
+        "duration": "34.0",
+        "name": "rendering.mobile/jarro_doverson"
+    },
+    {
+        "duration": "31.0",
+        "name": "rendering.mobile/kevs_3d"
+    },
+    {
+        "duration": "35.0",
+        "name": "rendering.mobile/keyframed_animations"
+    },
+    {
+        "duration": "32.0",
+        "name": "rendering.mobile/large_texture_uploads"
+    },
+    {
+        "duration": "41.0",
+        "name": "rendering.mobile/latimes_pathological"
+    },
+    {
+        "duration": "26.0",
+        "name": "rendering.mobile/linkedin"
+    },
+    {
+        "duration": "25.0",
+        "name": "rendering.mobile/linkedin_desktop_gpu_raster"
+    },
+    {
+        "duration": "32.0",
+        "name": "rendering.mobile/linkedin_mobile"
+    },
+    {
+        "duration": "32.0",
+        "name": "rendering.mobile/linkedin_mobile_sync_scroll"
+    },
+    {
+        "duration": "36.0",
+        "name": "rendering.mobile/linkedin_pathological"
+    },
+    {
+        "duration": "32.0",
+        "name": "rendering.mobile/linkedin_pinch"
+    },
+    {
+        "duration": "32.0",
+        "name": "rendering.mobile/linkedin_pinch_desktop_gpu_raster"
+    },
+    {
+        "duration": "30.0",
+        "name": "rendering.mobile/man_in_blue"
+    },
+    {
+        "duration": "41.0",
+        "name": "rendering.mobile/many_images"
+    },
+    {
+        "duration": "9.0",
+        "name": "rendering.mobile/many_planets_deep"
+    },
+    {
+        "duration": "8.0",
+        "name": "rendering.mobile/maps_perf_test"
+    },
+    {
+        "duration": "39.0",
+        "name": "rendering.mobile/masonry"
+    },
+    {
+        "duration": "35.0",
+        "name": "rendering.mobile/medium_texture_uploads"
+    },
+    {
+        "duration": "30.0",
+        "name": "rendering.mobile/megi_dish"
+    },
+    {
+        "duration": "35.0",
+        "name": "rendering.mobile/microsoft_asteroid_belt"
+    },
+    {
+        "duration": "37.0",
+        "name": "rendering.mobile/microsoft_fireflies"
+    },
+    {
+        "duration": "27.0",
+        "name": "rendering.mobile/microsoft_fish_ie_tank"
+    },
+    {
+        "duration": "28.0",
+        "name": "rendering.mobile/microsoft_snow"
+    },
+    {
+        "duration": "27.0",
+        "name": "rendering.mobile/microsoft_speed_reading"
+    },
+    {
+        "duration": "33.0",
+        "name": "rendering.mobile/microsoft_tweet_map"
+    },
+    {
+        "duration": "30.0",
+        "name": "rendering.mobile/microsoft_video_city"
+    },
+    {
+        "duration": "27.0",
+        "name": "rendering.mobile/microsoft_worker_fountains"
+    },
+    {
+        "duration": "29.0",
+        "name": "rendering.mobile/mix_10k"
+    },
+    {
+        "duration": "35.0",
+        "name": "rendering.mobile/mix_blend_mode_animation_difference"
+    },
+    {
+        "duration": "34.0",
+        "name": "rendering.mobile/mix_blend_mode_animation_hue"
+    },
+    {
+        "duration": "38.0",
+        "name": "rendering.mobile/mix_blend_mode_animation_propagating_isolation"
+    },
+    {
+        "duration": "22.0",
+        "name": "rendering.mobile/mlb_mobile"
+    },
+    {
+        "duration": "22.0",
+        "name": "rendering.mobile/mlb_mobile_sync_scroll"
+    },
+    {
+        "duration": "25.0",
+        "name": "scheduler.tough_scheduling_cases/raf.html"
+    },
+    {
+        "duration": "25.0",
+        "name": "scheduler.tough_scheduling_cases/raf_animation.html"
+    },
+    {
+        "duration": "25.0",
+        "name": "scheduler.tough_scheduling_cases/raf_canvas.html"
+    },
+    {
+        "duration": "25.0",
+        "name": "scheduler.tough_scheduling_cases/raf_touch_animation.html"
+    },
+    {
+        "duration": "19.0",
+        "name": "scheduler.tough_scheduling_cases/second_batch_js.html?heavy"
+    },
+    {
+        "duration": "17.0",
+        "name": "scheduler.tough_scheduling_cases/second_batch_js.html?light"
+    },
+    {
+        "duration": "17.0",
+        "name": "scheduler.tough_scheduling_cases/second_batch_js.html?medium"
+    },
+    {
+        "duration": "39.0",
+        "name": "scheduler.tough_scheduling_cases/simple_text_page.html"
+    },
+    {
+        "duration": "18.0",
+        "name": "scheduler.tough_scheduling_cases/simple_touch_drag.html"
+    },
+    {
+        "duration": "23.0",
+        "name": "scheduler.tough_scheduling_cases/sync_scroll_offset.html"
+    },
+    {
+        "duration": "23.0",
+        "name": "scheduler.tough_scheduling_cases/touch_handler_scrolling.html"
+    },
+    {
+        "duration": "33.0",
+        "name": "smoothness.gpu_rasterization.top_25_smooth/blogspot"
+    },
+    {
+        "duration": "26.0",
+        "name": "smoothness.gpu_rasterization.top_25_smooth/booking.com"
+    },
+    {
+        "duration": "19.0",
+        "name": "smoothness.gpu_rasterization.top_25_smooth/ebay"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.gpu_rasterization.top_25_smooth/espn"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.gpu_rasterization.top_25_smooth/facebook"
+    },
+    {
+        "duration": "65.0",
+        "name": "smoothness.gpu_rasterization.top_25_smooth/gmail"
+    },
+    {
+        "duration": "34.0",
+        "name": "smoothness.gpu_rasterization.top_25_smooth/google_calendar"
+    },
+    {
+        "duration": "51.0",
+        "name": "smoothness.gpu_rasterization.top_25_smooth/google_docs"
+    },
+    {
+        "duration": "38.0",
+        "name": "smoothness.gpu_rasterization.top_25_smooth/google_image_search"
+    },
+    {
+        "duration": "46.0",
+        "name": "smoothness.gpu_rasterization.top_25_smooth/google_plus"
+    },
+    {
+        "duration": "20.0",
+        "name": "smoothness.gpu_rasterization.top_25_smooth/google_web_search"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.gpu_rasterization.top_25_smooth/linkedin"
+    },
+    {
+        "duration": "34.0",
+        "name": "smoothness.gpu_rasterization.top_25_smooth/techcrunch"
+    },
+    {
+        "duration": "26.0",
+        "name": "smoothness.gpu_rasterization.top_25_smooth/twitter"
+    },
+    {
+        "duration": "28.0",
+        "name": "smoothness.gpu_rasterization.top_25_smooth/weather.com"
+    },
+    {
+        "duration": "37.0",
+        "name": "smoothness.gpu_rasterization.top_25_smooth/wikipedia"
+    },
+    {
+        "duration": "30.0",
+        "name": "smoothness.gpu_rasterization.top_25_smooth/wordpress"
+    },
+    {
+        "duration": "24.0",
+        "name": "smoothness.gpu_rasterization.top_25_smooth/yahoo_answers"
+    },
+    {
+        "duration": "39.0",
+        "name": "smoothness.gpu_rasterization.top_25_smooth/yahoo_games"
+    },
+    {
+        "duration": "29.0",
+        "name": "smoothness.gpu_rasterization.top_25_smooth/yahoo_news"
+    },
+    {
+        "duration": "26.0",
+        "name": "smoothness.gpu_rasterization.top_25_smooth/yahoo_sports"
+    },
+    {
+        "duration": "37.0",
+        "name": "smoothness.gpu_rasterization.top_25_smooth/youtube"
+    },
+    {
+        "duration": "28.0",
+        "name": "smoothness.gpu_rasterization.tough_filters_cases/Analog_Clock_SVG"
+    },
+    {
+        "duration": "32.0",
+        "name": "smoothness.gpu_rasterization.tough_filters_cases/Filter_Terrain_SVG"
+    },
+    {
+        "duration": "31.0",
+        "name": "smoothness.gpu_rasterization.tough_filters_cases/IE_PirateMark"
+    },
+    {
+        "duration": "42.0",
+        "name": "smoothness.gpu_rasterization.tough_filters_cases/MotionMark_Focus"
+    },
+    {
+        "duration": "43.0",
+        "name": "smoothness.gpu_rasterization.tough_path_rendering_cases/GUIMark_Vector_Chart_Test"
+    },
+    {
+        "duration": "39.0",
+        "name": "smoothness.gpu_rasterization.tough_path_rendering_cases/IE_Chalkboard"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.gpu_rasterization.tough_path_rendering_cases/MotionMark_Canvas_Fill_Shapes"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.gpu_rasterization.tough_path_rendering_cases/MotionMark_Canvas_Stroke_Shapes"
+    },
+    {
+        "duration": "32.0",
+        "name": "smoothness.gpu_rasterization.tough_pinch_zoom_cases/Blogger"
+    },
+    {
+        "duration": "39.0",
+        "name": "smoothness.gpu_rasterization.tough_pinch_zoom_cases/ESPN"
+    },
+    {
+        "duration": "29.0",
+        "name": "smoothness.gpu_rasterization.tough_pinch_zoom_cases/Facebook"
+    },
+    {
+        "duration": "24.0",
+        "name": "smoothness.gpu_rasterization.tough_pinch_zoom_cases/LinkedIn"
+    },
+    {
+        "duration": "29.0",
+        "name": "smoothness.gpu_rasterization.tough_pinch_zoom_cases/Twitter"
+    },
+    {
+        "duration": "36.0",
+        "name": "smoothness.gpu_rasterization.tough_pinch_zoom_cases/Weather.com"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.gpu_rasterization.tough_pinch_zoom_cases/http://booking.com"
+    },
+    {
+        "duration": "38.0",
+        "name": "smoothness.gpu_rasterization.tough_pinch_zoom_cases/http://games.yahoo.com"
+    },
+    {
+        "duration": "36.0",
+        "name": "smoothness.gpu_rasterization.tough_pinch_zoom_cases/http://news.yahoo.com"
+    },
+    {
+        "duration": "42.0",
+        "name": "smoothness.gpu_rasterization.tough_pinch_zoom_cases/http://sports.yahoo.com/"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.gpu_rasterization.tough_pinch_zoom_cases/http://www.amazon.com"
+    },
+    {
+        "duration": "36.0",
+        "name": "smoothness.gpu_rasterization.tough_pinch_zoom_cases/http://www.cnn.com"
+    },
+    {
+        "duration": "34.0",
+        "name": "smoothness.gpu_rasterization.tough_pinch_zoom_cases/http://www.ebay.com"
+    },
+    {
+        "duration": "33.0",
+        "name": "smoothness.gpu_rasterization.tough_pinch_zoom_cases/http://www.youtube.com"
+    },
+    {
+        "duration": "48.0",
+        "name": "smoothness.gpu_rasterization.tough_pinch_zoom_cases/https://mail.google.com/mail/"
+    },
+    {
+        "duration": "43.0",
+        "name": "smoothness.gpu_rasterization.tough_pinch_zoom_cases/https://www.google.com/#hl=en&q=barack+obama"
+    },
+    {
+        "duration": "28.0",
+        "name": "smoothness.gpu_rasterization.tough_pinch_zoom_cases/https://www.google.com/calendar/"
+    },
+    {
+        "duration": "28.0",
+        "name": "smoothness.gpu_rasterization.tough_pinch_zoom_cases/https://www.google.com/search?q=cats&tbm=isch"
+    },
+    {
+        "duration": "26.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/canvas_05000_pixels_per_second"
+    },
+    {
+        "duration": "26.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/canvas_10000_pixels_per_second"
+    },
+    {
+        "duration": "26.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/canvas_15000_pixels_per_second"
+    },
+    {
+        "duration": "26.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/canvas_20000_pixels_per_second"
+    },
+    {
+        "duration": "26.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/canvas_30000_pixels_per_second"
+    },
+    {
+        "duration": "26.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/canvas_40000_pixels_per_second"
+    },
+    {
+        "duration": "25.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/canvas_50000_pixels_per_second"
+    },
+    {
+        "duration": "24.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/canvas_60000_pixels_per_second"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/canvas_75000_pixels_per_second"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/canvas_90000_pixels_per_second"
+    },
+    {
+        "duration": "40.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_05000_pixels_per_second"
+    },
+    {
+        "duration": "24.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_10000_pixels_per_second"
+    },
+    {
+        "duration": "25.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_15000_pixels_per_second"
+    },
+    {
+        "duration": "25.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_20000_pixels_per_second"
+    },
+    {
+        "duration": "25.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_30000_pixels_per_second"
+    },
+    {
+        "duration": "25.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_40000_pixels_per_second"
+    },
+    {
+        "duration": "24.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_50000_pixels_per_second"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_60000_pixels_per_second"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_75000_pixels_per_second"
+    },
+    {
+        "duration": "20.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_90000_pixels_per_second"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_constant_full_page_raster_05000_pixels_per_second"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_constant_full_page_raster_10000_pixels_per_second"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_constant_full_page_raster_15000_pixels_per_second"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_constant_full_page_raster_20000_pixels_per_second"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_constant_full_page_raster_30000_pixels_per_second"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_constant_full_page_raster_40000_pixels_per_second"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_constant_full_page_raster_50000_pixels_per_second"
+    },
+    {
+        "duration": "26.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_constant_full_page_raster_60000_pixels_per_second"
+    },
+    {
+        "duration": "25.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_constant_full_page_raster_75000_pixels_per_second"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_constant_full_page_raster_90000_pixels_per_second"
+    },
+    {
+        "duration": "24.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_hover_05000_pixels_per_second"
+    },
+    {
+        "duration": "24.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_hover_10000_pixels_per_second"
+    },
+    {
+        "duration": "25.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_hover_15000_pixels_per_second"
+    },
+    {
+        "duration": "25.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_hover_20000_pixels_per_second"
+    },
+    {
+        "duration": "25.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_hover_30000_pixels_per_second"
+    },
+    {
+        "duration": "25.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_hover_40000_pixels_per_second"
+    },
+    {
+        "duration": "24.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_hover_50000_pixels_per_second"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_hover_60000_pixels_per_second"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_hover_75000_pixels_per_second"
+    },
+    {
+        "duration": "20.0",
+        "name": "smoothness.gpu_rasterization.tough_scrolling_cases/text_hover_90000_pixels_per_second"
+    },
+    {
+        "duration": "67.0",
+        "name": "smoothness.gpu_rasterization_and_decoding.image_decoding_cases/yuv_decoding.html"
+    },
+    {
+        "duration": "67.0",
+        "name": "smoothness.image_decoding_cases/yuv_decoding.html"
+    },
+    {
+        "duration": "26.0",
+        "name": "smoothness.key_mobile_sites_smooth/androidpolice"
+    },
+    {
+        "duration": "19.0",
+        "name": "smoothness.key_mobile_sites_smooth/baidu"
+    },
+    {
+        "duration": "18.0",
+        "name": "smoothness.key_mobile_sites_smooth/bing"
+    },
+    {
+        "duration": "20.0",
+        "name": "smoothness.key_mobile_sites_smooth/blogspot"
+    },
+    {
+        "duration": "35.0",
+        "name": "smoothness.key_mobile_sites_smooth/boingboing"
+    },
+    {
+        "duration": "26.0",
+        "name": "smoothness.key_mobile_sites_smooth/booking.com"
+    },
+    {
+        "duration": "42.0",
+        "name": "smoothness.key_mobile_sites_smooth/capitolvolkswagen"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.key_mobile_sites_smooth/cnn"
+    },
+    {
+        "duration": "37.0",
+        "name": "smoothness.key_mobile_sites_smooth/cnn_article"
+    },
+    {
+        "duration": "33.0",
+        "name": "smoothness.key_mobile_sites_smooth/cuteoverload"
+    },
+    {
+        "duration": "28.0",
+        "name": "smoothness.key_mobile_sites_smooth/deviantart"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.key_mobile_sites_smooth/ebay"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.key_mobile_sites_smooth/facebook"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.key_mobile_sites_smooth/google_news"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.key_mobile_sites_smooth/google_plus"
+    },
+    {
+        "duration": "19.0",
+        "name": "smoothness.key_mobile_sites_smooth/google_web_search"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.key_mobile_sites_smooth/gsp.ro"
+    },
+    {
+        "duration": "25.0",
+        "name": "smoothness.key_mobile_sites_smooth/linkedin"
+    },
+    {
+        "duration": "18.0",
+        "name": "smoothness.key_mobile_sites_smooth/mlb"
+    },
+    {
+        "duration": "24.0",
+        "name": "smoothness.key_mobile_sites_smooth/nytimes"
+    },
+    {
+        "duration": "28.0",
+        "name": "smoothness.key_mobile_sites_smooth/pinterest"
+    },
+    {
+        "duration": "29.0",
+        "name": "smoothness.key_mobile_sites_smooth/reddit"
+    },
+    {
+        "duration": "24.0",
+        "name": "smoothness.key_mobile_sites_smooth/sfgate"
+    },
+    {
+        "duration": "30.0",
+        "name": "smoothness.key_mobile_sites_smooth/slashdot"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.key_mobile_sites_smooth/techcrunch"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.key_mobile_sites_smooth/theverge"
+    },
+    {
+        "duration": "38.0",
+        "name": "smoothness.key_mobile_sites_smooth/theverge_article"
+    },
+    {
+        "duration": "35.0",
+        "name": "smoothness.key_mobile_sites_smooth/usatoday"
+    },
+    {
+        "duration": "26.0",
+        "name": "smoothness.key_mobile_sites_smooth/wikipedia"
+    },
+    {
+        "duration": "26.0",
+        "name": "smoothness.key_mobile_sites_smooth/wikipedia_delayed_scroll_start"
+    },
+    {
+        "duration": "28.0",
+        "name": "smoothness.key_mobile_sites_smooth/wordpress"
+    },
+    {
+        "duration": "46.0",
+        "name": "smoothness.key_mobile_sites_smooth/worldjournal"
+    },
+    {
+        "duration": "42.0",
+        "name": "smoothness.key_mobile_sites_smooth/wowwiki"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.key_mobile_sites_smooth/wsj"
+    },
+    {
+        "duration": "25.0",
+        "name": "smoothness.key_mobile_sites_smooth/yahoo_answers"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.key_mobile_sites_smooth/yahoo_news"
+    },
+    {
+        "duration": "19.0",
+        "name": "smoothness.key_mobile_sites_smooth/youtube"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.key_silk_cases/font_wipe.html"
+    },
+    {
+        "duration": "42.0",
+        "name": "smoothness.key_silk_cases/http://groupcloned.com/test/plain/list-recycle-transform.html"
+    },
+    {
+        "duration": "20.0",
+        "name": "smoothness.key_silk_cases/http://groupcloned.com/test/plain/sticky-using-webkit-backface-visibility.html"
+    },
+    {
+        "duration": "19.0",
+        "name": "smoothness.key_silk_cases/http://jsbin.com/UVIgUTa/38/quiet"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.key_silk_cases/http://jsfiddle.net/3yDKh/15/show/"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.key_silk_cases/http://jsfiddle.net/3yDKh/16/show/"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.key_silk_cases/http://jsfiddle.net/R8DX9/4/show/"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.key_silk_cases/http://jsfiddle.net/TLXLu/3/show/"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.key_silk_cases/http://jsfiddle.net/bNp2h/3/show/"
+    },
+    {
+        "duration": "24.0",
+        "name": "smoothness.key_silk_cases/http://jsfiddle.net/cKB9D/7/show/"
+    },
+    {
+        "duration": "24.0",
+        "name": "smoothness.key_silk_cases/http://jsfiddle.net/jx5De/14/show/"
+    },
+    {
+        "duration": "24.0",
+        "name": "smoothness.key_silk_cases/http://jsfiddle.net/rF9Gh/7/show/"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.key_silk_cases/http://jsfiddle.net/ugkd4/10/show/"
+    },
+    {
+        "duration": "24.0",
+        "name": "smoothness.key_silk_cases/http://jsfiddle.net/vBQHH/11/show/"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.key_silk_cases/http://jsfiddle.net/xLuvC/1/show/"
+    },
+    {
+        "duration": "24.0",
+        "name": "smoothness.key_silk_cases/http://mobile-news.sandbox.google.com/news/pt0?scroll"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.key_silk_cases/http://mobile-news.sandbox.google.com/news/pt0?swipe"
+    },
+    {
+        "duration": "32.0",
+        "name": "smoothness.key_silk_cases/http://plus.google.com/app/basic/stream"
+    },
+    {
+        "duration": "30.0",
+        "name": "smoothness.key_silk_cases/http://wiltzius.github.io/shape-shifter/"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.key_silk_cases/http://www.google.com/#q=google"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.key_silk_cases/https://www.google.com/search?hl=en&q=define%3Aboogie"
+    },
+    {
+        "duration": "35.0",
+        "name": "smoothness.key_silk_cases/inbox_app.html?stress_hidey_bars"
+    },
+    {
+        "duration": "18.0",
+        "name": "smoothness.key_silk_cases/inbox_app.html?swipe_to_dismiss"
+    },
+    {
+        "duration": "26.0",
+        "name": "smoothness.key_silk_cases/inbox_app.html?toggle_drawer"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.key_silk_cases/infinite_scrolling.html"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.key_silk_cases/list_animation_simple.html"
+    },
+    {
+        "duration": "31.0",
+        "name": "smoothness.key_silk_cases/masonry.html"
+    },
+    {
+        "duration": "25.0",
+        "name": "smoothness.key_silk_cases/pushState.html"
+    },
+    {
+        "duration": "31.0",
+        "name": "smoothness.key_silk_cases/silk_finance.html"
+    },
+    {
+        "duration": "25.0",
+        "name": "smoothness.maps/maps_perf_test"
+    },
+    {
+        "duration": "58.0",
+        "name": "smoothness.pathological_mobile_sites/http://edition.cnn.com"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.pathological_mobile_sites/http://m.espn.go.com/nhl/rankings"
+    },
+    {
+        "duration": "34.0",
+        "name": "smoothness.pathological_mobile_sites/http://recode.net"
+    },
+    {
+        "duration": "32.0",
+        "name": "smoothness.pathological_mobile_sites/http://sports.yahoo.com/"
+    },
+    {
+        "duration": "30.0",
+        "name": "smoothness.pathological_mobile_sites/http://www.latimes.com"
+    },
+    {
+        "duration": "32.0",
+        "name": "smoothness.pathological_mobile_sites/http://www.pbs.org/newshour/bb/much-really-cost-live-city-like-seattle/#the-rundown"
+    },
+    {
+        "duration": "24.0",
+        "name": "smoothness.pathological_mobile_sites/http://www.theguardian.com/politics/2015/mar/09/ed-balls-tory-spending-plans-nhs-charging"
+    },
+    {
+        "duration": "35.0",
+        "name": "smoothness.pathological_mobile_sites/http://www.wowwiki.com/World_of_Warcraft:_Mists_of_Pandaria"
+    },
+    {
+        "duration": "28.0",
+        "name": "smoothness.pathological_mobile_sites/http://www.zdnet.com"
+    },
+    {
+        "duration": "28.0",
+        "name": "smoothness.pathological_mobile_sites/https://www.linkedin.com/in/linustorvalds"
+    },
+    {
+        "duration": "31.0",
+        "name": "smoothness.simple_mobile_sites/http://m.nytimes.com/"
+    },
+    {
+        "duration": "52.0",
+        "name": "smoothness.simple_mobile_sites/http://www.ebay.co.uk/"
+    },
+    {
+        "duration": "33.0",
+        "name": "smoothness.simple_mobile_sites/http://www.nyc.gov"
+    },
+    {
+        "duration": "34.0",
+        "name": "smoothness.simple_mobile_sites/https://www.flickr.com/"
+    },
+    {
+        "duration": "7.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/amazon"
+    },
+    {
+        "duration": "26.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/androidpolice"
+    },
+    {
+        "duration": "19.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/baidu"
+    },
+    {
+        "duration": "17.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/bing"
+    },
+    {
+        "duration": "19.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/blogspot"
+    },
+    {
+        "duration": "35.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/boingboing"
+    },
+    {
+        "duration": "25.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/booking.com"
+    },
+    {
+        "duration": "42.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/capitolvolkswagen"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/cnn"
+    },
+    {
+        "duration": "37.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/cnn_article"
+    },
+    {
+        "duration": "34.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/cuteoverload"
+    },
+    {
+        "duration": "28.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/deviantart"
+    },
+    {
+        "duration": "0.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/digg"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/ebay"
+    },
+    {
+        "duration": "32.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/espn"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/facebook"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/forecast.io"
+    },
+    {
+        "duration": "26.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/google_news"
+    },
+    {
+        "duration": "24.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/google_plus"
+    },
+    {
+        "duration": "19.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/google_web_search"
+    },
+    {
+        "duration": "20.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/gsp.ro"
+    },
+    {
+        "duration": "25.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/linkedin"
+    },
+    {
+        "duration": "18.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/mlb"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/nytimes"
+    },
+    {
+        "duration": "28.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/pinterest"
+    },
+    {
+        "duration": "28.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/reddit"
+    },
+    {
+        "duration": "24.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/sfgate"
+    },
+    {
+        "duration": "29.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/slashdot"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/techcrunch"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/theverge"
+    },
+    {
+        "duration": "37.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/theverge_article"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/twitter"
+    },
+    {
+        "duration": "35.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/usatoday"
+    },
+    {
+        "duration": "26.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/wikipedia"
+    },
+    {
+        "duration": "26.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/wikipedia_delayed_scroll_start"
+    },
+    {
+        "duration": "28.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/wordpress"
+    },
+    {
+        "duration": "45.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/worldjournal"
+    },
+    {
+        "duration": "41.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/wowwiki"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/wsj"
+    },
+    {
+        "duration": "25.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/yahoo_answers"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/yahoo_news"
+    },
+    {
+        "duration": "19.0",
+        "name": "smoothness.sync_scroll.key_mobile_sites_smooth/youtube"
+    },
+    {
+        "duration": "0.0",
+        "name": "smoothness.top_25_smooth/amazon"
+    },
+    {
+        "duration": "32.0",
+        "name": "smoothness.top_25_smooth/blogspot"
+    },
+    {
+        "duration": "25.0",
+        "name": "smoothness.top_25_smooth/booking.com"
+    },
+    {
+        "duration": "0.0",
+        "name": "smoothness.top_25_smooth/cnn"
+    },
+    {
+        "duration": "18.0",
+        "name": "smoothness.top_25_smooth/ebay"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.top_25_smooth/espn"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.top_25_smooth/facebook"
+    },
+    {
+        "duration": "93.0",
+        "name": "smoothness.top_25_smooth/gmail"
+    },
+    {
+        "duration": "33.0",
+        "name": "smoothness.top_25_smooth/google_calendar"
+    },
+    {
+        "duration": "50.0",
+        "name": "smoothness.top_25_smooth/google_docs"
+    },
+    {
+        "duration": "38.0",
+        "name": "smoothness.top_25_smooth/google_image_search"
+    },
+    {
+        "duration": "45.0",
+        "name": "smoothness.top_25_smooth/google_plus"
+    },
+    {
+        "duration": "20.0",
+        "name": "smoothness.top_25_smooth/google_web_search"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.top_25_smooth/linkedin"
+    },
+    {
+        "duration": "26.0",
+        "name": "smoothness.top_25_smooth/pinterest"
+    },
+    {
+        "duration": "32.0",
+        "name": "smoothness.top_25_smooth/techcrunch"
+    },
+    {
+        "duration": "25.0",
+        "name": "smoothness.top_25_smooth/twitter"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.top_25_smooth/weather.com"
+    },
+    {
+        "duration": "36.0",
+        "name": "smoothness.top_25_smooth/wikipedia"
+    },
+    {
+        "duration": "29.0",
+        "name": "smoothness.top_25_smooth/wordpress"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.top_25_smooth/yahoo_answers"
+    },
+    {
+        "duration": "38.0",
+        "name": "smoothness.top_25_smooth/yahoo_games"
+    },
+    {
+        "duration": "28.0",
+        "name": "smoothness.top_25_smooth/yahoo_news"
+    },
+    {
+        "duration": "25.0",
+        "name": "smoothness.top_25_smooth/yahoo_sports"
+    },
+    {
+        "duration": "36.0",
+        "name": "smoothness.top_25_smooth/youtube"
+    },
+    {
+        "duration": "42.0",
+        "name": "smoothness.tough_ad_cases/http://localhost:8000/CICAgICQ15a9NxDIARjIASgBMghBC1XuTk8ezw.swiffy72.html"
+    },
+    {
+        "duration": "26.0",
+        "name": "smoothness.tough_ad_cases/http://localhost:8000/CICAgIDQ2Pb-MxCsAhj6ASgBMgi5DLoSO0gPbQ.swiffy72.html"
+    },
+    {
+        "duration": "26.0",
+        "name": "smoothness.tough_ad_cases/http://localhost:8000/CICAgKCN39CopQEQoAEY2AQoATIID59gK5hjjIg.swiffy72.html"
+    },
+    {
+        "duration": "26.0",
+        "name": "smoothness.tough_ad_cases/http://localhost:8000/CICAgKCNj4HgyAEQeBjYBCgBMgjQpPkOjyWNdw.1.swiffy72.html"
+    },
+    {
+        "duration": "26.0",
+        "name": "smoothness.tough_ad_cases/http://localhost:8000/CICAgMDOrcnRGRB4GNgEKAEyCP_ZBSfwUFsj.swiffy72.html"
+    },
+    {
+        "duration": "26.0",
+        "name": "smoothness.tough_ad_cases/http://localhost:8000/CNP2xe_LmqPEKBCsAhj6ASgBMggnyMqth81h8Q.swiffy72.html"
+    },
+    {
+        "duration": "26.0",
+        "name": "smoothness.tough_ad_cases/http://localhost:8000/clip-paths-CICAgMDO7Ye9-gEQ2AUYWigBMgjZxDii6aoK9w.swiffy72.html"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.tough_ad_cases/http://localhost:8000/clip-paths-CILZhLqO_-27bxB4GNgEKAEyCC46kMLBXnMT.swiffy72.html"
+    },
+    {
+        "duration": "26.0",
+        "name": "smoothness.tough_ad_cases/http://localhost:8000/filters-CNLa0t2T47qJ_wEQoAEY2AQoATIIFaIdc7VMBr4.swiffy72.html"
+    },
+    {
+        "duration": "26.0",
+        "name": "smoothness.tough_ad_cases/http://localhost:8000/shapes-CICAgMDO7cfIzwEQ1AMYPCgBMghqY8tqyRCArQ.swiffy72.html"
+    },
+    {
+        "duration": "26.0",
+        "name": "smoothness.tough_ad_cases/http://localhost:8000/shapes-CK7ptO3F8bi2KxDQAhiYAigBMgij6QBQtD2gyA.swiffy72.html"
+    },
+    {
+        "duration": "32.0",
+        "name": "smoothness.tough_animation_cases/balls_css_keyframe_animations.html"
+    },
+    {
+        "duration": "0.0",
+        "name": "smoothness.tough_animation_cases/balls_css_keyframe_animations_composited_transform.html"
+    },
+    {
+        "duration": "28.0",
+        "name": "smoothness.tough_animation_cases/balls_css_transition_2_properties.html"
+    },
+    {
+        "duration": "29.0",
+        "name": "smoothness.tough_animation_cases/balls_css_transition_40_properties.html"
+    },
+    {
+        "duration": "28.0",
+        "name": "smoothness.tough_animation_cases/balls_css_transition_all_properties.html"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.tough_animation_cases/balls_javascript_canvas.html"
+    },
+    {
+        "duration": "28.0",
+        "name": "smoothness.tough_animation_cases/balls_javascript_css.html"
+    },
+    {
+        "duration": "50.0",
+        "name": "smoothness.tough_animation_cases/balls_svg_animations.html"
+    },
+    {
+        "duration": "26.0",
+        "name": "smoothness.tough_animation_cases/compositor_heavy_animation.html?N=0200"
+    },
+    {
+        "duration": "136.0",
+        "name": "smoothness.tough_animation_cases/css_animations_many_keyframes.html?N=0316"
+    },
+    {
+        "duration": "31.0",
+        "name": "smoothness.tough_animation_cases/css_animations_simultaneous_by_inserting_new_element.html?N=0316"
+    },
+    {
+        "duration": "29.0",
+        "name": "smoothness.tough_animation_cases/css_animations_simultaneous_by_inserting_style_element.html?N=0316"
+    },
+    {
+        "duration": "29.0",
+        "name": "smoothness.tough_animation_cases/css_animations_simultaneous_by_updating_class.html?N=0316"
+    },
+    {
+        "duration": "29.0",
+        "name": "smoothness.tough_animation_cases/css_animations_simultaneous_by_updating_inline_style.html?N=0316"
+    },
+    {
+        "duration": "33.0",
+        "name": "smoothness.tough_animation_cases/css_animations_staggered_chaining_by_inserting_new_element.html?N=0316"
+    },
+    {
+        "duration": "35.0",
+        "name": "smoothness.tough_animation_cases/css_animations_staggered_chaining_by_inserting_style_element.html?N=0316"
+    },
+    {
+        "duration": "31.0",
+        "name": "smoothness.tough_animation_cases/css_animations_staggered_chaining_by_updating_class.html?N=0316"
+    },
+    {
+        "duration": "31.0",
+        "name": "smoothness.tough_animation_cases/css_animations_staggered_chaining_by_updating_inline_style.html?N=0316"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.tough_animation_cases/css_animations_staggered_infinite_iterations.html?N=0316"
+    },
+    {
+        "duration": "34.0",
+        "name": "smoothness.tough_animation_cases/css_animations_staggered_triggering_by_inserting_new_element.html?N=0316"
+    },
+    {
+        "duration": "31.0",
+        "name": "smoothness.tough_animation_cases/css_animations_staggered_triggering_by_inserting_style_element.html?N=0316"
+    },
+    {
+        "duration": "31.0",
+        "name": "smoothness.tough_animation_cases/css_animations_staggered_triggering_by_updating_class.html?N=0316"
+    },
+    {
+        "duration": "31.0",
+        "name": "smoothness.tough_animation_cases/css_animations_staggered_triggering_by_updating_inline_style.html?N=0316"
+    },
+    {
+        "duration": "30.0",
+        "name": "smoothness.tough_animation_cases/css_transitions_simultaneous_by_inserting_new_element.html?N=0316"
+    },
+    {
+        "duration": "30.0",
+        "name": "smoothness.tough_animation_cases/css_transitions_simultaneous_by_inserting_style_element.html?N=0316"
+    },
+    {
+        "duration": "30.0",
+        "name": "smoothness.tough_animation_cases/css_transitions_simultaneous_by_updating_class.html?N=0316"
+    },
+    {
+        "duration": "30.0",
+        "name": "smoothness.tough_animation_cases/css_transitions_simultaneous_by_updating_inline_style.html?N=0316"
+    },
+    {
+        "duration": "30.0",
+        "name": "smoothness.tough_animation_cases/css_transitions_staggered_chaining_by_inserting_new_element.html?N=0316"
+    },
+    {
+        "duration": "30.0",
+        "name": "smoothness.tough_animation_cases/css_transitions_staggered_chaining_by_inserting_style_element.html?N=0316"
+    },
+    {
+        "duration": "30.0",
+        "name": "smoothness.tough_animation_cases/css_transitions_staggered_chaining_by_updating_class.html?N=0316"
+    },
+    {
+        "duration": "30.0",
+        "name": "smoothness.tough_animation_cases/css_transitions_staggered_chaining_by_updating_inline_style.html?N=0316"
+    },
+    {
+        "duration": "31.0",
+        "name": "smoothness.tough_animation_cases/css_transitions_staggered_triggering_by_inserting_new_element.html?N=0316"
+    },
+    {
+        "duration": "30.0",
+        "name": "smoothness.tough_animation_cases/css_transitions_staggered_triggering_by_inserting_style_element.html?N=0316"
+    },
+    {
+        "duration": "31.0",
+        "name": "smoothness.tough_animation_cases/css_transitions_staggered_triggering_by_updating_class.html?N=0316"
+    },
+    {
+        "duration": "31.0",
+        "name": "smoothness.tough_animation_cases/css_transitions_staggered_triggering_by_updating_inline_style.html?N=0316"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.tough_animation_cases/css_value_type_color.html?api=css_animations&N=0316"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.tough_animation_cases/css_value_type_color.html?api=web_animations&N=0316"
+    },
+    {
+        "duration": "29.0",
+        "name": "smoothness.tough_animation_cases/css_value_type_filter.html?api=css_animations&N=0316"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.tough_animation_cases/css_value_type_length_3d.html?api=css_animations&N=0316"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.tough_animation_cases/css_value_type_length_3d.html?api=web_animations&N=0316"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.tough_animation_cases/css_value_type_length_complex.html?api=css_animations&N=0316"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.tough_animation_cases/css_value_type_length_complex.html?api=web_animations&N=0316"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.tough_animation_cases/css_value_type_length_simple.html?api=css_animations&N=0316"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.tough_animation_cases/css_value_type_length_simple.html?api=web_animations&N=0316"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.tough_animation_cases/css_value_type_path.html?api=css_animations&N=0316"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.tough_animation_cases/css_value_type_path.html?api=web_animations&N=0316"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.tough_animation_cases/css_value_type_shadow.html?api=css_animations&N=0316"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.tough_animation_cases/css_value_type_shadow.html?api=web_animations&N=0316"
+    },
+    {
+        "duration": "26.0",
+        "name": "smoothness.tough_animation_cases/css_value_type_transform_complex.html?api=css_animations&N=0316"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.tough_animation_cases/css_value_type_transform_complex.html?api=web_animations&N=0316"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.tough_animation_cases/css_value_type_transform_simple.html?api=css_animations&N=0316"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.tough_animation_cases/css_value_type_transform_simple.html?api=web_animations&N=0316"
+    },
+    {
+        "duration": "26.0",
+        "name": "smoothness.tough_animation_cases/keyframed_animations.html"
+    },
+    {
+        "duration": "29.0",
+        "name": "smoothness.tough_animation_cases/mix_blend_mode_animation_difference.html"
+    },
+    {
+        "duration": "29.0",
+        "name": "smoothness.tough_animation_cases/mix_blend_mode_animation_hue.html"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.tough_animation_cases/mix_blend_mode_animation_screen.html"
+    },
+    {
+        "duration": "28.0",
+        "name": "smoothness.tough_animation_cases/mix_blend_mode_propagating_isolation.html"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.tough_animation_cases/overlay_background_color_css_transitions.html"
+    },
+    {
+        "duration": "0.0",
+        "name": "smoothness.tough_animation_cases/robohornetpro"
+    },
+    {
+        "duration": "26.0",
+        "name": "smoothness.tough_animation_cases/transform_transition_js_block.html"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.tough_animation_cases/transform_transitions.html"
+    },
+    {
+        "duration": "68.0",
+        "name": "smoothness.tough_animation_cases/web_animations_many_keyframes.html?N=0316"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.tough_animation_cases/web_animations_set_current_time_in_raf.html?N=0316"
+    },
+    {
+        "duration": "29.0",
+        "name": "smoothness.tough_animation_cases/web_animations_simultaneous.html?N=0316"
+    },
+    {
+        "duration": "31.0",
+        "name": "smoothness.tough_animation_cases/web_animations_staggered_chaining.html?N=0316"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.tough_animation_cases/web_animations_staggered_infinite_iterations.html?N=0316"
+    },
+    {
+        "duration": "31.0",
+        "name": "smoothness.tough_animation_cases/web_animations_staggered_triggering.html?N=0316"
+    },
+    {
+        "duration": "28.0",
+        "name": "smoothness.tough_canvas_cases/../../../chrome/test/data/perf/canvas_bench/many_images.html"
+    },
+    {
+        "duration": "37.0",
+        "name": "smoothness.tough_canvas_cases/http://geoapis.appspot.com/agdnZW9hcGlzchMLEgtFeGFtcGxlQ29kZRjh1wIM"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.tough_canvas_cases/http://hakim.se/experiments/html5/magnetic/02/"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.tough_canvas_cases/http://ie.microsoft.com/testdrive/Graphics/TweetMap/Default.html"
+    },
+    {
+        "duration": "25.0",
+        "name": "smoothness.tough_canvas_cases/http://ie.microsoft.com/testdrive/Graphics/VideoCity/Default.html"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.tough_canvas_cases/http://ie.microsoft.com/testdrive/Graphics/WorkerFountains/Default.html"
+    },
+    {
+        "duration": "24.0",
+        "name": "smoothness.tough_canvas_cases/http://ie.microsoft.com/testdrive/Performance/AsteroidBelt/Default.html"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.tough_canvas_cases/http://ie.microsoft.com/testdrive/Performance/FishIETank/Default.html"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.tough_canvas_cases/http://ie.microsoft.com/testdrive/Performance/LetItSnow/"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.tough_canvas_cases/http://ie.microsoft.com/testdrive/Performance/SpeedReading/Default.html"
+    },
+    {
+        "duration": "24.0",
+        "name": "smoothness.tough_canvas_cases/http://jarrodoverson.com/static/demos/particleSystem/"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.tough_canvas_cases/http://mix10k.visitmix.com/Entry/Details/169"
+    },
+    {
+        "duration": "20.0",
+        "name": "smoothness.tough_canvas_cases/http://runway.countlessprojects.com/prototype/performance_test.html"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.tough_canvas_cases/http://spielzeugz.de/html5/liquid-particles.html"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.tough_canvas_cases/http://themaninblue.com/experiment/AnimationBenchmark/canvas/"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.tough_canvas_cases/http://www.chiptune.com/starfield/starfield.html"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.tough_canvas_cases/http://www.craftymind.com/factory/guimark2/HTML5ChartingTest.html"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.tough_canvas_cases/http://www.effectgames.com/demos/canvascycle/"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.tough_canvas_cases/http://www.kevs3d.co.uk/dev/canvask3d/k3d_test.html"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.tough_canvas_cases/http://www.megidish.net/awjs/"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.tough_canvas_cases/http://www.smashcat.org/av/canvas_test/"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.tough_canvas_cases/tough_canvas_cases/canvas-animation-no-clear.html"
+    },
+    {
+        "duration": "24.0",
+        "name": "smoothness.tough_canvas_cases/tough_canvas_cases/canvas-font-cycler.html"
+    },
+    {
+        "duration": "43.0",
+        "name": "smoothness.tough_canvas_cases/tough_canvas_cases/canvas2d_balls_common/bouncing_balls.html?ball=image_with_shadow&back=image"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.tough_canvas_cases/tough_canvas_cases/canvas2d_balls_common/bouncing_balls.html?ball=text&back=white&ball_count=15"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.tough_canvas_cases/tough_canvas_cases/canvas_toBlob.html"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.tough_canvas_cases/tough_canvas_cases/rendering_throughput/bouncing_clipped_rectangles.html"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.tough_canvas_cases/tough_canvas_cases/rendering_throughput/bouncing_gradient_circles.html"
+    },
+    {
+        "duration": "19.0",
+        "name": "smoothness.tough_canvas_cases/tough_canvas_cases/rendering_throughput/bouncing_png_images.html"
+    },
+    {
+        "duration": "35.0",
+        "name": "smoothness.tough_canvas_cases/tough_canvas_cases/rendering_throughput/bouncing_svg_images.html"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.tough_canvas_cases/tough_canvas_cases/rendering_throughput/canvas_arcs.html"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.tough_canvas_cases/tough_canvas_cases/rendering_throughput/canvas_lines.html"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.tough_canvas_cases/tough_canvas_cases/rendering_throughput/fill_shapes.html"
+    },
+    {
+        "duration": "68.0",
+        "name": "smoothness.tough_canvas_cases/tough_canvas_cases/rendering_throughput/put_get_image_data.html"
+    },
+    {
+        "duration": "25.0",
+        "name": "smoothness.tough_canvas_cases/tough_canvas_cases/rendering_throughput/stroke_shapes.html"
+    },
+    {
+        "duration": "26.0",
+        "name": "smoothness.tough_filters_cases/Analog_Clock_SVG"
+    },
+    {
+        "duration": "26.0",
+        "name": "smoothness.tough_filters_cases/Filter_Terrain_SVG"
+    },
+    {
+        "duration": "31.0",
+        "name": "smoothness.tough_filters_cases/IE_PirateMark"
+    },
+    {
+        "duration": "42.0",
+        "name": "smoothness.tough_filters_cases/MotionMark_Focus"
+    },
+    {
+        "duration": "32.0",
+        "name": "smoothness.tough_image_decode_cases/http://localhost:9000/cats-unscaled.html"
+    },
+    {
+        "duration": "15.0",
+        "name": "smoothness.tough_image_decode_cases/http://localhost:9000/cats-viewport-width.html"
+    },
+    {
+        "duration": "44.0",
+        "name": "smoothness.tough_path_rendering_cases/GUIMark_Vector_Chart_Test"
+    },
+    {
+        "duration": "38.0",
+        "name": "smoothness.tough_path_rendering_cases/IE_Chalkboard"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.tough_path_rendering_cases/MotionMark_Canvas_Fill_Shapes"
+    },
+    {
+        "duration": "28.0",
+        "name": "smoothness.tough_path_rendering_cases/MotionMark_Canvas_Stroke_Shapes"
+    },
+    {
+        "duration": "30.0",
+        "name": "smoothness.tough_pinch_zoom_cases/Blogger"
+    },
+    {
+        "duration": "37.0",
+        "name": "smoothness.tough_pinch_zoom_cases/ESPN"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.tough_pinch_zoom_cases/Facebook"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.tough_pinch_zoom_cases/LinkedIn"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.tough_pinch_zoom_cases/Twitter"
+    },
+    {
+        "duration": "33.0",
+        "name": "smoothness.tough_pinch_zoom_cases/Weather.com"
+    },
+    {
+        "duration": "26.0",
+        "name": "smoothness.tough_pinch_zoom_cases/http://booking.com"
+    },
+    {
+        "duration": "33.0",
+        "name": "smoothness.tough_pinch_zoom_cases/http://games.yahoo.com"
+    },
+    {
+        "duration": "32.0",
+        "name": "smoothness.tough_pinch_zoom_cases/http://news.yahoo.com"
+    },
+    {
+        "duration": "37.0",
+        "name": "smoothness.tough_pinch_zoom_cases/http://sports.yahoo.com/"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.tough_pinch_zoom_cases/http://www.amazon.com"
+    },
+    {
+        "duration": "33.0",
+        "name": "smoothness.tough_pinch_zoom_cases/http://www.cnn.com"
+    },
+    {
+        "duration": "32.0",
+        "name": "smoothness.tough_pinch_zoom_cases/http://www.ebay.com"
+    },
+    {
+        "duration": "30.0",
+        "name": "smoothness.tough_pinch_zoom_cases/http://www.youtube.com"
+    },
+    {
+        "duration": "45.0",
+        "name": "smoothness.tough_pinch_zoom_cases/https://mail.google.com/mail/"
+    },
+    {
+        "duration": "41.0",
+        "name": "smoothness.tough_pinch_zoom_cases/https://www.google.com/#hl=en&q=barack+obama"
+    },
+    {
+        "duration": "26.0",
+        "name": "smoothness.tough_pinch_zoom_cases/https://www.google.com/calendar/"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.tough_pinch_zoom_cases/https://www.google.com/search?q=cats&tbm=isch"
+    },
+    {
+        "duration": "26.0",
+        "name": "smoothness.tough_scrolling_cases/canvas_05000_pixels_per_second"
+    },
+    {
+        "duration": "26.0",
+        "name": "smoothness.tough_scrolling_cases/canvas_10000_pixels_per_second"
+    },
+    {
+        "duration": "26.0",
+        "name": "smoothness.tough_scrolling_cases/canvas_15000_pixels_per_second"
+    },
+    {
+        "duration": "26.0",
+        "name": "smoothness.tough_scrolling_cases/canvas_20000_pixels_per_second"
+    },
+    {
+        "duration": "26.0",
+        "name": "smoothness.tough_scrolling_cases/canvas_30000_pixels_per_second"
+    },
+    {
+        "duration": "26.0",
+        "name": "smoothness.tough_scrolling_cases/canvas_40000_pixels_per_second"
+    },
+    {
+        "duration": "25.0",
+        "name": "smoothness.tough_scrolling_cases/canvas_50000_pixels_per_second"
+    },
+    {
+        "duration": "24.0",
+        "name": "smoothness.tough_scrolling_cases/canvas_60000_pixels_per_second"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.tough_scrolling_cases/canvas_75000_pixels_per_second"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.tough_scrolling_cases/canvas_90000_pixels_per_second"
+    },
+    {
+        "duration": "40.0",
+        "name": "smoothness.tough_scrolling_cases/text_05000_pixels_per_second"
+    },
+    {
+        "duration": "24.0",
+        "name": "smoothness.tough_scrolling_cases/text_10000_pixels_per_second"
+    },
+    {
+        "duration": "24.0",
+        "name": "smoothness.tough_scrolling_cases/text_15000_pixels_per_second"
+    },
+    {
+        "duration": "24.0",
+        "name": "smoothness.tough_scrolling_cases/text_20000_pixels_per_second"
+    },
+    {
+        "duration": "24.0",
+        "name": "smoothness.tough_scrolling_cases/text_30000_pixels_per_second"
+    },
+    {
+        "duration": "24.0",
+        "name": "smoothness.tough_scrolling_cases/text_40000_pixels_per_second"
+    },
+    {
+        "duration": "24.0",
+        "name": "smoothness.tough_scrolling_cases/text_50000_pixels_per_second"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.tough_scrolling_cases/text_60000_pixels_per_second"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.tough_scrolling_cases/text_75000_pixels_per_second"
+    },
+    {
+        "duration": "20.0",
+        "name": "smoothness.tough_scrolling_cases/text_90000_pixels_per_second"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.tough_scrolling_cases/text_constant_full_page_raster_05000_pixels_per_second"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.tough_scrolling_cases/text_constant_full_page_raster_10000_pixels_per_second"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.tough_scrolling_cases/text_constant_full_page_raster_15000_pixels_per_second"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.tough_scrolling_cases/text_constant_full_page_raster_20000_pixels_per_second"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.tough_scrolling_cases/text_constant_full_page_raster_30000_pixels_per_second"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.tough_scrolling_cases/text_constant_full_page_raster_40000_pixels_per_second"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.tough_scrolling_cases/text_constant_full_page_raster_50000_pixels_per_second"
+    },
+    {
+        "duration": "26.0",
+        "name": "smoothness.tough_scrolling_cases/text_constant_full_page_raster_60000_pixels_per_second"
+    },
+    {
+        "duration": "24.0",
+        "name": "smoothness.tough_scrolling_cases/text_constant_full_page_raster_75000_pixels_per_second"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.tough_scrolling_cases/text_constant_full_page_raster_90000_pixels_per_second"
+    },
+    {
+        "duration": "23.0",
+        "name": "smoothness.tough_scrolling_cases/text_hover_05000_pixels_per_second"
+    },
+    {
+        "duration": "24.0",
+        "name": "smoothness.tough_scrolling_cases/text_hover_10000_pixels_per_second"
+    },
+    {
+        "duration": "24.0",
+        "name": "smoothness.tough_scrolling_cases/text_hover_15000_pixels_per_second"
+    },
+    {
+        "duration": "24.0",
+        "name": "smoothness.tough_scrolling_cases/text_hover_20000_pixels_per_second"
+    },
+    {
+        "duration": "24.0",
+        "name": "smoothness.tough_scrolling_cases/text_hover_30000_pixels_per_second"
+    },
+    {
+        "duration": "24.0",
+        "name": "smoothness.tough_scrolling_cases/text_hover_40000_pixels_per_second"
+    },
+    {
+        "duration": "24.0",
+        "name": "smoothness.tough_scrolling_cases/text_hover_50000_pixels_per_second"
+    },
+    {
+        "duration": "22.0",
+        "name": "smoothness.tough_scrolling_cases/text_hover_60000_pixels_per_second"
+    },
+    {
+        "duration": "21.0",
+        "name": "smoothness.tough_scrolling_cases/text_hover_75000_pixels_per_second"
+    },
+    {
+        "duration": "20.0",
+        "name": "smoothness.tough_scrolling_cases/text_hover_90000_pixels_per_second"
+    },
+    {
+        "duration": "45.0",
+        "name": "smoothness.tough_texture_upload_cases/background_color_animation.html"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.tough_texture_upload_cases/background_color_animation_with_gradient.html"
+    },
+    {
+        "duration": "32.0",
+        "name": "smoothness.tough_texture_upload_cases/extra_large_texture_uploads.html"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.tough_texture_upload_cases/large_texture_uploads.html"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.tough_texture_upload_cases/medium_texture_uploads.html"
+    },
+    {
+        "duration": "28.0",
+        "name": "smoothness.tough_texture_upload_cases/small_texture_uploads.html"
+    },
+    {
+        "duration": "43.0",
+        "name": "smoothness.tough_webgl_ad_cases/http://localhost:8000/CICAgICQ15a9NxDIARjIASgBMghBC1XuTk8ezw.swf.webglbeta.html"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.tough_webgl_ad_cases/http://localhost:8000/CICAgIDQ2Pb-MxCsAhj6ASgBMgi5DLoSO0gPbQ.swf.webglbeta.html"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.tough_webgl_ad_cases/http://localhost:8000/CICAgKCN39CopQEQoAEY2AQoATIID59gK5hjjIg.swf.webglbeta.html"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.tough_webgl_ad_cases/http://localhost:8000/CICAgKCNj4HgyAEQeBjYBCgBMgjQpPkOjyWNdw.1.swf.webglbeta.html"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.tough_webgl_ad_cases/http://localhost:8000/CICAgMDOrcnRGRB4GNgEKAEyCP_ZBSfwUFsj.swf.webglbeta.html"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.tough_webgl_ad_cases/http://localhost:8000/CNP2xe_LmqPEKBCsAhj6ASgBMggnyMqth81h8Q.swf.webglbeta.html"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.tough_webgl_ad_cases/http://localhost:8000/clip-paths-CICAgMDO7Ye9-gEQ2AUYWigBMgjZxDii6aoK9w.swf.webglbeta.html"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.tough_webgl_ad_cases/http://localhost:8000/clip-paths-CILZhLqO_-27bxB4GNgEKAEyCC46kMLBXnMT.swf.webglbeta.html"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.tough_webgl_ad_cases/http://localhost:8000/filters-CNLa0t2T47qJ_wEQoAEY2AQoATIIFaIdc7VMBr4.swf.webglbeta.html"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.tough_webgl_ad_cases/http://localhost:8000/shapes-CICAgMDO7cfIzwEQ1AMYPCgBMghqY8tqyRCArQ.swf.webglbeta.html"
+    },
+    {
+        "duration": "27.0",
+        "name": "smoothness.tough_webgl_ad_cases/http://localhost:8000/shapes-CK7ptO3F8bi2KxDQAhiYAigBMgij6QBQtD2gyA.swf.webglbeta.html"
+    },
+    {
+        "duration": "38.0",
+        "name": "start_with_url.cold.startup_pages/about:blank"
+    },
+    {
+        "duration": "37.0",
+        "name": "start_with_url.cold.startup_pages/http://bbc.co.uk"
+    },
+    {
+        "duration": "35.0",
+        "name": "start_with_url.warm.startup_pages/about:blank"
+    },
+    {
+        "duration": "37.0",
+        "name": "start_with_url.warm.startup_pages/http://bbc.co.uk"
+    },
+    {
+        "duration": "31.0",
+        "name": "system_health.common_mobile/background:media:imgur"
+    },
+    {
+        "duration": "33.0",
+        "name": "system_health.common_mobile/background:search:google"
+    },
+    {
+        "duration": "54.0",
+        "name": "system_health.common_mobile/background:social:facebook"
+    },
+    {
+        "duration": "50.0",
+        "name": "system_health.common_mobile/background:tools:gmail"
+    },
+    {
+        "duration": "186.0",
+        "name": "system_health.common_mobile/browse:chrome:newtab"
+    },
+    {
+        "duration": "54.0",
+        "name": "system_health.common_mobile/browse:chrome:omnibox"
+    },
+    {
+        "duration": "131.0",
+        "name": "system_health.common_mobile/browse:media:facebook_photos"
+    },
+    {
+        "duration": "72.0",
+        "name": "system_health.common_mobile/browse:media:flickr_infinite_scroll"
+    },
+    {
+        "duration": "110.0",
+        "name": "system_health.common_mobile/browse:media:imgur"
+    },
+    {
+        "duration": "163.0",
+        "name": "system_health.common_mobile/browse:media:youtube"
+    },
+    {
+        "duration": "268.0",
+        "name": "system_health.common_mobile/browse:news:cnn"
+    },
+    {
+        "duration": "95.0",
+        "name": "system_health.common_mobile/browse:news:cricbuzz"
+    },
+    {
+        "duration": "79.0",
+        "name": "system_health.common_mobile/browse:news:qq"
+    },
+    {
+        "duration": "91.0",
+        "name": "system_health.common_mobile/browse:news:reddit"
+    },
+    {
+        "duration": "80.0",
+        "name": "system_health.common_mobile/browse:news:washingtonpost"
+    },
+    {
+        "duration": "121.0",
+        "name": "system_health.common_mobile/browse:shopping:amazon"
+    },
+    {
+        "duration": "120.0",
+        "name": "system_health.common_mobile/browse:shopping:avito"
+    },
+    {
+        "duration": "59.0",
+        "name": "system_health.common_mobile/browse:shopping:lazada"
+    },
+    {
+        "duration": "103.0",
+        "name": "system_health.common_mobile/browse:social:facebook"
+    },
+    {
+        "duration": "165.0",
+        "name": "system_health.common_mobile/browse:social:facebook_infinite_scroll"
+    },
+    {
+        "duration": "126.0",
+        "name": "system_health.common_mobile/browse:social:instagram"
+    },
+    {
+        "duration": "132.0",
+        "name": "system_health.common_mobile/browse:social:pinterest_infinite_scroll"
+    },
+    {
+        "duration": "165.0",
+        "name": "system_health.common_mobile/browse:social:tumblr_infinite_scroll"
+    },
+    {
+        "duration": "79.0",
+        "name": "system_health.common_mobile/browse:social:twitter"
+    },
+    {
+        "duration": "105.0",
+        "name": "system_health.common_mobile/browse:tech:discourse_infinite_scroll"
+    },
+    {
+        "duration": "71.0",
+        "name": "system_health.common_mobile/browse:tools:maps"
+    },
+    {
+        "duration": "27.0",
+        "name": "system_health.common_mobile/load:chrome:blank"
+    },
+    {
+        "duration": "38.0",
+        "name": "system_health.common_mobile/load:games:bubbles"
+    },
+    {
+        "duration": "28.0",
+        "name": "system_health.common_mobile/load:games:lazors"
+    },
+    {
+        "duration": "38.0",
+        "name": "system_health.common_mobile/load:media:dailymotion"
+    },
+    {
+        "duration": "32.0",
+        "name": "system_health.common_mobile/load:media:facebook_photos"
+    },
+    {
+        "duration": "32.0",
+        "name": "system_health.common_mobile/load:media:google_images"
+    },
+    {
+        "duration": "32.0",
+        "name": "system_health.common_mobile/load:media:imgur"
+    },
+    {
+        "duration": "31.0",
+        "name": "system_health.common_mobile/load:media:soundcloud"
+    },
+    {
+        "duration": "32.0",
+        "name": "system_health.common_mobile/load:media:youtube"
+    },
+    {
+        "duration": "71.0",
+        "name": "system_health.common_mobile/load:news:cnn"
+    },
+    {
+        "duration": "48.0",
+        "name": "system_health.common_mobile/load:news:irctc"
+    },
+    {
+        "duration": "43.0",
+        "name": "system_health.common_mobile/load:news:nytimes"
+    },
+    {
+        "duration": "32.0",
+        "name": "system_health.common_mobile/load:news:qq"
+    },
+    {
+        "duration": "34.0",
+        "name": "system_health.common_mobile/load:news:reddit"
+    },
+    {
+        "duration": "37.0",
+        "name": "system_health.common_mobile/load:news:washingtonpost"
+    },
+    {
+        "duration": "34.0",
+        "name": "system_health.common_mobile/load:news:wikipedia"
+    },
+    {
+        "duration": "32.0",
+        "name": "system_health.common_mobile/load:search:baidu"
+    },
+    {
+        "duration": "33.0",
+        "name": "system_health.common_mobile/load:search:ebay"
+    },
+    {
+        "duration": "29.0",
+        "name": "system_health.common_mobile/load:search:google"
+    },
+    {
+        "duration": "32.0",
+        "name": "system_health.common_mobile/load:search:taobao"
+    },
+    {
+        "duration": "29.0",
+        "name": "system_health.common_mobile/load:search:yahoo"
+    },
+    {
+        "duration": "31.0",
+        "name": "system_health.common_mobile/load:search:yandex"
+    },
+    {
+        "duration": "31.0",
+        "name": "system_health.common_mobile/load:social:twitter"
+    },
+    {
+        "duration": "30.0",
+        "name": "system_health.common_mobile/load:tools:docs"
+    },
+    {
+        "duration": "42.0",
+        "name": "system_health.common_mobile/load:tools:drive"
+    },
+    {
+        "duration": "33.0",
+        "name": "system_health.common_mobile/load:tools:dropbox"
+    },
+    {
+        "duration": "33.0",
+        "name": "system_health.common_mobile/load:tools:stackoverflow"
+    },
+    {
+        "duration": "47.0",
+        "name": "system_health.common_mobile/load:tools:weather"
+    },
+    {
+        "duration": "148.0",
+        "name": "system_health.common_mobile/long_running:tools:gmail-background"
+    },
+    {
+        "duration": "147.0",
+        "name": "system_health.common_mobile/long_running:tools:gmail-foreground"
+    },
+    {
+        "duration": "31.0",
+        "name": "system_health.memory_mobile/background:media:imgur"
+    },
+    {
+        "duration": "32.0",
+        "name": "system_health.memory_mobile/background:search:google"
+    },
+    {
+        "duration": "37.0",
+        "name": "system_health.memory_mobile/background:social:facebook"
+    },
+    {
+        "duration": "43.0",
+        "name": "system_health.memory_mobile/background:tools:gmail"
+    },
+    {
+        "duration": "174.0",
+        "name": "system_health.memory_mobile/browse:chrome:newtab"
+    },
+    {
+        "duration": "52.0",
+        "name": "system_health.memory_mobile/browse:chrome:omnibox"
+    },
+    {
+        "duration": "102.0",
+        "name": "system_health.memory_mobile/browse:media:facebook_photos"
+    },
+    {
+        "duration": "56.0",
+        "name": "system_health.memory_mobile/browse:media:flickr_infinite_scroll"
+    },
+    {
+        "duration": "82.0",
+        "name": "system_health.memory_mobile/browse:media:imgur"
+    },
+    {
+        "duration": "102.0",
+        "name": "system_health.memory_mobile/browse:media:youtube"
+    },
+    {
+        "duration": "190.0",
+        "name": "system_health.memory_mobile/browse:news:cnn"
+    },
+    {
+        "duration": "69.0",
+        "name": "system_health.memory_mobile/browse:news:cricbuzz"
+    },
+    {
+        "duration": "62.0",
+        "name": "system_health.memory_mobile/browse:news:qq"
+    },
+    {
+        "duration": "73.0",
+        "name": "system_health.memory_mobile/browse:news:reddit"
+    },
+    {
+        "duration": "59.0",
+        "name": "system_health.memory_mobile/browse:news:washingtonpost"
+    },
+    {
+        "duration": "80.0",
+        "name": "system_health.memory_mobile/browse:shopping:amazon"
+    },
+    {
+        "duration": "86.0",
+        "name": "system_health.memory_mobile/browse:shopping:avito"
+    },
+    {
+        "duration": "48.0",
+        "name": "system_health.memory_mobile/browse:shopping:lazada"
+    },
+    {
+        "duration": "76.0",
+        "name": "system_health.memory_mobile/browse:social:facebook"
+    },
+    {
+        "duration": "91.0",
+        "name": "system_health.memory_mobile/browse:social:facebook_infinite_scroll"
+    },
+    {
+        "duration": "90.0",
+        "name": "system_health.memory_mobile/browse:social:instagram"
+    },
+    {
+        "duration": "96.0",
+        "name": "system_health.memory_mobile/browse:social:pinterest_infinite_scroll"
+    },
+    {
+        "duration": "106.0",
+        "name": "system_health.memory_mobile/browse:social:tumblr_infinite_scroll"
+    },
+    {
+        "duration": "62.0",
+        "name": "system_health.memory_mobile/browse:social:twitter"
+    },
+    {
+        "duration": "75.0",
+        "name": "system_health.memory_mobile/browse:tech:discourse_infinite_scroll"
+    },
+    {
+        "duration": "60.0",
+        "name": "system_health.memory_mobile/browse:tools:maps"
+    },
+    {
+        "duration": "28.0",
+        "name": "system_health.memory_mobile/load:chrome:blank"
+    },
+    {
+        "duration": "31.0",
+        "name": "system_health.memory_mobile/load:games:bubbles"
+    },
+    {
+        "duration": "29.0",
+        "name": "system_health.memory_mobile/load:games:lazors"
+    },
+    {
+        "duration": "38.0",
+        "name": "system_health.memory_mobile/load:games:spychase"
+    },
+    {
+        "duration": "37.0",
+        "name": "system_health.memory_mobile/load:media:dailymotion"
+    },
+    {
+        "duration": "32.0",
+        "name": "system_health.memory_mobile/load:media:facebook_photos"
+    },
+    {
+        "duration": "32.0",
+        "name": "system_health.memory_mobile/load:media:google_images"
+    },
+    {
+        "duration": "31.0",
+        "name": "system_health.memory_mobile/load:media:imgur"
+    },
+    {
+        "duration": "31.0",
+        "name": "system_health.memory_mobile/load:media:soundcloud"
+    },
+    {
+        "duration": "32.0",
+        "name": "system_health.memory_mobile/load:media:youtube"
+    },
+    {
+        "duration": "61.0",
+        "name": "system_health.memory_mobile/load:news:cnn"
+    },
+    {
+        "duration": "38.0",
+        "name": "system_health.memory_mobile/load:news:irctc"
+    },
+    {
+        "duration": "40.0",
+        "name": "system_health.memory_mobile/load:news:nytimes"
+    },
+    {
+        "duration": "32.0",
+        "name": "system_health.memory_mobile/load:news:qq"
+    },
+    {
+        "duration": "34.0",
+        "name": "system_health.memory_mobile/load:news:reddit"
+    },
+    {
+        "duration": "34.0",
+        "name": "system_health.memory_mobile/load:news:washingtonpost"
+    },
+    {
+        "duration": "34.0",
+        "name": "system_health.memory_mobile/load:news:wikipedia"
+    },
+    {
+        "duration": "32.0",
+        "name": "system_health.memory_mobile/load:search:baidu"
+    },
+    {
+        "duration": "31.0",
+        "name": "system_health.memory_mobile/load:search:ebay"
+    },
+    {
+        "duration": "30.0",
+        "name": "system_health.memory_mobile/load:search:google"
+    },
+    {
+        "duration": "32.0",
+        "name": "system_health.memory_mobile/load:search:taobao"
+    },
+    {
+        "duration": "30.0",
+        "name": "system_health.memory_mobile/load:search:yahoo"
+    },
+    {
+        "duration": "31.0",
+        "name": "system_health.memory_mobile/load:search:yandex"
+    },
+    {
+        "duration": "31.0",
+        "name": "system_health.memory_mobile/load:social:twitter"
+    },
+    {
+        "duration": "31.0",
+        "name": "system_health.memory_mobile/load:tools:docs"
+    },
+    {
+        "duration": "36.0",
+        "name": "system_health.memory_mobile/load:tools:drive"
+    },
+    {
+        "duration": "32.0",
+        "name": "system_health.memory_mobile/load:tools:dropbox"
+    },
+    {
+        "duration": "33.0",
+        "name": "system_health.memory_mobile/load:tools:stackoverflow"
+    },
+    {
+        "duration": "42.0",
+        "name": "system_health.memory_mobile/load:tools:weather"
+    },
+    {
+        "duration": "287.0",
+        "name": "system_health.memory_mobile/long_running:tools:gmail-foreground"
+    },
+    {
+        "duration": "44.0",
+        "name": "thread_times.key_idle_power_cases/animated-gif.html"
+    },
+    {
+        "duration": "52.0",
+        "name": "thread_times.key_idle_power_cases/blank.html"
+    },
+    {
+        "duration": "46.0",
+        "name": "thread_times.key_idle_power_cases/css-animation.html"
+    },
+    {
+        "duration": "47.0",
+        "name": "thread_times.key_idle_power_cases/request-animation-frame.html"
+    },
+    {
+        "duration": "47.0",
+        "name": "thread_times.key_idle_power_cases/set-timeout.html"
+    },
+    {
+        "duration": "117.0",
+        "name": "thread_times.key_idle_power_cases/set-timeout.html (Long Idle)"
+    },
+    {
+        "duration": "48.0",
+        "name": "thread_times.key_mobile_sites_smooth/boingboing"
+    },
+    {
+        "duration": "46.0",
+        "name": "thread_times.key_mobile_sites_smooth/cuteoverload"
+    },
+    {
+        "duration": "45.0",
+        "name": "thread_times.key_mobile_sites_smooth/nytimes"
+    },
+    {
+        "duration": "35.0",
+        "name": "thread_times.key_mobile_sites_smooth/reddit"
+    },
+    {
+        "duration": "36.0",
+        "name": "thread_times.key_mobile_sites_smooth/slashdot"
+    },
+    {
+        "duration": "42.0",
+        "name": "thread_times.key_noop_cases/no_op_raf.html"
+    },
+    {
+        "duration": "22.0",
+        "name": "thread_times.key_noop_cases/no_op_scroll.html"
+    },
+    {
+        "duration": "20.0",
+        "name": "thread_times.key_noop_cases/no_op_settimeout.html"
+    },
+    {
+        "duration": "26.0",
+        "name": "thread_times.key_noop_cases/no_op_touch_handler.html"
+    },
+    {
+        "duration": "22.0",
+        "name": "thread_times.key_silk_cases/font_wipe.html"
+    },
+    {
+        "duration": "48.0",
+        "name": "thread_times.key_silk_cases/http://groupcloned.com/test/plain/list-recycle-transform.html"
+    },
+    {
+        "duration": "21.0",
+        "name": "thread_times.key_silk_cases/http://groupcloned.com/test/plain/sticky-using-webkit-backface-visibility.html"
+    },
+    {
+        "duration": "20.0",
+        "name": "thread_times.key_silk_cases/http://jsbin.com/UVIgUTa/38/quiet"
+    },
+    {
+        "duration": "26.0",
+        "name": "thread_times.key_silk_cases/http://jsfiddle.net/3yDKh/15/show/"
+    },
+    {
+        "duration": "24.0",
+        "name": "thread_times.key_silk_cases/http://jsfiddle.net/3yDKh/16/show/"
+    },
+    {
+        "duration": "26.0",
+        "name": "thread_times.key_silk_cases/http://jsfiddle.net/R8DX9/4/show/"
+    },
+    {
+        "duration": "26.0",
+        "name": "thread_times.key_silk_cases/http://jsfiddle.net/TLXLu/3/show/"
+    },
+    {
+        "duration": "26.0",
+        "name": "thread_times.key_silk_cases/http://jsfiddle.net/bNp2h/3/show/"
+    },
+    {
+        "duration": "29.0",
+        "name": "thread_times.key_silk_cases/http://jsfiddle.net/cKB9D/7/show/"
+    },
+    {
+        "duration": "29.0",
+        "name": "thread_times.key_silk_cases/http://jsfiddle.net/jx5De/14/show/"
+    },
+    {
+        "duration": "28.0",
+        "name": "thread_times.key_silk_cases/http://jsfiddle.net/rF9Gh/7/show/"
+    },
+    {
+        "duration": "26.0",
+        "name": "thread_times.key_silk_cases/http://jsfiddle.net/ugkd4/10/show/"
+    },
+    {
+        "duration": "31.0",
+        "name": "thread_times.key_silk_cases/http://jsfiddle.net/vBQHH/11/show/"
+    },
+    {
+        "duration": "25.0",
+        "name": "thread_times.key_silk_cases/http://jsfiddle.net/xLuvC/1/show/"
+    },
+    {
+        "duration": "26.0",
+        "name": "thread_times.key_silk_cases/http://mobile-news.sandbox.google.com/news/pt0?scroll"
+    },
+    {
+        "duration": "21.0",
+        "name": "thread_times.key_silk_cases/http://mobile-news.sandbox.google.com/news/pt0?swipe"
+    },
+    {
+        "duration": "0.0",
+        "name": "thread_times.key_silk_cases/http://plus.google.com/app/basic/stream"
+    },
+    {
+        "duration": "0.0",
+        "name": "thread_times.key_silk_cases/http://s.codepen.io/befamous/fullpage/pFsqb?scroll"
+    },
+    {
+        "duration": "34.0",
+        "name": "thread_times.key_silk_cases/http://wiltzius.github.io/shape-shifter/"
+    },
+    {
+        "duration": "24.0",
+        "name": "thread_times.key_silk_cases/http://www.google.com/#q=google"
+    },
+    {
+        "duration": "0.0",
+        "name": "thread_times.key_silk_cases/https://polymer-topeka.appspot.com/"
+    },
+    {
+        "duration": "23.0",
+        "name": "thread_times.key_silk_cases/https://www.google.com/search?hl=en&q=define%3Aboogie"
+    },
+    {
+        "duration": "0.0",
+        "name": "thread_times.key_silk_cases/inbox_app.html?slide_drawer"
+    },
+    {
+        "duration": "44.0",
+        "name": "thread_times.key_silk_cases/inbox_app.html?stress_hidey_bars"
+    },
+    {
+        "duration": "0.0",
+        "name": "thread_times.key_silk_cases/inbox_app.html?swipe_to_dismiss"
+    },
+    {
+        "duration": "28.0",
+        "name": "thread_times.key_silk_cases/inbox_app.html?toggle_drawer"
+    },
+    {
+        "duration": "33.0",
+        "name": "thread_times.key_silk_cases/infinite_scrolling.html"
+    },
+    {
+        "duration": "22.0",
+        "name": "thread_times.key_silk_cases/list_animation_simple.html"
+    },
+    {
+        "duration": "0.0",
+        "name": "thread_times.key_silk_cases/masonry.html"
+    },
+    {
+        "duration": "29.0",
+        "name": "thread_times.key_silk_cases/pushState.html"
+    },
+    {
+        "duration": "41.0",
+        "name": "thread_times.key_silk_cases/silk_finance.html"
+    },
+    {
+        "duration": "38.0",
+        "name": "thread_times.simple_mobile_sites/http://m.nytimes.com/"
+    },
+    {
+        "duration": "63.0",
+        "name": "thread_times.simple_mobile_sites/http://www.ebay.co.uk/"
+    },
+    {
+        "duration": "43.0",
+        "name": "thread_times.simple_mobile_sites/http://www.nyc.gov"
+    },
+    {
+        "duration": "14.0",
+        "name": "thread_times.simple_mobile_sites/https://www.flickr.com/"
+    },
+    {
+        "duration": "51.0",
+        "name": "thread_times.tough_compositor_cases/http://jsbin.com/beqojupo/1/quiet?JS_FULL_SCREEN_INVALIDATION"
+    },
+    {
+        "duration": "41.0",
+        "name": "thread_times.tough_compositor_cases/http://jsbin.com/covoqi/1/quiet?NEW_TILINGS"
+    },
+    {
+        "duration": "36.0",
+        "name": "thread_times.tough_compositor_cases/http://jsbin.com/falefice/1/quiet?CC_POSTER_CIRCLE"
+    },
+    {
+        "duration": "39.0",
+        "name": "thread_times.tough_compositor_cases/http://jsbin.com/giqafofe/1/quiet?JS_POSTER_CIRCLE"
+    },
+    {
+        "duration": "33.0",
+        "name": "thread_times.tough_compositor_cases/http://jsbin.com/jevibahi/4/quiet?JS_SCROLL_200_LAYER_GRID"
+    },
+    {
+        "duration": "49.0",
+        "name": "thread_times.tough_compositor_cases/http://jsbin.com/pixavefe/1/quiet?CC_SCROLL_TEXT_ONLY"
+    },
+    {
+        "duration": "34.0",
+        "name": "thread_times.tough_compositor_cases/http://jsbin.com/wixadinu/2/quiet?JS_SCROLL_TEXT_ONLY"
+    },
+    {
+        "duration": "33.0",
+        "name": "thread_times.tough_compositor_cases/http://jsbin.com/yakagevo/1/quiet?CC_SCROLL_200_LAYER_GRID"
+    },
+    {
+        "duration": "34.0",
+        "name": "thread_times.tough_scrolling_cases/canvas_05000_pixels_per_second"
+    },
+    {
+        "duration": "34.0",
+        "name": "thread_times.tough_scrolling_cases/canvas_10000_pixels_per_second"
+    },
+    {
+        "duration": "34.0",
+        "name": "thread_times.tough_scrolling_cases/canvas_15000_pixels_per_second"
+    },
+    {
+        "duration": "34.0",
+        "name": "thread_times.tough_scrolling_cases/canvas_20000_pixels_per_second"
+    },
+    {
+        "duration": "35.0",
+        "name": "thread_times.tough_scrolling_cases/canvas_30000_pixels_per_second"
+    },
+    {
+        "duration": "35.0",
+        "name": "thread_times.tough_scrolling_cases/canvas_40000_pixels_per_second"
+    },
+    {
+        "duration": "33.0",
+        "name": "thread_times.tough_scrolling_cases/canvas_50000_pixels_per_second"
+    },
+    {
+        "duration": "30.0",
+        "name": "thread_times.tough_scrolling_cases/canvas_60000_pixels_per_second"
+    },
+    {
+        "duration": "27.0",
+        "name": "thread_times.tough_scrolling_cases/canvas_75000_pixels_per_second"
+    },
+    {
+        "duration": "25.0",
+        "name": "thread_times.tough_scrolling_cases/canvas_90000_pixels_per_second"
+    },
+    {
+        "duration": "44.0",
+        "name": "thread_times.tough_scrolling_cases/text_05000_pixels_per_second"
+    },
+    {
+        "duration": "29.0",
+        "name": "thread_times.tough_scrolling_cases/text_10000_pixels_per_second"
+    },
+    {
+        "duration": "30.0",
+        "name": "thread_times.tough_scrolling_cases/text_15000_pixels_per_second"
+    },
+    {
+        "duration": "30.0",
+        "name": "thread_times.tough_scrolling_cases/text_20000_pixels_per_second"
+    },
+    {
+        "duration": "31.0",
+        "name": "thread_times.tough_scrolling_cases/text_30000_pixels_per_second"
+    },
+    {
+        "duration": "31.0",
+        "name": "thread_times.tough_scrolling_cases/text_40000_pixels_per_second"
+    },
+    {
+        "duration": "30.0",
+        "name": "thread_times.tough_scrolling_cases/text_50000_pixels_per_second"
+    },
+    {
+        "duration": "27.0",
+        "name": "thread_times.tough_scrolling_cases/text_60000_pixels_per_second"
+    },
+    {
+        "duration": "25.0",
+        "name": "thread_times.tough_scrolling_cases/text_75000_pixels_per_second"
+    },
+    {
+        "duration": "23.0",
+        "name": "thread_times.tough_scrolling_cases/text_90000_pixels_per_second"
+    },
+    {
+        "duration": "33.0",
+        "name": "thread_times.tough_scrolling_cases/text_constant_full_page_raster_05000_pixels_per_second"
+    },
+    {
+        "duration": "33.0",
+        "name": "thread_times.tough_scrolling_cases/text_constant_full_page_raster_10000_pixels_per_second"
+    },
+    {
+        "duration": "33.0",
+        "name": "thread_times.tough_scrolling_cases/text_constant_full_page_raster_15000_pixels_per_second"
+    },
+    {
+        "duration": "33.0",
+        "name": "thread_times.tough_scrolling_cases/text_constant_full_page_raster_20000_pixels_per_second"
+    },
+    {
+        "duration": "33.0",
+        "name": "thread_times.tough_scrolling_cases/text_constant_full_page_raster_30000_pixels_per_second"
+    },
+    {
+        "duration": "32.0",
+        "name": "thread_times.tough_scrolling_cases/text_constant_full_page_raster_40000_pixels_per_second"
+    },
+    {
+        "duration": "32.0",
+        "name": "thread_times.tough_scrolling_cases/text_constant_full_page_raster_50000_pixels_per_second"
+    },
+    {
+        "duration": "30.0",
+        "name": "thread_times.tough_scrolling_cases/text_constant_full_page_raster_60000_pixels_per_second"
+    },
+    {
+        "duration": "28.0",
+        "name": "thread_times.tough_scrolling_cases/text_constant_full_page_raster_75000_pixels_per_second"
+    },
+    {
+        "duration": "26.0",
+        "name": "thread_times.tough_scrolling_cases/text_constant_full_page_raster_90000_pixels_per_second"
+    },
+    {
+        "duration": "27.0",
+        "name": "thread_times.tough_scrolling_cases/text_hover_05000_pixels_per_second"
+    },
+    {
+        "duration": "29.0",
+        "name": "thread_times.tough_scrolling_cases/text_hover_10000_pixels_per_second"
+    },
+    {
+        "duration": "30.0",
+        "name": "thread_times.tough_scrolling_cases/text_hover_15000_pixels_per_second"
+    },
+    {
+        "duration": "30.0",
+        "name": "thread_times.tough_scrolling_cases/text_hover_20000_pixels_per_second"
+    },
+    {
+        "duration": "31.0",
+        "name": "thread_times.tough_scrolling_cases/text_hover_30000_pixels_per_second"
+    },
+    {
+        "duration": "31.0",
+        "name": "thread_times.tough_scrolling_cases/text_hover_40000_pixels_per_second"
+    },
+    {
+        "duration": "30.0",
+        "name": "thread_times.tough_scrolling_cases/text_hover_50000_pixels_per_second"
+    },
+    {
+        "duration": "27.0",
+        "name": "thread_times.tough_scrolling_cases/text_hover_60000_pixels_per_second"
+    },
+    {
+        "duration": "25.0",
+        "name": "thread_times.tough_scrolling_cases/text_hover_75000_pixels_per_second"
+    },
+    {
+        "duration": "23.0",
+        "name": "thread_times.tough_scrolling_cases/text_hover_90000_pixels_per_second"
+    },
+    {
+        "duration": "20.0",
+        "name": "tracing.tracing_with_background_memory_infra/Facebook"
+    },
+    {
+        "duration": "23.0",
+        "name": "tracing.tracing_with_background_memory_infra/Wikipedia"
+    },
+    {
+        "duration": "17.0",
+        "name": "tracing.tracing_with_background_memory_infra/http://www.amazon.com"
+    },
+    {
+        "duration": "17.0",
+        "name": "tracing.tracing_with_background_memory_infra/http://www.ask.com/"
+    },
+    {
+        "duration": "17.0",
+        "name": "tracing.tracing_with_background_memory_infra/http://www.bing.com/"
+    },
+    {
+        "duration": "18.0",
+        "name": "tracing.tracing_with_background_memory_infra/http://www.yahoo.com/"
+    },
+    {
+        "duration": "19.0",
+        "name": "tracing.tracing_with_background_memory_infra/http://www.youtube.com"
+    },
+    {
+        "duration": "34.0",
+        "name": "tracing.tracing_with_background_memory_infra/https://www.google.com/#hl=en&q=barack+obama"
+    },
+    {
+        "duration": "21.0",
+        "name": "tracing.tracing_with_background_memory_infra/https://www.google.com/calendar/"
+    },
+    {
+        "duration": "206.0",
+        "name": "v8.browsing_mobile-future/browse:chrome:newtab"
+    },
+    {
+        "duration": "60.0",
+        "name": "v8.browsing_mobile-future/browse:chrome:omnibox"
+    },
+    {
+        "duration": "160.0",
+        "name": "v8.browsing_mobile-future/browse:media:facebook_photos"
+    },
+    {
+        "duration": "88.0",
+        "name": "v8.browsing_mobile-future/browse:media:flickr_infinite_scroll"
+    },
+    {
+        "duration": "135.0",
+        "name": "v8.browsing_mobile-future/browse:media:imgur"
+    },
+    {
+        "duration": "208.0",
+        "name": "v8.browsing_mobile-future/browse:media:youtube"
+    },
+    {
+        "duration": "388.0",
+        "name": "v8.browsing_mobile-future/browse:news:cnn"
+    },
+    {
+        "duration": "111.0",
+        "name": "v8.browsing_mobile-future/browse:news:cricbuzz"
+    },
+    {
+        "duration": "0.0",
+        "name": "v8.browsing_mobile-future/browse:news:globo"
+    },
+    {
+        "duration": "95.0",
+        "name": "v8.browsing_mobile-future/browse:news:qq"
+    },
+    {
+        "duration": "113.0",
+        "name": "v8.browsing_mobile-future/browse:news:reddit"
+    },
+    {
+        "duration": "0.0",
+        "name": "v8.browsing_mobile-future/browse:news:toi"
+    },
+    {
+        "duration": "96.0",
+        "name": "v8.browsing_mobile-future/browse:news:washingtonpost"
+    },
+    {
+        "duration": "176.0",
+        "name": "v8.browsing_mobile-future/browse:shopping:amazon"
+    },
+    {
+        "duration": "182.0",
+        "name": "v8.browsing_mobile-future/browse:shopping:avito"
+    },
+    {
+        "duration": "0.0",
+        "name": "v8.browsing_mobile-future/browse:shopping:flipkart"
+    },
+    {
+        "duration": "75.0",
+        "name": "v8.browsing_mobile-future/browse:shopping:lazada"
+    },
+    {
+        "duration": "140.0",
+        "name": "v8.browsing_mobile-future/browse:social:facebook"
+    },
+    {
+        "duration": "212.0",
+        "name": "v8.browsing_mobile-future/browse:social:facebook_infinite_scroll"
+    },
+    {
+        "duration": "189.0",
+        "name": "v8.browsing_mobile-future/browse:social:instagram"
+    },
+    {
+        "duration": "178.0",
+        "name": "v8.browsing_mobile-future/browse:social:pinterest_infinite_scroll"
+    },
+    {
+        "duration": "210.0",
+        "name": "v8.browsing_mobile-future/browse:social:tumblr_infinite_scroll"
+    },
+    {
+        "duration": "90.0",
+        "name": "v8.browsing_mobile-future/browse:social:twitter"
+    },
+    {
+        "duration": "138.0",
+        "name": "v8.browsing_mobile-future/browse:tech:discourse_infinite_scroll"
+    },
+    {
+        "duration": "90.0",
+        "name": "v8.browsing_mobile-future/browse:tools:maps"
+    },
+    {
+        "duration": "208.0",
+        "name": "v8.browsing_mobile/browse:chrome:newtab"
+    },
+    {
+        "duration": "59.0",
+        "name": "v8.browsing_mobile/browse:chrome:omnibox"
+    },
+    {
+        "duration": "161.0",
+        "name": "v8.browsing_mobile/browse:media:facebook_photos"
+    },
+    {
+        "duration": "87.0",
+        "name": "v8.browsing_mobile/browse:media:flickr_infinite_scroll"
+    },
+    {
+        "duration": "135.0",
+        "name": "v8.browsing_mobile/browse:media:imgur"
+    },
+    {
+        "duration": "210.0",
+        "name": "v8.browsing_mobile/browse:media:youtube"
+    },
+    {
+        "duration": "391.0",
+        "name": "v8.browsing_mobile/browse:news:cnn"
+    },
+    {
+        "duration": "111.0",
+        "name": "v8.browsing_mobile/browse:news:cricbuzz"
+    },
+    {
+        "duration": "0.0",
+        "name": "v8.browsing_mobile/browse:news:globo"
+    },
+    {
+        "duration": "95.0",
+        "name": "v8.browsing_mobile/browse:news:qq"
+    },
+    {
+        "duration": "113.0",
+        "name": "v8.browsing_mobile/browse:news:reddit"
+    },
+    {
+        "duration": "0.0",
+        "name": "v8.browsing_mobile/browse:news:toi"
+    },
+    {
+        "duration": "97.0",
+        "name": "v8.browsing_mobile/browse:news:washingtonpost"
+    },
+    {
+        "duration": "176.0",
+        "name": "v8.browsing_mobile/browse:shopping:amazon"
+    },
+    {
+        "duration": "182.0",
+        "name": "v8.browsing_mobile/browse:shopping:avito"
+    },
+    {
+        "duration": "0.0",
+        "name": "v8.browsing_mobile/browse:shopping:flipkart"
+    },
+    {
+        "duration": "74.0",
+        "name": "v8.browsing_mobile/browse:shopping:lazada"
+    },
+    {
+        "duration": "140.0",
+        "name": "v8.browsing_mobile/browse:social:facebook"
+    },
+    {
+        "duration": "214.0",
+        "name": "v8.browsing_mobile/browse:social:facebook_infinite_scroll"
+    },
+    {
+        "duration": "189.0",
+        "name": "v8.browsing_mobile/browse:social:instagram"
+    },
+    {
+        "duration": "180.0",
+        "name": "v8.browsing_mobile/browse:social:pinterest_infinite_scroll"
+    },
+    {
+        "duration": "215.0",
+        "name": "v8.browsing_mobile/browse:social:tumblr_infinite_scroll"
+    },
+    {
+        "duration": "91.0",
+        "name": "v8.browsing_mobile/browse:social:twitter"
+    },
+    {
+        "duration": "139.0",
+        "name": "v8.browsing_mobile/browse:tech:discourse_infinite_scroll"
+    },
+    {
+        "duration": "90.0",
+        "name": "v8.browsing_mobile/browse:tools:maps"
+    }
+]
\ No newline at end of file
diff --git a/ui/file_manager/file_manager/background/js/test_util.js b/ui/file_manager/file_manager/background/js/test_util.js
index bfec093..76c6d51 100644
--- a/ui/file_manager/file_manager/background/js/test_util.js
+++ b/ui/file_manager/file_manager/background/js/test_util.js
@@ -258,19 +258,23 @@
  *
  * @param {Window} contentWindow Window to be tested.
  * @param {string} folderName Name of the folder to be selected.
- * @return {boolean} True if file got selected, false otherwise.
+ * @return {boolean} True if Team Drive folder got selected, false otherwise.
  */
 test.util.sync.selectTeamDrive = function(contentWindow, teamDriveName) {
-  // Select the 'Team Drives' root.
-  if (!test.util.sync.selectFolderInTree(contentWindow, 'Team Drives'))
+  // Select + expand Team Drives gran root.
+  const teamDrivesSelector = '#directory-tree .tree-item ' +
+      '[entry-label="Team Drives"]:not([hidden])';
+  if (!test.util.sync.fakeMouseClick(contentWindow, teamDrivesSelector))
     return false;
 
   // Expand the 'Team Drives' root.
   if (!test.util.sync.expandSelectedFolderInTree(contentWindow))
     return false;
 
-  // Select the team drive.
-  if (!test.util.sync.selectFolderInTree(contentWindow, teamDriveName))
+  // Select the team drive folder.
+  const teamDriveNameSelector = '#directory-tree .tree-item ' +
+      '[entry-label="' + teamDriveName + '"]:not([hidden])';
+  if (!test.util.sync.fakeMouseClick(contentWindow, teamDriveNameSelector))
     return false;
 
   return true;
diff --git a/ui/file_manager/file_manager/common/js/file_type.js b/ui/file_manager/file_manager/common/js/file_type.js
index 401e54f..70b0d83 100644
--- a/ui/file_manager/file_manager/common/js/file_type.js
+++ b/ui/file_manager/file_manager/common/js/file_type.js
@@ -431,6 +431,6 @@
  *     It refers to a file 'images/filetype_' + icon + '.png'.
  */
 FileType.getIcon = function(entry, opt_mimeType) {
-  var fileType = FileType.getType(entry, opt_mimeType);
-  return fileType.icon || fileType.type || 'unknown';
+  const fileType = FileType.getType(entry, opt_mimeType);
+  return entry.iconName || fileType.icon || fileType.type || 'unknown';
 };
diff --git a/ui/file_manager/file_manager/common/js/files_app_entry_types.js b/ui/file_manager/file_manager/common/js/files_app_entry_types.js
index 6b0adb3a..47238ef 100644
--- a/ui/file_manager/file_manager/common/js/files_app_entry_types.js
+++ b/ui/file_manager/file_manager/common/js/files_app_entry_types.js
@@ -430,6 +430,14 @@
   }
 
   /**
+   * String used to determine the icon.
+   * @return {string}
+   */
+  get iconName() {
+    return this.volumeInfo_.volumeType;
+  }
+
+  /**
    * @param {function(Entry)|function(FilesAppEntry)} success callback, it
    * returns itself since EntryList is intended to be used as root node and the
    * Web Standard says to do so.
diff --git a/ui/file_manager/file_manager/common/js/files_app_entry_types_unittest.js b/ui/file_manager/file_manager/common/js/files_app_entry_types_unittest.js
index 70b523d..a8ac05e 100644
--- a/ui/file_manager/file_manager/common/js/files_app_entry_types_unittest.js
+++ b/ui/file_manager/file_manager/common/js/files_app_entry_types_unittest.js
@@ -6,8 +6,8 @@
 
 /**  Test constructor and default public attributes. */
 function testEntryList(testReportCallback) {
-  const entryList = new EntryList('My Files', 'my_files');
-  assertEquals('My Files', entryList.label);
+  const entryList = new EntryList('My files', 'my_files');
+  assertEquals('My files', entryList.label);
   assertEquals('entry-list://my_files', entryList.toURL());
   assertEquals('my_files', entryList.rootType);
   assertFalse(entryList.isNativeType);
@@ -48,7 +48,7 @@
 
 /** Tests method EntryList.getParent. */
 function testEntryListGetParent(testReportCallback) {
-  const entryList = new EntryList('My Files', 'my_files');
+  const entryList = new EntryList('My files', 'my_files');
   let callbackTriggered = false;
   entryList.getParent(parentEntry => {
     // EntryList should return itself since it's a root and that's what the web
@@ -61,13 +61,14 @@
 
 /** Tests method EntryList.addEntry. */
 function testEntryListAddEntry() {
-  const entryList = new EntryList('My Files');
+  const entryList = new EntryList('My files');
   assertEquals(0, entryList.children.length);
 
   const fakeRootEntry = createFakeDisplayRoot();
   const fakeVolumeInfo = {
     displayRoot: fakeRootEntry,
     label: 'Fake Filesystem',
+    volumeType: VolumeManagerCommon.VolumeType.DOWNLOADS,
   };
   const childEntry = new VolumeEntry(fakeVolumeInfo);
   entryList.addEntry(childEntry);
@@ -77,7 +78,7 @@
 
 /** Tests methods to remove entries. */
 function testEntryListRemoveEntry() {
-  const entryList = new EntryList('My Files');
+  const entryList = new EntryList('My files');
 
   const fakeRootEntry = createFakeDisplayRoot();
   const fakeVolumeInfo = {
@@ -94,7 +95,7 @@
  * Tests methods findIndexByVolumeInfo, removeByVolumeType, removeByRootType.
  */
 function testEntryFindIndex() {
-  const entryList = new EntryList('My Files');
+  const entryList = new EntryList('My files');
 
   const fakeRootEntry = createFakeDisplayRoot();
   const downloadsVolumeInfo = {
@@ -115,7 +116,7 @@
   const fakeEntry = {
     isDirectory: true,
     rootType: VolumeManagerCommon.RootType.CROSTINI,
-    name: 'Linux Files',
+    name: 'Linux files',
     toURL: function() {
       return 'fake-entry://linux-files';
     }
@@ -144,7 +145,7 @@
 
 /** Tests method EntryList.getMetadata. */
 function testEntryListGetMetadata(testReportCallback) {
-  const entryList = new EntryList('My Files');
+  const entryList = new EntryList('My files');
 
   let modificationTime = null;
   entryList.getMetadata(metadata => {
@@ -228,10 +229,12 @@
   const fakeVolumeInfo = {
     displayRoot: fakeRootEntry,
     label: 'Fake Filesystem',
+    volumeType: VolumeManagerCommon.VolumeType.DOWNLOADS,
   };
 
   const volumeEntry = new VolumeEntry(fakeVolumeInfo);
   assertEquals(fakeRootEntry, volumeEntry.rootEntry);
+  assertEquals(VolumeManagerCommon.VolumeType.DOWNLOADS, volumeEntry.iconName);
   assertEquals('fake-filesystem://', volumeEntry.filesystem);
   assertEquals('/fake/full/path', volumeEntry.fullPath);
   assertEquals('fake-filesystem://fake/full/path', volumeEntry.toURL());
@@ -327,7 +330,7 @@
     label: 'Fake Filesystem',
   };
   const volumeEntry = new VolumeEntry(fakeVolumeInfo);
-  const entryList = new EntryList('My Files', 'my_files');
+  const entryList = new EntryList('My files', 'my_files');
 
   entryList.addEntry(volumeEntry);
   assertEquals(1, entryList.children.length);
diff --git a/ui/file_manager/file_manager/foreground/css/file_types.css b/ui/file_manager/file_manager/foreground/css/file_types.css
index fa155b92..cdbc193e 100644
--- a/ui/file_manager/file_manager/foreground/css/file_types.css
+++ b/ui/file_manager/file_manager/foreground/css/file_types.css
@@ -223,6 +223,7 @@
       url(../images/volumes/2x/my_files_active.png) 2x);
 }
 
+[file-type-icon='downloads'],
 [volume-type-icon='downloads'] {
   background-image: -webkit-image-set(
       url(../images/volumes/downloads.png) 1x,
@@ -246,6 +247,17 @@
       url(../images/volumes/drive_active.png) 1x,
       url(../images/volumes/2x/drive_active.png) 2x);
 }
+[volume-type-icon='shortcut'] {
+  background-image: -webkit-image-set(
+      url(../images/volumes/shortcut.png) 1x,
+      url(../images/volumes/2x/shortcut.png) 2x);
+}
+
+.tree-row[selected] [volume-type-icon='shortcut'] {
+  background-image: -webkit-image-set(
+      url(../images/volumes/shortcut_active.png) 1x,
+      url(../images/volumes/2x/shortcut_active.png) 2x);
+}
 
 .drive-volume > .tree-row > [volume-type-icon='drive'] {
   background-image: -webkit-image-set(
@@ -443,22 +455,22 @@
       url(../images/volumes/2x/recent_active.png) 2x);
 }
 
+[file-type-icon='crostini'],
 [root-type-icon='crostini'],
 [volume-type-icon='crostini'] {
-  /* Need !important to override inline style applied to provided volumes. */
   background-image: -webkit-image-set(
       url(../images/volumes/linux_files.png) 1x,
-      url(../images/volumes/2x/linux_files.png) 2x) !important;
+      url(../images/volumes/2x/linux_files.png) 2x);
 }
 
 .tree-row[selected] [root-type-icon='crostini'],
 .tree-row[selected] [volume-type-icon='crostini'] {
-  /* Need !important to override inline style applied to provided volumes. */
   background-image: -webkit-image-set(
       url(../images/volumes/linux_files_active.png) 1x,
-      url(../images/volumes/2x/linux_files_active.png) 2x) !important;
+      url(../images/volumes/2x/linux_files_active.png) 2x);
 }
 
+[file-type-icon='android_files'],
 [volume-type-icon='android_files'] {
   background-image: -webkit-image-set(
       url(../images/volumes/android.png) 1x,
diff --git a/ui/file_manager/file_manager/foreground/images/volumes/2x/shortcut.png b/ui/file_manager/file_manager/foreground/images/volumes/2x/shortcut.png
new file mode 100644
index 0000000..9974120e
--- /dev/null
+++ b/ui/file_manager/file_manager/foreground/images/volumes/2x/shortcut.png
Binary files differ
diff --git a/ui/file_manager/file_manager/foreground/images/volumes/2x/shortcut_active.png b/ui/file_manager/file_manager/foreground/images/volumes/2x/shortcut_active.png
new file mode 100644
index 0000000..9737774
--- /dev/null
+++ b/ui/file_manager/file_manager/foreground/images/volumes/2x/shortcut_active.png
Binary files differ
diff --git a/ui/file_manager/file_manager/foreground/images/volumes/shortcut.png b/ui/file_manager/file_manager/foreground/images/volumes/shortcut.png
new file mode 100644
index 0000000..c50218ab
--- /dev/null
+++ b/ui/file_manager/file_manager/foreground/images/volumes/shortcut.png
Binary files differ
diff --git a/ui/file_manager/file_manager/foreground/images/volumes/shortcut_active.png b/ui/file_manager/file_manager/foreground/images/volumes/shortcut_active.png
new file mode 100644
index 0000000..46df6a9a
--- /dev/null
+++ b/ui/file_manager/file_manager/foreground/images/volumes/shortcut_active.png
Binary files differ
diff --git a/ui/file_manager/file_manager/foreground/js/file_manager.js b/ui/file_manager/file_manager/foreground/js/file_manager.js
index 5c9ddf2..d71ebb5 100644
--- a/ui/file_manager/file_manager/foreground/js/file_manager.js
+++ b/ui/file_manager/file_manager/foreground/js/file_manager.js
@@ -1240,6 +1240,7 @@
                 toURL: function() {
                   return 'fake-entry://linux-files';
                 },
+                iconName: VolumeManagerCommon.VolumeType.CROSTINI,
               }) :
           null;
       this.directoryTree.redraw(false);
diff --git a/ui/file_manager/file_manager/foreground/js/navigation_list_model_unittest.js b/ui/file_manager/file_manager/foreground/js/navigation_list_model_unittest.js
index 75c2fe8b..d203ff6 100644
--- a/ui/file_manager/file_manager/foreground/js/navigation_list_model_unittest.js
+++ b/ui/file_manager/file_manager/foreground/js/navigation_list_model_unittest.js
@@ -17,8 +17,8 @@
   DRIVE_SHARED_WITH_ME_COLLECTION_LABEL: 'Shared with me',
   DRIVE_RECENT_COLLECTION_LABEL: 'Recents',
   DOWNLOADS_DIRECTORY_LABEL: 'Downloads',
-  LINUX_FILES_ROOT_LABEL: 'Linux Files',
-  MY_FILES_ROOT_LABEL: 'My Files',
+  LINUX_FILES_ROOT_LABEL: 'Linux files',
+  MY_FILES_ROOT_LABEL: 'My files',
   RECENT_ROOT_LABEL: 'Recent',
   MEDIA_VIEW_IMAGES_ROOT_LABEL: 'Images',
   MEDIA_VIEW_VIDEOS_ROOT_LABEL: 'Videos',
@@ -222,10 +222,10 @@
   //  4.  media_view:audio_root
   //  5.  /root/shortcut
   //  6.  /root/shortcut2
-  //  7.  My-Files
+  //  7.  My files
   //        -> Downloads
-  //        -> Play Files
-  //        -> Linux Files
+  //        -> Play files
+  //        -> Linux files
   //  8.  removable:hoge
   //  9.  archive:a-rar  - mounted as archive
   // 10.  removable:fuga
@@ -250,7 +250,7 @@
 
   assertEquals('shortcut', model.item(4).label);
   assertEquals('shortcut2', model.item(5).label);
-  assertEquals('My Files', model.item(6).label);
+  assertEquals('My files', model.item(6).label);
 
   assertEquals('removable:hoge', model.item(7).label);
   assertEquals('archive:a-rar', model.item(8).label);
diff --git a/ui/file_manager/file_manager/foreground/js/ui/directory_tree.js b/ui/file_manager/file_manager/foreground/js/ui/directory_tree.js
index 1d7b6215..9df854d 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/directory_tree.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/directory_tree.js
@@ -1049,7 +1049,6 @@
     this.add(item);
     item.updateSubDirectories(false);
   }
-  this.expanded = true;
 };
 
 /**
@@ -1109,7 +1108,7 @@
 
   var icon = item.querySelector('.icon');
   icon.classList.add('item-icon');
-  icon.setAttribute('volume-type-icon', VolumeManagerCommon.VolumeType.DRIVE);
+  icon.setAttribute('volume-type-icon', 'shortcut');
 
   if (tree.contextMenuForRootItems)
     item.setContextMenu_(tree.contextMenuForRootItems);
diff --git a/ui/file_manager/file_manager/test/crostini.js b/ui/file_manager/file_manager/test/crostini.js
index f2fc2a0..2cadf5f4 100644
--- a/ui/file_manager/file_manager/test/crostini.js
+++ b/ui/file_manager/file_manager/test/crostini.js
@@ -183,7 +183,7 @@
         // Validate error messages, click 'OK' to close.  Ensure dialog closes.
         assertEquals(
             'To open files with Crostini App, ' +
-                'first copy to Linux Files folder.',
+                'first copy to Linux files folder.',
             document.querySelector('.cr-dialog-text').innerText);
         assertTrue(test.fakeMouseClick('button.cr-dialog-ok'));
         return test.waitForElementLost('.cr-dialog-container.shown');
diff --git a/ui/file_manager/file_manager/test/js/strings.js b/ui/file_manager/file_manager/test/js/strings.js
index 900a5edee..56fc7d5 100644
--- a/ui/file_manager/file_manager/test/js/strings.js
+++ b/ui/file_manager/file_manager/test/js/strings.js
@@ -48,7 +48,7 @@
           'All files saved in this folder are backed up online automatically',
       DRIVE_WELCOME_TITLE_ALTERNATIVE: 'Get 100 GB free with Google Drive',
       EMPTY_FOLDER: 'Nothing to see here...',
-      ERROR_LINUX_FILES_CONNECTION: 'Unable to view Linux Files',
+      ERROR_LINUX_FILES_CONNECTION: 'Unable to view Linux files',
       FILENAME_LABEL: 'File name',
       GALLERY_CONFIRM_DELETE_ONE: 'Are you sure you want to delete "$1"?',
       GALLERY_CONFIRM_DELETE_SOME: 'Are you sure you want to delete $1 items?',
@@ -59,7 +59,7 @@
           'utm_campaign=gsg',
       IMAGE_FILE_TYPE: '$1 image',
       INSTALL_NEW_EXTENSION_LABEL: 'Install new from the webstore',
-      LINUX_FILES_ROOT_LABEL: 'Linux Files',
+      LINUX_FILES_ROOT_LABEL: 'Linux files',
       MANY_ENTRIES_SELECTED: '$1 items selected',
       MANY_FILES_SELECTED: '$1 files selected',
       METADATA_BOX_ALBUM_TITLE: 'Album',
@@ -67,14 +67,14 @@
       METADATA_BOX_MODIFICATION_TIME: 'Modified time',
       MOVE_FILE_NAME: 'Moving $1...',
       MOVE_ITEMS_REMAINING: 'Moving $1 items...',
-      MY_FILES_ROOT_LABEL: 'My Files',
+      MY_FILES_ROOT_LABEL: 'My files',
       NAME_COLUMN_LABEL: 'Name',
       OFFLINE_COLUMN_LABEL: 'Available offline',
       OPEN_WITH_VERB_BUTTON_LABEL: 'Open with $1',
       OK_LABEL: 'OK',
       ONE_DIRECTORY_SELECTED: '1 folder selected',
       ONE_FILE_SELECTED: '1 file selected',
-      OPENING_LINUX_FILES: 'Opening Linux Files...',
+      OPENING_LINUX_FILES: 'Opening Linux files...',
       OPEN_LABEL: 'Open',
       PLAIN_TEXT_FILE_TYPE: 'Plain text',
       PREPARING_LABEL: 'Preparing',
@@ -104,7 +104,7 @@
       TOGGLE_HIDDEN_FILES_COMMAND_LABEL: 'Show hidden files',
       UNABLE_TO_OPEN_CROSTINI_TITLE: 'Unable to open with $1',
       UNABLE_TO_OPEN_CROSTINI:
-          'To open files with $1, first copy to Linux Files folder.',
+          'To open files with $1, first copy to Linux files folder.',
       VIDEO_FILE_TYPE: '$1 video',
       WAITING_FOR_SPACE_INFO: 'Waiting for space info...',
       language: 'en',
diff --git a/ui/file_manager/integration_tests/file_manager/my_files.js b/ui/file_manager/integration_tests/file_manager/my_files.js
index d574a309..b27e748 100644
--- a/ui/file_manager/integration_tests/file_manager/my_files.js
+++ b/ui/file_manager/integration_tests/file_manager/my_files.js
@@ -10,9 +10,9 @@
 
   const expectedElementLabels = [
     'Recent: FakeItem',
-    'My Files: EntryListItem',
+    'My files: EntryListItem',
     'Downloads: SubDirectoryItem',
-    'Linux Files: FakeItem',
+    'Linux files: FakeItem',
     'Google Drive: DriveVolumeItem',
     'My Drive: SubDirectoryItem',
     'Shared with me: SubDirectoryItem',
@@ -59,7 +59,7 @@
     },
     // Check that My Files is displayed on breadcrumbs.
     function(breadcrumbs) {
-      const expectedBreadcrumbs = 'My Files > Downloads';
+      const expectedBreadcrumbs = 'My files > Downloads';
       const resultBreadscrubms =
           breadcrumbs.map(crumb => crumb.text).join(' > ');
       chrome.test.assertEq(expectedBreadcrumbs, resultBreadscrubms);
@@ -104,7 +104,7 @@
     },
     // Select My Files folder.
     function() {
-      const myFilesQuery = '#directory-tree [entry-label="My Files"]';
+      const myFilesQuery = '#directory-tree [entry-label="My files"]';
       const isDriveQuery = false;
       remoteCall.callRemoteTestUtil(
           'selectInDirectoryTree', appId, [myFilesQuery, isDriveQuery],
@@ -183,7 +183,7 @@
     // Select My Files folder.
     function(results) {
       appId = results.windowId;
-      const myFilesQuery = '#directory-tree [entry-label="My Files"]';
+      const myFilesQuery = '#directory-tree [entry-label="My files"]';
       const isDriveQuery = false;
       remoteCall.callRemoteTestUtil(
           'selectInDirectoryTree', appId, [myFilesQuery, isDriveQuery],
@@ -193,7 +193,7 @@
     function(result) {
       chrome.test.assertTrue(result);
       const downloadsRow = ['Downloads', '--', 'Folder'];
-      const crostiniRow = ['Linux Files', '--', 'Folder'];
+      const crostiniRow = ['Linux files', '--', 'Folder'];
       remoteCall
           .waitForFiles(
               appId, [downloadsRow, crostiniRow],
diff --git a/ui/file_manager/integration_tests/file_manager/transfer.js b/ui/file_manager/integration_tests/file_manager/transfer.js
index b699ee33..96566be4 100644
--- a/ui/file_manager/integration_tests/file_manager/transfer.js
+++ b/ui/file_manager/integration_tests/file_manager/transfer.js
@@ -78,6 +78,11 @@
                               entry.teamDriveName === ''))
                       .sort();
   }
+  const myDriveContent = TestEntryInfo
+                             .getExpectedRows(src.initialEntries.filter(
+                                 entry => entry.type !== EntryType.TEAM_DRIVE &&
+                                     entry.teamDriveName === ''))
+                             .sort();
 
   let dstContents;
   if (dst.isTeamDrive) {
@@ -100,9 +105,30 @@
       setupAndWaitUntilReady(
           null, RootPath.DOWNLOADS, this.next, localFiles, driveFiles);
     },
-    // Select the source volume.
+    // Expand Drive root if either src or dst is within Drive.
     function(results) {
       appId = results.windowId;
+      if (src.isTeamDrive || dst.isTeamDrive) {
+        // Select + expand + wait for its content.
+        remoteCall
+            .callRemoteTestUtil('selectFolderInTree', appId, ['Google Drive'])
+            .then(result => {
+              chrome.test.assertTrue(result);
+              return remoteCall.callRemoteTestUtil(
+                  'expandSelectedFolderInTree', appId, []);
+            })
+            .then(result => {
+              chrome.test.assertTrue(result);
+              return remoteCall.waitForFiles(appId, myDriveContent);
+            })
+            .then(this.next);
+      } else {
+        // If isn't drive source, just move on.
+        this.next();
+      }
+    },
+    // Select the source volume.
+    function() {
       remoteCall.callRemoteTestUtil(
           src.isTeamDrive ? 'selectTeamDrive' : 'selectVolume', appId,
           [src.volumeName], this.next);
diff --git a/ui/file_manager/integration_tests/remote_call.js b/ui/file_manager/integration_tests/remote_call.js
index 7420fb4..8e91774d 100644
--- a/ui/file_manager/integration_tests/remote_call.js
+++ b/ui/file_manager/integration_tests/remote_call.js
@@ -413,7 +413,7 @@
       function(path) {
         // TODO(lucmult): Remove this once MyFiles flag is removed.
         // https://crbug.com/850348.
-        const myFilesExpectedPath = '/My Files' + expectedPath;
+        const myFilesExpectedPath = '/My files' + expectedPath;
         if(!(path === expectedPath || path === myFilesExpectedPath)) {
           return pending(
               caller, 'Expected path is %s got %s', expectedPath, path);
diff --git a/ui/gl/gl_fence.cc b/ui/gl/gl_fence.cc
index 9dcfee3..674cdd2 100644
--- a/ui/gl/gl_fence.cc
+++ b/ui/gl/gl_fence.cc
@@ -18,8 +18,7 @@
 #include "ui/gl/gl_fence_apple.h"
 #endif
 
-#if defined(USE_EGL) && defined(OS_POSIX) && !defined(OS_FUCHSIA) && \
-    !defined(OS_MACOSX)
+#if defined(USE_EGL) && defined(OS_POSIX) && !defined(OS_MACOSX)
 #define USE_GL_FENCE_ANDROID_NATIVE_FENCE_SYNC
 #include "ui/gl/gl_fence_android_native_fence_sync.h"
 #include "ui/gl/gl_surface_egl.h"