diff --git a/BUILD.gn b/BUILD.gn
index d05b1f7..5631732 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -13,6 +13,7 @@
 import("//build/config/sanitizers/sanitizers.gni")
 import("//build/config/ui.gni")
 import("//components/nacl/features.gni")
+import("//components/nux_google_apps/features.gni")
 import("//device/vr/buildflags/buildflags.gni")
 import("//extensions/buildflags/buildflags.gni")
 import("//media/media_options.gni")
@@ -1184,6 +1185,9 @@
     if (is_android) {
       data_deps += [ "components/offline_pages/resources:closure_compile" ]
     }
+    if (enable_nux_google_apps) {
+      data_deps += [ "components/nux_google_apps/resources:closure_compile" ]
+    }
   }
 }
 
diff --git a/DEPS b/DEPS
index 49581db..776a9bb 100644
--- a/DEPS
+++ b/DEPS
@@ -105,7 +105,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': '61582510eeb8484ad3e12df97bf781a3129f60d0',
+  'skia_revision': '9457546761a40c96f586b34b755fef47a7ad006a',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # 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': 'bcd66f54de1291ddf8b7b7caca3e7360e14fcc8d',
+  'pdfium_revision': 'c3cc2ab66d3d8f52dea8083abb6775115e17af7d',
   # 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.
@@ -165,7 +165,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling catapult
   # and whatever else without interference from each other.
-  'catapult_revision': '53842b6cbc1fbab4f69ed5b9c2c30babd61cefbd',
+  'catapult_revision': '7a75f465f541280d20b4e96caf477517b0fc4b18',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -393,7 +393,7 @@
   },
 
   'src/third_party/android_tools': {
-      'url': Var('chromium_git') + '/android_tools.git' + '@' + 'c22a664c39af72dd8f89200220713dcad811300a',
+      'url': Var('chromium_git') + '/android_tools.git' + '@' + '3545ab5b9883087a54cb9e5337c32617cb2a443d',
       'condition': 'checkout_android_native_support',
   },
 
@@ -503,7 +503,7 @@
       'packages': [
           {
               'package': 'chromium/third_party/byte_buddy',
-              'version': 'version:1.4.17-cr0',
+              'version': 'version:1.8.8-cr0',
           },
       ],
       'condition': 'checkout_android',
@@ -518,7 +518,7 @@
 
   # Build tools for Chrome OS. Note: This depends on third_party/pyelftools.
   'src/third_party/chromite': {
-      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '0d22d3fa3ae1e575fd0f5baa4d56e94e71ca9011',
+      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '694c8ff073d52bf47fa3292c17434a9303d7272d',
       'condition': 'checkout_linux',
   },
 
@@ -543,7 +543,7 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '04925ac3f7e50988945be3a5655198736a8b3e58',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '4099daa97b38b2ddb95e34d9fc3e2d37f58df069',
 
   'src/third_party/devtools-node-modules':
     Var('chromium_git') + '/external/github.com/ChromeDevTools/devtools-node-modules' + '@' + Var('devtools_node_modules_revision'),
@@ -833,7 +833,7 @@
   },
 
   'src/third_party/mockito/src': {
-      'url': Var('chromium_git') + '/external/mockito/mockito.git' + '@' + 'de83ad4598ad4cf5ea53c69a8a8053780b04b850',
+      'url': Var('chromium_git') + '/external/mockito/mockito.git' + '@' + '04a2a289a4222f80ad20717c25144981210d2eac',
       'condition': 'checkout_android',
   },
 
@@ -891,7 +891,7 @@
   },
 
   'src/third_party/perfetto':
-    Var('android_git') + '/platform/external/perfetto.git' + '@' +  '8d31c73edc4acdb042a36cb37f99c89889fbc476',
+    Var('android_git') + '/platform/external/perfetto.git' + '@' +  '6e6a25be184caa0f6a07ff5b452bdeff04ed9af6',
 
   'src/third_party/perl': {
       'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + 'ac0d98b5cee6c024b0cffeb4f8f45b6fc5ccdb78',
@@ -1010,7 +1010,7 @@
     Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '5e83981c2c44f24109b96b555d6865d481e0c609',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + '6f440ed5b51fe859a0c438db189962eaf737b8c7',
+    Var('webrtc_git') + '/src.git' + '@' + '5f5819f8ed8ae0561109040fbdce0b2ee4854257',
 
   'src/third_party/xdg-utils': {
       'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d',
diff --git a/ash/BUILD.gn b/ash/BUILD.gn
index bd52154..e9afb6d 100644
--- a/ash/BUILD.gn
+++ b/ash/BUILD.gn
@@ -1017,7 +1017,6 @@
     "utility/transformer_util.h",
     "voice_interaction/voice_interaction_controller.cc",
     "voice_interaction/voice_interaction_controller.h",
-    "voice_interaction/voice_interaction_observer.h",
     "wallpaper/wallpaper_controller.cc",
     "wallpaper/wallpaper_controller.h",
     "wallpaper/wallpaper_controller_observer.h",
diff --git a/ash/accelerators/accelerator_controller.cc b/ash/accelerators/accelerator_controller.cc
index 2dcb310..ce274497 100644
--- a/ash/accelerators/accelerator_controller.cc
+++ b/ash/accelerators/accelerator_controller.cc
@@ -15,7 +15,8 @@
 #include "ash/accessibility/accessibility_controller.h"
 #include "ash/app_list/app_list_controller_impl.h"
 #include "ash/assistant/assistant_controller.h"
-#include "ash/assistant/assistant_interaction_controller.h"
+#include "ash/assistant/assistant_ui_controller.h"
+#include "ash/assistant/model/assistant_ui_model.h"
 #include "ash/debug.h"
 #include "ash/display/display_configuration_controller.h"
 #include "ash/display/display_move_window_util.h"
@@ -672,10 +673,8 @@
   // TODO(dmblack): Remove. Enabling eligibility check bypass for development
   // purposes only. We should otherwise respect the eligibility rules below.
   if (chromeos::switches::IsAssistantEnabled()) {
-    Shell::Get()
-        ->assistant_controller()
-        ->interaction_controller()
-        ->ToggleInteraction();
+    Shell::Get()->assistant_controller()->ui_controller()->ToggleUi(
+        AssistantSource::kHotkey);
     return;
   }
 
@@ -714,10 +713,8 @@
   if (!chromeos::switches::IsAssistantEnabled()) {
     Shell::Get()->app_list_controller()->ToggleVoiceInteractionSession();
   } else {
-    Shell::Get()
-        ->assistant_controller()
-        ->interaction_controller()
-        ->ToggleInteraction();
+    Shell::Get()->assistant_controller()->ui_controller()->ToggleUi(
+        AssistantSource::kHotkey);
   }
 }
 
diff --git a/ash/accessibility/accessibility_controller.cc b/ash/accessibility/accessibility_controller.cc
index 378541d..2d98d724 100644
--- a/ash/accessibility/accessibility_controller.cc
+++ b/ash/accessibility/accessibility_controller.cc
@@ -41,6 +41,7 @@
 #include "ui/aura/window.h"
 #include "ui/base/cursor/cursor_type.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/base/ui_base_features.h"
 #include "ui/keyboard/keyboard_util.h"
 #include "ui/message_center/message_center.h"
 #include "ui/message_center/public/cpp/notifier_id.h"
@@ -1023,7 +1024,7 @@
 
   keyboard::SetAccessibilityKeyboardEnabled(enabled);
 
-  if (Shell::GetAshConfig() == Config::MASH) {
+  if (!features::IsAshInBrowserProcess()) {
     // TODO(mash): Support on-screen keyboard. See https://crbug.com/646565.
     NOTIMPLEMENTED();
     return;
diff --git a/ash/app_list/views/app_list_menu_model_adapter.cc b/ash/app_list/views/app_list_menu_model_adapter.cc
index 8b34fe4..57e7941 100644
--- a/ash/app_list/views/app_list_menu_model_adapter.cc
+++ b/ash/app_list/views/app_list_menu_model_adapter.cc
@@ -42,7 +42,7 @@
   menu_items_ = std::move(items);
 }
 
-void AppListMenuModelAdapter::RecordHistogram() {
+void AppListMenuModelAdapter::RecordHistogramOnMenuClosed() {
   const base::TimeDelta user_journey_time =
       base::TimeTicks::Now() - menu_open_time();
   switch (type_) {
@@ -97,6 +97,7 @@
 
 void AppListMenuModelAdapter::ExecuteCommand(int id, int mouse_event_flags) {
   delegate_->ExecuteCommand(id, mouse_event_flags);
+  RecordExecuteCommandHistogram(id);
 }
 
 }  // namespace app_list
diff --git a/ash/app_list/views/app_list_menu_model_adapter.h b/ash/app_list/views/app_list_menu_model_adapter.h
index 842522a..64024224 100644
--- a/ash/app_list/views/app_list_menu_model_adapter.h
+++ b/ash/app_list/views/app_list_menu_model_adapter.h
@@ -24,7 +24,8 @@
     : public ash::AppMenuModelAdapter {
  public:
   // The kinds of apps which show menus. This enum is used to record
-  // metrics, if a new value is added make sure to modify RecordHistogram().
+  // metrics, if a new value is added make sure to modify
+  // RecordHistogramOnMenuClosed().
   enum AppListViewAppType {
     FULLSCREEN_SEARCH_RESULT,
     FULLSCREEN_SUGGESTED,
@@ -54,7 +55,7 @@
   void Build(std::vector<ash::mojom::MenuItemPtr> items);
 
   // Overridden from AppMenuModelAdapter:
-  void RecordHistogram() override;
+  void RecordHistogramOnMenuClosed() override;
 
   // Overridden from views::MenuModelAdapter:
   bool IsItemChecked(int id) const override;
diff --git a/ash/app_menu/app_menu_model_adapter.cc b/ash/app_menu/app_menu_model_adapter.cc
index 29bc325..16889ffc 100644
--- a/ash/app_menu/app_menu_model_adapter.cc
+++ b/ash/app_menu/app_menu_model_adapter.cc
@@ -5,6 +5,7 @@
 #include "ash/app_menu/app_menu_model_adapter.h"
 
 #include "ash/app_menu/notification_menu_controller.h"
+#include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
 #include "ui/base/models/simple_menu_model.h"
 #include "ui/base/ui_base_features.h"
@@ -14,6 +15,20 @@
 
 namespace ash {
 
+namespace {
+
+// The UMA histogram that logs the commands which are executed on non-app
+// context menus.
+constexpr char kNonAppContextMenuExecuteCommand[] =
+    "Apps.ContextMenuExecuteCommand.NotFromApp";
+
+// The UMA histogram that logs the commands which are executed on app context
+// menus.
+constexpr char kAppContextMenuExecuteCommand[] =
+    "Apps.ContextMenuExecuteCommand.FromApp";
+
+}  // namespace
+
 AppMenuModelAdapter::AppMenuModelAdapter(
     const std::string& app_id,
     std::unique_ptr<ui::SimpleMenuModel> model,
@@ -66,12 +81,23 @@
   return menu_runner_->closing_event_time();
 }
 
+void AppMenuModelAdapter::ExecuteCommand(int id, int mouse_event_flags) {
+  views::MenuModelAdapter::ExecuteCommand(id, mouse_event_flags);
+  RecordExecuteCommandHistogram(id);
+}
+
 void AppMenuModelAdapter::OnMenuClosed(views::MenuItemView* menu) {
   DCHECK_NE(base::TimeTicks(), menu_open_time_);
-  RecordHistogram();
+  RecordHistogramOnMenuClosed();
 
   if (on_menu_closed_callback_)
     std::move(on_menu_closed_callback_).Run();
 }
 
+void AppMenuModelAdapter::RecordExecuteCommandHistogram(int command_id) {
+  base::UmaHistogramSparse(app_id().empty() ? kNonAppContextMenuExecuteCommand
+                                            : kAppContextMenuExecuteCommand,
+                           command_id);
+}
+
 }  // namespace ash
diff --git a/ash/app_menu/app_menu_model_adapter.h b/ash/app_menu/app_menu_model_adapter.h
index e57a6b5..a53870f 100644
--- a/ash/app_menu/app_menu_model_adapter.h
+++ b/ash/app_menu/app_menu_model_adapter.h
@@ -48,12 +48,10 @@
   // Closes the menu if one is being shown.
   void Cancel();
 
-  // Records the user journey time and show source histograms.
-  virtual void RecordHistogram() = 0;
-
   base::TimeTicks GetClosingEventTime();
 
   // Overridden from views::MenuModelAdapter:
+  void ExecuteCommand(int id, int mouse_event_flags) override;
   void OnMenuClosed(views::MenuItemView* menu) override;
 
  protected:
@@ -64,6 +62,13 @@
   ui::SimpleMenuModel* model() { return model_.get(); }
   const ui::SimpleMenuModel* model() const { return model_.get(); }
 
+  // Helper method to record ExecuteCommand() histograms.
+  void RecordExecuteCommandHistogram(int command_id);
+
+  // Records histograms on menu closed, such as the user journey time and show
+  // source histograms.
+  virtual void RecordHistogramOnMenuClosed() = 0;
+
  private:
   // The application identifier used to fetch active notifications to display.
   const std::string app_id_;
diff --git a/ash/assistant/assistant_controller.cc b/ash/assistant/assistant_controller.cc
index cb6f0ae..132b0ee 100644
--- a/ash/assistant/assistant_controller.cc
+++ b/ash/assistant/assistant_controller.cc
@@ -18,9 +18,20 @@
 AssistantController::AssistantController()
     : assistant_interaction_controller_(
           std::make_unique<AssistantInteractionController>()),
-      assistant_ui_controller_(std::make_unique<AssistantUiController>(this)) {}
+      assistant_ui_controller_(std::make_unique<AssistantUiController>(this)) {
+  // Note that the sub-controllers have a circular dependency.
+  // TODO(dmblack): Remove this circular dependency.
+  assistant_interaction_controller_->SetAssistantUiController(
+      assistant_ui_controller_.get());
+  assistant_ui_controller_->SetAssistantInteractionController(
+      assistant_interaction_controller_.get());
+}
 
-AssistantController::~AssistantController() = default;
+AssistantController::~AssistantController() {
+  // Explicitly clean up the circular dependency in the sub-controllers.
+  assistant_interaction_controller_->SetAssistantUiController(nullptr);
+  assistant_ui_controller_->SetAssistantInteractionController(nullptr);
+}
 
 void AssistantController::BindRequest(
     mojom::AssistantControllerRequest request) {
@@ -31,8 +42,9 @@
     chromeos::assistant::mojom::AssistantPtr assistant) {
   assistant_ = std::move(assistant);
 
-  // Provide reference to interaction controller.
+  // Provide reference to sub-controllers.
   assistant_interaction_controller_->SetAssistant(assistant_.get());
+  assistant_ui_controller_->SetAssistant(assistant_.get());
 }
 
 void AssistantController::SetAssistantImageDownloader(
@@ -44,8 +56,8 @@
     mojom::AssistantSetupPtr assistant_setup) {
   assistant_setup_ = std::move(assistant_setup);
 
-  // Provide reference to interaction controller.
-  assistant_interaction_controller_->SetAssistantSetup(assistant_setup_.get());
+  // Provide reference to UI controller.
+  assistant_ui_controller_->SetAssistantSetup(assistant_setup_.get());
 }
 
 void AssistantController::SetWebContentsManager(
@@ -90,6 +102,7 @@
   params->account_id = user_session->user_info->account_id;
 
   // Specify that we will handle top level browser requests.
+  // TODO(dmblack): Make AssistantController the OpenUrl delegate.
   ash::mojom::ManagedWebContentsOpenUrlDelegatePtr ptr;
   web_contents_open_url_delegate_bindings_.AddBinding(
       assistant_interaction_controller_.get(), mojo::MakeRequest(&ptr));
diff --git a/ash/assistant/assistant_controller_unittest.cc b/ash/assistant/assistant_controller_unittest.cc
index 86b951f..e5bfd20 100644
--- a/ash/assistant/assistant_controller_unittest.cc
+++ b/ash/assistant/assistant_controller_unittest.cc
@@ -7,7 +7,6 @@
 #include <memory>
 
 #include "ash/assistant/assistant_ui_controller.h"
-#include "ash/highlighter/highlighter_controller.h"
 #include "ash/shell.h"
 #include "ash/test/ash_test_base.h"
 #include "base/macros.h"
@@ -42,11 +41,11 @@
     assistant_binding_->Bind(mojo::MakeRequest(&assistant));
     controller_->SetAssistant(std::move(assistant));
 
-    ASSERT_FALSE(IsAssistantUiShown());
+    ASSERT_FALSE(IsAssistantUiVisible());
   }
 
-  bool IsAssistantUiShown() {
-    return controller_->ui_controller()->IsVisible();
+  bool IsAssistantUiVisible() {
+    return controller_->ui_controller()->model()->visible();
   }
 
  private:
diff --git a/ash/assistant/assistant_interaction_controller.cc b/ash/assistant/assistant_interaction_controller.cc
index e6517fe..9825ae8 100644
--- a/ash/assistant/assistant_interaction_controller.cc
+++ b/ash/assistant/assistant_interaction_controller.cc
@@ -4,39 +4,17 @@
 
 #include "ash/assistant/assistant_interaction_controller.h"
 
+#include "ash/assistant/assistant_controller.h"
+#include "ash/assistant/assistant_ui_controller.h"
 #include "ash/assistant/model/assistant_interaction_model_observer.h"
 #include "ash/assistant/model/assistant_query.h"
 #include "ash/assistant/model/assistant_ui_element.h"
 #include "ash/new_window_controller.h"
-#include "ash/public/interfaces/assistant_setup.mojom.h"
 #include "ash/shell.h"
-#include "ash/strings/grit/ash_strings.h"
-#include "ash/system/toast/toast_data.h"
-#include "ash/system/toast/toast_manager.h"
-#include "ash/voice_interaction/voice_interaction_controller.h"
 #include "base/strings/utf_string_conversions.h"
-#include "ui/base/l10n/l10n_util.h"
 
 namespace ash {
 
-namespace {
-
-// Toast -----------------------------------------------------------------------
-
-constexpr int kToastDurationMs = 2500;
-constexpr char kUnboundServiceToastId[] =
-    "assistant_controller_unbound_service";
-
-void ShowToast(const std::string& id, int message_id) {
-  ToastData toast(id, l10n_util::GetStringUTF16(message_id), kToastDurationMs,
-                  base::nullopt);
-  Shell::Get()->toast_manager()->Show(toast);
-}
-
-}  // namespace
-
-// AssistantInteractionController ----------------------------------------------
-
 AssistantInteractionController::AssistantInteractionController()
     : assistant_event_subscriber_binding_(this) {
   AddModelObserver(this);
@@ -58,9 +36,15 @@
   assistant_->AddAssistantEventSubscriber(std::move(ptr));
 }
 
-void AssistantInteractionController::SetAssistantSetup(
-    mojom::AssistantSetup* assistant_setup) {
-  assistant_setup_ = assistant_setup;
+void AssistantInteractionController::SetAssistantUiController(
+    AssistantUiController* assistant_ui_controller) {
+  if (assistant_ui_controller_)
+    assistant_ui_controller_->RemoveModelObserver(this);
+
+  assistant_ui_controller_ = assistant_ui_controller;
+
+  if (assistant_ui_controller_)
+    assistant_ui_controller_->AddModelObserver(this);
 }
 
 void AssistantInteractionController::AddModelObserver(
@@ -73,50 +57,6 @@
   assistant_interaction_model_.RemoveObserver(observer);
 }
 
-void AssistantInteractionController::StartInteraction() {
-  if (!Shell::Get()->voice_interaction_controller()->setup_completed()) {
-    assistant_setup_->StartAssistantOptInFlow();
-    return;
-  }
-
-  if (!Shell::Get()->voice_interaction_controller()->settings_enabled())
-    return;
-
-  if (!assistant_) {
-    ShowToast(kUnboundServiceToastId, IDS_ASH_ASSISTANT_ERROR_GENERIC);
-    return;
-  }
-
-  OnInteractionStarted();
-}
-
-void AssistantInteractionController::StopInteraction() {
-  assistant_interaction_model_.SetInteractionState(InteractionState::kInactive);
-}
-
-void AssistantInteractionController::ToggleInteraction() {
-  if (assistant_interaction_model_.interaction_state() ==
-      InteractionState::kInactive) {
-    StartInteraction();
-  } else {
-    StopInteraction();
-  }
-}
-
-void AssistantInteractionController::OnInteractionStateChanged(
-    InteractionState interaction_state) {
-  if (interaction_state == InteractionState::kActive)
-    return;
-
-  // When the user-facing interaction is dismissed, we instruct the service to
-  // terminate any listening, speaking, or pending query.
-  has_active_interaction_ = false;
-  assistant_->StopActiveInteraction();
-
-  assistant_interaction_model_.ClearInteraction();
-  assistant_interaction_model_.SetInputModality(InputModality::kKeyboard);
-}
-
 void AssistantInteractionController::OnCommittedQueryChanged(
     const AssistantQuery& committed_query) {
   // We clear the interaction when a query is committed, but need to retain
@@ -125,14 +65,35 @@
       /*retain_committed_query=*/true);
 }
 
+void AssistantInteractionController::OnUiVisibilityChanged(
+    bool visible,
+    AssistantSource source) {
+  if (visible) {
+    // TODO(dmblack): When the UI becomes visible, we may need to immediately
+    // start a voice interaction depending on |source| and user preference.
+    if (source == AssistantSource::kStylus)
+      assistant_interaction_model_.SetInputModality(InputModality::kStylus);
+    return;
+  }
+
+  // When the UI is hidden, we need to stop any active interaction. We also
+  // reset the interaction state and restore the default input modality.
+  StopActiveInteraction();
+  assistant_interaction_model_.ClearInteraction();
+  assistant_interaction_model_.SetInputModality(InputModality::kKeyboard);
+}
+
 void AssistantInteractionController::OnHighlighterEnabledChanged(
     HighlighterEnabledState state) {
-  assistant_interaction_model_.SetInputModality(InputModality::kStylus);
-  if (state == HighlighterEnabledState::kEnabled) {
-    assistant_interaction_model_.SetInteractionState(InteractionState::kActive);
-  } else if (state == HighlighterEnabledState::kDisabledByUser) {
-    assistant_interaction_model_.SetInteractionState(
-        InteractionState::kInactive);
+  switch (state) {
+    case HighlighterEnabledState::kEnabled:
+      assistant_interaction_model_.SetInputModality(InputModality::kStylus);
+      break;
+    case HighlighterEnabledState::kDisabledByUser:
+      FALLTHROUGH;
+    case HighlighterEnabledState::kDisabledBySessionEnd:
+      assistant_interaction_model_.SetInputModality(InputModality::kKeyboard);
+      break;
   }
 }
 
@@ -142,27 +103,21 @@
     return;
 
   // When switching to a non-voice input modality we instruct the underlying
-  // service to terminate any listening, speaking, or pending voice query. We do
-  // not do this when switching to voice input modality because initiation of a
-  // voice interaction will automatically interrupt any pre-existing activity.
-  // Stopping the active interaction here for voice input modality would
-  // actually have the undesired effect of stopping the voice interaction.
-  if (assistant_interaction_model_.pending_query().type() ==
-      AssistantQueryType::kVoice) {
-    has_active_interaction_ = false;
-    assistant_->StopActiveInteraction();
-    assistant_interaction_model_.ClearPendingQuery();
-  }
+  // service to terminate any pending query. We do not do this when switching to
+  // voice input modality because initiation of a voice interaction will
+  // automatically interrupt any pre-existing activity. Stopping the active
+  // interaction here for voice input modality would actually have the undesired
+  // effect of stopping the voice interaction.
+  StopActiveInteraction();
 }
 
 void AssistantInteractionController::OnInteractionStarted() {
-  has_active_interaction_ = true;
   assistant_interaction_model_.SetInteractionState(InteractionState::kActive);
 }
 
 void AssistantInteractionController::OnInteractionFinished(
     AssistantInteractionResolution resolution) {
-  has_active_interaction_ = false;
+  assistant_interaction_model_.SetInteractionState(InteractionState::kInactive);
 
   // When a voice query is interrupted we do not receive any follow up speech
   // recognition events but the mic is closed.
@@ -173,8 +128,10 @@
 
 void AssistantInteractionController::OnHtmlResponse(
     const std::string& response) {
-  if (!has_active_interaction_)
+  if (assistant_interaction_model_.interaction_state() !=
+      InteractionState::kActive) {
     return;
+  }
 
   assistant_interaction_model_.AddUiElement(
       std::make_unique<AssistantCardElement>(response));
@@ -192,27 +149,25 @@
   }
 
   // Otherwise, we will submit a simple text query using the suggestion text.
-  const std::string text = suggestion->text;
-
-  assistant_interaction_model_.SetPendingQuery(
-      std::make_unique<AssistantTextQuery>(text));
-  assistant_interaction_model_.CommitPendingQuery();
-
-  assistant_->SendTextQuery(text);
+  StartTextInteraction(suggestion->text);
 }
 
 void AssistantInteractionController::OnSuggestionsResponse(
     std::vector<AssistantSuggestionPtr> response) {
-  if (!has_active_interaction_)
+  if (assistant_interaction_model_.interaction_state() !=
+      InteractionState::kActive) {
     return;
+  }
 
   assistant_interaction_model_.AddSuggestions(std::move(response));
 }
 
 void AssistantInteractionController::OnTextResponse(
     const std::string& response) {
-  if (!has_active_interaction_)
+  if (assistant_interaction_model_.interaction_state() !=
+      InteractionState::kActive) {
     return;
+  }
 
   assistant_interaction_model_.AddUiElement(
       std::make_unique<AssistantTextElement>(response));
@@ -249,8 +204,10 @@
 }
 
 void AssistantInteractionController::OnOpenUrlResponse(const GURL& url) {
-  if (!has_active_interaction_)
+  if (assistant_interaction_model_.interaction_state() !=
+      InteractionState::kActive) {
     return;
+  }
 
   OpenUrl(url);
 }
@@ -266,17 +223,15 @@
     return;
   }
 
-  if (id != DialogPlateButtonId::kVoiceInputToggle) {
+  if (id != DialogPlateButtonId::kVoiceInputToggle)
     return;
-  }
 
   switch (assistant_interaction_model_.mic_state()) {
     case MicState::kClosed:
-      assistant_->StartVoiceInteraction();
+      StartVoiceInteraction();
       break;
     case MicState::kOpen:
-      has_active_interaction_ = false;
-      assistant_->StopActiveInteraction();
+      StopActiveInteraction();
       break;
   }
 }
@@ -288,6 +243,13 @@
   if (text.empty())
     return;
 
+  StartTextInteraction(text);
+}
+
+void AssistantInteractionController::StartTextInteraction(
+    const std::string text) {
+  StopActiveInteraction();
+
   assistant_interaction_model_.SetPendingQuery(
       std::make_unique<AssistantTextQuery>(text));
   assistant_interaction_model_.CommitPendingQuery();
@@ -295,9 +257,32 @@
   assistant_->SendTextQuery(text);
 }
 
+void AssistantInteractionController::StartVoiceInteraction() {
+  StopActiveInteraction();
+
+  assistant_interaction_model_.SetPendingQuery(
+      std::make_unique<AssistantVoiceQuery>());
+
+  assistant_->StartVoiceInteraction();
+}
+
+void AssistantInteractionController::StopActiveInteraction() {
+  // Even though the interaction state will be asynchronously set to inactive
+  // via a call to OnInteractionFinished(Resolution), we explicitly set it to
+  // inactive here to prevent processing any additional UI related service
+  // events belonging to the interaction being stopped.
+  assistant_interaction_model_.SetInteractionState(InteractionState::kInactive);
+  assistant_interaction_model_.ClearPendingQuery();
+  assistant_->StopActiveInteraction();
+}
+
+// TODO(dmblack): Move OpenUrl logic into AssistantController. The interaction
+// sub-controller shouldn't need to talk to the UI controller directly.
 void AssistantInteractionController::OpenUrl(const GURL& url) {
   Shell::Get()->new_window_controller()->NewTabWithUrl(url);
-  StopInteraction();
+
+  if (assistant_ui_controller_)
+    assistant_ui_controller_->HideUi(AssistantSource::kUnspecified);
 }
 
 }  // namespace ash
diff --git a/ash/assistant/assistant_interaction_controller.h b/ash/assistant/assistant_interaction_controller.h
index 5a94297..5b648bd 100644
--- a/ash/assistant/assistant_interaction_controller.h
+++ b/ash/assistant/assistant_interaction_controller.h
@@ -11,6 +11,7 @@
 
 #include "ash/assistant/model/assistant_interaction_model.h"
 #include "ash/assistant/model/assistant_interaction_model_observer.h"
+#include "ash/assistant/model/assistant_ui_model_observer.h"
 #include "ash/assistant/ui/dialog_plate/dialog_plate.h"
 #include "ash/highlighter/highlighter_controller.h"
 #include "ash/public/interfaces/web_contents_manager.mojom.h"
@@ -21,14 +22,12 @@
 namespace ash {
 
 class AssistantInteractionModelObserver;
-
-namespace mojom {
-class AssistantSetup;
-}  // namespace mojom
+class AssistantUiController;
 
 class AssistantInteractionController
     : public chromeos::assistant::mojom::AssistantEventSubscriber,
       public AssistantInteractionModelObserver,
+      public AssistantUiModelObserver,
       public HighlighterController::Observer,
       public DialogPlateDelegate,
       public mojom::ManagedWebContentsOpenUrlDelegate {
@@ -39,14 +38,15 @@
   using AssistantInteractionResolution =
       chromeos::assistant::mojom::AssistantInteractionResolution;
 
-  explicit AssistantInteractionController();
+  AssistantInteractionController();
   ~AssistantInteractionController() override;
 
   // Provides a pointer to the |assistant| owned by AssistantController.
   void SetAssistant(chromeos::assistant::mojom::Assistant* assistant);
 
-  // Provides a pointer to the |assistant_setup| owned by AssistantController.
-  void SetAssistantSetup(mojom::AssistantSetup* assistant_setup);
+  // Provides a pointer to the |assistant_ui_controller| owned by
+  // AssistantController.
+  void SetAssistantUiController(AssistantUiController* assistant_ui_controller);
 
   // Returns a reference to the underlying model.
   const AssistantInteractionModel* model() const {
@@ -57,19 +57,16 @@
   void AddModelObserver(AssistantInteractionModelObserver* observer);
   void RemoveModelObserver(AssistantInteractionModelObserver* observer);
 
-  // Invoke to modify the Assistant interaction state.
-  void StartInteraction();
-  void StopInteraction();
-  void ToggleInteraction();
-
   // Invoked on suggestion chip pressed event.
   void OnSuggestionChipPressed(int id);
 
   // AssistantInteractionModelObserver:
   void OnInputModalityChanged(InputModality input_modality) override;
-  void OnInteractionStateChanged(InteractionState interaction_state) override;
   void OnCommittedQueryChanged(const AssistantQuery& committed_query) override;
 
+  // AssistantUiModelObserver:
+  void OnUiVisibilityChanged(bool visible, AssistantSource source) override;
+
   // HighlighterController::Observer:
   void OnHighlighterEnabledChanged(HighlighterEnabledState state) override;
 
@@ -98,24 +95,23 @@
   void OnDialogPlateContentsCommitted(const std::string& text) override;
 
  private:
+  void StartTextInteraction(const std::string text);
+  void StartVoiceInteraction();
+  void StopActiveInteraction();
+
   void OpenUrl(const GURL& url);
 
+  // Owned by AssistantController.
+  chromeos::assistant::mojom::Assistant* assistant_ = nullptr;
+
+  // Owned by AssisantController.
+  AssistantUiController* assistant_ui_controller_ = nullptr;
+
   mojo::Binding<chromeos::assistant::mojom::AssistantEventSubscriber>
       assistant_event_subscriber_binding_;
 
   AssistantInteractionModel assistant_interaction_model_;
 
-  // Owned by AssistantController.
-  chromeos::assistant::mojom::Assistant* assistant_ = nullptr;
-
-  // Owned by AssistantController.
-  mojom::AssistantSetup* assistant_setup_ = nullptr;
-
-  // Indicates whether or not there is an active interaction in progress. If
-  // there is no active interaction, UI related service events should be
-  // discarded.
-  bool has_active_interaction_;
-
   DISALLOW_COPY_AND_ASSIGN(AssistantInteractionController);
 };
 
diff --git a/ash/assistant/assistant_ui_controller.cc b/ash/assistant/assistant_ui_controller.cc
index 52908a2..3e3f468 100644
--- a/ash/assistant/assistant_ui_controller.cc
+++ b/ash/assistant/assistant_ui_controller.cc
@@ -7,23 +7,70 @@
 #include "ash/assistant/assistant_controller.h"
 #include "ash/assistant/assistant_interaction_controller.h"
 #include "ash/assistant/ui/assistant_container_view.h"
+#include "ash/public/interfaces/assistant_setup.mojom.h"
+#include "ash/shell.h"
+#include "ash/strings/grit/ash_strings.h"
+#include "ash/system/toast/toast_data.h"
+#include "ash/system/toast/toast_manager.h"
+#include "ash/voice_interaction/voice_interaction_controller.h"
 #include "base/optional.h"
+#include "chromeos/services/assistant/public/mojom/assistant.mojom.h"
+#include "ui/base/l10n/l10n_util.h"
 
 namespace ash {
 
+namespace {
+
+// Toast -----------------------------------------------------------------------
+
+constexpr int kToastDurationMs = 2500;
+constexpr char kUnboundServiceToastId[] =
+    "assistant_controller_unbound_service";
+
+void ShowToast(const std::string& id, int message_id) {
+  ToastData toast(id, l10n_util::GetStringUTF16(message_id), kToastDurationMs,
+                  base::nullopt);
+  Shell::Get()->toast_manager()->Show(toast);
+}
+
+}  // namespace
+
+// AssistantUiController -------------------------------------------------------
+
 AssistantUiController::AssistantUiController(
     AssistantController* assistant_controller)
     : assistant_controller_(assistant_controller) {
-  assistant_controller_->interaction_controller()->AddModelObserver(this);
+  Shell::Get()->highlighter_controller()->AddObserver(this);
 }
 
 AssistantUiController::~AssistantUiController() {
-  assistant_controller_->interaction_controller()->RemoveModelObserver(this);
+  Shell::Get()->highlighter_controller()->RemoveObserver(this);
 
   if (container_view_)
     container_view_->GetWidget()->RemoveObserver(this);
 }
 
+void AssistantUiController::SetAssistant(
+    chromeos::assistant::mojom::Assistant* assistant) {
+  assistant_ = assistant;
+}
+
+void AssistantUiController::SetAssistantInteractionController(
+    AssistantInteractionController* assistant_interaction_controller) {
+  if (assistant_interaction_controller_)
+    assistant_interaction_controller_->RemoveModelObserver(this);
+
+  assistant_interaction_controller_ = assistant_interaction_controller;
+
+  if (assistant_interaction_controller_)
+    assistant_interaction_controller_->AddModelObserver(this);
+}
+
+void AssistantUiController::SetAssistantSetup(
+    mojom::AssistantSetup* assistant_setup) {
+  assistant_setup_ = assistant_setup;
+}
+
 void AssistantUiController::AddModelObserver(
     AssistantUiModelObserver* observer) {
   assistant_ui_model_.AddObserver(observer);
@@ -46,13 +93,10 @@
 }
 
 void AssistantUiController::OnWidgetDestroying(views::Widget* widget) {
-  // We need to be sure that the Assistant interaction is stopped when the
-  // widget is closed. Special cases, such as closing the widget via the |ESC|
-  // key might otherwise go unhandled, causing inconsistencies between the
-  // widget visibility state and the underlying interaction model state.
-  // TODO(dmblack): Clean this up. Sibling controllers shouldn't need to
-  // communicate to each other directly in this way.
-  assistant_controller_->interaction_controller()->StopInteraction();
+  // We need to update the model when the widget is destroyed as this may not
+  // have occurred due to a call to HideUi/ToggleUi. This can occur as the
+  // result of pressing the ESC key.
+  assistant_ui_model_.SetVisible(false, AssistantSource::kUnspecified);
 
   container_view_->GetWidget()->RemoveObserver(this);
   container_view_ = nullptr;
@@ -65,14 +109,13 @@
 
 void AssistantUiController::OnInteractionStateChanged(
     InteractionState interaction_state) {
-  switch (interaction_state) {
-    case InteractionState::kActive:
-      Show();
-      break;
-    case InteractionState::kInactive:
-      Dismiss();
-      break;
-  }
+  if (interaction_state != InteractionState::kActive)
+    return;
+
+  // If there is an active interaction, we need to show Assistant UI if it is
+  // not already showing. An interaction can only be started when the Assistant
+  // UI is hidden if the entry point is hotword.
+  ShowUi(AssistantSource::kHotword);
 }
 
 void AssistantUiController::OnMicStateChanged(MicState mic_state) {
@@ -97,21 +140,64 @@
   UpdateUiMode(AssistantUiMode::kWebUi);
 }
 
-bool AssistantUiController::IsVisible() const {
-  return container_view_ && container_view_->GetWidget()->IsVisible();
+void AssistantUiController::OnHighlighterEnabledChanged(
+    HighlighterEnabledState state) {
+  switch (state) {
+    case HighlighterEnabledState::kEnabled:
+      if (!assistant_ui_model_.visible())
+        ShowUi(AssistantSource::kStylus);
+      break;
+    case HighlighterEnabledState::kDisabledByUser:
+      if (assistant_ui_model_.visible())
+        HideUi(AssistantSource::kStylus);
+      break;
+    case HighlighterEnabledState::kDisabledBySessionEnd:
+      // No action necessary.
+      break;
+  }
 }
 
-void AssistantUiController::Show() {
+void AssistantUiController::ShowUi(AssistantSource source) {
+  if (!Shell::Get()->voice_interaction_controller()->setup_completed()) {
+    assistant_setup_->StartAssistantOptInFlow();
+    return;
+  }
+
+  if (!Shell::Get()->voice_interaction_controller()->settings_enabled())
+    return;
+
+  if (!assistant_) {
+    ShowToast(kUnboundServiceToastId, IDS_ASH_ASSISTANT_ERROR_GENERIC);
+    return;
+  }
+
+  if (assistant_ui_model_.visible())
+    return;
+
   if (!container_view_) {
     container_view_ = new AssistantContainerView(assistant_controller_);
     container_view_->GetWidget()->AddObserver(this);
   }
+
   container_view_->GetWidget()->Show();
+  assistant_ui_model_.SetVisible(true, source);
 }
 
-void AssistantUiController::Dismiss() {
+void AssistantUiController::HideUi(AssistantSource source) {
+  if (!assistant_ui_model_.visible())
+    return;
+
   if (container_view_)
     container_view_->GetWidget()->Hide();
+
+  assistant_ui_model_.SetVisible(false, source);
+}
+
+void AssistantUiController::ToggleUi(AssistantSource source) {
+  if (assistant_ui_model_.visible())
+    HideUi(source);
+  else
+    ShowUi(source);
 }
 
 void AssistantUiController::UpdateUiMode(
@@ -123,29 +209,13 @@
     return;
   }
 
-  // When Assistant UI is not visible, we should reset to main UI mode.
-  if (!IsVisible()) {
-    assistant_ui_model_.SetUiMode(AssistantUiMode::kMainUi);
-    return;
-  }
-
-  const AssistantInteractionModel* interaction_model =
-      assistant_controller_->interaction_controller()->model();
-
-  // When the mic is open, we should be in main UI mode.
-  if (interaction_model->mic_state() == MicState::kOpen) {
-    assistant_ui_model_.SetUiMode(AssistantUiMode::kMainUi);
-    return;
-  }
-
   // When stylus input modality is selected, we should be in mini UI mode.
-  if (interaction_model->input_modality() == InputModality::kStylus) {
-    assistant_ui_model_.SetUiMode(AssistantUiMode::kMiniUi);
-    return;
-  }
-
-  // By default, we will fall back to main UI mode.
-  assistant_ui_model_.SetUiMode(AssistantUiMode::kMainUi);
+  // Otherwise we fall back to main UI mode.
+  assistant_ui_model_.SetUiMode(
+      assistant_interaction_controller_->model()->input_modality() ==
+              InputModality::kStylus
+          ? AssistantUiMode::kMiniUi
+          : AssistantUiMode::kMainUi);
 }
 
 }  // namespace ash
diff --git a/ash/assistant/assistant_ui_controller.h b/ash/assistant/assistant_ui_controller.h
index c2c08c0..bfad506 100644
--- a/ash/assistant/assistant_ui_controller.h
+++ b/ash/assistant/assistant_ui_controller.h
@@ -10,9 +10,18 @@
 #include "ash/assistant/model/assistant_ui_model.h"
 #include "ash/assistant/ui/caption_bar.h"
 #include "ash/assistant/ui/dialog_plate/dialog_plate.h"
+#include "ash/highlighter/highlighter_controller.h"
 #include "base/macros.h"
 #include "ui/views/widget/widget_observer.h"
 
+namespace chromeos {
+namespace assistant {
+namespace mojom {
+class Assistant;
+}  // namespace mojom
+}  // namespace assistant
+}  // namespace chromeos
+
 namespace views {
 class Widget;
 }  // namespace views
@@ -21,16 +30,33 @@
 
 class AssistantContainerView;
 class AssistantController;
+class AssistantInteractionController;
+
+namespace mojom {
+class AssistantSetup;
+}  // namespace mojom
 
 class ASH_EXPORT AssistantUiController
     : public views::WidgetObserver,
       public AssistantInteractionModelObserver,
       public CaptionBarDelegate,
-      public DialogPlateDelegate {
+      public DialogPlateDelegate,
+      public HighlighterController::Observer {
  public:
   explicit AssistantUiController(AssistantController* assistant_controller);
   ~AssistantUiController() override;
 
+  // Provides a pointer to the |assistant| owned by AssistantController.
+  void SetAssistant(chromeos::assistant::mojom::Assistant* assistant);
+
+  // Provides a pointer to the |assistant_interaction_controller| owned by
+  // AssistantController.
+  void SetAssistantInteractionController(
+      AssistantInteractionController* assistant_interaction_controller);
+
+  // Provides a pointer to the |assistant_setup| owned by AssistantController.
+  void SetAssistantSetup(mojom::AssistantSetup* assistant_setup);
+
   // Returns the underlying model.
   const AssistantUiModel* model() const { return &assistant_ui_model_; }
 
@@ -54,19 +80,29 @@
   // DialogPlateDelegate:
   void OnDialogPlateButtonPressed(DialogPlateButtonId id) override;
 
-  // Returns true if assistant bubble is visible, otherwise false.
-  bool IsVisible() const;
+  // HighlighterController::Observer:
+  void OnHighlighterEnabledChanged(HighlighterEnabledState state) override;
+
+  void ShowUi(AssistantSource source);
+  void HideUi(AssistantSource source);
+  void ToggleUi(AssistantSource source);
 
  private:
-  void Show();
-  void Dismiss();
-
   // Updates UI mode to |ui_mode| if specified. Otherwise UI mode is updated on
   // the basis of interaction/widget visibility state.
   void UpdateUiMode(base::Optional<AssistantUiMode> ui_mode = base::nullopt);
 
   AssistantController* const assistant_controller_;  // Owned by Shell.
 
+  // Owned by AssistantController.
+  chromeos::assistant::mojom::Assistant* assistant_ = nullptr;
+
+  // Owned by AssistantController.
+  AssistantInteractionController* assistant_interaction_controller_ = nullptr;
+
+  // Owned by AssistantController.
+  mojom::AssistantSetup* assistant_setup_ = nullptr;
+
   AssistantUiModel assistant_ui_model_;
 
   AssistantContainerView* container_view_ =
diff --git a/ash/assistant/model/assistant_ui_model.cc b/ash/assistant/model/assistant_ui_model.cc
index a1ff517..5db2388 100644
--- a/ash/assistant/model/assistant_ui_model.cc
+++ b/ash/assistant/model/assistant_ui_model.cc
@@ -28,9 +28,22 @@
   NotifyUiModeChanged();
 }
 
+void AssistantUiModel::SetVisible(bool visible, AssistantSource source) {
+  if (visible == visible_)
+    return;
+
+  visible_ = visible;
+  NotifyUiVisibilityChanged(source);
+}
+
 void AssistantUiModel::NotifyUiModeChanged() {
   for (AssistantUiModelObserver& observer : observers_)
     observer.OnUiModeChanged(ui_mode_);
 }
 
+void AssistantUiModel::NotifyUiVisibilityChanged(AssistantSource source) {
+  for (AssistantUiModelObserver& observer : observers_)
+    observer.OnUiVisibilityChanged(visible_, source);
+}
+
 }  // namespace ash
diff --git a/ash/assistant/model/assistant_ui_model.h b/ash/assistant/model/assistant_ui_model.h
index 7501f33..d9a7c0e4 100644
--- a/ash/assistant/model/assistant_ui_model.h
+++ b/ash/assistant/model/assistant_ui_model.h
@@ -12,6 +12,15 @@
 
 class AssistantUiModelObserver;
 
+// Enumeration of Assistant entry/exit points.
+enum class AssistantSource {
+  kUnspecified,
+  kHotkey,
+  kHotword,
+  kLongPressLauncher,
+  kStylus,
+};
+
 // Enumeration of Assistant UI modes.
 enum class AssistantUiMode {
   kMainUi,
@@ -35,11 +44,19 @@
   // Returns the UI mode.
   AssistantUiMode ui_mode() const { return ui_mode_; }
 
+  // Sets the UI visibility.
+  void SetVisible(bool visible, AssistantSource source);
+
+  bool visible() const { return visible_; }
+
  private:
   void NotifyUiModeChanged();
+  void NotifyUiVisibilityChanged(AssistantSource source);
 
   AssistantUiMode ui_mode_ = AssistantUiMode::kMainUi;
 
+  bool visible_ = false;
+
   base::ObserverList<AssistantUiModelObserver> observers_;
 
   DISALLOW_COPY_AND_ASSIGN(AssistantUiModel);
diff --git a/ash/assistant/model/assistant_ui_model_observer.h b/ash/assistant/model/assistant_ui_model_observer.h
index 91cd81c0..5cb020b 100644
--- a/ash/assistant/model/assistant_ui_model_observer.h
+++ b/ash/assistant/model/assistant_ui_model_observer.h
@@ -9,6 +9,7 @@
 
 namespace ash {
 
+enum class AssistantSource;
 enum class AssistantUiMode;
 
 // An observer which receives notification of changes to the Assistant UI model.
@@ -17,6 +18,10 @@
   // Invoked when the UI mode is changed.
   virtual void OnUiModeChanged(AssistantUiMode ui_mode) {}
 
+  // Invoked when the UI visibility is changed. The |source| of the visibility
+  // change event is provided for interested observers.
+  virtual void OnUiVisibilityChanged(bool visible, AssistantSource source) {}
+
  protected:
   AssistantUiModelObserver() = default;
   virtual ~AssistantUiModelObserver() = default;
diff --git a/ash/assistant/ui/assistant_main_view.cc b/ash/assistant/ui/assistant_main_view.cc
index 5a49c12..ecef14cf 100644
--- a/ash/assistant/ui/assistant_main_view.cc
+++ b/ash/assistant/ui/assistant_main_view.cc
@@ -7,7 +7,6 @@
 #include <memory>
 
 #include "ash/assistant/assistant_controller.h"
-#include "ash/assistant/assistant_interaction_controller.h"
 #include "ash/assistant/assistant_ui_controller.h"
 #include "ash/assistant/model/assistant_interaction_model.h"
 #include "ash/assistant/ui/assistant_ui_constants.h"
@@ -34,12 +33,13 @@
   caption_bar_->set_delegate(assistant_controller_->ui_controller());
   dialog_plate_->set_delegate(assistant_controller_);
 
-  // Observe changes to interaction model.
-  assistant_controller_->interaction_controller()->AddModelObserver(this);
+  // The AssistantController indirectly owns the view hierarchy to which
+  // AssistantMainView belongs so is guaranteed to outlive it.
+  assistant_controller_->ui_controller()->AddModelObserver(this);
 }
 
 AssistantMainView::~AssistantMainView() {
-  assistant_controller_->interaction_controller()->RemoveModelObserver(this);
+  assistant_controller_->ui_controller()->RemoveModelObserver(this);
 }
 
 gfx::Size AssistantMainView::CalculatePreferredSize() const {
@@ -92,9 +92,9 @@
   AddChildView(dialog_plate_);
 }
 
-void AssistantMainView::OnInteractionStateChanged(
-    InteractionState interaction_state) {
-  if (interaction_state != InteractionState::kInactive)
+void AssistantMainView::OnUiVisibilityChanged(bool visible,
+                                              AssistantSource source) {
+  if (visible)
     return;
 
   // When the Assistant UI is being hidden we need to reset our minimum height
diff --git a/ash/assistant/ui/assistant_main_view.h b/ash/assistant/ui/assistant_main_view.h
index bb5b237..35e94a1 100644
--- a/ash/assistant/ui/assistant_main_view.h
+++ b/ash/assistant/ui/assistant_main_view.h
@@ -5,7 +5,7 @@
 #ifndef ASH_ASSISTANT_UI_ASSISTANT_MAIN_VIEW_H_
 #define ASH_ASSISTANT_UI_ASSISTANT_MAIN_VIEW_H_
 
-#include "ash/assistant/model/assistant_interaction_model_observer.h"
+#include "ash/assistant/model/assistant_ui_model_observer.h"
 #include "base/macros.h"
 #include "ui/views/view.h"
 
@@ -16,8 +16,7 @@
 class CaptionBar;
 class DialogPlate;
 
-class AssistantMainView : public views::View,
-                          public AssistantInteractionModelObserver {
+class AssistantMainView : public views::View, public AssistantUiModelObserver {
  public:
   explicit AssistantMainView(AssistantController* assistant_controller);
   ~AssistantMainView() override;
@@ -29,8 +28,8 @@
   void OnBoundsChanged(const gfx::Rect& prev_bounds) override;
   void RequestFocus() override;
 
-  // AssistantInteractionModelObserver:
-  void OnInteractionStateChanged(InteractionState interaction_state) override;
+  // AssistantUiModelObserver:
+  void OnUiVisibilityChanged(bool visible, AssistantSource source) override;
 
  private:
   void InitLayout();
diff --git a/ash/assistant/ui/dialog_plate/dialog_plate.cc b/ash/assistant/ui/dialog_plate/dialog_plate.cc
index d9a6627..90aeb47 100644
--- a/ash/assistant/ui/dialog_plate/dialog_plate.cc
+++ b/ash/assistant/ui/dialog_plate/dialog_plate.cc
@@ -8,6 +8,7 @@
 
 #include "ash/assistant/assistant_controller.h"
 #include "ash/assistant/assistant_interaction_controller.h"
+#include "ash/assistant/assistant_ui_controller.h"
 #include "ash/assistant/ui/assistant_ui_constants.h"
 #include "ash/public/cpp/vector_icons/vector_icons.h"
 #include "ash/resources/vector_icons/vector_icons.h"
@@ -57,9 +58,11 @@
   // The Assistant controller indirectly owns the view hierarchy to which
   // DialogPlate belongs so is guaranteed to outlive it.
   assistant_controller_->interaction_controller()->AddModelObserver(this);
+  assistant_controller_->ui_controller()->AddModelObserver(this);
 }
 
 DialogPlate::~DialogPlate() {
+  assistant_controller_->ui_controller()->RemoveModelObserver(this);
   assistant_controller_->interaction_controller()->RemoveModelObserver(this);
 }
 
@@ -220,11 +223,10 @@
   }
 }
 
-void DialogPlate::OnInteractionStateChanged(
-    InteractionState interaction_state) {
-  // When the Assistant interaction becomes inactive we need to clear the
-  // dialog plate so that text does not persist across Assistant entries.
-  if (interaction_state == InteractionState::kInactive)
+void DialogPlate::OnUiVisibilityChanged(bool visible, AssistantSource source) {
+  // When the Assistant UI is hidden we need to clear the dialog plate so that
+  // text does not persist across Assistant entries.
+  if (!visible)
     textfield_->SetText(base::string16());
 }
 
diff --git a/ash/assistant/ui/dialog_plate/dialog_plate.h b/ash/assistant/ui/dialog_plate/dialog_plate.h
index 81c9214..4f7c3e9 100644
--- a/ash/assistant/ui/dialog_plate/dialog_plate.h
+++ b/ash/assistant/ui/dialog_plate/dialog_plate.h
@@ -8,6 +8,7 @@
 #include <string>
 
 #include "ash/assistant/model/assistant_interaction_model_observer.h"
+#include "ash/assistant/model/assistant_ui_model_observer.h"
 #include "ash/assistant/ui/dialog_plate/action_view.h"
 #include "base/macros.h"
 #include "ui/views/controls/button/button.h"
@@ -55,6 +56,7 @@
                     public views::TextfieldController,
                     public ActionViewListener,
                     public AssistantInteractionModelObserver,
+                    public AssistantUiModelObserver,
                     public views::ButtonListener {
  public:
   explicit DialogPlate(AssistantController* assistant_controller);
@@ -79,7 +81,9 @@
 
   // AssistantInteractionModelObserver:
   void OnInputModalityChanged(InputModality input_modality) override;
-  void OnInteractionStateChanged(InteractionState interaction_state) override;
+
+  // AssistantUiModelObserver:
+  void OnUiVisibilityChanged(bool visible, AssistantSource source) override;
 
   void set_delegate(DialogPlateDelegate* delegate) { delegate_ = delegate; }
 
diff --git a/ash/assistant/ui/main_stage/assistant_header_view.cc b/ash/assistant/ui/main_stage/assistant_header_view.cc
index 261df7f..4de12ba6 100644
--- a/ash/assistant/ui/main_stage/assistant_header_view.cc
+++ b/ash/assistant/ui/main_stage/assistant_header_view.cc
@@ -8,6 +8,7 @@
 
 #include "ash/assistant/assistant_controller.h"
 #include "ash/assistant/assistant_interaction_controller.h"
+#include "ash/assistant/assistant_ui_controller.h"
 #include "ash/assistant/model/assistant_interaction_model.h"
 #include "ash/assistant/model/assistant_query.h"
 #include "ash/assistant/ui/assistant_ui_constants.h"
@@ -37,9 +38,11 @@
   // The Assistant controller indirectly owns the view hierarchy to which
   // AssistantHeaderView belongs so is guaranteed to outlive it.
   assistant_controller_->interaction_controller()->AddModelObserver(this);
+  assistant_controller_->ui_controller()->AddModelObserver(this);
 }
 
 AssistantHeaderView::~AssistantHeaderView() {
+  assistant_controller_->ui_controller()->RemoveModelObserver(this);
   assistant_controller_->interaction_controller()->RemoveModelObserver(this);
 }
 
@@ -90,17 +93,16 @@
   AddChildView(label_);
 }
 
-void AssistantHeaderView::OnInteractionStateChanged(
-    InteractionState interaction_state) {
-  if (interaction_state != InteractionState::kInactive)
-    return;
-
-  label_->SetVisible(true);
-}
-
 void AssistantHeaderView::OnCommittedQueryChanged(
     const AssistantQuery& committed_query) {
   label_->SetVisible(false);
 }
 
+void AssistantHeaderView::OnUiVisibilityChanged(bool visible,
+                                                AssistantSource source) {
+  // When Assistant UI is being hidden, we need to restore default view state.
+  if (!visible)
+    label_->SetVisible(true);
+}
+
 }  // namespace ash
diff --git a/ash/assistant/ui/main_stage/assistant_header_view.h b/ash/assistant/ui/main_stage/assistant_header_view.h
index 2332d7d..e0d2562 100644
--- a/ash/assistant/ui/main_stage/assistant_header_view.h
+++ b/ash/assistant/ui/main_stage/assistant_header_view.h
@@ -6,6 +6,7 @@
 #define ASH_ASSISTANT_UI_MAIN_STAGE_ASSISTANT_HEADER_VIEW_H_
 
 #include "ash/assistant/model/assistant_interaction_model_observer.h"
+#include "ash/assistant/model/assistant_ui_model_observer.h"
 #include "base/macros.h"
 #include "ui/views/view.h"
 
@@ -21,7 +22,8 @@
 // AssistantHeaderView is the child of UiElementContainerView which provides
 // the Assistant icon. On first launch, it also displays a greeting to the user.
 class AssistantHeaderView : public views::View,
-                            public AssistantInteractionModelObserver {
+                            public AssistantInteractionModelObserver,
+                            public AssistantUiModelObserver {
  public:
   explicit AssistantHeaderView(AssistantController* assistant_controller);
   ~AssistantHeaderView() override;
@@ -32,9 +34,11 @@
   void ChildVisibilityChanged(views::View* child) override;
 
   // AssistantInteractionModelObserver:
-  void OnInteractionStateChanged(InteractionState interaction_state) override;
   void OnCommittedQueryChanged(const AssistantQuery& committed_query) override;
 
+  // AssistantUiModelObserver:
+  void OnUiVisibilityChanged(bool visible, AssistantSource source) override;
+
  private:
   void InitLayout();
 
diff --git a/ash/display/cursor_window_controller.cc b/ash/display/cursor_window_controller.cc
index b028491a..fda1aae 100644
--- a/ash/display/cursor_window_controller.cc
+++ b/ash/display/cursor_window_controller.cc
@@ -160,7 +160,8 @@
         shell->display_color_manager()->displays_ctm_support();
     UMA_HISTOGRAM_ENUMERATION("Ash.NightLight.DisplayCrtcCtmSupport",
                               displays_ctm_support);
-    return displays_ctm_support != DisplayColorManager::DisplayCtmSupport::kAll;
+    if (displays_ctm_support != DisplayColorManager::DisplayCtmSupport::kAll)
+      return true;
   }
 
   return prefs->GetBoolean(prefs::kAccessibilityLargeCursorEnabled) ||
diff --git a/ash/login/ui/login_auth_user_view.cc b/ash/login/ui/login_auth_user_view.cc
index 97370b3..dc4b37a6 100644
--- a/ash/login/ui/login_auth_user_view.cc
+++ b/ash/login/ui/login_auth_user_view.cc
@@ -448,14 +448,15 @@
   bool has_tap = HasAuthMethod(AUTH_TAP);
   bool force_online_sign_in = HasAuthMethod(AUTH_ONLINE_SIGN_IN);
   bool has_fingerprint = HasAuthMethod(AUTH_FINGERPRINT);
-  bool disabled_auth = HasAuthMethod(AUTH_DISABLED);
+  bool auth_disabled = HasAuthMethod(AUTH_DISABLED);
+  bool hide_auth = auth_disabled || force_online_sign_in;
 
   online_sign_in_message_->SetVisible(force_online_sign_in);
-  disabled_auth_message_->SetVisible(disabled_auth);
+  disabled_auth_message_->SetVisible(auth_disabled);
 
   password_view_->SetEnabled(has_password);
   password_view_->SetFocusEnabledForChildViews(has_password);
-  password_view_->SetVisible(!force_online_sign_in && !disabled_auth);
+  password_view_->SetVisible(!hide_auth);
   password_view_->layer()->SetOpacity(has_password ? 1 : 0);
 
   if (!had_password && has_password)
@@ -479,9 +480,10 @@
   // Only the active auth user view has a password displayed. If that is the
   // case, then render the user view as if it was always focused, since clicking
   // on it will not do anything (such as swapping users).
-  user_view_->SetForceOpaque(has_password || force_online_sign_in ||
-                             disabled_auth);
+  user_view_->SetForceOpaque(has_password || hide_auth);
   user_view_->SetTapEnabled(!has_password);
+  if (hide_auth)
+    user_view_->RequestFocus();
 
   PreferredSizeChanged();
 }
diff --git a/ash/login/ui/login_user_view.cc b/ash/login/ui/login_user_view.cc
index dfefbbf..909c459 100644
--- a/ash/login/ui/login_user_view.cc
+++ b/ash/login/ui/login_user_view.cc
@@ -490,6 +490,10 @@
   tap_button_->SetBoundsRect(GetLocalBounds());
 }
 
+void LoginUserView::RequestFocus() {
+  tap_button_->RequestFocus();
+}
+
 void LoginUserView::ButtonPressed(views::Button* sender,
                                   const ui::Event& event) {
   // Handle click on the dropdown arrow.
diff --git a/ash/login/ui/login_user_view.h b/ash/login/ui/login_user_view.h
index 70010c87..b6b4e60 100644
--- a/ash/login/ui/login_user_view.h
+++ b/ash/login/ui/login_user_view.h
@@ -76,6 +76,7 @@
   const char* GetClassName() const override;
   gfx::Size CalculatePreferredSize() const override;
   void Layout() override;
+  void RequestFocus() override;
 
   // views::ButtonListener:
   void ButtonPressed(views::Button* sender, const ui::Event& event) override;
diff --git a/ash/public/interfaces/voice_interaction_controller.mojom b/ash/public/interfaces/voice_interaction_controller.mojom
index 56c73f8..04cada3 100644
--- a/ash/public/interfaces/voice_interaction_controller.mojom
+++ b/ash/public/interfaces/voice_interaction_controller.mojom
@@ -43,6 +43,25 @@
   DISALLOWED_BY_INCOGNITO
 };
 
+// Allows observing changes to voice interaction status and settings.
+interface VoiceInteractionObserver {
+  // Called when voice interaction session state changes.
+  OnVoiceInteractionStatusChanged(VoiceInteractionState state);
+
+  // Called when voice interaction is enabled/disabled in settings.
+  OnVoiceInteractionSettingsEnabled(bool enabled);
+
+  // Called when voice interaction service is allowed/disallowed to access
+  // the "context" (text and graphic content that is currently on screen).
+  OnVoiceInteractionContextEnabled(bool enabled);
+
+  // Called when voice interaction setup flow completed.
+  OnVoiceInteractionSetupCompleted(bool completed);
+
+  // Called when assistant feature allowed state has changed.
+  OnAssistantFeatureAllowedChanged(AssistantAllowedState state);
+};
+
 // Interface for ash client (Chrome) to connect to the voice interaction
 // controller, which notifies changes of voice interaction related flags.
 interface VoiceInteractionController {
@@ -63,4 +82,10 @@
   // Notify if voice interaction feature is allowed or not. e.g. not allowed
   // if disabled by policy.
   NotifyFeatureAllowed(AssistantAllowedState state);
+
+  // Return if the voice interaction setting is enabled/disabled.
+  IsSettingEnabled() => (bool enabled);
+
+  // Return the voice interaction setup complete status.
+  IsSetupCompleted() => (bool completed);
 };
diff --git a/ash/shelf/app_list_button.cc b/ash/shelf/app_list_button.cc
index 4ca6fce..7478322f 100644
--- a/ash/shelf/app_list_button.cc
+++ b/ash/shelf/app_list_button.cc
@@ -10,7 +10,8 @@
 
 #include "ash/app_list/app_list_controller_impl.h"
 #include "ash/assistant/assistant_controller.h"
-#include "ash/assistant/assistant_interaction_controller.h"
+#include "ash/assistant/assistant_ui_controller.h"
+#include "ash/assistant/model/assistant_ui_model.h"
 #include "ash/public/cpp/shelf_types.h"
 #include "ash/session/session_controller.h"
 #include "ash/shelf/assistant_overlay.h"
@@ -60,13 +61,18 @@
     : views::ImageButton(nullptr),
       listener_(listener),
       shelf_view_(shelf_view),
-      shelf_(shelf) {
+      shelf_(shelf),
+      voice_interaction_binding_(this) {
   DCHECK(listener_);
   DCHECK(shelf_view_);
   DCHECK(shelf_);
   Shell::Get()->AddShellObserver(this);
   Shell::Get()->session_controller()->AddObserver(this);
-  Shell::Get()->voice_interaction_controller()->AddObserver(this);
+
+  mojom::VoiceInteractionObserverPtr ptr;
+  voice_interaction_binding_.Bind(mojo::MakeRequest(&ptr));
+  Shell::Get()->voice_interaction_controller()->AddVoiceInteractionObserver(
+      std::move(ptr));
   SetInkDropMode(InkDropMode::ON_NO_GESTURE_HANDLER);
   set_ink_drop_base_color(kShelfInkDropBaseColor);
   set_ink_drop_visible_opacity(kShelfInkDropVisibleOpacity);
@@ -86,7 +92,6 @@
 }
 
 AppListButton::~AppListButton() {
-  Shell::Get()->voice_interaction_controller()->RemoveObserver(this);
   Shell::Get()->RemoveShellObserver(this);
   Shell::Get()->session_controller()->RemoveObserver(this);
 }
@@ -138,10 +143,8 @@
         assistant_overlay_->BurstAnimation();
         event->SetHandled();
         if (chromeos::switches::IsAssistantEnabled()) {
-          Shell::Get()
-              ->assistant_controller()
-              ->interaction_controller()
-              ->StartInteraction();
+          Shell::Get()->assistant_controller()->ui_controller()->ShowUi(
+              AssistantSource::kLongPressLauncher);
         } else {
           Shell::Get()->app_list_controller()->StartVoiceInteractionSession();
         }
diff --git a/ash/shelf/app_list_button.h b/ash/shelf/app_list_button.h
index c79c6df..d3efb8d 100644
--- a/ash/shelf/app_list_button.h
+++ b/ash/shelf/app_list_button.h
@@ -8,10 +8,11 @@
 #include <memory>
 
 #include "ash/ash_export.h"
+#include "ash/public/interfaces/voice_interaction_controller.mojom.h"
 #include "ash/session/session_observer.h"
 #include "ash/shell_observer.h"
-#include "ash/voice_interaction/voice_interaction_observer.h"
 #include "base/macros.h"
+#include "mojo/public/cpp/bindings/binding.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "ui/views/controls/button/image_button.h"
 
@@ -30,7 +31,7 @@
 class ASH_EXPORT AppListButton : public views::ImageButton,
                                  public ShellObserver,
                                  public SessionObserver,
-                                 public VoiceInteractionObserver {
+                                 public mojom::VoiceInteractionObserver {
  public:
   AppListButton(InkDropButtonListener* listener,
                 ShelfView* shelf_view,
@@ -68,11 +69,14 @@
   void OnAppListVisibilityChanged(bool shown,
                                   aura::Window* root_window) override;
 
-  // VoiceInteractionObserver:
+  // mojom::VoiceInteractionObserver:
   void OnVoiceInteractionStatusChanged(
       mojom::VoiceInteractionState state) override;
   void OnVoiceInteractionSettingsEnabled(bool enabled) override;
+  void OnVoiceInteractionContextEnabled(bool enabled) override {}
   void OnVoiceInteractionSetupCompleted(bool completed) override;
+  void OnAssistantFeatureAllowedChanged(
+      mojom::AssistantAllowedState state) override {}
 
   // SessionObserver:
   void OnActiveUserSessionChanged(const AccountId& account_id) override;
@@ -99,6 +103,8 @@
   std::unique_ptr<base::OneShotTimer> assistant_animation_hide_delay_timer_;
   base::TimeTicks voice_interaction_start_timestamp_;
 
+  mojo::Binding<mojom::VoiceInteractionObserver> voice_interaction_binding_;
+
   DISALLOW_COPY_AND_ASSIGN(AppListButton);
 };
 
diff --git a/ash/shelf/shelf_menu_model_adapter.cc b/ash/shelf/shelf_menu_model_adapter.cc
index 88b08d1..13c70b9 100644
--- a/ash/shelf/shelf_menu_model_adapter.cc
+++ b/ash/shelf/shelf_menu_model_adapter.cc
@@ -23,7 +23,7 @@
 
 ShelfMenuModelAdapter::~ShelfMenuModelAdapter() = default;
 
-void ShelfMenuModelAdapter::RecordHistogram() {
+void ShelfMenuModelAdapter::RecordHistogramOnMenuClosed() {
   base::TimeDelta user_journey_time = base::TimeTicks::Now() - menu_open_time();
   // If the menu is for a ShelfButton.
   if (!app_id().empty()) {
diff --git a/ash/shelf/shelf_menu_model_adapter.h b/ash/shelf/shelf_menu_model_adapter.h
index 648b7d4..e1c1b3991 100644
--- a/ash/shelf/shelf_menu_model_adapter.h
+++ b/ash/shelf/shelf_menu_model_adapter.h
@@ -22,7 +22,7 @@
   ~ShelfMenuModelAdapter() override;
 
   // Overridden from AppMenuModelAdapter:
-  void RecordHistogram() override;
+  void RecordHistogramOnMenuClosed() override;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(ShelfMenuModelAdapter);
diff --git a/ash/shelf/shelf_view.cc b/ash/shelf/shelf_view.cc
index ba65071..7a68efa 100644
--- a/ash/shelf/shelf_view.cc
+++ b/ash/shelf/shelf_view.cc
@@ -90,15 +90,6 @@
              ->tablet_mode_controller()
              ->IsTabletModeWindowManagerEnabled();
 }
-// The UMA histogram that logs the commands which are executed on non-app
-// context menus.
-constexpr char kNonAppContextMenuExecuteCommand[] =
-    "Apps.ContextMenuExecuteCommand.NotFromApp";
-
-// The UMA histogram that logs the commands which are executed on app context
-// menus.
-constexpr char kAppContextMenuExecuteCommand[] =
-    "Apps.ContextMenuExecuteCommand.FromApp";
 
 // A class to temporarily disable a given bounds animator.
 class BoundsAnimatorDisabler {
@@ -1941,9 +1932,6 @@
       std::make_unique<ShelfContextMenuModel>(
           std::move(menu_items), model_->GetShelfItemDelegate(shelf_id),
           display_id);
-  menu_model->set_histogram_name(ShelfItemForView(source)
-                                     ? kAppContextMenuExecuteCommand
-                                     : kNonAppContextMenuExecuteCommand);
   ShowMenu(std::move(menu_model), source, point, true /* context_menu */,
            source_type);
 }
@@ -1959,7 +1947,6 @@
     std::unique_ptr<ShelfContextMenuModel> menu_model =
         std::make_unique<ShelfContextMenuModel>(
             std::vector<mojom::MenuItemPtr>(), nullptr, display_id);
-    menu_model->set_histogram_name(kNonAppContextMenuExecuteCommand);
     ShowMenu(std::move(menu_model), source, point, true, source_type);
     return;
   }
diff --git a/ash/shell_port_mash.h b/ash/shell_port_mash.h
index b7a007a..cb32283a 100644
--- a/ash/shell_port_mash.h
+++ b/ash/shell_port_mash.h
@@ -25,6 +25,7 @@
 class WindowManager;
 
 // ShellPort implementation for mash. See ash/README.md for more.
+// NOTE: this is also used for OopAsh.
 class ShellPortMash : public ShellPort {
  public:
   ShellPortMash(WindowManager* window_manager,
diff --git a/ash/system/night_light/night_light_controller_unittest.cc b/ash/system/night_light/night_light_controller_unittest.cc
index f0813d8..a767245 100644
--- a/ash/system/night_light/night_light_controller_unittest.cc
+++ b/ash/system/night_light/night_light_controller_unittest.cc
@@ -929,6 +929,22 @@
   logger_actions = GetLoggerActionsAndClear();
   EXPECT_TRUE(VerifyCrtcMatrix(kId1, temperature, logger_actions));
   EXPECT_TRUE(VerifyCrtcMatrix(kId2, temperature, logger_actions));
+
+  // Test the cursor compositing behavior when Night Light is on (and doesn't
+  // require the software cursor) while other accessibility settings that affect
+  // the cursor are toggled.
+  for (const auto* const pref : {prefs::kAccessibilityLargeCursorEnabled,
+                                 prefs::kAccessibilityHighContrastEnabled}) {
+    user1_pref_service()->SetBoolean(pref, true);
+    Shell::Get()->UpdateCursorCompositingEnabled();
+    EXPECT_TRUE(IsCursorCompositingEnabled());
+
+    // Disabling the accessibility feature should revert back to the hardware
+    // cursor.
+    user1_pref_service()->SetBoolean(pref, false);
+    Shell::Get()->UpdateCursorCompositingEnabled();
+    EXPECT_FALSE(IsCursorCompositingEnabled());
+  }
 }
 
 // One display supports CRTC matrix and the other doesn't.
diff --git a/ash/system/palette/palette_tray_unittest.cc b/ash/system/palette/palette_tray_unittest.cc
index ff30eab..41bf40f 100644
--- a/ash/system/palette/palette_tray_unittest.cc
+++ b/ash/system/palette/palette_tray_unittest.cc
@@ -333,6 +333,7 @@
       mojom::VoiceInteractionState::RUNNING);
   Shell::Get()->voice_interaction_controller()->NotifySettingsEnabled(true);
   Shell::Get()->voice_interaction_controller()->NotifyContextEnabled(true);
+  Shell::Get()->voice_interaction_controller()->FlushForTesting();
 
   ui::test::EventGenerator& generator = GetEventGenerator();
   generator.EnterPenPointerMode();
@@ -395,6 +396,7 @@
   // tool.
   test_api_->palette_tool_manager()->ActivateTool(PaletteToolId::METALAYER);
   Shell::Get()->voice_interaction_controller()->NotifyContextEnabled(false);
+  Shell::Get()->voice_interaction_controller()->FlushForTesting();
   EXPECT_FALSE(metalayer_enabled());
 
   // With the metalayer disabled again, press/drag does not activate the
@@ -410,6 +412,7 @@
       mojom::VoiceInteractionState::NOT_READY);
   Shell::Get()->voice_interaction_controller()->NotifySettingsEnabled(false);
   Shell::Get()->voice_interaction_controller()->NotifyContextEnabled(false);
+  Shell::Get()->voice_interaction_controller()->FlushForTesting();
 
   ui::test::EventGenerator& generator = GetEventGenerator();
   generator.EnterPenPointerMode();
@@ -430,12 +433,14 @@
 
   // Enable one of the two user prefs, should not be sufficient.
   Shell::Get()->voice_interaction_controller()->NotifyContextEnabled(true);
+  Shell::Get()->voice_interaction_controller()->FlushForTesting();
   WaitDragAndAssertMetalayer("one pref enabled", origin,
                              ui::EF_LEFT_MOUSE_BUTTON, false /* no metalayer */,
                              false /* no highlighter on press */);
 
   // Enable the other user pref, still not sufficient.
   Shell::Get()->voice_interaction_controller()->NotifySettingsEnabled(true);
+  Shell::Get()->voice_interaction_controller()->FlushForTesting();
   WaitDragAndAssertMetalayer("two prefs enabled", origin,
                              ui::EF_LEFT_MOUSE_BUTTON, false /* no metalayer */,
                              false /* no highlighter on press */);
@@ -443,6 +448,7 @@
   // Once the service is ready, the button should start working.
   Shell::Get()->voice_interaction_controller()->NotifyStatusChanged(
       mojom::VoiceInteractionState::RUNNING);
+  Shell::Get()->voice_interaction_controller()->FlushForTesting();
 
   // Press and drag with no button, still no highlighter.
   WaitDragAndAssertMetalayer("all enabled, no button ", origin, ui::EF_NONE,
@@ -507,6 +513,7 @@
   // Disable the metalayer support.
   // This should deactivate both the palette tool and the highlighter.
   Shell::Get()->voice_interaction_controller()->NotifyContextEnabled(false);
+  Shell::Get()->voice_interaction_controller()->FlushForTesting();
   EXPECT_FALSE(test_api_->palette_tool_manager()->IsToolActive(
       PaletteToolId::METALAYER));
 
diff --git a/ash/system/palette/tools/metalayer_mode.cc b/ash/system/palette/tools/metalayer_mode.cc
index 50d0fc8..fba94d3 100644
--- a/ash/system/palette/tools/metalayer_mode.cc
+++ b/ash/system/palette/tools/metalayer_mode.cc
@@ -35,15 +35,20 @@
 }  // namespace
 
 MetalayerMode::MetalayerMode(Delegate* delegate)
-    : CommonPaletteTool(delegate), weak_factory_(this) {
+    : CommonPaletteTool(delegate),
+      voice_interaction_binding_(this),
+      weak_factory_(this) {
   Shell::Get()->AddPreTargetHandler(this);
-  Shell::Get()->voice_interaction_controller()->AddObserver(this);
+
+  mojom::VoiceInteractionObserverPtr ptr;
+  voice_interaction_binding_.Bind(mojo::MakeRequest(&ptr));
+  Shell::Get()->voice_interaction_controller()->AddVoiceInteractionObserver(
+      std::move(ptr));
   Shell::Get()->highlighter_controller()->AddObserver(this);
 }
 
 MetalayerMode::~MetalayerMode() {
   Shell::Get()->highlighter_controller()->RemoveObserver(this);
-  Shell::Get()->voice_interaction_controller()->RemoveObserver(this);
   Shell::Get()->RemovePreTargetHandler(this);
 }
 
diff --git a/ash/system/palette/tools/metalayer_mode.h b/ash/system/palette/tools/metalayer_mode.h
index c79bc48..8254bad 100644
--- a/ash/system/palette/tools/metalayer_mode.h
+++ b/ash/system/palette/tools/metalayer_mode.h
@@ -9,7 +9,6 @@
 #include "ash/highlighter/highlighter_controller.h"
 #include "ash/public/interfaces/voice_interaction_controller.mojom.h"
 #include "ash/system/palette/common_palette_tool.h"
-#include "ash/voice_interaction/voice_interaction_observer.h"
 #include "base/memory/weak_ptr.h"
 #include "ui/events/event_handler.h"
 
@@ -22,7 +21,7 @@
 // menu, but also by the stylus button click.
 class ASH_EXPORT MetalayerMode : public CommonPaletteTool,
                                  public ui::EventHandler,
-                                 public VoiceInteractionObserver,
+                                 public mojom::VoiceInteractionObserver,
                                  public HighlighterController::Observer {
  public:
   explicit MetalayerMode(Delegate* delegate);
@@ -64,11 +63,12 @@
   // ui::EventHandler:
   void OnTouchEvent(ui::TouchEvent* event) override;
 
-  // VoiceInteractionObserver:
+  // mojom::VoiceInteractionObserver:
   void OnVoiceInteractionStatusChanged(
       mojom::VoiceInteractionState state) override;
   void OnVoiceInteractionSettingsEnabled(bool enabled) override;
   void OnVoiceInteractionContextEnabled(bool enabled) override;
+  void OnVoiceInteractionSetupCompleted(bool completed) override {}
   void OnAssistantFeatureAllowedChanged(
       mojom::AssistantAllowedState state) override;
 
@@ -99,6 +99,8 @@
   // True when the mode is activated via the stylus barrel button.
   bool activated_via_button_ = false;
 
+  mojo::Binding<mojom::VoiceInteractionObserver> voice_interaction_binding_;
+
   base::WeakPtrFactory<MetalayerMode> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(MetalayerMode);
diff --git a/ash/system/palette/tools/metalayer_unittest.cc b/ash/system/palette/tools/metalayer_unittest.cc
index d8da4e9d..67cc204 100644
--- a/ash/system/palette/tools/metalayer_unittest.cc
+++ b/ash/system/palette/tools/metalayer_unittest.cc
@@ -97,6 +97,7 @@
               context);
           Shell::Get()->voice_interaction_controller()->NotifyFeatureAllowed(
               allowed_state);
+          Shell::Get()->voice_interaction_controller()->FlushForTesting();
 
           std::unique_ptr<views::View> view =
               base::WrapUnique(tool_->CreateView());
@@ -146,21 +147,26 @@
       mojom::VoiceInteractionState::RUNNING);
   Shell::Get()->voice_interaction_controller()->NotifySettingsEnabled(true);
   Shell::Get()->voice_interaction_controller()->NotifyContextEnabled(true);
+  Shell::Get()->voice_interaction_controller()->FlushForTesting();
 
   // Disabling the user prefs individually should disable the tool.
   tool_->OnEnable();
   EXPECT_CALL(*palette_tool_delegate_.get(),
               DisableTool(PaletteToolId::METALAYER));
   Shell::Get()->voice_interaction_controller()->NotifySettingsEnabled(false);
+  Shell::Get()->voice_interaction_controller()->FlushForTesting();
   testing::Mock::VerifyAndClearExpectations(palette_tool_delegate_.get());
   Shell::Get()->voice_interaction_controller()->NotifySettingsEnabled(true);
+  Shell::Get()->voice_interaction_controller()->FlushForTesting();
 
   tool_->OnEnable();
   EXPECT_CALL(*palette_tool_delegate_.get(),
               DisableTool(PaletteToolId::METALAYER));
   Shell::Get()->voice_interaction_controller()->NotifyContextEnabled(false);
+  Shell::Get()->voice_interaction_controller()->FlushForTesting();
   testing::Mock::VerifyAndClearExpectations(palette_tool_delegate_.get());
   Shell::Get()->voice_interaction_controller()->NotifyContextEnabled(true);
+  Shell::Get()->voice_interaction_controller()->FlushForTesting();
 
   // Test VoiceInteractionState changes.
   tool_->OnEnable();
@@ -174,6 +180,7 @@
       mojom::VoiceInteractionState::STOPPED);
   Shell::Get()->voice_interaction_controller()->NotifyStatusChanged(
       mojom::VoiceInteractionState::RUNNING);
+  Shell::Get()->voice_interaction_controller()->FlushForTesting();
   testing::Mock::VerifyAndClearExpectations(palette_tool_delegate_.get());
 
   // Changing the state to NOT_READY should disable the tool.
@@ -181,6 +188,7 @@
               DisableTool(PaletteToolId::METALAYER));
   Shell::Get()->voice_interaction_controller()->NotifyStatusChanged(
       mojom::VoiceInteractionState::NOT_READY);
+  Shell::Get()->voice_interaction_controller()->FlushForTesting();
   testing::Mock::VerifyAndClearExpectations(palette_tool_delegate_.get());
 }
 
diff --git a/ash/system/unified/unified_system_tray_bubble.cc b/ash/system/unified/unified_system_tray_bubble.cc
index 0e09183..3481305 100644
--- a/ash/system/unified/unified_system_tray_bubble.cc
+++ b/ash/system/unified/unified_system_tray_bubble.cc
@@ -90,9 +90,19 @@
 void UnifiedSystemTrayBubble::ActivateBubble() {
   DCHECK(unified_view_);
   DCHECK(bubble_widget_);
+
+  views::Widget* bubble_widget = bubble_widget_;
+  // RequestInitFocus() may cause UnifiedSystemTrayBubble to destruct through
+  // Shell::NotifyFullscreenStateChanged, MessageCenter::OnBlockingStateChanged,
+  // and UiDelegate::HideMessageCenter().  https://crbug.com/853434
   unified_view_->RequestInitFocus();
-  bubble_widget_->widget_delegate()->set_can_activate(true);
-  bubble_widget_->Activate();
+
+  // |bubble_widget| is destructed asynchronously, so the instance is still
+  // alive here.
+  if (bubble_widget->IsClosed())
+    return;
+  bubble_widget->widget_delegate()->set_can_activate(true);
+  bubble_widget->Activate();
 }
 
 void UnifiedSystemTrayBubble::CloseNow() {
diff --git a/ash/system/unified/user_chooser_view.cc b/ash/system/unified/user_chooser_view.cc
index 9459237b..46a0275 100644
--- a/ash/system/unified/user_chooser_view.cc
+++ b/ash/system/unified/user_chooser_view.cc
@@ -35,6 +35,7 @@
   DCHECK(user_session);
 
   auto* image_view = new tray::RoundedImageView(kTrayItemSize / 2);
+  image_view->set_can_process_events_within_subtree(false);
   if (user_session->user_info->type == user_manager::USER_TYPE_GUEST) {
     gfx::ImageSkia icon =
         gfx::CreateVectorIcon(kSystemMenuGuestIcon, kMenuIconColor);
diff --git a/ash/voice_interaction/voice_interaction_controller.cc b/ash/voice_interaction/voice_interaction_controller.cc
index 4cfc6ec..524b9a3 100644
--- a/ash/voice_interaction/voice_interaction_controller.cc
+++ b/ash/voice_interaction/voice_interaction_controller.cc
@@ -17,45 +17,59 @@
   binding_.Bind(std::move(request));
 }
 
-void VoiceInteractionController::AddObserver(
-    VoiceInteractionObserver* observer) {
-  observers_.AddObserver(observer);
-}
-
-void VoiceInteractionController::RemoveObserver(
-    VoiceInteractionObserver* observer) {
-  observers_.RemoveObserver(observer);
+void VoiceInteractionController::AddVoiceInteractionObserver(
+    mojom::VoiceInteractionObserverPtr observer) {
+  observers_.AddPtr(std::move(observer));
 }
 
 void VoiceInteractionController::NotifyStatusChanged(
     mojom::VoiceInteractionState state) {
   voice_interaction_state_ = state;
-  for (auto& observer : observers_)
-    observer.OnVoiceInteractionStatusChanged(state);
+  observers_.ForAllPtrs([state](auto* observer) {
+    observer->OnVoiceInteractionStatusChanged(state);
+  });
 }
 
 void VoiceInteractionController::NotifySettingsEnabled(bool enabled) {
   settings_enabled_ = enabled;
-  for (auto& observer : observers_)
-    observer.OnVoiceInteractionSettingsEnabled(enabled);
+  observers_.ForAllPtrs([enabled](auto* observer) {
+    observer->OnVoiceInteractionSettingsEnabled(enabled);
+  });
 }
 
 void VoiceInteractionController::NotifyContextEnabled(bool enabled) {
-  for (auto& observer : observers_)
-    observer.OnVoiceInteractionContextEnabled(enabled);
+  observers_.ForAllPtrs([enabled](auto* observer) {
+    observer->OnVoiceInteractionContextEnabled(enabled);
+  });
 }
 
 void VoiceInteractionController::NotifySetupCompleted(bool completed) {
   setup_completed_ = completed;
-  for (auto& observer : observers_)
-    observer.OnVoiceInteractionSetupCompleted(completed);
+  observers_.ForAllPtrs([completed](auto* observer) {
+    observer->OnVoiceInteractionSetupCompleted(completed);
+  });
 }
 
 void VoiceInteractionController::NotifyFeatureAllowed(
     mojom::AssistantAllowedState state) {
   allowed_state_ = state;
-  for (auto& observer : observers_)
-    observer.OnAssistantFeatureAllowedChanged(state);
+  observers_.ForAllPtrs([state](auto* observer) {
+    observer->OnAssistantFeatureAllowedChanged(state);
+  });
+}
+
+void VoiceInteractionController::IsSettingEnabled(
+    IsSettingEnabledCallback callback) {
+  std::move(callback).Run(settings_enabled_);
+}
+
+void VoiceInteractionController::IsSetupCompleted(
+    IsSetupCompletedCallback callback) {
+  std::move(callback).Run(setup_completed_);
+}
+
+void VoiceInteractionController::FlushForTesting() {
+  observers_.FlushForTesting();
 }
 
 }  // namespace ash
diff --git a/ash/voice_interaction/voice_interaction_controller.h b/ash/voice_interaction/voice_interaction_controller.h
index 0686351..1898c3e 100644
--- a/ash/voice_interaction/voice_interaction_controller.h
+++ b/ash/voice_interaction/voice_interaction_controller.h
@@ -9,8 +9,8 @@
 
 #include "ash/ash_export.h"
 #include "ash/public/interfaces/voice_interaction_controller.mojom.h"
-#include "ash/voice_interaction/voice_interaction_observer.h"
 #include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/bindings/interface_ptr_set.h"
 
 namespace ash {
 
@@ -22,8 +22,7 @@
 
   void BindRequest(mojom::VoiceInteractionControllerRequest request);
 
-  void AddObserver(VoiceInteractionObserver* observer);
-  void RemoveObserver(VoiceInteractionObserver* observer);
+  void AddVoiceInteractionObserver(mojom::VoiceInteractionObserverPtr observer);
 
   // ash::mojom::VoiceInteractionController:
   void NotifyStatusChanged(mojom::VoiceInteractionState state) override;
@@ -31,6 +30,8 @@
   void NotifyContextEnabled(bool enabled) override;
   void NotifySetupCompleted(bool completed) override;
   void NotifyFeatureAllowed(mojom::AssistantAllowedState state) override;
+  void IsSettingEnabled(IsSettingEnabledCallback callback) override;
+  void IsSetupCompleted(IsSetupCompletedCallback callback) override;
 
   mojom::VoiceInteractionState voice_interaction_state() const {
     return voice_interaction_state_;
@@ -42,6 +43,8 @@
 
   mojom::AssistantAllowedState allowed_state() const { return allowed_state_; }
 
+  void FlushForTesting();
+
  private:
   // Voice interaction state. The initial value should be set to STOPPED to make
   // sure the app list button burst animation could be correctly shown.
@@ -58,10 +61,10 @@
   mojom::AssistantAllowedState allowed_state_ =
       mojom::AssistantAllowedState::ALLOWED;
 
-  base::ObserverList<VoiceInteractionObserver> observers_;
-
   mojo::Binding<mojom::VoiceInteractionController> binding_;
 
+  mojo::InterfacePtrSet<mojom::VoiceInteractionObserver> observers_;
+
   DISALLOW_COPY_AND_ASSIGN(VoiceInteractionController);
 };
 
diff --git a/ash/voice_interaction/voice_interaction_controller_unittest.cc b/ash/voice_interaction/voice_interaction_controller_unittest.cc
index 7ea9614..b042411 100644
--- a/ash/voice_interaction/voice_interaction_controller_unittest.cc
+++ b/ash/voice_interaction/voice_interaction_controller_unittest.cc
@@ -6,19 +6,21 @@
 
 #include <memory>
 
+#include "ash/public/interfaces/voice_interaction_controller.mojom.h"
 #include "ash/shell.h"
 #include "ash/test/ash_test_base.h"
-#include "ash/voice_interaction/voice_interaction_observer.h"
+#include "mojo/public/cpp/bindings/binding.h"
 
 namespace ash {
 namespace {
 
-class TestVoiceInteractionObserver : public VoiceInteractionObserver {
+class TestVoiceInteractionObserver : public mojom::VoiceInteractionObserver {
  public:
-  TestVoiceInteractionObserver() = default;
+  TestVoiceInteractionObserver() : voice_interaction_binding_(this) {}
+
   ~TestVoiceInteractionObserver() override = default;
 
-  // VoiceInteractionObserver overrides:
+  // mojom::VoiceInteractionObserver overrides:
   void OnVoiceInteractionStatusChanged(
       mojom::VoiceInteractionState state) override {
     state_ = state;
@@ -32,6 +34,8 @@
   void OnVoiceInteractionSetupCompleted(bool completed) override {
     setup_completed_ = completed;
   }
+  void OnAssistantFeatureAllowedChanged(
+      mojom::AssistantAllowedState state) override {}
 
   mojom::VoiceInteractionState voice_interaction_state() const {
     return state_;
@@ -40,12 +44,20 @@
   bool context_enabled() const { return context_enabled_; }
   bool setup_completed() const { return setup_completed_; }
 
+  void SetVoiceInteractionController(VoiceInteractionController* controller) {
+    mojom::VoiceInteractionObserverPtr ptr;
+    voice_interaction_binding_.Bind(mojo::MakeRequest(&ptr));
+    controller->AddVoiceInteractionObserver(std::move(ptr));
+  }
+
  private:
   mojom::VoiceInteractionState state_ = mojom::VoiceInteractionState::STOPPED;
   bool settings_enabled_ = false;
   bool context_enabled_ = false;
   bool setup_completed_ = false;
 
+  mojo::Binding<mojom::VoiceInteractionObserver> voice_interaction_binding_;
+
   DISALLOW_COPY_AND_ASSIGN(TestVoiceInteractionObserver);
 };
 
@@ -58,11 +70,10 @@
     AshTestBase::SetUp();
 
     observer_ = std::make_unique<TestVoiceInteractionObserver>();
-    controller()->AddObserver(observer_.get());
+    observer_->SetVoiceInteractionController(controller());
   }
 
   void TearDown() override {
-    controller()->RemoveObserver(observer_.get());
     observer_.reset();
 
     AshTestBase::TearDown();
@@ -85,6 +96,8 @@
 
 TEST_F(VoiceInteractionControllerTest, NotifyStatusChanged) {
   controller()->NotifyStatusChanged(mojom::VoiceInteractionState::RUNNING);
+  controller()->FlushForTesting();
+
   // The cached state should be updated.
   EXPECT_EQ(mojom::VoiceInteractionState::RUNNING,
             controller()->voice_interaction_state());
@@ -95,6 +108,7 @@
 
 TEST_F(VoiceInteractionControllerTest, NotifySettingsEnabled) {
   controller()->NotifySettingsEnabled(true);
+  controller()->FlushForTesting();
   // The cached state should be updated.
   EXPECT_TRUE(controller()->settings_enabled());
   // The observers should be notified.
@@ -103,12 +117,14 @@
 
 TEST_F(VoiceInteractionControllerTest, NotifyContextEnabled) {
   controller()->NotifyContextEnabled(true);
+  controller()->FlushForTesting();
   // The observers should be notified.
   EXPECT_TRUE(observer()->context_enabled());
 }
 
 TEST_F(VoiceInteractionControllerTest, NotifySetupCompleted) {
   controller()->NotifySetupCompleted(true);
+  controller()->FlushForTesting();
   // The cached state should be updated.
   EXPECT_TRUE(controller()->setup_completed());
   // The observers should be notified.
diff --git a/ash/voice_interaction/voice_interaction_observer.h b/ash/voice_interaction/voice_interaction_observer.h
deleted file mode 100644
index d6b8b37a..0000000
--- a/ash/voice_interaction/voice_interaction_observer.h
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef ASH_VOICE_INTERACTION_VOICE_INTERACTION_OBSERVER_H_
-#define ASH_VOICE_INTERACTION_VOICE_INTERACTION_OBSERVER_H_
-
-namespace ash {
-
-namespace mojom {
-
-enum class AssistantAllowedState;
-enum class VoiceInteractionState;
-
-}  // namespace mojom
-
-class VoiceInteractionObserver {
- public:
-  // Called when voice interaction session state changes.
-  virtual void OnVoiceInteractionStatusChanged(
-      mojom::VoiceInteractionState state) {}
-
-  // Called when voice interaction is enabled/disabled in settings.
-  virtual void OnVoiceInteractionSettingsEnabled(bool enabled) {}
-
-  // Called when voice interaction service is allowed/disallowed to access
-  // the "context" (text and graphic content that is currently on screen).
-  virtual void OnVoiceInteractionContextEnabled(bool enabled) {}
-
-  // Called when voice interaction setup flow completed.
-  virtual void OnVoiceInteractionSetupCompleted(bool completed) {}
-
-  // Called when assistant feature allowed state has changed.
-  virtual void OnAssistantFeatureAllowedChanged(
-      mojom::AssistantAllowedState state) {}
-
- protected:
-  virtual ~VoiceInteractionObserver() = default;
-};
-
-}  // namespace ash
-
-#endif  // ASH_VOICE_INTERACTION_VOICE_INTERACTION_OBSERVER_H_
diff --git a/ash/ws/ash_gpu_interface_provider.cc b/ash/ws/ash_gpu_interface_provider.cc
index 7d1a1950..dd2b311 100644
--- a/ash/ws/ash_gpu_interface_provider.cc
+++ b/ash/ws/ash_gpu_interface_provider.cc
@@ -26,11 +26,17 @@
 
 void AshGpuInterfaceProvider::RegisterGpuInterfaces(
     service_manager::BinderRegistry* registry) {
-  registry->AddInterface(base::BindRepeating(
-      &AshGpuInterfaceProvider::BindGpuRequest, base::Unretained(this)));
+  registry->AddInterface<ui::mojom::Arc>(base::BindRepeating(
+      &AshGpuInterfaceProvider::BindArcRequest, base::Unretained(this)));
   registry->AddInterface(base::BindRepeating(
       &AshGpuInterfaceProvider::BindDiscardableSharedMemoryManagerRequest,
       base::Unretained(this)));
+  registry->AddInterface(base::BindRepeating(
+      &AshGpuInterfaceProvider::BindGpuRequest, base::Unretained(this)));
+}
+
+void AshGpuInterfaceProvider::BindArcRequest(ui::mojom::ArcRequest request) {
+  gpu_host_->AddArc(std::move(request));
 }
 
 void AshGpuInterfaceProvider::BindDiscardableSharedMemoryManagerRequest(
diff --git a/ash/ws/ash_gpu_interface_provider.h b/ash/ws/ash_gpu_interface_provider.h
index f90b1bf..0d1d0637 100644
--- a/ash/ws/ash_gpu_interface_provider.h
+++ b/ash/ws/ash_gpu_interface_provider.h
@@ -6,6 +6,7 @@
 #define ASH_WS_ASH_GPU_INTERFACE_PROVIDER_H_
 
 #include "components/discardable_memory/public/interfaces/discardable_shared_memory_manager.mojom.h"
+#include "services/ui/public/interfaces/arc.mojom.h"
 #include "services/ui/public/interfaces/gpu.mojom.h"
 #include "services/ui/ws2/gpu_interface_provider.h"
 
@@ -34,9 +35,9 @@
       service_manager::BinderRegistry* registry) override;
 
  private:
+  void BindArcRequest(ui::mojom::ArcRequest request);
   void BindDiscardableSharedMemoryManagerRequest(
       discardable_memory::mojom::DiscardableSharedMemoryManagerRequest request);
-
   void BindGpuRequest(ui::mojom::GpuRequest request);
 
   ui::gpu_host::GpuHost* gpu_host_;
diff --git a/ash/ws/window_service_delegate_impl.cc b/ash/ws/window_service_delegate_impl.cc
index 8f8af8f6..6ad3ff76 100644
--- a/ash/ws/window_service_delegate_impl.cc
+++ b/ash/ws/window_service_delegate_impl.cc
@@ -34,23 +34,33 @@
       .Run(result == wm::WmToplevelWindowEventHandler::DragResult::SUCCESS);
 }
 
-// Returns true if a window move loop can be started.
-bool ShouldStartMoveLoop(aura::Window* window,
-                         ui::mojom::MoveLoopSource source) {
-  // A window move can not be started while drag and drop is in progress.
+// Returns true if there is a drag and drop in progress.
+bool InDragLoop(aura::Window* window) {
   aura::client::DragDropClient* drag_drop_client =
       aura::client::GetDragDropClient(window->GetRootWindow());
-  if (drag_drop_client && drag_drop_client->IsDragDropInProgress())
-    return false;
+  return drag_drop_client && drag_drop_client->IsDragDropInProgress();
+}
 
-  ToplevelWindowEventHandler* event_handler =
-      Shell::Get()->toplevel_window_event_handler();
-  // Only one move is allowed at a time.
-  if (event_handler->wm_toplevel_window_event_handler()
-          ->is_drag_in_progress()) {
-    return false;
-  }
-  return true;
+// Returns true if there is a window move loop in progress.
+bool InWindowMoveLoop() {
+  return Shell::Get()
+      ->toplevel_window_event_handler()
+      ->wm_toplevel_window_event_handler()
+      ->is_drag_in_progress();
+}
+
+// Returns true if a window move loop can be started.
+bool ShouldStartMoveLoop(aura::Window* window) {
+  // A window move can only be started when there is no in progress drag loop or
+  // window move loop.
+  return !InDragLoop(window) && !InWindowMoveLoop();
+}
+
+// Returns true if a drag loop can be started.
+bool ShouldStartDragLoop(aura::Window* window) {
+  // A drag loop can only be started when there is no in progress drag loop or
+  // window move loop.
+  return !InDragLoop(window) && !InWindowMoveLoop();
 }
 
 }  // namespace
@@ -94,7 +104,7 @@
     ui::mojom::MoveLoopSource source,
     const gfx::Point& cursor,
     DoneCallback callback) {
-  if (!ShouldStartMoveLoop(window, source)) {
+  if (!ShouldStartMoveLoop(window)) {
     std::move(callback).Run(false);
     return;
   }
@@ -121,4 +131,32 @@
       ->RevertDrag();
 }
 
+void WindowServiceDelegateImpl::RunDragLoop(
+    aura::Window* window,
+    const ui::OSExchangeData& data,
+    const gfx::Point& screen_location,
+    uint32_t drag_operation,
+    ui::DragDropTypes::DragEventSource source,
+    DragDropCompletedCallback callback) {
+  if (!ShouldStartDragLoop(window)) {
+    std::move(callback).Run(ui::DragDropTypes::DRAG_NONE);
+    return;
+  }
+
+  aura::Window* const root_window = window->GetRootWindow();
+  aura::client::DragDropClient* drag_drop_client =
+      aura::client::GetDragDropClient(root_window);
+  DCHECK(drag_drop_client);
+
+  std::move(callback).Run(drag_drop_client->StartDragAndDrop(
+      data, root_window, window, screen_location, drag_operation, source));
+}
+
+void WindowServiceDelegateImpl::CancelDragLoop(aura::Window* window) {
+  if (!InDragLoop(window))
+    return;
+
+  aura::client::GetDragDropClient(window->GetRootWindow())->DragCancel();
+}
+
 }  // namespace ash
diff --git a/ash/ws/window_service_delegate_impl.h b/ash/ws/window_service_delegate_impl.h
index fe9702e..e532372 100644
--- a/ash/ws/window_service_delegate_impl.h
+++ b/ash/ws/window_service_delegate_impl.h
@@ -28,6 +28,13 @@
                          const gfx::Point& cursor,
                          DoneCallback callback) override;
   void CancelWindowMoveLoop() override;
+  void RunDragLoop(aura::Window* window,
+                   const ui::OSExchangeData& data,
+                   const gfx::Point& screen_location,
+                   uint32_t drag_operation,
+                   ui::DragDropTypes::DragEventSource source,
+                   DragDropCompletedCallback callback) override;
+  void CancelDragLoop(aura::Window* window) override;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(WindowServiceDelegateImpl);
diff --git a/ash/ws/window_service_delegate_impl_unittest.cc b/ash/ws/window_service_delegate_impl_unittest.cc
index 2e39bd4..8c775b98 100644
--- a/ash/ws/window_service_delegate_impl_unittest.cc
+++ b/ash/ws/window_service_delegate_impl_unittest.cc
@@ -5,13 +5,43 @@
 #include "ash/shell.h"
 #include "ash/test/ash_test_base.h"
 #include "ash/wm/toplevel_window_event_handler.h"
+#include "base/run_loop.h"
+#include "base/test/bind_test_util.h"
+#include "base/threading/thread_task_runner_handle.h"
 #include "services/ui/ws2/test_window_tree_client.h"
 #include "services/ui/ws2/window_tree_test_helper.h"
+#include "ui/aura/client/drag_drop_client.h"
+#include "ui/aura/client/drag_drop_delegate.h"
 #include "ui/aura/window.h"
+#include "ui/base/dragdrop/drag_drop_types.h"
 #include "ui/events/test/event_generator.h"
 
 namespace ash {
 
+namespace {
+
+// A testing DragDropDelegate that accepts any drops.
+class TestDragDropDelegate : public aura::client::DragDropDelegate {
+ public:
+  TestDragDropDelegate() = default;
+  ~TestDragDropDelegate() override = default;
+
+  // aura::client::DragDropDelegate:
+  void OnDragEntered(const ui::DropTargetEvent& event) override {}
+  int OnDragUpdated(const ui::DropTargetEvent& event) override {
+    return ui::DragDropTypes::DRAG_MOVE;
+  }
+  void OnDragExited() override {}
+  int OnPerformDrop(const ui::DropTargetEvent& event) override {
+    return ui::DragDropTypes::DRAG_MOVE;
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(TestDragDropDelegate);
+};
+
+}  // namespace
+
 // This test creates a top-level window via the WindowService in SetUp() and
 // provides some ease of use functions to access WindowService related state.
 class WindowServiceDelegateImplTest : public AshTestBase {
@@ -33,6 +63,16 @@
     return GetTestWindowTreeClient()->tracker()->changes();
   }
 
+  void SetCanAcceptDrops() {
+    aura::client::SetDragDropDelegate(top_level_.get(),
+                                      &test_drag_drop_delegate_);
+  }
+
+  bool IsDragDropInProgress() {
+    return aura::client::GetDragDropClient(top_level_->GetRootWindow())
+        ->IsDragDropInProgress();
+  }
+
   // AshTestBase:
   void SetUp() override {
     AshTestBase::SetUp();
@@ -49,6 +89,7 @@
   }
 
  protected:
+  TestDragDropDelegate test_drag_drop_delegate_;
   std::unique_ptr<aura::Window> top_level_;
 
  private:
@@ -99,4 +140,111 @@
   EXPECT_EQ(gfx::Point(100, 100), top_level_->bounds().origin());
 }
 
+TEST_F(WindowServiceDelegateImplTest, RunDragLoop) {
+  SetCanAcceptDrops();
+  GetWindowTreeTestHelper()->window_tree()->PerformDragDrop(
+      21, GetTopLevelWindowId(), gfx::Point(),
+      base::flat_map<std::string, std::vector<uint8_t>>(), gfx::ImageSkia(),
+      gfx::Vector2d(), 0, ::ui::mojom::PointerKind::MOUSE);
+
+  base::RunLoop run_loop;
+
+  // Post mouse move and release to allow the nested drag loop to pick it up.
+  base::ThreadTaskRunnerHandle::Get()->PostTask(
+      FROM_HERE, base::BindLambdaForTesting([this] {
+        ASSERT_TRUE(IsDragDropInProgress());
+
+        // Move mouse to center of |top_level_|.
+        GetEventGenerator().MoveMouseTo(gfx::Point(150, 150));
+        GetWindowTreeClientChanges()->clear();
+        GetEventGenerator().ReleaseLeftButton();
+      }));
+
+  // Let the drop loop task run.
+  run_loop.RunUntilIdle();
+
+  EXPECT_TRUE(
+      ContainsChange(*GetWindowTreeClientChanges(),
+                     "OnPerformDragDropCompleted id=21 success=true action=1"));
+}
+
+TEST_F(WindowServiceDelegateImplTest, DeleteWindowWithInProgressDragLoop) {
+  SetCanAcceptDrops();
+  GetWindowTreeTestHelper()->window_tree()->PerformDragDrop(
+      21, GetTopLevelWindowId(), gfx::Point(),
+      base::flat_map<std::string, std::vector<uint8_t>>(), gfx::ImageSkia(),
+      gfx::Vector2d(), 0, ::ui::mojom::PointerKind::MOUSE);
+
+  base::RunLoop run_loop;
+
+  // Post the task to delete the window to allow nested drag loop to pick it up.
+  base::ThreadTaskRunnerHandle::Get()->PostTask(
+      FROM_HERE, base::BindLambdaForTesting([this] {
+        ASSERT_TRUE(IsDragDropInProgress());
+
+        // Deletes the window.
+        top_level_.reset();
+
+        // Move mouse and release the button and it should not crash.
+        GetEventGenerator().MoveMouseTo(gfx::Point(150, 150));
+        GetWindowTreeClientChanges()->clear();
+        GetEventGenerator().ReleaseLeftButton();
+      }));
+
+  // Let the drop loop task run.
+  run_loop.RunUntilIdle();
+
+  // It fails because the target window |top_level_| is deleted.
+  EXPECT_TRUE(ContainsChange(
+      *GetWindowTreeClientChanges(),
+      "OnPerformDragDropCompleted id=21 success=false action=0"));
+}
+
+TEST_F(WindowServiceDelegateImplTest, CancelDragDropBeforeDragLoopRun) {
+  SetCanAcceptDrops();
+  GetWindowTreeTestHelper()->window_tree()->PerformDragDrop(
+      21, GetTopLevelWindowId(), gfx::Point(),
+      base::flat_map<std::string, std::vector<uint8_t>>(), gfx::ImageSkia(),
+      gfx::Vector2d(), 0, ::ui::mojom::PointerKind::MOUSE);
+
+  // Cancel the drag before the drag loop runs.
+  GetWindowTreeTestHelper()->window_tree()->CancelDragDrop(
+      GetTopLevelWindowId());
+
+  // Let the drop loop task run.
+  base::RunLoop().RunUntilIdle();
+
+  // It fails because the drag is canceled.
+  EXPECT_TRUE(ContainsChange(
+      *GetWindowTreeClientChanges(),
+      "OnPerformDragDropCompleted id=21 success=false action=0"));
+}
+
+TEST_F(WindowServiceDelegateImplTest, CancelDragDropAfterDragLoopRun) {
+  SetCanAcceptDrops();
+  GetWindowTreeTestHelper()->window_tree()->PerformDragDrop(
+      21, GetTopLevelWindowId(), gfx::Point(),
+      base::flat_map<std::string, std::vector<uint8_t>>(), gfx::ImageSkia(),
+      gfx::Vector2d(), 0, ::ui::mojom::PointerKind::MOUSE);
+
+  base::RunLoop run_loop;
+
+  // Post the task to cancel to allow nested drag loop to pick it up.
+  base::ThreadTaskRunnerHandle::Get()->PostTask(
+      FROM_HERE, base::BindLambdaForTesting([this] {
+        ASSERT_TRUE(IsDragDropInProgress());
+
+        GetWindowTreeTestHelper()->window_tree()->CancelDragDrop(
+            GetTopLevelWindowId());
+      }));
+
+  // Let the drop loop task run.
+  run_loop.RunUntilIdle();
+
+  // It fails because the drag is canceled.
+  EXPECT_TRUE(ContainsChange(
+      *GetWindowTreeClientChanges(),
+      "OnPerformDragDropCompleted id=21 success=false action=0"));
+}
+
 }  // namespace ash
diff --git a/ash/ws/window_service_owner.cc b/ash/ws/window_service_owner.cc
index 6a36bc9..d6cec6e 100644
--- a/ash/ws/window_service_owner.cc
+++ b/ash/ws/window_service_owner.cc
@@ -11,6 +11,7 @@
 #include "services/service_manager/public/cpp/service_context.h"
 #include "services/ui/ws2/gpu_interface_provider.h"
 #include "services/ui/ws2/window_service.h"
+#include "ui/base/ui_base_features.h"
 #include "ui/wm/core/focus_controller.h"
 
 namespace ash {
@@ -32,7 +33,7 @@
   std::unique_ptr<ui::ws2::WindowService> window_service =
       std::make_unique<ui::ws2::WindowService>(
           window_service_delegate_.get(), std::move(gpu_interface_provider_),
-          Shell::Get()->focus_controller());
+          Shell::Get()->focus_controller(), features::IsAshInBrowserProcess());
   window_service_ = window_service.get();
   window_service_->SetFrameDecorationValues(
       NonClientFrameController::GetPreferredClientAreaInsets(),
diff --git a/base/test/fontconfig_util_linux.cc b/base/test/fontconfig_util_linux.cc
index 5c9bf5c..4171378 100644
--- a/base/test/fontconfig_util_linux.cc
+++ b/base/test/fontconfig_util_linux.cc
@@ -14,6 +14,12 @@
 #include "base/path_service.h"
 #include "base/strings/string_util.h"
 
+namespace switches {
+// Indicate to child processes that they should set up the FontConfig testing
+// environment.
+const char kFontConfigTestingEnvironment[] = "fontconfig-testing-environment";
+};  // namespace switches
+
 namespace base {
 
 namespace {
diff --git a/base/test/fontconfig_util_linux.h b/base/test/fontconfig_util_linux.h
index 3122526..21d4079 100644
--- a/base/test/fontconfig_util_linux.h
+++ b/base/test/fontconfig_util_linux.h
@@ -5,6 +5,10 @@
 #ifndef BASE_TEST_FONTCONFIG_UTIL_LINUX_H_
 #define BASE_TEST_FONTCONFIG_UTIL_LINUX_H_
 
+namespace switches {
+extern const char kFontConfigTestingEnvironment[];
+};
+
 namespace base {
 
 // Initializes Fontconfig with a custom configuration suitable for tests.
diff --git a/base/test/test_suite.cc b/base/test/test_suite.cc
index 3d53097..69f2fa5 100644
--- a/base/test/test_suite.cc
+++ b/base/test/test_suite.cc
@@ -411,6 +411,11 @@
   switches.erase(switches::kEnableFeatures);
   switches.erase(switches::kDisableFeatures);
 
+#if defined(OS_LINUX)
+  // Pass to child processes that we need the FontConfig testing environment.
+  switches[switches::kFontConfigTestingEnvironment] = "";
+#endif
+
   for (const auto& iter : switches)
     new_command_line.AppendSwitchNative(iter.first, iter.second);
 
diff --git a/build/android/gyp/javac.py b/build/android/gyp/javac.py
index e99cb16..54335f9 100755
--- a/build/android/gyp/javac.py
+++ b/build/android/gyp/javac.py
@@ -572,7 +572,7 @@
                       options.processorpath)
   # GN already knows of java_files, so listing them just make things worse when
   # they change.
-  depfile_deps = [javac_path] + classpath_inputs + options.java_srcjars
+  depfile_deps = ([javac_path] + classpath_inputs + options.java_srcjars)
   input_paths = depfile_deps + java_files
 
   output_paths = [
diff --git a/build/config/android/internal_rules.gni b/build/config/android/internal_rules.gni
index cf84f5a..9740179 100644
--- a/build/config/android/internal_rules.gni
+++ b/build/config/android/internal_rules.gni
@@ -2961,9 +2961,13 @@
       }
       if (defined(invoker.include_java_resources) &&
           invoker.include_java_resources) {
-        # Use original jar_path because _jar_path points to a library without
-        # resources.
-        java_resources_jar = invoker.jar_path
+        if (defined(invoker.jar_path)) {
+          # Use original jar_path because _jar_path points to a library without
+          # resources.
+          java_resources_jar = invoker.jar_path
+        } else {
+          java_resources_jar = _final_jar_path
+        }
       }
     }
     _accumulated_public_deps += [ ":$_build_config_target_name" ]
diff --git a/build/secondary/third_party/android_tools/BUILD.gn b/build/secondary/third_party/android_tools/BUILD.gn
index dfd2b69..e8ee862 100644
--- a/build/secondary/third_party/android_tools/BUILD.gn
+++ b/build/secondary/third_party/android_tools/BUILD.gn
@@ -286,4 +286,14 @@
     proguard_configs =
         [ "${target_gen_dir}/google_play_services_basement_java/proguard.txt" ]
   }
+
+  # The current version of //third_party/byte_buddy relies on an older
+  # version of dx.
+  java_prebuilt("dx_25_0_2_java") {
+    supports_android = true
+    requires_android = true
+    no_build_hooks = true
+    testonly = true
+    jar_path = "//third_party/android_tools/sdk/build-tools/25.0.2/lib/dx.jar"
+  }
 }
diff --git a/build/toolchain/win/BUILD.gn b/build/toolchain/win/BUILD.gn
index 6f47ea9..eb3e2b2 100644
--- a/build/toolchain/win/BUILD.gn
+++ b/build/toolchain/win/BUILD.gn
@@ -133,16 +133,23 @@
       sys_include_flags = ""
     }
 
-    if (use_lld) {
+    # ninja does not have -t msvc other than windows, and lld doesn't depend on
+    # mt.exe in PATH on non-Windows, so it's not needed there anyways.
+    if (defined(invoker.sys_lib_flags)) {
+      linker_wrapper = ""
+      sys_lib_flags = "${invoker.sys_lib_flags} "  # Note trailing space
+    } else if (use_lld) {
       # Invoke ninja as wrapper instead of tool wrapper, because python
       # invocation requires higher cpu usage compared to ninja invocation, and
       # the python wrapper is only needed to work around link.exe problems.
       # TODO(thakis): Remove wrapper once lld-link can merge manifests without
       # relying on mt.exe being in %PATH% on Windows.
       linker_wrapper = "ninja -t msvc -e $env -- "  # Note trailing space.
+      sys_lib_flags = ""
     } else {
       linker_wrapper =
           "$python_path $tool_wrapper_path link-wrapper $env False "  # Note trailing space.
+      sys_lib_flags = ""
     }
 
     clflags = ""
@@ -208,8 +215,7 @@
 
     tool("alink") {
       rspfile = "{{output}}.rsp"
-      command =
-          "$linker_wrapper$lib /nologo {{arflags}} /OUT:{{output}} @$rspfile"
+      command = "$linker_wrapper$lib /nologo ${sys_lib_flags}{{arflags}} /OUT:{{output}} @$rspfile"
       description = "LIB {{output}}"
       outputs = [
         # Ignore {{output_extension}} and always use .lib, there's no reason to
@@ -231,7 +237,7 @@
       rspfile = "${dllname}.rsp"
       pool = "//build/toolchain:link_pool($default_toolchain)"
 
-      command = "$linker_wrapper$link /nologo /IMPLIB:$libname /DLL /OUT:$dllname /PDB:$pdbname @$rspfile"
+      command = "$linker_wrapper$link /nologo ${sys_lib_flags}/IMPLIB:$libname /DLL /OUT:$dllname /PDB:$pdbname @$rspfile"
 
       default_output_extension = ".dll"
       default_output_dir = "{{root_out_dir}}"
@@ -264,7 +270,7 @@
       rspfile = "${dllname}.rsp"
       pool = "//build/toolchain:link_pool($default_toolchain)"
 
-      command = "$linker_wrapper$link /nologo /DLL /OUT:$dllname /PDB:$pdbname @$rspfile"
+      command = "$linker_wrapper$link /nologo ${sys_lib_flags}/DLL /OUT:$dllname /PDB:$pdbname @$rspfile"
 
       default_output_extension = ".dll"
       default_output_dir = "{{root_out_dir}}"
@@ -288,8 +294,7 @@
       rspfile = "$exename.rsp"
       pool = "//build/toolchain:link_pool($default_toolchain)"
 
-      command =
-          "$linker_wrapper$link /nologo /OUT:$exename /PDB:$pdbname @$rspfile"
+      command = "$linker_wrapper$link /nologo ${sys_lib_flags}/OUT:$exename /PDB:$pdbname @$rspfile"
 
       if (host_os == "win") {
         shellprefix = "cmd /c"
@@ -373,6 +378,10 @@
   msvc_toolchain(win_build_host_cpu) {
     environment = "environment." + win_build_host_cpu
     cl = "${goma_prefix}\"${build_cpu_toolchain_data.vc_bin_dir}/cl.exe\""
+    if (host_os != "win") {
+      # For win cross build.
+      sys_lib_flags = "${build_cpu_toolchain_data.libpath_flags}"
+    }
     toolchain_args = {
       current_os = "win"
       current_cpu = win_build_host_cpu
@@ -385,6 +394,10 @@
     prefix = rebase_path("$clang_base_path/bin", root_build_dir)
     cl = "${goma_prefix}$prefix/${clang_cl}"
     sys_include_flags = "${build_cpu_toolchain_data.include_flags_imsvc}"
+    if (host_os != "win") {
+      # For win cross build.
+      sys_lib_flags = "${build_cpu_toolchain_data.libpath_flags}"
+    }
 
     toolchain_args = {
       current_os = "win"
@@ -410,6 +423,10 @@
   msvc_toolchain(target_name) {
     environment = "environment.x64"
     cl = "${goma_prefix}\"${x64_toolchain_data.vc_bin_dir}/cl.exe\""
+    if (host_os != "win") {
+      # For win cross build
+      sys_lib_flags = "${x64_toolchain_data.libpath_flags}"
+    }
 
     toolchain_args = {
       if (defined(invoker.toolchain_args)) {
@@ -426,6 +443,10 @@
     prefix = rebase_path("$clang_base_path/bin", root_build_dir)
     cl = "${goma_prefix}$prefix/${clang_cl}"
     sys_include_flags = "${x64_toolchain_data.include_flags_imsvc}"
+    if (host_os != "win") {
+      # For win cross build
+      sys_lib_flags = "${x64_toolchain_data.libpath_flags}"
+    }
 
     toolchain_args = {
       if (defined(invoker.toolchain_args)) {
diff --git a/build/toolchain/win/setup_toolchain.py b/build/toolchain/win/setup_toolchain.py
index 2ee36e2..1ba5533 100644
--- a/build/toolchain/win/setup_toolchain.py
+++ b/build/toolchain/win/setup_toolchain.py
@@ -207,6 +207,7 @@
   vc_lib_atlmfc_path = ''
   vc_lib_um_path = ''
   include = ''
+  lib = ''
 
   # TODO(scottmg|goma): Do we need an equivalent of
   # ninja_use_custom_environment_files?
@@ -247,10 +248,18 @@
       except ValueError:
         pass
 
+      lib = [p.replace('"', r'\"') for p in env['LIB'].split(';') if p]
+      # Make lib path relative to builddir when cwd and sdk in same drive.
+      try:
+        lib = map(os.path.relpath, lib)
+      except ValueError:
+        pass
+
       def q(s):  # Quote s if it contains spaces or other weird characters.
         return s if re.match(r'^[a-zA-Z0-9._/\\:-]*$', s) else '"' + s + '"'
       include_I = ' '.join([q('/I' + i) for i in include])
       include_imsvc = ' '.join([q('-imsvc' + i) for i in include])
+      libpath_flags = ' '.join([q('-libpath:' + i) for i in lib])
 
       if (environment_block_name != ''):
         env_block = _FormatAsEnvironmentBlock(env)
@@ -275,6 +284,9 @@
   assert vc_lib_um_path
   print 'vc_lib_um_path = ' + gn_helpers.ToGNString(vc_lib_um_path)
   print 'paths = ' + gn_helpers.ToGNString(env['PATH'])
+  assert libpath_flags
+  print 'libpath_flags = ' + gn_helpers.ToGNString(libpath_flags)
+
 
 if __name__ == '__main__':
   main()
diff --git a/cc/layers/surface_layer.cc b/cc/layers/surface_layer.cc
index 6124fe4..7dcffc9b 100644
--- a/cc/layers/surface_layer.cc
+++ b/cc/layers/surface_layer.cc
@@ -30,8 +30,13 @@
     return;
   }
   primary_surface_id_ = surface_id;
-  if (!deadline_policy.use_existing_deadline())
+  // We should never block or set a deadline on an invalid
+  // |primary_surface_id_|.
+  if (!primary_surface_id_.is_valid()) {
+    deadline_in_frames_ = 0u;
+  } else if (!deadline_policy.use_existing_deadline()) {
     deadline_in_frames_ = deadline_policy.deadline_in_frames();
+  }
   UpdateDrawsContent(HasDrawableContent());
   SetNeedsCommit();
 }
diff --git a/cc/layers/surface_layer_unittest.cc b/cc/layers/surface_layer_unittest.cc
index 9eb987a..23ecc6a31 100644
--- a/cc/layers/surface_layer_unittest.cc
+++ b/cc/layers/surface_layer_unittest.cc
@@ -98,6 +98,25 @@
   EXPECT_EQ(std::numeric_limits<uint32_t>::max(), layer->deadline_in_frames());
 }
 
+// This test verifies that if an invalid primary surface ID is set then the
+// deadline will be reset to 0 frames.
+TEST_F(SurfaceLayerTest, ResetDeadlineOnInvalidSurfaceId) {
+  scoped_refptr<SurfaceLayer> layer = SurfaceLayer::Create();
+  layer_tree_host_->SetRootLayer(layer);
+  viz::SurfaceId primary_id(
+      kArbitraryFrameSinkId,
+      viz::LocalSurfaceId(1, base::UnguessableToken::Create()));
+  layer->SetPrimarySurfaceId(primary_id,
+                             DeadlinePolicy::UseSpecifiedDeadline(3u));
+  EXPECT_EQ(3u, layer->deadline_in_frames());
+
+  // Reset the surface layer to an invalid SurfaceId. Verify that the deadline
+  // is reset.
+  layer->SetPrimarySurfaceId(viz::SurfaceId(),
+                             DeadlinePolicy::UseSpecifiedDeadline(3u));
+  EXPECT_EQ(0u, layer->deadline_in_frames());
+}
+
 // This test verifies that SurfaceLayer properties are pushed across to
 // SurfaceLayerImpl.
 TEST_F(SurfaceLayerTest, PushProperties) {
diff --git a/cc/paint/paint_op_reader.cc b/cc/paint/paint_op_reader.cc
index bfe3661..b20600ef 100644
--- a/cc/paint/paint_op_reader.cc
+++ b/cc/paint/paint_op_reader.cc
@@ -315,6 +315,10 @@
                  .set_id(PaintImage::GetNextId())
                  .set_image(entry->image(), PaintImage::kNonLazyStableId)
                  .TakePaintImage();
+  } else {
+    // If a transfer cache id exists, we must have a valid entry for it in the
+    // cache.
+    SetInvalid();
   }
 }
 
diff --git a/cc/trees/layer_tree_host.cc b/cc/trees/layer_tree_host.cc
index 195da7b..667f1e3 100644
--- a/cc/trees/layer_tree_host.cc
+++ b/cc/trees/layer_tree_host.cc
@@ -1130,6 +1130,13 @@
     return;
   DCHECK_GE(page_scale_factor, min_page_scale_factor);
   DCHECK_LE(page_scale_factor, max_page_scale_factor);
+  // We should never process non-unit page_scale_delta for an OOPIF subframe.
+  // TODO(wjmaclean): Remove this check as a pre-condition to closing the bug.
+  // https://crbug.com/845097
+  CHECK(!settings_.is_layer_tree_for_subframe ||
+        page_scale_factor == page_scale_factor_)
+      << "Setting PSF in oopif subframe: old psf = " << page_scale_factor_
+      << ", new psf = " << page_scale_factor;
 
   page_scale_factor_ = page_scale_factor;
   min_page_scale_factor_ = min_page_scale_factor;
@@ -1292,6 +1299,13 @@
 
 void LayerTreeHost::SetPageScaleFromImplSide(float page_scale) {
   DCHECK(CommitRequested());
+  // We should never process non-unit page_scale_delta for an OOPIF subframe.
+  // TODO(wjmaclean): Remove this check as a pre-condition to closing the bug.
+  // https://crbug.com/845097
+  CHECK(!settings_.is_layer_tree_for_subframe ||
+        page_scale == page_scale_factor_)
+      << "Setting PSF in oopif subframe: old psf = " << page_scale_factor_
+      << ", new psf = " << page_scale;
   page_scale_factor_ = page_scale;
   SetPropertyTreesNeedRebuild();
 }
diff --git a/cc/trees/layer_tree_host_common.cc b/cc/trees/layer_tree_host_common.cc
index f8ee1f7..d556360f 100644
--- a/cc/trees/layer_tree_host_common.cc
+++ b/cc/trees/layer_tree_host_common.cc
@@ -563,6 +563,23 @@
         device_scale_factor_for_page_scale_node = inputs->device_scale_factor;
       }
 
+      // We should never be setting a non-unit page scale factor on an oopif
+      // subframe ... if we attempt this log it and fail.
+      // TODO(wjmaclean): Remove as part of conditions for closing the bug.
+      // https://crbug.com/845097
+      if (inputs->page_scale_factor !=
+              inputs->property_trees->transform_tree.page_scale_factor() &&
+          !inputs->page_scale_transform_node) {
+        LOG(ERROR) << "Setting PageScale on subframe: new psf = "
+                   << inputs->page_scale_factor << ", old psf = "
+                   << inputs->property_trees->transform_tree.page_scale_factor()
+                   << ", in_oopif = "
+                   << inputs->root_layer->layer_tree_impl()
+                          ->settings()
+                          .is_layer_tree_for_subframe;
+        CHECK(false);
+      }
+
       draw_property_utils::UpdatePageScaleFactor(
           inputs->property_trees, inputs->page_scale_transform_node,
           inputs->page_scale_factor, device_scale_factor_for_page_scale_node,
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index dfcba3e..39284d8 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -4564,6 +4564,11 @@
   CollectScrollbarUpdates(scroll_info.get());
   scroll_info->page_scale_delta =
       active_tree_->page_scale_factor()->PullDeltaForMainThread();
+  // We should never process non-unit page_scale_delta for an OOPIF subframe.
+  // TODO(wjmaclean): Remove this check as a pre-condition to closing the bug.
+  // https://crbug.com/845097
+  CHECK(!settings().is_layer_tree_for_subframe ||
+        scroll_info->page_scale_delta == 1.f);
   scroll_info->top_controls_delta =
       active_tree()->top_controls_shown_ratio()->PullDeltaForMainThread();
   scroll_info->elastic_overscroll_delta =
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java
index a9e655a2..78185fd 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java
@@ -257,7 +257,11 @@
         // [1] - https://developer.android.com/reference/android/view/WindowManager.LayoutParams.html#FLAG_FULLSCREEN
         if (mSystemUiFullscreen) {
             getWindowVisibleDisplayFrame(mCacheRect);
-            return mCacheRect.width();
+
+            // On certain devices, getWindowVisibleDisplayFrame is larger than the screen size, so
+            // this ensures we never draw beyond the underlying dimensions of the view.
+            // https://crbug.com/854109
+            return Math.min(mCacheRect.width(), getWidth());
         } else {
             return getWidth();
         }
@@ -267,7 +271,7 @@
         // See comment in getWidthForViewport() for an explainer of why this is done.
         if (mSystemUiFullscreen) {
             getWindowVisibleDisplayFrame(mCacheRect);
-            return mCacheRect.height();
+            return Math.min(mCacheRect.height(), getHeight());
         } else {
             return getHeight();
         }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsCluster.java b/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsCluster.java
index 915e4271..98c334ed 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsCluster.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextual_suggestions/ContextualSuggestionsCluster.java
@@ -12,7 +12,6 @@
 import org.chromium.chrome.browser.ntp.cards.InnerNode;
 import org.chromium.chrome.browser.ntp.cards.ItemViewType;
 import org.chromium.chrome.browser.ntp.cards.NewTabPageViewHolder;
-import org.chromium.chrome.browser.ntp.cards.NodeVisitor;
 import org.chromium.chrome.browser.ntp.cards.SuggestionsCategoryInfo;
 import org.chromium.chrome.browser.ntp.snippets.ContentSuggestionsCardLayout;
 import org.chromium.chrome.browser.ntp.snippets.KnownCategories;
@@ -28,6 +27,7 @@
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Locale;
 import java.util.Set;
 
 /** A node in a tree that groups contextual suggestions in a cluster of related items. */
@@ -127,13 +127,6 @@
         }
 
         @Override
-        public void visitItems(NodeVisitor visitor) {
-            for (SnippetArticle suggestion : mSuggestions) {
-                visitor.visitSuggestion(suggestion);
-            }
-        }
-
-        @Override
         public Set<Integer> getItemDismissalGroup(int position) {
             // Contextual suggestions are not dismissible.
             assert false;
@@ -147,6 +140,12 @@
             assert false;
         }
 
+        @Override
+        public String describeItemForTesting(int position) {
+            return String.format(
+                    Locale.US, "SUGGESTION(%1.42s)", mSuggestions.get(position).mTitle);
+        }
+
         @NonNull
         @Override
         public Iterator<SnippetArticle> iterator() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/AboveTheFoldItem.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/AboveTheFoldItem.java
index eba86ab2..30d0235 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/AboveTheFoldItem.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/AboveTheFoldItem.java
@@ -26,7 +26,7 @@
     }
 
     @Override
-    public void visitItems(NodeVisitor visitor) {
-        visitor.visitAboveTheFoldItem();
+    public String describeForTesting() {
+        return "ABOVE_THE_FOLD";
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/ActionItem.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/ActionItem.java
index 2aec098bb..3f34bb3 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/ActionItem.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/ActionItem.java
@@ -26,6 +26,7 @@
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.util.Locale;
 
 /**
  * Item that allows the user to perform an action on the NTP. Depending on its state, it can also
@@ -69,14 +70,12 @@
     }
 
     @Override
-    public void visitOptionalItem(NodeVisitor visitor) {
+    public String describeForTesting() {
         switch (mState) {
             case State.BUTTON:
-                visitor.visitActionItem(mCategoryInfo.getAdditionalAction());
-                break;
+                return String.format(Locale.US, "ACTION(%d)", mCategoryInfo.getAdditionalAction());
             case State.LOADING:
-                visitor.visitProgressItem();
-                break;
+                return "PROGRESS";
             case State.HIDDEN:
                 // If state is HIDDEN, itemCount should be 0 and this method should not be called.
             default:
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/AllDismissedItem.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/AllDismissedItem.java
index 041d47fc..af0be07 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/AllDismissedItem.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/AllDismissedItem.java
@@ -33,8 +33,8 @@
     }
 
     @Override
-    public void visitOptionalItem(NodeVisitor visitor) {
-        visitor.visitAllDismissedItem();
+    public String describeForTesting() {
+        return "ALL_DISMISSED";
     }
 
     public void setVisible(boolean visible) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/Footer.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/Footer.java
index 1ae6abc..4d807e00 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/Footer.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/Footer.java
@@ -32,8 +32,8 @@
     }
 
     @Override
-    public void visitOptionalItem(NodeVisitor visitor) {
-        visitor.visitFooter();
+    public String describeForTesting() {
+        return "FOOTER";
     }
 
     public void setVisible(boolean visible) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/InnerNode.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/InnerNode.java
index 8efd2db..65ef74d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/InnerNode.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/InnerNode.java
@@ -95,10 +95,10 @@
     }
 
     @Override
-    public void visitItems(NodeVisitor visitor) {
-        for (TreeNode child : getChildren()) {
-            child.visitItems(visitor);
-        }
+    public String describeItemForTesting(int position) {
+        int index = getChildIndexForPosition(position);
+        return getChildren().get(index).describeItemForTesting(
+                position - getStartingOffsetForChildIndex(index));
     }
 
     @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/Leaf.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/Leaf.java
index a1122e4..2f7e0a1 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/Leaf.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/Leaf.java
@@ -49,6 +49,14 @@
         assert false;
     }
 
+    @Override
+    public String describeItemForTesting(int position) {
+        if (position != 0) throw new IndexOutOfBoundsException();
+        return describeForTesting();
+    }
+
+    protected abstract String describeForTesting();
+
     /**
      * Display the data for this item.
      * @param holder The view holder that should be updated.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/NodeVisitor.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/NodeVisitor.java
deleted file mode 100644
index c058f886..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/NodeVisitor.java
+++ /dev/null
@@ -1,60 +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.
-
-package org.chromium.chrome.browser.ntp.cards;
-
-import org.chromium.chrome.browser.ntp.snippets.SnippetArticle;
-import org.chromium.chrome.browser.suggestions.ContentSuggestionsAdditionalAction;
-
-/**
- * Allows implementing a visitor pattern to iterate over all items under a (sub-)tree.
- */
-public class NodeVisitor {
-    /**
-     * Visits the above-the-fold item.
-     */
-    public void visitAboveTheFoldItem() {}
-
-    /**
-     * Visits an action item.
-     * @param currentAction The action enum value for the item.
-     */
-    public void visitActionItem(@ContentSuggestionsAdditionalAction int currentAction) {}
-
-    /**
-     * Visits the "all dimissed" item.
-     */
-    public void visitAllDismissedItem() {}
-
-    /**
-     * Visits the footer.
-     */
-    public void visitFooter() {}
-
-    /**
-     * Visits a progress item.
-     */
-    public void visitProgressItem() {}
-
-    /**
-     * Visits a sign-in promo.
-     */
-    public void visitSignInPromo() {}
-
-    /**
-     * Visits a "no suggestions" item.
-     */
-    public void visitNoSuggestionsItem() {}
-
-    /**
-     * Visits a suggestion.
-     * @param suggestion The {@link SnippetArticle} represented by the item.
-     */
-    public void visitSuggestion(SnippetArticle suggestion) {}
-
-    /**
-     * Visits a header.
-     */
-    public void visitHeader() {}
-}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/OptionalLeaf.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/OptionalLeaf.java
index 26174cc7..b344975 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/OptionalLeaf.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/OptionalLeaf.java
@@ -52,10 +52,13 @@
     }
 
     @Override
-    public final void visitItems(NodeVisitor visitor) {
-        if (mVisible) visitOptionalItem(visitor);
+    public String describeItemForTesting(int position) {
+        checkIndex(position);
+        return describeForTesting();
     }
 
+    protected abstract String describeForTesting();
+
     /** @return Whether the optional item is currently visible. */
     public final boolean isVisible() {
         return mVisible;
@@ -110,10 +113,4 @@
     protected void dismiss(Callback<String> itemRemovedCallback) {
         assert false;
     }
-
-    /**
-     * Visits this item. This method is called iff the optional item is currently visible.
-     * @param visitor The visitor with which to visit this item.
-     */
-    protected abstract void visitOptionalItem(NodeVisitor visitor);
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/ProgressItem.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/ProgressItem.java
index 198e1d1..c1eb6b6 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/ProgressItem.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/ProgressItem.java
@@ -24,8 +24,8 @@
     }
 
     @Override
-    protected void visitOptionalItem(NodeVisitor visitor) {
-        visitor.visitProgressItem();
+    public String describeForTesting() {
+        return "PROGRESS";
     }
 
     public void setVisible(boolean visible) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SignInPromo.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SignInPromo.java
index fda55d1..6626eb7 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SignInPromo.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SignInPromo.java
@@ -151,8 +151,8 @@
     }
 
     @Override
-    protected void visitOptionalItem(NodeVisitor visitor) {
-        visitor.visitSignInPromo();
+    public String describeForTesting() {
+        return "SIGN_IN_PROMO";
     }
 
     private void updateVisibility() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/StatusItem.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/StatusItem.java
index 651bb5a..df6d45d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/StatusItem.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/StatusItem.java
@@ -47,8 +47,8 @@
         }
 
         @Override
-        protected void visitOptionalItem(NodeVisitor visitor) {
-            visitor.visitNoSuggestionsItem();
+        public String describeForTesting() {
+            return "NO_SUGGESTIONS";
         }
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SuggestionsSection.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SuggestionsSection.java
index 2f891873..5680427 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SuggestionsSection.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SuggestionsSection.java
@@ -35,6 +35,7 @@
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Locale;
 import java.util.Set;
 
 /**
@@ -192,10 +193,9 @@
         }
 
         @Override
-        public void visitItems(NodeVisitor visitor) {
-            for (SnippetArticle suggestion : mSuggestions) {
-                visitor.visitSuggestion(suggestion);
-            }
+        public String describeItemForTesting(int position) {
+            return String.format(
+                    Locale.US, "SUGGESTION(%1.42s)", mSuggestions.get(position).mTitle);
         }
 
         @Override
@@ -342,6 +342,10 @@
         return mSuggestionsList.getItemCount();
     }
 
+    public SnippetArticle getSuggestionForTesting(int index) {
+        return mSuggestionsList.getSuggestionAt(index);
+    }
+
     public boolean isDataStale() {
         return mIsDataStale;
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/TreeNode.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/TreeNode.java
index 529392e..ed22707 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/TreeNode.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/TreeNode.java
@@ -56,9 +56,12 @@
     void dismissItem(int position, Callback<String> itemRemovedCallback);
 
     /**
-     * Iterates over all items under this subtree and visits them with the given
-     * {@link NodeVisitor}.
-     * @param visitor The {@link NodeVisitor} with which to visit all items under this subtree.
+     * Describe the item at the given {@code position}. As the description is used in tests for
+     * dumping state and equality checks, different items should have distinct descriptions,
+     * but for items that are unique or don't have interesting state it can be sufficient to return
+     * e.g. a string that describes the type of the item.
+     * @param position The position of the item to be described.
+     * @return A string description of the item.
      */
-    void visitItems(NodeVisitor visitor);
+    String describeItemForTesting(int position);
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SectionHeader.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SectionHeader.java
index ab2eff4..be96cb1 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SectionHeader.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SectionHeader.java
@@ -8,7 +8,6 @@
 
 import org.chromium.chrome.browser.ntp.cards.ItemViewType;
 import org.chromium.chrome.browser.ntp.cards.NewTabPageViewHolder;
-import org.chromium.chrome.browser.ntp.cards.NodeVisitor;
 import org.chromium.chrome.browser.ntp.cards.OptionalLeaf;
 
 /**
@@ -81,8 +80,8 @@
     }
 
     @Override
-    public void visitOptionalItem(NodeVisitor visitor) {
-        visitor.visitHeader();
+    public String describeForTesting() {
+        return "HEADER";
     }
 
     public void setVisible(boolean visible) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SiteSection.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SiteSection.java
index 30e5a27..efb8199 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SiteSection.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SiteSection.java
@@ -14,7 +14,6 @@
 import org.chromium.chrome.browser.ntp.ContextMenuManager;
 import org.chromium.chrome.browser.ntp.cards.ItemViewType;
 import org.chromium.chrome.browser.ntp.cards.NewTabPageViewHolder;
-import org.chromium.chrome.browser.ntp.cards.NodeVisitor;
 import org.chromium.chrome.browser.ntp.cards.OptionalLeaf;
 import org.chromium.chrome.browser.offlinepages.OfflinePageBridge;
 import org.chromium.chrome.browser.widget.displaystyle.UiConfig;
@@ -73,8 +72,10 @@
     }
 
     @Override
-    protected void visitOptionalItem(NodeVisitor visitor) {
-        assert false;
+    public String describeForTesting() {
+        // Throw an exception instead of just `assert false` to avoid compiler warnings about the
+        // return value.
+        throw new IllegalStateException();
     }
 
     @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/BottomToolbarMediator.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/BottomToolbarMediator.java
index 6eca361..4ada79f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/BottomToolbarMediator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/BottomToolbarMediator.java
@@ -72,8 +72,8 @@
      */
     public void destroy() {
         mFullscreenManager.removeListener(this);
-        mOverviewModeBehavior.removeOverviewModeObserver(this);
         if (mContextualSearchManger != null) mContextualSearchManger.removeObserver(this);
+        if (mOverviewModeBehavior != null) mOverviewModeBehavior.removeOverviewModeObserver(this);
     }
 
     @Override
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni
index 10c2828..ccb0de3 100644
--- a/chrome/android/java_sources.gni
+++ b/chrome/android/java_sources.gni
@@ -845,7 +845,6 @@
   "java/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapter.java",
   "java/src/org/chromium/chrome/browser/ntp/cards/NewTabPageRecyclerView.java",
   "java/src/org/chromium/chrome/browser/ntp/cards/NewTabPageViewHolder.java",
-  "java/src/org/chromium/chrome/browser/ntp/cards/NodeVisitor.java",
   "java/src/org/chromium/chrome/browser/ntp/cards/OptionalLeaf.java",
   "java/src/org/chromium/chrome/browser/ntp/cards/ProgressIndicatorView.java",
   "java/src/org/chromium/chrome/browser/ntp/cards/ProgressItem.java",
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java
index 04b05cca..7f41ec8 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java
@@ -12,6 +12,7 @@
 import android.app.Instrumentation;
 import android.app.Instrumentation.ActivityMonitor;
 import android.graphics.Canvas;
+import android.os.Build;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.LargeTest;
 import android.support.test.filters.MediumTest;
@@ -163,6 +164,11 @@
 
     @ParameterAnnotations.UseMethodParameterBefore(InterestFeedParams.class)
     public void setupInterestFeed(boolean interestFeedEnabled) {
+        // TODO(twellington): Re-enable interest Feed test on arm64 M. See https://crbug.com/854866.
+        if (Build.VERSION.SDK_INT == Build.VERSION_CODES.M
+                && Arrays.asList(Build.SUPPORTED_ABIS).contains("arm64-v8a")) {
+            interestFeedEnabled = false;
+        }
         if (interestFeedEnabled) {
             Features.getInstance().enable(ChromeFeatureList.INTEREST_FEED_CONTENT_SUGGESTIONS);
         } else {
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapterTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapterTest.java
index 429ee056e..ff1372c 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapterTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/NewTabPageAdapterTest.java
@@ -4,30 +4,28 @@
 
 package org.chromium.chrome.browser.ntp.cards;
 
+import static org.hamcrest.Matchers.is;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.atLeast;
 import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.inOrder;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
 import static org.mockito.Mockito.when;
 
 import static org.chromium.chrome.browser.ntp.cards.ContentSuggestionsUnitTestUtils.makeUiConfig;
 import static org.chromium.chrome.test.util.browser.suggestions.ContentSuggestionsTestUtils.createDummySuggestions;
 import static org.chromium.chrome.test.util.browser.suggestions.ContentSuggestionsTestUtils.registerCategory;
-import static org.chromium.chrome.test.util.browser.suggestions.ContentSuggestionsTestUtils.stringify;
 
 import android.accounts.Account;
 import android.content.res.Resources;
@@ -43,13 +41,8 @@
 import org.junit.rules.TestRule;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
-import org.mockito.InOrder;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
-import org.mockito.exceptions.base.MockitoAssertionError;
-import org.mockito.internal.verification.Times;
-import org.mockito.internal.verification.api.VerificationDataInOrder;
-import org.mockito.verification.VerificationMode;
 import org.robolectric.annotation.Config;
 import org.robolectric.annotation.Implementation;
 import org.robolectric.annotation.Implements;
@@ -94,6 +87,7 @@
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
+import java.util.Locale;
 
 /**
  * Unit tests for {@link NewTabPageAdapter}. {@link AccountManagerFacade} uses AsyncTasks, thus
@@ -101,11 +95,9 @@
  */
 @RunWith(BaseRobolectricTestRunner.class)
 @Config(manifest = Config.NONE, shadows = {CustomShadowAsyncTask.class})
-
 @DisableFeatures({ChromeFeatureList.CONTENT_SUGGESTIONS_SCROLL_TO_LOAD,
         ChromeFeatureList.NTP_ARTICLE_SUGGESTIONS_EXPANDABLE_HEADER,
         ChromeFeatureList.SIMPLIFIED_NTP, ChromeFeatureList.CHROME_DUPLEX})
-
 public class NewTabPageAdapterTest {
     @Rule
     public DisableHistogramsRule mDisableHistogramsRule = new DisableHistogramsRule();
@@ -187,82 +179,67 @@
      * expressed as a sequence of calls to the {@code expect...()} methods.
      */
     private static class ItemsMatcher { // TODO(pke): Find better name.
-        private final TreeNode mRoot;
-        private final NodeVisitor mVisitor = mock(NodeVisitor.class);
-        private final InOrder mInOrder = inOrder(mVisitor);
-
-        /**
-         * The {@link org.mockito.internal.verification.Description} verification mode doesn't
-         * support in-order verification, so we use a custom verification mode that derives from the
-         * default one.
-         */
-        private final VerificationMode mVerification = new Times(1) {
-            @Override
-            public void verifyInOrder(VerificationDataInOrder data) {
-                try {
-                    super.verifyInOrder(data);
-                } catch (MockitoAssertionError e) {
-                    throw new MockitoAssertionError(e, stringify(mRoot));
-                }
-            }
-        };
+        private final List<String> mExpectedDescriptions = new ArrayList<>();
+        private final List<String> mActualDescriptions = new ArrayList<>();
 
         public ItemsMatcher(TreeNode root) {
-            mRoot = root;
-            root.visitItems(mVisitor);
+            for (int i = 0; i < root.getItemCount(); i++) {
+                mActualDescriptions.add(root.describeItemForTesting(i));
+            }
+        }
+
+        private void expectDescription(String description) {
+            mExpectedDescriptions.add(description);
         }
 
         public void expectSection(SectionDescriptor descriptor) {
             if (descriptor.mIsSignInPromo) {
-                mInOrder.verify(mVisitor, mVerification).visitSignInPromo();
+                expectDescription("SIGN_IN_PROMO");
                 return;
             }
 
             if (descriptor.mHeader) {
-                mInOrder.verify(mVisitor, mVerification).visitHeader();
+                expectDescription("HEADER");
             }
 
             for (SnippetArticle suggestion : descriptor.mSuggestions) {
-                mInOrder.verify(mVisitor, mVerification).visitSuggestion(eq(suggestion));
+                expectDescription(
+                        String.format(Locale.US, "SUGGESTION(%1.42s)", suggestion.mTitle));
             }
 
             if (descriptor.mStatusCard) {
-                mInOrder.verify(mVisitor, mVerification).visitNoSuggestionsItem();
+                expectDescription("NO_SUGGESTIONS");
             }
 
             if (descriptor.mViewAllButton) {
-                mInOrder.verify(mVisitor, mVerification)
-                        .visitActionItem(ContentSuggestionsAdditionalAction.VIEW_ALL);
+                expectDescription(String.format(
+                        Locale.US, "ACTION(%d)", ContentSuggestionsAdditionalAction.VIEW_ALL));
             }
 
             if (descriptor.mFetchButton) {
-                mInOrder.verify(mVisitor, mVerification)
-                        .visitActionItem(ContentSuggestionsAdditionalAction.FETCH);
+                expectDescription(String.format(
+                        Locale.US, "ACTION(%d)", ContentSuggestionsAdditionalAction.FETCH));
             }
 
             if (descriptor.mProgressItem) {
-                mInOrder.verify(mVisitor, mVerification).visitProgressItem();
+                expectDescription("PROGRESS");
             }
         }
 
         public void expectAboveTheFoldItem() {
-            mInOrder.verify(mVisitor, mVerification).visitAboveTheFoldItem();
+            expectDescription("ABOVE_THE_FOLD");
         }
 
         public void expectAllDismissedItem() {
-            mInOrder.verify(mVisitor, mVerification).visitAllDismissedItem();
+            expectDescription("ALL_DISMISSED");
         }
 
         public void expectFooter() {
-            mInOrder.verify(mVisitor, mVerification).visitFooter();
+            expectDescription("FOOTER");
         }
 
-        public void expectEnd() {
-            try {
-                verifyNoMoreInteractions(mVisitor);
-            } catch (MockitoAssertionError e) {
-                throw new MockitoAssertionError(e, stringify(mRoot));
-            }
+        public void finish() {
+            assertThat(mActualDescriptions, is(mExpectedDescriptions));
         }
     }
 
@@ -1175,7 +1152,7 @@
     private void assertSectionMatches(SectionDescriptor descriptor, SuggestionsSection section) {
         ItemsMatcher matcher = new ItemsMatcher(section);
         matcher.expectSection(descriptor);
-        matcher.expectEnd();
+        matcher.finish();
     }
 
     /**
@@ -1194,7 +1171,7 @@
         } else {
             matcher.expectFooter();
         }
-        matcher.expectEnd();
+        matcher.finish();
     }
 
     /**
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/SuggestionsSectionTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/SuggestionsSectionTest.java
index b41fbdc..321b5441 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/SuggestionsSectionTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/ntp/cards/SuggestionsSectionTest.java
@@ -1011,14 +1011,11 @@
         return new TreeSet<>(Arrays.asList(elements));
     }
 
-    private static List<SnippetArticle> getSuggestions(TreeNode root) {
-        final List<SnippetArticle> suggestions = new ArrayList<>();
-        root.visitItems(new NodeVisitor() {
-            @Override
-            public void visitSuggestion(SnippetArticle suggestion) {
-                suggestions.add(suggestion);
-            }
-        });
+    private static List<SnippetArticle> getSuggestions(SuggestionsSection section) {
+        ArrayList<SnippetArticle> suggestions = new ArrayList<>(section.getSuggestionsCount());
+        for (int i = 0; i < section.getSuggestionsCount(); i++) {
+            suggestions.add(section.getSuggestionForTesting(i));
+        }
         return suggestions;
     }
 
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp
index 23a8acb..b912837 100644
--- a/chrome/app/chromeos_strings.grdp
+++ b/chrome/app/chromeos_strings.grdp
@@ -4710,7 +4710,37 @@
   <message name="IDS_ASSISTANT_GET_MORE_SCREEN_TITLE" desc="Title for assistant get more screen.">
     Get the most out of your Assistant
   </message>
-  <message name="IDS_ASSISTANT_GET_MORE_SCREEN_CONTINUE_BUTTON" desc="Button label for accepting the get more screen.">
+  <message name="IDS_ASSISTANT_READY_SCREEN_TITLE" desc="Title for assistant ready screen.">
+    Your Assistant is ready
+  </message>
+  <message name="IDS_ASSISTANT_READY_SCREEN_MESSAGE" desc="Message for assistant ready screen.">
+    When your Chromebook is set up, press the Assistant button or say "OK Google" to get help from your Assistant anytime.
+  </message>
+  <message name="IDS_ASSISTANT_THIRD_PARTY_SCREEN_TITLE" desc="Title for assitant third party screen.">
+    Google Partners work with your Assistant to help you
+  </message>
+  <message name="IDS_ASSISTANT_CONFIRM_SCREEN_TITLE" desc="Title for assistant confirm screen.">
+    Get the full Assistant experience with these settings
+  </message>
+  <message name="IDS_ASSISTANT_CONFIRM_SCREEN_ACCEPT_TITLE" desc="Title for accept assistant confirm screen.">
+    Yes I'm In
+  </message>
+  <message name="IDS_ASSISTANT_CONFIRM_SCREEN_ACCEPT_MESSAGE" desc="Message for accept assistant confirm screen.">
+    To help you with your calendar, reminders, flights and more, your Assistant needs the Web &amp; App Activity, Device Information, Voice &amp; Audio Activity settings.
+  </message>
+  <message name="IDS_ASSISTANT_CONFIRM_SCREEN_ACCEPT_MESSAGE_EXPANDED" desc="Extra message for accept assistant confirm screen.">
+    Note: The data these settings control may be saved and used in any Google service where you are signed in to give you personalized experiences and useful ads. You can see your data, delete it and change your settings at account.google.com.
+  </message>
+  <message name="IDS_ASSISTANT_CONFIRM_SCREEN_REJECT_TITLE" desc="Title for reject assistant confirm screen.">
+    No Thanks
+  </message>
+  <message name="IDS_ASSISTANT_CONFIRM_SCREEN_REJECT_MESSAGE" desc="Message for reject assistant confirm screen.">
+    Depending on your account settings, your Assistant experience may be limited to things like web results, jokes, and local info.
+  </message>
+  <message name="IDS_ASSISTANT_CONTINUE_BUTTON" desc="Continue button for asssitant optin flow.">
+    Continue
+  </message>
+  <message name="IDS_ASSISTANT_DONE_BUTTON" desc="Done button for asssitant optin flow.">
     Done
   </message>
 
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp
index 2d23967..8e24253 100644
--- a/chrome/app/settings_strings.grdp
+++ b/chrome/app/settings_strings.grdp
@@ -3173,6 +3173,9 @@
   <message name="IDS_SETTINGS_PEOPLE_SYNC_UNIFIED_CONSENT_TOGGLE_SUBTITLE" desc="The subtitle of the toggle to opt into unified consent and enable all its services.">
     Uses content on sites you visit and browser activity and interations.
   </message>
+  <message name="IDS_SETTINGS_PEOPLE_SIGN_OUT" desc="The label of the button that lets user sign-out of Chrome.">
+    Sign out
+  </message>
 
   <if expr="chromeos">
     <message name="IDS_SETTINGS_PEOPLE_CONFIGURE_PIN_CHOOSE_PIN_TITLE" desc="Message shown below the title that tells the user to enter the initial PIN.">
@@ -3417,9 +3420,6 @@
   <message name="IDS_SETTINGS_SYNC_OVERVIEW" desc="The message that appears in the options dialog when sync has not been set up by the user.">
     Sign in to get your bookmarks, history, passwords, and other settings on all your devices. You'll also automatically be signed in to your Google services.
   </message>
-  <message name="IDS_SETTINGS_SYNC_DISCONNECT" desc="The text to display on the button to indicate stop syncing functionality.">
-    Sign Out
-  </message>
   <message name="IDS_SETTINGS_SYNC_DISCONNECT_EXPLANATION" desc="The text to display in the Sign out of Chrome dialog to stop syncing for non-managed profiles.">
     Changes to your bookmarks, history, passwords, and other settings will no longer be synced to your Google Account. However, your existing data will remain stored in your Google Account and can be managed on <ph name="BEGIN_LINK">&lt;a href="$1" target=&quot;_blank&quot;&gt;<ex>&lt;a href="$1" target=&quot;_blank&quot;&gt;</ex></ph>Google Dashboard<ph name="END_LINK">&lt;/a&gt;<ex>&lt;/a&gt;</ex></ph>.
   </message>
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 7ef9503..bb1a0e8 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -1289,6 +1289,8 @@
     "resources_util.h",
     "search/instant_io_context.cc",
     "search/instant_io_context.h",
+    "search/ntp_icon_source.cc",
+    "search/ntp_icon_source.h",
     "search/search.cc",
     "search/search.h",
     "search/suggestions/image_decoder_impl.cc",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index f89c8d1..c630f0c 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -228,6 +228,19 @@
 
 #endif  // USE_AURA
 
+const FeatureEntry::Choice kOverlayStrategiesChoices[] = {
+    {flag_descriptions::kOverlayStrategiesDefault, "", ""},
+    {flag_descriptions::kOverlayStrategiesNone,
+     switches::kEnableHardwareOverlays, ""},
+    {flag_descriptions::kOverlayStrategiesUnoccludedFullscreen,
+     switches::kEnableHardwareOverlays, "single-fullscreen"},
+    {flag_descriptions::kOverlayStrategiesUnoccluded,
+     switches::kEnableHardwareOverlays, "single-fullscreen,single-on-top"},
+    {flag_descriptions::kOverlayStrategiesOccludedAndUnoccluded,
+     switches::kEnableHardwareOverlays,
+     "single-fullscreen,single-on-top,underlay"},
+};
+
 const FeatureEntry::Choice kTouchTextSelectionStrategyChoices[] = {
     {flags_ui::kGenericExperimentChoiceDefault, "", ""},
     {flag_descriptions::kTouchSelectionStrategyCharacter,
@@ -1156,6 +1169,9 @@
     {"composited-layer-borders", flag_descriptions::kCompositedLayerBordersName,
      flag_descriptions::kCompositedLayerBordersDescription, kOsAll,
      SINGLE_VALUE_TYPE(cc::switches::kShowCompositedLayerBorders)},
+    {"overlay-strategies", flag_descriptions::kOverlayStrategiesName,
+     flag_descriptions::kOverlayStrategiesDescription, kOsAll,
+     MULTI_VALUE_TYPE(kOverlayStrategiesChoices)},
     {"tint-gl-composited-content",
      flag_descriptions::kTintGlCompositedContentName,
      flag_descriptions::kTintGlCompositedContentDescription, kOsAll,
@@ -3314,12 +3330,13 @@
      flag_descriptions::kClickToOpenPDFDescription, kOsAll,
      FEATURE_VALUE_TYPE(features::kClickToOpenPDFPlaceholder)},
 
-#if defined(OS_WIN)
+#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX)
     {"direct-manipulation-stylus",
      flag_descriptions::kDirectManipulationStylusName,
-     flag_descriptions::kDirectManipulationStylusDescription, kOsWin,
+     flag_descriptions::kDirectManipulationStylusDescription,
+     kOsWin | kOsMac | kOsLinux,
      FEATURE_VALUE_TYPE(features::kDirectManipulationStylus)},
-#endif  // defined(OS_WIN)
+#endif  // defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX)
 
 #if !defined(OS_ANDROID)
     {"remove-deprecared-gaia-signin-endpoint",
diff --git a/chrome/browser/android/signin/signin_manager_android.cc b/chrome/browser/android/signin/signin_manager_android.cc
index 0ff10d2..92b751f 100644
--- a/chrome/browser/android/signin/signin_manager_android.cc
+++ b/chrome/browser/android/signin/signin_manager_android.cc
@@ -44,6 +44,7 @@
 #include "components/signin/core/browser/signin_pref_names.h"
 #include "content/public/browser/browsing_data_filter_builder.h"
 #include "content/public/browser/browsing_data_remover.h"
+#include "content/public/browser/storage_partition.h"
 #include "google_apis/gaia/gaia_auth_util.h"
 #include "google_apis/gaia/gaia_constants.h"
 #include "jni/SigninManager_jni.h"
@@ -172,11 +173,15 @@
   if (!dm_token_.empty()) {
     policy::UserPolicySigninService* service =
         policy::UserPolicySigninServiceFactory::GetForProfile(profile_);
+    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory =
+        content::BrowserContext::GetDefaultStoragePartition(profile_)
+            ->GetURLLoaderFactoryForBrowserProcess();
     service->FetchPolicyForSignedInUser(
         AccountTrackerServiceFactory::GetForProfile(profile_)
             ->FindAccountInfoByEmail(username_)
             .GetAccountId(),
         dm_token_, client_id_, profile_->GetRequestContext(),
+        url_loader_factory,
         base::Bind(&SigninManagerAndroid::OnPolicyFetchDone,
                    weak_factory_.GetWeakPtr()));
     dm_token_.clear();
diff --git a/chrome/browser/background/background_application_list_model.cc b/chrome/browser/background/background_application_list_model.cc
index 8e03331..1dfc6338 100644
--- a/chrome/browser/background/background_application_list_model.cc
+++ b/chrome/browser/background/background_application_list_model.cc
@@ -6,6 +6,7 @@
 
 #include <algorithm>
 #include <set>
+#include <utility>
 
 #include "base/strings/string_number_conversions.h"
 #include "chrome/app/chrome_command_ids.h"
@@ -106,15 +107,10 @@
 
 }  // namespace
 
-void
-BackgroundApplicationListModel::Observer::OnApplicationDataChanged(
-    const Extension* extension, Profile* profile) {
-}
+void BackgroundApplicationListModel::Observer::OnApplicationDataChanged() {}
 
-void
-BackgroundApplicationListModel::Observer::OnApplicationListChanged(
-    Profile* profile) {
-}
+void BackgroundApplicationListModel::Observer::OnApplicationListChanged(
+    const Profile* profile) {}
 
 BackgroundApplicationListModel::Observer::~Observer() {
 }
@@ -132,7 +128,7 @@
   if (image.IsEmpty())
     return;
   icon_.reset(image.CopyImageSkia());
-  model_->SendApplicationDataChangedNotifications(extension_);
+  model_->SendApplicationDataChangedNotifications();
 }
 
 void BackgroundApplicationListModel::Application::RequestIcon(
@@ -304,10 +300,9 @@
   }
 }
 
-void BackgroundApplicationListModel::SendApplicationDataChangedNotifications(
-    const Extension* extension) {
+void BackgroundApplicationListModel::SendApplicationDataChangedNotifications() {
   for (auto& observer : observers_)
-    observer.OnApplicationDataChanged(extension, profile_);
+    observer.OnApplicationDataChanged();
 }
 
 void BackgroundApplicationListModel::OnExtensionLoaded(
diff --git a/chrome/browser/background/background_application_list_model.h b/chrome/browser/background/background_application_list_model.h
index 7abe622b..0d4fca5 100644
--- a/chrome/browser/background/background_application_list_model.h
+++ b/chrome/browser/background/background_application_list_model.h
@@ -8,6 +8,7 @@
 #include <stddef.h>
 
 #include <map>
+#include <memory>
 #include <string>
 
 #include "base/macros.h"
@@ -43,15 +44,13 @@
   // Observers of the model.
   class Observer {
    public:
-    // Invoked when data that the model associates with the extension, such as
+    // Invoked when data that the model associates with an extension, such as
     // the Icon, has changed.
-    virtual void OnApplicationDataChanged(
-        const extensions::Extension* extension,
-        Profile* profile);
+    virtual void OnApplicationDataChanged();
 
     // Invoked when the model detects a previously unknown extension and/or when
     // it no longer detects a previously known extension.
-    virtual void OnApplicationListChanged(Profile* profile);
+    virtual void OnApplicationListChanged(const Profile* profile);
 
    protected:
     virtual ~Observer();
@@ -140,9 +139,8 @@
   void OnExtensionSystemReady();
 
   // Notifies observers that some of the data associated with this background
-  // application, e. g. the Icon, has changed.
-  void SendApplicationDataChangedNotifications(
-      const extensions::Extension* extension);
+  // application, e.g. the Icon, has changed.
+  void SendApplicationDataChangedNotifications();
 
   // Notifies observers that at least one background application has been added
   // or removed.
@@ -162,7 +160,7 @@
 
   extensions::ExtensionList extensions_;
   base::ObserverList<Observer, true> observers_;
-  Profile* profile_;
+  Profile* const profile_;
   content::NotificationRegistrar registrar_;
   bool ready_;
 
diff --git a/chrome/browser/background/background_mode_manager.cc b/chrome/browser/background/background_mode_manager.cc
index 3f6cef2..5b1d737e 100644
--- a/chrome/browser/background/background_mode_manager.cc
+++ b/chrome/browser/background/background_mode_manager.cc
@@ -19,6 +19,7 @@
 #include "base/metrics/histogram_macros.h"
 #include "base/metrics/user_metrics.h"
 #include "base/single_thread_task_runner.h"
+#include "base/stl_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
@@ -100,10 +101,9 @@
 BackgroundModeManager::BackgroundModeData::BackgroundModeData(
     Profile* profile,
     CommandIdHandlerVector* command_id_handler_vector)
-    : applications_(new BackgroundApplicationListModel(profile)),
+    : applications_(std::make_unique<BackgroundApplicationListModel>(profile)),
       profile_(profile),
-      command_id_handler_vector_(command_id_handler_vector) {
-}
+      command_id_handler_vector_(command_id_handler_vector) {}
 
 BackgroundModeManager::BackgroundModeData::~BackgroundModeData() {
 }
@@ -129,21 +129,14 @@
   return BackgroundModeManager::GetBrowserWindowForProfile(profile_);
 }
 
-int BackgroundModeManager::BackgroundModeData::GetBackgroundClientCount()
-    const {
-  return applications_->size() + registered_triggers_.size();
+bool BackgroundModeManager::BackgroundModeData::HasBackgroundClient() const {
+  return applications_->size() > 0 || !registered_triggers_.empty();
 }
 
 void BackgroundModeManager::BackgroundModeData::BuildProfileMenu(
     StatusIconMenuModel* menu,
     StatusIconMenuModel* containing_menu) {
-  // When there are no background clients, we want to display just a label
-  // stating that none are running.
-  if (GetBackgroundClientCount() == 0) {
-    menu->AddItemWithStringId(IDC_MinimumLabelValue,
-                              IDS_BACKGROUND_APP_NOT_INSTALLED);
-    menu->SetCommandIdEnabled(IDC_MinimumLabelValue, false);
-  } else {
+  if (HasBackgroundClient()) {
     // Add a menu item for each application (extension).
     for (const auto& application : *applications_) {
       const gfx::ImageSkia* icon = applications_->GetIcon(application.get());
@@ -151,9 +144,9 @@
       int command_id = command_id_handler_vector_->size();
       // Check that the command ID is within the dynamic range.
       DCHECK_LT(command_id, IDC_MinimumLabelValue);
-      command_id_handler_vector_->push_back(
-          base::Bind(&BackgroundModeManager::LaunchBackgroundApplication,
-                     profile_, base::RetainedRef(application)));
+      command_id_handler_vector_->push_back(base::BindRepeating(
+          &BackgroundModeManager::LaunchBackgroundApplication, profile_,
+          base::RetainedRef(application)));
       menu->AddItem(command_id, base::UTF8ToUTF16(name));
       if (icon)
         menu->SetIcon(menu->GetItemCount() - 1, gfx::Image(*icon));
@@ -182,12 +175,18 @@
       int command_id = command_id_handler_vector_->size();
       // Check that the command ID is within the dynamic range.
       DCHECK_LT(command_id, IDC_MinimumLabelValue);
-      command_id_handler_vector_->push_back(base::Bind(
+      command_id_handler_vector_->push_back(base::BindRepeating(
           &BackgroundTrigger::OnMenuClick, base::Unretained(trigger)));
       menu->AddItem(command_id, name);
       if (icon)
         menu->SetIcon(menu->GetItemCount() - 1, gfx::Image(*icon));
     }
+  } else {
+    // When there are no background clients, we want to display just a label
+    // stating that none are running.
+    menu->AddItemWithStringId(IDC_MinimumLabelValue,
+                              IDS_BACKGROUND_APP_NOT_INSTALLED);
+    menu->SetCommandIdEnabled(IDC_MinimumLabelValue, false);
   }
   if (containing_menu) {
     int menu_command_id = command_id_handler_vector_->size();
@@ -242,16 +241,12 @@
 }
 
 BackgroundModeManager::PendingTriggerData
-BackgroundModeManager::BackgroundModeData::GetPendingTriggerData() const {
-  return pending_trigger_data_;
+BackgroundModeManager::BackgroundModeData::TakePendingTriggerData() {
+  return std::move(pending_trigger_data_);
 }
 
-void BackgroundModeManager::BackgroundModeData::ClearPendingTriggerData() {
-  pending_trigger_data_.clear();
-}
-
-int BackgroundModeManager::BackgroundModeData::GetPendingTriggerCount() const {
-  return pending_trigger_data_.size();
+bool BackgroundModeManager::BackgroundModeData::HasPendingTrigger() const {
+  return !pending_trigger_data_.empty();
 }
 
 void BackgroundModeManager::BackgroundModeData::RegisterTrigger(
@@ -269,9 +264,8 @@
 
 bool BackgroundModeManager::BackgroundModeData::HasTrigger(
     BackgroundTrigger* trigger) {
-  if (registered_triggers_.find(trigger) != registered_triggers_.end())
-    return true;
-  return pending_trigger_data_.find(trigger) != pending_trigger_data_.end();
+  return base::ContainsKey(registered_triggers_, trigger) ||
+         base::ContainsKey(pending_trigger_data_, trigger);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -280,17 +274,11 @@
     const base::CommandLine& command_line,
     ProfileAttributesStorage* profile_storage)
     : profile_storage_(profile_storage),
-      status_tray_(NULL),
-      status_icon_(NULL),
-      context_menu_(NULL),
-      in_background_mode_(false),
-      keep_alive_for_test_(false),
-      background_mode_suspended_(false),
       task_runner_(CreateTaskRunner()),
       weak_factory_(this) {
   // We should never start up if there is no browser process or if we are
   // currently quitting.
-  CHECK(g_browser_process != NULL);
+  CHECK(g_browser_process);
   CHECK(!browser_shutdown::IsTryingToQuit());
 
   // Add self as an observer for the ProfileAttributesStorage so we know when
@@ -307,8 +295,9 @@
     pref_registrar_.Init(g_browser_process->local_state());
     pref_registrar_.Add(
         prefs::kBackgroundModeEnabled,
-        base::Bind(&BackgroundModeManager::OnBackgroundModeEnabledPrefChanged,
-                   base::Unretained(this)));
+        base::BindRepeating(
+            &BackgroundModeManager::OnBackgroundModeEnabledPrefChanged,
+            base::Unretained(this)));
   }
 
   // Keep the browser alive until extensions are done loading - this is needed
@@ -345,7 +334,7 @@
   // Remove ourselves from the application observer list (only needed by unit
   // tests since APP_TERMINATING is what does this in a real running system).
   for (const auto& it : background_mode_data_)
-    it.second->applications_->RemoveObserver(this);
+    it.second->applications()->RemoveObserver(this);
   BrowserList::RemoveObserver(this);
 
   // We're going away, so exit background mode (does nothing if we aren't in
@@ -367,10 +356,11 @@
 
 void BackgroundModeManager::RegisterProfile(Profile* profile) {
   // We don't want to register multiple times for one profile.
-  DCHECK(background_mode_data_.find(profile) == background_mode_data_.end());
-  BackgroundModeInfo bmd(
-      new BackgroundModeData(profile, &command_id_handler_vector_));
-  background_mode_data_[profile] = bmd;
+  DCHECK(!base::ContainsKey(background_mode_data_, profile));
+  auto bmd = std::make_unique<BackgroundModeData>(profile,
+                                                  &command_id_handler_vector_);
+  BackgroundModeData* bmd_ptr = bmd.get();
+  background_mode_data_[profile] = std::move(bmd);
 
   // Initially set the name for this background mode data.
   base::string16 name = l10n_util::GetStringUTF16(IDS_PROFILES_DEFAULT_NAME);
@@ -379,7 +369,7 @@
       profile->GetPath(), &entry)) {
     name = entry->GetName();
   }
-  bmd->SetName(name);
+  bmd_ptr->SetName(name);
 
   // Check for the presence of background apps after all extensions have been
   // loaded, to handle the case where an extension has been manually removed
@@ -389,7 +379,7 @@
       base::Bind(&BackgroundModeManager::OnExtensionsReady,
         weak_factory_.GetWeakPtr(), profile));
 
-  bmd->applications_->AddObserver(this);
+  bmd_ptr->applications()->AddObserver(this);
 
   // If we're adding a new profile and running in multi-profile mode, this new
   // profile should be added to the status icon if one currently exists.
@@ -432,11 +422,11 @@
   });
 }
 
-int BackgroundModeManager::NumberOfBackgroundModeData() {
+size_t BackgroundModeManager::NumberOfBackgroundModeData() {
   return background_mode_data_.size();
 }
 
-void BackgroundModeManager::RegisterTrigger(Profile* profile,
+void BackgroundModeManager::RegisterTrigger(const Profile* profile,
                                             BackgroundTrigger* trigger,
                                             bool should_notify_user) {
   BackgroundModeManager::BackgroundModeData* bmd =
@@ -462,7 +452,7 @@
   OnClientsChanged(profile, new_client_names);
 }
 
-void BackgroundModeManager::UnregisterTrigger(Profile* profile,
+void BackgroundModeManager::UnregisterTrigger(const Profile* profile,
                                               BackgroundTrigger* trigger) {
   if (!IsBackgroundModePrefEnabled())
     return;
@@ -499,15 +489,15 @@
   // try to re-enter/exit background mode again.
   registrar_.RemoveAll();
   for (const auto& it : background_mode_data_)
-    it.second->applications_->RemoveObserver(this);
+    it.second->applications()->RemoveObserver(this);
 }
 
-void BackgroundModeManager::OnExtensionsReady(Profile* profile) {
+void BackgroundModeManager::OnExtensionsReady(const Profile* profile) {
   BackgroundModeManager::BackgroundModeData* bmd =
       GetBackgroundModeData(profile);
   if (bmd) {
     UMA_HISTOGRAM_COUNTS_100("BackgroundMode.BackgroundApplicationsCount",
-        bmd->applications_->size());
+                             bmd->applications()->size());
   }
   // Extensions are loaded, so we don't need to manually keep the browser
   // process alive any more when running in no-startup-window mode.
@@ -526,12 +516,11 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 //  BackgroundModeManager, BackgroundApplicationListModel::Observer overrides
-void BackgroundModeManager::OnApplicationDataChanged(
-    const Extension* extension, Profile* profile) {
+void BackgroundModeManager::OnApplicationDataChanged() {
   UpdateStatusTrayIconContextMenu();
 }
 
-void BackgroundModeManager::OnApplicationListChanged(Profile* profile) {
+void BackgroundModeManager::OnApplicationListChanged(const Profile* profile) {
   if (!IsBackgroundModePrefEnabled())
     return;
 
@@ -581,7 +570,7 @@
       GetBackgroundModeIterator(profile_name);
   // If a profile isn't running a background app, it may not be in the map.
   if (it != background_mode_data_.end()) {
-    it->second->applications_->RemoveObserver(this);
+    it->second->applications()->RemoveObserver(this);
     background_mode_data_.erase(it);
     // If there are no background mode profiles any longer, then turn off
     // background mode.
@@ -620,7 +609,7 @@
       background_mode_data_.find(most_recent_profile);
 
   if (profile_background_data == background_mode_data_.end())
-    return NULL;
+    return nullptr;
 
   // Do not permit a locked profile to be used to open a browser.
   ProfileAttributesEntry* entry;
@@ -628,7 +617,7 @@
       profile_background_data->first->GetPath(), &entry);
   DCHECK(success);
   if (entry->IsSigninRequired())
-    return NULL;
+    return nullptr;
 
   return profile_background_data->second.get();
 }
@@ -750,10 +739,9 @@
     // Register pending triggers.
     for (const auto& bmd_iterator : background_mode_data_) {
       PendingTriggerData pending_trigger_data =
-          bmd_iterator.second->GetPendingTriggerData();
-      bmd_iterator.second->ClearPendingTriggerData();
+          bmd_iterator.second->TakePendingTriggerData();
       for (const auto& trigger_data_iterator : pending_trigger_data) {
-        Profile* profile = bmd_iterator.first;
+        const Profile* profile = bmd_iterator.first;
         BackgroundTrigger* trigger = trigger_data_iterator.first;
         bool should_notify_user = trigger_data_iterator.second;
         RegisterTrigger(profile, trigger, should_notify_user);
@@ -786,9 +774,9 @@
 void BackgroundModeManager::UpdateKeepAliveAndTrayIcon() {
   if (in_background_mode_ && !background_mode_suspended_) {
     if (!keep_alive_) {
-      keep_alive_.reset(
-          new ScopedKeepAlive(KeepAliveOrigin::BACKGROUND_MODE_MANAGER,
-                              KeepAliveRestartOption::ENABLED));
+      keep_alive_ = std::make_unique<ScopedKeepAlive>(
+          KeepAliveOrigin::BACKGROUND_MODE_MANAGER,
+          KeepAliveRestartOption::ENABLED);
     }
     CreateStatusTrayIcon();
     return;
@@ -803,7 +791,7 @@
 }
 
 void BackgroundModeManager::OnClientsChanged(
-    Profile* profile,
+    const Profile* profile,
     const std::vector<base::string16>& new_client_names) {
   DCHECK(IsBackgroundModePrefEnabled());
 
@@ -812,8 +800,7 @@
   ProfileAttributesEntry* entry;
   if (profile_storage_->
       GetProfileAttributesWithPath(profile->GetPath(), &entry)) {
-    entry->SetBackgroundStatus(
-        GetBackgroundClientCountForProfile(profile) != 0);
+    entry->SetBackgroundStatus(HasBackgroundClientForProfile(profile));
   }
 
   if (!ShouldBeInBackgroundMode()) {
@@ -842,36 +829,32 @@
   }
 }
 
-int BackgroundModeManager::GetBackgroundClientCount() const {
-  int count = 0;
-  // Walk the BackgroundModeData for all profiles and count the number of
-  // clients.
-  for (const auto& it : background_mode_data_)
-    count += it.second->GetBackgroundClientCount();
-  DCHECK(count >= 0);
-  return count;
+bool BackgroundModeManager::HasBackgroundClient() const {
+  for (const auto& it : background_mode_data_) {
+    if (it.second->HasBackgroundClient())
+      return true;
+  }
+  return false;
 }
 
-int BackgroundModeManager::GetBackgroundClientCountForProfile(
-    Profile* const profile) const {
+bool BackgroundModeManager::HasBackgroundClientForProfile(
+    const Profile* profile) const {
   BackgroundModeManager::BackgroundModeData* bmd =
       GetBackgroundModeData(profile);
-  if (!bmd)
-    return 0;
-  return bmd->GetBackgroundClientCount();
+  return bmd && bmd->HasBackgroundClient();
 }
 
-int BackgroundModeManager::GetPendingTriggerCount() const {
-  int count = 0;
-  for (const auto& it : background_mode_data_)
-    count += it.second->GetPendingTriggerCount();
-  return count;
+bool BackgroundModeManager::HasPendingTrigger() const {
+  for (const auto& it : background_mode_data_) {
+    if (it.second->HasPendingTrigger())
+      return true;
+  }
+  return false;
 }
 
 bool BackgroundModeManager::ShouldBeInBackgroundMode() const {
   return IsBackgroundModePrefEnabled() &&
-         (GetBackgroundClientCount() > 0 || GetPendingTriggerCount() > 0 ||
-          keep_alive_for_test_);
+         (HasBackgroundClient() || HasPendingTrigger() || keep_alive_for_test_);
 }
 
 void BackgroundModeManager::OnBackgroundClientInstalled(
@@ -975,7 +958,7 @@
     for (auto* bmd : bmd_vector) {
       // We should only display the profile in the status icon if it has at
       // least one background app.
-      if (bmd->GetBackgroundClientCount() > 0) {
+      if (bmd->HasBackgroundClient()) {
         // The submenu constructor caller owns the lifetime of the submenu.
         // The containing menu does not handle the lifetime.
         submenus.push_back(std::make_unique<StatusIconMenuModel>(bmd));
@@ -993,7 +976,8 @@
     // not have any profiles in the ProfileAttributesStorage.
     DCHECK(profile_storage_->GetNumberOfProfiles() == size_t(1) ||
            keep_alive_for_test_);
-    background_mode_data_.begin()->second->BuildProfileMenu(menu.get(), NULL);
+    background_mode_data_.begin()->second->BuildProfileMenu(menu.get(),
+                                                            nullptr);
   }
 
   menu->AddSeparator(ui::NORMAL_SEPARATOR);
@@ -1019,18 +1003,17 @@
 void BackgroundModeManager::RemoveStatusTrayIcon() {
   if (status_icon_)
     status_tray_->RemoveStatusIcon(status_icon_);
-  status_icon_ = NULL;
-  context_menu_ = NULL;
+  status_icon_ = nullptr;
+  context_menu_ = nullptr;
 }
 
 BackgroundModeManager::BackgroundModeData*
-BackgroundModeManager::GetBackgroundModeData(Profile* const profile) const {
+BackgroundModeManager::GetBackgroundModeData(const Profile* profile) const {
   // Profiles are shut down and destroyed asynchronously after
   // OnProfileWillBeRemoved is called, so we may have dropped anything
   // associated with the profile already.
-  if (background_mode_data_.find(profile) == background_mode_data_.end())
-    return NULL;
-  return background_mode_data_.find(profile)->second.get();
+  auto it = background_mode_data_.find(profile);
+  return it != background_mode_data_.end() ? it->second.get() : nullptr;
 }
 
 BackgroundModeManager::BackgroundModeInfoMap::iterator
diff --git a/chrome/browser/background/background_mode_manager.h b/chrome/browser/background/background_mode_manager.h
index d943c117..b2c35b6 100644
--- a/chrome/browser/background/background_mode_manager.h
+++ b/chrome/browser/background/background_mode_manager.h
@@ -13,7 +13,6 @@
 #include "base/callback_forward.h"
 #include "base/gtest_prod_util.h"
 #include "base/macros.h"
-#include "base/memory/linked_ptr.h"
 #include "base/memory/weak_ptr.h"
 #include "base/sequenced_task_runner.h"
 #include "chrome/browser/background/background_application_list_model.h"
@@ -44,7 +43,7 @@
 class Extension;
 }
 
-typedef std::vector<base::Closure> CommandIdHandlerVector;
+using CommandIdHandlerVector = std::vector<base::RepeatingClosure>;
 
 // BackgroundModeManager is responsible for switching Chrome into and out of
 // "background mode" and for providing UI for the user to exit Chrome when there
@@ -74,7 +73,8 @@
 
   virtual void RegisterProfile(Profile* profile);
 
-  static void LaunchBackgroundApplication(Profile* profile,
+  static void LaunchBackgroundApplication(
+      Profile* profile,
       const extensions::Extension* extension);
 
   // Gets a browser window for |profile| associated with the active desktop.
@@ -107,16 +107,16 @@
   virtual void ResumeBackgroundMode();
 
   // For testing purposes.
-  int NumberOfBackgroundModeData();
+  size_t NumberOfBackgroundModeData();
 
   // Registers |trigger| as a reason for enabling background mode. Does not
-  // take ownership of |profile| or |trigger|.
-  void RegisterTrigger(Profile* profile,
+  // take ownership of |trigger|.
+  void RegisterTrigger(const Profile* profile,
                        BackgroundTrigger* trigger,
                        bool should_notify_user);
 
   // Unregisters |trigger| as a reason for enabling background mode.
-  void UnregisterTrigger(Profile* profile, BackgroundTrigger* trigger);
+  void UnregisterTrigger(const Profile* profile, BackgroundTrigger* trigger);
 
  private:
   friend class AppBackgroundPageApiTest;
@@ -170,20 +170,21 @@
                        CommandIdHandlerVector* command_id_handler_vector);
     ~BackgroundModeData() override;
 
-    // The cached list of BackgroundApplications.
-    std::unique_ptr<BackgroundApplicationListModel> applications_;
-
     // Overrides from StatusIconMenuModel::Delegate implementation.
     void ExecuteCommand(int command_id, int event_flags) override;
 
+    BackgroundApplicationListModel* applications() {
+      return applications_.get();
+    }
+
     // Returns a browser window, or creates one if none are open. Used by
     // operations (like displaying the preferences dialog) that require a
     // Browser window.
     Browser* GetBrowserWindow();
 
-    // Returns the number of background clients for this profile. A client can
-    // be a trigger or an extension.
-    int GetBackgroundClientCount() const;
+    // Returns if this profile has background clients. A client can be a trigger
+    // or an extension.
+    bool HasBackgroundClient() const;
 
     // Builds the profile specific parts of the menu. The menu passed in may
     // be a submenu in the case of multi-profiles or the main menu in the case
@@ -213,14 +214,11 @@
     // RegisterPendingTriggers. Does not take ownership of |trigger|.
     void AddPendingTrigger(BackgroundTrigger* trigger, bool should_notify_user);
 
-    // The pending trigger data.
-    PendingTriggerData GetPendingTriggerData() const;
+    // Takes ownership of the pending trigger data.
+    PendingTriggerData TakePendingTriggerData();
 
-    // Clears the pending trigger data.
-    void ClearPendingTriggerData();
-
-    // Counts the number of pending triggers.
-    int GetPendingTriggerCount() const;
+    // If there are pending triggers.
+    bool HasPendingTrigger() const;
 
     // Registers |trigger| as a reason to enable background mode. Does not take
     // ownership of |trigger|. Idempotent.
@@ -234,15 +232,18 @@
     bool HasTrigger(BackgroundTrigger* trigger);
 
    private:
+    // The cached list of BackgroundApplications.
+    std::unique_ptr<BackgroundApplicationListModel> applications_;
+
     // Name associated with this profile which is used to label its submenu.
     base::string16 name_;
 
     // The profile associated with this background app data.
-    Profile* profile_;
+    Profile* const profile_;
 
     // Weak ref vector owned by BackgroundModeManager where the indices
     // correspond to Command IDs and values correspond to their handlers.
-    CommandIdHandlerVector* command_id_handler_vector_;
+    CommandIdHandlerVector* const command_id_handler_vector_;
 
     // The list of notified extensions for this profile. We track this to ensure
     // that we never notify the user about the same extension twice in a single
@@ -260,16 +261,8 @@
     std::set<BackgroundTrigger*> registered_triggers_;
   };
 
-  // Ideally we would want our BackgroundModeData to be scoped_ptrs,
-  // but since maps copy their entries, we can't used scoped_ptrs.
-  // Similarly, we can't just have a map of BackgroundModeData objects,
-  // since BackgroundModeData contains a scoped_ptr which once again
-  // can't be copied. So rather than using BackgroundModeData* which
-  // we'd have to remember to delete, we use the ref-counted linked_ptr
-  // which is similar to a shared_ptr.
-  typedef linked_ptr<BackgroundModeData> BackgroundModeInfo;
-
-  typedef std::map<Profile*, BackgroundModeInfo> BackgroundModeInfoMap;
+  using BackgroundModeInfoMap =
+      std::map<const Profile*, std::unique_ptr<BackgroundModeData>>;
 
   // content::NotificationObserver implementation.
   void Observe(int type,
@@ -277,15 +270,14 @@
                const content::NotificationDetails& details) override;
 
   // Called when ExtensionSystem is ready.
-  void OnExtensionsReady(Profile* profile);
+  void OnExtensionsReady(const Profile* profile);
 
   // Called when the kBackgroundModeEnabled preference changes.
   void OnBackgroundModeEnabledPrefChanged();
 
   // BackgroundApplicationListModel::Observer implementation.
-  void OnApplicationDataChanged(const extensions::Extension* extension,
-                                Profile* profile) override;
-  void OnApplicationListChanged(Profile* profile) override;
+  void OnApplicationDataChanged() override;
+  void OnApplicationListChanged(const Profile* profile) override;
 
   // Overrides from ProfileAttributesStorage::Observer
   void OnProfileAdded(const base::FilePath& profile_path) override;
@@ -303,20 +295,13 @@
   // number of background clients. Updates the background status of |profile| in
   // the ProfileAttributesStorage if needed. If |new_client_names| is not empty
   // the user will be notified about the added client(s).
-  void OnClientsChanged(Profile* profile,
+  void OnClientsChanged(const Profile* profile,
                         const std::vector<base::string16>& new_client_names);
 
   // Invoked when a background client is installed so we can ensure that
   // launch-on-startup is enabled if appropriate.
   void OnBackgroundClientInstalled(const base::string16& name);
 
-  // Walk the list of profiles and see if an extension or app is being
-  // currently upgraded or reloaded by any profile.  If so, update the
-  // output variables appropriately.
-  void CheckReloadStatus(
-      const extensions::Extension* extension,
-      bool* is_being_reloaded);
-
   // Called to make sure that our launch-on-startup mode is properly set.
   // (virtual so it can be mocked in tests).
   virtual void EnableLaunchOnStartup(bool should_launch);
@@ -347,10 +332,6 @@
   // manually, or all apps have been loaded).
   void ReleaseStartupKeepAlive();
 
-  // Return an appropriate name for a Preferences menu entry.  Preferences is
-  // sometimes called Options or Settings.
-  base::string16 GetPreferencesMenuLabel();
-
   // Create a status tray icon to allow the user to shutdown Chrome when running
   // in background mode. Virtual to enable testing.
   virtual void CreateStatusTrayIcon();
@@ -367,7 +348,7 @@
 
   // Returns the BackgroundModeData associated with this profile. If it does
   // not exist, returns NULL.
-  BackgroundModeData* GetBackgroundModeData(Profile* const profile) const;
+  BackgroundModeData* GetBackgroundModeData(const Profile* profile) const;
 
   // Returns the iterator associated with a particular profile name.
   // This should not be used to iterate over the background mode data. It is
@@ -385,17 +366,17 @@
   // Turns on background mode if it's currently disabled.
   void EnableBackgroundMode();
 
-  // Returns the number of background clients in the system, for all profiles.
+  // Returns if any profile on the system has a background client.
   // A client can be a trigger or an extension.
   // (virtual to allow overriding in unit tests)
-  virtual int GetBackgroundClientCount() const;
+  virtual bool HasBackgroundClient() const;
 
-  // Returns the number of background clients for a profile. A client can be a
+  // Returns if there are background clients for a profile. A client can be a
   // trigger or an extension.
-  virtual int GetBackgroundClientCountForProfile(Profile* const profile) const;
+  virtual bool HasBackgroundClientForProfile(const Profile* profile) const;
 
-  // Returns the number of pending triggers in the system, for all profiles.
-  int GetPendingTriggerCount() const;
+  // Returns if the system has any pending triggers, for all profiles.
+  bool HasPendingTrigger() const;
 
   // Returns true if we should be in background mode.
   bool ShouldBeInBackgroundMode() const;
@@ -435,19 +416,19 @@
 
   // Reference to our status tray. If null, the platform doesn't support status
   // icons.
-  StatusTray* status_tray_;
+  StatusTray* status_tray_ = nullptr;
 
   // Reference to our status icon (if any) - owned by the StatusTray.
-  StatusIcon* status_icon_;
+  StatusIcon* status_icon_ = nullptr;
 
   // Reference to our status icon's context menu (if any) - owned by the
   // status_icon_.
-  StatusIconMenuModel* context_menu_;
+  StatusIconMenuModel* context_menu_ = nullptr;
 
   // Set to true when we are running in background mode. Allows us to track our
   // current background state so we can take the appropriate action when the
   // user disables/enables background mode via preferences.
-  bool in_background_mode_;
+  bool in_background_mode_ = false;
 
   // Background mode does not always keep Chrome alive. When it does, it is
   // using this scoped object.
@@ -465,10 +446,10 @@
   // Set to true when Chrome is running with the --keep-alive-for-test flag
   // (used for testing background mode without having to install a background
   // app).
-  bool keep_alive_for_test_;
+  bool keep_alive_for_test_ = false;
 
   // Set to true when background mode is suspended.
-  bool background_mode_suspended_;
+  bool background_mode_suspended_ = false;
 
   // Task runner for making startup/login configuration changes that may
   // require file system or registry access.
diff --git a/chrome/browser/background/background_mode_manager_aura.cc b/chrome/browser/background/background_mode_manager_aura.cc
index cdd306b..7a88d95 100644
--- a/chrome/browser/background/background_mode_manager_aura.cc
+++ b/chrome/browser/background/background_mode_manager_aura.cc
@@ -5,8 +5,6 @@
 #include "chrome/browser/background/background_mode_manager.h"
 
 #include "base/sequenced_task_runner.h"
-#include "chrome/grit/generated_resources.h"
-#include "ui/base/l10n/l10n_util.h"
 
 // No background jobs for aura for now.
 
@@ -19,10 +17,6 @@
   NOTIMPLEMENTED();
 }
 
-base::string16 BackgroundModeManager::GetPreferencesMenuLabel() {
-  return l10n_util::GetStringUTF16(IDS_SETTINGS);
-}
-
 // static
 scoped_refptr<base::SequencedTaskRunner>
 BackgroundModeManager::CreateTaskRunner() {
diff --git a/chrome/browser/background/background_mode_manager_chromeos.cc b/chrome/browser/background/background_mode_manager_chromeos.cc
index e6d7b82..755be60 100644
--- a/chrome/browser/background/background_mode_manager_chromeos.cc
+++ b/chrome/browser/background/background_mode_manager_chromeos.cc
@@ -5,8 +5,6 @@
 #include "chrome/browser/background/background_mode_manager.h"
 
 #include "base/sequenced_task_runner.h"
-#include "chrome/grit/generated_resources.h"
-#include "ui/base/l10n/l10n_util.h"
 
 void BackgroundModeManager::EnableLaunchOnStartup(bool should_launch) {
   NOTREACHED();
@@ -18,10 +16,6 @@
   // the time anyway.
 }
 
-base::string16 BackgroundModeManager::GetPreferencesMenuLabel() {
-  return l10n_util::GetStringUTF16(IDS_SETTINGS);
-}
-
 // static
 scoped_refptr<base::SequencedTaskRunner>
 BackgroundModeManager::CreateTaskRunner() {
diff --git a/chrome/browser/background/background_mode_manager_mac.mm b/chrome/browser/background/background_mode_manager_mac.mm
index 427133e7..04dc0ac 100644
--- a/chrome/browser/background/background_mode_manager_mac.mm
+++ b/chrome/browser/background/background_mode_manager_mac.mm
@@ -12,10 +12,8 @@
 #include "chrome/browser/browser_process.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/pref_names.h"
-#include "chrome/grit/generated_resources.h"
 #include "components/prefs/pref_service.h"
 #include "content/public/browser/browser_thread.h"
-#include "ui/base/l10n/l10n_util.h"
 
 using content::BrowserThread;
 
@@ -156,10 +154,6 @@
   // http://crbug.com/74970
 }
 
-base::string16 BackgroundModeManager::GetPreferencesMenuLabel() {
-  return l10n_util::GetStringUTF16(IDS_OPTIONS);
-}
-
 scoped_refptr<base::SequencedTaskRunner>
 BackgroundModeManager::CreateTaskRunner() {
   return base::CreateSequencedTaskRunnerWithTraits(
diff --git a/chrome/browser/background/background_mode_manager_unittest.cc b/chrome/browser/background/background_mode_manager_unittest.cc
index c4c7097..deb11b0 100644
--- a/chrome/browser/background/background_mode_manager_unittest.cc
+++ b/chrome/browser/background/background_mode_manager_unittest.cc
@@ -81,7 +81,7 @@
 
 base::string16 FakeBackgroundTrigger::GetName() {
   get_name_call_count_++;
-  return base::UTF8ToUTF16("FakeBackgroundTrigger");
+  return base::ASCIIToUTF16("FakeBackgroundTrigger");
 }
 
 gfx::ImageSkia* FakeBackgroundTrigger::GetIcon() {
@@ -104,6 +104,7 @@
         has_shown_balloon_(false) {
     ResumeBackgroundMode();
   }
+  ~TestBackgroundModeManager() override {}
 
   MOCK_METHOD1(EnableLaunchOnStartup, void(bool should_launch));
 
@@ -162,34 +163,38 @@
                                     ProfileAttributesStorage* storage,
                                     bool enabled)
       : TestBackgroundModeManager(command_line, storage), enabled_(enabled) {}
+  ~AdvancedTestBackgroundModeManager() override {}
 
-  int GetBackgroundClientCount() const override {
-    int app_count = 0;
-    for (const auto& profile_count_pair : profile_app_counts_)
-      app_count += profile_count_pair.second;
-    return app_count;
+  // TestBackgroundModeManager:
+  bool HasBackgroundClient() const override {
+    for (const auto& profile_count_pair : profile_app_counts_) {
+      if (profile_count_pair.second > 0)
+        return true;
+    }
+    return false;
   }
-  int GetBackgroundClientCountForProfile(
-      Profile* const profile) const override {
+  bool HasBackgroundClientForProfile(const Profile* profile) const override {
     auto it = profile_app_counts_.find(profile);
     if (it == profile_app_counts_.end()) {
       ADD_FAILURE();
-      return 0;
+      return false;
     }
-    return it->second;
+    return it->second > 0;
   }
-  void SetBackgroundClientCountForProfile(Profile* profile, int count) {
+  bool IsBackgroundModePrefEnabled() const override { return enabled_; }
+
+  void SetBackgroundClientCountForProfile(const Profile* profile,
+                                          size_t count) {
     profile_app_counts_[profile] = count;
   }
   void SetEnabled(bool enabled) {
     enabled_ = enabled;
     OnBackgroundModeEnabledPrefChanged();
   }
-  bool IsBackgroundModePrefEnabled() const override { return enabled_; }
 
  private:
   bool enabled_;
-  std::map<Profile*, int> profile_app_counts_;
+  std::map<const Profile*, size_t> profile_app_counts_;
 
   DISALLOW_COPY_AND_ASSIGN(AdvancedTestBackgroundModeManager);
 };
@@ -240,9 +245,8 @@
   void TearDown() override {
     // Clean up the status icon. If this is not done before profile deletes,
     // the context menu updates will DCHECK with the now deleted profiles.
-    StatusIcon* status_icon = manager_->status_icon_;
-    manager_->status_icon_ = NULL;
-    delete status_icon;
+    delete manager_->status_icon_;
+    manager_->status_icon_ = nullptr;
 
     // We have to destroy the profiles now because we created them with real
     // thread state. This causes a lot of machinery to spin up that stops
@@ -333,7 +337,7 @@
 
   // Mimic app load.
   EXPECT_CALL(manager, EnableLaunchOnStartup(true)).Times(Exactly(1));
-  manager.OnBackgroundClientInstalled(base::UTF8ToUTF16("name"));
+  manager.OnBackgroundClientInstalled(base::ASCIIToUTF16("name"));
   manager.SetBackgroundClientCountForProfile(profile_, 1);
   manager.OnApplicationListChanged(profile_);
   Mock::VerifyAndClearExpectations(&manager);
@@ -356,7 +360,7 @@
   // Mimic app load while suspended, e.g. from sync. This should enable and
   // resume background mode.
   EXPECT_CALL(manager, EnableLaunchOnStartup(true)).Times(Exactly(1));
-  manager.OnBackgroundClientInstalled(base::UTF8ToUTF16("name"));
+  manager.OnBackgroundClientInstalled(base::ASCIIToUTF16("name"));
   manager.SetBackgroundClientCountForProfile(profile_, 1);
   manager.OnApplicationListChanged(profile_);
   Mock::VerifyAndClearExpectations(&manager);
@@ -377,7 +381,7 @@
 
   // When a new client is installed, status tray icons will not be created,
   // launch on startup status will not be modified.
-  manager.OnBackgroundClientInstalled(base::UTF8ToUTF16("name"));
+  manager.OnBackgroundClientInstalled(base::ASCIIToUTF16("name"));
   manager.SetBackgroundClientCountForProfile(profile_, 1);
   manager.OnApplicationListChanged(profile_);
   AssertBackgroundModeInactive(manager);
@@ -402,7 +406,7 @@
 
   // When a new client is installed, status tray icons will not be created,
   // launch on startup status will not be modified.
-  manager.OnBackgroundClientInstalled(base::UTF8ToUTF16("name"));
+  manager.OnBackgroundClientInstalled(base::ASCIIToUTF16("name"));
   manager.SetBackgroundClientCountForProfile(profile_, 1);
   manager.OnApplicationListChanged(profile_);
   AssertBackgroundModeInactive(manager);
@@ -426,7 +430,7 @@
 
   // Install app, should show status tray icon.
   EXPECT_CALL(manager, EnableLaunchOnStartup(true)).Times(Exactly(1));
-  manager.OnBackgroundClientInstalled(base::UTF8ToUTF16("name"));
+  manager.OnBackgroundClientInstalled(base::ASCIIToUTF16("name"));
   // OnBackgroundClientInstalled does not actually add an app to the
   // BackgroundApplicationListModel which would result in another
   // call to CreateStatusTray.
@@ -466,14 +470,14 @@
 
   // Install app, should show status tray icon.
   EXPECT_CALL(manager, EnableLaunchOnStartup(true)).Times(Exactly(1));
-  manager.OnBackgroundClientInstalled(base::UTF8ToUTF16("name"));
+  manager.OnBackgroundClientInstalled(base::ASCIIToUTF16("name"));
   manager.SetBackgroundClientCountForProfile(profile_, 1);
   manager.OnApplicationListChanged(profile_);
   Mock::VerifyAndClearExpectations(&manager);
   AssertBackgroundModeActive(manager);
 
   // Install app for other profile, should show other status tray icon.
-  manager.OnBackgroundClientInstalled(base::UTF8ToUTF16("name"));
+  manager.OnBackgroundClientInstalled(base::ASCIIToUTF16("name"));
   manager.SetBackgroundClientCountForProfile(profile2, 2);
   manager.OnApplicationListChanged(profile2);
   AssertBackgroundModeActive(manager);
@@ -528,13 +532,13 @@
 
   // Install app, should show status tray icon.
   EXPECT_CALL(manager, EnableLaunchOnStartup(true)).Times(Exactly(1));
-  manager.OnBackgroundClientInstalled(base::UTF8ToUTF16("name"));
+  manager.OnBackgroundClientInstalled(base::ASCIIToUTF16("name"));
   manager.SetBackgroundClientCountForProfile(profile_, 1);
   manager.OnApplicationListChanged(profile_);
   Mock::VerifyAndClearExpectations(&manager);
 
   // Install app for other profile.
-  manager.OnBackgroundClientInstalled(base::UTF8ToUTF16("name"));
+  manager.OnBackgroundClientInstalled(base::ASCIIToUTF16("name"));
   manager.SetBackgroundClientCountForProfile(profile2, 1);
   manager.OnApplicationListChanged(profile2);
 
@@ -566,7 +570,7 @@
 
   // Install app, should show status tray icon.
   EXPECT_CALL(manager, EnableLaunchOnStartup(true)).Times(Exactly(1));
-  manager.OnBackgroundClientInstalled(base::UTF8ToUTF16("name"));
+  manager.OnBackgroundClientInstalled(base::ASCIIToUTF16("name"));
   manager.SetBackgroundClientCountForProfile(profile_, 1);
   manager.OnApplicationListChanged(profile_);
   Mock::VerifyAndClearExpectations(&manager);
@@ -577,25 +581,25 @@
       profile_->GetPath(),
       manager.GetBackgroundModeData(profile_)->name());
 
-  EXPECT_EQ(base::UTF8ToUTF16("p1"),
+  EXPECT_EQ(base::ASCIIToUTF16("p1"),
             manager.GetBackgroundModeData(profile_)->name());
 
   EXPECT_TRUE(KeepAliveRegistry::GetInstance()->IsKeepingAlive());
   TestingProfile* profile2 = profile_manager_->CreateTestingProfile("p2");
   manager.RegisterProfile(profile2);
-  EXPECT_EQ(2, manager.NumberOfBackgroundModeData());
+  EXPECT_EQ(2U, manager.NumberOfBackgroundModeData());
 
   manager.OnProfileAdded(profile2->GetPath());
-  EXPECT_EQ(base::UTF8ToUTF16("p2"),
+  EXPECT_EQ(base::ASCIIToUTF16("p2"),
             manager.GetBackgroundModeData(profile2)->name());
 
   manager.OnProfileWillBeRemoved(profile2->GetPath());
   // Should still be in background mode after deleting profile.
   EXPECT_TRUE(KeepAliveRegistry::GetInstance()->IsKeepingAlive());
-  EXPECT_EQ(1, manager.NumberOfBackgroundModeData());
+  EXPECT_EQ(1U, manager.NumberOfBackgroundModeData());
 
   // Check that the background mode data we think is in the map actually is.
-  EXPECT_EQ(base::UTF8ToUTF16("p1"),
+  EXPECT_EQ(base::ASCIIToUTF16("p1"),
             manager.GetBackgroundModeData(profile_)->name());
 }
 
@@ -609,7 +613,7 @@
 
   // Install app, should show status tray icon.
   EXPECT_CALL(manager, EnableLaunchOnStartup(true)).Times(Exactly(1));
-  manager.OnBackgroundClientInstalled(base::UTF8ToUTF16("name"));
+  manager.OnBackgroundClientInstalled(base::ASCIIToUTF16("name"));
   manager.SetBackgroundClientCountForProfile(profile_, 1);
   manager.OnApplicationListChanged(profile_);
   Mock::VerifyAndClearExpectations(&manager);
@@ -707,26 +711,20 @@
   service->AddExtension(regular_extension_with_options.get());
   Mock::VerifyAndClearExpectations(manager_.get());
 
-  std::unique_ptr<StatusIconMenuModel> menu(new StatusIconMenuModel(NULL));
-  std::unique_ptr<StatusIconMenuModel> submenu(new StatusIconMenuModel(NULL));
+  auto menu = std::make_unique<StatusIconMenuModel>(nullptr);
+  auto submenu = std::make_unique<StatusIconMenuModel>(nullptr);
   BackgroundModeManager::BackgroundModeData* bmd =
       manager_->GetBackgroundModeData(profile_);
   bmd->BuildProfileMenu(submenu.get(), menu.get());
-  EXPECT_TRUE(
-      submenu->GetLabelAt(0) ==
-          base::UTF8ToUTF16("Component Extension"));
+  EXPECT_EQ(submenu->GetLabelAt(0), base::ASCIIToUTF16("Component Extension"));
   EXPECT_FALSE(submenu->IsCommandIdEnabled(submenu->GetCommandIdAt(0)));
-  EXPECT_TRUE(
-      submenu->GetLabelAt(1) ==
-          base::UTF8ToUTF16("Component Extension with Options"));
+  EXPECT_EQ(submenu->GetLabelAt(1),
+            base::ASCIIToUTF16("Component Extension with Options"));
   EXPECT_TRUE(submenu->IsCommandIdEnabled(submenu->GetCommandIdAt(1)));
-  EXPECT_TRUE(
-      submenu->GetLabelAt(2) ==
-          base::UTF8ToUTF16("Regular Extension"));
+  EXPECT_EQ(submenu->GetLabelAt(2), base::ASCIIToUTF16("Regular Extension"));
   EXPECT_TRUE(submenu->IsCommandIdEnabled(submenu->GetCommandIdAt(2)));
-  EXPECT_TRUE(
-      submenu->GetLabelAt(3) ==
-          base::UTF8ToUTF16("Regular Extension with Options"));
+  EXPECT_EQ(submenu->GetLabelAt(3),
+            base::ASCIIToUTF16("Regular Extension with Options"));
   EXPECT_TRUE(submenu->IsCommandIdEnabled(submenu->GetCommandIdAt(3)));
 }
 
@@ -805,75 +803,68 @@
   manager_->status_icon_ = new TestStatusIcon();
   manager_->UpdateStatusTrayIconContextMenu();
   StatusIconMenuModel* context_menu = manager_->context_menu_;
-  EXPECT_TRUE(context_menu != NULL);
+  EXPECT_TRUE(context_menu);
 
   // Background Profile Enable Checks
-  EXPECT_TRUE(context_menu->GetLabelAt(3) == base::UTF8ToUTF16("p1"));
+  EXPECT_EQ(context_menu->GetLabelAt(3), base::ASCIIToUTF16("p1"));
   EXPECT_TRUE(
       context_menu->IsCommandIdEnabled(context_menu->GetCommandIdAt(3)));
-  EXPECT_TRUE(context_menu->GetCommandIdAt(3) == 4);
+  EXPECT_EQ(context_menu->GetCommandIdAt(3), 4);
 
-  EXPECT_TRUE(context_menu->GetLabelAt(4) == base::UTF8ToUTF16("p2"));
+  EXPECT_EQ(context_menu->GetLabelAt(4), base::ASCIIToUTF16("p2"));
   EXPECT_TRUE(
       context_menu->IsCommandIdEnabled(context_menu->GetCommandIdAt(4)));
-  EXPECT_TRUE(context_menu->GetCommandIdAt(4) == 8);
+  EXPECT_EQ(context_menu->GetCommandIdAt(4), 8);
 
   // Profile 1 Submenu Checks
   StatusIconMenuModel* profile1_submenu =
       static_cast<StatusIconMenuModel*>(context_menu->GetSubmenuModelAt(3));
-  EXPECT_TRUE(
-      profile1_submenu->GetLabelAt(0) ==
-          base::UTF8ToUTF16("Component Extension"));
+  EXPECT_EQ(profile1_submenu->GetLabelAt(0),
+            base::ASCIIToUTF16("Component Extension"));
   EXPECT_FALSE(
       profile1_submenu->IsCommandIdEnabled(
           profile1_submenu->GetCommandIdAt(0)));
-  EXPECT_TRUE(profile1_submenu->GetCommandIdAt(0) == 0);
-  EXPECT_TRUE(
-      profile1_submenu->GetLabelAt(1) ==
-          base::UTF8ToUTF16("Component Extension with Options"));
+  EXPECT_EQ(profile1_submenu->GetCommandIdAt(0), 0);
+  EXPECT_EQ(profile1_submenu->GetLabelAt(1),
+            base::ASCIIToUTF16("Component Extension with Options"));
   EXPECT_TRUE(
       profile1_submenu->IsCommandIdEnabled(
           profile1_submenu->GetCommandIdAt(1)));
-  EXPECT_TRUE(profile1_submenu->GetCommandIdAt(1) == 1);
-  EXPECT_TRUE(
-      profile1_submenu->GetLabelAt(2) ==
-          base::UTF8ToUTF16("Regular Extension"));
+  EXPECT_EQ(profile1_submenu->GetCommandIdAt(1), 1);
+  EXPECT_EQ(profile1_submenu->GetLabelAt(2),
+            base::ASCIIToUTF16("Regular Extension"));
   EXPECT_TRUE(
       profile1_submenu->IsCommandIdEnabled(
           profile1_submenu->GetCommandIdAt(2)));
-  EXPECT_TRUE(profile1_submenu->GetCommandIdAt(2) == 2);
-  EXPECT_TRUE(
-      profile1_submenu->GetLabelAt(3) ==
-          base::UTF8ToUTF16("Regular Extension with Options"));
+  EXPECT_EQ(profile1_submenu->GetCommandIdAt(2), 2);
+  EXPECT_EQ(profile1_submenu->GetLabelAt(3),
+            base::ASCIIToUTF16("Regular Extension with Options"));
   EXPECT_TRUE(
       profile1_submenu->IsCommandIdEnabled(
           profile1_submenu->GetCommandIdAt(3)));
-  EXPECT_TRUE(profile1_submenu->GetCommandIdAt(3) == 3);
+  EXPECT_EQ(profile1_submenu->GetCommandIdAt(3), 3);
 
   // Profile 2 Submenu Checks
   StatusIconMenuModel* profile2_submenu =
       static_cast<StatusIconMenuModel*>(context_menu->GetSubmenuModelAt(4));
-  EXPECT_TRUE(
-      profile2_submenu->GetLabelAt(0) ==
-          base::UTF8ToUTF16("Component Extension"));
+  EXPECT_EQ(profile2_submenu->GetLabelAt(0),
+            base::ASCIIToUTF16("Component Extension"));
   EXPECT_FALSE(
       profile2_submenu->IsCommandIdEnabled(
           profile2_submenu->GetCommandIdAt(0)));
-  EXPECT_TRUE(profile2_submenu->GetCommandIdAt(0) == 5);
-  EXPECT_TRUE(
-      profile2_submenu->GetLabelAt(1) ==
-          base::UTF8ToUTF16("Regular Extension"));
+  EXPECT_EQ(profile2_submenu->GetCommandIdAt(0), 5);
+  EXPECT_EQ(profile2_submenu->GetLabelAt(1),
+            base::ASCIIToUTF16("Regular Extension"));
   EXPECT_TRUE(
       profile2_submenu->IsCommandIdEnabled(
           profile2_submenu->GetCommandIdAt(1)));
-  EXPECT_TRUE(profile2_submenu->GetCommandIdAt(1) == 6);
-  EXPECT_TRUE(
-      profile2_submenu->GetLabelAt(2) ==
-          base::UTF8ToUTF16("Regular Extension with Options"));
+  EXPECT_EQ(profile2_submenu->GetCommandIdAt(1), 6);
+  EXPECT_EQ(profile2_submenu->GetLabelAt(2),
+            base::ASCIIToUTF16("Regular Extension with Options"));
   EXPECT_TRUE(
       profile2_submenu->IsCommandIdEnabled(
           profile2_submenu->GetCommandIdAt(2)));
-  EXPECT_TRUE(profile2_submenu->GetCommandIdAt(2) == 7);
+  EXPECT_EQ(profile2_submenu->GetCommandIdAt(2), 7);
 
   // Model Adapter Checks for crbug.com/315164
   // P1: Profile 1 Menu Item
@@ -986,7 +977,7 @@
   EXPECT_CALL(manager, EnableLaunchOnStartup(true));
   manager.RegisterTrigger(profile_, &trigger, true /* should_notify_user */);
   Mock::VerifyAndClearExpectations(&manager);
-  ASSERT_EQ(1, manager.GetBackgroundClientCountForProfile(profile_));
+  ASSERT_TRUE(manager.HasBackgroundClientForProfile(profile_));
   AssertBackgroundModeActive(manager);
   ASSERT_TRUE(manager.HasShownBalloon());
 
@@ -994,7 +985,7 @@
   EXPECT_CALL(manager, EnableLaunchOnStartup(false));
   manager.UnregisterTrigger(profile_, &trigger);
   Mock::VerifyAndClearExpectations(&manager);
-  ASSERT_EQ(0, manager.GetBackgroundClientCountForProfile(profile_));
+  ASSERT_FALSE(manager.HasBackgroundClientForProfile(profile_));
   AssertBackgroundModeInactive(manager);
 }
 
@@ -1013,7 +1004,7 @@
   // Registering a trigger while disabled has no immediate effect but it is
   // stored as pending in case background mode is later enabled.
   manager.RegisterTrigger(profile_, &trigger, true /* should_notify_user */);
-  ASSERT_EQ(0, manager.GetBackgroundClientCountForProfile(profile_));
+  ASSERT_FALSE(manager.HasBackgroundClientForProfile(profile_));
   AssertBackgroundModeInactive(manager);
   ASSERT_FALSE(manager.HasShownBalloon());
 
@@ -1023,7 +1014,7 @@
   g_browser_process->local_state()->SetBoolean(prefs::kBackgroundModeEnabled,
                                                true);
   Mock::VerifyAndClearExpectations(&manager);
-  ASSERT_EQ(1, manager.GetBackgroundClientCountForProfile(profile_));
+  ASSERT_TRUE(manager.HasBackgroundClientForProfile(profile_));
   AssertBackgroundModeActive(manager);
   ASSERT_TRUE(manager.HasShownBalloon());
 }
diff --git a/chrome/browser/background/background_mode_manager_win.cc b/chrome/browser/background/background_mode_manager_win.cc
index bc0dd5360..1789409 100644
--- a/chrome/browser/background/background_mode_manager_win.cc
+++ b/chrome/browser/background/background_mode_manager_win.cc
@@ -51,10 +51,6 @@
                                  kAppInstalledNotifierId));
 }
 
-base::string16 BackgroundModeManager::GetPreferencesMenuLabel() {
-  return l10n_util::GetStringUTF16(IDS_OPTIONS);
-}
-
 scoped_refptr<base::SequencedTaskRunner>
 BackgroundModeManager::CreateTaskRunner() {
   return base::CreateSequencedTaskRunnerWithTraits(
diff --git a/chrome/browser/browser_process_impl.cc b/chrome/browser/browser_process_impl.cc
index c61a9acd..a02e15b 100644
--- a/chrome/browser/browser_process_impl.cc
+++ b/chrome/browser/browser_process_impl.cc
@@ -88,6 +88,7 @@
 #include "chrome/common/url_constants.h"
 #include "chrome/installer/util/google_update_settings.h"
 #include "components/component_updater/component_updater_service.h"
+#include "components/component_updater/timer_update_scheduler.h"
 #include "components/crash/core/common/crash_key.h"
 #include "components/gcm_driver/gcm_driver.h"
 #include "components/metrics/metrics_pref_names.h"
@@ -1002,7 +1003,8 @@
   component_updater_ = component_updater::ComponentUpdateServiceFactory(
       component_updater::MakeChromeComponentUpdaterConfigurator(
           base::CommandLine::ForCurrentProcess(),
-          g_browser_process->local_state()));
+          g_browser_process->local_state()),
+      std::make_unique<component_updater::TimerUpdateScheduler>());
 
   return component_updater_.get();
 }
@@ -1128,7 +1130,9 @@
   // requires that threads are running; this Init() call lets the connector
   // resume its initialization now that the loops are spinning and the
   // system request context is available for the fetchers.
-  browser_policy_connector()->Init(local_state(), system_request_context());
+  browser_policy_connector()->Init(
+      local_state(), system_request_context(),
+      system_network_context_manager()->GetSharedURLLoaderFactory());
 
   if (local_state_->IsManagedPreference(prefs::kDefaultBrowserSettingEnabled))
     ApplyDefaultBrowserPolicy();
diff --git a/chrome/browser/chromeos/arc/voice_interaction/fake_voice_interaction_controller.cc b/chrome/browser/chromeos/arc/voice_interaction/fake_voice_interaction_controller.cc
index f1048b4..c39b6e1b 100644
--- a/chrome/browser/chromeos/arc/voice_interaction/fake_voice_interaction_controller.cc
+++ b/chrome/browser/chromeos/arc/voice_interaction/fake_voice_interaction_controller.cc
@@ -40,4 +40,14 @@
   assistant_allowed_state_ = state;
 }
 
+void FakeVoiceInteractionController::IsSettingEnabled(
+    IsSettingEnabledCallback callback) {
+  std::move(callback).Run(voice_interaction_settings_enabled_);
+}
+
+void FakeVoiceInteractionController::IsSetupCompleted(
+    IsSetupCompletedCallback callback) {
+  std::move(callback).Run(voice_interaction_setup_completed_);
+}
+
 }  // namespace arc
diff --git a/chrome/browser/chromeos/arc/voice_interaction/fake_voice_interaction_controller.h b/chrome/browser/chromeos/arc/voice_interaction/fake_voice_interaction_controller.h
index a84c36b..ecdf343 100644
--- a/chrome/browser/chromeos/arc/voice_interaction/fake_voice_interaction_controller.h
+++ b/chrome/browser/chromeos/arc/voice_interaction/fake_voice_interaction_controller.h
@@ -24,6 +24,8 @@
   void NotifyContextEnabled(bool enabled) override;
   void NotifySetupCompleted(bool completed) override;
   void NotifyFeatureAllowed(ash::mojom::AssistantAllowedState state) override;
+  void IsSettingEnabled(IsSettingEnabledCallback callback) override;
+  void IsSetupCompleted(IsSetupCompletedCallback callback) override;
 
   ash::mojom::VoiceInteractionState voice_interaction_state() const {
     return voice_interaction_state_;
diff --git a/chrome/browser/chromeos/drive/drive_integration_service.cc b/chrome/browser/chromeos/drive/drive_integration_service.cc
index 54e1c1f..0c4ddc48 100644
--- a/chrome/browser/chromeos/drive/drive_integration_service.cc
+++ b/chrome/browser/chromeos/drive/drive_integration_service.cc
@@ -23,6 +23,7 @@
 #include "chrome/browser/download/download_core_service_factory.h"
 #include "chrome/browser/download/download_prefs.h"
 #include "chrome/browser/drive/drive_notification_manager_factory.h"
+#include "chrome/browser/net/system_network_context_manager.h"
 #include "chrome/browser/profiles/incognito_helpers.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
@@ -56,6 +57,7 @@
 #include "net/traffic_annotation/network_traffic_annotation.h"
 #include "services/device/public/mojom/constants.mojom.h"
 #include "services/device/public/mojom/wake_lock_provider.mojom.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
 #include "services/service_manager/public/cpp/connector.h"
 #include "storage/browser/fileapi/external_mount_points.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -362,9 +364,15 @@
   if (test_drive_service) {
     drive_service_.reset(test_drive_service);
   } else {
+    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory;
+    if (g_browser_process->system_network_context_manager()) {
+      // system_network_context_manager() returns nullptr in unit-tests.
+      url_loader_factory = g_browser_process->system_network_context_manager()
+                               ->GetSharedURLLoaderFactory();
+    }
     drive_service_.reset(new DriveAPIService(
         oauth_service, g_browser_process->system_request_context(),
-        blocking_task_runner_.get(),
+        url_loader_factory, blocking_task_runner_.get(),
         GURL(google_apis::DriveApiUrlGenerator::kBaseUrlForProduction),
         GURL(google_apis::DriveApiUrlGenerator::kBaseThumbnailUrlForProduction),
         GetDriveUserAgent(), NO_TRAFFIC_ANNOTATION_YET));
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_drive.cc b/chrome/browser/chromeos/extensions/file_manager/private_api_drive.cc
index d8d74ec4..6ef652b8 100644
--- a/chrome/browser/chromeos/extensions/file_manager/private_api_drive.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/private_api_drive.cc
@@ -26,6 +26,7 @@
 #include "chrome/browser/chromeos/fileapi/external_file_url_util.h"
 #include "chrome/browser/chromeos/fileapi/file_system_backend.h"
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
+#include "chrome/browser/net/system_network_context_manager.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
@@ -39,10 +40,12 @@
 #include "components/signin/core/browser/profile_oauth2_token_service.h"
 #include "components/signin/core/browser/signin_manager.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/browser/storage_partition.h"
 #include "google_apis/drive/auth_service.h"
 #include "google_apis/drive/drive_api_url_generator.h"
 #include "google_apis/drive/drive_switches.h"
 #include "mojo/public/cpp/bindings/callback_helpers.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
 #include "storage/common/fileapi/file_system_info.h"
 #include "storage/common/fileapi/file_system_util.h"
 #include "url/gurl.h"
@@ -1522,9 +1525,12 @@
   std::vector<std::string> scopes;
   scopes.emplace_back("https://www.googleapis.com/auth/drive.readonly");
 
+  scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory =
+      content::BrowserContext::GetDefaultStoragePartition(GetProfile())
+          ->GetURLLoaderFactoryForBrowserProcess();
   auth_service_ = std::make_unique<google_apis::AuthService>(
       oauth2_token_service, account_id, GetProfile()->GetRequestContext(),
-      scopes);
+      url_loader_factory, scopes);
   auth_service_->StartAuthentication(base::Bind(
       &FileManagerPrivateInternalGetDownloadUrlFunction::OnTokenFetched, this));
 }
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_misc.cc b/chrome/browser/chromeos/extensions/file_manager/private_api_misc.cc
index 743c1ed2..0273e04 100644
--- a/chrome/browser/chromeos/extensions/file_manager/private_api_misc.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/private_api_misc.cc
@@ -35,6 +35,7 @@
 #include "chrome/browser/devtools/devtools_window.h"
 #include "chrome/browser/extensions/devtools_util.h"
 #include "chrome/browser/lifetime/application_lifetime.h"
+#include "chrome/browser/net/system_network_context_manager.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/profiles/profiles_state.h"
@@ -63,6 +64,7 @@
 #include "extensions/browser/app_window/app_window.h"
 #include "extensions/browser/app_window/app_window_registry.h"
 #include "google_apis/drive/auth_service.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
 #include "storage/browser/fileapi/external_mount_points.h"
 #include "storage/common/fileapi/file_system_types.h"
 #include "ui/base/webui/web_ui_util.h"
@@ -374,7 +376,10 @@
       SigninManagerFactory::GetForProfile(GetProfile());
   auth_service_ = std::make_unique<google_apis::AuthService>(
       oauth_service, signin_manager->GetAuthenticatedAccountId(),
-      url_request_context_getter, scopes);
+      url_request_context_getter,
+      g_browser_process->system_network_context_manager()
+          ->GetSharedURLLoaderFactory(),
+      scopes);
   auth_service_->StartAuthentication(base::Bind(
       &FileManagerPrivateRequestWebStoreAccessTokenFunction::
           OnAccessTokenFetched,
diff --git a/chrome/browser/chromeos/login/chrome_restart_request.cc b/chrome/browser/chromeos/login/chrome_restart_request.cc
index 7f709c3..666a4d2 100644
--- a/chrome/browser/chromeos/login/chrome_restart_request.cc
+++ b/chrome/browser/chromeos/login/chrome_restart_request.cc
@@ -134,6 +134,7 @@
     ::switches::kGpuRasterizationMSAASampleCount,
     ::switches::kGpuStartupDialog,
     ::switches::kGpuSandboxStartEarly,
+    ::switches::kLowPressureTouchFiltering,
     ::switches::kNumRasterThreads,
     ::switches::kPpapiFlashArgs,
     ::switches::kPpapiFlashPath,
diff --git a/chrome/browser/chromeos/login/enrollment/enterprise_enrollment_helper_impl.cc b/chrome/browser/chromeos/login/enrollment/enterprise_enrollment_helper_impl.cc
index 1d10ef1..a404bd1 100644
--- a/chrome/browser/chromeos/login/enrollment/enterprise_enrollment_helper_impl.cc
+++ b/chrome/browser/chromeos/login/enrollment/enterprise_enrollment_helper_impl.cc
@@ -20,12 +20,14 @@
 #include "chrome/browser/chromeos/policy/enrollment_status_chromeos.h"
 #include "chrome/browser/chromeos/policy/policy_oauth2_token_fetcher.h"
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
+#include "chrome/browser/net/system_network_context_manager.h"
 #include "chromeos/chromeos_switches.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "components/policy/core/common/cloud/cloud_policy_constants.h"
 #include "google_apis/gaia/gaia_auth_consumer.h"
 #include "google_apis/gaia/gaia_auth_fetcher.h"
 #include "google_apis/gaia/gaia_constants.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
 
 namespace {
 
@@ -98,6 +100,8 @@
   oauth_fetcher_.reset(policy::PolicyOAuth2TokenFetcher::CreateInstance());
   oauth_fetcher_->StartWithAuthCode(
       auth_code, g_browser_process->system_request_context(),
+      g_browser_process->system_network_context_manager()
+          ->GetSharedURLLoaderFactory(),
       base::Bind(&EnterpriseEnrollmentHelperImpl::OnTokenFetched,
                  weak_ptr_factory_.GetWeakPtr(),
                  fetch_additional_token /* is_additional_token */));
@@ -267,6 +271,8 @@
   oauth_fetcher_.reset(policy::PolicyOAuth2TokenFetcher::CreateInstance());
   oauth_fetcher_->StartWithRefreshToken(
       refresh_token, g_browser_process->system_request_context(),
+      g_browser_process->system_network_context_manager()
+          ->GetSharedURLLoaderFactory(),
       base::Bind(&EnterpriseEnrollmentHelperImpl::OnTokenFetched,
                  weak_ptr_factory_.GetWeakPtr(),
                  false /* is_additional_token */));
diff --git a/chrome/browser/chromeos/login/existing_user_controller.cc b/chrome/browser/chromeos/login/existing_user_controller.cc
index 8fbd012..d558eab3 100644
--- a/chrome/browser/chromeos/login/existing_user_controller.cc
+++ b/chrome/browser/chromeos/login/existing_user_controller.cc
@@ -51,6 +51,7 @@
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
 #include "chrome/browser/chromeos/settings/cros_settings.h"
 #include "chrome/browser/chromeos/system/device_disabling_manager.h"
+#include "chrome/browser/net/system_network_context_manager.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/aura/accessibility/automation_manager_aura.h"
 #include "chrome/browser/ui/webui/chromeos/login/l10n_util.h"
@@ -98,6 +99,7 @@
 #include "net/http/http_transaction_factory.h"
 #include "net/url_request/url_request_context.h"
 #include "net/url_request/url_request_context_getter.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
 #include "ui/accessibility/ax_enums.mojom.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/views/widget/widget.h"
@@ -1067,10 +1069,17 @@
   // Use signin profile request context
   net::URLRequestContextGetter* const signin_profile_context =
       ProfileHelper::GetSigninProfile()->GetRequestContext();
+  scoped_refptr<network::SharedURLLoaderFactory>
+      sigin_profile_url_loader_factory =
+          content::BrowserContext::GetDefaultStoragePartition(
+              ProfileHelper::GetSigninProfile())
+              ->GetURLLoaderFactoryForBrowserProcess();
+
   auto cloud_policy_client = std::make_unique<policy::CloudPolicyClient>(
       std::string() /* machine_id */, std::string() /* machine_model */,
       std::string() /* brand_code */, device_management_service,
-      signin_profile_context, nullptr /* signing_service */,
+      signin_profile_context, sigin_profile_url_loader_factory,
+      nullptr /* signing_service */,
       chromeos::GetDeviceDMTokenForUserPolicyGetter(
           user_context.GetAccountId()));
   pre_signin_policy_fetcher_ = std::make_unique<policy::PreSigninPolicyFetcher>(
diff --git a/chrome/browser/chromeos/login/ui/login_display_host_mojo.cc b/chrome/browser/chromeos/login/ui/login_display_host_mojo.cc
index 6fec22e..0d80ae0 100644
--- a/chrome/browser/chromeos/login/ui/login_display_host_mojo.cc
+++ b/chrome/browser/chromeos/login/ui/login_display_host_mojo.cc
@@ -254,7 +254,7 @@
 
 void LoginDisplayHostMojo::UpdateGaiaDialogSize(int width, int height) {
   if (dialog_)
-    dialog_->SetSize(width, height);
+    dialog_->UpdateSizeAndPosition(width, height);
 }
 
 const user_manager::UserList LoginDisplayHostMojo::GetUsers() {
diff --git a/chrome/browser/chromeos/login/ui/oobe_ui_dialog_delegate.cc b/chrome/browser/chromeos/login/ui/oobe_ui_dialog_delegate.cc
index 95d0361..0670eb4 100644
--- a/chrome/browser/chromeos/login/ui/oobe_ui_dialog_delegate.cc
+++ b/chrome/browser/chromeos/login/ui/oobe_ui_dialog_delegate.cc
@@ -9,6 +9,7 @@
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
 #include "chrome/browser/extensions/chrome_extension_web_contents_observer.h"
 #include "chrome/browser/ui/ash/ash_util.h"
+#include "chrome/browser/ui/ash/tablet_mode_client.h"
 #include "chrome/browser/ui/webui/chrome_web_contents_handler.h"
 #include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h"
 #include "content/public/browser/web_contents.h"
@@ -31,7 +32,12 @@
 OobeUIDialogDelegate::OobeUIDialogDelegate(
     base::WeakPtr<LoginDisplayHostMojo> controller)
     : controller_(controller),
-      size_(gfx::Size(kGaiaDialogWidth, kGaiaDialogHeight)) {}
+      size_(gfx::Size(kGaiaDialogWidth, kGaiaDialogHeight)),
+      display_observer_(this),
+      tablet_mode_observer_(this) {
+  display_observer_.Add(display::Screen::GetScreen());
+  tablet_mode_observer_.Add(TabletModeClient::Get());
+}
 
 OobeUIDialogDelegate::~OobeUIDialogDelegate() {
   if (controller_)
@@ -71,7 +77,7 @@
 void OobeUIDialogDelegate::ShowFullScreen() {
   const gfx::Size& size =
       display::Screen::GetScreen()->GetPrimaryDisplay().size();
-  SetSize(size.width(), size.height());
+  UpdateSizeAndPosition(size.width(), size.height());
   Show(false /*closable_by_esc*/);
 }
 
@@ -85,10 +91,7 @@
     dialog_widget_->Close();
 }
 
-void OobeUIDialogDelegate::SetSize(int width, int height) {
-  if (size_ == gfx::Size(width, height))
-    return;
-
+void OobeUIDialogDelegate::UpdateSizeAndPosition(int width, int height) {
   size_.SetSize(width, height);
   if (!dialog_widget_)
     return;
@@ -118,6 +121,26 @@
   return dialog_widget_ ? dialog_widget_->GetNativeWindow() : nullptr;
 }
 
+void OobeUIDialogDelegate::OnDisplayMetricsChanged(
+    const display::Display& display,
+    uint32_t changed_metrics) {
+  if (!dialog_widget_)
+    return;
+
+  const display::Display this_display =
+      display::Screen::GetScreen()->GetDisplayNearestWindow(
+          dialog_widget_->GetNativeWindow());
+  if (this_display.id() == display.id())
+    UpdateSizeAndPosition(size_.width(), size_.height());
+}
+
+void OobeUIDialogDelegate::OnTabletModeToggled(bool enabled) {
+  if (!dialog_widget_)
+    return;
+
+  UpdateSizeAndPosition(size_.width(), size_.height());
+}
+
 ui::ModalType OobeUIDialogDelegate::GetDialogModalType() const {
   return ui::MODAL_TYPE_SYSTEM;
 }
diff --git a/chrome/browser/chromeos/login/ui/oobe_ui_dialog_delegate.h b/chrome/browser/chromeos/login/ui/oobe_ui_dialog_delegate.h
index 31ae401..afcef44 100644
--- a/chrome/browser/chromeos/login/ui/oobe_ui_dialog_delegate.h
+++ b/chrome/browser/chromeos/login/ui/oobe_ui_dialog_delegate.h
@@ -9,13 +9,22 @@
 
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
+#include "base/scoped_observer.h"
 #include "base/strings/string16.h"
+#include "chrome/browser/ui/ash/tablet_mode_client_observer.h"
+#include "ui/display/display_observer.h"
 #include "ui/web_dialogs/web_dialog_delegate.h"
 
+class TabletModeClient;
+
 namespace content {
 class WebContents;
 }
 
+namespace display {
+class Screen;
+}
+
 namespace ui {
 class Accelerator;
 }
@@ -37,7 +46,9 @@
 //         |
 //         V
 //   clientView---->Widget's view hierarchy
-class OobeUIDialogDelegate : public ui::WebDialogDelegate {
+class OobeUIDialogDelegate : public display::DisplayObserver,
+                             public TabletModeClientObserver,
+                             public ui::WebDialogDelegate {
  public:
   explicit OobeUIDialogDelegate(base::WeakPtr<LoginDisplayHostMojo> controller);
   ~OobeUIDialogDelegate() override;
@@ -61,11 +72,17 @@
 
   content::WebContents* GetWebContents();
 
-  void SetSize(int width, int height);
+  void UpdateSizeAndPosition(int width, int height);
   OobeUI* GetOobeUI() const;
   gfx::NativeWindow GetNativeWindow() const;
 
  private:
+  // display::DisplayObserver:
+  void OnDisplayMetricsChanged(const display::Display& display,
+                               uint32_t changed_metrics) override;
+  // TabletModeClientObserver:
+  void OnTabletModeToggled(bool enabled) override;
+
   // ui::WebDialogDelegate:
   ui::ModalType GetDialogModalType() const override;
   base::string16 GetDialogTitle() const override;
@@ -93,6 +110,10 @@
   gfx::Size size_;
   bool closable_by_esc_ = true;
 
+  ScopedObserver<display::Screen, display::DisplayObserver> display_observer_;
+  ScopedObserver<TabletModeClient, TabletModeClientObserver>
+      tablet_mode_observer_;
+
   DISALLOW_COPY_AND_ASSIGN(OobeUIDialogDelegate);
 };
 
diff --git a/chrome/browser/chromeos/oauth2_token_service_delegate.cc b/chrome/browser/chromeos/oauth2_token_service_delegate.cc
index 6bc35a6..a77b672e 100644
--- a/chrome/browser/chromeos/oauth2_token_service_delegate.cc
+++ b/chrome/browser/chromeos/oauth2_token_service_delegate.cc
@@ -11,6 +11,7 @@
 #include "base/logging.h"
 #include "chromeos/account_manager/account_manager.h"
 #include "components/signin/core/browser/account_tracker_service.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
 
 namespace chromeos {
 
@@ -30,6 +31,7 @@
 ChromeOSOAuth2TokenServiceDelegate::CreateAccessTokenFetcher(
     const std::string& account_id,
     net::URLRequestContextGetter* getter,
+    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
     OAuth2AccessTokenConsumer* consumer) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK_EQ(LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS, load_credentials_state_);
@@ -41,7 +43,7 @@
 
   // |OAuth2TokenService| will manage the lifetime of the released pointer.
   return account_manager_
-      ->CreateAccessTokenFetcher(account_key, getter, consumer)
+      ->CreateAccessTokenFetcher(account_key, url_loader_factory, consumer)
       .release();
 }
 
diff --git a/chrome/browser/chromeos/oauth2_token_service_delegate.h b/chrome/browser/chromeos/oauth2_token_service_delegate.h
index aeb0d1f9..6b9bcfd 100644
--- a/chrome/browser/chromeos/oauth2_token_service_delegate.h
+++ b/chrome/browser/chromeos/oauth2_token_service_delegate.h
@@ -36,6 +36,7 @@
   OAuth2AccessTokenFetcher* CreateAccessTokenFetcher(
       const std::string& account_id,
       net::URLRequestContextGetter* getter,
+      scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
       OAuth2AccessTokenConsumer* consumer) override;
   bool RefreshTokenIsAvailable(const std::string& account_id) const override;
   void UpdateAuthError(const std::string& account_id,
diff --git a/chrome/browser/chromeos/policy/affiliated_invalidation_service_provider_impl_unittest.cc b/chrome/browser/chromeos/policy/affiliated_invalidation_service_provider_impl_unittest.cc
index 4401c14..bd30975 100644
--- a/chrome/browser/chromeos/policy/affiliated_invalidation_service_provider_impl_unittest.cc
+++ b/chrome/browser/chromeos/policy/affiliated_invalidation_service_provider_impl_unittest.cc
@@ -10,6 +10,7 @@
 
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
+#include "base/memory/ref_counted.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h"
 #include "chrome/browser/chromeos/settings/cros_settings.h"
@@ -35,6 +36,8 @@
 #include "content/public/browser/notification_details.h"
 #include "content/public/browser/notification_service.h"
 #include "content/public/test/test_browser_thread_bundle.h"
+#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
+#include "services/network/test/test_url_loader_factory.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace policy {
@@ -137,6 +140,9 @@
   std::unique_ptr<chromeos::ScopedTestDeviceSettingsService>
       test_device_settings_service_;
   std::unique_ptr<chromeos::ScopedTestCrosSettings> test_cros_settings_;
+  network::TestURLLoaderFactory test_url_loader_factory_;
+  scoped_refptr<network::WeakWrapperSharedURLLoaderFactory>
+      test_shared_loader_factory_;
   TestingProfileManager profile_manager_;
 };
 
@@ -197,6 +203,9 @@
           chromeos::ScopedStubInstallAttributes::CreateCloudManaged(
               "example.com",
               "device_id")),
+      test_shared_loader_factory_(
+          base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
+              &test_url_loader_factory_)),
       profile_manager_(TestingBrowserProcess::GetGlobal()) {}
 
 void AffiliatedInvalidationServiceProviderImplTest::SetUp() {
@@ -207,7 +216,8 @@
   test_device_settings_service_.reset(new
       chromeos::ScopedTestDeviceSettingsService);
   test_cros_settings_.reset(new chromeos::ScopedTestCrosSettings);
-  chromeos::DeviceOAuth2TokenServiceFactory::Initialize();
+  chromeos::DeviceOAuth2TokenServiceFactory::Initialize(
+      test_shared_loader_factory_);
 
   invalidation::ProfileInvalidationProviderFactory::GetInstance()->
       RegisterTestingFactory(BuildProfileInvalidationProvider);
@@ -219,6 +229,7 @@
   consumer_.reset();
   provider_->Shutdown();
   provider_.reset();
+  test_shared_loader_factory_->Detach();
 
   invalidation::ProfileInvalidationProviderFactory::GetInstance()->
       RegisterTestingFactory(nullptr);
diff --git a/chrome/browser/chromeos/policy/browser_policy_connector_chromeos.cc b/chrome/browser/chromeos/policy/browser_policy_connector_chromeos.cc
index 6b26d83..c41c301 100644
--- a/chrome/browser/chromeos/policy/browser_policy_connector_chromeos.cc
+++ b/chrome/browser/chromeos/policy/browser_policy_connector_chromeos.cc
@@ -63,6 +63,7 @@
 #include "content/public/browser/browser_thread.h"
 #include "google_apis/gaia/gaia_auth_util.h"
 #include "net/url_request/url_request_context_getter.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
 
 using content::BrowserThread;
 
@@ -147,9 +148,11 @@
 
 void BrowserPolicyConnectorChromeOS::Init(
     PrefService* local_state,
-    scoped_refptr<net::URLRequestContextGetter> request_context) {
+    scoped_refptr<net::URLRequestContextGetter> request_context,
+    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) {
   local_state_ = local_state;
-  ChromeBrowserPolicyConnector::Init(local_state, request_context);
+  ChromeBrowserPolicyConnector::Init(local_state, request_context,
+                                     url_loader_factory);
 
   affiliated_invalidation_service_provider_ =
       std::make_unique<AffiliatedInvalidationServiceProviderImpl>();
@@ -177,7 +180,7 @@
             GetBackgroundTaskRunner(),
             content::BrowserThread::GetTaskRunnerForThread(
                 content::BrowserThread::IO),
-            request_context);
+            request_context, url_loader_factory);
     device_local_account_policy_service_->Connect(device_management_service());
   }
 
diff --git a/chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h b/chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h
index 4cd9bc3..ec9d371 100644
--- a/chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h
+++ b/chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h
@@ -30,10 +30,6 @@
 
 }  // namespace chromeos
 
-namespace net {
-class URLRequestContextGetter;
-}
-
 namespace policy {
 
 class AffiliatedCloudPolicyInvalidator;
@@ -60,9 +56,10 @@
   ~BrowserPolicyConnectorChromeOS() override;
 
   // ChromeBrowserPolicyConnector:
-  void Init(
-      PrefService* local_state,
-      scoped_refptr<net::URLRequestContextGetter> request_context) override;
+  void Init(PrefService* local_state,
+            scoped_refptr<net::URLRequestContextGetter> request_context,
+            scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory)
+      override;
 
   // Checks whether this devices is under any kind of enterprise management.
   bool IsEnterpriseManaged() const override;
diff --git a/chrome/browser/chromeos/policy/cloud_external_data_policy_observer_unittest.cc b/chrome/browser/chromeos/policy/cloud_external_data_policy_observer_unittest.cc
index d857b0a..a074462 100644
--- a/chrome/browser/chromeos/policy/cloud_external_data_policy_observer_unittest.cc
+++ b/chrome/browser/chromeos/policy/cloud_external_data_policy_observer_unittest.cc
@@ -191,7 +191,8 @@
           base::ThreadTaskRunnerHandle::Get(),
           base::ThreadTaskRunnerHandle::Get(),
           base::ThreadTaskRunnerHandle::Get(),
-          base::ThreadTaskRunnerHandle::Get(), nullptr));
+          base::ThreadTaskRunnerHandle::Get(), /*request_context=*/nullptr,
+          /*url_loader_factory=*/nullptr));
   url_fetcher_factory_.set_remove_fetcher_on_delete(true);
 
   EXPECT_CALL(user_policy_provider_, IsInitializationComplete(_))
diff --git a/chrome/browser/chromeos/policy/device_cloud_policy_initializer.cc b/chrome/browser/chromeos/policy/device_cloud_policy_initializer.cc
index 30b6ca0..e87f253 100644
--- a/chrome/browser/chromeos/policy/device_cloud_policy_initializer.cc
+++ b/chrome/browser/chromeos/policy/device_cloud_policy_initializer.cc
@@ -23,6 +23,7 @@
 #include "chrome/browser/chromeos/policy/enrollment_status_chromeos.h"
 #include "chrome/browser/chromeos/policy/server_backed_device_state.h"
 #include "chrome/browser/chromeos/settings/install_attributes.h"
+#include "chrome/browser/net/system_network_context_manager.h"
 #include "chrome/common/chrome_content_client.h"
 #include "chrome/common/pref_names.h"
 #include "chromeos/attestation/attestation.pb.h"
@@ -70,6 +71,11 @@
   signing_service_ = std::move(signing_service);
 }
 
+void DeviceCloudPolicyInitializer::SetSystemURLLoaderFactoryForTesting(
+    scoped_refptr<network::SharedURLLoaderFactory> system_url_loader_factory) {
+  system_url_loader_factory_for_testing_ = system_url_loader_factory;
+}
+
 DeviceCloudPolicyInitializer::~DeviceCloudPolicyInitializer() {
   DCHECK(!is_initialized_);
 }
@@ -297,6 +303,10 @@
   return std::make_unique<CloudPolicyClient>(
       statistics_provider_->GetEnterpriseMachineID(), machine_model, brand_code,
       device_management_service, g_browser_process->system_request_context(),
+      system_url_loader_factory_for_testing_
+          ? system_url_loader_factory_for_testing_
+          : g_browser_process->system_network_context_manager()
+                ->GetSharedURLLoaderFactory(),
       signing_service_.get(), CloudPolicyClient::DeviceDMTokenCallback());
 }
 
diff --git a/chrome/browser/chromeos/policy/device_cloud_policy_initializer.h b/chrome/browser/chromeos/policy/device_cloud_policy_initializer.h
index c09b3ae..b09df8e 100644
--- a/chrome/browser/chromeos/policy/device_cloud_policy_initializer.h
+++ b/chrome/browser/chromeos/policy/device_cloud_policy_initializer.h
@@ -19,6 +19,7 @@
 #include "components/policy/core/common/cloud/cloud_policy_constants.h"
 #include "components/policy/core/common/cloud/cloud_policy_store.h"
 #include "components/policy/core/common/cloud/signing_service.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
 
 class PrefService;
 
@@ -121,6 +122,8 @@
   // Allows testing code to set a signing service tailored to its needs.
   void SetSigningServiceForTesting(
       std::unique_ptr<policy::SigningService> signing_service);
+  void SetSystemURLLoaderFactoryForTesting(
+      scoped_refptr<network::SharedURLLoaderFactory> system_url_loader_factory);
 
  private:
   // Signing class implementing the policy::SigningService interface to
@@ -180,6 +183,10 @@
   // Our signing service.
   std::unique_ptr<SigningService> signing_service_;
 
+  // The URLLoaderFactory set in tests.
+  scoped_refptr<network::SharedURLLoaderFactory>
+      system_url_loader_factory_for_testing_;
+
   DISALLOW_COPY_AND_ASSIGN(DeviceCloudPolicyInitializer);
 };
 
diff --git a/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos_unittest.cc b/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos_unittest.cc
index 8ecf4c6..acf27f5 100644
--- a/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos_unittest.cc
+++ b/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos_unittest.cc
@@ -16,6 +16,7 @@
 #include "base/compiler_specific.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
+#include "base/memory/ref_counted.h"
 #include "base/run_loop.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "chrome/browser/chromeos/ownership/owner_settings_service_chromeos.h"
@@ -59,6 +60,8 @@
 #include "google_apis/gaia/gaia_oauth_client.h"
 #include "net/url_request/test_url_fetcher_factory.h"
 #include "net/url_request/url_request_test_util.h"
+#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
+#include "services/network/test/test_url_loader_factory.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -118,7 +121,10 @@
   DeviceCloudPolicyManagerChromeOSTest()
       : fake_cryptohome_client_(new chromeos::FakeCryptohomeClient()),
         state_keys_broker_(&fake_session_manager_client_),
-        store_(NULL) {
+        store_(nullptr),
+        test_shared_loader_factory_(
+            base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
+                &test_url_loader_factory_)) {
     fake_statistics_provider_.SetMachineStatistic(
         chromeos::system::kSerialNumberKeyForTest, "test_sn");
     fake_statistics_provider_.SetMachineStatistic(
@@ -165,7 +171,9 @@
     TestingBrowserProcess::GetGlobal()->SetLocalState(&local_state_);
     // SystemSaltGetter is used in DeviceOAuth2TokenService.
     chromeos::SystemSaltGetter::Initialize();
-    chromeos::DeviceOAuth2TokenServiceFactory::Initialize();
+    chromeos::DeviceOAuth2TokenServiceFactory::Initialize(
+        test_shared_loader_factory_);
+
     url_fetcher_response_code_ = 200;
     url_fetcher_response_string_ = "{\"access_token\":\"accessToken4Test\","
                                    "\"expires_in\":1234,"
@@ -196,6 +204,7 @@
     chromeos::DeviceOAuth2TokenServiceFactory::Shutdown();
     chromeos::SystemSaltGetter::Shutdown();
     TestingBrowserProcess::GetGlobal()->SetLocalState(NULL);
+    test_shared_loader_factory_->Detach();
   }
 
   void LockDevice() {
@@ -224,6 +233,8 @@
         &fake_statistics_provider_);
     initializer_->SetSigningServiceForTesting(
         std::make_unique<FakeSigningService>());
+    initializer_->SetSystemURLLoaderFactoryForTesting(
+        test_shared_loader_factory_);
     initializer_->Init();
   }
 
@@ -275,6 +286,10 @@
   std::unique_ptr<DeviceCloudPolicyInitializer> initializer_;
 
  private:
+  network::TestURLLoaderFactory test_url_loader_factory_;
+  scoped_refptr<network::WeakWrapperSharedURLLoaderFactory>
+      test_shared_loader_factory_;
+
   DISALLOW_COPY_AND_ASSIGN(DeviceCloudPolicyManagerChromeOSTest);
 };
 
diff --git a/chrome/browser/chromeos/policy/device_local_account_policy_service.cc b/chrome/browser/chromeos/policy/device_local_account_policy_service.cc
index 629bd10..0091e48 100644
--- a/chrome/browser/chromeos/policy/device_local_account_policy_service.cc
+++ b/chrome/browser/chromeos/policy/device_local_account_policy_service.cc
@@ -64,7 +64,8 @@
 std::unique_ptr<CloudPolicyClient> CreateClient(
     chromeos::DeviceSettingsService* device_settings_service,
     DeviceManagementService* device_management_service,
-    scoped_refptr<net::URLRequestContextGetter> system_request_context) {
+    scoped_refptr<net::URLRequestContextGetter> system_request_context,
+    scoped_refptr<network::SharedURLLoaderFactory> system_url_loader_factory) {
   const em::PolicyData* policy_data = device_settings_service->policy_data();
   if (!policy_data ||
       !policy_data->has_request_token() ||
@@ -77,7 +78,8 @@
       std::make_unique<CloudPolicyClient>(
           std::string() /* machine_id */, std::string() /* machine_model */,
           std::string() /* brand_code */, device_management_service,
-          system_request_context, nullptr /* signing_service */,
+          system_request_context, system_url_loader_factory,
+          nullptr /* signing_service */,
           base::BindRepeating(&GetDeviceDMToken, device_settings_service));
   std::vector<std::string> user_affiliation_ids(
       policy_data->user_affiliation_ids().begin(),
@@ -188,12 +190,14 @@
 void DeviceLocalAccountPolicyBroker::ConnectIfPossible(
     chromeos::DeviceSettingsService* device_settings_service,
     DeviceManagementService* device_management_service,
-    scoped_refptr<net::URLRequestContextGetter> request_context) {
+    scoped_refptr<net::URLRequestContextGetter> request_context,
+    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) {
   if (core_.client())
     return;
 
-  std::unique_ptr<CloudPolicyClient> client(CreateClient(
-      device_settings_service, device_management_service, request_context));
+  std::unique_ptr<CloudPolicyClient> client(
+      CreateClient(device_settings_service, device_management_service,
+                   request_context, url_loader_factory));
   if (!client)
     return;
 
@@ -270,7 +274,8 @@
     scoped_refptr<base::SequencedTaskRunner>
         external_data_service_backend_task_runner,
     scoped_refptr<base::SequencedTaskRunner> io_task_runner,
-    scoped_refptr<net::URLRequestContextGetter> request_context)
+    scoped_refptr<net::URLRequestContextGetter> request_context,
+    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory)
     : session_manager_client_(session_manager_client),
       device_settings_service_(device_settings_service),
       cros_settings_(cros_settings),
@@ -283,6 +288,7 @@
       resource_cache_task_runner_(base::CreateSequencedTaskRunnerWithTraits(
           {base::MayBlock(), base::TaskPriority::BACKGROUND})),
       request_context_(request_context),
+      url_loader_factory_(url_loader_factory),
       local_accounts_subscription_(cros_settings_->AddSettingsObserver(
           chromeos::kAccountsPrefDeviceLocalAccounts,
           base::Bind(
@@ -319,8 +325,8 @@
   for (PolicyBrokerMap::iterator it(policy_brokers_.begin());
        it != policy_brokers_.end(); ++it) {
     it->second->ConnectIfPossible(device_settings_service_,
-                                  device_management_service_,
-                                  request_context_);
+                                  device_management_service_, request_context_,
+                                  url_loader_factory_);
   }
 }
 
@@ -493,8 +499,8 @@
     // Fire up the cloud connection for fetching policy for the account from
     // the cloud if this is an enterprise-managed device.
     broker->ConnectIfPossible(device_settings_service_,
-                              device_management_service_,
-                              request_context_);
+                              device_management_service_, request_context_,
+                              url_loader_factory_);
 
     policy_brokers_[it->user_id] = broker.release();
     if (!broker_initialized) {
diff --git a/chrome/browser/chromeos/policy/device_local_account_policy_service.h b/chrome/browser/chromeos/policy/device_local_account_policy_service.h
index 3646b59..2db069f 100644
--- a/chrome/browser/chromeos/policy/device_local_account_policy_service.h
+++ b/chrome/browser/chromeos/policy/device_local_account_policy_service.h
@@ -25,6 +25,7 @@
 #include "components/policy/core/common/cloud/cloud_policy_store.h"
 #include "components/policy/core/common/cloud/component_cloud_policy_service.h"
 #include "components/policy/core/common/schema_registry.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
 
 namespace base {
 class SequencedTaskRunner;
@@ -107,7 +108,8 @@
   void ConnectIfPossible(
       chromeos::DeviceSettingsService* device_settings_service,
       DeviceManagementService* device_management_service,
-      scoped_refptr<net::URLRequestContextGetter> request_context);
+      scoped_refptr<net::URLRequestContextGetter> request_context,
+      scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory);
 
   // Reads the refresh delay from policy and configures the refresh scheduler.
   void UpdateRefreshDelay();
@@ -175,7 +177,8 @@
       scoped_refptr<base::SequencedTaskRunner>
           external_data_service_backend_task_runner,
       scoped_refptr<base::SequencedTaskRunner> io_task_runner,
-      scoped_refptr<net::URLRequestContextGetter> request_context);
+      scoped_refptr<net::URLRequestContextGetter> request_context,
+      scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory);
   virtual ~DeviceLocalAccountPolicyService();
 
   // Shuts down the service and prevents further policy fetches from the cloud.
@@ -273,6 +276,7 @@
   std::unique_ptr<DeviceLocalAccountExternalDataService> external_data_service_;
 
   scoped_refptr<net::URLRequestContextGetter> request_context_;
+  scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
 
   const std::unique_ptr<chromeos::CrosSettings::ObserverSubscription>
       local_accounts_subscription_;
diff --git a/chrome/browser/chromeos/policy/device_local_account_policy_service_unittest.cc b/chrome/browser/chromeos/policy/device_local_account_policy_service_unittest.cc
index 592d6bd..2b2959e7 100644
--- a/chrome/browser/chromeos/policy/device_local_account_policy_service_unittest.cc
+++ b/chrome/browser/chromeos/policy/device_local_account_policy_service_unittest.cc
@@ -47,6 +47,7 @@
 #include "components/policy/proto/device_management_backend.pb.h"
 #include "net/url_request/url_request_context_getter.h"
 #include "net/url_request/url_request_test_util.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 using testing::AnyNumber;
@@ -167,8 +168,8 @@
       &affiliated_invalidation_service_provider_,
       base::ThreadTaskRunnerHandle::Get(), extension_cache_task_runner_,
       base::ThreadTaskRunnerHandle::Get(), base::ThreadTaskRunnerHandle::Get(),
-      new net::TestURLRequestContextGetter(
-          base::ThreadTaskRunnerHandle::Get())));
+      new net::TestURLRequestContextGetter(base::ThreadTaskRunnerHandle::Get()),
+      /*url_loader_factory=*/nullptr));
 }
 
 void DeviceLocalAccountPolicyServiceTestBase::
diff --git a/chrome/browser/chromeos/policy/policy_oauth2_token_fetcher.cc b/chrome/browser/chromeos/policy/policy_oauth2_token_fetcher.cc
index a2230a8f..620f0f2 100644
--- a/chrome/browser/chromeos/policy/policy_oauth2_token_fetcher.cc
+++ b/chrome/browser/chromeos/policy/policy_oauth2_token_fetcher.cc
@@ -20,6 +20,7 @@
 #include "google_apis/gaia/google_service_auth_error.h"
 #include "google_apis/gaia/oauth2_access_token_fetcher_impl.h"
 #include "net/url_request/url_request_context_getter.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
 
 using content::BrowserThread;
 
@@ -48,13 +49,17 @@
   void StartWithSigninContext(
       net::URLRequestContextGetter* auth_context_getter,
       net::URLRequestContextGetter* system_context_getter,
+      scoped_refptr<network::SharedURLLoaderFactory> system_url_loader_factory,
       const TokenCallback& callback) override;
-  void StartWithAuthCode(const std::string& auth_code,
-                         net::URLRequestContextGetter* system_context_getter,
-                         const TokenCallback& callback) override;
+  void StartWithAuthCode(
+      const std::string& auth_code,
+      net::URLRequestContextGetter* system_context_getter,
+      scoped_refptr<network::SharedURLLoaderFactory> system_url_loader_factory,
+      const TokenCallback& callback) override;
   void StartWithRefreshToken(
       const std::string& oauth2_refresh_token,
       net::URLRequestContextGetter* system_context_getter,
+      scoped_refptr<network::SharedURLLoaderFactory> system_url_loader_factory,
       const TokenCallback& callback) override;
 
   // Returns true if we have previously attempted to fetch tokens with this
@@ -100,6 +105,7 @@
 
   scoped_refptr<net::URLRequestContextGetter> auth_context_getter_;
   scoped_refptr<net::URLRequestContextGetter> system_context_getter_;
+  scoped_refptr<network::SharedURLLoaderFactory> system_url_loader_factory_;
   std::unique_ptr<GaiaAuthFetcher> refresh_token_fetcher_;
   std::unique_ptr<OAuth2AccessTokenFetcher> access_token_fetcher_;
 
@@ -132,11 +138,13 @@
 void PolicyOAuth2TokenFetcherImpl::StartWithSigninContext(
     net::URLRequestContextGetter* auth_context_getter,
     net::URLRequestContextGetter* system_context_getter,
+    scoped_refptr<network::SharedURLLoaderFactory> system_url_loader_factory,
     const TokenCallback& callback) {
   DCHECK(!refresh_token_fetcher_ && !access_token_fetcher_);
 
   auth_context_getter_ = auth_context_getter;
   system_context_getter_ = system_context_getter;
+  system_url_loader_factory_ = system_url_loader_factory;
   callback_ = callback;
   StartFetchingRefreshToken();
 }
@@ -144,11 +152,13 @@
 void PolicyOAuth2TokenFetcherImpl::StartWithAuthCode(
     const std::string& auth_code,
     net::URLRequestContextGetter* system_context_getter,
+    scoped_refptr<network::SharedURLLoaderFactory> system_url_loader_factory,
     const TokenCallback& callback) {
   DCHECK(!refresh_token_fetcher_ && !access_token_fetcher_);
 
   auth_code_ = auth_code;
   system_context_getter_ = system_context_getter;
+  system_url_loader_factory_ = system_url_loader_factory;
   callback_ = callback;
   StartFetchingRefreshToken();
 }
@@ -156,11 +166,13 @@
 void PolicyOAuth2TokenFetcherImpl::StartWithRefreshToken(
     const std::string& oauth2_refresh_token,
     net::URLRequestContextGetter* system_context_getter,
+    scoped_refptr<network::SharedURLLoaderFactory> system_url_loader_factory,
     const TokenCallback& callback) {
   DCHECK(!refresh_token_fetcher_ && !access_token_fetcher_);
 
   oauth2_refresh_token_ = oauth2_refresh_token;
   system_context_getter_ = system_context_getter;
+  system_url_loader_factory_ = system_url_loader_factory;
   callback_ = callback;
   StartFetchingAccessToken();
 }
@@ -192,10 +204,8 @@
   std::vector<std::string> scopes;
   scopes.push_back(GaiaConstants::kDeviceManagementServiceOAuth);
   scopes.push_back(GaiaConstants::kOAuthWrapBridgeUserInfoScope);
-  access_token_fetcher_.reset(
-      new OAuth2AccessTokenFetcherImpl(this,
-                                       system_context_getter_.get(),
-                                       oauth2_refresh_token_));
+  access_token_fetcher_.reset(new OAuth2AccessTokenFetcherImpl(
+      this, system_url_loader_factory_, oauth2_refresh_token_));
   access_token_fetcher_->Start(
       GaiaUrls::GetInstance()->oauth2_chrome_client_id(),
       GaiaUrls::GetInstance()->oauth2_chrome_client_secret(),
@@ -277,19 +287,23 @@
   void StartWithSigninContext(
       net::URLRequestContextGetter* auth_context_getter,
       net::URLRequestContextGetter* system_context_getter,
+      scoped_refptr<network::SharedURLLoaderFactory> system_url_loader_factory,
       const TokenCallback& callback) override {
     ForwardPolicyToken(callback);
   }
 
-  void StartWithAuthCode(const std::string& auth_code,
-                         net::URLRequestContextGetter* system_context_getter,
-                         const TokenCallback& callback) override {
+  void StartWithAuthCode(
+      const std::string& auth_code,
+      net::URLRequestContextGetter* system_context_getter,
+      scoped_refptr<network::SharedURLLoaderFactory> system_url_loader_factory,
+      const TokenCallback& callback) override {
     ForwardPolicyToken(callback);
   }
 
   void StartWithRefreshToken(
       const std::string& oauth2_refresh_token,
       net::URLRequestContextGetter* system_context_getter,
+      scoped_refptr<network::SharedURLLoaderFactory> system_url_loader_factory,
       const TokenCallback& callback) override {
     ForwardPolicyToken(callback);
   }
diff --git a/chrome/browser/chromeos/policy/policy_oauth2_token_fetcher.h b/chrome/browser/chromeos/policy/policy_oauth2_token_fetcher.h
index a42bf80..f32574d 100644
--- a/chrome/browser/chromeos/policy/policy_oauth2_token_fetcher.h
+++ b/chrome/browser/chromeos/policy/policy_oauth2_token_fetcher.h
@@ -10,12 +10,17 @@
 
 #include "base/callback.h"
 #include "base/macros.h"
+#include "base/memory/ref_counted.h"
 #include "google_apis/gaia/gaia_auth_consumer.h"
 
 namespace net {
 class URLRequestContextGetter;
 }
 
+namespace network {
+class SharedURLLoaderFactory;
+}
+
 namespace policy {
 
 // Fetches the OAuth2 token for the device management service. Since Profile
@@ -43,14 +48,17 @@
   virtual void StartWithSigninContext(
       net::URLRequestContextGetter* auth_context_getter,
       net::URLRequestContextGetter* system_context_getter,
+      scoped_refptr<network::SharedURLLoaderFactory> system_url_loader_factory,
       const TokenCallback& callback) = 0;
   virtual void StartWithAuthCode(
       const std::string& auth_code,
       net::URLRequestContextGetter* system_context_getter,
+      scoped_refptr<network::SharedURLLoaderFactory> system_url_loader_factory,
       const TokenCallback& callback) = 0;
   virtual void StartWithRefreshToken(
       const std::string& oauth2_refresh_token,
       net::URLRequestContextGetter* system_context_getter,
+      scoped_refptr<network::SharedURLLoaderFactory> system_url_loader_factory,
       const TokenCallback& callback) = 0;
 
   // Returns true if we have previously attempted to fetch tokens with this
diff --git a/chrome/browser/chromeos/policy/upload_job_unittest.cc b/chrome/browser/chromeos/policy/upload_job_unittest.cc
index ab2bec3..657e7270 100644
--- a/chrome/browser/chromeos/policy/upload_job_unittest.cc
+++ b/chrome/browser/chromeos/policy/upload_job_unittest.cc
@@ -28,6 +28,7 @@
 #include "net/test/embedded_test_server/http_response.h"
 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
 #include "net/url_request/url_request_test_util.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace policy {
@@ -69,12 +70,14 @@
   ~MockOAuth2TokenService() override;
 
   // OAuth2TokenService:
-  void FetchOAuth2Token(RequestImpl* request,
-                        const std::string& account_id,
-                        net::URLRequestContextGetter* getter,
-                        const std::string& client_id,
-                        const std::string& client_secret,
-                        const ScopeSet& scopes) override;
+  void FetchOAuth2Token(
+      RequestImpl* request,
+      const std::string& account_id,
+      net::URLRequestContextGetter* getter,
+      scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
+      const std::string& client_id,
+      const std::string& client_secret,
+      const ScopeSet& scopes) override;
 
   // OAuth2TokenService:
   void InvalidateAccessTokenImpl(const std::string& account_id,
@@ -104,6 +107,7 @@
     OAuth2TokenService::RequestImpl* request,
     const std::string& account_id,
     net::URLRequestContextGetter* getter,
+    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
     const std::string& client_id,
     const std::string& client_secret,
     const FakeOAuth2TokenService::ScopeSet& scopes) {
diff --git a/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.cc b/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.cc
index 586bc19..7c860b6 100644
--- a/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.cc
+++ b/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.cc
@@ -34,6 +34,7 @@
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
 #include "chrome/browser/invalidation/profile_invalidation_provider_factory.h"
 #include "chrome/browser/lifetime/application_lifetime.h"
+#include "chrome/browser/net/system_network_context_manager.h"
 #include "chrome/browser/policy/cloud/remote_commands_invalidator_impl.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/chrome_content_client.h"
@@ -56,6 +57,7 @@
 #include "content/public/browser/notification_details.h"
 #include "content/public/browser/notification_source.h"
 #include "net/url_request/url_request_context_getter.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
 #include "url/gurl.h"
 
 namespace em = enterprise_management;
@@ -179,12 +181,18 @@
   OnPolicyRefreshTimeout();
 }
 
+void UserCloudPolicyManagerChromeOS::SetSystemURLLoaderFactoryForTests(
+    scoped_refptr<network::SharedURLLoaderFactory> system_url_loader_factory) {
+  system_url_loader_factory_for_tests_ = system_url_loader_factory;
+}
+
 UserCloudPolicyManagerChromeOS::~UserCloudPolicyManagerChromeOS() {}
 
 void UserCloudPolicyManagerChromeOS::Connect(
     PrefService* local_state,
     DeviceManagementService* device_management_service,
-    scoped_refptr<net::URLRequestContextGetter> system_request_context) {
+    scoped_refptr<net::URLRequestContextGetter> system_request_context,
+    scoped_refptr<network::SharedURLLoaderFactory> system_url_loader_factory) {
   DCHECK(device_management_service);
   DCHECK(local_state);
 
@@ -209,7 +217,8 @@
       std::make_unique<CloudPolicyClient>(
           std::string() /* machine_id */, std::string() /* machine_model */,
           std::string() /* brand_code */, device_management_service,
-          system_request_context, nullptr /* signing_service */,
+          system_request_context, system_url_loader_factory,
+          nullptr /* signing_service */,
           chromeos::GetDeviceDMTokenForUserPolicyGetter(account_id_));
   CreateComponentCloudPolicyService(
       dm_protocol::kChromeExtensionPolicyType, component_policy_cache_path_,
@@ -535,6 +544,17 @@
     return;
   }
 
+  // TODO(jcivelli): Connect() is passed a SharedURLLoaderFactory but here we
+  // retrieve it from |g_browser_process|. We should move away from retrieving
+  // it from |g_browser_process| at which point we can remove
+  // SetSystemURLLoaderFactoryForTests().
+  scoped_refptr<network::SharedURLLoaderFactory> system_url_loader_factory =
+      system_url_loader_factory_for_tests_;
+  if (!system_url_loader_factory) {
+    system_url_loader_factory =
+        g_browser_process->system_network_context_manager()
+            ->GetSharedURLLoaderFactory();
+  }
   const std::string& refresh_token = chromeos::UserSessionManager::GetInstance()
                                          ->user_context()
                                          .GetRefreshToken();
@@ -542,6 +562,7 @@
     token_fetcher_.reset(PolicyOAuth2TokenFetcher::CreateInstance());
     token_fetcher_->StartWithRefreshToken(
         refresh_token, g_browser_process->system_request_context(),
+        system_url_loader_factory,
         base::Bind(&UserCloudPolicyManagerChromeOS::OnOAuth2PolicyTokenFetched,
                    base::Unretained(this)));
     return;
@@ -559,6 +580,7 @@
   token_fetcher_.reset(PolicyOAuth2TokenFetcher::CreateInstance());
   token_fetcher_->StartWithSigninContext(
       signin_context.get(), g_browser_process->system_request_context(),
+      system_url_loader_factory,
       base::Bind(&UserCloudPolicyManagerChromeOS::OnOAuth2PolicyTokenFetched,
                  base::Unretained(this)));
 }
diff --git a/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.h b/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.h
index 7601e8f4..99508ed 100644
--- a/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.h
+++ b/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.h
@@ -39,6 +39,10 @@
 class URLRequestContextGetter;
 }
 
+namespace network {
+class SharedURLLoaderFactory;
+}
+
 namespace policy {
 
 class AppInstallEventLogUploader;
@@ -114,7 +118,8 @@
   void Connect(
       PrefService* local_state,
       DeviceManagementService* device_management_service,
-      scoped_refptr<net::URLRequestContextGetter> system_request_context);
+      scoped_refptr<net::URLRequestContextGetter> system_request_context,
+      scoped_refptr<network::SharedURLLoaderFactory> system_url_loader_factory);
 
   // This class is one of the policy providers, and must be ready for the
   // creation of the Profile's PrefService; all the other KeyedServices depend
@@ -163,6 +168,11 @@
   // policy server.
   StatusUploader* GetStatusUploader() const { return status_uploader_.get(); }
 
+  // Sets a SharedURLLoaderFactory that should be used for tests instead of
+  // retrieving one from the BrowserProcess object in FetchPolicyOAuthToken().
+  void SetSystemURLLoaderFactoryForTests(
+      scoped_refptr<network::SharedURLLoaderFactory> system_url_loader_factory);
+
  protected:
   // CloudPolicyManager:
   void GetChromePolicy(PolicyMap* policy_map) override;
@@ -295,6 +305,10 @@
   std::unique_ptr<KeyedServiceShutdownNotifier::Subscription>
       shutdown_notifier_;
 
+  // The SharedURLLoaderFactory used in some tests to simulate network requests.
+  scoped_refptr<network::SharedURLLoaderFactory>
+      system_url_loader_factory_for_tests_;
+
   DISALLOW_COPY_AND_ASSIGN(UserCloudPolicyManagerChromeOS);
 };
 
diff --git a/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos_unittest.cc b/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos_unittest.cc
index 12e792ce..04024e2f 100644
--- a/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos_unittest.cc
+++ b/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos_unittest.cc
@@ -59,6 +59,9 @@
 #include "net/url_request/url_fetcher_delegate.h"
 #include "net/url_request/url_request_context_getter.h"
 #include "net/url_request/url_request_status.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
+#include "services/network/test/test_url_loader_factory.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -81,26 +84,26 @@
 
 using PolicyEnforcement = UserCloudPolicyManagerChromeOS::PolicyEnforcement;
 
-const char kAccountId[] = "user@example.com";
-const char kTestGaiaId[] = "12345";
+constexpr char kAccountId[] = "user@example.com";
+constexpr char kTestGaiaId[] = "12345";
 
-const char kChildAccountId[] = "child@example.com";
-const char kChildTestGaiaId[] = "54321";
+constexpr char kChildAccountId[] = "child@example.com";
+constexpr char kChildTestGaiaId[] = "54321";
 
-const char kOAuthCodeCookie[] = "oauth_code=1234; Secure; HttpOnly";
+constexpr char kOAuthCodeCookie[] = "oauth_code=1234; Secure; HttpOnly";
 
-const char kOAuth2TokenPairData[] =
-    "{"
-    "  \"refresh_token\": \"1234\","
-    "  \"access_token\": \"5678\","
-    "  \"expires_in\": 3600"
-    "}";
+constexpr char kOAuth2TokenPairData[] = R"(
+    {
+      "refresh_token": "1234",
+      "access_token": "5678",
+      "expires_in": 3600
+    })";
 
-const char kOAuth2AccessTokenData[] =
-    "{"
-    "  \"access_token\": \"5678\","
-    "  \"expires_in\": 3600"
-    "}";
+constexpr char kOAuth2AccessTokenData[] = R"(
+    {
+      "access_token": "5678",
+      "expires_in": 3600
+    })";
 
 class UserCloudPolicyManagerChromeOSTest : public testing::Test {
  public:
@@ -122,13 +125,16 @@
 
  protected:
   UserCloudPolicyManagerChromeOSTest()
-      : store_(NULL),
-        external_data_manager_(NULL),
+      : store_(nullptr),
+        external_data_manager_(nullptr),
         task_runner_(new base::TestSimpleTaskRunner()),
-        profile_(NULL),
-        signin_profile_(NULL),
+        profile_(nullptr),
+        signin_profile_(nullptr),
         user_manager_(new chromeos::FakeChromeUserManager()),
-        user_manager_enabler_(base::WrapUnique(user_manager_)) {}
+        user_manager_enabler_(base::WrapUnique(user_manager_)),
+        test_shared_loader_factory_(
+            base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
+                &test_url_loader_factory_)) {}
 
   void AddAndSwitchToChildAccountWithProfile() {
     const AccountId child_account_id =
@@ -217,6 +223,7 @@
     signin_profile_ = NULL;
     profile_ = NULL;
     profile_manager_->DeleteTestingProfile(chrome::kInitialProfile);
+    test_shared_loader_factory_->Detach();
 
     chromeos::DBusThreadManager::Shutdown();
   }
@@ -251,6 +258,19 @@
     return fetcher;
   }
 
+  void SimulateOAuth2TokenResponse(const std::string& content) {
+    GURL url = GaiaUrls::GetInstance()->oauth2_token_url();
+    ASSERT_TRUE(test_url_loader_factory_.IsPending(url.spec()));
+    ASSERT_EQ(url, (*test_url_loader_factory_.pending_requests())[0].url);
+
+    network::TestURLLoaderFactory::PendingRequest request =
+        std::move((*test_url_loader_factory_.pending_requests())[0]);
+    test_url_loader_factory_.pending_requests()->erase(
+        test_url_loader_factory_.pending_requests()->begin());
+    network::TestURLLoaderFactory::SimulateResponse(std::move(request),
+                                                    content);
+  }
+
   // Issues the OAuth2 tokens and returns the device management register job
   // if the flow succeeded.
   MockDeviceManagementJob* IssueOAuthToken(bool has_request_token) {
@@ -265,13 +285,13 @@
 
     if (!has_request_token) {
       GaiaUrls* gaia_urls = GaiaUrls::GetInstance();
-      net::TestURLFetcher* fetcher = NULL;
+      net::TestURLFetcher* fetcher = nullptr;
 
       // Issue the oauth_token cookie first.
       fetcher = PrepareOAuthFetcher(
           gaia_urls->deprecated_client_login_to_oauth2_url());
       if (!fetcher)
-        return NULL;
+        return nullptr;
 
       scoped_refptr<net::HttpResponseHeaders> reponse_headers =
           new net::HttpResponseHeaders("");
@@ -280,18 +300,16 @@
       fetcher->delegate()->OnURLFetchComplete(fetcher);
 
       // Issue the refresh token.
+      // This uses GaiaAuthFetcher() which still uses URLRequests.
       fetcher = PrepareOAuthFetcher(gaia_urls->oauth2_token_url());
       if (!fetcher)
         return NULL;
       fetcher->SetResponseString(kOAuth2TokenPairData);
       fetcher->delegate()->OnURLFetchComplete(fetcher);
 
-      // Issue the access token.
-      fetcher = PrepareOAuthFetcher(gaia_urls->oauth2_token_url());
-      if (!fetcher)
-        return NULL;
-      fetcher->SetResponseString(kOAuth2AccessTokenData);
-      fetcher->delegate()->OnURLFetchComplete(fetcher);
+      // Issue the access token. This uses OAuth2AccessTokenFetcher which uses
+      // the network service.
+      SimulateOAuth2TokenResponse(kOAuth2AccessTokenData);
     } else {
       // Since the refresh token is available, OAuth2TokenService was used
       // to request the access token and not UserCloudPolicyTokenForwarder.
@@ -404,12 +422,15 @@
             base::Unretained(this)),
         active_user->GetAccountId(), task_runner_, task_runner_));
     manager_->AddObserver(&observer_);
+    manager_->SetSystemURLLoaderFactoryForTests(test_shared_loader_factory_);
     should_create_token_forwarder_ = fetch_timeout.is_zero();
   }
 
   void InitAndConnectManager() {
     manager_->Init(&schema_registry_);
-    manager_->Connect(&prefs_, &device_management_service_, NULL);
+    manager_->Connect(&prefs_, &device_management_service_,
+                      /*system_request_context=*/nullptr,
+                      /*system_url_loader_factory=*/nullptr);
     if (should_create_token_forwarder_) {
       // Create the UserCloudPolicyTokenForwarder, which fetches the access
       // token using the OAuth2PolicyFetcher and forwards it to the
@@ -433,6 +454,10 @@
   bool should_create_token_forwarder_ = false;
   bool fatal_error_encountered_ = false;
 
+  network::TestURLLoaderFactory test_url_loader_factory_;
+  scoped_refptr<network::WeakWrapperSharedURLLoaderFactory>
+      test_shared_loader_factory_;
+
   DISALLOW_COPY_AND_ASSIGN(UserCloudPolicyManagerChromeOSTest);
 };
 
diff --git a/chrome/browser/chromeos/policy/user_policy_manager_factory_chromeos.cc b/chrome/browser/chromeos/policy/user_policy_manager_factory_chromeos.cc
index c41203cc..5a376bef 100644
--- a/chrome/browser/chromeos/policy/user_policy_manager_factory_chromeos.cc
+++ b/chrome/browser/chromeos/policy/user_policy_manager_factory_chromeos.cc
@@ -28,6 +28,7 @@
 #include "chrome/browser/chromeos/settings/cros_settings.h"
 #include "chrome/browser/chromeos/settings/install_attributes.h"
 #include "chrome/browser/lifetime/application_lifetime.h"
+#include "chrome/browser/net/system_network_context_manager.h"
 #include "chrome/browser/policy/schema_registry_service.h"
 #include "chrome/browser/policy/schema_registry_service_factory.h"
 #include "chrome/browser/profiles/profile.h"
@@ -49,6 +50,7 @@
 #include "components/user_manager/user_manager.h"
 #include "content/public/browser/browser_thread.h"
 #include "net/url_request/url_request_context_getter.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
 
 using user_manager::known_user::ProfileRequiresPolicy;
 namespace policy {
@@ -419,7 +421,9 @@
         SchemaRegistryServiceFactory::GetForContext(profile)->registry());
     manager->Connect(g_browser_process->local_state(),
                      device_management_service,
-                     g_browser_process->system_request_context());
+                     g_browser_process->system_request_context(),
+                     g_browser_process->system_network_context_manager()
+                         ->GetSharedURLLoaderFactory());
 
     cloud_managers_[profile] = manager.get();
     return std::move(manager);
diff --git a/chrome/browser/chromeos/policy/wildcard_login_checker.cc b/chrome/browser/chromeos/policy/wildcard_login_checker.cc
index b0192d8..7d12bce 100644
--- a/chrome/browser/chromeos/policy/wildcard_login_checker.cc
+++ b/chrome/browser/chromeos/policy/wildcard_login_checker.cc
@@ -9,8 +9,10 @@
 #include "base/metrics/histogram_macros.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chromeos/policy/policy_oauth2_token_fetcher.h"
+#include "chrome/browser/net/system_network_context_manager.h"
 #include "components/policy/core/browser/browser_policy_connector.h"
 #include "net/url_request/url_request_context_getter.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
 
 namespace policy {
 
@@ -46,6 +48,8 @@
   token_fetcher_.reset(PolicyOAuth2TokenFetcher::CreateInstance());
   token_fetcher_->StartWithSigninContext(
       signin_context.get(), g_browser_process->system_request_context(),
+      g_browser_process->system_network_context_manager()
+          ->GetSharedURLLoaderFactory(),
       base::Bind(&WildcardLoginChecker::OnPolicyTokenFetched,
                  base::Unretained(this)));
 }
@@ -62,6 +66,8 @@
   token_fetcher_.reset(PolicyOAuth2TokenFetcher::CreateInstance());
   token_fetcher_->StartWithRefreshToken(
       refresh_token, g_browser_process->system_request_context(),
+      g_browser_process->system_network_context_manager()
+          ->GetSharedURLLoaderFactory(),
       base::Bind(&WildcardLoginChecker::OnPolicyTokenFetched,
                  base::Unretained(this)));
 }
diff --git a/chrome/browser/chromeos/settings/device_oauth2_token_service.cc b/chrome/browser/chromeos/settings/device_oauth2_token_service.cc
index 0273d2c..7742b30 100644
--- a/chrome/browser/chromeos/settings/device_oauth2_token_service.cc
+++ b/chrome/browser/chromeos/settings/device_oauth2_token_service.cc
@@ -17,6 +17,7 @@
 #include "chrome/common/pref_names.h"
 #include "components/prefs/pref_registry_simple.h"
 #include "google_apis/gaia/google_service_auth_error.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
 
 namespace chromeos {
 
@@ -75,6 +76,7 @@
     RequestImpl* request,
     const std::string& account_id,
     net::URLRequestContextGetter* getter,
+    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
     const std::string& client_id,
     const std::string& client_secret,
     const ScopeSet& scopes) {
@@ -98,8 +100,9 @@
       return;
     case DeviceOAuth2TokenServiceDelegate::STATE_TOKEN_VALID:
       // Pass through to OAuth2TokenService to satisfy the request.
-      OAuth2TokenService::FetchOAuth2Token(
-          request, account_id, getter, client_id, client_secret, scopes);
+      OAuth2TokenService::FetchOAuth2Token(request, account_id, getter,
+                                           url_loader_factory, client_id,
+                                           client_secret, scopes);
       return;
   }
 
@@ -122,7 +125,8 @@
       OAuth2TokenService::FetchOAuth2Token(
           scoped_request->request.get(),
           scoped_request->request->GetAccountId(),
-          GetDeviceDelegate()->GetRequestContext(), scoped_request->client_id,
+          GetDeviceDelegate()->GetRequestContext(),
+          GetDeviceDelegate()->GetURLLoaderFactory(), scoped_request->client_id,
           scoped_request->client_secret, scoped_request->scopes);
     } else {
       FailRequest(scoped_request->request.get(), error);
diff --git a/chrome/browser/chromeos/settings/device_oauth2_token_service.h b/chrome/browser/chromeos/settings/device_oauth2_token_service.h
index b23e93a2..7a75849 100644
--- a/chrome/browser/chromeos/settings/device_oauth2_token_service.h
+++ b/chrome/browser/chromeos/settings/device_oauth2_token_service.h
@@ -12,11 +12,6 @@
 #include "base/macros.h"
 #include "chrome/browser/chromeos/settings/device_oauth2_token_service_delegate.h"
 #include "google_apis/gaia/oauth2_token_service.h"
-#include "net/url_request/url_request_context_getter.h"
-
-namespace net {
-class URLRequestContextGetter;
-}
 
 class PrefRegistrySimple;
 
@@ -51,12 +46,15 @@
 
  protected:
   // Implementation of OAuth2TokenService.
-  void FetchOAuth2Token(RequestImpl* request,
-                        const std::string& account_id,
-                        net::URLRequestContextGetter* getter,
-                        const std::string& client_id,
-                        const std::string& client_secret,
-                        const ScopeSet& scopes) override;
+  void FetchOAuth2Token(
+      RequestImpl* request,
+      const std::string& account_id,
+      net::URLRequestContextGetter* getter,
+      scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
+      const std::string& client_id,
+      const std::string& client_secret,
+      const ScopeSet& scopes) override;
+
  private:
   friend class DeviceOAuth2TokenServiceFactory;
   friend class DeviceOAuth2TokenServiceTest;
diff --git a/chrome/browser/chromeos/settings/device_oauth2_token_service_delegate.cc b/chrome/browser/chromeos/settings/device_oauth2_token_service_delegate.cc
index 7d850d15..be9058b 100644
--- a/chrome/browser/chromeos/settings/device_oauth2_token_service_delegate.cc
+++ b/chrome/browser/chromeos/settings/device_oauth2_token_service_delegate.cc
@@ -23,6 +23,7 @@
 #include "google_apis/gaia/gaia_urls.h"
 #include "google_apis/gaia/google_service_auth_error.h"
 #include "google_apis/gaia/oauth2_access_token_fetcher_impl.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
 
 namespace chromeos {
 
@@ -33,20 +34,21 @@
 
 DeviceOAuth2TokenServiceDelegate::DeviceOAuth2TokenServiceDelegate(
     net::URLRequestContextGetter* getter,
+    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
     PrefService* local_state)
     : url_request_context_getter_(getter),
+      url_loader_factory_(url_loader_factory),
       local_state_(local_state),
       state_(STATE_LOADING),
       max_refresh_token_validation_retries_(3),
       validation_requested_(false),
       validation_status_delegate_(nullptr),
       service_account_identity_subscription_(
-          CrosSettings::Get()
-              ->AddSettingsObserver(
-                  kServiceAccountIdentity,
-                  base::Bind(&DeviceOAuth2TokenServiceDelegate::
-                                 OnServiceAccountIdentityChanged,
-                             base::Unretained(this)))),
+          CrosSettings::Get()->AddSettingsObserver(
+              kServiceAccountIdentity,
+              base::Bind(&DeviceOAuth2TokenServiceDelegate::
+                             OnServiceAccountIdentityChanged,
+                         base::Unretained(this)))),
       weak_ptr_factory_(this) {
   // Pull in the system salt.
   SystemSaltGetter::Get()->GetSystemSalt(
@@ -163,14 +165,21 @@
   return url_request_context_getter_.get();
 }
 
+scoped_refptr<network::SharedURLLoaderFactory>
+DeviceOAuth2TokenServiceDelegate::GetURLLoaderFactory() const {
+  return url_loader_factory_;
+}
+
 OAuth2AccessTokenFetcher*
 DeviceOAuth2TokenServiceDelegate::CreateAccessTokenFetcher(
     const std::string& account_id,
     net::URLRequestContextGetter* getter,
+    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
     OAuth2AccessTokenConsumer* consumer) {
   std::string refresh_token = GetRefreshToken(account_id);
   DCHECK(!refresh_token.empty());
-  return new OAuth2AccessTokenFetcherImpl(consumer, getter, refresh_token);
+  return new OAuth2AccessTokenFetcherImpl(consumer, url_loader_factory,
+                                          refresh_token);
 }
 
 void DeviceOAuth2TokenServiceDelegate::DidGetSystemSalt(
diff --git a/chrome/browser/chromeos/settings/device_oauth2_token_service_delegate.h b/chrome/browser/chromeos/settings/device_oauth2_token_service_delegate.h
index 7ae81df..07b4c34 100644
--- a/chrome/browser/chromeos/settings/device_oauth2_token_service_delegate.h
+++ b/chrome/browser/chromeos/settings/device_oauth2_token_service_delegate.h
@@ -11,6 +11,7 @@
 
 #include "base/callback.h"
 #include "base/macros.h"
+#include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
 #include "chrome/browser/chromeos/settings/cros_settings.h"
 #include "google_apis/gaia/gaia_oauth_client.h"
@@ -24,6 +25,9 @@
 namespace net {
 class URLRequestContextGetter;
 }
+namespace network {
+class SharedURLLoaderFactory;
+}
 
 class PrefService;
 
@@ -33,8 +37,10 @@
     : public OAuth2TokenServiceDelegate,
       public gaia::GaiaOAuthClient::Delegate {
  public:
-  DeviceOAuth2TokenServiceDelegate(net::URLRequestContextGetter* getter,
-                                   PrefService* local_state);
+  DeviceOAuth2TokenServiceDelegate(
+      net::URLRequestContextGetter* getter,
+      scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
+      PrefService* local_state);
   ~DeviceOAuth2TokenServiceDelegate() override;
 
   typedef base::Callback<void(bool)> StatusCallback;
@@ -53,9 +59,13 @@
 
   net::URLRequestContextGetter* GetRequestContext() const override;
 
+  scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory()
+      const override;
+
   OAuth2AccessTokenFetcher* CreateAccessTokenFetcher(
       const std::string& account_id,
       net::URLRequestContextGetter* getter,
+      scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
       OAuth2AccessTokenConsumer* consumer) override;
 
   // gaia::GaiaOAuthClient::Delegate implementation.
@@ -122,6 +132,7 @@
 
   // Dependencies.
   scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_;
+  scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
   PrefService* local_state_;
 
   // Current operational state.
diff --git a/chrome/browser/chromeos/settings/device_oauth2_token_service_factory.cc b/chrome/browser/chromeos/settings/device_oauth2_token_service_factory.cc
index 61d8a0ac..239f4b7 100644
--- a/chrome/browser/chromeos/settings/device_oauth2_token_service_factory.cc
+++ b/chrome/browser/chromeos/settings/device_oauth2_token_service_factory.cc
@@ -10,8 +10,10 @@
 #include "chrome/browser/chromeos/settings/device_oauth2_token_service.h"
 #include "chrome/browser/chromeos/settings/device_oauth2_token_service_delegate.h"
 #include "chrome/browser/chromeos/settings/token_encryptor.h"
+#include "chrome/browser/net/system_network_context_manager.h"
 #include "chromeos/cryptohome/system_salt_getter.h"
 #include "content/public/browser/browser_thread.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
 
 namespace chromeos {
 
@@ -27,13 +29,19 @@
   return g_device_oauth2_token_service_;
 }
 
-// static
 void DeviceOAuth2TokenServiceFactory::Initialize() {
+  Initialize(g_browser_process->system_network_context_manager()
+                 ->GetSharedURLLoaderFactory());
+}
+
+// static
+void DeviceOAuth2TokenServiceFactory::Initialize(
+    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   DCHECK(!g_device_oauth2_token_service_);
   g_device_oauth2_token_service_ = new DeviceOAuth2TokenService(
       std::make_unique<DeviceOAuth2TokenServiceDelegate>(
-          g_browser_process->system_request_context(),
+          g_browser_process->system_request_context(), url_loader_factory,
           g_browser_process->local_state()));
 }
 
diff --git a/chrome/browser/chromeos/settings/device_oauth2_token_service_factory.h b/chrome/browser/chromeos/settings/device_oauth2_token_service_factory.h
index 11bce88..e8a951cd 100644
--- a/chrome/browser/chromeos/settings/device_oauth2_token_service_factory.h
+++ b/chrome/browser/chromeos/settings/device_oauth2_token_service_factory.h
@@ -9,6 +9,11 @@
 #include <string>
 
 #include "base/macros.h"
+#include "base/memory/ref_counted.h"
+
+namespace network {
+class SharedURLLoaderFactory;
+}
 
 namespace chromeos {
 
@@ -29,6 +34,11 @@
   // available (local state, request context getter and CrosSettings).
   static void Initialize();
 
+  // Same as |Initialize()| but uses |url_loader_factory| for fetching OAuth
+  // tokens. Used in tests.
+  static void Initialize(
+      scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory);
+
   // Called by ChromeBrowserMainPartsChromeOS in order to shutdown the
   // DeviceOAuth2TokenService instance and cancel all in-flight requests before
   // the required global data is destroyed (local state, request context getter
diff --git a/chrome/browser/chromeos/settings/device_oauth2_token_service_unittest.cc b/chrome/browser/chromeos/settings/device_oauth2_token_service_unittest.cc
index 651a62d34..d5228dc 100644
--- a/chrome/browser/chromeos/settings/device_oauth2_token_service_unittest.cc
+++ b/chrome/browser/chromeos/settings/device_oauth2_token_service_unittest.cc
@@ -31,11 +31,14 @@
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "content/public/test/test_utils.h"
 #include "google_apis/gaia/gaia_oauth_client.h"
+#include "google_apis/gaia/gaia_urls.h"
 #include "google_apis/gaia/oauth2_token_service_test_util.h"
 #include "net/http/http_status_code.h"
 #include "net/url_request/test_url_fetcher_factory.h"
 #include "net/url_request/url_fetcher_delegate.h"
 #include "net/url_request/url_request_test_util.h"
+#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
+#include "services/network/test/test_url_loader_factory.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -59,7 +62,6 @@
 
 }  // namespace
 
-static const int kOAuthTokenServiceUrlFetcherId = 0;
 static const int kValidatorUrlFetcherId = gaia::GaiaOAuthClient::kUrlFetcherId;
 
 class DeviceOAuth2TokenServiceTest : public testing::Test {
@@ -67,7 +69,10 @@
   DeviceOAuth2TokenServiceTest()
       : scoped_testing_local_state_(TestingBrowserProcess::GetGlobal()),
         request_context_getter_(new net::TestURLRequestContextGetter(
-            base::ThreadTaskRunnerHandle::Get())) {}
+            base::ThreadTaskRunnerHandle::Get())),
+        test_shared_loader_factory_(
+            base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
+                &test_url_loader_factory_)) {}
   ~DeviceOAuth2TokenServiceTest() override {}
 
   // Most tests just want a noop crypto impl with a dummy refresh token value in
@@ -124,6 +129,7 @@
 
   void TearDown() override {
     oauth2_service_.reset();
+    test_shared_loader_factory_->Detach();
     CrosSettings::Shutdown();
     TestingBrowserProcess::GetGlobal()->ShutdownBrowserPolicyConnector();
     base::TaskScheduler::GetInstance()->FlushForTesting();
@@ -136,7 +142,8 @@
 
   void CreateService() {
     auto delegate = std::make_unique<DeviceOAuth2TokenServiceDelegate>(
-        request_context_getter_.get(), scoped_testing_local_state_.Get());
+        request_context_getter_.get(), test_shared_loader_factory_,
+        scoped_testing_local_state_.Get());
     delegate->max_refresh_token_validation_retries_ = 0;
     oauth2_service_.reset(new DeviceOAuth2TokenService(std::move(delegate)));
     oauth2_service_->set_max_authorization_token_fetch_retries_for_testing(0);
@@ -210,6 +217,9 @@
   content::TestBrowserThreadBundle test_browser_thread_bundle_;
   ScopedTestingLocalState scoped_testing_local_state_;
   scoped_refptr<net::TestURLRequestContextGetter> request_context_getter_;
+  network::TestURLLoaderFactory test_url_loader_factory_;
+  scoped_refptr<network::WeakWrapperSharedURLLoaderFactory>
+      test_shared_loader_factory_;
   net::TestURLFetcherFactory factory_;
   FakeCryptohomeClient* fake_cryptohome_client_;
   FakeSessionManagerClient session_manager_client_;
@@ -240,6 +250,12 @@
     const std::string& tokeninfo_fetch_response,
     net::HttpStatusCode service_access_token_status,
     const std::string& service_access_token_response) {
+  test_url_loader_factory_.AddResponse(
+      GaiaUrls::GetInstance()->oauth2_token_url().spec(),
+      service_access_token_response, service_access_token_status);
+
+  // This sends a response to the OAuth token request made by
+  // GaiaOAuthClient::Core, that should eventually be ported to SimpleURLLoader.
   ReturnOAuthUrlFetchResults(
       kValidatorUrlFetcherId,
       tokeninfo_access_token_status,
@@ -249,11 +265,6 @@
       kValidatorUrlFetcherId,
       tokeninfo_fetch_status,
       tokeninfo_fetch_response);
-
-  ReturnOAuthUrlFetchResults(
-      kOAuthTokenServiceUrlFetcherId,
-      service_access_token_status,
-      service_access_token_response);
 }
 
 void DeviceOAuth2TokenServiceTest::PerformURLFetches() {
diff --git a/chrome/browser/component_updater/cros_component_installer_chromeos.cc b/chrome/browser/component_updater/cros_component_installer_chromeos.cc
index 50eeda3..ab97982 100644
--- a/chrome/browser/component_updater/cros_component_installer_chromeos.cc
+++ b/chrome/browser/component_updater/cros_component_installer_chromeos.cc
@@ -36,7 +36,7 @@
      "1913a5e0a6cad30b6f03e176177e0d7ed62c5d6700a9c66da556d7c3f5d6a47e"},
     {"cros-termina", "1.1",
      "e9d960f84f628e1f42d05de4046bb5b3154b6f1f65c08412c6af57a29aecaffb"},
-    {"rtanalytics-light", "4.0",
+    {"rtanalytics-light", "4.1",
      "69f09d33c439c2ab55bbbe24b47ab55cb3f6c0bd1f1ef46eefea3216ec925038"},
     {"rtanalytics-full", "1.0",
      "c93c3e1013c52100a20038b405ac854d69fa889f6dc4fa6f188267051e05e444"},
diff --git a/chrome/browser/component_updater/widevine_cdm_component_installer.cc b/chrome/browser/component_updater/widevine_cdm_component_installer.cc
index bfe62c44..209c609 100644
--- a/chrome/browser/component_updater/widevine_cdm_component_installer.cc
+++ b/chrome/browser/component_updater/widevine_cdm_component_installer.cc
@@ -327,14 +327,22 @@
 
   VLOG(1) << "Register Widevine CDM with Chrome";
 
+  // Temporary session is always supported.
+  base::flat_set<media::CdmSessionType> supported_session_types = {
+      media::CdmSessionType::TEMPORARY_SESSION};
+  if (supports_persistent_license) {
+    supported_session_types.insert(
+        media::CdmSessionType::PERSISTENT_LICENSE_SESSION);
+  }
+
   const base::FilePath cdm_path =
       GetPlatformDirectory(cdm_install_dir)
           .AppendASCII(base::GetNativeLibraryName(kWidevineCdmLibraryName));
+
   CdmRegistry::GetInstance()->RegisterCdm(content::CdmInfo(
       kWidevineCdmDisplayName, kWidevineCdmGuid, cdm_version, cdm_path,
-      kWidevineCdmFileSystemId, supported_video_codecs,
-      supports_persistent_license, supported_encryption_schemes,
-      kWidevineKeySystem, false));
+      kWidevineCdmFileSystemId, supported_video_codecs, supported_session_types,
+      supported_encryption_schemes, kWidevineKeySystem, false));
 }
 
 }  // namespace
diff --git a/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_api.cc b/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_api.cc
index 0012a40..a2c2510 100644
--- a/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_api.cc
+++ b/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_api.cc
@@ -11,6 +11,7 @@
 #include "base/values.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/extensions/api/enterprise_reporting_private/chrome_desktop_report_request_helper.h"
+#include "chrome/browser/net/system_network_context_manager.h"
 #include "chrome/browser/policy/browser_dm_token_storage.h"
 #include "chrome/browser/policy/chrome_browser_policy_connector.h"
 #include "chrome/browser/profiles/profile.h"
@@ -19,6 +20,7 @@
 #include "components/policy/core/common/cloud/device_management_service.h"
 #include "components/policy/proto/device_management_backend.pb.h"
 #include "net/url_request/url_request_context_getter.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
 
 namespace em = enterprise_management;
 
@@ -40,17 +42,25 @@
 }  // namespace enterprise_reporting
 
 EnterpriseReportingPrivateUploadChromeDesktopReportFunction::
-    EnterpriseReportingPrivateUploadChromeDesktopReportFunction() {
+    EnterpriseReportingPrivateUploadChromeDesktopReportFunction()
+    : EnterpriseReportingPrivateUploadChromeDesktopReportFunction(
+          g_browser_process->system_network_context_manager()
+              ->GetSharedURLLoaderFactory()) {}
+
+EnterpriseReportingPrivateUploadChromeDesktopReportFunction::
+    EnterpriseReportingPrivateUploadChromeDesktopReportFunction(
+        scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) {
   policy::DeviceManagementService* device_management_service =
       g_browser_process->browser_policy_connector()
           ->device_management_service();
   // Initial the DeviceManagementService if it exist and hasn't been initialized
   if (device_management_service)
     device_management_service->ScheduleInitialization(0);
+
   cloud_policy_client_ = std::make_unique<policy::CloudPolicyClient>(
       std::string() /* machine_id */, std::string() /* machine_model */,
       std::string() /* brand_code */, device_management_service,
-      g_browser_process->system_request_context(), nullptr,
+      g_browser_process->system_request_context(), url_loader_factory, nullptr,
       policy::CloudPolicyClient::DeviceDMTokenCallback());
   dm_token_ = policy::BrowserDMTokenStorage::Get()->RetrieveDMToken();
   client_id_ = policy::BrowserDMTokenStorage::Get()->RetrieveClientId();
@@ -59,6 +69,14 @@
 EnterpriseReportingPrivateUploadChromeDesktopReportFunction::
     ~EnterpriseReportingPrivateUploadChromeDesktopReportFunction() {}
 
+// static
+EnterpriseReportingPrivateUploadChromeDesktopReportFunction*
+EnterpriseReportingPrivateUploadChromeDesktopReportFunction::CreateForTesting(
+    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) {
+  return new EnterpriseReportingPrivateUploadChromeDesktopReportFunction(
+      url_loader_factory);
+}
+
 ExtensionFunction::ResponseAction
 EnterpriseReportingPrivateUploadChromeDesktopReportFunction::Run() {
   VLOG(1) << "Uploading enterprise report";
diff --git a/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_api.h b/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_api.h
index 7f1df151..d5b68d2 100644
--- a/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_api.h
+++ b/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_api.h
@@ -5,12 +5,17 @@
 #ifndef CHROME_BROWSER_EXTENSIONS_API_ENTERPRISE_REPORTING_PRIVATE_ENTERPRISE_REPORTING_PRIVATE_API_H_
 #define CHROME_BROWSER_EXTENSIONS_API_ENTERPRISE_REPORTING_PRIVATE_ENTERPRISE_REPORTING_PRIVATE_API_H_
 
+#include "base/memory/ref_counted.h"
 #include "extensions/browser/extension_function.h"
 
 namespace policy {
 class CloudPolicyClient;
 }
 
+namespace network {
+class SharedURLLoaderFactory;
+}
+
 namespace extensions {
 namespace enterprise_reporting {
 
@@ -36,7 +41,16 @@
   void SetRegistrationInfoForTesting(const std::string& dm_token,
                                      const std::string& client_id);
 
+  // Used by tests that want to overrode the URLLoaderFactory used to simulate
+  // network requests.
+  static EnterpriseReportingPrivateUploadChromeDesktopReportFunction*
+  CreateForTesting(
+      scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory);
+
  private:
+  explicit EnterpriseReportingPrivateUploadChromeDesktopReportFunction(
+      scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory);
+
   ~EnterpriseReportingPrivateUploadChromeDesktopReportFunction() override;
 
   // ExtensionFunction
diff --git a/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_unittest.cc b/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_unittest.cc
index 14c234c6..6cd8da0 100644
--- a/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_unittest.cc
+++ b/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_unittest.cc
@@ -9,6 +9,9 @@
 #include "chrome/browser/extensions/extension_api_unittest.h"
 #include "chrome/browser/extensions/extension_function_test_utils.h"
 #include "components/policy/core/common/cloud/mock_cloud_policy_client.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
+#include "services/network/test/test_url_loader_factory.h"
 #include "testing/gmock/include/gmock/gmock.h"
 
 using ::testing::_;
@@ -54,12 +57,18 @@
 
 class EnterpriseReportingPrivateTest : public ExtensionApiUnittest {
  public:
-  EnterpriseReportingPrivateTest() = default;
+  EnterpriseReportingPrivateTest()
+      : test_shared_loader_factory_(
+            base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
+                &test_url_loader_factory_)) {}
+
+  void TearDown() override { test_shared_loader_factory_->Detach(); }
 
   UIThreadExtensionFunction* CreateChromeDesktopReportingFunction(
       const std::string& dm_token) {
     EnterpriseReportingPrivateUploadChromeDesktopReportFunction* function =
-        new EnterpriseReportingPrivateUploadChromeDesktopReportFunction();
+        EnterpriseReportingPrivateUploadChromeDesktopReportFunction::
+            CreateForTesting(test_shared_loader_factory_);
     std::unique_ptr<MockCloudPolicyClient> client =
         std::make_unique<MockCloudPolicyClient>();
     client_ = client.get();
@@ -83,6 +92,10 @@
   MockCloudPolicyClient* client_;
 
  private:
+  network::TestURLLoaderFactory test_url_loader_factory_;
+  scoped_refptr<network::WeakWrapperSharedURLLoaderFactory>
+      test_shared_loader_factory_;
+
   DISALLOW_COPY_AND_ASSIGN(EnterpriseReportingPrivateTest);
 };
 
diff --git a/chrome/browser/extensions/api/sync_file_system/sync_file_system_browsertest.cc b/chrome/browser/extensions/api/sync_file_system/sync_file_system_browsertest.cc
index 5685c04c..5a2d4da 100644
--- a/chrome/browser/extensions/api/sync_file_system/sync_file_system_browsertest.cc
+++ b/chrome/browser/extensions/api/sync_file_system/sync_file_system_browsertest.cc
@@ -41,6 +41,7 @@
   std::unique_ptr<drive::DriveServiceInterface> CreateDriveService(
       OAuth2TokenService* oauth2_token_service,
       net::URLRequestContextGetter* url_request_context_getter,
+      scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
       base::SequencedTaskRunner* blocking_task_runner) override {
     std::unique_ptr<drive::FakeDriveService> drive_service(
         new drive::FakeDriveService);
@@ -90,12 +91,13 @@
         base::ThreadTaskRunnerHandle::Get(),  // ui_task_runner
         MakeSequencedTaskRunner(), MakeSequencedTaskRunner(),
         base_dir_.GetPath(),
-        NULL,  // task_logger
-        NULL,  // notification_manager
+        nullptr,  // task_logger
+        nullptr,  // notification_manager
         extension_service,
         fake_signin_manager_.get(),  // signin_manager
-        NULL,                        // token_service
-        NULL,                        // request_context
+        nullptr,                     // token_service
+        nullptr,                     // request_context
+        nullptr,                     // url_loader_factory
         std::move(drive_service_factory), in_memory_env_.get());
     remote_service_->SetSyncEnabled(true);
     factory->set_mock_remote_file_service(
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index eed1fe7..9240249 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -1231,6 +1231,19 @@
     "Flash Overlay Scrollbars When Mouse Enter a scrollable area. You must also"
     " enable Overlay Scrollbars.";
 
+const char kOverlayStrategiesName[] = "Select HW overlay strategies";
+const char kOverlayStrategiesDescription[] =
+    "Select strategies used to promote quads to HW overlays.";
+const char kOverlayStrategiesDefault[] = "Default";
+const char kOverlayStrategiesNone[] = "None";
+const char kOverlayStrategiesUnoccludedFullscreen[] =
+    "Unoccluded fullscreen buffers (single-fullscreen)";
+const char kOverlayStrategiesUnoccluded[] =
+    "Unoccluded buffers (single-fullscreen,single-on-top)";
+const char kOverlayStrategiesOccludedAndUnoccluded[] =
+    "Occluded and unoccluded buffers "
+    "(single-fullscreen,single-on-top,underlay)";
+
 const char kUseNewAcceptLanguageHeaderName[] = "Use new Accept-Language header";
 const char kUseNewAcceptLanguageHeaderDescription[] =
     "Adds the base language code after other corresponding language+region "
@@ -2631,10 +2644,6 @@
     "Print with Chrome. Printers must be re-connected after changing this "
     "flag.";
 
-const char kDirectManipulationStylusName[] = "Direct Manipulation Stylus";
-const char kDirectManipulationStylusDescription[] =
-    "If enabled, Chrome will scroll web pages on stylus drag.";
-
 const char kDisablePostscriptPrinting[] = "Disable PostScript Printing";
 const char kDisablePostscriptPrintingDescription[] =
     "Disables PostScript generation when printing to PostScript capable "
@@ -3255,6 +3264,14 @@
 
 #endif  // defined(OS_WIN) || defined(OS_MACOSX)
 
+#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX)
+
+const char kDirectManipulationStylusName[] = "Direct Manipulation Stylus";
+const char kDirectManipulationStylusDescription[] =
+    "If enabled, Chrome will scroll web pages on stylus drag.";
+
+#endif  // defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX)
+
 const char kExperimentalUiName[] = "Use all upcoming UI features";
 const char kExperimentalUiDescription[] = "Use all upcoming UI features.";
 
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index ce6814d..91d36e12 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -766,6 +766,14 @@
 extern const char kOverlayScrollbarsFlashWhenMouseEnterName[];
 extern const char kOverlayScrollbarsFlashWhenMouseEnterDescription[];
 
+extern const char kOverlayStrategiesName[];
+extern const char kOverlayStrategiesDescription[];
+extern const char kOverlayStrategiesDefault[];
+extern const char kOverlayStrategiesNone[];
+extern const char kOverlayStrategiesUnoccludedFullscreen[];
+extern const char kOverlayStrategiesUnoccluded[];
+extern const char kOverlayStrategiesOccludedAndUnoccluded[];
+
 extern const char kUseNewAcceptLanguageHeaderName[];
 extern const char kUseNewAcceptLanguageHeaderDescription[];
 
@@ -1595,9 +1603,6 @@
 extern const char kCloudPrintXpsName[];
 extern const char kCloudPrintXpsDescription[];
 
-extern const char kDirectManipulationStylusName[];
-extern const char kDirectManipulationStylusDescription[];
-
 extern const char kDisablePostscriptPrinting[];
 extern const char kDisablePostscriptPrintingDescription[];
 
@@ -2001,6 +2006,13 @@
 
 #endif  // defined(OS_WIN) || defined(OS_MACOSX)
 
+#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX)
+
+extern const char kDirectManipulationStylusName[];
+extern const char kDirectManipulationStylusDescription[];
+
+#endif  // defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX)
+
 // Feature flags --------------------------------------------------------------
 
 #if BUILDFLAG(ENABLE_VR)
diff --git a/chrome/browser/metrics/ukm_browsertest.cc b/chrome/browser/metrics/ukm_browsertest.cc
index 5d17c13..c7856b9 100644
--- a/chrome/browser/metrics/ukm_browsertest.cc
+++ b/chrome/browser/metrics/ukm_browsertest.cc
@@ -68,17 +68,6 @@
     run_loop->Quit();
 }
 
-Profile* CreateNonSyncProfile() {
-  ProfileManager* profile_manager = g_browser_process->profile_manager();
-  base::FilePath new_path = profile_manager->GenerateNextProfileDirectoryPath();
-  base::RunLoop run_loop;
-  profile_manager->CreateProfileAsync(
-      new_path, base::Bind(&UnblockOnProfileCreation, &run_loop),
-      base::string16(), std::string(), std::string());
-  run_loop.Run();
-  return profile_manager->GetProfileByPath(new_path);
-}
-
 Profile* CreateGuestProfile() {
   ProfileManager* profile_manager = g_browser_process->profile_manager();
   base::FilePath new_path = profile_manager->GetGuestProfilePath();
@@ -215,6 +204,20 @@
     return harness;
   }
 
+  Profile* CreateNonSyncProfile() {
+    ProfileManager* profile_manager = g_browser_process->profile_manager();
+    base::FilePath new_path =
+        profile_manager->GenerateNextProfileDirectoryPath();
+    base::RunLoop run_loop;
+    profile_manager->CreateProfileAsync(
+        new_path, base::Bind(&UnblockOnProfileCreation, &run_loop),
+        base::string16(), std::string(), std::string());
+    run_loop.Run();
+    Profile* profile = profile_manager->GetProfileByPath(new_path);
+    SetupMockGaiaResponsesForProfile(profile);
+    return profile;
+  }
+
  private:
   ukm::UkmService* ukm_service() const {
     return g_browser_process->GetMetricsServicesManager()->GetUkmService();
@@ -229,7 +232,7 @@
 class UkmConsentParamBrowserTest : public UkmBrowserTest,
                                    public testing::WithParamInterface<bool> {
  public:
-  UkmConsentParamBrowserTest() : UkmBrowserTest() {}
+  UkmConsentParamBrowserTest() {}
 
   static bool IsMetricsAndCrashReportingEnabled() {
     return ChromeMetricsServiceAccessor::IsMetricsAndCrashReportingEnabled();
diff --git a/chrome/browser/offline_pages/recent_tab_helper.cc b/chrome/browser/offline_pages/recent_tab_helper.cc
index f1c5a8e..125cbde 100644
--- a/chrome/browser/offline_pages/recent_tab_helper.cc
+++ b/chrome/browser/offline_pages/recent_tab_helper.cc
@@ -339,6 +339,24 @@
       base::Bind(&RecentTabHelper::ContinueSnapshotWithIdsToPurge,
                  weak_ptr_factory_.GetWeakPtr(),
                  last_n_ongoing_snapshot_info_.get()));
+
+  IsSavingSamePageEnum saving_same_page_value = IsSavingSamePageEnum::kNewPage;
+  if (last_n_latest_saved_snapshot_info_) {
+    // If there was a previously saved snapshot for the current page we are
+    // saving a new one for the same page.
+    // Note: there might be a difference in page quality between here and when
+    // it's assessed again in ContinueSnapshotAfterPurge but this is not
+    // expected to happen often.
+    if (last_n_latest_saved_snapshot_info_->expected_page_quality ==
+        snapshot_controller_->current_page_quality()) {
+      saving_same_page_value = IsSavingSamePageEnum::kSamePageSameQuality;
+    } else {
+      saving_same_page_value = IsSavingSamePageEnum::kSamePageBetterQuality;
+    }
+  }
+  UMA_HISTOGRAM_ENUMERATION("OfflinePages.LastN.IsSavingSamePage",
+                            saving_same_page_value);
+
   last_n_latest_saved_snapshot_info_.reset();
 }
 
diff --git a/chrome/browser/offline_pages/recent_tab_helper.h b/chrome/browser/offline_pages/recent_tab_helper.h
index 44c45ef..0c5bea7 100644
--- a/chrome/browser/offline_pages/recent_tab_helper.h
+++ b/chrome/browser/offline_pages/recent_tab_helper.h
@@ -30,6 +30,23 @@
       public content::WebContentsUserData<RecentTabHelper>,
       public SnapshotController::Client {
  public:
+  // Possible values to be reported to the IsSavingSamePage histogram. Reflects
+  // the contents of the respective histogram enum and must be kept in sync with
+  // it.
+  enum class IsSavingSamePageEnum {
+    // The snapshot is for a new page.
+    kNewPage = 0,
+    // The snapshot is for a page that has already been saved but a better
+    // expected quality.
+    kSamePageBetterQuality = 1,
+    // The snapshot is for a page that has already been saved at the same
+    // expected quality.
+    kSamePageSameQuality = 2,
+    // Note: Always leave this item last. Update if the actual last item
+    // changes.
+    kMaxValue = kSamePageSameQuality,
+  };
+
   ~RecentTabHelper() override;
 
   // content::WebContentsObserver
@@ -141,8 +158,9 @@
   std::unique_ptr<SnapshotProgressInfo> last_n_ongoing_snapshot_info_;
 
   // Snapshot information for the last successful snapshot requested by
-  // last_n. Null if no successful one has ever completed for the current page.
-  // It is cleared when the referenced snapshot is deleted.
+  // last_n for the currently loaded page. Null if no successful one has ever
+  // completed for the current page. It is cleared when the referenced snapshot
+  // is about to be deleted.
   std::unique_ptr<SnapshotProgressInfo> last_n_latest_saved_snapshot_info_;
 
   // If empty, the tab does not have AndroidId and can not capture pages.
diff --git a/chrome/browser/offline_pages/recent_tab_helper_unittest.cc b/chrome/browser/offline_pages/recent_tab_helper_unittest.cc
index b757219..535a496 100644
--- a/chrome/browser/offline_pages/recent_tab_helper_unittest.cc
+++ b/chrome/browser/offline_pages/recent_tab_helper_unittest.cc
@@ -8,6 +8,7 @@
 
 #include "base/strings/string16.h"
 #include "base/strings/string_number_conversions.h"
+#include "base/test/metrics/histogram_tester.h"
 #include "base/test/scoped_feature_list.h"
 #include "base/test/scoped_mock_time_message_loop_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
@@ -28,6 +29,7 @@
 namespace offline_pages {
 
 namespace {
+using IsSavingSamePageEnum = RecentTabHelper::IsSavingSamePageEnum;
 const GURL kTestPageUrl("http://mystery.site/foo.html");
 const GURL kTestPageUrlOther("http://crazy.site/foo_other.html");
 const int kTabId = 153;
@@ -111,6 +113,8 @@
 
   TestDelegate* default_test_delegate() { return default_test_delegate_; }
 
+  base::HistogramTester* histogram_tester() { return histogram_tester_.get(); }
+
   // Returns a OfflinePageItem pointer from |all_pages| that matches the
   // provided |offline_id|. If a match is not found returns nullptr.
   const OfflinePageItem* FindPageForOfflineId(int64_t offline_id) {
@@ -152,6 +156,7 @@
   size_t model_removed_count_;
   std::vector<OfflinePageItem> all_pages_;
   bool all_pages_needs_updating_;
+  std::unique_ptr<base::HistogramTester> histogram_tester_;
 
   // Mocks the RenderViewHostTestHarness' main thread runner. Needs to be delay
   // initialized in SetUp() -- can't be a simple member -- since
@@ -222,6 +227,8 @@
 
   model_ = OfflinePageModelFactory::GetForBrowserContext(browser_context());
   model_->AddObserver(this);
+
+  histogram_tester_ = std::make_unique<base::HistogramTester>();
 }
 
 void RecentTabHelperTest::TearDown() {
@@ -283,6 +290,9 @@
 TEST_F(RecentTabHelperTest, LastNCaptureAfterLoad) {
   // Navigate and finish loading. Nothing should be saved.
   NavigateAndCommit(kTestPageUrl);
+  histogram_tester()->ExpectUniqueSample("OfflinePages.CanSaveRecentPage", true,
+                                         1);
+
   recent_tab_helper()->DocumentOnLoadCompletedInMainFrame();
   // Move the snapshot controller's time forward so it gets past timeouts.
   FastForwardSnapshotController();
@@ -296,6 +306,8 @@
   ASSERT_EQ(1U, GetAllPages().size());
   EXPECT_EQ(kTestPageUrl, GetAllPages()[0].url);
   EXPECT_EQ(kLastNNamespace, GetAllPages()[0].client_id.name_space);
+  histogram_tester()->ExpectUniqueSample("OfflinePages.LastN.IsSavingSamePage",
+                                         IsSavingSamePageEnum::kNewPage, 1);
 }
 
 // Simulates the tab being hidden too early in the page loading so that a
@@ -303,6 +315,8 @@
 TEST_F(RecentTabHelperTest, NoLastNCaptureIfTabHiddenTooEarlyInPageLoad) {
   // Commit the navigation and hide the tab. Nothing should be saved.
   NavigateAndCommit(kTestPageUrl);
+  histogram_tester()->ExpectUniqueSample("OfflinePages.CanSaveRecentPage", true,
+                                         1);
   recent_tab_helper()->OnVisibilityChanged(content::Visibility::HIDDEN);
   RunUntilIdle();
   EXPECT_EQ(0U, page_added_count());
@@ -314,6 +328,8 @@
   FastForwardSnapshotController();
   EXPECT_EQ(0U, page_added_count());
   ASSERT_EQ(0U, GetAllPages().size());
+  histogram_tester()->ExpectTotalCount("OfflinePages.LastN.IsSavingSamePage",
+                                       0);
 }
 
 // Checks that WebContents with no tab IDs have snapshot requests properly
@@ -324,6 +340,7 @@
       std::make_unique<TestDelegate>(this, kTabId, false));
 
   NavigateAndCommit(kTestPageUrl);
+  histogram_tester()->ExpectTotalCount("OfflinePages.CanSaveRecentPage", 0);
   recent_tab_helper()->DocumentOnLoadCompletedInMainFrame();
   FastForwardSnapshotController();
   recent_tab_helper()->OnVisibilityChanged(content::Visibility::HIDDEN);
@@ -333,6 +350,8 @@
   // No page should be captured.
   EXPECT_EQ(0U, page_added_count());
   ASSERT_EQ(0U, GetAllPages().size());
+  histogram_tester()->ExpectTotalCount("OfflinePages.LastN.IsSavingSamePage",
+                                       0);
 }
 
 // Checks that last_n is disabled if the device is low-end (aka svelte) but that
@@ -343,6 +362,9 @@
 
   // Navigate and finish loading then hide the tab. Nothing should be saved.
   NavigateAndCommit(kTestPageUrl);
+  histogram_tester()->ExpectUniqueSample("OfflinePages.CanSaveRecentPage", true,
+                                         1);
+
   recent_tab_helper()->DocumentOnLoadCompletedInMainFrame();
   FastForwardSnapshotController();
   recent_tab_helper()->OnVisibilityChanged(content::Visibility::HIDDEN);
@@ -356,6 +378,8 @@
   RunUntilIdle();
   EXPECT_EQ(1U, page_added_count());
   ASSERT_EQ(1U, GetAllPages().size());
+  histogram_tester()->ExpectTotalCount("OfflinePages.LastN.IsSavingSamePage",
+                                       0);
 }
 
 // Checks that last_n will not save a snapshot while the tab is being presented
@@ -366,6 +390,8 @@
 
   // Navigate and finish loading then hide the tab. Nothing should be saved.
   NavigateAndCommit(kTestPageUrl);
+  histogram_tester()->ExpectUniqueSample("OfflinePages.CanSaveRecentPage", true,
+                                         1);
   recent_tab_helper()->DocumentOnLoadCompletedInMainFrame();
   FastForwardSnapshotController();
   recent_tab_helper()->OnVisibilityChanged(content::Visibility::HIDDEN);
@@ -379,6 +405,8 @@
   RunUntilIdle();
   EXPECT_EQ(1U, page_added_count());
   ASSERT_EQ(1U, GetAllPages().size());
+  histogram_tester()->ExpectTotalCount("OfflinePages.LastN.IsSavingSamePage",
+                                       0);
 
   // Simulates the tab being transfered from the CustomTabActivity back to a
   // ChromeActivity.
@@ -389,12 +417,16 @@
   RunUntilIdle();
   EXPECT_EQ(2U, page_added_count());
   ASSERT_EQ(2U, GetAllPages().size());
+  histogram_tester()->ExpectUniqueSample("OfflinePages.LastN.IsSavingSamePage",
+                                         IsSavingSamePageEnum::kNewPage, 1);
 }
 
 // Triggers two last_n snapshot captures during a single page load. Should end
 // up with one snapshot, the 1st being replaced by the 2nd.
 TEST_F(RecentTabHelperTest, TwoCapturesSamePageLoad) {
   NavigateAndCommit(kTestPageUrl);
+  histogram_tester()->ExpectUniqueSample("OfflinePages.CanSaveRecentPage", true,
+                                         1);
   // Set page loading state to the 1st snapshot-able stage. No capture so far.
   recent_tab_helper()->DocumentAvailableInMainFrame();
   FastForwardSnapshotController();
@@ -407,6 +439,8 @@
   EXPECT_EQ(0U, model_removed_count());
   ASSERT_EQ(1U, GetAllPages().size());
   EXPECT_EQ(kTestPageUrl, GetAllPages()[0].url);
+  histogram_tester()->ExpectUniqueSample("OfflinePages.LastN.IsSavingSamePage",
+                                         IsSavingSamePageEnum::kNewPage, 1);
   int64_t first_offline_id = GetAllPages()[0].offline_id;
 
   // Set page loading state to the 2nd and last snapshot-able stage. No new
@@ -426,6 +460,11 @@
   ASSERT_EQ(1U, GetAllPages().size());
   EXPECT_EQ(kTestPageUrl, GetAllPages()[0].url);
   EXPECT_NE(first_offline_id, GetAllPages()[0].offline_id);
+  histogram_tester()->ExpectTotalCount("OfflinePages.LastN.IsSavingSamePage",
+                                       2);
+  histogram_tester()->ExpectBucketCount(
+      "OfflinePages.LastN.IsSavingSamePage",
+      IsSavingSamePageEnum::kSamePageBetterQuality, 1);
 }
 
 // Triggers two last_n captures during a single page load, where the 2nd capture
@@ -470,6 +509,8 @@
 TEST_F(RecentTabHelperTest, TwoCapturesDifferentPageLoadsSameUrl) {
   // Fully load the page. Hide the tab and check for a snapshot.
   NavigateAndCommit(kTestPageUrl);
+  histogram_tester()->ExpectUniqueSample("OfflinePages.CanSaveRecentPage", true,
+                                         1);
   recent_tab_helper()->DocumentOnLoadCompletedInMainFrame();
   FastForwardSnapshotController();
   recent_tab_helper()->OnVisibilityChanged(content::Visibility::HIDDEN);
@@ -478,11 +519,15 @@
   EXPECT_EQ(0U, model_removed_count());
   ASSERT_EQ(1U, GetAllPages().size());
   EXPECT_EQ(kTestPageUrl, GetAllPages()[0].url);
+  histogram_tester()->ExpectUniqueSample("OfflinePages.LastN.IsSavingSamePage",
+                                         IsSavingSamePageEnum::kNewPage, 1);
   int64_t first_offline_id = GetAllPages()[0].offline_id;
 
   // Reload the same URL until the page is minimally loaded. The previous
   // snapshot should have been removed.
   NavigateAndCommitTyped(kTestPageUrl);
+  histogram_tester()->ExpectUniqueSample("OfflinePages.CanSaveRecentPage", true,
+                                         2);
   recent_tab_helper()->DocumentAvailableInMainFrame();
   FastForwardSnapshotController();
   EXPECT_EQ(1U, page_added_count());
@@ -497,6 +542,8 @@
   ASSERT_EQ(1U, GetAllPages().size());
   EXPECT_EQ(kTestPageUrl, GetAllPages()[0].url);
   EXPECT_NE(first_offline_id, GetAllPages()[0].offline_id);
+  histogram_tester()->ExpectUniqueSample("OfflinePages.LastN.IsSavingSamePage",
+                                         IsSavingSamePageEnum::kNewPage, 2);
 }
 
 // Triggers two last_n captures for two different page loads of the same URL
@@ -505,6 +552,8 @@
 TEST_F(RecentTabHelperTest, TwoCapturesWhere2ndFailsDifferentPageLoadsSameUrl) {
   // Fully load the page then hide the tab. A capture is expected.
   NavigateAndCommit(kTestPageUrl);
+  histogram_tester()->ExpectUniqueSample("OfflinePages.CanSaveRecentPage", true,
+                                         1);
   recent_tab_helper()->DocumentOnLoadCompletedInMainFrame();
   FastForwardSnapshotController();
   recent_tab_helper()->OnVisibilityChanged(content::Visibility::HIDDEN);
@@ -513,6 +562,8 @@
   EXPECT_EQ(0U, model_removed_count());
   ASSERT_EQ(1U, GetAllPages().size());
   EXPECT_EQ(kTestPageUrl, GetAllPages()[0].url);
+  histogram_tester()->ExpectUniqueSample("OfflinePages.LastN.IsSavingSamePage",
+                                         IsSavingSamePageEnum::kNewPage, 1);
 
   // Updates the delegate so that will make the second snapshot fail.
   default_test_delegate()->set_archive_size(-1);
@@ -523,6 +574,8 @@
   // Fully load the page once more then hide the tab again. A capture happens
   // and fails but no snapshot should remain.
   NavigateAndCommitTyped(kTestPageUrl);
+  histogram_tester()->ExpectUniqueSample("OfflinePages.CanSaveRecentPage", true,
+                                         2);
   recent_tab_helper()->DocumentOnLoadCompletedInMainFrame();
   FastForwardSnapshotController();
   recent_tab_helper()->OnVisibilityChanged(content::Visibility::HIDDEN);
@@ -530,6 +583,8 @@
   EXPECT_EQ(1U, page_added_count());
   EXPECT_EQ(1U, model_removed_count());
   ASSERT_EQ(0U, GetAllPages().size());
+  histogram_tester()->ExpectUniqueSample("OfflinePages.LastN.IsSavingSamePage",
+                                         IsSavingSamePageEnum::kNewPage, 2);
 }
 
 // Triggers two last_n captures for two different page loads of different URLs.
@@ -537,6 +592,9 @@
 TEST_F(RecentTabHelperTest, TwoCapturesDifferentPageLoadsDifferentUrls) {
   // Fully load the first URL then hide the tab and check for a snapshot.
   NavigateAndCommit(kTestPageUrl);
+  histogram_tester()->ExpectUniqueSample("OfflinePages.CanSaveRecentPage", true,
+                                         1);
+
   recent_tab_helper()->DocumentOnLoadCompletedInMainFrame();
   FastForwardSnapshotController();
   recent_tab_helper()->OnVisibilityChanged(content::Visibility::HIDDEN);
@@ -545,9 +603,14 @@
   EXPECT_EQ(0U, model_removed_count());
   ASSERT_EQ(1U, GetAllPages().size());
   EXPECT_EQ(kTestPageUrl, GetAllPages()[0].url);
+  histogram_tester()->ExpectUniqueSample("OfflinePages.LastN.IsSavingSamePage",
+                                         IsSavingSamePageEnum::kNewPage, 1);
 
   // Fully load the second URL. The previous snapshot should have been deleted.
   NavigateAndCommitTyped(kTestPageUrlOther);
+  histogram_tester()->ExpectUniqueSample("OfflinePages.CanSaveRecentPage", true,
+                                         2);
+
   recent_tab_helper()->DocumentOnLoadCompletedInMainFrame();
   FastForwardSnapshotController();
   EXPECT_EQ(1U, page_added_count());
@@ -561,6 +624,8 @@
   EXPECT_EQ(1U, model_removed_count());
   ASSERT_EQ(1U, GetAllPages().size());
   EXPECT_EQ(kTestPageUrlOther, GetAllPages()[0].url);
+  histogram_tester()->ExpectUniqueSample("OfflinePages.LastN.IsSavingSamePage",
+                                         IsSavingSamePageEnum::kNewPage, 2);
 }
 
 // Fully loads a page where last_n captures two snapshots. Then triggers two
@@ -571,6 +636,8 @@
   // Fully loads the page with intermediary steps where the tab is hidden. Then
   // check that two last_n snapshots were created but only one was kept.
   NavigateAndCommit(kTestPageUrl);
+  histogram_tester()->ExpectUniqueSample("OfflinePages.CanSaveRecentPage", true,
+                                         1);
   recent_tab_helper()->DocumentAvailableInMainFrame();
   FastForwardSnapshotController();
   recent_tab_helper()->OnVisibilityChanged(content::Visibility::HIDDEN);
@@ -583,6 +650,13 @@
   EXPECT_EQ(1U, model_removed_count());
   ASSERT_EQ(1U, GetAllPages().size());
   EXPECT_EQ(kTestPageUrl, GetAllPages()[0].url);
+  histogram_tester()->ExpectTotalCount("OfflinePages.LastN.IsSavingSamePage",
+                                       2);
+  histogram_tester()->ExpectBucketCount("OfflinePages.LastN.IsSavingSamePage",
+                                        IsSavingSamePageEnum::kNewPage, 1);
+  histogram_tester()->ExpectBucketCount(
+      "OfflinePages.LastN.IsSavingSamePage",
+      IsSavingSamePageEnum::kSamePageBetterQuality, 1);
   int64_t first_offline_id = GetAllPages()[0].offline_id;
 
   // First snapshot request by downloads. Two offline pages are expected.
@@ -615,6 +689,8 @@
   ASSERT_NE(nullptr, third_page);
   EXPECT_EQ(kTestPageUrl, third_page->url);
   EXPECT_EQ(third_client_id, third_page->client_id);
+  histogram_tester()->ExpectTotalCount("OfflinePages.LastN.IsSavingSamePage",
+                                       2);
 }
 
 // Simulates an error (disconnection) during the load of a page. Should end up
@@ -628,6 +704,10 @@
                                                      123L, "");
   RunUntilIdle();
   ASSERT_EQ(0U, GetAllPages().size());
+  histogram_tester()->ExpectUniqueSample("OfflinePages.CanSaveRecentPage",
+                                         false, 1);
+  histogram_tester()->ExpectTotalCount("OfflinePages.LastN.IsSavingSamePage",
+                                       0);
 }
 
 // Checks that last_n snapshots are not created if the feature is disabled.
@@ -636,6 +716,8 @@
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndDisableFeature(kOffliningRecentPagesFeature);
   NavigateAndCommit(kTestPageUrl);
+  histogram_tester()->ExpectUniqueSample("OfflinePages.CanSaveRecentPage", true,
+                                         1);
   recent_tab_helper()->DocumentOnLoadCompletedInMainFrame();
   FastForwardSnapshotController();
   recent_tab_helper()->OnVisibilityChanged(content::Visibility::HIDDEN);
@@ -648,6 +730,8 @@
   RunUntilIdle();
   // No page should be captured.
   ASSERT_EQ(1U, GetAllPages().size());
+  histogram_tester()->ExpectTotalCount("OfflinePages.LastN.IsSavingSamePage",
+                                       0);
 }
 
 // Simulates a download request to offline the current page made early during
@@ -656,6 +740,8 @@
   // Commit the navigation and request the snapshot from downloads. No captures
   // so far.
   NavigateAndCommit(kTestPageUrl);
+  histogram_tester()->ExpectUniqueSample("OfflinePages.CanSaveRecentPage", true,
+                                         1);
   const ClientId client_id = NewDownloadClientId();
   recent_tab_helper()->ObserveAndDownloadCurrentPage(client_id, 153L, "");
   FastForwardSnapshotController();
@@ -680,6 +766,8 @@
   EXPECT_EQ(kTestPageUrl, later_page.url);
   EXPECT_EQ(client_id, later_page.client_id);
   EXPECT_EQ(153L, later_page.offline_id);
+  histogram_tester()->ExpectTotalCount("OfflinePages.LastN.IsSavingSamePage",
+                                       0);
 }
 
 // Simulates a download request to offline the current page made when the page
@@ -687,6 +775,8 @@
 // kept.
 TEST_F(RecentTabHelperTest, DownloadRequestLaterInLoad) {
   NavigateAndCommit(kTestPageUrl);
+  histogram_tester()->ExpectUniqueSample("OfflinePages.CanSaveRecentPage", true,
+                                         1);
   recent_tab_helper()->DocumentAvailableInMainFrame();
   FastForwardSnapshotController();
   ASSERT_EQ(0U, GetAllPages().size());
@@ -705,12 +795,16 @@
   EXPECT_EQ(2U, page_added_count());
   EXPECT_EQ(1U, model_removed_count());
   ASSERT_EQ(1U, GetAllPages().size());
+  histogram_tester()->ExpectTotalCount("OfflinePages.LastN.IsSavingSamePage",
+                                       0);
 }
 
 // Simulates a download request to offline the current page made after loading
 // is completed. Should end up with one offline page.
 TEST_F(RecentTabHelperTest, DownloadRequestAfterFullyLoad) {
   NavigateAndCommit(kTestPageUrl);
+  histogram_tester()->ExpectUniqueSample("OfflinePages.CanSaveRecentPage", true,
+                                         1);
   recent_tab_helper()->DocumentOnLoadCompletedInMainFrame();
   FastForwardSnapshotController();
   ASSERT_EQ(0U, GetAllPages().size());
@@ -724,12 +818,16 @@
   EXPECT_EQ(client_id, page.client_id);
   EXPECT_EQ(153L, page.offline_id);
   EXPECT_EQ("", page.request_origin);
+  histogram_tester()->ExpectTotalCount("OfflinePages.LastN.IsSavingSamePage",
+                                       0);
 }
 
 // Simulates a download request to offline the current page made after loading
 // is completed. Should end up with one offline page.
 TEST_F(RecentTabHelperTest, DownloadRequestAfterFullyLoadWithOrigin) {
   NavigateAndCommit(kTestPageUrl);
+  histogram_tester()->ExpectUniqueSample("OfflinePages.CanSaveRecentPage", true,
+                                         1);
   recent_tab_helper()->DocumentOnLoadCompletedInMainFrame();
   FastForwardSnapshotController();
   ASSERT_EQ(0U, GetAllPages().size());
@@ -743,12 +841,16 @@
   EXPECT_EQ(client_id, page.client_id);
   EXPECT_EQ(153L, page.offline_id);
   EXPECT_EQ("abc", page.request_origin);
+  histogram_tester()->ExpectTotalCount("OfflinePages.LastN.IsSavingSamePage",
+                                       0);
 }
 
 // Simulates requests coming from last_n and downloads at the same time for a
 // fully loaded page.
 TEST_F(RecentTabHelperTest, SimultaneousCapturesFromLastNAndDownloads) {
   NavigateAndCommit(kTestPageUrl);
+  histogram_tester()->ExpectUniqueSample("OfflinePages.CanSaveRecentPage", true,
+                                         1);
   recent_tab_helper()->DocumentOnLoadCompletedInMainFrame();
   FastForwardSnapshotController();
   recent_tab_helper()->OnVisibilityChanged(content::Visibility::HIDDEN);
@@ -758,6 +860,8 @@
                                                      download_offline_id, "");
   RunUntilIdle();
   ASSERT_EQ(2U, GetAllPages().size());
+  histogram_tester()->ExpectUniqueSample("OfflinePages.LastN.IsSavingSamePage",
+                                         IsSavingSamePageEnum::kNewPage, 1);
 
   const OfflinePageItem* downloads_page =
       FindPageForOfflineId(download_offline_id);
@@ -778,6 +882,8 @@
 // signals are poor signals for those).
 TEST_F(RecentTabHelperTest, DuplicateTabHiddenEventsShouldTriggerNewSnapshots) {
   NavigateAndCommit(kTestPageUrl);
+  histogram_tester()->ExpectUniqueSample("OfflinePages.CanSaveRecentPage", true,
+                                         1);
   recent_tab_helper()->DocumentAvailableInMainFrame();
   FastForwardSnapshotController();
   recent_tab_helper()->OnVisibilityChanged(content::Visibility::HIDDEN);
@@ -785,12 +891,19 @@
   EXPECT_EQ(1U, page_added_count());
   EXPECT_EQ(0U, model_removed_count());
   ASSERT_EQ(1U, GetAllPages().size());
+  histogram_tester()->ExpectUniqueSample("OfflinePages.LastN.IsSavingSamePage",
+                                         IsSavingSamePageEnum::kNewPage, 1);
 
   recent_tab_helper()->OnVisibilityChanged(content::Visibility::HIDDEN);
   RunUntilIdle();
   EXPECT_EQ(2U, page_added_count());
   EXPECT_EQ(1U, model_removed_count());
   ASSERT_EQ(1U, GetAllPages().size());
+  histogram_tester()->ExpectTotalCount("OfflinePages.LastN.IsSavingSamePage",
+                                       2);
+  histogram_tester()->ExpectBucketCount(
+      "OfflinePages.LastN.IsSavingSamePage",
+      IsSavingSamePageEnum::kSamePageSameQuality, 1);
 
   recent_tab_helper()->DocumentOnLoadCompletedInMainFrame();
   FastForwardSnapshotController();
@@ -799,12 +912,22 @@
   EXPECT_EQ(3U, page_added_count());
   EXPECT_EQ(2U, model_removed_count());
   ASSERT_EQ(1U, GetAllPages().size());
+  histogram_tester()->ExpectTotalCount("OfflinePages.LastN.IsSavingSamePage",
+                                       3);
+  histogram_tester()->ExpectBucketCount(
+      "OfflinePages.LastN.IsSavingSamePage",
+      IsSavingSamePageEnum::kSamePageBetterQuality, 1);
 
   recent_tab_helper()->OnVisibilityChanged(content::Visibility::HIDDEN);
   RunUntilIdle();
   EXPECT_EQ(4U, page_added_count());
   EXPECT_EQ(3U, model_removed_count());
   ASSERT_EQ(1U, GetAllPages().size());
+  histogram_tester()->ExpectTotalCount("OfflinePages.LastN.IsSavingSamePage",
+                                       4);
+  histogram_tester()->ExpectBucketCount(
+      "OfflinePages.LastN.IsSavingSamePage",
+      IsSavingSamePageEnum::kSamePageSameQuality, 2);
 }
 
 // Simulates multiple download requests and verifies that overlapping requests
@@ -812,6 +935,8 @@
 TEST_F(RecentTabHelperTest, OverlappingDownloadRequestsAreIgnored) {
   // Navigates and commits then make two download snapshot requests.
   NavigateAndCommit(kTestPageUrl);
+  histogram_tester()->ExpectUniqueSample("OfflinePages.CanSaveRecentPage", true,
+                                         1);
   const ClientId client_id_1 = NewDownloadClientId();
   const int64_t offline_id_1 = 153L;
   recent_tab_helper()->ObserveAndDownloadCurrentPage(client_id_1, offline_id_1,
@@ -845,6 +970,8 @@
   ASSERT_TRUE(second_page);
   EXPECT_EQ(client_id_3, second_page->client_id);
   EXPECT_EQ(offline_id_3, second_page->offline_id);
+  histogram_tester()->ExpectTotalCount("OfflinePages.LastN.IsSavingSamePage",
+                                       0);
 }
 
 // Simulates a same document navigation and checks we snapshot correctly with
@@ -852,6 +979,8 @@
 TEST_F(RecentTabHelperTest, SaveSameDocumentNavigationSnapshots) {
   // Navigates and load fully then hide the tab so that a snapshot is created.
   NavigateAndCommit(kTestPageUrl);
+  histogram_tester()->ExpectUniqueSample("OfflinePages.CanSaveRecentPage", true,
+                                         1);
   recent_tab_helper()->DocumentOnLoadCompletedInMainFrame();
   FastForwardSnapshotController();
   recent_tab_helper()->OnVisibilityChanged(content::Visibility::HIDDEN);
@@ -859,17 +988,26 @@
   EXPECT_EQ(1U, page_added_count());
   EXPECT_EQ(0U, model_removed_count());
   ASSERT_EQ(1U, GetAllPages().size());
+  histogram_tester()->ExpectUniqueSample("OfflinePages.LastN.IsSavingSamePage",
+                                         IsSavingSamePageEnum::kNewPage, 1);
 
   // Now navigates same page and check the results of hiding the tab again.
   // Another snapshot should be created to the updated URL.
   const GURL kTestPageUrlWithFragment(kTestPageUrl.spec() + "#aaa");
   NavigateAndCommit(kTestPageUrlWithFragment);
+  histogram_tester()->ExpectUniqueSample("OfflinePages.CanSaveRecentPage", true,
+                                         1);
   recent_tab_helper()->OnVisibilityChanged(content::Visibility::HIDDEN);
   RunUntilIdle();
   EXPECT_EQ(2U, page_added_count());
   EXPECT_EQ(1U, model_removed_count());
   ASSERT_EQ(1U, GetAllPages().size());
   EXPECT_EQ(kTestPageUrlWithFragment, GetAllPages()[0].url);
+  histogram_tester()->ExpectTotalCount("OfflinePages.LastN.IsSavingSamePage",
+                                       2);
+  histogram_tester()->ExpectBucketCount(
+      "OfflinePages.LastN.IsSavingSamePage",
+      IsSavingSamePageEnum::kSamePageSameQuality, 1);
 
   // Now create a download request and check the snapshot is properly created.
   const ClientId client_id = NewDownloadClientId();
@@ -883,6 +1021,8 @@
   EXPECT_EQ(kTestPageUrlWithFragment, downloads_page->url);
   EXPECT_EQ(client_id, downloads_page->client_id);
   EXPECT_EQ(offline_id, downloads_page->offline_id);
+  histogram_tester()->ExpectTotalCount("OfflinePages.LastN.IsSavingSamePage",
+                                       2);
 }
 
 // Tests that a page reloaded is tracked as an actual load and properly saved.
@@ -894,6 +1034,8 @@
   recent_tab_helper()->OnVisibilityChanged(content::Visibility::HIDDEN);
   RunUntilIdle();
   ASSERT_EQ(1U, GetAllPages().size());
+  histogram_tester()->ExpectUniqueSample("OfflinePages.LastN.IsSavingSamePage",
+                                         IsSavingSamePageEnum::kNewPage, 1);
 
   // Starts a reload and hides the tab before it minimally load. The previous
   // snapshot should be removed.
@@ -912,6 +1054,8 @@
   EXPECT_EQ(2U, page_added_count());
   EXPECT_EQ(1U, model_removed_count());
   ASSERT_EQ(1U, GetAllPages().size());
+  histogram_tester()->ExpectUniqueSample("OfflinePages.LastN.IsSavingSamePage",
+                                         IsSavingSamePageEnum::kNewPage, 2);
 }
 
 // Checks that a closing tab doesn't trigger the creation of a snapshot. And
@@ -930,6 +1074,8 @@
   EXPECT_EQ(0U, page_added_count());
   EXPECT_EQ(0U, model_removed_count());
   ASSERT_EQ(0U, GetAllPages().size());
+  histogram_tester()->ExpectTotalCount("OfflinePages.LastN.IsSavingSamePage",
+                                       0);
 
   // Simulates the page being restored and shown again, then hidden. At this
   // moment a snapshot should be created.
@@ -939,6 +1085,8 @@
   EXPECT_EQ(1U, page_added_count());
   EXPECT_EQ(0U, model_removed_count());
   ASSERT_EQ(1U, GetAllPages().size());
+  histogram_tester()->ExpectUniqueSample("OfflinePages.LastN.IsSavingSamePage",
+                                         IsSavingSamePageEnum::kNewPage, 1);
 }
 
 }  // namespace offline_pages
diff --git a/chrome/browser/policy/chrome_browser_policy_connector.cc b/chrome/browser/policy/chrome_browser_policy_connector.cc
index 598f5fe..fd4d95a 100644
--- a/chrome/browser/policy/chrome_browser_policy_connector.cc
+++ b/chrome/browser/policy/chrome_browser_policy_connector.cc
@@ -28,6 +28,7 @@
 #include "components/policy/core/common/policy_types.h"
 #include "components/policy/policy_constants.h"
 #include "net/url_request/url_request_context_getter.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
 
 #if defined(OS_WIN)
 #include "base/win/registry.h"
@@ -67,7 +68,8 @@
 
 void ChromeBrowserPolicyConnector::Init(
     PrefService* local_state,
-    scoped_refptr<net::URLRequestContextGetter> request_context) {
+    scoped_refptr<net::URLRequestContextGetter> request_context,
+    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) {
   std::unique_ptr<DeviceManagementService::Configuration> configuration(
       new DeviceManagementServiceConfiguration(
           BrowserPolicyConnector::GetDeviceManagementUrl()));
@@ -79,8 +81,8 @@
   InitInternal(local_state, std::move(device_management_service));
 
 #if !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
-  machine_level_user_cloud_policy_controller_->Init(local_state,
-                                                    request_context);
+  machine_level_user_cloud_policy_controller_->Init(
+      local_state, request_context, url_loader_factory);
 #endif
 }
 
diff --git a/chrome/browser/policy/chrome_browser_policy_connector.h b/chrome/browser/policy/chrome_browser_policy_connector.h
index c22580b..36af5691 100644
--- a/chrome/browser/policy/chrome_browser_policy_connector.h
+++ b/chrome/browser/policy/chrome_browser_policy_connector.h
@@ -17,10 +17,6 @@
 
 class PrefService;
 
-namespace net {
-class URLRequestContextGetter;
-}
-
 namespace policy {
 class ConfigurationPolicyProvider;
 
@@ -47,9 +43,10 @@
   // class to notify observers.
   void OnResourceBundleCreated();
 
-  void Init(
-      PrefService* local_state,
-      scoped_refptr<net::URLRequestContextGetter> request_context) override;
+  void Init(PrefService* local_state,
+            scoped_refptr<net::URLRequestContextGetter> request_context,
+            scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory)
+      override;
 
   bool IsEnterpriseManaged() const override;
 
diff --git a/chrome/browser/policy/cloud/cloud_policy_browsertest.cc b/chrome/browser/policy/cloud/cloud_policy_browsertest.cc
index 42c93d7..684f4000 100644
--- a/chrome/browser/policy/cloud/cloud_policy_browsertest.cc
+++ b/chrome/browser/policy/cloud/cloud_policy_browsertest.cc
@@ -64,6 +64,7 @@
 #include "components/account_id/account_id.h"
 #include "components/user_manager/user_names.h"
 #else
+#include "chrome/browser/net/system_network_context_manager.h"
 #include "chrome/browser/policy/cloud/user_cloud_policy_manager_factory.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
 #include "components/policy/core/common/cloud/user_cloud_policy_manager.h"
@@ -223,11 +224,14 @@
         UserCloudPolicyManagerFactory::GetForBrowserContext(
             browser()->profile());
     ASSERT_TRUE(policy_manager);
-    policy_manager->Connect(g_browser_process->local_state(),
-                            g_browser_process->system_request_context(),
-                            UserCloudPolicyManager::CreateCloudPolicyClient(
-                                connector->device_management_service(),
-                                g_browser_process->system_request_context()));
+    policy_manager->Connect(
+        g_browser_process->local_state(),
+        g_browser_process->system_request_context(),
+        UserCloudPolicyManager::CreateCloudPolicyClient(
+            connector->device_management_service(),
+            g_browser_process->system_request_context(),
+            g_browser_process->system_network_context_manager()
+                ->GetSharedURLLoaderFactory()));
 #endif  // defined(OS_CHROMEOS)
 
     ASSERT_TRUE(policy_manager->core()->client());
diff --git a/chrome/browser/policy/cloud/cloud_policy_manager_browsertest.cc b/chrome/browser/policy/cloud/cloud_policy_manager_browsertest.cc
index c8aca52..e73aa4e 100644
--- a/chrome/browser/policy/cloud/cloud_policy_manager_browsertest.cc
+++ b/chrome/browser/policy/cloud/cloud_policy_manager_browsertest.cc
@@ -30,6 +30,7 @@
 #include "chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.h"
 #include "chrome/browser/chromeos/policy/user_policy_manager_factory_chromeos.h"
 #else
+#include "chrome/browser/net/system_network_context_manager.h"
 #include "chrome/browser/policy/cloud/user_cloud_policy_manager_factory.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
 #include "components/policy/core/common/cloud/user_cloud_policy_manager.h"
@@ -82,11 +83,14 @@
     signin_manager->SetAuthenticatedAccountInfo("12345", "user@example.com");
 
     ASSERT_TRUE(policy_manager());
-    policy_manager()->Connect(g_browser_process->local_state(),
-                              g_browser_process->system_request_context(),
-                              UserCloudPolicyManager::CreateCloudPolicyClient(
-                                  connector->device_management_service(),
-                                  g_browser_process->system_request_context()));
+    policy_manager()->Connect(
+        g_browser_process->local_state(),
+        g_browser_process->system_request_context(),
+        UserCloudPolicyManager::CreateCloudPolicyClient(
+            connector->device_management_service(),
+            g_browser_process->system_request_context(),
+            g_browser_process->system_network_context_manager()
+                ->GetSharedURLLoaderFactory()));
 #endif
   }
 
diff --git a/chrome/browser/policy/cloud/component_cloud_policy_browsertest.cc b/chrome/browser/policy/cloud/component_cloud_policy_browsertest.cc
index 0bf1325..b0c9e55d 100644
--- a/chrome/browser/policy/cloud/component_cloud_policy_browsertest.cc
+++ b/chrome/browser/policy/cloud/component_cloud_policy_browsertest.cc
@@ -43,6 +43,7 @@
 #include "chrome/browser/chromeos/policy/user_policy_manager_factory_chromeos.h"
 #include "chromeos/chromeos_switches.h"
 #else
+#include "chrome/browser/net/system_network_context_manager.h"
 #include "chrome/browser/policy/cloud/user_cloud_policy_manager_factory.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
 #include "components/policy/core/common/cloud/user_cloud_policy_manager.h"
@@ -193,11 +194,15 @@
     ASSERT_TRUE(policy_manager);
     policy_manager->SetSigninAccountId(
         PolicyBuilder::GetFakeAccountIdForTesting());
-    policy_manager->Connect(g_browser_process->local_state(),
-                            g_browser_process->system_request_context(),
-                            UserCloudPolicyManager::CreateCloudPolicyClient(
-                                connector->device_management_service(),
-                                g_browser_process->system_request_context()));
+    policy_manager->Connect(
+        g_browser_process->local_state(),
+        g_browser_process->system_request_context(),
+        UserCloudPolicyManager::CreateCloudPolicyClient(
+            connector->device_management_service(),
+            g_browser_process->system_request_context(),
+            g_browser_process->system_network_context_manager()
+                ->GetSharedURLLoaderFactory()));
+
 #endif  // defined(OS_CHROMEOS)
 
     // Register the cloud policy client.
diff --git a/chrome/browser/policy/cloud/machine_level_user_cloud_policy_helper.cc b/chrome/browser/policy/cloud/machine_level_user_cloud_policy_helper.cc
index 4185962..65caeca 100644
--- a/chrome/browser/policy/cloud/machine_level_user_cloud_policy_helper.cc
+++ b/chrome/browser/policy/cloud/machine_level_user_cloud_policy_helper.cc
@@ -20,6 +20,7 @@
 #include "components/policy/core/common/cloud/machine_level_user_cloud_policy_store.h"
 #include "components/prefs/pref_service.h"
 #include "net/url_request/url_request_context_getter.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
 
 namespace policy {
 
@@ -34,9 +35,11 @@
 /* MachineLevelUserCloudPolicyRegistrar */
 MachineLevelUserCloudPolicyRegistrar::MachineLevelUserCloudPolicyRegistrar(
     DeviceManagementService* device_management_service,
-    scoped_refptr<net::URLRequestContextGetter> system_request_context)
+    scoped_refptr<net::URLRequestContextGetter> system_request_context,
+    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory)
     : device_management_service_(device_management_service),
-      system_request_context_(system_request_context) {}
+      system_request_context_(system_request_context),
+      url_loader_factory_(url_loader_factory) {}
 
 MachineLevelUserCloudPolicyRegistrar::~MachineLevelUserCloudPolicyRegistrar() {}
 
@@ -59,7 +62,7 @@
       std::make_unique<CloudPolicyClient>(
           std::string() /* machine_id */, std::string() /* machine_model */,
           std::string() /* brand_code */, device_management_service_,
-          system_request_context_, nullptr,
+          system_request_context_, url_loader_factory_, nullptr,
           CloudPolicyClient::DeviceDMTokenCallback());
 
   // Fire off the registration process. Callback keeps the CloudPolicyClient
@@ -88,16 +91,18 @@
     MachineLevelUserCloudPolicyManager* policy_manager,
     PrefService* local_state,
     DeviceManagementService* device_management_service,
-    scoped_refptr<net::URLRequestContextGetter> system_request_context)
+    scoped_refptr<net::URLRequestContextGetter> system_request_context,
+    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory)
     : policy_manager_(policy_manager),
       local_state_(local_state),
       device_management_service_(device_management_service),
-      system_request_context_(system_request_context) {
+      system_request_context_(system_request_context),
+      url_loader_factory_(url_loader_factory) {
   std::unique_ptr<CloudPolicyClient> client =
       std::make_unique<CloudPolicyClient>(
           std::string() /* machine_id */, std::string() /* machine_model */,
           std::string() /* brand_code */, device_management_service_,
-          system_request_context_, nullptr,
+          system_request_context_, url_loader_factory, nullptr,
           CloudPolicyClient::DeviceDMTokenCallback());
   InitializeManager(std::move(client));
 }
diff --git a/chrome/browser/policy/cloud/machine_level_user_cloud_policy_helper.h b/chrome/browser/policy/cloud/machine_level_user_cloud_policy_helper.h
index 4723c30..685f2a9 100644
--- a/chrome/browser/policy/cloud/machine_level_user_cloud_policy_helper.h
+++ b/chrome/browser/policy/cloud/machine_level_user_cloud_policy_helper.h
@@ -17,6 +17,10 @@
 
 class PrefService;
 
+namespace network {
+class SharedURLLoaderFactory;
+}
+
 namespace policy {
 
 class CloudPolicyClient;
@@ -29,7 +33,8 @@
  public:
   MachineLevelUserCloudPolicyRegistrar(
       DeviceManagementService* device_management_service,
-      scoped_refptr<net::URLRequestContextGetter> system_request_context);
+      scoped_refptr<net::URLRequestContextGetter> system_request_context,
+      scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory);
   ~MachineLevelUserCloudPolicyRegistrar();
 
   // The callback invoked once policy registration is complete. Passed
@@ -53,6 +58,7 @@
   std::unique_ptr<CloudPolicyClientRegistrationHelper> registration_helper_;
   DeviceManagementService* device_management_service_;
   scoped_refptr<net::URLRequestContextGetter> system_request_context_;
+  scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(MachineLevelUserCloudPolicyRegistrar);
 };
@@ -64,7 +70,8 @@
       MachineLevelUserCloudPolicyManager* policy_manager,
       PrefService* local_state,
       DeviceManagementService* device_management_service,
-      scoped_refptr<net::URLRequestContextGetter> system_request_context);
+      scoped_refptr<net::URLRequestContextGetter> system_request_context,
+      scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory);
   ~MachineLevelUserCloudPolicyFetcher() override;
 
   // Initialize the cloud policy client and policy store then fetch
@@ -84,6 +91,7 @@
   PrefService* local_state_;
   DeviceManagementService* device_management_service_;
   scoped_refptr<net::URLRequestContextGetter> system_request_context_;
+  scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(MachineLevelUserCloudPolicyFetcher);
 };
diff --git a/chrome/browser/policy/cloud/user_policy_signin_service.cc b/chrome/browser/policy/cloud/user_policy_signin_service.cc
index 3633e08..aaaebeb 100644
--- a/chrome/browser/policy/cloud/user_policy_signin_service.cc
+++ b/chrome/browser/policy/cloud/user_policy_signin_service.cc
@@ -21,8 +21,10 @@
 #include "components/signin/core/browser/signin_manager.h"
 #include "content/public/browser/notification_details.h"
 #include "content/public/browser/notification_source.h"
+#include "content/public/browser/storage_partition.h"
 #include "google_apis/gaia/gaia_constants.h"
 #include "net/url_request/url_request_context_getter.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
 
 namespace policy {
 
@@ -33,13 +35,15 @@
     UserCloudPolicyManager* policy_manager,
     SigninManager* signin_manager,
     scoped_refptr<net::URLRequestContextGetter> system_request_context,
+    scoped_refptr<network::SharedURLLoaderFactory> system_url_loader_factory,
     ProfileOAuth2TokenService* token_service)
     : UserPolicySigninServiceBase(profile,
                                   local_state,
                                   device_management_service,
                                   policy_manager,
                                   signin_manager,
-                                  system_request_context),
+                                  system_request_context,
+                                  system_url_loader_factory),
       profile_(profile),
       oauth2_token_service_(token_service) {
   // ProfileOAuth2TokenService should not yet have loaded its tokens since this
@@ -173,7 +177,9 @@
 
   InitializeForSignedInUser(
       signin_manager()->GetAuthenticatedAccountInfo().GetAccountId(),
-      profile_->GetRequestContext());
+      profile_->GetRequestContext(),
+      content::BrowserContext::GetDefaultStoragePartition(profile_)
+          ->GetURLLoaderFactoryForBrowserProcess());
 }
 
 void UserPolicySigninService::InitializeUserCloudPolicyManager(
diff --git a/chrome/browser/policy/cloud/user_policy_signin_service.h b/chrome/browser/policy/cloud/user_policy_signin_service.h
index 239852af..50b93f8 100644
--- a/chrome/browser/policy/cloud/user_policy_signin_service.h
+++ b/chrome/browser/policy/cloud/user_policy_signin_service.h
@@ -21,6 +21,9 @@
 namespace net {
 class URLRequestContextGetter;
 }
+namespace network {
+class SharedURLLoaderFactory;
+}
 
 namespace policy {
 
@@ -40,6 +43,7 @@
       UserCloudPolicyManager* policy_manager,
       SigninManager* signin_manager,
       scoped_refptr<net::URLRequestContextGetter> system_request_context,
+      scoped_refptr<network::SharedURLLoaderFactory> system_url_loader_factory,
       ProfileOAuth2TokenService* oauth2_token_service);
   ~UserPolicySigninService() override;
 
diff --git a/chrome/browser/policy/cloud/user_policy_signin_service_base.cc b/chrome/browser/policy/cloud/user_policy_signin_service_base.cc
index b974f67..1c3aaac 100644
--- a/chrome/browser/policy/cloud/user_policy_signin_service_base.cc
+++ b/chrome/browser/policy/cloud/user_policy_signin_service_base.cc
@@ -22,7 +22,9 @@
 #include "components/policy/core/common/cloud/user_cloud_policy_manager.h"
 #include "components/signin/core/browser/signin_manager.h"
 #include "content/public/browser/notification_source.h"
+#include "content/public/browser/storage_partition.h"
 #include "net/url_request/url_request_context_getter.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
 
 namespace policy {
 
@@ -32,12 +34,14 @@
     DeviceManagementService* device_management_service,
     UserCloudPolicyManager* policy_manager,
     SigninManager* signin_manager,
-    scoped_refptr<net::URLRequestContextGetter> system_request_context)
+    scoped_refptr<net::URLRequestContextGetter> system_request_context,
+    scoped_refptr<network::SharedURLLoaderFactory> system_url_loader_factory)
     : policy_manager_(policy_manager),
       signin_manager_(signin_manager),
       local_state_(local_state),
       device_management_service_(device_management_service),
       system_request_context_(system_request_context),
+      system_url_loader_factory_(system_url_loader_factory),
       weak_factory_(this) {
   // Register a listener to be called back once the current profile has finished
   // initializing, so we can startup/shutdown the UserCloudPolicyManager.
@@ -53,10 +57,12 @@
     const std::string& dm_token,
     const std::string& client_id,
     scoped_refptr<net::URLRequestContextGetter> profile_request_context,
+    scoped_refptr<network::SharedURLLoaderFactory> profile_url_loader_factory,
     const PolicyFetchCallback& callback) {
   std::unique_ptr<CloudPolicyClient> client =
       UserCloudPolicyManager::CreateCloudPolicyClient(
-          device_management_service_, profile_request_context);
+          device_management_service_, profile_request_context,
+          profile_url_loader_factory);
   client->SetupRegistration(
       dm_token, client_id,
       std::vector<std::string>() /* user_affiliation_ids */);
@@ -164,7 +170,8 @@
 
   // Create a new CloudPolicyClient for fetching the DMToken.
   return UserCloudPolicyManager::CreateCloudPolicyClient(
-      device_management_service_, system_request_context_);
+      device_management_service_, system_request_context_,
+      system_url_loader_factory_);
 }
 
 bool UserPolicySigninServiceBase::ShouldLoadPolicyForUser(
@@ -194,12 +201,16 @@
   if (!account_id.is_valid())
     ShutdownUserCloudPolicyManager();
   else
-    InitializeForSignedInUser(account_id, profile->GetRequestContext());
+    InitializeForSignedInUser(
+        account_id, profile->GetRequestContext(),
+        content::BrowserContext::GetDefaultStoragePartition(profile)
+            ->GetURLLoaderFactoryForBrowserProcess());
 }
 
 void UserPolicySigninServiceBase::InitializeForSignedInUser(
     const AccountId& account_id,
-    scoped_refptr<net::URLRequestContextGetter> profile_request_context) {
+    scoped_refptr<net::URLRequestContextGetter> profile_request_context,
+    scoped_refptr<network::SharedURLLoaderFactory> profile_url_loader_factory) {
   DCHECK(account_id.is_valid());
   if (!ShouldLoadPolicyForUser(account_id.GetUserEmail())) {
     DVLOG(1) << "Policy load not enabled for user: "
@@ -215,7 +226,8 @@
     // initiate a policy fetch.
     InitializeUserCloudPolicyManager(
         account_id, UserCloudPolicyManager::CreateCloudPolicyClient(
-                        device_management_service_, profile_request_context));
+                        device_management_service_, profile_request_context,
+                        profile_url_loader_factory));
   } else {
     manager->SetSigninAccountId(account_id);
   }
diff --git a/chrome/browser/policy/cloud/user_policy_signin_service_base.h b/chrome/browser/policy/cloud/user_policy_signin_service_base.h
index 48a5a82..8bb5c8dede 100644
--- a/chrome/browser/policy/cloud/user_policy_signin_service_base.h
+++ b/chrome/browser/policy/cloud/user_policy_signin_service_base.h
@@ -27,6 +27,9 @@
 namespace net {
 class URLRequestContextGetter;
 }
+namespace network {
+class SharedURLLoaderFactory;
+}
 
 namespace policy {
 
@@ -69,7 +72,8 @@
       DeviceManagementService* device_management_service,
       UserCloudPolicyManager* policy_manager,
       SigninManager* signin_manager,
-      scoped_refptr<net::URLRequestContextGetter> system_request_context);
+      scoped_refptr<net::URLRequestContextGetter> system_request_context,
+      scoped_refptr<network::SharedURLLoaderFactory> system_url_loader_factory);
   ~UserPolicySigninServiceBase() override;
 
   // Initiates a policy fetch as part of user signin, using a |dm_token| and
@@ -82,6 +86,7 @@
       const std::string& dm_token,
       const std::string& client_id,
       scoped_refptr<net::URLRequestContextGetter> profile_request_context,
+      scoped_refptr<network::SharedURLLoaderFactory> profile_url_loader_factory,
       const PolicyFetchCallback& callback);
 
   // SigninManagerBase::Observer implementation:
@@ -135,7 +140,9 @@
   // user signs-in and an OAuth2 login refresh token becomes available.
   void InitializeForSignedInUser(
       const AccountId& account_id,
-      scoped_refptr<net::URLRequestContextGetter> profile_request_context);
+      scoped_refptr<net::URLRequestContextGetter> profile_request_context,
+      scoped_refptr<network::SharedURLLoaderFactory>
+          profile_url_loader_factory);
 
   // Initializes the cloud policy manager with the passed |client|. This is
   // called from InitializeForSignedInUser() when the Profile already has a
@@ -171,6 +178,7 @@
   PrefService* local_state_;
   DeviceManagementService* device_management_service_;
   scoped_refptr<net::URLRequestContextGetter> system_request_context_;
+  scoped_refptr<network::SharedURLLoaderFactory> system_url_loader_factory_;
 
   base::WeakPtrFactory<UserPolicySigninServiceBase> weak_factory_;
 
diff --git a/chrome/browser/policy/cloud/user_policy_signin_service_factory.cc b/chrome/browser/policy/cloud/user_policy_signin_service_factory.cc
index 46469e4a..79749e7 100644
--- a/chrome/browser/policy/cloud/user_policy_signin_service_factory.cc
+++ b/chrome/browser/policy/cloud/user_policy_signin_service_factory.cc
@@ -7,6 +7,7 @@
 #include "base/memory/ref_counted.h"
 #include "build/build_config.h"
 #include "chrome/browser/browser_process.h"
+#include "chrome/browser/net/system_network_context_manager.h"
 #include "chrome/browser/policy/chrome_browser_policy_connector.h"
 #include "chrome/browser/policy/cloud/user_cloud_policy_manager_factory.h"
 #include "chrome/browser/profiles/profile.h"
@@ -18,6 +19,7 @@
 #include "components/pref_registry/pref_registry_syncable.h"
 #include "components/prefs/pref_service.h"
 #include "net/url_request/url_request_context_getter.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
 
 #if defined(OS_ANDROID)
 #include "chrome/browser/policy/cloud/user_policy_signin_service_mobile.h"
@@ -34,6 +36,11 @@
 
 }  // namespace
 
+// static
+base::LazyInstance<scoped_refptr<network::SharedURLLoaderFactory>>::Leaky
+    UserPolicySigninServiceFactory::system_url_loader_factory_for_tests_ =
+        LAZY_INSTANCE_INITIALIZER;
+
 UserPolicySigninServiceFactory::UserPolicySigninServiceFactory()
     : BrowserContextKeyedServiceFactory(
         "UserPolicySigninService",
@@ -63,6 +70,12 @@
   g_device_management_service = device_management_service;
 }
 
+// static
+void UserPolicySigninServiceFactory::SetSystemURLLoaderFactoryForTesting(
+    scoped_refptr<network::SharedURLLoaderFactory> system_url_loader_factory) {
+  system_url_loader_factory_for_tests_.Get() = system_url_loader_factory;
+}
+
 KeyedService* UserPolicySigninServiceFactory::BuildServiceInstanceFor(
     content::BrowserContext* context) const {
   Profile* profile = static_cast<Profile*>(context);
@@ -71,13 +84,21 @@
   DeviceManagementService* device_management_service =
       g_device_management_service ? g_device_management_service
                                   : connector->device_management_service();
+
+  scoped_refptr<network::SharedURLLoaderFactory> system_url_loader_factory =
+      system_url_loader_factory_for_tests_.Get();
+  if (!system_url_loader_factory &&
+      g_browser_process->system_network_context_manager()) {
+    system_url_loader_factory =
+        g_browser_process->system_network_context_manager()
+            ->GetSharedURLLoaderFactory();
+  }
+
   UserPolicySigninService* service = new UserPolicySigninService(
-      profile,
-      g_browser_process->local_state(),
-      device_management_service,
+      profile, g_browser_process->local_state(), device_management_service,
       UserCloudPolicyManagerFactory::GetForBrowserContext(context),
       SigninManagerFactory::GetForProfile(profile),
-      g_browser_process->system_request_context(),
+      g_browser_process->system_request_context(), system_url_loader_factory,
       ProfileOAuth2TokenServiceFactory::GetForProfile(profile));
   return service;
 }
diff --git a/chrome/browser/policy/cloud/user_policy_signin_service_factory.h b/chrome/browser/policy/cloud/user_policy_signin_service_factory.h
index dcef00d..0e15762 100644
--- a/chrome/browser/policy/cloud/user_policy_signin_service_factory.h
+++ b/chrome/browser/policy/cloud/user_policy_signin_service_factory.h
@@ -5,7 +5,9 @@
 #ifndef CHROME_BROWSER_POLICY_CLOUD_USER_POLICY_SIGNIN_SERVICE_FACTORY_H_
 #define CHROME_BROWSER_POLICY_CLOUD_USER_POLICY_SIGNIN_SERVICE_FACTORY_H_
 
+#include "base/lazy_instance.h"
 #include "base/macros.h"
+#include "base/memory/ref_counted.h"
 #include "base/memory/singleton.h"
 #include "components/keyed_service/content/browser_context_keyed_service_factory.h"
 
@@ -15,6 +17,10 @@
 class PrefRegistrySyncable;
 }
 
+namespace network {
+class SharedURLLoaderFactory;
+}
+
 namespace policy {
 
 class DeviceManagementService;
@@ -38,6 +44,9 @@
   static void SetDeviceManagementServiceForTesting(
       DeviceManagementService* device_management_service);
 
+  static void SetSystemURLLoaderFactoryForTesting(
+      scoped_refptr<network::SharedURLLoaderFactory> system_url_loader_factory);
+
  protected:
   // BrowserContextKeyedServiceFactory implementation.
   KeyedService* BuildServiceInstanceFor(
@@ -53,6 +62,9 @@
  private:
   friend struct base::DefaultSingletonTraits<UserPolicySigninServiceFactory>;
 
+  static base::LazyInstance<scoped_refptr<network::SharedURLLoaderFactory>>::
+      Leaky system_url_loader_factory_for_tests_;
+
   UserPolicySigninServiceFactory();
   ~UserPolicySigninServiceFactory() override;
 
diff --git a/chrome/browser/policy/cloud/user_policy_signin_service_mobile.cc b/chrome/browser/policy/cloud/user_policy_signin_service_mobile.cc
index 7536472..c3aad7fc 100644
--- a/chrome/browser/policy/cloud/user_policy_signin_service_mobile.cc
+++ b/chrome/browser/policy/cloud/user_policy_signin_service_mobile.cc
@@ -25,6 +25,7 @@
 #include "components/signin/core/browser/signin_manager.h"
 #include "net/base/network_change_notifier.h"
 #include "net/url_request/url_request_context_getter.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
 
 namespace em = enterprise_management;
 
@@ -48,17 +49,18 @@
     UserCloudPolicyManager* policy_manager,
     SigninManager* signin_manager,
     scoped_refptr<net::URLRequestContextGetter> system_request_context,
+    scoped_refptr<network::SharedURLLoaderFactory> system_url_loader_factory,
     ProfileOAuth2TokenService* token_service)
     : UserPolicySigninServiceBase(profile,
                                   local_state,
                                   device_management_service,
                                   policy_manager,
                                   signin_manager,
-                                  system_request_context),
+                                  system_request_context,
+                                  system_url_loader_factory),
       oauth2_token_service_(token_service),
       profile_prefs_(profile->GetPrefs()),
-      weak_factory_(this) {
-}
+      weak_factory_(this) {}
 
 UserPolicySigninService::~UserPolicySigninService() {}
 
diff --git a/chrome/browser/policy/cloud/user_policy_signin_service_mobile.h b/chrome/browser/policy/cloud/user_policy_signin_service_mobile.h
index 1c3e4c8..2cd2a303 100644
--- a/chrome/browser/policy/cloud/user_policy_signin_service_mobile.h
+++ b/chrome/browser/policy/cloud/user_policy_signin_service_mobile.h
@@ -22,6 +22,9 @@
 namespace net {
 class URLRequestContextGetter;
 }
+namespace network {
+class SharedURLLoaderFactory;
+}
 
 namespace policy {
 
@@ -38,6 +41,7 @@
       UserCloudPolicyManager* policy_manager,
       SigninManager* signin_manager,
       scoped_refptr<net::URLRequestContextGetter> system_request_context,
+      scoped_refptr<network::SharedURLLoaderFactory> system_url_loader_factory,
       ProfileOAuth2TokenService* token_service);
   ~UserPolicySigninService() override;
 
diff --git a/chrome/browser/policy/cloud/user_policy_signin_service_unittest.cc b/chrome/browser/policy/cloud/user_policy_signin_service_unittest.cc
index 3a501e5..3584d95 100644
--- a/chrome/browser/policy/cloud/user_policy_signin_service_unittest.cc
+++ b/chrome/browser/policy/cloud/user_policy_signin_service_unittest.cc
@@ -7,6 +7,7 @@
 
 #include "base/files/file_path.h"
 #include "base/run_loop.h"
+#include "base/test/bind_test_util.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
@@ -47,6 +48,7 @@
 #include "content/public/browser/notification_source.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "google_apis/gaia/gaia_constants.h"
+#include "google_apis/gaia/gaia_urls.h"
 #include "google_apis/gaia/google_service_auth_error.h"
 #include "net/base/net_errors.h"
 #include "net/http/http_status_code.h"
@@ -54,6 +56,8 @@
 #include "net/url_request/url_request_context_getter.h"
 #include "net/url_request/url_request_status.h"
 #include "net/url_request/url_request_test_util.h"
+#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
+#include "services/network/test/test_url_loader_factory.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -73,22 +77,22 @@
 
 namespace {
 
-const char kTestGaiaId[] = "gaia-id-testuser@test.com";
-const char kTestUser[] = "testuser@test.com";
+constexpr char kTestGaiaId[] = "gaia-id-testuser@test.com";
+constexpr char kTestUser[] = "testuser@test.com";
 
 #if !defined(OS_ANDROID)
-const char kValidTokenResponse[] =
-    "{"
-    "  \"access_token\": \"at1\","
-    "  \"expires_in\": 3600,"
-    "  \"token_type\": \"Bearer\""
-    "}";
+constexpr char kValidTokenResponse[] = R"(
+    {
+      "access_token": "at1",
+      "expires_in": 3600,
+      "token_type": "Bearer"
+    })";
 #endif
 
-const char kHostedDomainResponse[] =
-    "{"
-    "  \"hd\": \"test.com\""
-    "}";
+constexpr char kHostedDomainResponse[] = R"(
+    {
+      "hd": "test.com"
+    })";
 
 UserCloudPolicyManager* BuildCloudPolicyManager(
     content::BrowserContext* context) {
@@ -108,7 +112,10 @@
         thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
         test_account_id_(
             AccountId::FromUserEmailGaiaId(kTestUser, kTestGaiaId)),
-        register_completed_(false) {}
+        register_completed_(false),
+        test_system_shared_loader_factory_(
+            base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
+                &test_url_loader_factory_)) {}
 
   MOCK_METHOD1(OnPolicyRefresh, void(bool));
 
@@ -132,16 +139,19 @@
             profile_.get()->GetPrefs(), kTestGaiaId, kTestUser),
         "oauth2_login_refresh_token");
     service->RegisterForPolicyWithAccountId(kTestUser, kTestGaiaId, callback);
+    ASSERT_TRUE(IsRequestActive());
 #else
     service->RegisterForPolicyWithLoginToken(kTestUser, "mock_oauth_token",
                                              callback);
+    ASSERT_TRUE(IsOAuthTokenRequestActive());
 #endif
-    ASSERT_TRUE(IsRequestActive());
   }
 
   void SetUp() override {
     UserPolicySigninServiceFactory::SetDeviceManagementServiceForTesting(
         &device_management_service_);
+    UserPolicySigninServiceFactory::SetSystemURLLoaderFactoryForTesting(
+        test_system_shared_loader_factory_);
 
     local_state_.reset(new TestingPrefServiceSimple);
     RegisterLocalState(local_state_->registry());
@@ -152,7 +162,8 @@
     TestingBrowserProcess::GetGlobal()->SetLocalState(local_state_.get());
 
     g_browser_process->browser_policy_connector()->Init(
-        local_state_.get(), system_request_context_getter_);
+        local_state_.get(), system_request_context_getter_,
+        test_system_shared_loader_factory_);
 
     // Create a testing profile with cloud-policy-on-signin enabled, and bring
     // up a UserCloudPolicyManager with a MockUserCloudPolicyStore.
@@ -208,6 +219,7 @@
     testing_browser_process->SetLocalState(NULL);
     local_state_.reset();
     testing_browser_process->ShutdownBrowserPolicyConnector();
+    test_system_shared_loader_factory_->Detach();
     base::RunLoop run_loop;
     run_loop.RunUntilIdle();
   }
@@ -233,6 +245,16 @@
     return static_cast<FakeProfileOAuth2TokenService*>(service);
   }
 
+  // Reports whether an OAuth token request is active.
+  // Note that at this time, only OAuth token requests use the SimpleURLLoader,
+  // and that's why we need this method and IsRequestActive().
+  // Once the other Gaia requests use it, we can have only one method.
+  bool IsOAuthTokenRequestActive() {
+    if (!GetTokenService()->GetPendingRequests().empty())
+      return true;
+    return test_url_loader_factory_.NumPending() > 0;
+  }
+
   bool IsRequestActive() {
     if (!GetTokenService()->GetPendingRequests().empty())
       return true;
@@ -240,15 +262,32 @@
   }
 
   void MakeOAuthTokenFetchSucceed() {
-    ASSERT_TRUE(IsRequestActive());
 #if defined(OS_ANDROID)
+    ASSERT_TRUE(IsRequestActive());
     GetTokenService()->IssueTokenForAllPendingRequests("access_token",
                                                        base::Time::Now());
 #else
-    net::TestURLFetcher* fetcher = url_factory_.GetFetcherByID(0);
-    fetcher->set_response_code(net::HTTP_OK);
-    fetcher->SetResponseString(kValidTokenResponse);
-    fetcher->delegate()->OnURLFetchComplete(fetcher);
+    ASSERT_TRUE(IsOAuthTokenRequestActive());
+    test_url_loader_factory_.AddResponse(
+        GaiaUrls::GetInstance()->oauth2_token_url().spec(),
+        kValidTokenResponse);
+    base::RunLoop().RunUntilIdle();
+    test_url_loader_factory_.ClearResponses();
+#endif
+  }
+
+  void MakeOAuthTokenFetchFail() {
+#if defined(OS_ANDROID)
+    ASSERT_TRUE(!GetTokenService()->GetPendingRequests().empty());
+    GetTokenService()->IssueErrorForAllPendingRequests(
+        GoogleServiceAuthError::FromServiceError("fail"));
+#else
+    ASSERT_GT(test_url_loader_factory_.NumPending(), 0);
+    test_url_loader_factory_.AddResponse(
+        GaiaUrls::GetInstance()->oauth2_token_url().spec(), "",
+        net::HTTP_BAD_REQUEST);
+    base::RunLoop().RunUntilIdle();
+    test_url_loader_factory_.ClearResponses();
 #endif
   }
 
@@ -313,6 +352,7 @@
 
     signin_service->FetchPolicyForSignedInUser(
         test_account_id_, dm_token_, client_id_, profile_->GetRequestContext(),
+        test_system_shared_loader_factory_,
         base::Bind(&UserPolicySigninServiceTest::OnPolicyRefresh,
                    base::Unretained(this)));
 
@@ -374,6 +414,9 @@
 
   std::unique_ptr<TestingPrefServiceSimple> local_state_;
   scoped_refptr<net::URLRequestContextGetter> system_request_context_getter_;
+  network::TestURLLoaderFactory test_url_loader_factory_;
+  scoped_refptr<network::WeakWrapperSharedURLLoaderFactory>
+      test_system_shared_loader_factory_;
 };
 
 class UserPolicySigninServiceSignedInTest : public UserPolicySigninServiceTest {
@@ -630,23 +673,15 @@
 
   // UserCloudPolicyManager should not be initialized.
   ASSERT_FALSE(manager_->core()->service());
-  ASSERT_TRUE(IsRequestActive());
+  ASSERT_TRUE(IsOAuthTokenRequestActive());
   EXPECT_FALSE(register_completed_);
 
   // Cause the access token fetch to fail - callback should be invoked.
-#if defined(OS_ANDROID)
-  ASSERT_TRUE(!GetTokenService()->GetPendingRequests().empty());
-  GetTokenService()->IssueErrorForAllPendingRequests(
-      GoogleServiceAuthError::FromServiceError("fail"));
-#else
-  net::TestURLFetcher* fetcher = url_factory_.GetFetcherByID(0);
-  fetcher->set_status(net::URLRequestStatus::FromError(net::ERR_FAILED));
-  fetcher->delegate()->OnURLFetchComplete(fetcher);
-#endif
+  MakeOAuthTokenFetchFail();
 
   EXPECT_TRUE(register_completed_);
   EXPECT_TRUE(dm_token_.empty());
-  EXPECT_FALSE(IsRequestActive());
+  ASSERT_FALSE(IsOAuthTokenRequestActive());
 }
 
 TEST_F(UserPolicySigninServiceTest, RegisterPolicyClientNonHostedDomain) {
@@ -656,7 +691,7 @@
 
   // UserCloudPolicyManager should not be initialized.
   ASSERT_FALSE(manager_->core()->service());
-  ASSERT_TRUE(IsRequestActive());
+  ASSERT_TRUE(IsOAuthTokenRequestActive());
 
   // Cause the access token request to succeed.
   MakeOAuthTokenFetchSucceed();
@@ -675,7 +710,7 @@
   // DMToken.
   EXPECT_TRUE(register_completed_);
   EXPECT_TRUE(dm_token_.empty());
-  ASSERT_FALSE(IsRequestActive());
+  ASSERT_FALSE(IsOAuthTokenRequestActive());
 }
 
 TEST_F(UserPolicySigninServiceTest, RegisterPolicyClientFailedRegistration) {
@@ -770,7 +805,7 @@
       UserPolicySigninServiceFactory::GetForProfile(profile_.get());
   signin_service->FetchPolicyForSignedInUser(
       test_account_id_, "mock_dm_token", "mock_client_id",
-      profile_->GetRequestContext(),
+      profile_->GetRequestContext(), test_system_shared_loader_factory_,
       base::Bind(&UserPolicySigninServiceTest::OnPolicyRefresh,
                  base::Unretained(this)));
   ASSERT_TRUE(fetch_request);
diff --git a/chrome/browser/policy/machine_level_user_cloud_policy_controller.cc b/chrome/browser/policy/machine_level_user_cloud_policy_controller.cc
index 6d3edb3..ee17b3a 100644
--- a/chrome/browser/policy/machine_level_user_cloud_policy_controller.cc
+++ b/chrome/browser/policy/machine_level_user_cloud_policy_controller.cc
@@ -27,6 +27,7 @@
 #include "components/policy/core/common/cloud/machine_level_user_cloud_policy_store.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/common/content_switches.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
 
 #if defined(OS_WIN)
 #include "chrome/install_static/install_util.h"
@@ -90,7 +91,8 @@
 
 void MachineLevelUserCloudPolicyController::Init(
     PrefService* local_state,
-    scoped_refptr<net::URLRequestContextGetter> request_context) {
+    scoped_refptr<net::URLRequestContextGetter> request_context,
+    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) {
   MachineLevelUserCloudPolicyManager* policy_manager =
       g_browser_process->browser_policy_connector()
           ->machine_level_user_cloud_policy_manager();
@@ -111,8 +113,8 @@
 
   if (!dm_token.empty()) {
     policy_fetcher_ = std::make_unique<MachineLevelUserCloudPolicyFetcher>(
-        policy_manager, local_state, device_management_service,
-        request_context);
+        policy_manager, local_state, device_management_service, request_context,
+        url_loader_factory);
     return;
   }
 
@@ -123,9 +125,10 @@
   DCHECK(!client_id.empty());
 
   policy_registrar_ = std::make_unique<MachineLevelUserCloudPolicyRegistrar>(
-      device_management_service, request_context);
+      device_management_service, request_context, url_loader_factory);
   policy_fetcher_ = std::make_unique<MachineLevelUserCloudPolicyFetcher>(
-      policy_manager, local_state, device_management_service, request_context);
+      policy_manager, local_state, device_management_service, request_context,
+      url_loader_factory);
 
   if (dm_token.empty()) {
     policy_register_watcher_ =
diff --git a/chrome/browser/policy/machine_level_user_cloud_policy_controller.h b/chrome/browser/policy/machine_level_user_cloud_policy_controller.h
index f0293f2..9a29153 100644
--- a/chrome/browser/policy/machine_level_user_cloud_policy_controller.h
+++ b/chrome/browser/policy/machine_level_user_cloud_policy_controller.h
@@ -17,6 +17,10 @@
 
 class PrefService;
 
+namespace network {
+class SharedURLLoaderFactory;
+}
+
 namespace policy {
 class MachineLevelUserCloudPolicyManager;
 class MachineLevelUserCloudPolicyFetcher;
@@ -55,7 +59,8 @@
   CreatePolicyManager();
 
   void Init(PrefService* local_state,
-            scoped_refptr<net::URLRequestContextGetter> request_context);
+            scoped_refptr<net::URLRequestContextGetter> request_context,
+            scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory);
 
   RegisterResult WaitUntilPolicyEnrollmentFinished();
 
diff --git a/chrome/browser/resource_coordinator/tab_helper.cc b/chrome/browser/resource_coordinator/tab_helper.cc
index 2775ffdb..43b931e 100644
--- a/chrome/browser/resource_coordinator/tab_helper.cc
+++ b/chrome/browser/resource_coordinator/tab_helper.cc
@@ -114,7 +114,7 @@
 
 void ResourceCoordinatorTabHelper::DidFinishNavigation(
     content::NavigationHandle* navigation_handle) {
-  if (!navigation_handle->HasCommitted() || navigation_handle->IsErrorPage() ||
+  if (!navigation_handle->HasCommitted() ||
       navigation_handle->IsSameDocument()) {
     return;
   }
diff --git a/chrome/browser/resources/chromeos/assistant_optin/assistant_confirm_reject.css b/chrome/browser/resources/chromeos/assistant_optin/assistant_confirm_reject.css
new file mode 100644
index 0000000..a9ddb4f
--- /dev/null
+++ b/chrome/browser/resources/chromeos/assistant_optin/assistant_confirm_reject.css
@@ -0,0 +1,48 @@
+/* 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. */
+
+#main-container {
+  height: 372px;
+  overflow: hidden;
+  padding: 48px 48px 0 48px;
+  position: absolute;
+  width: 480px;
+}
+
+img {
+  display: block;
+  height: 100px;
+  margin: auto;
+}
+
+.title {
+  font-size: 18px;
+  padding: 32px 0 18px 0;
+}
+
+.sub-title {
+  font-size: 12px;
+}
+
+.content {
+  color: rgba(0, 0, 0, .8);
+  font-size: 11px;
+  padding-top: 6px;
+}
+
+.extra-content {
+  color: rgba(0, 0, 0, .54);
+  font-size: 10px;
+  padding-top: 6px;
+}
+
+#accept,
+#reject {
+  align-items: unset;
+  padding: 10px 0 10px 0;
+}
+
+#next-button {
+  -webkit-margin-end: 18px;
+}
diff --git a/chrome/browser/resources/chromeos/assistant_optin/assistant_confirm_reject.html b/chrome/browser/resources/chromeos/assistant_optin/assistant_confirm_reject.html
new file mode 100644
index 0000000..c28dd13
--- /dev/null
+++ b/chrome/browser/resources/chromeos/assistant_optin/assistant_confirm_reject.html
@@ -0,0 +1,42 @@
+<!-- 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. -->
+
+<link rel="import" href="chrome://resources/cr_elements/cr_radio_button/cr_radio_button.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-radio-group/paper-radio-group.html">
+<dom-module id="assistant-confirm-reject">
+  <template>
+    <link rel="stylesheet" href="../login/oobe_dialog_parameters.css">
+    <link rel="stylesheet" href="../login/oobe_flex_layout.css">
+    <link rel="stylesheet" href="assistant_confirm_reject.css">
+    <oobe-dialog id="confirm-reject-dialog" role="dialog" has-buttons
+        hide-shadow no-footer-padding no-header android>
+      <div slot="footer">
+        <div id="main-container">
+          <iron-icon src="assistant_logo.png">
+          </iron-icon>
+          <div class="title" id="title-text"></div>
+          <img src="assistant_confirm_reject.svg">
+          <paper-radio-group selected="accept" selectable="cr-radio-button">
+            <cr-radio-button id="accept" name="accept">
+              <div class="sub-title" id="accept-title-text"></div>
+              <div class="content" id="accept-message-text"></div>
+              <div class="extra-content" id="accept-message-extra-text"></div>
+            </cr-radio-button>
+            <cr-radio-button id="reject" name="reject">
+              <div class="sub-title" id="reject-title-text"></div>
+              <div class="content" id="reject-message-text"></div>
+            </cr-radio-button>
+          </paper-radio-group>
+        </div>
+      </div>
+      <div slot="bottom-buttons" class="flex layout horizontal">
+        <div class="flex"></div>
+        <oobe-text-button id="next-button" inverse android on-tap="onNextTap_"
+            disabled="[[buttonsDisabled]]" hidden="[[moreContents]]">
+          <div id="next-button-text"></div>
+        </oobe-text-button>
+      </div>
+    </oobe-dialog>
+  </template>
+</dom-module>
diff --git a/chrome/browser/resources/chromeos/assistant_optin/assistant_confirm_reject.js b/chrome/browser/resources/chromeos/assistant_optin/assistant_confirm_reject.js
new file mode 100644
index 0000000..94db603
--- /dev/null
+++ b/chrome/browser/resources/chromeos/assistant_optin/assistant_confirm_reject.js
@@ -0,0 +1,90 @@
+// 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 Polymer element for displaying material design assistant
+ * confirm reject screen.
+ *
+ * Event 'loading' will be fired when the page is loading/reloading.
+ * Event 'loaded' will be fired when the page has been successfully loaded.
+ */
+
+Polymer({
+  is: 'assistant-confirm-reject',
+
+  properties: {
+    /**
+     * Buttons are disabled when the page content is loading.
+     */
+    buttonsDisabled: {
+      type: Boolean,
+      value: true,
+    },
+  },
+
+  /**
+   * Whether all the screen content has been successfully loaded.
+   * @type {boolean}
+   * @private
+   */
+  pageLoaded_: false,
+
+  /**
+   * On-tap event handler for next button.
+   *
+   * @private
+   */
+  onNextTap_: function() {
+    var confirmResult = this.$['accept'].getAttribute('checked') != null;
+    chrome.send('AssistantConfirmRejectScreen.userActed', [confirmResult]);
+  },
+
+  /**
+   * Reloads the page.
+   */
+  reloadPage: function() {
+    this.fire('loading');
+    this.buttonsDisabled = true;
+  },
+
+  /**
+   * Reload the page with the given consent string text data.
+   */
+  reloadContent: function(data) {
+    this.$['title-text'].textContent = data['confirmRejectTitle'];
+    this.$['next-button-text'].textContent =
+        data['confirmRejectContinueButton'];
+    this.$['accept-title-text'].textContent = data['confirmRejectAcceptTitle'];
+    this.$['accept-message-text'].textContent =
+        data['confirmRejectAcceptMessage'];
+    this.$['accept-message-extra-text'].textContent =
+        data['confirmRejectAcceptMessageExpanded'];
+    this.$['reject-title-text'].textContent = data['confirmRejectRejectTitle'];
+    this.$['reject-message-text'].textContent =
+        data['confirmRejectRejectMessage'];
+
+    this.pageLoaded_ = true;
+    this.onPageLoaded();
+  },
+
+  /**
+   * Handles event when all the page content has been loaded.
+   */
+  onPageLoaded: function() {
+    this.fire('loaded');
+    this.buttonsDisabled = false;
+    this.$['next-button'].focus();
+  },
+
+  /**
+   * Signal from host to show the screen.
+   */
+  onShow: function() {
+    if (!this.pageLoaded_) {
+      this.reloadPage();
+    } else {
+      this.$['next-button'].focus();
+    }
+  },
+});
diff --git a/chrome/browser/resources/chromeos/assistant_optin/assistant_confirm_reject.svg b/chrome/browser/resources/chromeos/assistant_optin/assistant_confirm_reject.svg
new file mode 100644
index 0000000..0420bc4
--- /dev/null
+++ b/chrome/browser/resources/chromeos/assistant_optin/assistant_confirm_reject.svg
@@ -0,0 +1,208 @@
+<svg xmlns="http://www.w3.org/2000/svg"
+  xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 1586.38 846.63">
+  <defs>
+    <style>      .cls-15,      .cls-16,      .cls-20,      .cls-21,      .cls-23,      .cls-29,      .cls-33,      .cls-46,      .cls-47,      .cls-5 {        fill: none      }
+      .cls-3 {        fill: #f1f2f2      }
+      .cls-4 {        fill: #e1e2e6      }
+      .cls-33,      .cls-47,      .cls-5 {        stroke: #fff      }
+      .cls-15,      .cls-20,      .cls-23,      .cls-29,      .cls-33,      .cls-46,      .cls-47,      .cls-5 {        stroke-linecap: round      }
+      .cls-15,      .cls-16,      .cls-20,      .cls-21,      .cls-5 {        stroke-miterlimit: 10      }
+      .cls-5 {        stroke-width: 12.41px      }
+      .cls-6 {        fill: #fff      }
+      .cls-23 {        mix-blend-mode: multiply      }
+      .cls-10 {        fill: #4285f4      }
+      .cls-15 {        stroke: #979da5      }
+      .cls-15,      .cls-29 {        stroke-width: 5.15px      }
+      .cls-16,      .cls-20,      .cls-46 {        stroke: #686c71      }
+      .cls-16,      .cls-20,      .cls-46,      .cls-47 {        stroke-width: 6.4px      }
+      .cls-17 {        fill: #979da5      }
+      .cls-19 {        fill: #34a853      }
+      .cls-21 {        stroke: #f2f3f4;        stroke-width: 3.43px      }
+      .cls-22 {        fill: #ea4335      }
+      .cls-23,      .cls-29 {        stroke: #4285f4      }
+      .cls-23,      .cls-29,      .cls-33,      .cls-46,      .cls-47 {        stroke-linejoin: round      }
+      .cls-23 {        stroke-width: 12px      }
+      .cls-28 {        fill: #fbbc05      }
+      .cls-33 {        stroke-width: 5.64px      }
+      .cls-36 {        fill: #686c71      }
+      .cls-41 {        fill: #2a2c33      }    </style>
+    <linearGradient id="linear-gradient" x1="9424.34" y1="297.42" x2="9625.34" y2="297.42" gradientTransform="matrix(1.05 0 0 1 -9807.24 471.69)" gradientUnits="userSpaceOnUse">
+      <stop offset="0" stop-color="#fff" />
+      <stop offset="1" stop-color="#979da5" />
+    </linearGradient>
+    <linearGradient id="linear-gradient-2" x1="10211.87" y1="301.85" x2="10461.84" y2="301.85" xlink:href="#linear-gradient" />
+    <linearGradient id="linear-gradient-3" x1="10591.49" y1="305.35" x2="10705.62" y2="305.35" xlink:href="#linear-gradient" />
+    <linearGradient id="linear-gradient-4" x1="1057.05" y1="644" x2="1418.97" y2="644" gradientTransform="matrix(-1 0 0 1 1928 0)" gradientUnits="userSpaceOnUse">
+      <stop offset="0" stop-color="#686c71" />
+      <stop offset=".32" stop-color="#9d9fa3" />
+      <stop offset=".78" stop-color="#e3e4e5" />
+      <stop offset="1" stop-color="#fff" />
+    </linearGradient>
+    <linearGradient id="linear-gradient-5" x1="955.26" y1="129.27" x2="1021.33" y2="129.27" gradientTransform="rotate(180 894.015 222.815)" gradientUnits="userSpaceOnUse">
+      <stop offset="0" stop-color="#979da5" />
+      <stop offset="1" stop-color="#fff" />
+    </linearGradient>
+    <linearGradient id="linear-gradient-6" x1="741.04" y1="121.29" x2="822.23" y2="121.29" gradientTransform="rotate(90 691.195 352.105)" xlink:href="#linear-gradient-5" />
+    <linearGradient id="linear-gradient-7" x1="672.18" y1="632.75" x2="909.85" y2="395.08" xlink:href="#linear-gradient" />
+    <linearGradient id="linear-gradient-8" x1="1124.31" y1="657.44" x2="1005.01" y2="657.44" xlink:href="#linear-gradient" />
+    <linearGradient id="linear-gradient-9" x1="1291.74" y1="328.74" x2="1400.04" y2="437.04" gradientTransform="rotate(90 1368.5 322.5)" gradientUnits="userSpaceOnUse">
+      <stop offset="0" stop-color="#e1e2e6" />
+      <stop offset="1" stop-color="#fff" />
+    </linearGradient>
+    <linearGradient id="linear-gradient-10" x1="890.9" y1="351.48" x2="843.75" y2="398.63" xlink:href="#linear-gradient-5" />
+    <linearGradient id="linear-gradient-11" x1="882.1" y1="713.27" x2="896.32" y2="727.49" xlink:href="#linear-gradient-5" />
+    <linearGradient id="linear-gradient-12" x1="585.8" y1="656.66" x2="585.8" y2="500.58" gradientTransform="rotate(-7.81 -260.353 1606.207)" xlink:href="#linear-gradient" />
+    <linearGradient id="linear-gradient-13" x1="594.3" y1="502.49" x2="594.3" y2="628.88" gradientTransform="rotate(-7.81 -260.353 1606.207)" gradientUnits="userSpaceOnUse">
+      <stop offset=".38" stop-color="#fff" stop-opacity="0" />
+      <stop offset=".38" stop-color="#f9f9fa" stop-opacity=".06" />
+      <stop offset=".38" stop-color="#e2e4e6" stop-opacity=".28" />
+      <stop offset=".39" stop-color="#ced0d4" stop-opacity=".48" />
+      <stop offset=".4" stop-color="#bcc0c5" stop-opacity=".64" />
+      <stop offset=".4" stop-color="#afb3b9" stop-opacity=".77" />
+      <stop offset=".41" stop-color="#a4a9b0" stop-opacity=".88" />
+      <stop offset=".42" stop-color="#9ca2aa" stop-opacity=".95" />
+      <stop offset=".43" stop-color="#989ea6" stop-opacity=".99" />
+      <stop offset=".47" stop-color="#979da5" />
+      <stop offset=".57" stop-color="#bfc3c8" stop-opacity=".61" />
+      <stop offset=".66" stop-color="#e2e3e6" stop-opacity=".28" />
+      <stop offset=".73" stop-color="#f7f7f8" stop-opacity=".08" />
+      <stop offset=".77" stop-color="#fff" stop-opacity="0" />
+    </linearGradient>
+    <linearGradient id="linear-gradient-14" x1="260.06" y1="560.5" x2="366.27" y2="560.5" xlink:href="#linear-gradient" />
+    <linearGradient id="linear-gradient-15" x1="2123.45" y1="1680.93" x2="2059.86" y2="1680.93" gradientTransform="rotate(180 1271.845 1170.365)" gradientUnits="userSpaceOnUse">
+      <stop offset="0" stop-color="#fff" />
+      <stop offset="1" stop-color="#686c71" />
+    </linearGradient>
+    <linearGradient id="linear-gradient-16" x1="2003.93" y1="1681.29" x2="2003.93" y2="1756.07" gradientTransform="translate(-1558.93 -1115.88)" gradientUnits="userSpaceOnUse">
+      <stop offset="0" stop-color="#fff" />
+      <stop offset="1" stop-color="#808285" />
+    </linearGradient>
+    <linearGradient id="linear-gradient-17" x1="-17031.15" y1="3746.35" x2="-17031.15" y2="4024.29" gradientTransform="matrix(.21 0 0 .66 4090.12 -1587.95)" gradientUnits="userSpaceOnUse">
+      <stop offset="0" stop-color="#fff" />
+      <stop offset=".91" stop-color="#8c8d90" />
+      <stop offset="1" stop-color="#808285" />
+    </linearGradient>
+    <linearGradient id="linear-gradient-18" x1="3.51" y1="3618.68" x2="3.51" y2="3643.66" gradientTransform="translate(510.76 -2786.98)" gradientUnits="userSpaceOnUse">
+      <stop offset="0" stop-color="#fff" />
+      <stop offset=".91" stop-color="#fbc21d" />
+      <stop offset="1" stop-color="#fbbc05" />
+    </linearGradient>
+    <linearGradient id="linear-gradient-19" x1="-146.99" y1="-862.05" x2="-76.83" y2="-791.89" gradientTransform="rotate(111.7 193.858 577.349)" xlink:href="#linear-gradient-9" />
+    <linearGradient id="linear-gradient-20" x1="9501.62" y1="75.44" x2="9556.03" y2="75.44" xlink:href="#linear-gradient" />
+    <clipPath id="clip-path" transform="translate(-149.62 -106.37)">
+      <path d="M1085.1 397H735.44v494h349.66a12.27 12.27 0 0 0 12.27-12.27V409.27A12.27 12.27 0 0 0 1085.1 397z" fill="none" />
+    </clipPath>
+  </defs>
+  <g style="isolation:isolate">
+    <g id="Background">
+      <rect class="cls-3" x="649.46" width="298.45" height="512.27" rx="149.23" ry="149.23" />
+      <rect class="cls-3" x="1287.92" width="298.45" height="512.27" rx="149.23" ry="149.23" />
+      <path class="cls-4" d="M1444.72 209.78h284.1a149.28 149.28 0 0 0-142.05-103.41 149.28 149.28 0 0 0-142.05 103.41z" transform="translate(-149.62 -106.37)" />
+      <path class="cls-5" d="M1392.15 74.69h90" />
+      <path class="cls-6" d="M1306.37 461.82a46.49 46.49 0 0 1 64-39.76 103.65 103.65 0 0 1 194.07-11.69 61.75 61.75 0 0 1 88.07 51.46z" transform="translate(-149.62 -106.37)" />
+      <path class="cls-4" d="M806.26 209.78h284.1a149.28 149.28 0 0 0-142.05-103.41 149.28 149.28 0 0 0-142.05 103.41z" transform="translate(-149.62 -106.37)" />
+      <path class="cls-5" d="M753.69 74.69h90" />
+      <rect class="cls-3" x="30.42" width="298.45" height="512.27" rx="149.23" ry="149.23" />
+      <path class="cls-4" d="M187.22 209.78h284.1a149.28 149.28 0 0 0-142.05-103.41 149.28 149.28 0 0 0-142.05 103.41z" transform="translate(-149.62 -106.37)" />
+      <path class="cls-5" d="M134.64 74.69h90.01" />
+      <path class="cls-6" d="M987.73 304.24a42.64 42.64 0 0 1 18.27 4.13 71.8 71.8 0 0 1 137.48 28.94c0 2.26-.13 4.49-.34 6.69H945a42.85 42.85 0 0 1 42.73-39.76zM258.56 490.62a27.22 27.22 0 0 1 11.66 2.64A45.84 45.84 0 0 1 358 511.73c0 1.44-.09 2.87-.22 4.27H231.29a27.36 27.36 0 0 1 27.27-25.38zM482.56 246.62a27.22 27.22 0 0 1 11.66 2.64A45.84 45.84 0 0 1 582 267.73c0 1.44-.09 2.87-.22 4.27H455.29a27.36 27.36 0 0 1 27.27-25.38zM1661.2 531.43a17.77 17.77 0 0 0-7.61 1.72 29.92 29.92 0 0 0-57.3 12.06c0 .94.06 1.87.14 2.79H1679a17.86 17.86 0 0 0-17.8-16.57zM896.93 445.32a17.62 17.62 0 0 0-7.55 1.71 29.67 29.67 0 0 0-56.8 12c0 .93.06 1.85.14 2.77h81.86a17.71 17.71 0 0 0-17.65-16.48zM149.62 397a39.81 39.81 0 0 1 54.79-34 88.75 88.75 0 0 1 166.17-10A52.88 52.88 0 0 1 446 397z" transform="translate(-149.62 -106.37)" />
+    </g>
+    <g id="Foreground">
+      <path style="mix-blend-mode:multiply" fill="url(#linear-gradient)" d="M64.38 753.76h211.59v30.72H64.38z" />
+      <path style="mix-blend-mode:multiply" fill="url(#linear-gradient-2)" d="M881.38 762.63h263.15v21.82H881.38z" />
+      <path style="mix-blend-mode:multiply" fill="url(#linear-gradient-3)" d="M1314.38 770.63h120.15v12.82h-120.15z" />
+      <rect class="cls-10" x="220.47" y="290.63" width="727.28" height="494" rx="12.27" ry="12.27" />
+      <path d="M382.36 397H732v494H382.36a12.27 12.27 0 0 1-12.27-12.27V409.27A12.27 12.27 0 0 1 382.36 397z" transform="translate(-149.62 -106.37)" style="mix-blend-mode:multiply" fill="url(#linear-gradient-4)" opacity=".2" />
+      <path style="mix-blend-mode:multiply" opacity=".7" fill="url(#linear-gradient-5)" d="M847.27 342.09l-51.89-51.46h-42.32v51.46h94.21z" />
+      <path style="mix-blend-mode:multiply" fill="url(#linear-gradient-6)" opacity=".5" d="M947.74 421.85l-51.46-37.73V499.9h51.46v-78.05z" />
+      <path style="mix-blend-mode:multiply" fill="url(#linear-gradient-7)" opacity=".5" d="M628.36 330.6L434.53 524.42l141.94 260.21h289.8l46.31-46.31L628.36 330.6z" />
+      <rect class="cls-4" x="704.8" y="493.76" width="423.07" height="299.88" rx="24.28" ry="24.28" transform="rotate(90 894.71 515.7)" />
+      <path class="cls-6" transform="rotate(90 894.71 511.41)" d="M748.65 505.06h335.37v268.69H748.65z" />
+      <path class="cls-15" d="M751.59 347.02h30.25" />
+      <circle class="cls-15" cx="766.72" cy="724.08" r="11.23" />
+      <path class="cls-16" d="M1399 658.24a19.11 19.11 0 1 1 0-38.21M1270.44 658.24a19.11 19.11 0 1 1 0-38.21" transform="translate(-149.62 -106.37)" />
+      <path class="cls-17" d="M1132.1 784.38l-55.11-253.85-20.79-.04-40.81 253.89h116.71z" />
+      <path style="mix-blend-mode:multiply" fill="url(#linear-gradient-8)" opacity=".5" d="M1056.2 530.49l.05 253.89h119.25l-60.27-253.85-59.03-.04z" />
+      <path class="cls-4" d="M1350.38 784.38l-40.82-253.23-253.36-.66 40.98 253.89h253.2z" />
+      <path class="cls-19" d="M1319.28 591.66l-9.83-61.17H1056.2l9.89 61.17h253.19z" />
+      <path class="cls-20" d="M1270.44 620a19.11 19.11 0 1 1 0 38.21M1399 620a19.11 19.11 0 1 1 0 38.21" transform="translate(-149.62 -106.37)" />
+      <path class="cls-17" d="M664.72 395.27h181.82v144.08H664.72z" />
+      <path class="cls-3" d="M683.46 436.96v230.52h183.6l.07-230.52H683.46z" />
+      <path class="cls-4" d="M794.97 546.08h55.43v103.97h-55.43z" />
+      <path class="cls-4" d="M700.66 528.32H850.3v103.43H700.66zM827.14 491.53h8.84v19.36h-8.84z" />
+      <path class="cls-6" d="M700.66 528.32H850.3v14.37H700.66z" />
+      <path class="cls-21" d="M793.45 660.37V526.38M696.76 560.55h159.43M696.76 543.4h159.43M697.14 578.12h159.44M696.14 596.16h159.43M697.03 614.14h159.44M695.67 631.87h159.44" />
+      <circle class="cls-6" cx="885.47" cy="592" r="26.18" transform="rotate(-45 682.266 719.426)" />
+      <path class="cls-6" d="M785.53 464.44h9.45v46.51h-9.45z" />
+      <path class="cls-19" d="M799.94 483.03h9.03v27.92h-9.03z" />
+      <path class="cls-10" d="M813.55 500.89h8.88v9.99h-8.88z" />
+      <path class="cls-19" d="M904 573.49a26.1 26.1 0 0 0-18.51-7.67v25.9l26.15-.84a26.08 26.08 0 0 0-7.64-17.39z" transform="translate(-149.62 -106.37)" />
+      <path class="cls-10" d="M664.72 395.27h181.82v18.01H664.72z" />
+      <circle class="cls-6" cx="674.16" cy="404.7" r="4.29" />
+      <path class="cls-6" d="M1273.5 455.3a120.8 120.8 0 1 1 120.8-120.8 120.94 120.94 0 0 1-120.8 120.8z" transform="translate(-149.62 -106.37)" />
+      <path class="cls-22" d="M1273.5 222A112.5 112.5 0 1 1 1161 334.5 112.5 112.5 0 0 1 1273.5 222m0-16.6a129.1 129.1 0 1 0 91.29 37.81 128.25 128.25 0 0 0-91.29-37.81z" transform="translate(-149.62 -106.37)" />
+      <path class="cls-23" d="M1124.74 235.92l39.81-39.81M1124.74 235.92l-51.06-51.06" />
+      <circle class="cls-4" cx="1123.88" cy="134.67" r="7.63" />
+      <circle class="cls-4" cx="1123.88" cy="321.6" r="7.63" />
+      <circle class="cls-4" cx="1217.34" cy="228.13" r="7.63" />
+      <circle class="cls-4" cx="1030.41" cy="228.13" r="7.63" />
+      <path d="M1257.92 237.58a112.5 112.5 0 0 1 87 183.88 112.5 112.5 0 1 0-158.33-158.33 112 112 0 0 1 71.33-25.55z" transform="translate(-149.62 -106.37)" style="mix-blend-mode:multiply" fill="url(#linear-gradient-9)" />
+      <path style="mix-blend-mode:multiply" fill="url(#linear-gradient-10)" opacity=".4" d="M834.53 325.8H800.8l115.78 115.78V400.7l-82.05-74.9z" />
+      <path style="mix-blend-mode:multiply" fill="url(#linear-gradient-11)" opacity=".4" d="M916.87 689.44l-58.03 59.17h14.57l43.46-42.02v-17.15z" />
+      <path class="cls-4" d="M885.53 591.73v26.45a26.16 26.16 0 0 0 26-24.16z" transform="translate(-149.62 -106.37)" />
+      <path class="cls-10" d="M885.47 591.72l25.85 4.39a26.29 26.29 0 0 0-.95-12.17z" transform="translate(-149.62 -106.37)" />
+      <path style="mix-blend-mode:multiply" fill="url(#linear-gradient-12)" d="M509.12 548.79l-118.98 16.32-11.93-118.31 115.05-15.77 15.86 117.76z" />
+      <path class="cls-28" d="M516.72 508.15l-18.97-63.79-3.58-26.15-117.67 16.14 3.58 26.14 25.31 87.06 90.9-12.46 20.43-26.94z" />
+      <path class="cls-29" d="M438.08 472.46l27.89 30.63M461.33 469.28l-18.61 37M432.06 490.78l39.83-5.46" />
+      <path fill="#ffd364" d="M496.27 535.1l20.47-26.96-23.72 3.25 3.25 23.71z" />
+      <path style="mix-blend-mode:color-burn" fill="url(#linear-gradient-13)" opacity=".4" d="M516.72 508.15l-18.97-63.79-3.58-26.15-117.67 16.14 3.58 26.14 25.31 87.06 90.9-12.46 20.43-26.94z" />
+      <g>
+        <path d="M1433.91 493.8H1359a33.28 33.28 0 0 0-33.28 33.28 33.28 33.28 0 0 0 25.58 32.37V577l16.7-16.64h65.94a33.28 33.28 0 0 0 33.28-33.28 33.28 33.28 0 0 0-33.31-33.28z" transform="translate(-149.62 -106.37)" style="mix-blend-mode:multiply" fill="#4285f4" />
+        <path class="cls-33" d="M1206.93 411.01h78.49M1206.93 431.15h78.49" />
+      </g>
+      <path style="mix-blend-mode:multiply" fill="url(#linear-gradient-14)" opacity=".5" d="M284.5 422.56l-33.59 33.59v242.29l45.03-43.53-11.44-232.35z" />
+      <g>
+        <path stroke-width="4.67" stroke-linejoin="round" stroke-linecap="round" stroke="#fff" fill="none" d="M307.92 437.91h8.6v54.45" />
+        <path class="cls-36" transform="rotate(-90 317.37 670.32)" d="M362.8 637.59h165.13v22.21H362.8z" />
+        <path transform="rotate(-90 317.37 681.43)" style="mix-blend-mode:multiply" fill="url(#linear-gradient-15)" opacity=".4" d="M373.91 648.69h142.92v22.21H373.91z" />
+        <path class="cls-6" d="M456.12 731.26l-9.43 28.9a1.31 1.31 0 0 1-2.48 0l-10.07-28.93z" transform="translate(-149.62 -106.37)" />
+        <path class="cls-36" d="M442.36 754.88l1.85 5.31a1.31 1.31 0 0 0 2.48 0l1.71-5.26z" transform="translate(-149.62 -106.37)" />
+        <path class="cls-36" d="M418.42 551.08h67.43v28.66h-67.43a14.26 14.26 0 0 1-14.26-14.26v-.15a14.26 14.26 0 0 1 14.26-14.26z" transform="rotate(90 423.375 437.415)" />
+        <path d="M418.42 551.08h67.43v28.66h-67.43a14.26 14.26 0 0 1-14.26-14.26v-.15a14.26 14.26 0 0 1 14.26-14.26z" transform="rotate(90 423.375 437.415)" style="mix-blend-mode:multiply" fill="url(#linear-gradient-16)" opacity=".4" />
+      </g>
+      <rect class="cls-10" x="146.71" y="527.05" width="200.69" height="39.45" rx="19.73" ry="19.73" />
+      <path transform="rotate(-90 322.645 970.395)" style="mix-blend-mode:multiply" fill="url(#linear-gradient-17)" opacity=".2" d="M446.4 819.13h8.47v259.28h-8.47z" />
+      <g>
+        <path class="cls-28" d="M413.59 820.79h201.36v25.81H413.59z" />
+        <path style="mix-blend-mode:multiply" fill="url(#linear-gradient-18)" opacity=".4" d="M413.59 820.79h201.36v25.81H413.59z" />
+        <path class="cls-4" d="M413.59 846.6l-38.27-12.48 38.27-13.33v25.81z" />
+        <path class="cls-41" d="M385.86 830.45l-10.54 3.67 10.51 3.41.03-7.08z" />
+        <path class="cls-22" d="M764.69 927.15h-14V953h14a12.91 12.91 0 0 0 0-25.82z" transform="translate(-149.62 -106.37)" />
+        <path class="cls-4" d="M598.79 820.79h5.91v25.82h-5.91z" />
+      </g>
+      <path stroke="#e1e2e6" stroke-width="3.24" stroke-miterlimit="10" stroke-linecap="round" fill="none" d="M421.15 833.53h168.74" />
+      <g>
+        <path stroke-width="8.85" stroke="#fbbc05" stroke-linecap="square" stroke-linejoin="round" fill="none" d="M1438.61 716.94l66-28.46" />
+        <path stroke="#2a2c33" stroke-width="8.85" stroke-linejoin="round" stroke-linecap="round" fill="none" d="M1470.3 636.72l-10.85 27.33" />
+        <path class="cls-6" d="M1588.53 885.06a62.67 62.67 0 1 1 58.25-39.54 62.36 62.36 0 0 1-58.25 39.54z" transform="translate(-149.62 -106.37)" />
+        <path class="cls-28" d="M1588.56 764.68a57.7 57.7 0 1 1-53.63 36.4 57.52 57.52 0 0 1 53.63-36.4m0-10a67.71 67.71 0 1 0 25 4.79 67.56 67.56 0 0 0-25-4.79z" transform="translate(-149.62 -106.37)" />
+        <path class="cls-28" transform="rotate(21.67 1822.347 299.971)" d="M1601.56 737.12h35.87v14.11h-35.87z" />
+        <circle class="cls-4" cx="1605.59" cy="779.47" r="3.82" transform="rotate(-68.33 1452.5 836.499)" />
+        <circle class="cls-4" cx="1571.08" cy="866.36" r="3.82" transform="rotate(-68.33 1417.981 923.397)" />
+        <circle class="cls-4" cx="1631.78" cy="840.18" r="3.82" transform="rotate(-68.33 1478.69 897.208)" />
+        <circle class="cls-4" cx="1544.89" cy="805.66" r="3.82" transform="rotate(-68.33 1391.8 862.693)" />
+        <path d="M1600.16 775.19a57.69 57.69 0 0 1 15.32 98.19 57.68 57.68 0 1 0-63-96l1-.39a57.54 57.54 0 0 1 46.68-1.8z" transform="translate(-149.62 -106.37)" style="mix-blend-mode:multiply" fill="url(#linear-gradient-19)" />
+        <path class="cls-36" d="M1582.63 820.27l15-30.87a3.13 3.13 0 0 1 5.84 2.19l-9 33.1a6.33 6.33 0 0 1-12.21-3.32 6.76 6.76 0 0 1 .37-1.1z" transform="translate(-149.62 -106.37)" />
+      </g>
+      <g>
+        <path class="cls-46" d="M1382.68 740.17c-1.25-7.34 3.68-13.29 11-13.29s14.29 6 15.54 13.29-3.68 13.29-11 13.29M1398.25 753.62c9.95 0 19.39 8.07 21.08 18s-5 18-14.95 18-19.39-8.07-21.08-18" transform="translate(-149.62 -106.37)" />
+        <path class="cls-46" d="M1280.72 631.67l8.87-11.5 10.06 63.15" />
+        <path class="cls-47" d="M1105.16 623.59h81.03M1112.28 666.77h83.16M1120.47 709.96h185.21M1127.59 753.14h185.56" />
+      </g>
+      <path style="mix-blend-mode:multiply" fill="url(#linear-gradient-20)" d="M174.38 527.63h46v39h-46z" />
+      <g clip-path="url(#clip-path)">
+        <path class="cls-41" d="M1133.12 586.81L893.84 347.53l19.41-19.41 239.28 239.28zM1152.53 712l-19.41-19.41L893.84 931.9l19.41 19.41z" transform="translate(-149.62 -106.37)" />
+      </g>
+    </g>
+  </g>
+</svg>
diff --git a/chrome/browser/resources/chromeos/assistant_optin/assistant_loading.css b/chrome/browser/resources/chromeos/assistant_optin/assistant_loading.css
index 961473b..82aab55 100644
--- a/chrome/browser/resources/chromeos/assistant_optin/assistant_loading.css
+++ b/chrome/browser/resources/chromeos/assistant_optin/assistant_loading.css
@@ -2,60 +2,60 @@
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file. */
 
- #retry-button {
-   display: none;
- }
+#retry-button {
+  display: none;
+}
 
- .error #retry-button {
-   display: block;
- }
+.error #retry-button {
+  display: block;
+}
 
- #loading-container,
- #error-container {
-   height: 372px;
-   overflow: hidden;
-   padding: 48px 48px 0 48px;
-   position: absolute;
-   visibility: hidden;
-   width: 480px;
- }
+#loading-container,
+#error-container {
+  height: 372px;
+  overflow: hidden;
+  padding: 48px 48px 0 48px;
+  position: absolute;
+  visibility: hidden;
+  width: 480px;
+}
 
- .loading-animation #loading-container,
- .error #error-container {
-   visibility: visible;
- }
+.loading-animation #loading-container,
+.error #error-container {
+  visibility: visible;
+}
 
- .loading #retry-button {
-   pointer-events: none;
- }
+.loading #retry-button {
+  pointer-events: none;
+}
 
- .title {
-   font-size: 18px;
-   padding-bottom: 10px;
- }
+.title {
+  font-size: 18px;
+  padding-bottom: 10px;
+}
 
- .sub-title {
-   font-size: 12px;
-   padding: 8px 0 8px 0;
- }
+.sub-title {
+  font-size: 12px;
+  padding: 8px 0 8px 0;
+}
 
- #loading-message {
-   color: rgba(0, 0, 0, .54);
-   font-size: 12px;
-   line: 17px;
-   padding: 168px 0 0 0;
- }
+#loading-message {
+  color: rgba(0, 0, 0, .54);
+  font-size: 12px;
+  line: 17px;
+  padding: 168px 0 0 0;
+}
 
- paper-progress {
-   --paper-progress-active-color: rgb(66, 133, 244);
-   --paper-progress-container-color: #CEE0FC;
-   --paper-progress-secondary-color: rgb(66, 133, 244);
-   display: block;
-   height: 3px;
-   padding: 4px 0 0 0;
-   width: 100%;
- }
+paper-progress {
+  --paper-progress-active-color: rgb(66, 133, 244);
+  --paper-progress-container-color: #CEE0FC;
+  --paper-progress-secondary-color: rgb(66, 133, 244);
+  display: block;
+  height: 3px;
+  padding: 4px 0 0 0;
+  width: 100%;
+}
 
- #retry-button {
-   -webkit-margin-end: 18px;
- }
+#retry-button {
+  -webkit-margin-end: 18px;
+}
diff --git a/chrome/browser/resources/chromeos/assistant_optin/assistant_optin.html b/chrome/browser/resources/chromeos/assistant_optin/assistant_optin.html
index d2cdbb8e..1af6164 100644
--- a/chrome/browser/resources/chromeos/assistant_optin/assistant_optin.html
+++ b/chrome/browser/resources/chromeos/assistant_optin/assistant_optin.html
@@ -19,8 +19,10 @@
 <include src="../login/oobe_buttons.html">
 <include src="../login/oobe_change_picture.html">
 <include src="../login/oobe_dialog.html">
+<include src="assistant_confirm_reject.html">
 <include src="assistant_get_more.html">
 <include src="assistant_loading.html">
+<include src="assistant_ready.html">
 <include src="assistant_third_party.html">
 <include src="assistant_value_prop.html">
 <include src="setting_zippy.html">
@@ -46,10 +48,14 @@
    </assistant-loading>
    <assistant-value-prop id="value-prop">
    </assistant-value-prop>
+   <assistant-confirm-reject id="confirm-reject" hidden>
+   </assistant-confirm-reject>
    <assistant-third-party id="third-party" hidden>
    </assistant-third-party>
    <assistant-get-more id="get-more" hidden>
    </assistant-get-more>
+   <assistant-ready id="ready" hidden>
+   </assistant-ready>
 </div>
 
 <script src="chrome://resources/js/i18n_template.js"></script>
diff --git a/chrome/browser/resources/chromeos/assistant_optin/assistant_optin.js b/chrome/browser/resources/chromeos/assistant_optin/assistant_optin.js
index 069fc054..a9e6c353 100644
--- a/chrome/browser/resources/chromeos/assistant_optin/assistant_optin.js
+++ b/chrome/browser/resources/chromeos/assistant_optin/assistant_optin.js
@@ -8,8 +8,10 @@
 // <include src="../login/oobe_dialog.js">
 // <include src="utils.js">
 // <include src="setting_zippy.js">
+// <include src="assistant_confirm_reject.js">
 // <include src="assistant_get_more.js">
 // <include src="assistant_loading.js">
+// <include src="assistant_ready.js">
 // <include src="assistant_third_party.js">
 // <include src="assistant_value_prop.js">
 
@@ -40,6 +42,7 @@
       loadTimeData.overrideValues(data);
       i18nTemplate.process(document, loadTimeData);
       $('value-prop').reloadContent(data);
+      $('confirm-reject').reloadContent(data);
       $('third-party').reloadContent(data);
       $('get-more').reloadContent(data);
     },
@@ -71,11 +74,21 @@
     showNextScreen: function() {
       switch (this.currentScreen) {
         case $('value-prop'):
+          if ($('value-prop').userAccepted) {
+            this.showScreen($('third-party'));
+          } else {
+            this.showScreen($('confirm-reject'));
+          }
+          break;
+        case $('confirm-reject'):
           this.showScreen($('third-party'));
           break;
         case $('third-party'):
           this.showScreen($('get-more'));
           break;
+        case $('get-more'):
+          this.showScreen($('ready'));
+          break;
         default:
           console.error('Undefined');
           chrome.send('dialogClose');
diff --git a/chrome/browser/resources/chromeos/assistant_optin/assistant_ready.css b/chrome/browser/resources/chromeos/assistant_optin/assistant_ready.css
new file mode 100644
index 0000000..6f0f647
--- /dev/null
+++ b/chrome/browser/resources/chromeos/assistant_optin/assistant_ready.css
@@ -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. */
+
+#main-container {
+  height: 372px;
+  overflow: hidden;
+  padding: 48px 48px 0 48px;
+  position: absolute;
+  width: 480px;
+}
+
+.title {
+  font-size: 18px;
+  padding-top: 32px;
+}
+
+.sub-title {
+  font-size: 12px;
+  padding-top: 12px;
+}
+
+img {
+  display: block;
+  height: 180px;
+  margin: auto;
+  padding: 48px 0 0 32px;
+}
+
+#next-button {
+  -webkit-margin-end: 18px;
+}
diff --git a/chrome/browser/resources/chromeos/assistant_optin/assistant_ready.html b/chrome/browser/resources/chromeos/assistant_optin/assistant_ready.html
new file mode 100644
index 0000000..a5f9152
--- /dev/null
+++ b/chrome/browser/resources/chromeos/assistant_optin/assistant_ready.html
@@ -0,0 +1,30 @@
+<!-- Copyright 2018 The Chromium Authors. All rights reserved.
+     Use of this source code is governed by a BSD-style license that can be
+     found in the LICENSE file. -->
+
+<dom-module id="assistant-ready">
+  <template>
+    <link rel="stylesheet" href="../login/oobe_dialog_parameters.css">
+    <link rel="stylesheet" href="../login/oobe_flex_layout.css">
+    <link rel="stylesheet" href="assistant_ready.css">
+    <oobe-dialog id="ready-dialog" role="dialog" has-buttons hide-shadow
+        no-footer-padding no-header android>
+      <div slot="footer">
+        <div id="main-container">
+          <iron-icon src="assistant_logo.png">
+          </iron-icon>
+          <div class="title" i18n-content="assistantReadyTitle"></div>
+          <div class="sub-title" i18n-content="assistantReadyMessage"></div>
+          <img src="assistant_ready.svg">
+        </div>
+      </div>
+      <div slot="bottom-buttons" class="flex layout horizontal">
+        <div class="flex"></div>
+        <oobe-text-button id="next-button" inverse android on-tap="onNextTap_"
+            disabled="[[buttonsDisabled]]" hidden="[[moreContents]]">
+          <div i18n-content="assistantReadyButton"></div>
+        </oobe-text-button>
+      </div>
+    </oobe-dialog>
+  </template>
+</dom-module>
diff --git a/chrome/browser/resources/chromeos/assistant_optin/assistant_ready.js b/chrome/browser/resources/chromeos/assistant_optin/assistant_ready.js
new file mode 100644
index 0000000..511d6e9
--- /dev/null
+++ b/chrome/browser/resources/chromeos/assistant_optin/assistant_ready.js
@@ -0,0 +1,29 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview Polymer element for displaying material design assistant
+ * ready screen.
+ *
+ */
+
+Polymer({
+  is: 'assistant-ready',
+
+  /**
+   * On-tap event handler for next button.
+   *
+   * @private
+   */
+  onNextTap_: function() {
+    chrome.send('dialogClose');
+  },
+
+  /**
+   * Signal from host to show the screen.
+   */
+  onShow: function() {
+    this.$['next-button'].focus();
+  },
+});
diff --git a/chrome/browser/resources/chromeos/assistant_optin/assistant_ready.svg b/chrome/browser/resources/chromeos/assistant_optin/assistant_ready.svg
new file mode 100644
index 0000000..18888047
--- /dev/null
+++ b/chrome/browser/resources/chromeos/assistant_optin/assistant_ready.svg
@@ -0,0 +1,30 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="328" height="232">
+  <g fill="none" fill-rule="evenodd">
+    <path stroke="#DADCE0" stroke-width="3.211" d="M253.065 227.197H3m160.298 0H92.767c-4.87 0-8.817-3.954-8.817-8.831v-70.653c0-4.877 3.948-8.831 8.817-8.831h70.53c4.87 0 8.817 3.954 8.817 8.831v70.653c0 4.877-3.947 8.831-8.816 8.831z"/>
+    <path fill="#4285F4" d="M112.433 157.231c4.248-.724 8.77.383 12.175 3.037 3.43 2.621 5.697 6.714 6.064 11.027.417 4.294-1.038 8.727-3.93 11.927-3.032 3.433-7.62 5.411-12.195 5.229-4.553-.11-8.981-2.352-11.796-5.934-2.974-3.7-4.092-8.79-2.98-13.402 1.346-6.028 6.569-10.936 12.662-11.884"/>
+    <path fill="#34A853" d="M151.643 167.589c2.277-.819 4.946.987 5.052 3.397.24 2.19-1.693 4.278-3.888 4.19-2.188.062-4.098-2.03-3.849-4.206.097-1.54 1.223-2.923 2.685-3.381"/>
+    <path fill="#EA4335" d="M139.011 172.848c2.218-.624 4.711-.218 6.582 1.14 2.156 1.5 3.434 4.16 3.258 6.788-.116 2.449-1.494 4.778-3.553 6.093-2.864 1.887-6.955 1.543-9.436-.834-2.145-1.94-3.031-5.135-2.181-7.903.713-2.527 2.804-4.59 5.33-5.284"/>
+    <path fill="#FBBC05" d="M139.348 191.075c4.877-1.123 10.13 2.57 10.737 7.542.88 4.902-2.994 9.961-7.949 10.37-4.746.667-9.51-3.088-9.992-7.86-.697-4.572 2.665-9.247 7.204-10.052"/>
+    <path fill="#FFF" d="M11.915 36.083l37.161-9.974 9.958 37.224-37.161 9.975z"/>
+    <path fill="#E74133" d="M50.21 24.143L9.952 34.948l10.787 40.327 40.258-10.806L50.21 24.143zm-2.267 3.933l9.127 34.123-34.064 9.143-9.127-34.123 34.064-9.143z"/>
+    <path fill="#E74133" d="M51.98 36.967l-37.16 9.974-2.904-10.858 37.16-9.974zM33.208 53.642l-6.194 1.662-1.659-6.204 6.193-1.662z"/>
+    <path fill="#E74133" d="M15.316 30.184l-3.096.831 1.659 6.204 3.096-.831zM21.509 28.522l-3.096.831 1.659 6.204 3.097-.832zM27.703 26.859l-3.097.831 1.66 6.205 3.096-.831zM33.896 25.197l-3.097.831 1.66 6.204 3.097-.831zM40.09 23.534l-3.097.831 1.659 6.205 3.097-.831z"/>
+    <path fill="#EA4335" d="M46.284 21.872l-3.097.831 1.659 6.205 3.097-.832z"/>
+    <path stroke="#DADCE0" stroke-width="3.211" d="M285.926 84.287h-96.18c-22.131 0-40.074-17.973-40.074-40.144C149.672 21.973 167.615 4 189.747 4h96.179C308.058 4 326 21.973 326 44.143s-17.942 40.144-40.074 40.144z"/>
+    <path fill="#DADCE0" d="M192.953 101.95V84.287H218.6l-24.365 18.305a.801.801 0 0 1-1.282-.642"/>
+    <path stroke="#DADCE0" stroke-width="3.211" d="M181.732 34.509H293.94"/>
+    <path stroke="#34A853" stroke-width="3.211" d="M181.732 34.509h58.509"/>
+    <path stroke="#FBBC05" stroke-width="3.211" d="M181.732 53.778H293.94"/>
+    <path stroke="#EA4335" stroke-width="3.211" d="M181.732 53.778h78.546"/>
+    <path stroke="#4285F4" stroke-width="3.211" d="M181.732 53.778h39.273"/>
+    <path fill="#4285F4" d="M95.77 106.34a4.015 4.015 0 0 1-2.833 4.917 4.015 4.015 0 0 1-2.075-7.756 4.008 4.008 0 0 1 4.909 2.84"/>
+    <path stroke="#4285F4" stroke-width="3.211" d="M95.77 106.34a4.015 4.015 0 0 1-2.833 4.917 4.015 4.015 0 0 1-2.075-7.756 4.008 4.008 0 0 1 4.909 2.84zm0 0L89.34 82.3"/>
+    <path fill="#4285F4" d="M115.125 101.145a4.016 4.016 0 0 1-2.834 4.917 4.006 4.006 0 0 1-4.907-2.839 4.007 4.007 0 1 1 7.742-2.078"/>
+    <path stroke="#4285F4" stroke-width="3.211" d="M115.125 101.145a4.016 4.016 0 0 1-2.834 4.917 4.006 4.006 0 0 1-4.907-2.839 4.007 4.007 0 1 1 7.742-2.078zm0 0l-6.43-24.04"/>
+    <path fill="#4285F4" d="M89.34 82.3l1.245 4.653 20.515-5.507a4.819 4.819 0 0 0 3.401-5.9L89.341 82.3z"/>
+    <path stroke="#4285F4" stroke-width="3.211" d="M89.34 82.3l1.245 4.653 20.515-5.507a4.819 4.819 0 0 0 3.401-5.9L89.341 82.3z"/>
+    <path stroke="#34A853" stroke-width="3.211" d="M47.648 127c4.78 8.294 1.943 18.9-6.337 23.689-8.28 4.789-18.868 1.947-23.648-6.348-4.781-8.294-1.944-18.9 6.336-23.689 8.28-4.79 18.868-1.948 23.649 6.347z"/>
+    <path stroke="#34A853" stroke-width="3.211" d="M36.441 129.281l-3.071 11.483-5.223-1.402"/>
+    <path fill="#F1F3F4" d="M50.288 102.81l-5.667-5.677 5.667-5.678 5.667 5.678zM209.784 144.559l-5.667-5.677 5.667-5.678 5.667 5.678zM86.355 31.297a2.406 2.406 0 0 1-2.405 2.41 2.406 2.406 0 0 1-2.404-2.41 2.406 2.406 0 0 1 2.404-2.408 2.406 2.406 0 0 1 2.405 2.408m68.928 67.441a2.406 2.406 0 0 1-2.405 2.409 2.406 2.406 0 0 1-2.404-2.409 2.406 2.406 0 0 1 2.404-2.408 2.406 2.406 0 0 1 2.405 2.408"/>
+  </g>
+</svg>
diff --git a/chrome/browser/resources/chromeos/assistant_optin/assistant_value_prop.html b/chrome/browser/resources/chromeos/assistant_optin/assistant_value_prop.html
index 641b516..ae461d8 100644
--- a/chrome/browser/resources/chromeos/assistant_optin/assistant_value_prop.html
+++ b/chrome/browser/resources/chromeos/assistant_optin/assistant_value_prop.html
@@ -34,7 +34,7 @@
         <div class="flex"></div>
         <oobe-text-button id="more-button" inverse android on-tap="onMoreTap_"
             disabled="[[buttonsDisabled]]" hidden="[[!moreContents]]">
-          <div i18n-content="valuePropMoreButton"></div>
+          <div i18n-content="assistantOptinMoreButton"></div>
         </oobe-text-button>
         <oobe-text-button id="next-button" inverse android on-tap="onNextTap_"
             disabled="[[buttonsDisabled]]" hidden="[[moreContents]]">
diff --git a/chrome/browser/resources/chromeos/assistant_optin/assistant_value_prop.js b/chrome/browser/resources/chromeos/assistant_optin/assistant_value_prop.js
index aff2aea6..ad7e683 100644
--- a/chrome/browser/resources/chromeos/assistant_optin/assistant_value_prop.js
+++ b/chrome/browser/resources/chromeos/assistant_optin/assistant_value_prop.js
@@ -46,6 +46,14 @@
       type: Boolean,
       value: false,
     },
+
+    /**
+     * Whether user accept the activity control.
+     */
+    userAccepted: {
+      type: Boolean,
+      value: true,
+    },
   },
 
   /**
@@ -117,6 +125,7 @@
    * @private
    */
   onSkipTap_: function() {
+    this.userAccepted = false;
     chrome.send('AssistantValuePropScreen.userActed', ['skip-pressed']);
   },
 
@@ -138,6 +147,7 @@
    * @private
    */
   onNextTap_: function() {
+    this.userAccepted = true;
     chrome.send('AssistantValuePropScreen.userActed', ['next-pressed']);
   },
 
diff --git a/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings.grd b/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings.grd
index e3a7822..0afa689 100644
--- a/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings.grd
+++ b/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings.grd
@@ -2963,6 +2963,9 @@
       <message desc="A hint to the user that there are details associated with this element." name="IDS_CHROMEVOX_HINT_DETAILS">
         Press Search+A, J to jump to details.
       </message>
+      <message desc="The display name of the command that will jump to more details about an item." name="IDS_CHROMEVOX_JUMP_TO_DETAILS">
+        Jump to Details
+      </message>
       <message desc="Describes the action of decrementing a control." name="IDS_CHROMEVOX_ACTION_DECREMENT_DESCRIPTION">
         Decrease value
       </message>
diff --git a/chrome/browser/resources/local_ntp/most_visited_single.css b/chrome/browser/resources/local_ntp/most_visited_single.css
index 123e202..b5f06348 100644
--- a/chrome/browser/resources/local_ntp/most_visited_single.css
+++ b/chrome/browser/resources/local_ntp/most_visited_single.css
@@ -461,9 +461,9 @@
 }
 
 .md-favicon {
-  height: var(--md-favicon-size);
+  min-height: var(--md-favicon-size);
+  min-width: var(--md-favicon-size);
   pointer-events: none;
-  width: var(--md-favicon-size);
 }
 
 .md-favicon img {
diff --git a/chrome/browser/resources/local_ntp/most_visited_single.js b/chrome/browser/resources/local_ntp/most_visited_single.js
index 61a0229d..0e9fb3c 100644
--- a/chrome/browser/resources/local_ntp/most_visited_single.js
+++ b/chrome/browser/resources/local_ntp/most_visited_single.js
@@ -615,49 +615,44 @@
 
   let mdFavicon = document.createElement('div');
   mdFavicon.className = CLASSES.MD_FAVICON;
-  // Determine if a fallback icon should be displayed instead.
-  if (!data.fallbackBackgroundColorRgba || !data.fallbackTextColorRgba) {
-    let fi = document.createElement('img');
-    fi.src = data.faviconUrl;
-    // Set title and alt to empty so screen readers won't say the image name.
-    fi.title = '';
-    fi.alt = '';
-    loadedCounter += 1;
-    fi.addEventListener('load', function(ev) {
-      // Store the type for a potential later navigation.
-      tileType = TileVisualType.ICON_REAL;
-      logMostVisitedImpression(
-          position, data.tileTitleSource, data.tileSource, tileType,
-          data.dataGenerationTime);
-      // Note: It's important to call countLoad last, because that might emit
-      // the NTP_ALL_TILES_LOADED event, which must happen after the impression
-      // log.
-      countLoad();
-    });
-    fi.addEventListener('error', function(ev) {
-      mdFavicon.classList.add(CLASSES.FAILED_FAVICON);
-      mdFavicon.removeChild(fi);
-      // Store the type for a potential later navigation.
-      tileType = TileVisualType.ICON_DEFAULT;
-      logMostVisitedImpression(
-          position, data.tileTitleSource, data.tileSource, tileType,
-          data.dataGenerationTime);
-      // Note: It's important to call countLoad last, because that might emit
-      // the NTP_ALL_TILES_LOADED event, which must happen after the impression
-      // log.
-      countLoad();
-    });
-    mdFavicon.appendChild(fi);
-  } else {
-    mdIconBackground.style.backgroundColor =
-        convertToRGBAColor(data.fallbackBackgroundColorRgba);
-    mdFavicon.classList.add(CLASSES.FALLBACK);
-    let fallbackLetter = document.createElement('div');
-    fallbackLetter.className = CLASSES.FALLBACK_LETTER;
-    fallbackLetter.style.color = convertToRGBAColor(data.fallbackTextColorRgba);
-    fallbackLetter.innerText = data.title.charAt(0);
-    mdFavicon.appendChild(fallbackLetter);
-  }
+  let fi = document.createElement('img');
+  // TODO(crbug.com/853780): Use data.fallbackBackgroundColorRgba and
+  // data.fallbackTextColorRgba;
+  fi.src = 'chrome-search://ntpicon/size/16@' + window.devicePixelRatio + 'x/' +
+      data.url;
+  // Set title and alt to empty so screen readers won't say the image name.
+  fi.title = '';
+  fi.alt = '';
+  // Images from this source may come as multiples of 16dp or multiples of 40dp.
+  // We display them as full size (e.g. 48px for 3x) but zoom accordingly to
+  // keep the right visual appearance.
+  fi.style = 'zoom: ' + 100 / window.devicePixelRatio + '%;';
+  loadedCounter += 1;
+  fi.addEventListener('load', function(ev) {
+    // Store the type for a potential later navigation.
+    tileType = TileVisualType.ICON_REAL;
+    logMostVisitedImpression(
+        position, data.tileTitleSource, data.tileSource, tileType,
+        data.dataGenerationTime);
+    // Note: It's important to call countLoad last, because that might emit
+    // the NTP_ALL_TILES_LOADED event, which must happen after the impression
+    // log.
+    countLoad();
+  });
+  fi.addEventListener('error', function(ev) {
+    mdFavicon.classList.add(CLASSES.FAILED_FAVICON);
+    mdFavicon.removeChild(fi);
+    // Store the type for a potential later navigation.
+    tileType = TileVisualType.ICON_DEFAULT;
+    logMostVisitedImpression(
+        position, data.tileTitleSource, data.tileSource, tileType,
+        data.dataGenerationTime);
+    // Note: It's important to call countLoad last, because that might emit
+    // the NTP_ALL_TILES_LOADED event, which must happen after the impression
+    // log.
+    countLoad();
+  });
+  mdFavicon.appendChild(fi);
 
   mdIconBackground.appendChild(mdFavicon);
   mdIcon.appendChild(mdIconBackground);
diff --git a/chrome/browser/resources/md_extensions/toolbar.html b/chrome/browser/resources/md_extensions/toolbar.html
index 0468062b..b609815 100644
--- a/chrome/browser/resources/md_extensions/toolbar.html
+++ b/chrome/browser/resources/md_extensions/toolbar.html
@@ -6,6 +6,7 @@
 <link rel="import" href="chrome://resources/cr_elements/hidden_style_css.html">
 <link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html">
 <link rel="import" href="chrome://resources/cr_elements/policy/cr_tooltip_icon.html">
+<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
 <link rel="import" href="chrome://resources/html/assert.html">
 <link rel="import" href="chrome://resources/html/cr.html">
 <link rel="import" href="chrome://resources/html/util.html">
@@ -32,9 +33,10 @@
 
       /* This toggle needs special styling because it's on blue background. */
       cr-toolbar cr-toggle {
-        --cr-toggle-checked-bar-color: white;
+        --cr-toggle-checked-bar-color: var(--google-grey-refresh-100);
         --cr-toggle-checked-button-color: white;
         --cr-toggle-checked-ink-color: white;
+        --cr-toggle-unchecked-bar-color: var(--google-grey-600);
         --cr-toggle-unchecked-ink-color: white;
       }
 
diff --git a/chrome/browser/resources/pdf/elements/viewer-page-selector/BUILD.gn b/chrome/browser/resources/pdf/elements/viewer-page-selector/BUILD.gn
index 1c34433..725e3f9 100644
--- a/chrome/browser/resources/pdf/elements/viewer-page-selector/BUILD.gn
+++ b/chrome/browser/resources/pdf/elements/viewer-page-selector/BUILD.gn
@@ -11,4 +11,7 @@
 }
 
 js_library("viewer-page-selector") {
+  deps = [
+    "//ui/webui/resources/cr_elements/cr_input:cr_input",
+  ]
 }
diff --git a/chrome/browser/resources/pdf/elements/viewer-page-selector/viewer-page-selector.html b/chrome/browser/resources/pdf/elements/viewer-page-selector/viewer-page-selector.html
index 3d55cbd8..23e7055 100644
--- a/chrome/browser/resources/pdf/elements/viewer-page-selector/viewer-page-selector.html
+++ b/chrome/browser/resources/pdf/elements/viewer-page-selector/viewer-page-selector.html
@@ -1,13 +1,13 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/iron-input/iron-input.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-input/paper-input-container.html">
+
+<link rel="import" href="chrome://resources/cr_elements/cr_input/cr_input.html">
 
 <dom-module id="viewer-page-selector">
   <template>
     <style>
       :host {
         color: #fff;
-        font-size: 1.23rem;
+        font-size: 0.81rem;
       }
 
       :host ::selection {
@@ -15,27 +15,31 @@
       }
 
       #pageselector {
-        --container: { display: none; };
-        --paper-input-container-underline: var(--container);
-        --paper-input-container-underline-focus: var(--container);
-        padding: 0;
+        --cr-input-focus-color: transparent;
+        --cr-input-container: {
+          overflow: initial;
+        }
+        --cr-input-error-display: none;
+        --cr-input-background-color: transparent;
+        --cr-input-input: {
+          -webkit-margin-start: -3px;
+          -webkit-padding-end: 3px;
+          -webkit-padding-start: 3px;
+          padding-bottom: 0;
+          padding-top: 0;
+          text-align: end;
+          caret-color: #fff;
+          border-radius: 2px;
+          box-sizing: content-box;
+        }
+        -webkit-margin-start: -3px;
+        height: 100%;
         width: 1ch;
       }
 
-      #input {
-        -webkit-margin-start: -3px;
-        color: #fff;
-        height: 100%;
-        line-height: 18px;
-        padding: 3px;
-        text-align: end;
-        vertical-align: baseline;
-      }
-
-      #input:focus,
-      #input:hover {
-        background-color: rgba(0, 0, 0, 0.5);
-        border-radius: 2px;
+      #pageselector[focused_],
+      #pageselector:hover {
+        --cr-input-background-color: rgba(0, 0, 0, 0.5);
       }
 
       #slash {
@@ -44,7 +48,6 @@
 
       #pagelength-spacer {
         -webkit-margin-start: -2px;
-        padding-bottom: 1px;
         text-align: start;
       }
 
@@ -52,27 +55,12 @@
       #slash,
       #pagelength-spacer {
         display: inline-block;
-        margin-bottom: 2px;
-        vertical-align: middle;
-      }
-
-      #input,
-      #slash,
-      #pagelength {
-        font-size: 0.81rem;
-      }
-
-      iron-input input {
-        @apply --paper-input-container-shared-input-style;
       }
     </style>
-    <paper-input-container id="pageselector" no-label-float>
-      <iron-input slot="input" bind-value="[[pageNo]]" allowed-pattern="\d">
-        <input id="input" prevent-invalid-input value="{{value::input}}"
-            on-mouseup="select" on-change="pageNoCommitted"
-            aria-label$="{{strings.labelPageNumber}}">
-      </iron-input>
-    </paper-input-container>
+    <cr-input id="pageselector" value="[[pageNo]]" on-mouseup="select"
+        on-value-changed="onInputValueChange_" on-change="pageNoCommitted"
+        aria-label$="{{strings.labelPageNumber}}">
+    </cr-input>
     <span id="slash"> / </span>
     <span id="pagelength-spacer">
       <span id="pagelength">{{docLength}}</span>
diff --git a/chrome/browser/resources/pdf/elements/viewer-page-selector/viewer-page-selector.js b/chrome/browser/resources/pdf/elements/viewer-page-selector/viewer-page-selector.js
index a0b0188..75d3918 100644
--- a/chrome/browser/resources/pdf/elements/viewer-page-selector/viewer-page-selector.js
+++ b/chrome/browser/resources/pdf/elements/viewer-page-selector/viewer-page-selector.js
@@ -16,38 +16,54 @@
      * immediately to the input field. A change to the input field is not
      * mirrored back until pageNoCommitted() is called and change-page is fired.
      */
-    pageNo: {type: Number, value: 1},
+    pageNo: {
+      type: Number,
+      value: 1,
+    },
 
     strings: Object,
   },
 
+  /** @return {!CrInputElement} */
+  get pageSelector() {
+    return this.$.pageselector;
+  },
+
   pageNoCommitted: function() {
-    var page = parseInt(this.$.input.value, 10);
+    var page = parseInt(this.pageSelector.value, 10);
 
     if (!isNaN(page) && page <= this.docLength && page > 0)
       this.fire('change-page', {page: page - 1, origin: 'pageselector'});
     else
-      this.$.input.value = this.pageNo;
-    this.$.input.blur();
+      this.pageSelector.value = this.pageNo.toString();
+    this.pageSelector.blur();
   },
 
   /** @private */
   docLengthChanged_: function() {
     var numDigits = this.docLength.toString().length;
-    this.$.pageselector.style.width = numDigits + 'ch';
+    this.pageSelector.style.width = numDigits + 'ch';
     // Set both sides of the slash to the same width, so that the layout is
     // exactly centered.
     this.$['pagelength-spacer'].style.width = numDigits + 'ch';
   },
 
   select: function() {
-    this.$.input.select();
+    this.pageSelector.inputElement.select();
   },
 
   /**
    * @return {boolean} True if the selector input field is currently focused.
    */
   isActive: function() {
-    return this.shadowRoot.activeElement == this.$.input;
-  }
+    return this.shadowRoot.activeElement == this.pageSelector;
+  },
+
+  /**
+   * Immediately remove any non-digit characters.
+   * @private
+   */
+  onInputValueChange_: function() {
+    this.pageSelector.value = this.pageSelector.value.replace(/[^\d]/, '');
+  },
 });
diff --git a/chrome/browser/resources/pdf/elements/viewer-password-screen/viewer-password-screen.html b/chrome/browser/resources/pdf/elements/viewer-password-screen/viewer-password-screen.html
index 2c040ca..5120c53 100644
--- a/chrome/browser/resources/pdf/elements/viewer-password-screen/viewer-password-screen.html
+++ b/chrome/browser/resources/pdf/elements/viewer-password-screen/viewer-password-screen.html
@@ -1,32 +1,29 @@
 <link rel="import" href="chrome://resources/html/polymer.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-input/paper-input.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html">
+
 <link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_input/cr_input.html">
 <link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html">
 <link rel="import" href="chrome://resources/cr_elements/shared_style_css.html">
+<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
 
 <dom-module id="viewer-password-screen">
   <template>
     <style include="cr-shared-style paper-button-style">
       #password {
-        --paper-input-container-focus-color: var(--google-blue-500);
-        --paper-input-container-input: {
-          font-size: inherit;
-        };
+        margin-top: var(--cr-form-field-bottom-spacing);
       }
     </style>
     <cr-dialog id="dialog" no-cancel>
       <div slot="title">[[strings.passwordDialogTitle]]</div>
       <div slot="body">
         <div id="message">[[strings.passwordPrompt]]</div>
-        <paper-input id="password"
+        <cr-input id="password"
             type="password"
             error-message="[[strings.passwordInvalid]]"
             invalid="[[invalid]]"
-            no-label-float
             autofocus>
-        </paper-input>
+        </cr-input>
       </div>
       <div slot="button-container">
         <paper-button id="submit" class="action-button" on-click="submit">
diff --git a/chrome/browser/resources/print_preview/new/header.js b/chrome/browser/resources/print_preview/new/header.js
index 2801f38..7156fb9 100644
--- a/chrome/browser/resources/print_preview/new/header.js
+++ b/chrome/browser/resources/print_preview/new/header.js
@@ -52,6 +52,9 @@
        'settings.pages.value, settings.pagesPerSheet.value, state, ' +
        'destination.id)'],
 
+  /** @private {!print_preview_new.State} */
+  lastState_: print_preview_new.State.NOT_READY,
+
   /** @private */
   onPrintClick_: function() {
     this.fire('print-requested');
@@ -140,6 +143,11 @@
         const labelInfo = this.computeLabelInfo_();
         this.summary_ = this.getSummary_(labelInfo);
         this.summaryLabel_ = this.getSummaryLabel_(labelInfo);
+        if (this.lastState_ != this.state &&
+            (document.activeElement == null ||
+             document.activeElement == document.body)) {
+          this.$$('button.print').focus();
+        }
         break;
       case (print_preview_new.State.FATAL_ERROR):
         this.printButtonEnabled_ = false;
@@ -152,6 +160,7 @@
         this.printButtonEnabled_ = false;
         break;
     }
+    this.lastState_ = this.state;
   },
 
   /**
diff --git a/chrome/browser/resources/settings/appearance_page/home_url_input.html b/chrome/browser/resources/settings/appearance_page/home_url_input.html
index a127b20..185c62a 100644
--- a/chrome/browser/resources/settings/appearance_page/home_url_input.html
+++ b/chrome/browser/resources/settings/appearance_page/home_url_input.html
@@ -25,7 +25,7 @@
     <cr-input id="input" value="{{value}}" error-message="$i18n{notValid}"
         placeholder="$i18n{enterCustomWebAddress}" maxlength="102400"
         on-change="onChange_" on-keydown="onKeydown_" on-input="validate_"
-        invalid="{{invalid}}" tab-index$="[[getTabindex_(canTab)]]"
+        invalid="{{invalid}}" tabindex="[[getTabindex_(canTab)]]"
         disabled="[[isDisabled_(disabled, pref.*)]]" spellcheck="false"
         on-keyup="stopKeyEventPropagation_"
         on-keypress="stopKeyEventPropagation_">
diff --git a/chrome/browser/resources/settings/device_page/display.html b/chrome/browser/resources/settings/device_page/display.html
index 5d1a3f8f..577ec09 100644
--- a/chrome/browser/resources/settings/device_page/display.html
+++ b/chrome/browser/resources/settings/device_page/display.html
@@ -205,7 +205,7 @@
         </div>
       </template>
 
-      <cr-link-row icon-class="subpage-arrow" class="indented hr"
+      <cr-link-row embedded icon-class="subpage-arrow" class="indented hr"
           id="overscan" label="$i18n{displayOverscanPageTitle}"
           sub-label="$i18n{displayOverscanPageText}" on-click="onOverscanTap_"
           hidden$="[[!showOverscanSetting_(selectedDisplay)]]">
@@ -216,21 +216,12 @@
           on-close="onCloseOverscanDialog_">
       </settings-display-overscan-dialog>
 
-      <div class="settings-box indented two-line"
+      <cr-link-row embedded icon-class="subpage-arrow" class="indented hr"
+          id="touchCalibration" label="$i18n{displayTouchCalibrationTitle}"
+          sub-label="$i18n{displayTouchCalibrationText}"
           on-click="onTouchCalibrationTap_"
-          hidden$="[[!showTouchCalibrationSetting_(selectedDisplay)]]"
-          actionable>
-        <div class="start">
-          $i18n{displayTouchCalibrationTitle}
-          <div class="secondary" id="touchCalibrationSecondary">
-            $i18n{displayTouchCalibrationText}
-          </div>
-        </div>
-        <paper-icon-button-light class="subpage-arrow">
-          <button aria-label="$i18n{displayTouchCalibrationTitle}"
-              aria-describedby="touchCalibrationSecondary"></button>
-        </paper-icon-button-light>
-      </div>
+          hidden$="[[!showTouchCalibrationSetting_(selectedDisplay)]]">
+      </cr-link-row>
     </div>
 
     <!-- Night Light Settings -->
diff --git a/chrome/browser/resources/settings/icons.html b/chrome/browser/resources/settings/icons.html
index c939fe6..30a4f48 100644
--- a/chrome/browser/resources/settings/icons.html
+++ b/chrome/browser/resources/settings/icons.html
@@ -78,6 +78,7 @@
 </if>
       <g id="done"><path d="M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4L9 16.2z"></path></g>
       <g id="error"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"></path></g>
+      <g id="exit-to-app"><path d="M10.09 15.59L11.5 17l5-5-5-5-1.41 1.41L12.67 11H3v2h9.67l-2.58 2.59zM19 3H5c-1.11 0-2 .9-2 2v4h2V5h14v14H5v-4H3v4c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z"></path></g>
 <if expr="chromeos">
       <g id="fingerprint"><path d="M17.81 4.47c-.08 0-.16-.02-.23-.06C15.66 3.42 14 3 12.01 3c-1.98 0-3.86.47-5.57 1.41-.24.13-.54.04-.68-.2-.13-.24-.04-.55.2-.68C7.82 2.52 9.86 2 12.01 2c2.13 0 3.99.47 6.03 1.52.25.13.34.43.21.67-.09.18-.26.28-.44.28zM3.5 9.72c-.1 0-.2-.03-.29-.09-.23-.16-.28-.47-.12-.7.99-1.4 2.25-2.5 3.75-3.27C9.98 4.04 14 4.03 17.15 5.65c1.5.77 2.76 1.86 3.75 3.25.16.22.11.54-.12.7-.23.16-.54.11-.7-.12-.9-1.26-2.04-2.25-3.39-2.94-2.87-1.47-6.54-1.47-9.4.01-1.36.7-2.5 1.7-3.4 2.96-.08.14-.23.21-.39.21zm6.25 12.07c-.13 0-.26-.05-.35-.15-.87-.87-1.34-1.43-2.01-2.64-.69-1.23-1.05-2.73-1.05-4.34 0-2.97 2.54-5.39 5.66-5.39s5.66 2.42 5.66 5.39c0 .28-.22.5-.5.5s-.5-.22-.5-.5c0-2.42-2.09-4.39-4.66-4.39-2.57 0-4.66 1.97-4.66 4.39 0 1.44.32 2.77.93 3.85.64 1.15 1.08 1.64 1.85 2.42.19.2.19.51 0 .71-.11.1-.24.15-.37.15zm7.17-1.85c-1.19 0-2.24-.3-3.1-.89-1.49-1.01-2.38-2.65-2.38-4.39 0-.28.22-.5.5-.5s.5.22.5.5c0 1.41.72 2.74 1.94 3.56.71.48 1.54.71 2.54.71.24 0 .64-.03 1.04-.1.27-.05.53.13.58.41.05.27-.13.53-.41.58-.57.11-1.07.12-1.21.12zM14.91 22c-.04 0-.09-.01-.13-.02-1.59-.44-2.63-1.03-3.72-2.1-1.4-1.39-2.17-3.24-2.17-5.22 0-1.62 1.38-2.94 3.08-2.94 1.7 0 3.08 1.32 3.08 2.94 0 1.07.93 1.94 2.08 1.94s2.08-.87 2.08-1.94c0-3.77-3.25-6.83-7.25-6.83-2.84 0-5.44 1.58-6.61 4.03-.39.81-.59 1.76-.59 2.8 0 .78.07 2.01.67 3.61.1.26-.03.55-.29.64-.26.1-.55-.04-.64-.29-.49-1.31-.73-2.61-.73-3.96 0-1.2.23-2.29.68-3.24 1.33-2.79 4.28-4.6 7.51-4.6 4.55 0 8.25 3.51 8.25 7.83 0 1.62-1.38 2.94-3.08 2.94s-3.08-1.32-3.08-2.94c0-1.07-.93-1.94-2.08-1.94s-2.08.87-2.08 1.94c0 1.71.66 3.31 1.87 4.51.95.94 1.86 1.46 3.27 1.85.27.07.42.35.35.61-.05.23-.26.38-.47.38z"></path></g>
       <g id="gamepad"><path d="M15 7.5V2H9v5.5l3 3 3-3zM7.5 9H2v6h5.5l3-3-3-3zM9 16.5V22h6v-5.5l-3-3-3 3zM16.5 9l-3 3 3 3H22V9h-5.5z"></path></g>
diff --git a/chrome/browser/resources/settings/people_page/password_prompt_dialog.js b/chrome/browser/resources/settings/people_page/password_prompt_dialog.js
index 8da743c..8831d91 100644
--- a/chrome/browser/resources/settings/people_page/password_prompt_dialog.js
+++ b/chrome/browser/resources/settings/people_page/password_prompt_dialog.js
@@ -128,8 +128,8 @@
         // Select the whole password if user entered an incorrect password.
         // Return focus to the password input if it lost focus while being
         // checked (user pressed confirm button).
-        this.$.passwordInput.inputElement.select();
         this.$.passwordInput.focus();
+        this.$.passwordInput.inputElement.select();
         return;
       }
 
diff --git a/chrome/browser/resources/settings/people_page/sync_account_control.html b/chrome/browser/resources/settings/people_page/sync_account_control.html
index a27d4a1..ec5317e 100644
--- a/chrome/browser/resources/settings/people_page/sync_account_control.html
+++ b/chrome/browser/resources/settings/people_page/sync_account_control.html
@@ -212,6 +212,11 @@
                 src="chrome://theme/IDR_PROFILE_AVATAR_PLACEHOLDER_LARGE">
             <span>$i18n{useAnotherAccount}</span>
           </button>
+          <button class="dropdown-item" on-click="onSignoutTap_" slot="item"
+              disabled="[[syncStatus.setupInProgress]]" id="sign-out-item">
+            <iron-icon icon="settings:exit-to-app"></iron-icon>
+            <span>$i18n{peopleSignOut}</span>
+          </button>
         </cr-action-menu>
       </template>
     </template>
diff --git a/chrome/browser/resources/settings/people_page/sync_account_control.js b/chrome/browser/resources/settings/people_page/sync_account_control.js
index e8f3013..4639d008 100644
--- a/chrome/browser/resources/settings/people_page/sync_account_control.js
+++ b/chrome/browser/resources/settings/people_page/sync_account_control.js
@@ -248,6 +248,12 @@
   },
 
   /** @private */
+  onSignoutTap_: function() {
+    this.syncBrowserProxy_.signOut(false /* deleteProfile */);
+    /** @type {!CrActionMenuElement} */ (this.$$('#menu')).close();
+  },
+
+  /** @private */
   onSyncButtonTap_: function() {
     assert(this.shownAccount_);
     assert(this.storedAccounts_.length > 0);
diff --git a/chrome/browser/safe_browsing/safe_browsing_navigation_observer_browsertest.cc b/chrome/browser/safe_browsing/safe_browsing_navigation_observer_browsertest.cc
index 78a53c4..b462263 100644
--- a/chrome/browser/safe_browsing/safe_browsing_navigation_observer_browsertest.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_navigation_observer_browsertest.cc
@@ -241,10 +241,13 @@
   // This function needs javascript support from the test page hosted at
   // |page_url|. It calls "clickLink(..)" javascript function to "click" on the
   // html element with ID specified by |element_id|, and waits for
-  // |number_of_navigations| to complete.
+  // |number_of_navigations| to complete.  If a |subframe_index| is specified,
+  // |element_id| is assumed to be in corresponding subframe of the test page,
+  // and the javascript function is executed that subframe.
   void ClickTestLink(const char* element_id,
                      int number_of_navigations,
-                     const GURL& page_url) {
+                     const GURL& page_url,
+                     int subframe_index = -1) {
     TabStripModel* tab_strip = browser()->tab_strip_model();
     content::WebContents* current_web_contents =
         tab_strip->GetActiveWebContents();
@@ -254,8 +257,16 @@
         content::MessageLoopRunner::QuitMode::DEFERRED);
     navigation_observer.StartWatchingNewWebContents();
     // Execute test.
-    std::string script = base::StringPrintf("clickLink('%s');", element_id);
-    ASSERT_TRUE(content::ExecuteScript(current_web_contents, script));
+    {
+      std::string script = base::StringPrintf("clickLink('%s');", element_id);
+      content::RenderFrameHost* script_executing_frame =
+          current_web_contents->GetMainFrame();
+      if (subframe_index != -1) {
+        script_executing_frame =
+            ChildFrameAt(script_executing_frame, subframe_index);
+      }
+      ASSERT_TRUE(content::ExecuteScript(script_executing_frame, script));
+    }
     // Wait for navigations on current tab and new tab (if any) to finish.
     navigation_observer.Wait();
     navigation_observer.StopWatchingNewWebContents();
@@ -1269,12 +1280,10 @@
       browser(), embedded_test_server()->GetURL(kSingleFrameTestURL));
   GURL initial_url = embedded_test_server()->GetURL(kSingleFrameTestURL);
   ClickTestLink("sub_frame_download_attribution", 1, initial_url);
-  std::string test_name =
-      base::StringPrintf("%s', '%s", "iframe1", "iframe_direct_download");
   GURL multi_frame_test_url =
       embedded_test_server()->GetURL(kMultiFrameTestURL);
   GURL iframe_url = embedded_test_server()->GetURL(kIframeDirectDownloadURL);
-  ClickTestLink(test_name.c_str(), 1, iframe_url);
+  ClickTestLink("iframe_direct_download", 1, iframe_url, 0);
   GURL iframe_retargeting_url =
       embedded_test_server()->GetURL(kIframeRetargetingURL);
   GURL download_url = embedded_test_server()->GetURL(kDownloadItemURL);
@@ -1400,14 +1409,12 @@
       browser(), embedded_test_server()->GetURL(kSingleFrameTestURL));
   GURL initial_url = embedded_test_server()->GetURL(kSingleFrameTestURL);
   ClickTestLink("sub_frame_download_attribution", 1, initial_url);
-  std::string test_name =
-      base::StringPrintf("%s', '%s", "iframe2", "iframe_new_tab_download");
   GURL multi_frame_test_url =
       embedded_test_server()->GetURL(kMultiFrameTestURL);
   GURL iframe_url = embedded_test_server()->GetURL(kIframeDirectDownloadURL);
   GURL iframe_retargeting_url =
       embedded_test_server()->GetURL(kIframeRetargetingURL);
-  ClickTestLink(test_name.c_str(), 2, iframe_retargeting_url);
+  ClickTestLink("iframe_new_tab_download", 2, iframe_retargeting_url, 1);
   GURL blank_url = GURL(url::kAboutBlankURL);
   GURL download_url = embedded_test_server()->GetURL(kDownloadItemURL);
   std::string test_server_ip(embedded_test_server()->host_port_pair().host());
diff --git a/chrome/browser/search/instant_service.cc b/chrome/browser/search/instant_service.cc
index 8c17848..d3efe22 100644
--- a/chrome/browser/search/instant_service.cc
+++ b/chrome/browser/search/instant_service.cc
@@ -15,6 +15,7 @@
 #include "chrome/browser/search/instant_service_observer.h"
 #include "chrome/browser/search/local_ntp_source.h"
 #include "chrome/browser/search/most_visited_iframe_source.h"
+#include "chrome/browser/search/ntp_icon_source.h"
 #include "chrome/browser/search/search.h"
 #include "chrome/browser/search/thumbnail_source.h"
 #include "chrome/browser/themes/theme_properties.h"
@@ -88,6 +89,7 @@
   // Set up the data sources that Instant uses on the NTP.
   content::URLDataSource::Add(profile_, new ThemeSource(profile_));
   content::URLDataSource::Add(profile_, new LocalNtpSource(profile_));
+  content::URLDataSource::Add(profile_, new NtpIconSource(profile_));
   content::URLDataSource::Add(profile_, new ThumbnailSource(profile_, false));
   content::URLDataSource::Add(profile_, new ThumbnailSource(profile_, true));
   content::URLDataSource::Add(profile_, new ThumbnailListSource(profile_));
diff --git a/chrome/browser/search/ntp_icon_source.cc b/chrome/browser/search/ntp_icon_source.cc
new file mode 100644
index 0000000..2396f5b
--- /dev/null
+++ b/chrome/browser/search/ntp_icon_source.cc
@@ -0,0 +1,247 @@
+// 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/search/ntp_icon_source.h"
+
+#include <stddef.h>
+#include <algorithm>
+#include <cmath>
+
+#include "base/callback.h"
+#include "base/memory/ref_counted_memory.h"
+#include "base/strings/string_number_conversions.h"
+#include "cc/paint/skia_paint_canvas.h"
+#include "chrome/browser/favicon/favicon_service_factory.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/search/instant_io_context.h"
+#include "chrome/common/url_constants.h"
+#include "chrome/grit/platform_locale_settings.h"
+#include "components/favicon/core/fallback_url_util.h"
+#include "components/favicon/core/favicon_service.h"
+#include "components/favicon_base/favicon_types.h"
+#include "third_party/skia/include/core/SkColor.h"
+#include "third_party/skia/include/core/SkPaint.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/webui/web_ui_util.h"
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/codec/png_codec.h"
+#include "ui/gfx/favicon_size.h"
+#include "ui/gfx/font_list.h"
+#include "ui/gfx/geometry/rect.h"
+#include "url/gurl.h"
+
+namespace {
+
+// Delimiter in the url that looks for the size specification.
+const char kSizeParameter[] = "size/";
+
+// Size of the fallback icon (letter + circle), in dp.
+const int kFallbackIconSizeDip = 40;
+
+// Used to parse the specification from the path.
+struct ParsedNtpIconPath {
+  // The URL from which the icon is being requested.
+  GURL url;
+
+  // The size of the requested icon in dip.
+  int size_in_dip = 0;
+
+  // The device scale factor of the requested icon.
+  float device_scale_factor = 1.0;
+};
+
+// Returns true if |search| is a substring of |path| which starts at
+// |start_index|.
+bool HasSubstringAt(const std::string& path,
+                    size_t start_index,
+                    const std::string& search) {
+  return path.compare(start_index, search.length(), search) == 0;
+}
+
+// Parses the path after chrome-search://ntpicon/. Example path is
+// "size/16@2x/https://cnn.com".
+const ParsedNtpIconPath ParseNtpIconPath(const std::string& path) {
+  ParsedNtpIconPath parsed;
+  parsed.url = GURL();
+  parsed.size_in_dip = gfx::kFaviconSize;
+  parsed.device_scale_factor = 1.0f;
+
+  if (path.empty())
+    return parsed;
+
+  // Size specification has to be present.
+  size_t parsed_index = 0;
+  if (!HasSubstringAt(path, parsed_index, kSizeParameter))
+    return parsed;
+
+  parsed_index += strlen(kSizeParameter);
+  size_t slash = path.find("/", parsed_index);
+  if (slash == std::string::npos)
+    return parsed;
+
+  // Parse the size spec (e.g. "16@2x")
+  size_t scale_delimiter = path.find("@", parsed_index);
+  std::string size_str =
+      path.substr(parsed_index, scale_delimiter - parsed_index);
+  std::string scale_str =
+      path.substr(scale_delimiter + 1, slash - scale_delimiter - 1);
+
+  if (!base::StringToInt(size_str, &parsed.size_in_dip))
+    return parsed;
+
+  if (!scale_str.empty())
+    webui::ParseScaleFactor(scale_str, &parsed.device_scale_factor);
+
+  parsed_index = slash + 1;
+
+  parsed.url = GURL(path.substr(parsed_index));
+  return parsed;
+}
+
+// Will paint the letter + circle in the specified |canvas|.
+void DrawFallbackIcon(const GURL& icon_url, int size, gfx::Canvas* canvas) {
+  const int kOffsetX = 0;
+  const int kOffsetY = 0;
+  cc::PaintFlags flags;
+  flags.setStyle(cc::PaintFlags::kFill_Style);
+  flags.setAntiAlias(true);
+  // Draw a filled, colored circle.
+  // TODO(crbug.com/853780): Set the appropriate background color.
+  flags.setColor(SK_ColorGRAY);
+  int corner_radius = static_cast<int>(size * 0.5 + 0.5);
+  canvas->DrawColor(SK_ColorTRANSPARENT, SkBlendMode::kSrc);
+  canvas->DrawRoundRect(gfx::Rect(kOffsetX, kOffsetY, size, size),
+                        corner_radius, flags);
+
+  // Get the appropriate letter to draw, then eventually draw it.
+  base::string16 icon_text = favicon::GetFallbackIconText(icon_url);
+  if (icon_text.empty())
+    return;
+
+  const double kDefaultFontSizeRatio = 0.44;
+  int font_size = static_cast<int>(size * kDefaultFontSizeRatio);
+  if (font_size <= 0)
+    return;
+
+  // TODO(crbug.com/853780): Adjust the text color according to the background
+  // color.
+  canvas->DrawStringRectWithFlags(
+      icon_text,
+      gfx::FontList({l10n_util::GetStringUTF8(IDS_SANS_SERIF_FONT_FAMILY)},
+                    gfx::Font::NORMAL, font_size, gfx::Font::Weight::NORMAL),
+      SK_ColorWHITE, gfx::Rect(kOffsetX, kOffsetY, size, size),
+      gfx::Canvas::TEXT_ALIGN_CENTER);
+}
+
+// For the given |icon_url|, will render a fallback icon with an appropriate
+// letter in a circle.
+std::vector<unsigned char> RenderFallbackIconBitmap(const GURL& icon_url,
+                                                    int size) {
+  const int size_to_use = std::min(64, size);
+  SkBitmap bitmap;
+  bitmap.allocN32Pixels(size_to_use, size_to_use, false);
+  cc::SkiaPaintCanvas paint_canvas(bitmap);
+  gfx::Canvas canvas(&paint_canvas, 1.f);
+  DrawFallbackIcon(icon_url, size_to_use, &canvas);
+  std::vector<unsigned char> bitmap_data;
+  bool result = gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, false, &bitmap_data);
+  DCHECK(result);
+  return bitmap_data;
+}
+
+}  // namespace
+
+struct NtpIconSource::NtpIconRequest {
+  NtpIconRequest(const content::URLDataSource::GotDataCallback& cb,
+                 const GURL& path,
+                 int size,
+                 float scale)
+      : callback(cb),
+        path(path),
+        size_in_dip(size),
+        device_scale_factor(scale) {}
+  NtpIconRequest(const NtpIconRequest& other) = default;
+  ~NtpIconRequest() {}
+
+  content::URLDataSource::GotDataCallback callback;
+  GURL path;
+  int size_in_dip;
+  float device_scale_factor;
+};
+
+NtpIconSource::NtpIconSource(Profile* profile)
+    : profile_(profile), weak_ptr_factory_(this) {}
+
+NtpIconSource::~NtpIconSource() = default;
+
+std::string NtpIconSource::GetSource() const {
+  return chrome::kChromeUINewTabIconHost;
+}
+
+void NtpIconSource::StartDataRequest(
+    const std::string& path,
+    const content::ResourceRequestInfo::WebContentsGetter& wc_getter,
+    const content::URLDataSource::GotDataCallback& callback) {
+  favicon::FaviconService* favicon_service =
+      FaviconServiceFactory::GetForProfile(profile_,
+                                           ServiceAccessType::EXPLICIT_ACCESS);
+
+  const ParsedNtpIconPath parsed = ParseNtpIconPath(path);
+
+  if (parsed.url.is_valid()) {
+    // This will query for a local favicon. If not found, will take alternative
+    // action in OnFaviconDataAvailable.
+    const bool fallback_to_host = true;
+    int desired_size_in_pixel =
+        std::ceil(parsed.size_in_dip * parsed.device_scale_factor);
+    favicon_service->GetRawFaviconForPageURL(
+        parsed.url, {favicon_base::IconType::kFavicon}, desired_size_in_pixel,
+        fallback_to_host,
+        base::Bind(&NtpIconSource::OnFaviconDataAvailable,
+                   weak_ptr_factory_.GetWeakPtr(),
+                   NtpIconRequest(callback, parsed.url, parsed.size_in_dip,
+                                  parsed.device_scale_factor)),
+        &cancelable_task_tracker_);
+  } else {
+    callback.Run(nullptr);
+  }
+}
+
+void NtpIconSource::OnFaviconDataAvailable(
+    const NtpIconRequest& request,
+    const favicon_base::FaviconRawBitmapResult& bitmap_result) {
+  if (bitmap_result.is_valid()) {
+    // Local favicon hit, return it.
+    request.callback.Run(bitmap_result.bitmap_data.get());
+  } else {
+    // Draw a fallback (letter in a circle).
+    int desired_size_in_pixel =
+        std::ceil(kFallbackIconSizeDip * request.device_scale_factor);
+    std::vector<unsigned char> bitmap_data =
+        RenderFallbackIconBitmap(request.path, desired_size_in_pixel);
+    request.callback.Run(base::RefCountedBytes::TakeVector(&bitmap_data));
+  }
+}
+
+std::string NtpIconSource::GetMimeType(const std::string&) const {
+  // NOTE: this may not always be correct for all possible types that this
+  // source will serve. Seems to work fine, however.
+  return "image/png";
+}
+
+bool NtpIconSource::AllowCaching() const {
+  return false;
+}
+
+bool NtpIconSource::ShouldServiceRequest(
+    const GURL& url,
+    content::ResourceContext* resource_context,
+    int render_process_id) const {
+  if (url.SchemeIs(chrome::kChromeSearchScheme)) {
+    return InstantIOContext::ShouldServiceRequest(url, resource_context,
+                                                  render_process_id);
+  }
+  return URLDataSource::ShouldServiceRequest(url, resource_context,
+                                             render_process_id);
+}
diff --git a/chrome/browser/search/ntp_icon_source.h b/chrome/browser/search/ntp_icon_source.h
new file mode 100644
index 0000000..f75f39b
--- /dev/null
+++ b/chrome/browser/search/ntp_icon_source.h
@@ -0,0 +1,55 @@
+// 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_SEARCH_NTP_ICON_SOURCE_H_
+#define CHROME_BROWSER_SEARCH_NTP_ICON_SOURCE_H_
+
+#include <string>
+
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "base/task/cancelable_task_tracker.h"
+#include "content/public/browser/url_data_source.h"
+
+class GURL;
+class Profile;
+
+namespace favicon_base {
+struct FaviconRawBitmapResult;
+}
+
+// NTP Icon Source is the gateway between network-level chrome: requests for
+// NTP icons and the various backends that may serve them.
+class NtpIconSource : public content::URLDataSource {
+ public:
+  explicit NtpIconSource(Profile* profile);
+  ~NtpIconSource() override;
+
+  // content::URLDataSource implementation.
+  std::string GetSource() const override;
+  void StartDataRequest(
+      const std::string& path,
+      const content::ResourceRequestInfo::WebContentsGetter& wc_getter,
+      const content::URLDataSource::GotDataCallback& callback) override;
+  std::string GetMimeType(const std::string& path) const override;
+  bool AllowCaching() const override;
+  bool ShouldServiceRequest(const GURL& url,
+                            content::ResourceContext* resource_context,
+                            int render_process_id) const override;
+
+ private:
+  struct NtpIconRequest;
+  void OnFaviconDataAvailable(
+      const NtpIconRequest& request,
+      const favicon_base::FaviconRawBitmapResult& bitmap_result);
+
+  base::CancelableTaskTracker cancelable_task_tracker_;
+  Profile* profile_;
+
+  base::WeakPtrFactory<NtpIconSource> weak_ptr_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(NtpIconSource);
+};
+
+#endif  // CHROME_BROWSER_SEARCH_NTP_ICON_SOURCE_H_
diff --git a/chrome/browser/sessions/session_restore.cc b/chrome/browser/sessions/session_restore.cc
index e9219ad..0cb1cc7d 100644
--- a/chrome/browser/sessions/session_restore.cc
+++ b/chrome/browser/sessions/session_restore.cc
@@ -45,6 +45,7 @@
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/startup/startup_browser_creator.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/browser/ui/tabs/tab_strip_model_observer.h"
 #include "chrome/common/extensions/extension_metrics.h"
 #include "chrome/common/url_constants.h"
 #include "components/keep_alive_registry/keep_alive_types.h"
@@ -61,6 +62,7 @@
 #include "content/public/browser/session_storage_namespace.h"
 #include "content/public/browser/storage_partition.h"
 #include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents_observer.h"
 #include "content/public/common/page_state.h"
 #include "extensions/browser/extension_registry.h"
 #include "extensions/common/extension_set.h"
@@ -85,6 +87,70 @@
          search::IsInstantNTP(active_tab);
 }
 
+// WebContentsDestructionChecker crashes if the WebContents that it's observing
+// gets destroyed.
+// TODO(crbug.com/850626): Remove after bug is fixed.
+class WebContentsDestructionChecker : public content::WebContentsObserver {
+ public:
+  explicit WebContentsDestructionChecker(content::WebContents* contents)
+      : WebContentsObserver(contents) {}
+  ~WebContentsDestructionChecker() override = default;
+
+  const WebContents* contents() const { return web_contents(); }
+
+  // content::WebContentsObserver:
+  void WebContentsDestroyed() override {
+    LOG(FATAL) << "Restored WebContents " << web_contents() << " destroyed";
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(WebContentsDestructionChecker);
+};
+
+// TabStripRestoreObserver watches the next WebContents that's added to a
+// TabStripModel and crashes if it's closed or detached.
+// TODO(crbug.com/850626): Remove after bug is fixed.
+class TabStripRestoreObserver : public TabStripModelObserver {
+ public:
+  explicit TabStripRestoreObserver(TabStripModel* tab_strip)
+      : tab_strip_(tab_strip) {
+    DCHECK(tab_strip_);
+    tab_strip_->AddObserver(this);
+  }
+  ~TabStripRestoreObserver() override { tab_strip_->RemoveObserver(this); }
+
+  // TabStripModelObserver:
+  void TabInsertedAt(TabStripModel* tab_strip_model,
+                     content::WebContents* contents,
+                     int index,
+                     bool foreground) override {
+    if (!destruction_checker_) {
+      destruction_checker_ =
+          std::make_unique<WebContentsDestructionChecker>(contents);
+    }
+  }
+  void TabClosingAt(TabStripModel* tab_strip_model,
+                    content::WebContents* contents,
+                    int index) override {
+    if (destruction_checker_ && contents == destruction_checker_->contents())
+      LOG(FATAL) << "Restored WebContents " << contents << " closing";
+  }
+  void TabDetachedAt(content::WebContents* contents,
+                     int previous_index,
+                     bool was_active) override {
+    if (destruction_checker_ && contents == destruction_checker_->contents())
+      LOG(FATAL) << "Restored WebContents " << contents << " detached";
+  }
+
+ private:
+  TabStripModel* tab_strip_;  // owned by caller
+
+  // Initialized after a WebContents is inserted into the strip.
+  std::unique_ptr<WebContentsDestructionChecker> destruction_checker_;
+
+  DISALLOW_COPY_AND_ASSIGN(TabStripRestoreObserver);
+};
+
 // Pointers to SessionRestoreImpls which are currently restoring the session.
 std::set<SessionRestoreImpl*>* active_session_restorers = nullptr;
 
@@ -583,6 +649,9 @@
               ->RecreateSessionStorage(tab.session_storage_persistent_id);
     }
 
+    // TODO(crbug.com/850626): Remove this after bug is fixed.
+    TabStripRestoreObserver tab_strip_observer(browser->tab_strip_model());
+
     WebContents* web_contents = chrome::AddRestoredTab(
         browser, tab.navigations, tab_index, selected_index,
         tab.extension_app_id, is_selected_tab, tab.pinned, true,
@@ -607,8 +676,6 @@
 
     ShowBrowser(browser, browser->tab_strip_model()->GetIndexOfWebContents(
                              web_contents));
-    // TODO(sky): remove. For debugging 368236.
-    CHECK_EQ(browser->tab_strip_model()->GetActiveWebContents(), web_contents);
   }
 
   Browser* CreateRestoredBrowser(Browser::Type type,
@@ -641,8 +708,6 @@
     browser->window()->Show();
     browser->set_is_session_restore(false);
 
-    // TODO(jcampan): http://crbug.com/8123 we should not need to set the
-    //                initial focus explicitly.
     browser->tab_strip_model()->GetActiveWebContents()->SetInitialFocus();
   }
 
diff --git a/chrome/browser/signin/chrome_signin_client.cc b/chrome/browser/signin/chrome_signin_client.cc
index 1e55772b..40b57fd4 100644
--- a/chrome/browser/signin/chrome_signin_client.cc
+++ b/chrome/browser/signin/chrome_signin_client.cc
@@ -45,6 +45,7 @@
 #include "components/signin/core/browser/signin_header_helper.h"
 #include "components/signin/core/browser/signin_pref_names.h"
 #include "components/signin/core/browser/signin_switches.h"
+#include "content/public/browser/browser_context.h"
 #include "content/public/browser/storage_partition.h"
 #include "google_apis/gaia/gaia_constants.h"
 #include "google_apis/gaia/gaia_urls.h"
@@ -206,6 +207,9 @@
 
 scoped_refptr<network::SharedURLLoaderFactory>
 ChromeSigninClient::GetURLLoaderFactory() {
+  if (url_loader_factory_for_testing_)
+    return url_loader_factory_for_testing_;
+
   return content::BrowserContext::GetDefaultStoragePartition(profile_)
       ->GetURLLoaderFactoryForBrowserProcess();
 }
@@ -478,6 +482,11 @@
 #endif
 }
 
+void ChromeSigninClient::SetURLLoaderFactoryForTest(
+    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) {
+  url_loader_factory_for_testing_ = url_loader_factory;
+}
+
 void ChromeSigninClient::OnCloseBrowsersSuccess(
     const base::Callback<void()>& sign_out,
     const signin_metrics::ProfileSignout signout_source_metric,
diff --git a/chrome/browser/signin/chrome_signin_client.h b/chrome/browser/signin/chrome_signin_client.h
index d2ea062..b11f238 100644
--- a/chrome/browser/signin/chrome_signin_client.h
+++ b/chrome/browser/signin/chrome_signin_client.h
@@ -15,6 +15,7 @@
 #include "google_apis/gaia/gaia_oauth_client.h"
 #include "google_apis/gaia/oauth2_token_service.h"
 #include "net/cookies/cookie_change_dispatcher.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
 #include "services/network/public/mojom/network_change_manager.mojom.h"
 
 #if !defined(OS_CHROMEOS)
@@ -109,6 +110,11 @@
   void AfterCredentialsCopied() override;
   void SetReadyForDiceMigration(bool is_ready) override;
 
+  // Used in tests to override the URLLoaderFactory returned by
+  // GetURLLoaderFactory().
+  void SetURLLoaderFactoryForTest(
+      scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory);
+
  protected:
   virtual void ShowUserManager(const base::FilePath& profile_path);
   virtual void LockForceSigninProfile(const base::FilePath& profile_path);
@@ -137,6 +143,9 @@
   std::unique_ptr<gaia::GaiaOAuthClient> oauth_client_;
   std::unique_ptr<OAuth2TokenService::Request> oauth_request_;
 
+  scoped_refptr<network::SharedURLLoaderFactory>
+      url_loader_factory_for_testing_;
+
   base::WeakPtrFactory<ChromeSigninClient> weak_ptr_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(ChromeSigninClient);
diff --git a/chrome/browser/signin/mutable_profile_oauth2_token_service_delegate.cc b/chrome/browser/signin/mutable_profile_oauth2_token_service_delegate.cc
index 55c0fb6..066bd8b 100644
--- a/chrome/browser/signin/mutable_profile_oauth2_token_service_delegate.cc
+++ b/chrome/browser/signin/mutable_profile_oauth2_token_service_delegate.cc
@@ -26,6 +26,7 @@
 #include "google_apis/gaia/oauth2_access_token_fetcher_immediate_error.h"
 #include "google_apis/gaia/oauth2_access_token_fetcher_impl.h"
 #include "net/url_request/url_request_context_getter.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
 
 namespace {
 
@@ -376,6 +377,7 @@
 MutableProfileOAuth2TokenServiceDelegate::CreateAccessTokenFetcher(
     const std::string& account_id,
     net::URLRequestContextGetter* getter,
+    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
     OAuth2AccessTokenConsumer* consumer) {
   ValidateAccountId(account_id);
   // check whether the account has persistent error.
@@ -392,7 +394,8 @@
   }
   std::string refresh_token = GetRefreshToken(account_id);
   DCHECK(!refresh_token.empty());
-  return new OAuth2AccessTokenFetcherImpl(consumer, getter, refresh_token);
+  return new OAuth2AccessTokenFetcherImpl(consumer, url_loader_factory,
+                                          refresh_token);
 }
 
 GoogleServiceAuthError MutableProfileOAuth2TokenServiceDelegate::GetAuthError(
@@ -467,6 +470,11 @@
   return client_->GetURLRequestContext();
 }
 
+scoped_refptr<network::SharedURLLoaderFactory>
+MutableProfileOAuth2TokenServiceDelegate::GetURLLoaderFactory() const {
+  return client_->GetURLLoaderFactory();
+}
+
 OAuth2TokenServiceDelegate::LoadCredentialsState
 MutableProfileOAuth2TokenServiceDelegate::GetLoadCredentialsState() const {
   return load_credentials_state_;
diff --git a/chrome/browser/signin/mutable_profile_oauth2_token_service_delegate.h b/chrome/browser/signin/mutable_profile_oauth2_token_service_delegate.h
index c739353..7037b09 100644
--- a/chrome/browser/signin/mutable_profile_oauth2_token_service_delegate.h
+++ b/chrome/browser/signin/mutable_profile_oauth2_token_service_delegate.h
@@ -44,6 +44,7 @@
   OAuth2AccessTokenFetcher* CreateAccessTokenFetcher(
       const std::string& account_id,
       net::URLRequestContextGetter* getter,
+      scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
       OAuth2AccessTokenConsumer* consumer) override;
 
   // Updates the internal cache of the result from the most-recently-completed
@@ -56,6 +57,8 @@
       const std::string& account_id) const override;
   std::vector<std::string> GetAccounts() override;
   net::URLRequestContextGetter* GetRequestContext() const override;
+  scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory()
+      const override;
 
   void LoadCredentials(const std::string& primary_account_id) override;
   void UpdateCredentials(const std::string& account_id,
diff --git a/chrome/browser/signin/mutable_profile_oauth2_token_service_delegate_unittest.cc b/chrome/browser/signin/mutable_profile_oauth2_token_service_delegate_unittest.cc
index 7c185085..2c0399c 100644
--- a/chrome/browser/signin/mutable_profile_oauth2_token_service_delegate_unittest.cc
+++ b/chrome/browser/signin/mutable_profile_oauth2_token_service_delegate_unittest.cc
@@ -34,6 +34,7 @@
 #include "google_apis/gaia/oauth2_token_service_test_util.h"
 #include "net/http/http_status_code.h"
 #include "net/url_request/test_url_fetcher_factory.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 // Defining constant here to handle backward compatiblity tests, but this
@@ -105,6 +106,8 @@
     client_.reset(new TestSigninClient(&pref_service_));
     client_->SetURLRequestContext(new net::TestURLRequestContextGetter(
         base::ThreadTaskRunnerHandle::Get()));
+    client_->test_url_loader_factory()->AddResponse(
+        GaiaUrls::GetInstance()->oauth2_revoke_url().spec(), "");
     client_->LoadTokenDatabase();
     account_tracker_service_.Initialize(client_.get());
   }
@@ -115,6 +118,12 @@
     OSCryptMocker::TearDown();
   }
 
+  void AddSuccessfulOAuhTokenResponse() {
+    client_->test_url_loader_factory()->AddResponse(
+        GaiaUrls::GetInstance()->oauth2_token_url().spec(),
+        GetValidTokenResponse("token", 3600));
+  }
+
   void CreateOAuth2ServiceDelegate(
       signin::AccountConsistencyMethod account_consistency) {
     oauth2_service_delegate_.reset(new MutableProfileOAuth2TokenServiceDelegate(
@@ -853,9 +862,7 @@
             oauth2_service_delegate_->GetAuthError(kEmail));
 
   // Create a "success" fetch we don't expect to get called.
-  factory_.SetFakeResponse(GaiaUrls::GetInstance()->oauth2_token_url(),
-                           GetValidTokenResponse("token", 3600), net::HTTP_OK,
-                           net::URLRequestStatus::SUCCESS);
+  AddSuccessfulOAuhTokenResponse();
 
   EXPECT_EQ(0, access_token_success_count_);
   EXPECT_EQ(0, access_token_failure_count_);
@@ -863,7 +870,8 @@
   scope_list.push_back("scope");
   std::unique_ptr<OAuth2AccessTokenFetcher> fetcher(
       oauth2_service_delegate_->CreateAccessTokenFetcher(
-          kEmail, oauth2_service_delegate_->GetRequestContext(), this));
+          kEmail, oauth2_service_delegate_->GetRequestContext(),
+          oauth2_service_delegate_->GetURLLoaderFactory(), this));
   fetcher->Start("foo", "bar", scope_list);
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(0, access_token_success_count_);
@@ -886,9 +894,7 @@
             oauth2_service_delegate_->GetAuthError(kEmail));
 
   // Create a "success" fetch we don't expect to get called just yet.
-  factory_.SetFakeResponse(GaiaUrls::GetInstance()->oauth2_token_url(),
-                           GetValidTokenResponse("token", 3600), net::HTTP_OK,
-                           net::URLRequestStatus::SUCCESS);
+  AddSuccessfulOAuhTokenResponse();
 
   // Transient error will repeat until backoff period expires.
   EXPECT_EQ(0, access_token_success_count_);
@@ -897,7 +903,8 @@
   scope_list.push_back("scope");
   std::unique_ptr<OAuth2AccessTokenFetcher> fetcher1(
       oauth2_service_delegate_->CreateAccessTokenFetcher(
-          kEmail, oauth2_service_delegate_->GetRequestContext(), this));
+          kEmail, oauth2_service_delegate_->GetRequestContext(),
+          oauth2_service_delegate_->GetURLLoaderFactory(), this));
   fetcher1->Start("foo", "bar", scope_list);
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(0, access_token_success_count_);
@@ -911,7 +918,8 @@
       base::TimeTicks());
   std::unique_ptr<OAuth2AccessTokenFetcher> fetcher2(
       oauth2_service_delegate_->CreateAccessTokenFetcher(
-          kEmail, oauth2_service_delegate_->GetRequestContext(), this));
+          kEmail, oauth2_service_delegate_->GetRequestContext(),
+          oauth2_service_delegate_->GetURLLoaderFactory(), this));
   fetcher2->Start("foo", "bar", scope_list);
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(1, access_token_success_count_);
@@ -934,9 +942,7 @@
             oauth2_service_delegate_->GetAuthError(kEmail));
 
   // Create a "success" fetch we don't expect to get called just yet.
-  factory_.SetFakeResponse(GaiaUrls::GetInstance()->oauth2_token_url(),
-                           GetValidTokenResponse("token", 3600), net::HTTP_OK,
-                           net::URLRequestStatus::SUCCESS);
+  AddSuccessfulOAuhTokenResponse();
 
   // Transient error will repeat until backoff period expires.
   EXPECT_EQ(0, access_token_success_count_);
@@ -945,7 +951,8 @@
   scope_list.push_back("scope");
   std::unique_ptr<OAuth2AccessTokenFetcher> fetcher1(
       oauth2_service_delegate_->CreateAccessTokenFetcher(
-          kEmail, oauth2_service_delegate_->GetRequestContext(), this));
+          kEmail, oauth2_service_delegate_->GetRequestContext(),
+          oauth2_service_delegate_->GetURLLoaderFactory(), this));
   fetcher1->Start("foo", "bar", scope_list);
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(0, access_token_success_count_);
@@ -956,7 +963,8 @@
       net::NetworkChangeNotifier::CONNECTION_WIFI);
   std::unique_ptr<OAuth2AccessTokenFetcher> fetcher2(
       oauth2_service_delegate_->CreateAccessTokenFetcher(
-          kEmail, oauth2_service_delegate_->GetRequestContext(), this));
+          kEmail, oauth2_service_delegate_->GetRequestContext(),
+          oauth2_service_delegate_->GetURLLoaderFactory(), this));
   fetcher2->Start("foo", "bar", scope_list);
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(1, access_token_success_count_);
diff --git a/chrome/browser/signin/oauth2_token_service_delegate_android.cc b/chrome/browser/signin/oauth2_token_service_delegate_android.cc
index 13815e7..992b64f 100644
--- a/chrome/browser/signin/oauth2_token_service_delegate_android.cc
+++ b/chrome/browser/signin/oauth2_token_service_delegate_android.cc
@@ -261,6 +261,7 @@
 OAuth2TokenServiceDelegateAndroid::CreateAccessTokenFetcher(
     const std::string& account_id,
     net::URLRequestContextGetter* getter,
+    scoped_refptr<network::SharedURLLoaderFactory> url_factory,
     OAuth2AccessTokenConsumer* consumer) {
   DVLOG(1) << "OAuth2TokenServiceDelegateAndroid::CreateAccessTokenFetcher"
            << " account= " << account_id;
diff --git a/chrome/browser/signin/oauth2_token_service_delegate_android.h b/chrome/browser/signin/oauth2_token_service_delegate_android.h
index b4f78f85..5dd1f08 100644
--- a/chrome/browser/signin/oauth2_token_service_delegate_android.h
+++ b/chrome/browser/signin/oauth2_token_service_delegate_android.h
@@ -99,6 +99,7 @@
   OAuth2AccessTokenFetcher* CreateAccessTokenFetcher(
       const std::string& account_id,
       net::URLRequestContextGetter* getter,
+      scoped_refptr<network::SharedURLLoaderFactory> url_factory,
       OAuth2AccessTokenConsumer* consumer) override;
 
   // Overridden from OAuth2TokenService to intercept token fetch requests and
diff --git a/chrome/browser/spellchecker/spellcheck_service.cc b/chrome/browser/spellchecker/spellcheck_service.cc
index 3112644..e80f87b 100644
--- a/chrome/browser/spellchecker/spellcheck_service.cc
+++ b/chrome/browser/spellchecker/spellcheck_service.cc
@@ -283,14 +283,14 @@
     const SpellcheckCustomDictionary::Change& change) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
-  auto process_hosts(content::RenderProcessHost::AllHostsIterator());
-
   const std::vector<std::string> additions(change.to_add().begin(),
                                            change.to_add().end());
   const std::vector<std::string> deletions(change.to_remove().begin(),
                                            change.to_remove().end());
-  while (!process_hosts.IsAtEnd()) {
-    content::RenderProcessHost* process = process_hosts.GetCurrentValue();
+  for (content::RenderProcessHost::iterator it(
+           content::RenderProcessHost::AllHostsIterator());
+       !it.IsAtEnd(); it.Advance()) {
+    content::RenderProcessHost* process = it.GetCurrentValue();
     if (!process->IsInitializedAndNotDead())
       continue;
 
@@ -302,7 +302,6 @@
                                   renderer_identity.instance()),
         &spellchecker);
     spellchecker->CustomDictionaryChanged(additions, deletions);
-    process_hosts.Advance();
   }
 }
 
diff --git a/chrome/browser/spellchecker/spellcheck_service_browsertest.cc b/chrome/browser/spellchecker/spellcheck_service_browsertest.cc
index 707860b..6e14c7d 100644
--- a/chrome/browser/spellchecker/spellcheck_service_browsertest.cc
+++ b/chrome/browser/spellchecker/spellcheck_service_browsertest.cc
@@ -33,6 +33,7 @@
 #include "components/spellcheck/common/spellcheck_common.h"
 #include "components/spellcheck/common/spellcheck_result.h"
 #include "components/user_prefs/user_prefs.h"
+#include "content/public/test/browser_test_utils.h"
 #include "content/public/test/mock_render_process_host.h"
 #include "content/public/test/test_utils.h"
 #include "mojo/public/cpp/bindings/binding.h"
@@ -386,6 +387,28 @@
   EXPECT_TRUE(GetCustomDictionaryChangedState());
 }
 
+// Regression test for https://crbug.com/854540.
+IN_PROC_BROWSER_TEST_F(SpellcheckServiceBrowserTest,
+                       CustomDictionaryChangedAfterRendererCrash) {
+  InitSpellcheck(true, "en-US", "");
+  EXPECT_TRUE(GetEnableSpellcheckState());
+
+  // Kill the renderer process.
+  content::RenderProcessHost* process = browser()
+                                            ->tab_strip_model()
+                                            ->GetActiveWebContents()
+                                            ->GetMainFrame()
+                                            ->GetProcess();
+  content::RenderProcessHostWatcher crash_observer(
+      process, content::RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
+  EXPECT_TRUE(process->Shutdown(0));
+  crash_observer.Wait();
+
+  // Change the custom dictionary - the test passes if there were no crashes or
+  // hangs.
+  ChangeCustomDictionary();
+}
+
 // Starting with only a single-language spellcheck setting, the host should
 // initialize the renderer's spellcheck system, and the same if the renderer
 // explicity requests the spellcheck dictionaries.
diff --git a/chrome/browser/sync/test/integration/sync_auth_test.cc b/chrome/browser/sync/test/integration/sync_auth_test.cc
index d234fa3..bd243ec 100644
--- a/chrome/browser/sync/test/integration/sync_auth_test.cc
+++ b/chrome/browser/sync/test/integration/sync_auth_test.cc
@@ -21,32 +21,32 @@
 
 using bookmarks_helper::AddURL;
 
-const char kShortLivedOAuth2Token[] =
-    "{"
-    "  \"refresh_token\": \"short_lived_refresh_token\","
-    "  \"access_token\": \"short_lived_access_token\","
-    "  \"expires_in\": 5,"  // 5 seconds.
-    "  \"token_type\": \"Bearer\""
-    "}";
+constexpr char kShortLivedOAuth2Token[] = R"(
+    {
+      "refresh_token": "short_lived_refresh_token",
+      "access_token": "short_lived_access_token",
+      "expires_in": 5,  // 5 seconds.
+      "token_type": "Bearer"
+    })";
 
-const char kValidOAuth2Token[] = "{"
-                                 "  \"refresh_token\": \"new_refresh_token\","
-                                 "  \"access_token\": \"new_access_token\","
-                                 "  \"expires_in\": 3600,"  // 1 hour.
-                                 "  \"token_type\": \"Bearer\""
-                                 "}";
+constexpr char kValidOAuth2Token[] = R"({
+                                   "refresh_token": "new_refresh_token",
+                                   "access_token": "new_access_token",
+                                   "expires_in": 3600,  // 1 hour.
+                                   "token_type": "Bearer"
+                                 })";
 
-const char kInvalidGrantOAuth2Token[] = "{"
-                                        "  \"error\": \"invalid_grant\""
-                                        "}";
+constexpr char kInvalidGrantOAuth2Token[] = R"({
+                                           "error": "invalid_grant"
+                                        })";
 
-const char kInvalidClientOAuth2Token[] = "{"
-                                         "  \"error\": \"invalid_client\""
-                                         "}";
+constexpr char kInvalidClientOAuth2Token[] = R"({
+                                           "error": "invalid_client"
+                                         })";
 
-const char kEmptyOAuth2Token[] = "";
+constexpr char kEmptyOAuth2Token[] = "";
 
-const char kMalformedOAuth2Token[] = "{ \"foo\": ";
+constexpr char kMalformedOAuth2Token[] = R"({ "foo": )";
 
 // Waits until local changes are committed or an auth error is encountered.
 class TestForAuthError : public UpdatedProgressMarkerChecker {
@@ -106,7 +106,6 @@
         set_max_authorization_token_fetch_retries_for_testing(0);
   }
 
-
  private:
   int GetNextBookmarkIndex() {
     return bookmark_index_++;
diff --git a/chrome/browser/sync/test/integration/sync_test.cc b/chrome/browser/sync/test/integration/sync_test.cc
index d0ba2b5..4a05d96a 100644
--- a/chrome/browser/sync/test/integration/sync_test.cc
+++ b/chrome/browser/sync/test/integration/sync_test.cc
@@ -39,6 +39,7 @@
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/profiles/profiles_state.h"
 #include "chrome/browser/search_engines/template_url_service_factory.h"
+#include "chrome/browser/signin/chrome_signin_client_factory.h"
 #include "chrome/browser/sync/profile_sync_service_factory.h"
 #include "chrome/browser/sync/test/integration/fake_server_invalidation_service.h"
 #include "chrome/browser/sync/test/integration/p2p_invalidation_forwarder.h"
@@ -87,9 +88,9 @@
 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
 #include "net/url_request/test_url_fetcher_factory.h"
 #include "net/url_request/url_fetcher.h"
-#include "net/url_request/url_fetcher_delegate.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 #include "services/network/public/cpp/simple_url_loader.h"
+#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
 #include "url/gurl.h"
 
 #if defined(OS_CHROMEOS)
@@ -198,7 +199,10 @@
       previous_profile_(nullptr),
       num_clients_(-1),
       use_verifier_(true),
-      create_gaia_account_at_runtime_(false) {
+      create_gaia_account_at_runtime_(false),
+      test_shared_url_loader_factory_(
+          base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
+              &test_url_loader_factory_)) {
   sync_datatype_helper::AssociateWithTest(this);
   switch (test_type_) {
     case SINGLE_CLIENT:
@@ -274,6 +278,7 @@
   // Return OSCrypt to its real behaviour
   OSCryptMocker::TearDown();
 
+  test_shared_url_loader_factory_->Detach();
   fake_server_.reset();
 }
 
@@ -359,7 +364,10 @@
     profile_delegates_[index] =
         std::make_unique<SyncProfileDelegate>(base::Bind(
             &SyncTest::InitializeProfile, base::Unretained(this), index));
-    MakeTestProfile(profile_path, index);
+    Profile* profile = MakeTestProfile(profile_path, index);
+    ChromeSigninClient* signin_client = static_cast<ChromeSigninClient*>(
+        ChromeSigninClientFactory::GetForProfile(profile));
+    signin_client->SetURLLoaderFactoryForTest(test_shared_url_loader_factory_);
   }
 
   // Once profile initialization has kicked off, wait for it to finish.
@@ -624,6 +632,12 @@
   fake_server_->RemoveObserver(fake_server_invalidation_services_[index]);
 }
 
+void SyncTest::SetupMockGaiaResponsesForProfile(Profile* profile) {
+  ChromeSigninClient* signin_client = static_cast<ChromeSigninClient*>(
+      ChromeSigninClientFactory::GetForProfile(profile));
+  signin_client->SetURLLoaderFactoryForTest(test_shared_url_loader_factory_);
+}
+
 void SyncTest::InitializeInvalidations(int index) {
   configuration_refresher_ = std::make_unique<ConfigurationRefresher>();
   if (UsingExternalServers()) {
@@ -798,6 +812,9 @@
 }
 
 void SyncTest::SetUpOnMainThread() {
+  if (!UsingExternalServers())
+    SetupMockGaiaResponsesForProfile(ProfileManager::GetActiveUserProfile());
+
   // Allows google.com as well as country-specific TLDs.
   host_resolver()->AllowDirectLookup("*.google.com");
   host_resolver()->AllowDirectLookup("accounts.google.*");
@@ -845,74 +862,55 @@
 }
 
 void SyncTest::SetupMockGaiaResponses() {
-  factory_ = std::make_unique<net::URLFetcherImplFactory>();
-  fake_factory_ = std::make_unique<net::FakeURLFetcherFactory>(factory_.get());
-  fake_factory_->SetFakeResponse(
-      GaiaUrls::GetInstance()->get_user_info_url(),
-      "email=user@gmail.com\ndisplayEmail=user@gmail.com",
-      net::HTTP_OK,
-      net::URLRequestStatus::SUCCESS);
-  fake_factory_->SetFakeResponse(
-      GaiaUrls::GetInstance()->issue_auth_token_url(),
-      "auth",
-      net::HTTP_OK,
-      net::URLRequestStatus::SUCCESS);
-  fake_factory_->SetFakeResponse(
-      GURL(GoogleURLTracker::kSearchDomainCheckURL),
-      ".google.com",
-      net::HTTP_OK,
-      net::URLRequestStatus::SUCCESS);
-  fake_factory_->SetFakeResponse(
-      GaiaUrls::GetInstance()->deprecated_client_login_to_oauth2_url(),
-      "some_response", net::HTTP_OK, net::URLRequestStatus::SUCCESS);
-  fake_factory_->SetFakeResponse(
-      GaiaUrls::GetInstance()->oauth2_token_url(),
-      "{"
-      "  \"refresh_token\": \"rt1\","
-      "  \"access_token\": \"at1\","
-      "  \"expires_in\": 3600,"
-      "  \"token_type\": \"Bearer\""
-      "}",
-      net::HTTP_OK,
-      net::URLRequestStatus::SUCCESS);
-  fake_factory_->SetFakeResponse(
-      GaiaUrls::GetInstance()->oauth_user_info_url(),
-      "{"
-      "  \"id\": \"12345\""
-      "}",
-      net::HTTP_OK,
-      net::URLRequestStatus::SUCCESS);
-  fake_factory_->SetFakeResponse(
-      GaiaUrls::GetInstance()->oauth1_login_url(),
-      "SID=sid\nLSID=lsid\nAuth=auth_token",
-      net::HTTP_OK,
-      net::URLRequestStatus::SUCCESS);
-  fake_factory_->SetFakeResponse(
-      GaiaUrls::GetInstance()->oauth2_revoke_url(),
-      "",
-      net::HTTP_OK,
-      net::URLRequestStatus::SUCCESS);
+  test_url_loader_factory_.AddResponse(
+      GaiaUrls::GetInstance()->get_user_info_url().spec(),
+      "email=user@gmail.com\ndisplayEmail=user@gmail.com");
+  test_url_loader_factory_.AddResponse(
+      GaiaUrls::GetInstance()->issue_auth_token_url().spec(), "auth");
+  test_url_loader_factory_.AddResponse(GoogleURLTracker::kSearchDomainCheckURL,
+                                       ".google.com");
+  test_url_loader_factory_.AddResponse(
+      GaiaUrls::GetInstance()->deprecated_client_login_to_oauth2_url().spec(),
+      "some_response");
+
+  test_url_loader_factory_.AddResponse(
+      GaiaUrls::GetInstance()->oauth2_token_url().spec(),
+      R"({
+            "refresh_token": "rt1",
+            "access_token": "at1",
+            "expires_in": 3600,
+            "token_type": "Bearer"
+         })");
+  test_url_loader_factory_.AddResponse(
+      GaiaUrls::GetInstance()->oauth_user_info_url().spec(),
+      "{ \"id\": \"12345\" }");
+  test_url_loader_factory_.AddResponse(
+      GaiaUrls::GetInstance()->oauth1_login_url().spec(),
+      "SID=sid\nLSID=lsid\nAuth=auth_token");
+  test_url_loader_factory_.AddResponse(
+      GaiaUrls::GetInstance()->oauth2_revoke_url().spec(), "");
 }
 
 void SyncTest::SetOAuth2TokenResponse(const std::string& response_data,
-                                      net::HttpStatusCode response_code,
+                                      net::HttpStatusCode status_code,
                                       net::URLRequestStatus::Status status) {
-  ASSERT_NE(nullptr, fake_factory_.get());
-  fake_factory_->SetFakeResponse(GaiaUrls::GetInstance()->oauth2_token_url(),
-                                 response_data, response_code, status);
+  network::URLLoaderCompletionStatus completion_status(status);
+  completion_status.decoded_body_length = response_data.size();
+
+  std::string response = base::StringPrintf("HTTP/1.1 %d %s\r\n", status_code,
+                                            GetHttpReasonPhrase(status_code));
+  network::ResourceResponseHead resource_response;
+  resource_response.headers =
+      base::MakeRefCounted<net::HttpResponseHeaders>(response);
+  test_url_loader_factory_.AddResponse(
+      GaiaUrls::GetInstance()->oauth2_token_url(), resource_response,
+      response_data, completion_status);
+  base::RunLoop().RunUntilIdle();
 }
 
 void SyncTest::ClearMockGaiaResponses() {
   // Clear any mock gaia responses that might have been set.
-  if (fake_factory_) {
-    fake_factory_->ClearFakeResponses();
-    fake_factory_.reset();
-  }
-
-  // Cancel any outstanding URL fetches and destroy the URLFetcherImplFactory we
-  // created.
-  net::URLFetcher::CancelAll();
-  factory_.reset();
+  test_url_loader_factory_.ClearResponses();
 }
 
 void SyncTest::DecideServerType() {
diff --git a/chrome/browser/sync/test/integration/sync_test.h b/chrome/browser/sync/test/integration/sync_test.h
index ea88d95..c3d32bb 100644
--- a/chrome/browser/sync/test/integration/sync_test.h
+++ b/chrome/browser/sync/test/integration/sync_test.h
@@ -25,6 +25,7 @@
 #include "components/sync/test/local_sync_test_server.h"
 #include "net/http/http_status_code.h"
 #include "net/url_request/url_request_status.h"
+#include "services/network/test/test_url_loader_factory.h"
 
 #if BUILDFLAG(ENABLE_APP_LIST)
 #include "chrome/browser/ui/app_list/app_list_syncable_service.h"
@@ -73,6 +74,10 @@
 class URLFetcherImplFactory;
 }  // namespace net
 
+namespace network {
+class WeakWrapperSharedURLLoaderFactory;
+}  // namespace network
+
 // This is the base class for integration tests for all sync data types. Derived
 // classes must be defined for each sync data type. Individual tests are defined
 // using the IN_PROC_BROWSER_TEST_F macro.
@@ -287,6 +292,11 @@
   // Stops notificatinos being sent to a client.
   void DisableNotificationsForClient(int index);
 
+  // Sets up fake responses for kClientLoginUrl, kIssueAuthTokenUrl,
+  // kGetUserInfoUrl and kSearchDomainCheckUrl in order to mock out calls to
+  // GAIA servers.
+  void SetupMockGaiaResponsesForProfile(Profile* profile);
+
   base::test::ScopedFeatureList feature_list_;
 
   // GAIA account used by the test case.
@@ -463,6 +473,13 @@
   // Used to start and stop the local test server.
   base::Process test_server_;
 
+  // The factory used to mock out GAIA signin.
+  network::TestURLLoaderFactory test_url_loader_factory_;
+
+  // The shared URLLoaderFactory backed by |test_url_loader_factory_|.
+  scoped_refptr<network::WeakWrapperSharedURLLoaderFactory>
+      test_shared_url_loader_factory_;
+
   // Fake URLFetcher factory used to mock out GAIA signin.
   std::unique_ptr<net::FakeURLFetcherFactory> fake_factory_;
 
diff --git a/chrome/browser/sync_file_system/drive_backend/drive_backend_sync_unittest.cc b/chrome/browser/sync_file_system/drive_backend/drive_backend_sync_unittest.cc
index 7ccd355f..c499d7ee 100644
--- a/chrome/browser/sync_file_system/drive_backend/drive_backend_sync_unittest.cc
+++ b/chrome/browser/sync_file_system/drive_backend/drive_backend_sync_unittest.cc
@@ -124,6 +124,7 @@
         nullptr,  // signin_manager
         nullptr,  // token_service
         nullptr,  // request_context
+        nullptr,  // url_loader_factory
         nullptr,  // drive_service
         in_memory_env_.get()));
     remote_sync_service_->AddServiceObserver(this);
diff --git a/chrome/browser/sync_file_system/drive_backend/sync_engine.cc b/chrome/browser/sync_file_system/drive_backend/sync_engine.cc
index 1ad7d997..a7cd7751 100644
--- a/chrome/browser/sync_file_system/drive_backend/sync_engine.cc
+++ b/chrome/browser/sync_file_system/drive_backend/sync_engine.cc
@@ -98,10 +98,12 @@
 SyncEngine::DriveServiceFactory::CreateDriveService(
     OAuth2TokenService* oauth2_token_service,
     net::URLRequestContextGetter* url_request_context_getter,
+    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
     base::SequencedTaskRunner* blocking_task_runner) {
   return std::unique_ptr<
       drive::DriveServiceInterface>(new drive::DriveAPIService(
-      oauth2_token_service, url_request_context_getter, blocking_task_runner,
+      oauth2_token_service, url_request_context_getter, url_loader_factory,
+      blocking_task_runner,
       GURL(google_apis::DriveApiUrlGenerator::kBaseUrlForProduction),
       GURL(google_apis::DriveApiUrlGenerator::kBaseThumbnailUrlForProduction),
       std::string(), /* custom_user_agent */
@@ -218,13 +220,16 @@
   scoped_refptr<net::URLRequestContextGetter> request_context =
       content::BrowserContext::GetDefaultStoragePartition(context)->
             GetURLRequestContext();
+  scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory =
+      content::BrowserContext::GetDefaultStoragePartition(context)
+          ->GetURLLoaderFactoryForBrowserProcess();
 
   std::unique_ptr<drive_backend::SyncEngine> sync_engine(new SyncEngine(
       ui_task_runner.get(), worker_task_runner.get(), drive_task_runner.get(),
       GetSyncFileSystemDir(context->GetPath()), task_logger,
       notification_manager, extension_service, signin_manager, token_service,
-      request_context.get(), std::make_unique<DriveServiceFactory>(),
-      nullptr /* env_override */));
+      request_context.get(), url_loader_factory,
+      std::make_unique<DriveServiceFactory>(), nullptr /* env_override */));
 
   sync_engine->Initialize();
   return sync_engine;
@@ -277,7 +282,8 @@
   DCHECK(drive_service_factory_);
   std::unique_ptr<drive::DriveServiceInterface> drive_service =
       drive_service_factory_->CreateDriveService(
-          token_service_, request_context_.get(), drive_task_runner_.get());
+          token_service_, request_context_.get(), url_loader_factory_,
+          drive_task_runner_.get());
 
   device::mojom::WakeLockProviderPtr wake_lock_provider(nullptr);
   DCHECK(content::ServiceManagerConnection::GetForProcess());
@@ -725,6 +731,7 @@
     SigninManagerBase* signin_manager,
     OAuth2TokenService* token_service,
     net::URLRequestContextGetter* request_context,
+    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
     std::unique_ptr<DriveServiceFactory> drive_service_factory,
     leveldb::Env* env_override)
     : ui_task_runner_(ui_task_runner),
@@ -737,6 +744,7 @@
       signin_manager_(signin_manager),
       token_service_(token_service),
       request_context_(request_context),
+      url_loader_factory_(url_loader_factory),
       drive_service_factory_(std::move(drive_service_factory)),
       remote_change_processor_(nullptr),
       service_state_(REMOTE_SERVICE_TEMPORARY_UNAVAILABLE),
diff --git a/chrome/browser/sync_file_system/drive_backend/sync_engine.h b/chrome/browser/sync_file_system/drive_backend/sync_engine.h
index 9859fad..1acf17f68 100644
--- a/chrome/browser/sync_file_system/drive_backend/sync_engine.h
+++ b/chrome/browser/sync_file_system/drive_backend/sync_engine.h
@@ -45,6 +45,9 @@
 namespace net {
 class URLRequestContextGetter;
 }
+namespace network {
+class SharedURLLoaderFactory;
+}
 
 namespace sync_file_system {
 
@@ -75,6 +78,7 @@
     virtual std::unique_ptr<drive::DriveServiceInterface> CreateDriveService(
         OAuth2TokenService* oauth2_token_service,
         net::URLRequestContextGetter* url_request_context_getter,
+        scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
         base::SequencedTaskRunner* blocking_task_runner);
 
    private:
@@ -167,6 +171,7 @@
              SigninManagerBase* signin_manager,
              OAuth2TokenService* token_service,
              net::URLRequestContextGetter* request_context,
+             scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
              std::unique_ptr<DriveServiceFactory> drive_service_factory,
              leveldb::Env* env_override);
 
@@ -199,6 +204,7 @@
   OAuth2TokenService* token_service_;
 
   scoped_refptr<net::URLRequestContextGetter> request_context_;
+  scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
 
   std::unique_ptr<DriveServiceFactory> drive_service_factory_;
 
diff --git a/chrome/browser/sync_file_system/drive_backend/sync_engine_unittest.cc b/chrome/browser/sync_file_system/drive_backend/sync_engine_unittest.cc
index 57020f9d..1cd0d82 100644
--- a/chrome/browser/sync_file_system/drive_backend/sync_engine_unittest.cc
+++ b/chrome/browser/sync_file_system/drive_backend/sync_engine_unittest.cc
@@ -23,6 +23,7 @@
 #include "content/public/browser/browser_thread.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "net/url_request/url_request_context_getter.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace sync_file_system {
@@ -57,6 +58,7 @@
         nullptr,    // signin_manager
         nullptr,    // token_service
         nullptr,    // request_context
+        nullptr,    // url_loader_factory
         nullptr,    // drive_service_factory
         nullptr));  // in_memory_env
 
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index 95d80ab..9451d7a9 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -10,6 +10,7 @@
 import("//chrome/common/features.gni")
 import("//chromeos/assistant/assistant.gni")
 import("//components/nacl/features.gni")
+import("//components/nux_google_apps/features.gni")
 import("//components/offline_pages/buildflags/features.gni")
 import("//components/signin/features.gni")
 import("//extensions/buildflags/buildflags.gni")
@@ -955,6 +956,7 @@
     "//components/net_log",
     "//components/ntp_snippets",
     "//components/ntp_tiles",
+    "//components/nux_google_apps:buildflags",
     "//components/offline_pages/buildflags",
     "//components/omnibox/browser",
     "//components/onc",
@@ -1935,8 +1937,12 @@
       "webui/chromeos/assistant_optin/assistant_optin_screen_exit_code.h",
       "webui/chromeos/assistant_optin/assistant_optin_ui.cc",
       "webui/chromeos/assistant_optin/assistant_optin_ui.h",
+      "webui/chromeos/assistant_optin/confirm_reject_screen_handler.cc",
+      "webui/chromeos/assistant_optin/confirm_reject_screen_handler.h",
       "webui/chromeos/assistant_optin/get_more_screen_handler.cc",
       "webui/chromeos/assistant_optin/get_more_screen_handler.h",
+      "webui/chromeos/assistant_optin/ready_screen_handler.cc",
+      "webui/chromeos/assistant_optin/ready_screen_handler.h",
       "webui/chromeos/assistant_optin/third_party_screen_handler.cc",
       "webui/chromeos/assistant_optin/third_party_screen_handler.h",
       "webui/chromeos/assistant_optin/value_prop_screen_handler.cc",
@@ -2420,8 +2426,6 @@
       "cocoa/md_hover_button.mm",
       "cocoa/md_util.h",
       "cocoa/md_util.mm",
-      "cocoa/media_picker/create_desktop_media_picker_cocoa.h",
-      "cocoa/media_picker/create_desktop_media_picker_cocoa.mm",
       "cocoa/media_picker/desktop_media_picker_bridge.h",
       "cocoa/media_picker/desktop_media_picker_bridge.mm",
       "cocoa/media_picker/desktop_media_picker_cocoa.h",
@@ -2840,12 +2844,6 @@
       "views/content_setting_domain_list_view.h",
       "views/cookie_info_view.cc",
       "views/cookie_info_view.h",
-      "views/desktop_capture/desktop_media_list_view.cc",
-      "views/desktop_capture/desktop_media_list_view.h",
-      "views/desktop_capture/desktop_media_picker_views.cc",
-      "views/desktop_capture/desktop_media_picker_views.h",
-      "views/desktop_capture/desktop_media_source_view.cc",
-      "views/desktop_capture/desktop_media_source_view.h",
       "views/device_chooser_content_view.cc",
       "views/device_chooser_content_view.h",
       "views/download/download_danger_prompt_views.cc",
@@ -3482,6 +3480,12 @@
       "views/color_chooser_aura.h",
       "views/crypto_module_password_dialog_view.cc",
       "views/crypto_module_password_dialog_view.h",
+      "views/desktop_capture/desktop_media_list_view.cc",
+      "views/desktop_capture/desktop_media_list_view.h",
+      "views/desktop_capture/desktop_media_picker_views.cc",
+      "views/desktop_capture/desktop_media_picker_views.h",
+      "views/desktop_capture/desktop_media_source_view.cc",
+      "views/desktop_capture/desktop_media_source_view.h",
       "views/dropdown_bar_host_aura.cc",
       "views/frame/browser_non_client_frame_view_factory_chromeos.cc",
       "views/ime/ime_window_frame_view.cc",
@@ -3851,6 +3855,10 @@
     deps += [ "//components/nacl/browser" ]
   }
 
+  if (enable_nux_google_apps) {
+    deps += [ "//components/nux_google_apps:nux_google_apps_feature" ]
+  }
+
   if (enable_plugins) {
     sources += [
       "hung_plugin_tab_helper.cc",
diff --git a/chrome/browser/ui/app_list/app_context_menu.cc b/chrome/browser/ui/app_list/app_context_menu.cc
index 440dd67..3f70ac9e 100644
--- a/chrome/browser/ui/app_list/app_context_menu.cc
+++ b/chrome/browser/ui/app_list/app_context_menu.cc
@@ -31,7 +31,6 @@
 void AppContextMenu::GetMenuModel(GetMenuModelCallback callback) {
   auto menu_model = std::make_unique<ui::SimpleMenuModel>(this);
   BuildMenu(menu_model.get());
-  menu_model->set_histogram_name("Apps.ContextMenuExecuteCommand.FromApp");
   std::move(callback).Run(std::move(menu_model));
 }
 
diff --git a/chrome/browser/ui/app_list/arc/arc_app_context_menu.cc b/chrome/browser/ui/app_list/arc/arc_app_context_menu.cc
index 66cc7ab..1631df9c 100644
--- a/chrome/browser/ui/app_list/arc/arc_app_context_menu.cc
+++ b/chrome/browser/ui/app_list/arc/arc_app_context_menu.cc
@@ -28,7 +28,6 @@
 
 void ArcAppContextMenu::GetMenuModel(GetMenuModelCallback callback) {
   auto menu_model = std::make_unique<ui::SimpleMenuModel>(this);
-  menu_model->set_histogram_name("Apps.ContextMenuExecuteCommand.FromApp");
   BuildMenu(menu_model.get());
   if (!features::IsTouchableAppContextMenuEnabled()) {
     std::move(callback).Run(std::move(menu_model));
diff --git a/chrome/browser/ui/autofill/autofill_popup_controller_impl.cc b/chrome/browser/ui/autofill/autofill_popup_controller_impl.cc
index 2ff718c..0470a8b 100644
--- a/chrome/browser/ui/autofill/autofill_popup_controller_impl.cc
+++ b/chrome/browser/ui/autofill/autofill_popup_controller_impl.cc
@@ -64,8 +64,10 @@
     const gfx::RectF& element_bounds,
     base::i18n::TextDirection text_direction)
     : controller_common_(element_bounds, text_direction, container_view),
+      view_(NULL),
       layout_model_(this, delegate->GetPopupType() == PopupType::kCreditCards),
-      delegate_(delegate) {
+      delegate_(delegate),
+      weak_ptr_factory_(this) {
   ClearState();
   delegate->RegisterDeletionCallback(base::BindOnce(
       &AutofillPopupControllerImpl::HideViewAndDie, GetWeakPtr()));
diff --git a/chrome/browser/ui/autofill/autofill_popup_controller_impl.h b/chrome/browser/ui/autofill/autofill_popup_controller_impl.h
index cc706f4a4..647f807 100644
--- a/chrome/browser/ui/autofill/autofill_popup_controller_impl.h
+++ b/chrome/browser/ui/autofill/autofill_popup_controller_impl.h
@@ -134,7 +134,9 @@
 
   base::WeakPtr<AutofillPopupControllerImpl> GetWeakPtr();
 
-  AutofillPopupLayoutModel& LayoutModelForTesting() { return layout_model_; }
+  // Contains common popup functionality such as popup layout. Protected for
+  // testing.
+  PopupControllerCommon controller_common_;
 
  private:
 #if !defined(OS_ANDROID)
@@ -155,8 +157,7 @@
   friend class AutofillPopupControllerUnitTest;
   void SetViewForTesting(AutofillPopupView* view) { view_ = view; }
 
-  PopupControllerCommon controller_common_;
-  AutofillPopupView* view_ = nullptr;  // Weak reference.
+  AutofillPopupView* view_;  // Weak reference.
   AutofillPopupLayoutModel layout_model_;
   base::WeakPtr<AutofillPopupDelegate> delegate_;
 
@@ -179,7 +180,7 @@
   // is drawn by Cocoa on macOS.
   gfx::Typesetter typesetter_ = gfx::Typesetter::HARFBUZZ;
 
-  base::WeakPtrFactory<AutofillPopupControllerImpl> weak_ptr_factory_{this};
+  base::WeakPtrFactory<AutofillPopupControllerImpl> weak_ptr_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(AutofillPopupControllerImpl);
 };
diff --git a/chrome/browser/ui/autofill/autofill_popup_controller_unittest.cc b/chrome/browser/ui/autofill/autofill_popup_controller_unittest.cc
index 7445f0d..341b1e2 100644
--- a/chrome/browser/ui/autofill/autofill_popup_controller_unittest.cc
+++ b/chrome/browser/ui/autofill/autofill_popup_controller_unittest.cc
@@ -13,8 +13,6 @@
 #include "build/build_config.h"
 #include "chrome/browser/ui/autofill/autofill_popup_controller_impl.h"
 #include "chrome/browser/ui/autofill/autofill_popup_view.h"
-#include "chrome/browser/ui/autofill/popup_view_common.h"
-#include "chrome/browser/ui/autofill/popup_view_test_helpers.h"
 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
 #include "chrome/test/base/testing_profile.h"
 #include "components/autofill/content/browser/content_autofill_driver.h"
@@ -98,10 +96,7 @@
                                     NULL,
                                     NULL,
                                     element_bounds,
-                                    base::i18n::UNKNOWN_DIRECTION) {
-    LayoutModelForTesting().SetUpForTesting(
-        std::make_unique<MockPopupViewCommonForUnitTesting>());
-  }
+                                    base::i18n::UNKNOWN_DIRECTION) {}
   ~TestAutofillPopupController() override {}
 
   // Making protected functions public for testing
diff --git a/chrome/browser/ui/autofill/autofill_popup_layout_model.cc b/chrome/browser/ui/autofill/autofill_popup_layout_model.cc
index 5e9ee54..8db77fb 100644
--- a/chrome/browser/ui/autofill/autofill_popup_layout_model.cc
+++ b/chrome/browser/ui/autofill/autofill_popup_layout_model.cc
@@ -95,7 +95,6 @@
   smaller_font_list_ =
       normal_font_list_.DeriveWithSizeDelta(kSmallerFontSizeDelta);
   bold_font_list_ = normal_font_list_.DeriveWithWeight(gfx::Font::Weight::BOLD);
-  view_common_ = std::make_unique<PopupViewCommon>();
 #endif
 }
 
@@ -153,7 +152,7 @@
   int popup_width = GetDesiredPopupWidth();
   int popup_height = GetDesiredPopupHeight();
 
-  popup_bounds_ = view_common_->CalculatePopupBounds(
+  popup_bounds_ = view_common_.CalculatePopupBounds(
       popup_width, popup_height, RoundedElementBounds(),
       delegate_->container_view(), delegate_->IsRTL());
 }
@@ -285,11 +284,6 @@
   return kResourceNotFoundId;
 }
 
-void AutofillPopupLayoutModel::SetUpForTesting(
-    std::unique_ptr<PopupViewCommon> view_common) {
-  view_common_ = std::move(view_common);
-}
-
 const gfx::Rect AutofillPopupLayoutModel::RoundedElementBounds() const {
   return gfx::ToEnclosingRect(delegate_->element_bounds());
 }
diff --git a/chrome/browser/ui/autofill/autofill_popup_layout_model.h b/chrome/browser/ui/autofill/autofill_popup_layout_model.h
index e240d7a..57b07f2 100644
--- a/chrome/browser/ui/autofill/autofill_popup_layout_model.h
+++ b/chrome/browser/ui/autofill/autofill_popup_layout_model.h
@@ -99,10 +99,6 @@
 
   bool is_credit_card_popup() const { return is_credit_card_popup_; }
 
-  // Allows the provision of another implementation of view_common, for use in
-  // unit tests where using the real thing could cause crashes.
-  void SetUpForTesting(std::unique_ptr<PopupViewCommon> view_common);
-
  private:
   // Returns the enclosing rectangle for the element_bounds.
   const gfx::Rect RoundedElementBounds() const;
@@ -120,7 +116,7 @@
   // The bounds of the Autofill popup.
   gfx::Rect popup_bounds_;
 
-  std::unique_ptr<PopupViewCommon> view_common_;
+  PopupViewCommon view_common_;
 
   AutofillPopupViewDelegate* delegate_;  // Weak reference.
 
diff --git a/chrome/browser/ui/autofill/popup_view_common.cc b/chrome/browser/ui/autofill/popup_view_common.cc
index 9d67c65..927e40f 100644
--- a/chrome/browser/ui/autofill/popup_view_common.cc
+++ b/chrome/browser/ui/autofill/popup_view_common.cc
@@ -7,18 +7,12 @@
 #include <algorithm>
 #include <utility>
 
-#include "build/build_config.h"
+#include "ui/display/display.h"
+#include "ui/display/screen.h"
+#include "ui/gfx/geometry/point.h"
+#include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/geometry/vector2d.h"
 
-#if defined(OS_ANDROID)
-#include "ui/android/view_android.h"
-#include "ui/android/window_android.h"
-#else  // defined(OS_ANDROID)
-#include "chrome/browser/platform_util.h"
-#include "chrome/browser/ui/browser_finder.h"
-#include "chrome/browser/ui/browser_window.h"
-#endif  // !defined(OS_ANDROID)
-
 namespace autofill {
 
 namespace {
@@ -27,23 +21,26 @@
 // the starting point and the width of the popup, taking into account the
 // direction it's supposed to grow (either to the left or to the right).
 // Components |y| and |height| of |popup_bounds| are not changed.
-void CalculatePopupXAndWidth(int leftmost_available_x,
-                             int rightmost_available_x,
+void CalculatePopupXAndWidth(const display::Display& left_display,
+                             const display::Display& right_display,
                              int popup_required_width,
                              const gfx::Rect& element_bounds,
                              bool is_rtl,
                              gfx::Rect* popup_bounds) {
+  int leftmost_display_x = left_display.bounds().x();
+  int rightmost_display_x =
+      right_display.GetSizeInPixel().width() + right_display.bounds().x();
+
   // Calculate the start coordinates for the popup if it is growing right or
   // the end position if it is growing to the left, capped to screen space.
-  int right_growth_start =
-      std::max(leftmost_available_x,
-               std::min(rightmost_available_x, element_bounds.x()));
+  int right_growth_start = std::max(
+      leftmost_display_x, std::min(rightmost_display_x, element_bounds.x()));
   int left_growth_end =
-      std::max(leftmost_available_x,
-               std::min(rightmost_available_x, element_bounds.right()));
+      std::max(leftmost_display_x,
+               std::min(rightmost_display_x, element_bounds.right()));
 
-  int right_available = rightmost_available_x - right_growth_start;
-  int left_available = left_growth_end - leftmost_available_x;
+  int right_available = rightmost_display_x - right_growth_start;
+  int left_available = left_growth_end - leftmost_display_x;
 
   int popup_width =
       std::min(popup_required_width, std::max(right_available, left_available));
@@ -69,92 +66,77 @@
 // the starting point and the height of the popup, taking into account the
 // direction it's supposed to grow (either up or down). Components |x| and
 // |width| of |popup_bounds| are not changed.
-void CalculatePopupYAndHeight(int topmost_available_y,
-                              int bottommost_available_y,
+void CalculatePopupYAndHeight(const display::Display& top_display,
+                              const display::Display& bottom_display,
                               int popup_required_height,
                               const gfx::Rect& element_bounds,
                               gfx::Rect* popup_bounds) {
+  int topmost_display_y = top_display.bounds().y();
+  int bottommost_display_y =
+      bottom_display.GetSizeInPixel().height() + bottom_display.bounds().y();
+
   // Calculate the start coordinates for the popup if it is growing down or
   // the end position if it is growing up, capped to screen space.
-  int top_growth_end =
-      std::max(topmost_available_y,
-               std::min(bottommost_available_y, element_bounds.y()));
+  int top_growth_end = std::max(
+      topmost_display_y, std::min(bottommost_display_y, element_bounds.y()));
   int bottom_growth_start =
-      std::max(topmost_available_y,
-               std::min(bottommost_available_y, element_bounds.bottom()));
+      std::max(topmost_display_y,
+               std::min(bottommost_display_y, element_bounds.bottom()));
 
-  int top_available = top_growth_end - topmost_available_y;
-  int bottom_available = bottommost_available_y - bottom_growth_start;
+  int top_available = bottom_growth_start - topmost_display_y;
+  int bottom_available = bottommost_display_y - top_growth_end;
 
+  // TODO(csharp): Restrict the popup height to what is available.
+  popup_bounds->set_height(popup_required_height);
   if (bottom_available >= popup_required_height ||
       bottom_available >= top_available) {
     // The popup can appear below the field.
-    popup_bounds->set_height(std::min(bottom_available, popup_required_height));
     popup_bounds->set_y(bottom_growth_start);
   } else {
     // The popup must appear above the field.
-    popup_bounds->set_height(std::min(top_available, popup_required_height));
-    popup_bounds->set_y(top_growth_end - popup_bounds->height());
+    popup_bounds->set_y(top_growth_end - popup_required_height);
   }
 }
 
 }  // namespace
 
-void PopupViewCommon::CalculatePopupHorizontalBounds(
-    int desired_width,
-    const gfx::Rect& element_bounds,
-    gfx::NativeView container_view,
-    bool is_rtl,
-    gfx::Rect* popup_bounds) {
-  const gfx::Rect bounds = GetWindowBounds(container_view);
-  CalculatePopupXAndWidth(/*leftmost_available_x=*/bounds.x(),
-                          /*rightmost_available_x=*/bounds.x() + bounds.width(),
-                          desired_width, element_bounds, is_rtl, popup_bounds);
-}
-
-void PopupViewCommon::CalculatePopupVerticalBounds(
-    int desired_height,
-    const gfx::Rect& element_bounds,
-    gfx::NativeView container_view,
-    gfx::Rect* popup_bounds) {
-  const gfx::Rect window_bounds = GetWindowBounds(container_view);
-  CalculatePopupYAndHeight(
-      /*topmost_available_y=*/window_bounds.y(),
-      /*bottommost_available_y=*/window_bounds.y() + window_bounds.height(),
-      desired_height, element_bounds, popup_bounds);
-}
-
 gfx::Rect PopupViewCommon::CalculatePopupBounds(int desired_width,
                                                 int desired_height,
                                                 const gfx::Rect& element_bounds,
                                                 gfx::NativeView container_view,
                                                 bool is_rtl) {
-  const gfx::Rect window_bounds = GetWindowBounds(container_view);
+  // This is the top left point of the popup if the popup is above the element
+  // and grows to the left (since that is the highest and furthest left the
+  // popup go could).
+  gfx::Point top_left_corner_of_popup =
+      element_bounds.origin() +
+      gfx::Vector2d(element_bounds.width() - desired_width, -desired_height);
+
+  // This is the bottom right point of the popup if the popup is below the
+  // element and grows to the right (since the is the lowest and furthest right
+  // the popup could go).
+  gfx::Point bottom_right_corner_of_popup =
+      element_bounds.origin() +
+      gfx::Vector2d(desired_width, element_bounds.height() + desired_height);
+
+  display::Display top_left_display =
+      GetDisplayNearestPoint(top_left_corner_of_popup, container_view);
+  display::Display bottom_right_display =
+      GetDisplayNearestPoint(bottom_right_corner_of_popup, container_view);
 
   gfx::Rect popup_bounds;
-  CalculatePopupXAndWidth(
-      /*leftmost_available_x=*/window_bounds.x(),
-      /*rightmost_available_x=*/window_bounds.x() + window_bounds.width(),
-      desired_width, element_bounds, is_rtl, &popup_bounds);
-  CalculatePopupYAndHeight(
-      /*topmost_available_y=*/window_bounds.y(),
-      /*bottommost_available_y=*/window_bounds.y() + window_bounds.height(),
-      desired_height, element_bounds, &popup_bounds);
+  CalculatePopupXAndWidth(top_left_display, bottom_right_display, desired_width,
+                          element_bounds, is_rtl, &popup_bounds);
+  CalculatePopupYAndHeight(top_left_display, bottom_right_display,
+                           desired_height, element_bounds, &popup_bounds);
 
   return popup_bounds;
 }
 
-gfx::Rect PopupViewCommon::GetWindowBounds(gfx::NativeView container_view) {
-// The call to FindBrowserWithWindow will fail on Android, so we use
-// platform-specific calls.
-#if defined(OS_ANDROID)
-  return container_view->GetWindowAndroid()->bounds();
-#else
-  gfx::NativeWindow window = platform_util::GetTopLevel(container_view);
-  Browser* browser = chrome::FindBrowserWithWindow(window);
-  DCHECK(browser);
-  return browser->window()->GetBounds();
-#endif
+display::Display PopupViewCommon::GetDisplayNearestPoint(
+    const gfx::Point& point,
+    gfx::NativeView container_view) {
+  return display::Screen::GetScreen()->GetDisplayNearestPoint(point);
 }
 
 }  // namespace autofill
diff --git a/chrome/browser/ui/autofill/popup_view_common.h b/chrome/browser/ui/autofill/popup_view_common.h
index d1445f3d..d99f20d 100644
--- a/chrome/browser/ui/autofill/popup_view_common.h
+++ b/chrome/browser/ui/autofill/popup_view_common.h
@@ -6,37 +6,25 @@
 #define CHROME_BROWSER_UI_AUTOFILL_POPUP_VIEW_COMMON_H_
 
 #include "base/macros.h"
-#include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/native_widget_types.h"
 
+namespace display {
+class Display;
+}
+
+namespace gfx {
+class Point;
+class Rect;
+}  // namespace gfx
+
 namespace autofill {
 
 // Provides utility functions for popup-style views.
 class PopupViewCommon {
  public:
-  virtual ~PopupViewCommon() = default;
-
-  // Writes the |x| and |width| properties to |popup_bounds| for the popup's
-  // placement based on the element's location, the desired width, whether or
-  // not this is RTL, and the space available in the window to the left/right
-  // of the element.
-  void CalculatePopupHorizontalBounds(int desired_width,
-                                      const gfx::Rect& element_bounds,
-                                      gfx::NativeView container_view,
-                                      bool is_rtl,
-                                      gfx::Rect* popup_bounds);
-
-  // Writes the |y| and |height| properties to |popup_bounds| for the popup's
-  // placement based on the element's location, the desired height, and the
-  // space available in the window above/below the element. The popup will be
-  // placed below the element as long as there is sufficient space.
-  void CalculatePopupVerticalBounds(int desired_height,
-                                    const gfx::Rect& element_bounds,
-                                    gfx::NativeView container_view,
-                                    gfx::Rect* popup_bounds);
-
-  // Convenience method which handles both the vertical and horizontal bounds
-  // and returns a new Rect.
+  // Returns the bounds that the popup should be placed at, given the desired
+  // width and height. By default this places the popup below |element_bounds|
+  // but it will be placed above if there isn't enough space.
   gfx::Rect CalculatePopupBounds(int desired_width,
                                  int desired_height,
                                  const gfx::Rect& element_bounds,
@@ -44,9 +32,11 @@
                                  bool is_rtl);
 
  protected:
-  // Returns the bounds of the containing window in screen space. Virtual for
-  // testing.
-  virtual gfx::Rect GetWindowBounds(gfx::NativeView container_view);
+  // A helper function to get the display closest to the given point (virtual
+  // for testing).
+  virtual display::Display GetDisplayNearestPoint(
+      const gfx::Point& point,
+      gfx::NativeView container_view);
 };
 
 }  // namespace autofill
diff --git a/chrome/browser/ui/autofill/popup_view_common_unittest.cc b/chrome/browser/ui/autofill/popup_view_common_unittest.cc
index fb4c507..003d37d 100644
--- a/chrome/browser/ui/autofill/popup_view_common_unittest.cc
+++ b/chrome/browser/ui/autofill/popup_view_common_unittest.cc
@@ -9,7 +9,6 @@
 #include <memory>
 
 #include "base/macros.h"
-#include "chrome/browser/ui/autofill/popup_view_test_helpers.h"
 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
 #include "content/public/browser/web_contents.h"
 #include "ui/display/display.h"
@@ -17,6 +16,26 @@
 
 namespace autofill {
 
+namespace {
+
+// Test class which overrides specific behavior for testing.
+class TestPopupViewCommon : public PopupViewCommon {
+ public:
+  explicit TestPopupViewCommon(const display::Display& display)
+      : display_(display) {}
+
+  display::Display GetDisplayNearestPoint(
+      const gfx::Point& point,
+      gfx::NativeView container_view) override {
+    return display_;
+  }
+
+ private:
+  display::Display display_;
+};
+
+}  // namespace
+
 class PopupViewCommonTest : public ChromeRenderViewHostTestHarness {
  public:
   PopupViewCommonTest() {}
@@ -30,8 +49,10 @@
   int desired_width = 40;
   int desired_height = 16;
 
-  gfx::Rect window_bounds(0, 0, 2 * desired_width, 2 * desired_height);
-  MockPopupViewCommonForUnitTesting view_common(window_bounds);
+  // Set up the visible screen space.
+  display::Display display(
+      0, gfx::Rect(0, 0, 2 * desired_width, 2 * desired_height));
+  TestPopupViewCommon view_common(display);
 
   struct {
     gfx::Rect element_bounds;
@@ -55,12 +76,12 @@
       {gfx::Rect(2 * desired_width, 2 * desired_height, 5, 0),
        gfx::Rect(desired_width, desired_height, desired_width, desired_height)},
 
-      // The popup would be partial off the top and left side of the window.
+      // The popup would be partial off the top and left side of the screen.
       {gfx::Rect(-desired_width / 2, -desired_height / 2, 5, 0),
        gfx::Rect(0, 0, desired_width, desired_height)},
 
       // The popup would be partially off the bottom and the right side of
-      // the window.
+      // the screen.
       {gfx::Rect(desired_width * 1.5, desired_height * 1.5, 5, 0),
        gfx::Rect((desired_width * 1.5 + 5 - desired_width),
                  (desired_height * 1.5 - desired_height), desired_width,
diff --git a/chrome/browser/ui/autofill/popup_view_test_helpers.cc b/chrome/browser/ui/autofill/popup_view_test_helpers.cc
deleted file mode 100644
index 304c73b..0000000
--- a/chrome/browser/ui/autofill/popup_view_test_helpers.cc
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ui/autofill/popup_view_test_helpers.h"
-
-namespace autofill {
-
-gfx::Rect MockPopupViewCommonForUnitTesting::GetWindowBounds(
-    gfx::NativeView container_view) {
-  return window_bounds_;
-}
-
-}  // namespace autofill
diff --git a/chrome/browser/ui/autofill/popup_view_test_helpers.h b/chrome/browser/ui/autofill/popup_view_test_helpers.h
deleted file mode 100644
index 0e85588f..0000000
--- a/chrome/browser/ui/autofill/popup_view_test_helpers.h
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_AUTOFILL_POPUP_VIEW_TEST_HELPERS_H_
-#define CHROME_BROWSER_UI_AUTOFILL_POPUP_VIEW_TEST_HELPERS_H_
-
-#include "chrome/browser/ui/autofill/popup_view_common.h"
-
-namespace autofill {
-
-// Attmepting to find the window's bounds in screen space will break in unit
-// tests, so this safe version of the class must be used instead. The
-// "interesting" geometry logic which calculates the bounds, determines the
-// direction, etc. will still run.
-class MockPopupViewCommonForUnitTesting : public PopupViewCommon {
- public:
-  // Initializes with arbitrary default window bounds.
-  MockPopupViewCommonForUnitTesting()
-      : window_bounds_(gfx::Rect(0, 0, 1000, 1000)) {}
-
-  ~MockPopupViewCommonForUnitTesting() override = default;
-
-  // Initializes with the given window bounds.
-  explicit MockPopupViewCommonForUnitTesting(const gfx::Rect& window_bounds)
-      : window_bounds_(window_bounds) {}
-
-  gfx::Rect GetWindowBounds(gfx::NativeView container_view) override;
-
- private:
-  gfx::Rect window_bounds_;
-
-  DISALLOW_COPY_AND_ASSIGN(MockPopupViewCommonForUnitTesting);
-};
-
-}  // namespace autofill
-
-#endif  // CHROME_BROWSER_UI_AUTOFILL_POPUP_VIEW_TEST_HELPERS_H_
diff --git a/chrome/browser/ui/cocoa/browser_window_controller.mm b/chrome/browser/ui/cocoa/browser_window_controller.mm
index 9766edf..e06ef00 100644
--- a/chrome/browser/ui/cocoa/browser_window_controller.mm
+++ b/chrome/browser/ui/cocoa/browser_window_controller.mm
@@ -1919,9 +1919,7 @@
 
 - (void)updateUIForTabFullscreen:
     (ExclusiveAccessContext::TabFullscreenState)state {
-  // Only need to update and layout toolbar in fullscreen mode.
-  if (![self isInAnyFullscreenMode])
-    return;
+  DCHECK([self isInAnyFullscreenMode]);
   [fullscreenToolbarController_
       layoutToolbarStyleIsExitingTabFullscreen:
           state == ExclusiveAccessContext::STATE_EXIT_TAB_FULLSCREEN];
diff --git a/chrome/browser/ui/cocoa/media_picker/create_desktop_media_picker_cocoa.h b/chrome/browser/ui/cocoa/media_picker/create_desktop_media_picker_cocoa.h
deleted file mode 100644
index 4ca31b9..0000000
--- a/chrome/browser/ui/cocoa/media_picker/create_desktop_media_picker_cocoa.h
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_COCOA_MEDIA_PICKER_CREATE_DESKTOP_MEDIA_PICKER_COCOA_H_
-#define CHROME_BROWSER_UI_COCOA_MEDIA_PICKER_CREATE_DESKTOP_MEDIA_PICKER_COCOA_H_
-
-#include <memory>
-
-#include "chrome/browser/media/webrtc/desktop_media_picker.h"
-
-// Returns a Cocoa DesktopMediaPicker or nullptr if the Views version should be
-// used instead.
-std::unique_ptr<DesktopMediaPicker> CreateDesktopMediaPickerCocoa();
-
-#endif  // CHROME_BROWSER_UI_COCOA_MEDIA_PICKER_CREATE_DESKTOP_MEDIA_PICKER_COCOA_H_
diff --git a/chrome/browser/ui/cocoa/media_picker/create_desktop_media_picker_cocoa.mm b/chrome/browser/ui/cocoa/media_picker/create_desktop_media_picker_cocoa.mm
deleted file mode 100644
index 5d45349..0000000
--- a/chrome/browser/ui/cocoa/media_picker/create_desktop_media_picker_cocoa.mm
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ui/cocoa/media_picker/create_desktop_media_picker_cocoa.h"
-
-#import "chrome/browser/ui/cocoa/media_picker/desktop_media_picker_cocoa.h"
-
-// static
-std::unique_ptr<DesktopMediaPicker> CreateDesktopMediaPickerCocoa() {
-  return std::make_unique<DesktopMediaPickerCocoa>();
-}
diff --git a/chrome/browser/ui/cocoa/media_picker/desktop_media_picker_cocoa.mm b/chrome/browser/ui/cocoa/media_picker/desktop_media_picker_cocoa.mm
index 832c23c..1036938 100644
--- a/chrome/browser/ui/cocoa/media_picker/desktop_media_picker_cocoa.mm
+++ b/chrome/browser/ui/cocoa/media_picker/desktop_media_picker_cocoa.mm
@@ -27,3 +27,8 @@
              requestAudio:params.request_audio]);
   [controller_ showWindow:nil];
 }
+
+// static
+std::unique_ptr<DesktopMediaPicker> DesktopMediaPicker::Create() {
+  return std::unique_ptr<DesktopMediaPicker>(new DesktopMediaPickerCocoa());
+}
diff --git a/chrome/browser/ui/exclusive_access/fullscreen_controller.cc b/chrome/browser/ui/exclusive_access/fullscreen_controller.cc
index 46daceb..56d0245 100644
--- a/chrome/browser/ui/exclusive_access/fullscreen_controller.cc
+++ b/chrome/browser/ui/exclusive_access/fullscreen_controller.cc
@@ -134,10 +134,6 @@
 
   ExclusiveAccessContext* exclusive_access_context =
       exclusive_access_manager()->context();
-  // This is needed on Mac as entering into Tab Fullscreen might change the top
-  // UI style.
-  exclusive_access_context->UpdateUIForTabFullscreen(
-      ExclusiveAccessContext::STATE_ENTER_TAB_FULLSCREEN);
 
   if (!exclusive_access_context->IsFullscreen()) {
     // Normal -> Tab Fullscreen.
@@ -147,8 +143,11 @@
   }
 
   // Browser Fullscreen -> Tab Fullscreen.
-  if (exclusive_access_context->IsFullscreen())
+  if (exclusive_access_context->IsFullscreen()) {
+    exclusive_access_context->UpdateUIForTabFullscreen(
+        ExclusiveAccessContext::STATE_ENTER_TAB_FULLSCREEN);
     state_prior_to_tab_fullscreen_ = STATE_BROWSER_FULLSCREEN;
+  }
 
   // We need to update the fullscreen exit bubble, e.g., going from browser
   // fullscreen to tab fullscreen will need to show different content.
diff --git a/chrome/browser/ui/sync/one_click_signin_sync_starter.cc b/chrome/browser/ui/sync/one_click_signin_sync_starter.cc
index ee2e5e4..bf7f2db 100644
--- a/chrome/browser/ui/sync/one_click_signin_sync_starter.cc
+++ b/chrome/browser/ui/sync/one_click_signin_sync_starter.cc
@@ -43,6 +43,7 @@
 #include "components/signin/core/browser/signin_manager.h"
 #include "components/signin/core/browser/signin_metrics.h"
 #include "components/sync/base/sync_prefs.h"
+#include "content/public/browser/storage_partition.h"
 #include "net/base/url_util.h"
 #include "net/url_request/url_request_context_getter.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -266,6 +267,8 @@
                        : AccountId::FromUserEmailGaiaId(username, gaia_id);
   policy_service->FetchPolicyForSignedInUser(
       account_id, dm_token_, client_id_, profile_->GetRequestContext(),
+      content::BrowserContext::GetDefaultStoragePartition(profile_)
+          ->GetURLLoaderFactoryForBrowserProcess(),
       base::Bind(&OneClickSigninSyncStarter::OnPolicyFetchComplete,
                  weak_pointer_factory_.GetWeakPtr()));
 }
diff --git a/chrome/browser/ui/toolbar/toolbar_actions_bar_unittest.cc b/chrome/browser/ui/toolbar/toolbar_actions_bar_unittest.cc
index eac3986..52b07e15 100644
--- a/chrome/browser/ui/toolbar/toolbar_actions_bar_unittest.cc
+++ b/chrome/browser/ui/toolbar/toolbar_actions_bar_unittest.cc
@@ -241,7 +241,9 @@
     ToolbarActionsBarUnitTest,
     testing::Values(ui::MaterialDesignController::MATERIAL_NORMAL,
                     ui::MaterialDesignController::MATERIAL_HYBRID,
-                    ui::MaterialDesignController::MATERIAL_TOUCH_OPTIMIZED));
+                    ui::MaterialDesignController::MATERIAL_TOUCH_OPTIMIZED,
+                    ui::MaterialDesignController::MATERIAL_REFRESH,
+                    ui::MaterialDesignController::MATERIAL_TOUCH_REFRESH));
 
 TEST_P(ToolbarActionsBarUnitTest, BasicToolbarActionsBarTest) {
   // Add three extensions to the profile; this is the easiest way to have
@@ -496,8 +498,13 @@
 
 TEST_P(ToolbarActionsBarUnitTest, TestStartAndEndIndexes) {
   const int icon_width = toolbar_actions_bar()->GetViewSize().width();
-  const int resize_handle_size =
+  // Width of the resize handle.
+  int extra_area_width =
       toolbar_actions_bar()->platform_settings().item_spacing;
+  if (ui::MaterialDesignController::IsRefreshUi()) {
+    // In Refresh there's a 1dp separator with spacing on both sides of it.
+    extra_area_width += 2 * GetLayoutConstant(TOOLBAR_STANDARD_SPACING) + 1;
+  }
 
   for (int i = 0; i < 3; ++i) {
     CreateAndAddExtension(base::StringPrintf("extension %d", i),
@@ -513,7 +520,7 @@
   EXPECT_FALSE(toolbar_actions_bar()->NeedsOverflow());
 
   // Shrink the width of the view to be a little over enough for one icon.
-  browser_action_test_util()->SetWidth(icon_width + 2 + resize_handle_size);
+  browser_action_test_util()->SetWidth(icon_width + 2 + extra_area_width);
   // Tricky: GetIconCount() is what we use to determine our preferred size,
   // stored pref size, etc, and should not be affected by a minimum size that is
   // too small to show everything. It should remain constant.
@@ -541,7 +548,7 @@
   // TODO(pbos): Set the full width in a less contrived way when
   // ToolbarActionsBar and BrowserActionsContainer merge.
   browser_action_test_util()->SetWidth(
-      toolbar_actions_bar()->GetFullSize().width() + resize_handle_size);
+      toolbar_actions_bar()->GetFullSize().width() + extra_area_width);
   EXPECT_EQ(3u, toolbar_actions_bar()->GetIconCount());
   EXPECT_EQ(0u, toolbar_actions_bar()->GetStartIndexInBounds());
   EXPECT_EQ(3u, toolbar_actions_bar()->GetEndIndexInBounds());
diff --git a/chrome/browser/ui/views/autofill/autofill_popup_view_native_views.cc b/chrome/browser/ui/views/autofill/autofill_popup_view_native_views.cc
index cf88b99..46a928f0 100644
--- a/chrome/browser/ui/views/autofill/autofill_popup_view_native_views.cc
+++ b/chrome/browser/ui/views/autofill/autofill_popup_view_native_views.cc
@@ -30,7 +30,6 @@
 #include "ui/views/controls/image_view.h"
 #include "ui/views/controls/label.h"
 #include "ui/views/controls/menu/menu_config.h"
-#include "ui/views/controls/scroll_view.h"
 #include "ui/views/controls/separator.h"
 #include "ui/views/layout/box_layout.h"
 #include "ui/views/layout/fill_layout.h"
@@ -53,10 +52,6 @@
 const SkColor kFooterBackgroundColor = gfx::kGoogleGrey050;
 const SkColor kSeparatorColor = gfx::kGoogleGrey200;
 
-// A space between the input element and the dropdown, so that the dropdown's
-// border doesn't look too close to the element.
-constexpr int kElementBorderPadding = 1;
-
 int GetCornerRadius() {
   return ChromeLayoutProvider::Get()->GetCornerRadiusMetric(
       views::EMPHASIS_MEDIUM);
@@ -384,9 +379,9 @@
     views::Widget* parent_widget)
     : AutofillPopupBaseView(controller, parent_widget),
       controller_(controller) {
-  layout_ = SetLayoutManager(
+  views::BoxLayout* layout = SetLayoutManager(
       std::make_unique<views::BoxLayout>(views::BoxLayout::kVertical));
-  layout_->set_main_axis_alignment(views::BoxLayout::MAIN_AXIS_ALIGNMENT_START);
+  layout->set_main_axis_alignment(views::BoxLayout::MAIN_AXIS_ALIGNMENT_START);
 
   CreateChildViews();
   SetBackground(views::CreateSolidBackground(kAutofillBackgroundColor));
@@ -405,6 +400,31 @@
   DoHide();
 }
 
+gfx::Size AutofillPopupViewNativeViews::CalculatePreferredSize() const {
+  // The border of the input element should be aligned with the border of the
+  // dropdown when suggestions are not too wide.
+  int contents_width =
+      gfx::ToEnclosingRect(controller_->element_bounds()).width();
+
+  // Allow the dropdown to grow beyond the element width if it requires more
+  // horizontal space to render the suggestions.
+  gfx::Size size = AutofillPopupBaseView::CalculatePreferredSize();
+  if (contents_width < size.width()) {
+    contents_width = size.width();
+    // Use multiples of |kDropdownWidthMultiple| if the required width is larger
+    // than the element width.
+    if (contents_width % kDropdownWidthMultiple) {
+      contents_width +=
+          kDropdownWidthMultiple - (contents_width % kDropdownWidthMultiple);
+    }
+  }
+
+  // Notwithstanding all the above rules, enforce a hard minimum so the dropdown
+  // is not too small to interact with.
+  size.set_width(std::max(kDropdownMinWidth, contents_width));
+  return size;
+}
+
 void AutofillPopupViewNativeViews::VisibilityChanged(View* starting_from,
                                                      bool is_visible) {
   if (is_visible) {
@@ -487,12 +507,7 @@
     line_number++;
   }
 
-  scroll_view_ = new views::ScrollView();
-  scroll_view_->set_hide_horizontal_scrollbar(true);
-  scroll_view_->SetContents(body_container);
-  AddChildView(scroll_view_);
-  layout_->SetFlexForView(scroll_view_, 1);
-  scroll_view_->ClipHeightTo(0, body_container->GetPreferredSize().height());
+  AddChildView(body_container);
 
   // All the remaining rows (where index >= |line_number|) are part of the
   // footer. This needs to be in its own container because it should not be
@@ -516,34 +531,9 @@
     }
 
     AddChildView(footer_container);
-    layout_->SetFlexForView(footer_container, 0);
   }
 }
 
-int AutofillPopupViewNativeViews::AdjustWidth(int width) const {
-  // The border of the input element should be aligned with the border of the
-  // dropdown when suggestions are not too wide.
-  int adjusted_width =
-      gfx::ToEnclosingRect(controller_->element_bounds()).width();
-
-  // Allow the dropdown to grow beyond the element width if it requires more
-  // horizontal space to render the suggestions.
-  if (adjusted_width < width) {
-    adjusted_width = width;
-    // Use multiples of |kDropdownWidthMultiple| if the required width is larger
-    // than the element width.
-    if (adjusted_width % kDropdownWidthMultiple) {
-      adjusted_width +=
-          kDropdownWidthMultiple - (adjusted_width % kDropdownWidthMultiple);
-    }
-  }
-
-  // Notwithstanding all the above rules, enforce a hard minimum so the dropdown
-  // is not too small to interact with.
-  adjusted_width = std::max(kDropdownMinWidth, adjusted_width);
-  return adjusted_width;
-}
-
 void AutofillPopupViewNativeViews::AddExtraInitParams(
     views::Widget::InitParams* params) {
   // Ensure the bubble border is not painted on an opaque background.
@@ -574,42 +564,16 @@
 }
 
 void AutofillPopupViewNativeViews::DoUpdateBoundsAndRedrawPopup() {
-  gfx::Size size = CalculatePreferredSize();
-  gfx::Rect popup_bounds;
+  SizeToPreferredSize();
 
   // When a bubble border is shown, the contents area (inside the shadow) is
   // supposed to be aligned with input element boundaries.
-  gfx::Rect element_bounds =
-      gfx::ToEnclosingRect(controller_->element_bounds());
-  // Consider the element is |kElementBorderPadding| pixels larger at the top
-  // and at the bottom in order to reposition the dropdown, so that it doesn't
-  // look too close to the element.
-  element_bounds.Inset(/*horizontal=*/0, /*vertical=*/-kElementBorderPadding);
+  gfx::Rect popup_bounds = PopupViewCommon().CalculatePopupBounds(
+      size().width(), size().height(),
+      gfx::ToEnclosingRect(controller_->element_bounds()),
+      controller_->container_view(), controller_->IsRTL());
 
-  PopupViewCommon().CalculatePopupVerticalBounds(size.height(), element_bounds,
-                                                 controller_->container_view(),
-                                                 &popup_bounds);
-
-  // Adjust the width to compensate for a scroll bar, if necessary, and for
-  // other rules.
-  int scroll_width = 0;
-  if (size.height() > popup_bounds.height()) {
-    size.set_height(popup_bounds.height());
-
-    // Because the preferred size is greater than the bounds available, the
-    // contents will have to scroll. The scroll bar will steal width from the
-    // content and smoosh everything together. Instead, add to the width to
-    // compensate.
-    scroll_width = scroll_view_->GetScrollBarLayoutWidth();
-  }
-  size.set_width(AdjustWidth(size.width() + scroll_width));
-
-  PopupViewCommon().CalculatePopupHorizontalBounds(
-      size.width(), element_bounds, controller_->container_view(),
-      controller_->IsRTL(), &popup_bounds);
-
-  SetSize(size);
-
+  // Expand the widget bounds to include the border.
   popup_bounds.Inset(-bubble_border_->GetInsets());
 
   GetWidget()->SetBounds(popup_bounds);
diff --git a/chrome/browser/ui/views/autofill/autofill_popup_view_native_views.h b/chrome/browser/ui/views/autofill/autofill_popup_view_native_views.h
index e943ce6..43122c8 100644
--- a/chrome/browser/ui/views/autofill/autofill_popup_view_native_views.h
+++ b/chrome/browser/ui/views/autofill/autofill_popup_view_native_views.h
@@ -17,10 +17,6 @@
 #include <memory>
 #include <vector>
 
-namespace views {
-class BoxLayout;
-}
-
 namespace autofill {
 
 class AutofillPopupController;
@@ -80,6 +76,9 @@
   void Show() override;
   void Hide() override;
 
+  // views::View:
+  gfx::Size CalculatePreferredSize() const override;
+
   // AutofillPopupBaseView:
   // TODO(crbug.com/831603): Remove these overrides and the corresponding
   // methods in AutofillPopupBaseView once deprecation of
@@ -97,10 +96,6 @@
   // Creates child views based on the suggestions given by |controller_|.
   void CreateChildViews();
 
-  // Applies certain rounding rules to the given width, such as matching the
-  // element width when possible.
-  int AdjustWidth(int width) const;
-
   // AutofillPopupBaseView:
   void AddExtraInitParams(views::Widget::InitParams* params) override;
   std::unique_ptr<views::View> CreateWrapperView() override;
@@ -109,10 +104,10 @@
 
   // Controller for this view.
   AutofillPopupController* controller_;
+
   std::vector<AutofillPopupRowView*> rows_;
+
   views::BubbleBorder* bubble_border_;
-  views::BoxLayout* layout_;
-  views::ScrollView* scroll_view_;
 
   DISALLOW_COPY_AND_ASSIGN(AutofillPopupViewNativeViews);
 };
diff --git a/chrome/browser/ui/views/autofill/autofill_popup_view_native_views_unittest.cc b/chrome/browser/ui/views/autofill/autofill_popup_view_native_views_unittest.cc
index 3528a22..1408d31 100644
--- a/chrome/browser/ui/views/autofill/autofill_popup_view_native_views_unittest.cc
+++ b/chrome/browser/ui/views/autofill/autofill_popup_view_native_views_unittest.cc
@@ -233,12 +233,7 @@
   EXPECT_CALL(autofill_popup_controller_, AcceptSuggestion(::testing::_))
       .Times(click.click);
   gfx::Point center =
-      view()->GetRowsForTesting()[0]->GetBoundsInScreen().CenterPoint();
-
-  // Because we use GetBoundsInScreen above, and because macOS may reposition
-  // the window, we need to turn this bit off or the clicks will miss their
-  // targets.
-  generator_->set_assume_window_at_origin(false);
+      view()->GetRowsForTesting()[0]->GetLocalBounds().CenterPoint();
   generator_->set_current_location(center);
   generator_->ClickLeftButton();
   view()->RemoveAllChildViews(true /* delete_children */);
diff --git a/chrome/browser/ui/views/constrained_web_dialog_delegate_views.cc b/chrome/browser/ui/views/constrained_web_dialog_delegate_views.cc
index c3b443cd..be8341f 100644
--- a/chrome/browser/ui/views/constrained_web_dialog_delegate_views.cc
+++ b/chrome/browser/ui/views/constrained_web_dialog_delegate_views.cc
@@ -42,6 +42,17 @@
     DISALLOW_COPY_AND_ASSIGN(InitiatorWebContentsObserver);
 };
 
+gfx::Size RestrictToPlatformMinimumSize(const gfx::Size& min_size) {
+#if defined(OS_MACOSX)
+  // http://crbug.com/78973 - MacOS does not handle zero-sized windows well.
+  gfx::Size adjusted_min_size(1, 1);
+  adjusted_min_size.SetToMax(min_size);
+  return adjusted_min_size;
+#else
+  return min_size;
+#endif
+}
+
 // The specialized WebView that lives in a constrained dialog.
 class ConstrainedDialogWebView : public views::WebView,
                                  public ConstrainedWebDialogDelegate,
@@ -224,7 +235,7 @@
                                                   delegate,
                                                   &initiator_observer_,
                                                   this)),
-      min_size_(min_size),
+      min_size_(RestrictToPlatformMinimumSize(min_size)),
       max_size_(max_size) {
   SetWebContents(GetWebContents());
   AddAccelerator(ui::Accelerator(ui::VKEY_ESCAPE, ui::EF_NONE));
diff --git a/chrome/browser/ui/views/desktop_capture/desktop_media_list_view.cc b/chrome/browser/ui/views/desktop_capture/desktop_media_list_view.cc
index 478ca47..837e769 100644
--- a/chrome/browser/ui/views/desktop_capture/desktop_media_list_view.cc
+++ b/chrome/browser/ui/views/desktop_capture/desktop_media_list_view.cc
@@ -10,7 +10,6 @@
 
 #include "base/command_line.h"
 #include "base/strings/utf_string_conversions.h"
-#include "build/build_config.h"
 #include "chrome/browser/media/webrtc/desktop_media_list.h"
 #include "chrome/browser/media/webrtc/window_icon_util.h"
 #include "chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.h"
@@ -21,11 +20,8 @@
 #include "content/public/browser/browser_thread.h"
 #include "extensions/grit/extensions_browser_resources.h"
 #include "ui/accessibility/ax_node_data.h"
-#include "ui/base/resource/resource_bundle.h"
-
-#if defined(OS_CHROMEOS)
 #include "ui/aura/window.h"
-#endif
+#include "ui/base/resource/resource_bundle.h"
 
 using content::DesktopMediaID;
 
diff --git a/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.cc b/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.cc
index 9636cb9b..b30ebb2 100644
--- a/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.cc
+++ b/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.cc
@@ -5,7 +5,6 @@
 #include "chrome/browser/ui/views/desktop_capture/desktop_media_picker_views.h"
 
 #include "base/callback.h"
-#include "build/build_config.h"
 #include "chrome/browser/media/webrtc/desktop_media_list.h"
 #include "chrome/browser/ui/browser_dialogs.h"
 #include "chrome/browser/ui/browser_finder.h"
@@ -21,6 +20,7 @@
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/web_contents_delegate.h"
+#include "ui/aura/window_tree_host.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/events/keycodes/keyboard_codes.h"
 #include "ui/gfx/canvas.h"
@@ -33,19 +33,11 @@
 #include "ui/views/window/dialog_client_view.h"
 #include "ui/wm/core/shadow_types.h"
 
-#if defined(USE_AURA)
-#include "ui/aura/window_tree_host.h"
-#endif
-
-#if defined(OS_MACOSX)
-#include "chrome/browser/ui/cocoa/media_picker/create_desktop_media_picker_cocoa.h"
-#endif
-
 using content::DesktopMediaID;
 
 namespace {
 
-#if !defined(OS_CHROMEOS) && defined(USE_AURA)
+#if !defined(OS_CHROMEOS)
 DesktopMediaID::Id AcceleratedWidgetToDesktopMediaId(
     gfx::AcceleratedWidget accelerated_widget) {
 #if defined(OS_WIN)
@@ -231,7 +223,6 @@
   // the Id is passed to DesktopMediaList.
   DesktopMediaID dialog_window_id;
   if (!modal_dialog) {
-#if defined(USE_AURA)
     dialog_window_id = DesktopMediaID::RegisterAuraWindow(
         DesktopMediaID::TYPE_WINDOW, widget->GetNativeWindow());
 
@@ -239,8 +230,7 @@
 #if !defined(OS_CHROMEOS)
     dialog_window_id.id = AcceleratedWidgetToDesktopMediaId(
         widget->GetNativeWindow()->GetHost()->GetAcceleratedWidget());
-#endif  // !defined(OS_CHROMEOS)
-#endif  // defined(USE_AURA)
+#endif
   }
 
   for (auto* list_view : list_views_)
@@ -459,11 +449,5 @@
 
 // static
 std::unique_ptr<DesktopMediaPicker> DesktopMediaPicker::Create() {
-#if defined(OS_MACOSX)
-  std::unique_ptr<DesktopMediaPicker> cocoa_ui =
-      CreateDesktopMediaPickerCocoa();
-  if (cocoa_ui)
-    return cocoa_ui;
-#endif
-  return std::make_unique<DesktopMediaPickerViews>();
+  return std::unique_ptr<DesktopMediaPicker>(new DesktopMediaPickerViews());
 }
diff --git a/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views_unittest.cc b/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views_unittest.cc
index fe8407d..d92929e 100644
--- a/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views_unittest.cc
+++ b/chrome/browser/ui/views/desktop_capture/desktop_media_picker_views_unittest.cc
@@ -10,7 +10,6 @@
 #include "base/bind.h"
 #include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
-#include "build/build_config.h"
 #include "chrome/browser/media/webrtc/fake_desktop_media_list.h"
 #include "chrome/browser/ui/views/desktop_capture/desktop_media_list_view.h"
 #include "chrome/browser/ui/views/desktop_capture/desktop_media_source_view.h"
@@ -60,12 +59,6 @@
     picker_params.app_name = app_name;
     picker_params.target_name = app_name;
     picker_params.request_audio = true;
-#if defined(OS_MACOSX)
-    // On Mac, we don't have a NativeView to provide to
-    // DialogDelegate::CreateDialogWidget for the default MODAL_TYPE_CHILD
-    // default. MODAL_TYPE_WINDOW works around this.
-    picker_params.modality = ui::ModalType::MODAL_TYPE_WINDOW;
-#endif
     picker_views_->Show(picker_params, std::move(source_lists),
                         base::Bind(&DesktopMediaPickerViewsTest::OnPickerDone,
                                    base::Unretained(this)));
diff --git a/chrome/browser/ui/views/frame/browser_frame_mac.h b/chrome/browser/ui/views/frame/browser_frame_mac.h
index 565b183..e12cda27 100644
--- a/chrome/browser/ui/views/frame/browser_frame_mac.h
+++ b/chrome/browser/ui/views/frame/browser_frame_mac.h
@@ -26,7 +26,6 @@
 
   // Overridden from views::NativeWidgetMac:
   int SheetPositionY() override;
-  void OnWindowFullscreenStateChange() override;
   void InitNativeWidget(const views::Widget::InitParams& params) override;
 
   // Overridden from NativeBrowserFrame:
diff --git a/chrome/browser/ui/views/frame/browser_frame_mac.mm b/chrome/browser/ui/views/frame/browser_frame_mac.mm
index 2740d99..b965f14 100644
--- a/chrome/browser/ui/views/frame/browser_frame_mac.mm
+++ b/chrome/browser/ui/views/frame/browser_frame_mac.mm
@@ -62,10 +62,6 @@
   return host_view_y - dialog_host->GetDialogPosition(gfx::Size()).y();
 }
 
-void BrowserFrameMac::OnWindowFullscreenStateChange() {
-  browser_view_->FullscreenStateChanged();
-}
-
 void BrowserFrameMac::InitNativeWidget(
     const views::Widget::InitParams& params) {
   views::NativeWidgetMac::InitNativeWidget(params);
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view.cc
index 3b98d1c..07cfbfc 100644
--- a/chrome/browser/ui/views/frame/browser_non_client_frame_view.cc
+++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view.cc
@@ -81,13 +81,6 @@
   return false;
 }
 
-void BrowserNonClientFrameView::UpdateFullscreenTopUI(
-    bool is_exiting_fullscreen) {}
-
-bool BrowserNonClientFrameView::ShouldHideTopUIForFullscreen() const {
-  return frame()->IsFullscreen();
-}
-
 gfx::ImageSkia BrowserNonClientFrameView::GetIncognitoAvatarIcon() const {
   const SkColor icon_color = color_utils::PickContrastingColor(
       SK_ColorWHITE, gfx::kChromeIconGrey, GetFrameColor());
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view.h b/chrome/browser/ui/views/frame/browser_non_client_frame_view.h
index 46c7da1d..67636fb 100644
--- a/chrome/browser/ui/views/frame/browser_non_client_frame_view.h
+++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view.h
@@ -65,13 +65,6 @@
   // Returns the amount that the theme background should be inset.
   virtual int GetThemeBackgroundXInset() const = 0;
 
-  // Updates the top UI state to be hidden or shown in fullscreen according to
-  // the preference's state. Currently only used on Mac.
-  virtual void UpdateFullscreenTopUI(bool is_exiting_fullscreen);
-
-  // Returns whether the top UI should hide.
-  virtual bool ShouldHideTopUIForFullscreen() const;
-
   // Retrieves the icon to use in the frame to indicate an incognito window.
   gfx::ImageSkia GetIncognitoAvatarIcon() const;
 
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_mac.h b/chrome/browser/ui/views/frame/browser_non_client_frame_view_mac.h
index 057c05e..3c126850 100644
--- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_mac.h
+++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_mac.h
@@ -9,7 +9,6 @@
 #include "chrome/browser/ui/views/frame/avatar_button_manager.h"
 #include "chrome/browser/ui/views/frame/browser_non_client_frame_view.h"
 #include "chrome/browser/ui/views/profiles/profile_indicator_icon.h"
-#include "components/prefs/pref_change_registrar.h"
 
 class BrowserNonClientFrameViewMac : public BrowserNonClientFrameView {
  public:
@@ -22,8 +21,6 @@
   gfx::Rect GetBoundsForTabStrip(views::View* tabstrip) const override;
   int GetTopInset(bool restored) const override;
   int GetThemeBackgroundXInset() const override;
-  void UpdateFullscreenTopUI(bool is_exiting_fullscreen) override;
-  bool ShouldHideTopUIForFullscreen() const override;
   void UpdateThrobber(bool running) override;
   int GetTabStripLeftInset() const override;
 
@@ -50,32 +47,9 @@
   AvatarButtonStyle GetAvatarButtonStyle() const override;
 
  private:
-  // This enum class represents the appearance of the fullscreen toolbar, which
-  // includes the tab strip and omnibox. These values are logged in a histogram
-  // and shouldn't be renumbered or removed.
-  enum class FullscreenToolbarStyle {
-    // The toolbar is present. Moving the cursor to the top
-    // causes the menubar to appear and the toolbar to slide down.
-    kToolbarPresent = 0,
-    // The toolbar is hidden. Moving cursor to top shows the
-    // toolbar and menubar.
-    kToolbarHidden,
-    // Toolbar is hidden. Moving cursor to top causes the menubar
-    // to appear, but not the toolbar.
-    kToolbarNone,
-    // The last enum value. Used for logging in a histogram.
-    kToolbarLast = kToolbarNone
-  };
-
   void PaintThemedFrame(gfx::Canvas* canvas);
   int GetTabStripRightInset() const;
 
-  // Used to keep track of the update of kShowFullscreenToolbar preference.
-  PrefChangeRegistrar pref_registrar_;
-
-  // The style of the fullscreen toolbar.
-  FullscreenToolbarStyle toolbar_style_;
-
   DISALLOW_COPY_AND_ASSIGN(BrowserNonClientFrameViewMac);
 };
 
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_mac.mm b/chrome/browser/ui/views/frame/browser_non_client_frame_view_mac.mm
index 4556e42..74ca3ac 100644
--- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_mac.mm
+++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_mac.mm
@@ -4,16 +4,12 @@
 
 #include "chrome/browser/ui/views/frame/browser_non_client_frame_view_mac.h"
 
-#include "base/metrics/histogram_macros.h"
 #include "chrome/browser/themes/theme_properties.h"
-#include "chrome/browser/ui/exclusive_access/fullscreen_controller.h"
 #include "chrome/browser/ui/layout_constants.h"
 #include "chrome/browser/ui/views/frame/browser_frame.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/browser/ui/views/frame/browser_view_layout.h"
 #include "chrome/browser/ui/views/tabs/tab_strip.h"
-#include "chrome/common/pref_names.h"
-#include "components/prefs/pref_service.h"
 #include "ui/base/hit_test.h"
 #include "ui/base/theme_provider.h"
 #include "ui/gfx/canvas.h"
@@ -30,13 +26,7 @@
 BrowserNonClientFrameViewMac::BrowserNonClientFrameViewMac(
     BrowserFrame* frame,
     BrowserView* browser_view)
-    : BrowserNonClientFrameView(frame, browser_view) {
-  pref_registrar_.Init(browser_view->GetProfile()->GetPrefs());
-  pref_registrar_.Add(
-      prefs::kShowFullscreenToolbar,
-      base::BindRepeating(&BrowserNonClientFrameViewMac::UpdateFullscreenTopUI,
-                          base::Unretained(this), false));
-}
+    : BrowserNonClientFrameView(frame, browser_view) {}
 
 BrowserNonClientFrameViewMac::~BrowserNonClientFrameViewMac() {
 }
@@ -78,40 +68,6 @@
   return 0;
 }
 
-void BrowserNonClientFrameViewMac::UpdateFullscreenTopUI(
-    bool is_exiting_fullscreen) {
-  FullscreenToolbarStyle old_style = toolbar_style_;
-
-  // Update to the new toolbar style if needed.
-  FullscreenController* controller =
-      browser_view()->GetExclusiveAccessManager()->fullscreen_controller();
-  if ((controller->IsWindowFullscreenForTabOrPending() ||
-       controller->IsExtensionFullscreenOrPending()) &&
-      !is_exiting_fullscreen) {
-    toolbar_style_ = FullscreenToolbarStyle::kToolbarNone;
-  } else {
-    PrefService* prefs = browser_view()->GetProfile()->GetPrefs();
-    toolbar_style_ = prefs->GetBoolean(prefs::kShowFullscreenToolbar)
-                         ? FullscreenToolbarStyle::kToolbarPresent
-                         : FullscreenToolbarStyle::kToolbarHidden;
-  }
-
-  if (old_style != toolbar_style_) {
-    // Re-layout if toolbar style changes in fullscreen mode.
-    if (frame()->IsFullscreen())
-      browser_view()->Layout();
-    UMA_HISTOGRAM_ENUMERATION(
-        "OSX.Fullscreen.ToolbarStyle", toolbar_style_,
-        static_cast<int>(FullscreenToolbarStyle::kToolbarLast) + 1);
-  }
-}
-
-bool BrowserNonClientFrameViewMac::ShouldHideTopUIForFullscreen() const {
-  return frame()->IsFullscreen()
-             ? toolbar_style_ != FullscreenToolbarStyle::kToolbarPresent
-             : false;
-}
-
 void BrowserNonClientFrameViewMac::UpdateThrobber(bool running) {
 }
 
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc
index b122aef..f77784e 100644
--- a/chrome/browser/ui/views/frame/browser_view.cc
+++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -951,7 +951,14 @@
   if (immersive_mode_controller_->IsEnabled())
     return false;
 
-  return frame_->GetFrameView()->ShouldHideTopUIForFullscreen();
+#if defined(OS_MACOSX)
+  // On Mac, fullscreen mode still has top chrome UI such as Toolbar and
+  // Tabstrip unless the user explicitly turned that off.
+  return IsFullscreen() && !browser_->profile()->GetPrefs()->GetBoolean(
+                               prefs::kShowFullscreenToolbar);
+#else
+  return IsFullscreen();
+#endif
 }
 
 bool BrowserView::IsFullscreen() const {
@@ -969,12 +976,8 @@
 }
 
 void BrowserView::FullscreenStateChanged() {
-  bool fullscreen = IsFullscreen();
-  ProcessFullscreen(
-      fullscreen, GURL(),
-      fullscreen
-          ? GetExclusiveAccessManager()->GetExclusiveAccessExitBubbleType()
-          : EXCLUSIVE_ACCESS_BUBBLE_TYPE_NONE);
+  CHECK(!IsFullscreen());
+  ProcessFullscreen(false, GURL(), EXCLUSIVE_ACCESS_BUBBLE_TYPE_NONE);
 }
 
 void BrowserView::SetToolbarButtonProvider(ToolbarButtonProvider* provider) {
@@ -2746,11 +2749,6 @@
   return browser_->profile();
 }
 
-void BrowserView::UpdateUIForTabFullscreen(TabFullscreenState state) {
-  frame()->GetFrameView()->UpdateFullscreenTopUI(
-      state == ExclusiveAccessContext::STATE_EXIT_TAB_FULLSCREEN);
-}
-
 WebContents* BrowserView::GetActiveWebContents() {
   return browser_->tab_strip_model()->GetActiveWebContents();
 }
diff --git a/chrome/browser/ui/views/frame/browser_view.h b/chrome/browser/ui/views/frame/browser_view.h
index b7b5afa..c3455b3 100644
--- a/chrome/browser/ui/views/frame/browser_view.h
+++ b/chrome/browser/ui/views/frame/browser_view.h
@@ -256,6 +256,7 @@
 
   // Called after the widget's fullscreen state is changed without going through
   // FullscreenController. This method does any processing which was skipped.
+  // Only exiting fullscreen in this way is currently supported.
   void FullscreenStateChanged();
 
   // Sets the button provider for this BrowserView. Must be called before
@@ -469,7 +470,6 @@
 
   // ExclusiveAccessContext:
   Profile* GetProfile() override;
-  void UpdateUIForTabFullscreen(TabFullscreenState state) override;
   content::WebContents* GetActiveWebContents() override;
   void HideDownloadShelf() override;
   void UnhideDownloadShelf() override;
diff --git a/chrome/browser/ui/views/frame/browser_view_interactive_uitest.cc b/chrome/browser/ui/views/frame/browser_view_interactive_uitest.cc
index 08d1701..068af85 100644
--- a/chrome/browser/ui/views/frame/browser_view_interactive_uitest.cc
+++ b/chrome/browser/ui/views/frame/browser_view_interactive_uitest.cc
@@ -7,11 +7,9 @@
 #include "base/macros.h"
 #include "build/build_config.h"
 #include "chrome/browser/ui/browser_commands.h"
-#include "chrome/browser/ui/exclusive_access/fullscreen_controller.h"
 #include "chrome/browser/ui/views/location_bar/location_bar_view.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/views/scoped_macviews_browser_mode.h"
-#include "content/public/browser/web_contents.h"
 
 #if defined(OS_MACOSX)
 #include "chrome/browser/ui/browser_commands_mac.h"
@@ -56,8 +54,8 @@
 }
 
 // Test whether the top view including toolbar and tab strip shows up or hides
-// correctly in browser full screen mode.
-IN_PROC_BROWSER_TEST_F(BrowserViewTest, BrowserFullscreenShowTopView) {
+// correctly in full screen mode.
+IN_PROC_BROWSER_TEST_F(BrowserViewTest, FullscreenShowTopView) {
   BrowserView* browser_view = static_cast<BrowserView*>(browser()->window());
 
   // The top view should always show up in regular mode.
@@ -82,11 +80,6 @@
   chrome::ToggleFullscreenMode(browser());
   EXPECT_TRUE(browser_view->IsFullscreen());
   EXPECT_FALSE(browser_view->IsTabStripVisible());
-
-  // Test toggling toolbar while being in fullscreen mode.
-  chrome::ToggleFullscreenToolbar(browser());
-  EXPECT_TRUE(browser_view->IsFullscreen());
-  EXPECT_TRUE(browser_view->IsTabStripVisible());
 #else
   // In immersive full screen mode, the top view should show up; otherwise, it
   // always hides.
@@ -95,47 +88,4 @@
   else
     EXPECT_FALSE(browser_view->IsTabStripVisible());
 #endif
-
-  // Enter into tab full screen mode from browser fullscreen mode.
-  FullscreenController* controller =
-      browser()->exclusive_access_manager()->fullscreen_controller();
-  content::WebContents* web_contents =
-      browser()->tab_strip_model()->GetActiveWebContents();
-  controller->EnterFullscreenModeForTab(web_contents, GURL());
-  EXPECT_TRUE(browser_view->IsFullscreen());
-  if (browser_view->immersive_mode_controller()->IsEnabled())
-    EXPECT_TRUE(browser_view->IsTabStripVisible());
-  else
-    EXPECT_FALSE(browser_view->IsTabStripVisible());
-
-  // Return back to regular mode.
-  chrome::ToggleFullscreenMode(browser());
-  EXPECT_FALSE(browser_view->IsFullscreen());
-  EXPECT_TRUE(browser_view->IsTabStripVisible());
-}
-
-// Test whether the top view including toolbar and tab strip appears or hides
-// correctly in tab full screen mode.
-IN_PROC_BROWSER_TEST_F(BrowserViewTest, TabFullscreenShowTopView) {
-  BrowserView* browser_view = static_cast<BrowserView*>(browser()->window());
-
-  // The top view should always show up in regular mode.
-  EXPECT_FALSE(browser_view->IsFullscreen());
-  EXPECT_TRUE(browser_view->IsTabStripVisible());
-
-  // Enter into tab full screen mode.
-  FullscreenController* controller =
-      browser()->exclusive_access_manager()->fullscreen_controller();
-  content::WebContents* web_contents =
-      browser()->tab_strip_model()->GetActiveWebContents();
-  controller->EnterFullscreenModeForTab(web_contents, GURL());
-  EXPECT_TRUE(browser_view->IsFullscreen());
-
-  // The top view should not show up.
-  EXPECT_FALSE(browser_view->IsTabStripVisible());
-
-  // After exiting the fullscreen mode, the top view should show up again.
-  controller->ExitFullscreenModeForTab(web_contents);
-  EXPECT_FALSE(browser_view->IsFullscreen());
-  EXPECT_TRUE(browser_view->IsTabStripVisible());
 }
diff --git a/chrome/browser/ui/views/menu_interactive_uitest.cc b/chrome/browser/ui/views/menu_interactive_uitest.cc
new file mode 100644
index 0000000..c030c05
--- /dev/null
+++ b/chrome/browser/ui/views/menu_interactive_uitest.cc
@@ -0,0 +1,110 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#include "ui/views/controls/menu/menu_controller.h"
+
+#include "base/macros.h"
+#include "base/run_loop.h"
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "chrome/test/base/interactive_test_utils.h"
+#include "chrome/test/base/test_browser_window.h"
+#include "ui/base/test/ui_controls.h"
+#include "ui/gfx/geometry/point.h"
+#include "ui/views/controls/menu/menu_item_view.h"
+#include "ui/views/controls/menu/submenu_view.h"
+#include "ui/views/test/platform_test_helper.h"
+#include "ui/views/widget/widget.h"
+
+#if !defined(OS_CHROMEOS)
+#include "ui/views/test/native_widget_factory.h"
+#endif
+
+namespace views {
+namespace test {
+
+class MenuControllerUITest : public InProcessBrowserTest {
+ public:
+  MenuControllerUITest() {}
+
+  // This method creates a MenuRunner, MenuItemView, etc, adds two menu
+  // items, shows the menu so that it can calculate the position of the first
+  // menu item and move the mouse there, and closes the menu.
+  void SetupMenu(Widget* widget) {
+    menu_delegate_ = std::make_unique<MenuDelegate>();
+    MenuItemView* menu_item = new MenuItemView(menu_delegate_.get());
+    menu_runner_ = std::make_unique<MenuRunner>(
+        +menu_item, views::MenuRunner::CONTEXT_MENU);
+    first_item_ =
+        menu_item->AppendMenuItemWithLabel(1, base::ASCIIToUTF16("One"));
+    menu_item->AppendMenuItemWithLabel(2, base::ASCIIToUTF16("Two"));
+    // Run the menu, so that the menu item size will be calculated.
+    menu_runner_->RunMenuAt(widget, nullptr, gfx::Rect(),
+                            views::MENU_ANCHOR_TOPLEFT, ui::MENU_SOURCE_NONE);
+    RunPendingMessages();
+    // Figure out the middle of the first menu item.
+    mouse_pos_.set_x(first_item_->width() / 2);
+    mouse_pos_.set_y(first_item_->height() / 2);
+    View::ConvertPointToScreen(
+        menu_item->GetSubmenu()->GetWidget()->GetRootView(), &mouse_pos_);
+    // Move the mouse so that it's where the menu will be shown.
+    base::RunLoop run_loop;
+    ui_controls::SendMouseMoveNotifyWhenDone(mouse_pos_.x(), mouse_pos_.y(),
+                                             run_loop.QuitClosure());
+    run_loop.Run();
+    EXPECT_TRUE(first_item_->IsSelected());
+    menu_runner_->Cancel();
+    RunPendingMessages();
+  }
+
+  void RunPendingMessages() {
+    base::RunLoop run_loop;
+    run_loop.RunUntilIdle();
+  }
+
+ protected:
+  MenuItemView* first_item_ = nullptr;
+  std::unique_ptr<MenuRunner> menu_runner_;
+  std::unique_ptr<MenuDelegate> menu_delegate_;
+  // Middle of first menu item.
+  gfx::Point mouse_pos_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(MenuControllerUITest);
+};
+
+IN_PROC_BROWSER_TEST_F(MenuControllerUITest, TestMouseOverShownMenu) {
+  // Create a parent widget.
+  Widget* widget = new views::Widget;
+  Widget::InitParams params(Widget::InitParams::TYPE_WINDOW);
+#if !defined(OS_CHROMEOS)
+  params.native_widget = ::views::test::CreatePlatformDesktopNativeWidgetImpl(
+      params, widget, nullptr);
+#endif
+  params.bounds = {0, 0, 200, 200};
+  widget->Init(params);
+  widget->Show();
+  widget->Activate();
+  // SetupMenu leaves the mouse position where the first menu item will be
+  // when we run the menu.
+  SetupMenu(widget);
+  menu_runner_->RunMenuAt(widget, nullptr, gfx::Rect(),
+                          views::MENU_ANCHOR_TOPLEFT, ui::MENU_SOURCE_NONE);
+  // One or two mouse events are posted by the menu being shown.
+  // Process event(s), and check what's selected in the menu.
+  RunPendingMessages();
+  EXPECT_FALSE(first_item_->IsSelected());
+  // Move mouse one pixel to left and verify that the first menu item
+  // is selected.
+  mouse_pos_.Offset(-1, 0);
+  base::RunLoop run_loop2;
+  ui_controls::SendMouseMoveNotifyWhenDone(mouse_pos_.x(), mouse_pos_.y(),
+                                           run_loop2.QuitClosure());
+  run_loop2.Run();
+  EXPECT_TRUE(first_item_->IsSelected());
+  menu_runner_->Cancel();
+  widget->Close();
+}
+
+}  // namespace test
+}  // namespace views
diff --git a/chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_screen_exit_code.h b/chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_screen_exit_code.h
index 4903e12..4098638 100644
--- a/chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_screen_exit_code.h
+++ b/chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_screen_exit_code.h
@@ -17,6 +17,8 @@
   THIRD_PARTY_CONTINUED = 2,
   EMAIL_OPTED_IN = 3,
   EMAIL_OPTED_OUT = 4,
+  CONFIRM_ACCEPTED = 5,
+  CONFIRM_REJECTED = 6,
   EXIT_CODES_COUNT
 };
 
diff --git a/chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_ui.cc b/chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_ui.cc
index 1cd35a1..562f4c75 100644
--- a/chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_ui.cc
+++ b/chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_ui.cc
@@ -10,7 +10,9 @@
 #include "base/macros.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/browser/ui/webui/chromeos/assistant_optin/confirm_reject_screen_handler.h"
 #include "chrome/browser/ui/webui/chromeos/assistant_optin/get_more_screen_handler.h"
+#include "chrome/browser/ui/webui/chromeos/assistant_optin/ready_screen_handler.h"
 #include "chrome/browser/ui/webui/chromeos/assistant_optin/third_party_screen_handler.h"
 #include "chrome/browser/ui/webui/chromeos/assistant_optin/value_prop_screen_handler.h"
 #include "chrome/browser/ui/webui/chromeos/login/base_screen_handler.h"
@@ -56,7 +58,6 @@
       assistant::ActivityControlSettingsUiSelector::
           ASSISTANT_SUW_ONBOARDING_ON_CHROME_OS);
   consent_flow_update->set_consent_token(consent_token);
-  consent_flow_update->set_saw_third_party_disclosure(true);
 
   return update;
 }
@@ -146,14 +147,15 @@
 // Get string constants for settings ui.
 base::DictionaryValue GetSettingsUiStrings(
     const assistant::SettingsUi& settings_ui,
-    bool activity_controll_needed) {
+    bool activity_control_needed) {
   auto consent_ui = settings_ui.consent_flow_ui().consent_ui();
+  auto confirm_reject_ui = consent_ui.activity_control_confirm_reject_ui();
   auto activity_control_ui = consent_ui.activity_control_ui();
   auto third_party_disclosure_ui = consent_ui.third_party_disclosure_ui();
   base::DictionaryValue dictionary;
 
   // Add activity controll string constants.
-  if (activity_controll_needed) {
+  if (activity_control_needed) {
     dictionary.SetString("valuePropIdentity", activity_control_ui.identity());
     if (activity_control_ui.intro_text_paragraph_size()) {
       dictionary.SetString("valuePropIntro",
@@ -169,10 +171,38 @@
                          consent_ui.reject_button_text());
   }
 
+  // Add confirm reject screen string constants.
+  // TODO(updowndota) Use remote strings after server bug fixed.
+  dictionary.SetString(
+      "confirmRejectTitle",
+      l10n_util::GetStringUTF16(IDS_ASSISTANT_CONFIRM_SCREEN_TITLE));
+  dictionary.SetString(
+      "confirmRejectAcceptTitle",
+      l10n_util::GetStringUTF16(IDS_ASSISTANT_CONFIRM_SCREEN_ACCEPT_TITLE));
+  dictionary.SetString(
+      "confirmRejectAcceptMessage",
+      l10n_util::GetStringUTF16(IDS_ASSISTANT_CONFIRM_SCREEN_ACCEPT_MESSAGE));
+  dictionary.SetString(
+      "confirmRejectAcceptMessageExpanded",
+      l10n_util::GetStringUTF16(
+          IDS_ASSISTANT_CONFIRM_SCREEN_ACCEPT_MESSAGE_EXPANDED));
+  dictionary.SetString(
+      "confirmRejectRejectTitle",
+      l10n_util::GetStringUTF16(IDS_ASSISTANT_CONFIRM_SCREEN_REJECT_TITLE));
+  dictionary.SetString(
+      "confirmRejectRejectMessage",
+      l10n_util::GetStringUTF16(IDS_ASSISTANT_CONFIRM_SCREEN_REJECT_MESSAGE));
+  dictionary.SetString(
+      "confirmRejectContinueButton",
+      l10n_util::GetStringUTF16(IDS_ASSISTANT_CONTINUE_BUTTON));
+
   // Add third party string constants.
-  dictionary.SetString("thirdPartyTitle", third_party_disclosure_ui.title());
-  dictionary.SetString("thirdPartyContinueButton",
-                       third_party_disclosure_ui.button_continue());
+  dictionary.SetString(
+      "thirdPartyTitle",
+      l10n_util::GetStringUTF16(IDS_ASSISTANT_THIRD_PARTY_SCREEN_TITLE));
+  dictionary.SetString(
+      "thirdPartyContinueButton",
+      l10n_util::GetStringUTF16(IDS_ASSISTANT_CONTINUE_BUTTON));
   dictionary.SetString("thirdPartyFooter", consent_ui.tos_pp_links());
 
   // Add get more screen string constants.
@@ -181,7 +211,7 @@
       l10n_util::GetStringUTF16(IDS_ASSISTANT_GET_MORE_SCREEN_TITLE));
   dictionary.SetString(
       "getMoreContinueButton",
-      l10n_util::GetStringUTF16(IDS_ASSISTANT_GET_MORE_SCREEN_CONTINUE_BUTTON));
+      l10n_util::GetStringUTF16(IDS_ASSISTANT_CONTINUE_BUTTON));
 
   return dictionary;
 }
@@ -203,10 +233,13 @@
 
   AddScreenHandler(std::make_unique<ValuePropScreenHandler>(
       base::BindOnce(&AssistantOptInUI::OnExit, weak_factory_.GetWeakPtr())));
+  AddScreenHandler(std::make_unique<ConfirmRejectScreenHandler>(
+      base::BindOnce(&AssistantOptInUI::OnExit, weak_factory_.GetWeakPtr())));
   AddScreenHandler(std::make_unique<ThirdPartyScreenHandler>(
       base::BindOnce(&AssistantOptInUI::OnExit, weak_factory_.GetWeakPtr())));
   AddScreenHandler(std::make_unique<GetMoreScreenHandler>(
       base::BindOnce(&AssistantOptInUI::OnExit, weak_factory_.GetWeakPtr())));
+  AddScreenHandler(std::make_unique<ReadyScreenHandler>());
 
   base::DictionaryValue localized_strings;
   for (auto* handler : screen_handlers_)
@@ -262,27 +295,21 @@
 }
 
 void AssistantOptInUI::OnExit(AssistantOptInScreenExitCode exit_code) {
-  PrefService* prefs = Profile::FromWebUI(web_ui())->GetPrefs();
   switch (exit_code) {
     case AssistantOptInScreenExitCode::VALUE_PROP_SKIPPED:
-      prefs->SetBoolean(arc::prefs::kArcVoiceInteractionValuePropAccepted,
-                        false);
-      prefs->SetBoolean(arc::prefs::kVoiceInteractionEnabled, false);
-      CloseDialog(nullptr);
-      break;
-    case AssistantOptInScreenExitCode::VALUE_PROP_ACCEPTED:
       assistant_handler_->ShowNextScreen();
       break;
+    case AssistantOptInScreenExitCode::VALUE_PROP_ACCEPTED:
+      OnActivityControlOptInResult(true);
+      break;
+    case AssistantOptInScreenExitCode::CONFIRM_ACCEPTED:
+      OnActivityControlOptInResult(true);
+      break;
+    case AssistantOptInScreenExitCode::CONFIRM_REJECTED:
+      OnActivityControlOptInResult(false);
+      break;
     case AssistantOptInScreenExitCode::THIRD_PARTY_CONTINUED:
-      if (activity_controll_needed_) {
-        // Send the update to complete user opt-in.
-        settings_manager_->UpdateSettings(
-            GetSettingsUiUpdate(consent_token_).SerializeAsString(),
-            base::BindOnce(&AssistantOptInUI::OnUpdateSettingsResponse,
-                           weak_factory_.GetWeakPtr(), false));
-      } else {
-        assistant_handler_->ShowNextScreen();
-      }
+      assistant_handler_->ShowNextScreen();
       break;
     case AssistantOptInScreenExitCode::EMAIL_OPTED_IN:
       DCHECK(email_optin_needed_);
@@ -292,18 +319,32 @@
       if (email_optin_needed_)
         OnEmailOptInResult(false);
       else
-        CloseDialog(nullptr);
+        assistant_handler_->ShowNextScreen();
       break;
     default:
       NOTREACHED();
   }
 }
 
+void AssistantOptInUI::OnActivityControlOptInResult(bool opted_in) {
+  if (opted_in) {
+    settings_manager_->UpdateSettings(
+        GetSettingsUiUpdate(consent_token_).SerializeAsString(),
+        base::BindOnce(&AssistantOptInUI::OnUpdateSettingsResponse,
+                       weak_factory_.GetWeakPtr()));
+  } else {
+    PrefService* prefs = Profile::FromWebUI(web_ui())->GetPrefs();
+    prefs->SetBoolean(arc::prefs::kArcVoiceInteractionValuePropAccepted, false);
+    prefs->SetBoolean(arc::prefs::kVoiceInteractionEnabled, false);
+    CloseDialog(nullptr);
+  }
+}
+
 void AssistantOptInUI::OnEmailOptInResult(bool opted_in) {
   settings_manager_->UpdateSettings(
       GetEmailOptInUpdate(opted_in).SerializeAsString(),
       base::BindOnce(&AssistantOptInUI::OnUpdateSettingsResponse,
-                     weak_factory_.GetWeakPtr(), true));
+                     weak_factory_.GetWeakPtr()));
 }
 
 void AssistantOptInUI::OnGetSettingsResponse(const std::string& settings) {
@@ -311,17 +352,17 @@
   settings_ui.ParseFromString(settings);
 
   DCHECK(settings_ui.has_consent_flow_ui());
-  auto activity_control_ui =
-      settings_ui.consent_flow_ui().consent_ui().activity_control_ui();
-  auto third_party_disclosure_ui =
-      settings_ui.consent_flow_ui().consent_ui().third_party_disclosure_ui();
+  auto consent_ui = settings_ui.consent_flow_ui().consent_ui();
+  auto activity_control_ui = consent_ui.activity_control_ui();
+  auto confirm_reject_ui = consent_ui.activity_control_confirm_reject_ui();
+  auto third_party_disclosure_ui = consent_ui.third_party_disclosure_ui();
 
   consent_token_ = activity_control_ui.consent_token();
 
-  // Process activity controll data.
+  // Process activity control data.
   if (!activity_control_ui.setting_zippy().size()) {
     // No need to consent. Move to the next screen.
-    activity_controll_needed_ = false;
+    activity_control_needed_ = false;
     PrefService* prefs = Profile::FromWebUI(web_ui())->GetPrefs();
     prefs->SetBoolean(arc::prefs::kArcVoiceInteractionValuePropAccepted, true);
     prefs->SetBoolean(arc::prefs::kVoiceInteractionEnabled, true);
@@ -345,11 +386,10 @@
 
   // Pass string constants dictionary.
   assistant_handler_->ReloadContent(
-      GetSettingsUiStrings(settings_ui, activity_controll_needed_));
+      GetSettingsUiStrings(settings_ui, activity_control_needed_));
 }
 
-void AssistantOptInUI::OnUpdateSettingsResponse(bool should_exit,
-                                                const std::string& result) {
+void AssistantOptInUI::OnUpdateSettingsResponse(const std::string& result) {
   assistant::SettingsUiUpdateResult ui_result;
   ui_result.ParseFromString(result);
 
@@ -358,7 +398,8 @@
         assistant::ConsentFlowUiUpdateResult::SUCCESS) {
       // TODO(updowndta): Handle consent update failure.
       LOG(ERROR) << "Consent udpate error.";
-    } else {
+    } else if (activity_control_needed_) {
+      activity_control_needed_ = false;
       PrefService* prefs = Profile::FromWebUI(web_ui())->GetPrefs();
       prefs->SetBoolean(arc::prefs::kArcVoiceInteractionValuePropAccepted,
                         true);
@@ -374,11 +415,7 @@
     }
   }
 
-  if (!should_exit) {
-    assistant_handler_->ShowNextScreen();
-  } else {
-    CloseDialog(nullptr);
-  }
+  assistant_handler_->ShowNextScreen();
 }
 
 // AssistantOptInDialog
diff --git a/chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_ui.h b/chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_ui.h
index 8672bcd..e52e957 100644
--- a/chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_ui.h
+++ b/chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_ui.h
@@ -41,11 +41,12 @@
   // Called by a screen when user's done with it.
   void OnExit(AssistantOptInScreenExitCode exit_code);
 
+  void OnActivityControlOptInResult(bool opted_in);
   void OnEmailOptInResult(bool opted_in);
 
   // Handle response from the settings manager.
   void OnGetSettingsResponse(const std::string& settings);
-  void OnUpdateSettingsResponse(bool should_exit, const std::string& settings);
+  void OnUpdateSettingsResponse(const std::string& settings);
 
   // Show next screen in the optin flow.
   void Next();
@@ -53,8 +54,8 @@
   // Consent token used to complete the opt-in.
   std::string consent_token_;
 
-  // Whether activity controll is needed for user.
-  bool activity_controll_needed_ = true;
+  // Whether activity control is needed for user.
+  bool activity_control_needed_ = true;
 
   // Whether email optin is needed for user.
   bool email_optin_needed_ = false;
diff --git a/chrome/browser/ui/webui/chromeos/assistant_optin/confirm_reject_screen_handler.cc b/chrome/browser/ui/webui/chromeos/assistant_optin/confirm_reject_screen_handler.cc
new file mode 100644
index 0000000..821e080
--- /dev/null
+++ b/chrome/browser/ui/webui/chromeos/assistant_optin/confirm_reject_screen_handler.cc
@@ -0,0 +1,48 @@
+// 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/chromeos/assistant_optin/confirm_reject_screen_handler.h"
+
+#include "chrome/browser/browser_process.h"
+#include "chrome/grit/generated_resources.h"
+#include "components/login/localized_values_builder.h"
+
+namespace {
+
+constexpr char kJsScreenPath[] = "AssistantConfirmRejectScreen";
+
+}  // namespace
+
+namespace chromeos {
+
+ConfirmRejectScreenHandler::ConfirmRejectScreenHandler(
+    OnAssistantOptInScreenExitCallback callback)
+    : BaseWebUIHandler(), exit_callback_(std::move(callback)) {
+  set_call_js_prefix(kJsScreenPath);
+}
+
+ConfirmRejectScreenHandler::~ConfirmRejectScreenHandler() = default;
+
+void ConfirmRejectScreenHandler::DeclareLocalizedValues(
+    ::login::LocalizedValuesBuilder* builder) {}
+
+void ConfirmRejectScreenHandler::RegisterMessages() {
+  AddPrefixedCallback("userActed",
+                      &ConfirmRejectScreenHandler::HandleUserAction);
+}
+
+void ConfirmRejectScreenHandler::Initialize() {}
+
+void ConfirmRejectScreenHandler::HandleUserAction(bool confirm_result) {
+  DCHECK(exit_callback_);
+  if (confirm_result) {
+    std::move(exit_callback_)
+        .Run(AssistantOptInScreenExitCode::CONFIRM_ACCEPTED);
+  } else {
+    std::move(exit_callback_)
+        .Run(AssistantOptInScreenExitCode::CONFIRM_REJECTED);
+  }
+}
+
+}  // namespace chromeos
diff --git a/chrome/browser/ui/webui/chromeos/assistant_optin/confirm_reject_screen_handler.h b/chrome/browser/ui/webui/chromeos/assistant_optin/confirm_reject_screen_handler.h
new file mode 100644
index 0000000..b1022678
--- /dev/null
+++ b/chrome/browser/ui/webui/chromeos/assistant_optin/confirm_reject_screen_handler.h
@@ -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.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_CHROMEOS_ASSISTANT_OPTIN_CONFIRM_REJECT_SCREEN_HANDLER_H_
+#define CHROME_BROWSER_UI_WEBUI_CHROMEOS_ASSISTANT_OPTIN_CONFIRM_REJECT_SCREEN_HANDLER_H_
+
+#include <memory>
+#include <string>
+
+#include "base/macros.h"
+#include "chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_screen_exit_code.h"
+#include "chrome/browser/ui/webui/chromeos/login/base_webui_handler.h"
+
+namespace chromeos {
+
+class ConfirmRejectScreenHandler : public BaseWebUIHandler {
+ public:
+  explicit ConfirmRejectScreenHandler(
+      OnAssistantOptInScreenExitCallback callback);
+  ~ConfirmRejectScreenHandler() override;
+
+  // BaseWebUIHandler:
+  void DeclareLocalizedValues(
+      ::login::LocalizedValuesBuilder* builder) override;
+  void RegisterMessages() override;
+  void Initialize() override;
+
+ private:
+  void HandleUserAction(bool confirm_result);
+
+  OnAssistantOptInScreenExitCallback exit_callback_;
+
+  DISALLOW_COPY_AND_ASSIGN(ConfirmRejectScreenHandler);
+};
+
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_UI_WEBUI_CHROMEOS_ASSISTANT_OPTIN_CONFIRM_REJECT_SCREEN_HANDLER_H_
diff --git a/chrome/browser/ui/webui/chromeos/assistant_optin/ready_screen_handler.cc b/chrome/browser/ui/webui/chromeos/assistant_optin/ready_screen_handler.cc
new file mode 100644
index 0000000..268ce34
--- /dev/null
+++ b/chrome/browser/ui/webui/chromeos/assistant_optin/ready_screen_handler.cc
@@ -0,0 +1,26 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/webui/chromeos/assistant_optin/ready_screen_handler.h"
+
+#include "chrome/browser/browser_process.h"
+#include "chrome/grit/generated_resources.h"
+#include "components/login/localized_values_builder.h"
+
+namespace chromeos {
+
+ReadyScreenHandler::ReadyScreenHandler() : BaseWebUIHandler() {}
+
+ReadyScreenHandler::~ReadyScreenHandler() = default;
+
+void ReadyScreenHandler::DeclareLocalizedValues(
+    ::login::LocalizedValuesBuilder* builder) {
+  builder->Add("assistantReadyTitle", IDS_ASSISTANT_READY_SCREEN_TITLE);
+  builder->Add("assistantReadyMessage", IDS_ASSISTANT_READY_SCREEN_MESSAGE);
+  builder->Add("assistantReadyButton", IDS_ASSISTANT_DONE_BUTTON);
+}
+
+void ReadyScreenHandler::Initialize() {}
+
+}  // namespace chromeos
diff --git a/chrome/browser/ui/webui/chromeos/assistant_optin/ready_screen_handler.h b/chrome/browser/ui/webui/chromeos/assistant_optin/ready_screen_handler.h
new file mode 100644
index 0000000..0975ce8
--- /dev/null
+++ b/chrome/browser/ui/webui/chromeos/assistant_optin/ready_screen_handler.h
@@ -0,0 +1,33 @@
+// 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_CHROMEOS_ASSISTANT_OPTIN_READY_SCREEN_HANDLER_H_
+#define CHROME_BROWSER_UI_WEBUI_CHROMEOS_ASSISTANT_OPTIN_READY_SCREEN_HANDLER_H_
+
+#include <memory>
+#include <string>
+
+#include "base/macros.h"
+#include "chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_screen_exit_code.h"
+#include "chrome/browser/ui/webui/chromeos/login/base_webui_handler.h"
+
+namespace chromeos {
+
+class ReadyScreenHandler : public BaseWebUIHandler {
+ public:
+  ReadyScreenHandler();
+  ~ReadyScreenHandler() override;
+
+  // BaseWebUIHandler:
+  void DeclareLocalizedValues(
+      ::login::LocalizedValuesBuilder* builder) override;
+  void Initialize() override;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ReadyScreenHandler);
+};
+
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_UI_WEBUI_CHROMEOS_ASSISTANT_OPTIN_READY_SCREEN_HANDLER_H_
diff --git a/chrome/browser/ui/webui/chromeos/assistant_optin/value_prop_screen_handler.cc b/chrome/browser/ui/webui/chromeos/assistant_optin/value_prop_screen_handler.cc
index 187cdf3..0954844 100644
--- a/chrome/browser/ui/webui/chromeos/assistant_optin/value_prop_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/assistant_optin/value_prop_screen_handler.cc
@@ -40,7 +40,7 @@
                IDS_VOICE_INTERACTION_VALUE_PROP_LOAD_ERROR_MESSAGE);
   builder->Add("assistantOptinRetryButton",
                IDS_VOICE_INTERACTION_VALUE_PROP_RETRY_BUTTON);
-  builder->Add("valuePropMoreButton",
+  builder->Add("assistantOptinMoreButton",
                IDS_VOICE_INTERACTION_VALUE_PROP_MORE_BUTTION);
   builder->Add("back", IDS_EULA_BACK_BUTTON);
   builder->Add("next", IDS_EULA_NEXT_BUTTON);
diff --git a/chrome/browser/ui/webui/local_discovery/local_discovery_ui_browsertest.cc b/chrome/browser/ui/webui/local_discovery/local_discovery_ui_browsertest.cc
index 90ee886..2488a41 100644
--- a/chrome/browser/ui/webui/local_discovery/local_discovery_ui_browsertest.cc
+++ b/chrome/browser/ui/webui/local_discovery/local_discovery_ui_browsertest.cc
@@ -12,6 +12,7 @@
 #include "base/compiler_specific.h"
 #include "base/location.h"
 #include "base/macros.h"
+#include "base/memory/ref_counted.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
@@ -20,6 +21,8 @@
 #include "chrome/browser/media/router/providers/cast/dual_media_sink_service.h"
 #include "chrome/browser/media/router/test/noop_dual_media_sink_service.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/browser/signin/chrome_signin_client_factory.h"
 #include "chrome/browser/signin/identity_manager_factory.h"
 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
@@ -36,6 +39,9 @@
 #include "net/url_request/url_request_status.h"
 #include "net/url_request/url_request_test_util.h"
 #include "services/identity/public/cpp/identity_test_utils.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
+#include "services/network/test/test_url_loader_factory.h"
 
 #if defined(OS_CHROMEOS)
 #include "chrome/common/pref_names.h"
@@ -347,10 +353,12 @@
 
 class LocalDiscoveryUITest : public WebUIBrowserTest {
  public:
-  LocalDiscoveryUITest() : fake_fetcher_factory_(
-      &fetcher_impl_factory_,
-      fake_url_fetcher_creator_.callback()) {
-  }
+  LocalDiscoveryUITest()
+      : test_shared_loader_factory_(
+            base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
+                &test_url_loader_factory_)),
+        fake_fetcher_factory_(&fetcher_impl_factory_,
+                              fake_url_fetcher_creator_.callback()) {}
   ~LocalDiscoveryUITest() override {
   }
 
@@ -377,6 +385,11 @@
                                     &TestMessageLoopCondition::Signal))
         .WillRepeatedly(Return());
 
+    test_url_loader_factory_.AddResponse(
+        GaiaUrls::GetInstance()->oauth2_token_url().spec(), kResponseGaiaToken);
+    test_url_loader_factory_.AddResponse(
+        GaiaUrls::GetInstance()->oauth_user_info_url().spec(), kResponseGaiaId);
+
     fake_fetcher_factory().SetFakeResponse(
         GURL(kURLInfo),
         kResponseInfo,
@@ -433,10 +446,16 @@
         kSampleUser);
 
     AddLibrary(base::FilePath(FILE_PATH_LITERAL("local_discovery_ui_test.js")));
+
+    ChromeSigninClient* signin_client = static_cast<ChromeSigninClient*>(
+        ChromeSigninClientFactory::GetForProfile(
+            ProfileManager::GetActiveUserProfile()));
+    signin_client->SetURLLoaderFactoryForTest(test_shared_loader_factory_);
   }
 
   void TearDownOnMainThread() override {
     test_service_discovery_client_ = nullptr;
+    test_shared_loader_factory_->Detach();
     WebUIBrowserTest::TearDownOnMainThread();
   }
 
@@ -483,6 +502,10 @@
   scoped_refptr<TestServiceDiscoveryClient> test_service_discovery_client_;
   TestMessageLoopCondition condition_devices_listed_;
 
+  network::TestURLLoaderFactory test_url_loader_factory_;
+  scoped_refptr<network::WeakWrapperSharedURLLoaderFactory>
+      test_shared_loader_factory_;
+
   net::URLFetcherImplFactory fetcher_impl_factory_;
   StrictMock<MockableFakeURLFetcherCreator> fake_url_fetcher_creator_;
   net::FakeURLFetcherFactory fake_fetcher_factory_;
@@ -521,8 +544,7 @@
 IN_PROC_BROWSER_TEST_F(LocalDiscoveryUITest, RegisterTest) {
   TestMessageLoopCondition condition_token_claimed;
 
-  ui_test_utils::NavigateToURL(browser(), GURL(
-      chrome::kChromeUIDevicesURL));
+  ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUIDevicesURL));
   condition_devices_listed().Wait();
 
   test_service_discovery_client()->SimulateReceive(
diff --git a/chrome/browser/ui/webui/policy_tool_ui_browsertest.cc b/chrome/browser/ui/webui/policy_tool_ui_browsertest.cc
index c58d6c2..48ee227 100644
--- a/chrome/browser/ui/webui/policy_tool_ui_browsertest.cc
+++ b/chrome/browser/ui/webui/policy_tool_ui_browsertest.cc
@@ -466,7 +466,13 @@
   EXPECT_TRUE(PathExists(GetSessionPath(FILE_PATH_LITERAL("сессия"))));
 }
 
-IN_PROC_BROWSER_TEST_F(PolicyToolUITest, ImportingSession) {
+// Flaky on Win buildbots. See crbug.com/842405.
+#if defined(OS_WIN)
+#define MAYBE_ImportingSession DISABLED_ImportingSession
+#else
+#define MAYBE_ImportingSession ImportingSession
+#endif
+IN_PROC_BROWSER_TEST_F(PolicyToolUITest, MAYBE_ImportingSession) {
   ui_test_utils::NavigateToURL(browser(), GURL("chrome://policy-tool"));
 
   // Set up policy values and put them in the session file.
@@ -851,4 +857,4 @@
   EXPECT_TRUE(CheckPolicyStatus(
       "ManagedBookmarks", "[{\"attribute\": \"value\"}]",
       l10n_util::GetStringUTF8(IDS_POLICY_TOOL_INVALID_TYPE)));
-}
\ No newline at end of file
+}
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 7e01868e..38a9847 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
@@ -1581,6 +1581,7 @@
 #endif  // defined(OS_CHROMEOS)
 #if BUILDFLAG(ENABLE_DICE_SUPPORT)
     {"peopleSignIn", IDS_SETTINGS_PEOPLE_SIGN_IN},
+    {"peopleSignOut", IDS_SETTINGS_PEOPLE_SIGN_OUT},
     {"peopleSignInPrompt", IDS_SETTINGS_PEOPLE_SIGN_IN_PROMPT},
     {"peopleSignInPromptSecondaryWithNoAccount",
      IDS_SETTINGS_PEOPLE_SIGN_IN_PROMPT_SECONDARY_WITH_NO_ACCOUNT},
@@ -1604,7 +1605,7 @@
     {"syncDisabledByAdministrator",
      IDS_SETTINGS_SYNC_DISABLED_BY_ADMINISTRATOR},
     {"syncSignin", IDS_SETTINGS_SYNC_SIGNIN},
-    {"syncDisconnect", IDS_SETTINGS_SYNC_DISCONNECT},
+    {"syncDisconnect", IDS_SETTINGS_PEOPLE_SIGN_OUT},
     {"syncDisconnectTitle", IDS_SETTINGS_SYNC_DISCONNECT_TITLE},
     {"syncDisconnectDeleteProfile",
      IDS_SETTINGS_SYNC_DISCONNECT_DELETE_PROFILE},
diff --git a/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper.cc b/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper.cc
index 3773b85e..63cc6a71 100644
--- a/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper.cc
+++ b/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper.cc
@@ -35,6 +35,7 @@
 #include "components/signin/core/browser/signin_metrics.h"
 #include "components/signin/core/browser/signin_pref_names.h"
 #include "components/sync/base/sync_prefs.h"
+#include "content/public/browser/storage_partition.h"
 #include "net/url_request/url_request_context_getter.h"
 
 namespace {
@@ -253,6 +254,8 @@
   policy_service->FetchPolicyForSignedInUser(
       account_info_.GetAccountId(), dm_token_, client_id_,
       profile_->GetRequestContext(),
+      content::BrowserContext::GetDefaultStoragePartition(profile_)
+          ->GetURLLoaderFactoryForBrowserProcess(),
       base::Bind(&DiceTurnSyncOnHelper::OnPolicyFetchComplete,
                  weak_pointer_factory_.GetWeakPtr()));
 }
diff --git a/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper_unittest.cc b/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper_unittest.cc
index 11c0e023..3a8c253 100644
--- a/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper_unittest.cc
+++ b/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper_unittest.cc
@@ -39,6 +39,7 @@
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "google_apis/gaia/google_service_auth_error.h"
 #include "net/url_request/url_request_context_getter.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 using ::testing::AtLeast;
@@ -133,6 +134,7 @@
                                 nullptr,
                                 signin_manager,
                                 nullptr,
+                                nullptr,
                                 oauth2_token_service) {}
 
   void set_dm_token(const std::string& dm_token) { dm_token_ = dm_token; }
@@ -158,6 +160,7 @@
       const std::string& dm_token,
       const std::string& client_id,
       scoped_refptr<net::URLRequestContextGetter> profile_request_context,
+      scoped_refptr<network::SharedURLLoaderFactory> test_shared_loader_factory,
       const PolicyFetchCallback& callback) override {
     callback.Run(true);
   }
diff --git a/chrome/browser/ui/webui/welcome_ui.cc b/chrome/browser/ui/webui/welcome_ui.cc
index a634404..1f1bae0 100644
--- a/chrome/browser/ui/webui/welcome_ui.cc
+++ b/chrome/browser/ui/webui/welcome_ui.cc
@@ -14,11 +14,17 @@
 #include "chrome/grit/chrome_unscaled_resources.h"
 #include "chrome/grit/chromium_strings.h"
 #include "chrome/grit/generated_resources.h"
+#include "components/nux_google_apps/buildflags.h"
 #include "components/prefs/pref_service.h"
 #include "content/public/browser/web_ui_data_source.h"
 #include "net/base/url_util.h"
 #include "ui/base/l10n/l10n_util.h"
 
+#if BUILDFLAG(ENABLE_NUX_GOOGLE_APPS)
+#include "components/nux_google_apps/constants.h"
+#include "components/nux_google_apps/webui.h"
+#endif  // ENABLE_NUX_GOOGLE_APPS
+
 namespace {
   const bool kIsBranded =
 #if defined(GOOGLE_CHROME_BUILD)
@@ -99,6 +105,12 @@
     html_source->SetDefaultResource(IDR_WELCOME_HTML);
   }
 
+#if BUILDFLAG(ENABLE_NUX_GOOGLE_APPS)
+  if (base::FeatureList::IsEnabled(nux_google_apps::kNuxGoogleAppsFeature)) {
+    nux_google_apps::AddSources(html_source);
+  }
+#endif  // ENABLE_NUX_GOOGLE_APPS
+
   content::WebUIDataSource::Add(profile, html_source);
 }
 
diff --git a/chrome/common/chrome_content_client.cc b/chrome/common/chrome_content_client.cc
index c4c094b..06d0d28 100644
--- a/chrome/common/chrome_content_client.cc
+++ b/chrome/common/chrome_content_client.cc
@@ -541,10 +541,18 @@
       const base::Version version(WIDEVINE_CDM_VERSION_STRING);
       DCHECK(version.IsValid());
 
+      // Temporary session is always supported.
+      base::flat_set<media::CdmSessionType> supported_session_types = {
+          media::CdmSessionType::TEMPORARY_SESSION};
+      if (supports_persistent_license) {
+        supported_session_types.insert(
+            media::CdmSessionType::PERSISTENT_LICENSE_SESSION);
+      }
+
       cdms->push_back(content::CdmInfo(
           kWidevineCdmDisplayName, kWidevineCdmGuid, version, cdm_path,
           kWidevineCdmFileSystemId, video_codecs_supported,
-          supports_persistent_license, encryption_modes_supported,
+          supported_session_types, encryption_modes_supported,
           kWidevineKeySystem, false));
     }
 #endif  // defined(WIDEVINE_CDM_AVAILABLE_NOT_COMPONENT)
@@ -562,8 +570,6 @@
       // A variant of ECK key system that has a different GUID.
       const char kExternalClearKeyDifferentGuidTestKeySystem[] =
           "org.chromium.externalclearkey.differentguid";
-      // ECK implementation supports persistent licenses.
-      constexpr bool supports_persistent_license = true;
 
       // Register kExternalClearKeyDifferentGuidTestKeySystem first separately.
       // Otherwise, it'll be treated as a sub-key-system of normal
@@ -572,7 +578,9 @@
       cdms->push_back(content::CdmInfo(
           media::kClearKeyCdmDisplayName, media::kClearKeyCdmDifferentGuid,
           base::Version("0.1.0.0"), clear_key_cdm_path,
-          media::kClearKeyCdmFileSystemId, {}, supports_persistent_license,
+          media::kClearKeyCdmFileSystemId, {},
+          {media::CdmSessionType::TEMPORARY_SESSION,
+           media::CdmSessionType::PERSISTENT_LICENSE_SESSION},
           {media::EncryptionMode::kCenc, media::EncryptionMode::kCbcs},
           kExternalClearKeyDifferentGuidTestKeySystem, false));
 
@@ -580,7 +588,9 @@
       cdms->push_back(content::CdmInfo(
           media::kClearKeyCdmDisplayName, media::kClearKeyCdmGuid,
           base::Version("0.1.0.0"), clear_key_cdm_path,
-          media::kClearKeyCdmFileSystemId, {}, supports_persistent_license,
+          media::kClearKeyCdmFileSystemId, {},
+          {media::CdmSessionType::TEMPORARY_SESSION,
+           media::CdmSessionType::PERSISTENT_LICENSE_SESSION},
           {media::EncryptionMode::kCenc, media::EncryptionMode::kCbcs},
           kExternalClearKeyKeySystem, true));
     }
diff --git a/chrome/common/webui_url_constants.cc b/chrome/common/webui_url_constants.cc
index e0367a1..8de2ab8 100644
--- a/chrome/common/webui_url_constants.cc
+++ b/chrome/common/webui_url_constants.cc
@@ -100,6 +100,7 @@
 const char kChromeUINetInternalsHost[] = "net-internals";
 const char kChromeUINetInternalsURL[] = "chrome://net-internals/";
 const char kChromeUINewTabHost[] = "newtab";
+const char kChromeUINewTabIconHost[] = "ntpicon";
 const char kChromeUINewTabURL[] = "chrome://newtab/";
 const char kChromeUIOmniboxHost[] = "omnibox";
 const char kChromeUIOmniboxURL[] = "chrome://omnibox/";
diff --git a/chrome/common/webui_url_constants.h b/chrome/common/webui_url_constants.h
index 0ec350d..5934388 100644
--- a/chrome/common/webui_url_constants.h
+++ b/chrome/common/webui_url_constants.h
@@ -104,6 +104,7 @@
 extern const char kChromeUINetInternalsHost[];
 extern const char kChromeUINetInternalsURL[];
 extern const char kChromeUINewTabHost[];
+extern const char kChromeUINewTabIconHost[];
 extern const char kChromeUINewTabURL[];
 extern const char kChromeUIOfflineInternalsHost[];
 extern const char kChromeUIOmniboxHost[];
diff --git a/chrome/renderer/net/net_error_helper_core_unittest.cc b/chrome/renderer/net/net_error_helper_core_unittest.cc
index 669fc19..5ac9d9a 100644
--- a/chrome/renderer/net/net_error_helper_core_unittest.cc
+++ b/chrome/renderer/net/net_error_helper_core_unittest.cc
@@ -17,6 +17,7 @@
 #include "base/json/json_writer.h"
 #include "base/logging.h"
 #include "base/macros.h"
+#include "base/memory/ptr_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "base/timer/mock_timer.h"
@@ -176,10 +177,10 @@
                  bool visible) {
     // The old value of timer_, if any, will be freed by the old core_ being
     // destructed, since core_ takes ownership of the timer.
-    timer_ = new base::MockTimer(false, false);
+    timer_ = new base::MockOneShotTimer();
     core_.reset(new NetErrorHelperCore(this, auto_reload_enabled,
                                        auto_reload_visible_only, visible));
-    core_->set_timer_for_testing(std::unique_ptr<base::Timer>(timer_));
+    core_->set_timer_for_testing(base::WrapUnique(timer_));
   }
 
   NetErrorHelperCore* core() { return core_.get(); }
@@ -231,7 +232,7 @@
   }
   int tracking_request_count() const { return tracking_request_count_; }
 
-  base::MockTimer* timer() { return timer_; }
+  base::MockOneShotTimer* timer() { return timer_; }
 
   void NavigationCorrectionsLoadSuccess(const NavigationCorrection* corrections,
                                         int num_corrections) {
@@ -430,7 +431,7 @@
     EXPECT_TRUE(StringValueEquals(*dict, "params.key", kApiKey));
   }
 
-  base::MockTimer* timer_;
+  base::MockOneShotTimer* timer_;
 
   std::unique_ptr<NetErrorHelperCore> core_;
 
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 714d806..ff2a4c34 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -1415,7 +1415,6 @@
         "../browser/ui/views/autofill/save_card_bubble_views_browsertest_base.h",
         "../browser/ui/views/bookmarks/bookmark_bubble_view_browsertest.cc",
         "../browser/ui/views/bookmarks/bookmark_editor_view_browsertest.cc",
-        "../browser/ui/views/desktop_capture/desktop_media_picker_views_browsertest.cc",
         "../browser/ui/views/extensions/extension_message_bubble_view_browsertest.cc",
         "../browser/ui/views/extensions/pwa_confirmation_view_browsertest.cc",
         "../browser/ui/views/external_protocol_dialog_browsertest.cc",
@@ -2101,12 +2100,15 @@
       data_deps += [ "//remoting/webapp" ]
     }
 
-    if (use_aura && enable_wifi_display) {
-      sources += [
-        "../../extensions/browser/api/display_source/display_source_apitestbase.cc",
-        "../../extensions/browser/api/display_source/display_source_apitestbase.h",
-        "../browser/extensions/api/display_source/display_source_wifi_display_apitest.cc",
-      ]
+    if (use_aura) {
+      sources += [ "../browser/ui/views/desktop_capture/desktop_media_picker_views_browsertest.cc" ]
+      if (enable_wifi_display) {
+        sources += [
+          "../../extensions/browser/api/display_source/display_source_apitestbase.cc",
+          "../../extensions/browser/api/display_source/display_source_apitestbase.h",
+          "../browser/extensions/api/display_source/display_source_wifi_display_apitest.cc",
+        ]
+      }
     }
 
     if (is_chromeos || (is_linux && use_dbus)) {
@@ -2617,8 +2619,6 @@
     "../browser/ui/autofill/autofill_dialog_models_unittest.cc",
     "../browser/ui/autofill/autofill_popup_layout_model_unittest.cc",
     "../browser/ui/autofill/popup_view_common_unittest.cc",
-    "../browser/ui/autofill/popup_view_test_helpers.cc",
-    "../browser/ui/autofill/popup_view_test_helpers.h",
     "../browser/ui/bloated_renderer/bloated_renderer_tab_helper_unittest.cc",
     "../browser/ui/blocked_content/popup_opener_tab_helper_unittest.cc",
     "../browser/ui/blocked_content/safe_browsing_triggered_popup_blocker_unittest.cc",
@@ -4351,7 +4351,6 @@
         "../browser/ui/views/bookmarks/bookmark_context_menu_unittest.cc",
         "../browser/ui/views/bookmarks/bookmark_editor_view_unittest.cc",
         "../browser/ui/views/bookmarks/bookmark_menu_delegate_unittest.cc",
-        "../browser/ui/views/desktop_capture/desktop_media_picker_views_unittest.cc",
         "../browser/ui/views/device_chooser_content_view_unittest.cc",
         "../browser/ui/views/download/download_item_view_unittest.cc",
         "../browser/ui/views/extensions/chooser_dialog_view_unittest.cc",
@@ -4393,6 +4392,7 @@
 
         # Get these compiling on Mac - see http://crbug.com/657883.
         "../browser/ui/views/crypto_module_password_dialog_view_unittest.cc",
+        "../browser/ui/views/desktop_capture/desktop_media_picker_views_unittest.cc",
       ]
     }
   }
@@ -4835,6 +4835,7 @@
     if (toolkit_views) {
       sources += [
         "../browser/ui/views/menu_controller_interactive_uitest.cc",
+        "../browser/ui/views/menu_interactive_uitest.cc",
         "../browser/ui/views/menu_item_view_interactive_uitest.cc",
         "../browser/ui/views/menu_model_adapter_test.cc",
         "../browser/ui/views/menu_test_base.cc",
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/suggestions/ContentSuggestionsTestUtils.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/suggestions/ContentSuggestionsTestUtils.java
index 5cd8c69..0a522846 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/suggestions/ContentSuggestionsTestUtils.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/suggestions/ContentSuggestionsTestUtils.java
@@ -4,7 +4,6 @@
 
 package org.chromium.chrome.test.util.browser.suggestions;
 
-import org.chromium.chrome.browser.ntp.cards.NodeVisitor;
 import org.chromium.chrome.browser.ntp.cards.SuggestionsCategoryInfo;
 import org.chromium.chrome.browser.ntp.cards.TreeNode;
 import org.chromium.chrome.browser.ntp.snippets.CategoryInt;
@@ -139,63 +138,11 @@
     public static String stringify(TreeNode root) {
         final StringBuilder stringBuilder = new StringBuilder();
 
-        root.visitItems(new NodeVisitor() {
-            private int mPosition;
+        for (int i = 0; i < root.getItemCount(); i++) {
+            stringBuilder.append(
+                    String.format(Locale.US, "%s - %s%n", i, root.describeItemForTesting(i)));
+        }
 
-            @Override
-            public void visitAboveTheFoldItem() {
-                describeItem("ABOVE_THE_FOLD");
-            }
-
-            @Override
-            public void visitActionItem(@ContentSuggestionsAdditionalAction int currentAction) {
-                describeItem("ACTION(%d)", currentAction);
-            }
-
-            @Override
-            public void visitAllDismissedItem() {
-                describeItem("ALL_DISMISSED");
-            }
-
-            @Override
-            public void visitFooter() {
-                describeItem("FOOTER");
-            }
-
-            @Override
-            public void visitProgressItem() {
-                describeItem("PROGRESS");
-            }
-
-            @Override
-            public void visitSignInPromo() {
-                describeItem("SIGN_IN_PROMO");
-            }
-
-            @Override
-            public void visitNoSuggestionsItem() {
-                describeItem("NO_SUGGESTIONS");
-            }
-
-            @Override
-            public void visitSuggestion(SnippetArticle suggestion) {
-                describeItem("SUGGESTION(%1.42s)", suggestion.mTitle);
-            }
-
-            @Override
-            public void visitHeader() {
-                describeItem("HEADER");
-            }
-
-            private void describeItem(String description) {
-                stringBuilder.append(
-                        String.format(Locale.US, "%s - %s%n", mPosition++, description));
-            }
-
-            private void describeItem(String template, Object... args) {
-                describeItem(String.format(Locale.US, template, args));
-            }
-        });
         return stringBuilder.toString();
     }
 }
diff --git a/chrome/test/chromedriver/chrome_launcher.cc b/chrome/test/chromedriver/chrome_launcher.cc
index c982813..9436c48f 100644
--- a/chrome/test/chromedriver/chrome_launcher.cc
+++ b/chrome/test/chromedriver/chrome_launcher.cc
@@ -142,12 +142,16 @@
     switches.SetUnparsedSwitch(common_switch);
   for (auto* desktop_switch : kDesktopSwitches)
     switches.SetUnparsedSwitch(desktop_switch);
-  switches.SetSwitch("remote-debugging-port", "0");
   for (const auto& excluded_switch : capabilities.exclude_switches) {
     switches.RemoveSwitch(excluded_switch);
   }
   switches.SetFromSwitches(capabilities.switches);
-
+  if (switches.HasSwitch("remote-debugging-port")) {
+    return Status(kUnknownError,
+                  "Argument 'remote-debugging-port' is not allowed. "
+                  "You must let Chrome pick a remote debug port for you.");
+  }
+  switches.SetSwitch("remote-debugging-port", "0");
   if (capabilities.exclude_switches.count("user-data-dir") > 0)
     LOG(WARNING) << "excluding user-data-dir switch is not supported";
   if (switches.HasSwitch("user-data-dir")) {
@@ -408,49 +412,58 @@
   VLOG(0) << "Launching chrome: " << command_string;
   base::Process process = base::LaunchProcess(command, options);
   if (!process.IsValid())
-    return Status(kUnknownError, "chrome failed to start");
+    return Status(kUnknownError, "Failed to create a Chrome process.");
 
+  // Attempt to connect to devtools in order to send commands to Chrome. If
+  // attempts fail, check if Chrome has crashed and return error.
   std::unique_ptr<DevToolsHttpClient> devtools_http_client;
   int devtools_port;
-  status = internal::ParseDevToolsActivePortFile(user_data_dir, &devtools_port);
-  if (status.IsError()) {
-    return status;
-  }
-  status = WaitForDevToolsAndCheckVersion(NetAddress(devtools_port),
-                                          context_getter, socket_factory,
-                                          &capabilities, &devtools_http_client);
-  if (status.IsError()) {
-    int exit_code;
-    base::TerminationStatus chrome_status =
-        base::GetTerminationStatus(process.Handle(), &exit_code);
-    if (chrome_status != base::TERMINATION_STATUS_STILL_RUNNING) {
-      std::string termination_reason;
-      switch (chrome_status) {
-        case base::TERMINATION_STATUS_NORMAL_TERMINATION:
-          termination_reason = "exited normally";
-          break;
-        case base::TERMINATION_STATUS_ABNORMAL_TERMINATION:
-          termination_reason = "exited abnormally";
-          break;
-        case base::TERMINATION_STATUS_PROCESS_WAS_KILLED:
-#if defined(OS_CHROMEOS)
-        case base::TERMINATION_STATUS_PROCESS_WAS_KILLED_BY_OOM:
-#endif
-          termination_reason = "was killed";
-          break;
-        case base::TERMINATION_STATUS_PROCESS_CRASHED:
-          termination_reason = "crashed";
-          break;
-        case base::TERMINATION_STATUS_LAUNCH_FAILED:
-          termination_reason = "failed to launch";
-          break;
-        default:
-          termination_reason = "unknown";
-          break;
-      }
-      return Status(kUnknownError,
-                    "Chrome failed to start: " + termination_reason);
+  int exit_code;
+  base::TerminationStatus chrome_status =
+      base::TERMINATION_STATUS_STILL_RUNNING;
+  base::TimeTicks deadline =
+      base::TimeTicks::Now() + base::TimeDelta::FromSeconds(60);
+  while (base::TimeTicks::Now() < deadline) {
+    status =
+        internal::ParseDevToolsActivePortFile(user_data_dir, &devtools_port);
+    if (status.IsOk()) {
+      status = WaitForDevToolsAndCheckVersion(
+          NetAddress(devtools_port), context_getter, socket_factory,
+          &capabilities, &devtools_http_client);
     }
+    if (status.IsOk()) {
+      break;
+    }
+    chrome_status = base::GetTerminationStatus(process.Handle(), &exit_code);
+    if (chrome_status != base::TERMINATION_STATUS_STILL_RUNNING) {
+      std::string termination_reason =
+          internal::GetTerminationReason(chrome_status);
+      Status failure_status = Status(
+          kUnknownError, "Chrome failed to start: " + termination_reason);
+      failure_status.AddDetails(status.message());
+      // There is a use case of someone passing a path to a binary to us in
+      // capabilities that is not an actual Chrome binary but a script that
+      // intercepts our arguments and then starts Chrome itself. This method
+      // of starting Chrome should be done carefully. The right way to do it
+      // is to do an exec of Chrome at the end of the script so that Chrome
+      // remains a subprocess of ChromeDriver. This allows us to have the
+      // correct process handle so that we can terminate Chrome after the
+      // test has finished or in the case of any failure. If you can't exec the
+      // Chrome binary at the end of your script, you must find a way to
+      // properly handle our termination signal so that you don't have zombie
+      // Chrome processes running after the test is completed.
+      failure_status.AddDetails(
+          "The process started from chrome location " +
+          command.GetProgram().AsUTF8Unsafe() +
+          " is no longer running, so ChromeDriver is assuming that Chrome has "
+          "crashed.");
+      return failure_status;
+    }
+    base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(50));
+  }
+
+  if (status.IsError()) {
+    VLOG(0) << "Failed to connect to Chrome. Attempting to kill it.";
     if (!process.Terminate(0, true)) {
       int exit_code;
       if (base::GetTerminationStatus(process.Handle(), &exit_code) ==
@@ -570,6 +583,8 @@
                     std::unique_ptr<Chrome>* chrome,
                     bool w3c_compliant) {
   if (capabilities.IsRemoteBrowser()) {
+    // TODO(johnchen): Clean up naming for ChromeDriver sessions created
+    // by connecting to an already-running Chrome at a given debuggerAddress.
     return LaunchRemoteChromeSession(
         context_getter, socket_factory, capabilities,
         std::move(devtools_event_listeners), chrome);
@@ -878,7 +893,9 @@
   return Status(kOk);
 }
 
-Status ReadInPort(const base::FilePath& port_filepath, int* port) {
+Status ParseDevToolsActivePortFile(const base::FilePath& user_data_dir,
+                                   int* port) {
+  base::FilePath port_filepath = user_data_dir.Append(kDevToolsActivePort);
   if (!base::PathExists(port_filepath)) {
     return Status(kUnknownError, "DevToolsActivePort file doesn't exist");
   }
@@ -901,23 +918,6 @@
   return Status(kOk);
 }
 
-Status ParseDevToolsActivePortFile(const base::FilePath& user_data_dir,
-                                   int* port) {
-  base::FilePath port_filepath = user_data_dir.Append(kDevToolsActivePort);
-  base::TimeTicks deadline =
-      base::TimeTicks::Now() + base::TimeDelta::FromSeconds(60);
-  Status result =
-      Status(kUnknownError, "This should not happen: increase the deadline");
-  while (base::TimeTicks::Now() < deadline) {
-    result = ReadInPort(port_filepath, port);
-    if (result.IsOk()) {
-      return result;
-    }
-    base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(50));
-  }
-  return result;
-}
-
 Status RemoveOldDevToolsActivePortFile(const base::FilePath& user_data_dir) {
   base::FilePath port_filepath = user_data_dir.Append(kDevToolsActivePort);
   // Note that calling DeleteFile on a path that doesn't exist returns True.
@@ -933,4 +933,24 @@
                       "process."));
 }
 
+std::string GetTerminationReason(base::TerminationStatus status) {
+  switch (status) {
+    case base::TERMINATION_STATUS_NORMAL_TERMINATION:
+      return "exited normally";
+    case base::TERMINATION_STATUS_ABNORMAL_TERMINATION:
+      return "exited abnormally";
+    case base::TERMINATION_STATUS_PROCESS_WAS_KILLED:
+#if defined(OS_CHROMEOS)
+    case base::TERMINATION_STATUS_PROCESS_WAS_KILLED_BY_OOM:
+#endif
+      return "was killed";
+    case base::TERMINATION_STATUS_PROCESS_CRASHED:
+      return "crashed";
+    case base::TERMINATION_STATUS_LAUNCH_FAILED:
+      return "failed to launch";
+    default:
+      return "unknown";
+  }
+}
+
 }  // namespace internal
diff --git a/chrome/test/chromedriver/chrome_launcher.h b/chrome/test/chromedriver/chrome_launcher.h
index d18e59e7..77fb00e 100644
--- a/chrome/test/chromedriver/chrome_launcher.h
+++ b/chrome/test/chromedriver/chrome_launcher.h
@@ -10,6 +10,7 @@
 #include <vector>
 
 #include "base/files/file_path.h"
+#include "base/process/kill.h"
 #include "chrome/test/chromedriver/capabilities.h"
 #include "chrome/test/chromedriver/net/sync_websocket_factory.h"
 
@@ -18,6 +19,7 @@
 namespace base {
 class DictionaryValue;
 class FilePath;
+enum TerminationStatus;
 }
 
 class Chrome;
@@ -46,8 +48,8 @@
     const base::DictionaryValue* custom_local_state);
 Status ParseDevToolsActivePortFile(const base::FilePath& user_data_dir,
                                    int* port);
-Status ReadInPort(const base::FilePath& port_filepath, int* port);
 Status RemoveOldDevToolsActivePortFile(const base::FilePath& user_data_dir);
+std::string GetTerminationReason(base::TerminationStatus status);
 }  // namespace internal
 
 #endif  // CHROME_TEST_CHROMEDRIVER_CHROME_LAUNCHER_H_
diff --git a/chrome/test/chromedriver/chrome_launcher_unittest.cc b/chrome/test/chromedriver/chrome_launcher_unittest.cc
index 70b0508..88a27989c 100644
--- a/chrome/test/chromedriver/chrome_launcher_unittest.cc
+++ b/chrome/test/chromedriver/chrome_launcher_unittest.cc
@@ -202,7 +202,7 @@
   AssertEQ(*local_state_dict, "local.state.sub", "2");
 }
 
-TEST(DesktopLauncher, ReadInPort_Success) {
+TEST(DesktopLauncher, ParseDevToolsActivePortFile_Success) {
   base::ScopedTempDir temp_dir;
   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
   char data[] = "12345\nblahblah";
@@ -210,11 +210,12 @@
       temp_dir.GetPath().Append(FILE_PATH_LITERAL("DevToolsActivePort"));
   ASSERT_TRUE(base::WriteFile(temp_file, data, strlen(data)));
   int port;
-  ASSERT_TRUE(internal::ReadInPort(temp_file, &port).IsOk());
+  ASSERT_TRUE(
+      internal::ParseDevToolsActivePortFile(temp_dir.GetPath(), &port).IsOk());
   ASSERT_EQ(port, 12345);
 }
 
-TEST(DesktopLauncher, ReadInPort_NoNewline) {
+TEST(DesktopLauncher, ParseDevToolsActivePortFile_NoNewline) {
   base::ScopedTempDir temp_dir;
   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
   char data[] = "12345";
@@ -222,11 +223,12 @@
       temp_dir.GetPath().Append(FILE_PATH_LITERAL("DevToolsActivePort"));
   ASSERT_TRUE(base::WriteFile(temp_file, data, strlen(data)));
   int port = 1111;
-  ASSERT_FALSE(internal::ReadInPort(temp_file, &port).IsOk());
+  ASSERT_FALSE(
+      internal::ParseDevToolsActivePortFile(temp_dir.GetPath(), &port).IsOk());
   ASSERT_EQ(port, 1111);
 }
 
-TEST(DesktopLauncher, ReadInPort_NotNumber) {
+TEST(DesktopLauncher, ParseDevToolsActivePortFile_NotNumber) {
   base::ScopedTempDir temp_dir;
   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
   char data[] = "12345asdf\nblahblah";
@@ -234,16 +236,18 @@
       temp_dir.GetPath().Append(FILE_PATH_LITERAL("DevToolsActivePort"));
   ASSERT_TRUE(base::WriteFile(temp_file, data, strlen(data)));
   int port;
-  ASSERT_FALSE(internal::ReadInPort(temp_file, &port).IsOk());
+  ASSERT_FALSE(
+      internal::ParseDevToolsActivePortFile(temp_dir.GetPath(), &port).IsOk());
 }
 
-TEST(DesktopLauncher, ReadInPort_NoFile) {
+TEST(DesktopLauncher, ParseDevToolsActivePortFile_NoFile) {
   base::ScopedTempDir temp_dir;
   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
   base::FilePath temp_file =
       temp_dir.GetPath().Append(FILE_PATH_LITERAL("DevToolsActivePort"));
   int port = 1111;
-  ASSERT_FALSE(internal::ReadInPort(temp_file, &port).IsOk());
+  ASSERT_FALSE(
+      internal::ParseDevToolsActivePortFile(temp_dir.GetPath(), &port).IsOk());
   ASSERT_EQ(port, 1111);
 }
 
diff --git a/chrome/test/chromedriver/test/run_py_tests.py b/chrome/test/chromedriver/test/run_py_tests.py
index d85577e..c92cf74 100755
--- a/chrome/test/chromedriver/test/run_py_tests.py
+++ b/chrome/test/chromedriver/test/run_py_tests.py
@@ -205,8 +205,8 @@
         'ChromeDriverTest.testCloseWindowUsingJavascript',
         # Android doesn't support headless mode
         'HeadlessInvalidCertificateTest.*',
-        # Android doesn't support user-data-dir switch
-        'ExistingUserDataDirTest.*',
+        # Tests of the desktop Chrome launch process.
+        'LaunchDesktopTest.*',
     ]
 )
 _ANDROID_NEGATIVE_FILTER['chrome_stable'] = (
@@ -2029,6 +2029,22 @@
         None,
         driver.ExecuteScript('return window.domAutomationController'))
 
+  def testRemoteDebugPortSwitchError(self):
+    """Tests that passing --remote-debugging-port through capabilities raises a
+    ChromeDriver error."""
+    exception_raised = False
+    try:
+      driver = self.CreateDriver(chrome_switches=['remote-debugging-port=5'])
+    except Exception as e:
+      self.assertIn(
+          '\'remote-debugging-port\' is not allowed', e.message,
+          'ChromeDriver should provide a useful error message for '
+          'remote-debugging-port users.')
+      exception_raised = True
+    self.assertTrue(
+        exception_raised,
+        'ChromeDriver should not allow the --remote-debugging-port flag.')
+
 
 class ChromeDesiredCapabilityTest(ChromeDriverBaseTest):
   """Tests that chromedriver properly processes desired capabilities."""
@@ -2621,25 +2637,73 @@
     raise RuntimeError('Cannot find open port')
 
 
-class ExistingUserDataDirTest(ChromeDriverBaseTest):
+class LaunchDesktopTest(ChromeDriverBaseTest):
+  """Tests that launching desktop Chrome works."""
 
-  def setUp(self):
-    self.user_data_dir = tempfile.mkdtemp()
+  def testExistingDevToolsPortFile(self):
+    """If a DevTools port file already exists before startup, then we should
+    ignore it and get our debug port number from the new file."""
+    user_data_dir = tempfile.mkdtemp()
+    try:
+      dev_tools_port_file = os.path.join(user_data_dir, 'DevToolsActivePort')
+      with open(dev_tools_port_file, 'w') as fd:
+        fd.write('34\n/devtools/browser/2dab5fb1-5571-40d8-a6ad-98823bc5ff84')
+      driver = self.CreateDriver(
+          chrome_switches=['user-data-dir=' + user_data_dir])
+      with open(dev_tools_port_file, 'r') as fd:
+        port = int(fd.readlines()[0])
+      # Ephemeral ports are always high numbers.
+      self.assertTrue(port > 100)
+    finally:
+      shutil.rmtree(user_data_dir, ignore_errors=True)
 
-  def tearDown(self):
-    super(ExistingUserDataDirTest, self).tearDown()
-    shutil.rmtree(self.user_data_dir, ignore_errors=True)
+  def testHelpfulErrorMessage_NormalExit(self):
+    """If Chrome fails to start, we should provide a useful error message."""
+    if util.IsWindows():
+      # Not bothering implementing a Windows test since then I would have
+      # to implement Windows-specific code for a program that quits and ignores
+      # any arguments. Linux and Mac should be good enough coverage.
+      return
 
-  def testStartUpWithExistingDevToolsPortFile(self):
-    dev_tools_port_file = os.path.join(self.user_data_dir, 'DevToolsActivePort')
-    with open(dev_tools_port_file, 'w') as fd:
-      fd.write('34\n/devtools/browser/2dab5fb1-5571-40d8-a6ad-98823bc5ff84')
-    driver = self.CreateDriver(
-        chrome_switches=['user-data-dir=' + self.user_data_dir])
-    with open(dev_tools_port_file, 'r') as fd:
-      port = int(fd.readlines()[0])
-    # Ephemeral ports are always high numbers.
-    self.assertTrue(port > 100)
+    file_descriptor, path = tempfile.mkstemp()
+    try:
+      os.write(file_descriptor, '#!/bin/bash\nexit 0')
+      os.close(file_descriptor)
+      os.chmod(path, 0777)
+      exception_raised = False
+      try:
+        driver = chromedriver.ChromeDriver(_CHROMEDRIVER_SERVER_URL,
+                                           chrome_binary=path,
+                                           test_name=self.id())
+      except Exception as e:
+        self.assertIn('Chrome failed to start', e.message)
+        self.assertIn('exited normally', e.message)
+        self.assertIn('ChromeDriver is assuming that Chrome has crashed',
+                      e.message)
+        exception_raised = True
+      self.assertTrue(exception_raised)
+      try:
+        driver.Quit()
+      except:
+        pass
+    finally:
+      pass
+      os.remove(path)
+
+  def testNoBinaryErrorMessage(self):
+    temp_dir = tempfile.mkdtemp()
+    exception_raised = False
+    try:
+      driver = chromedriver.ChromeDriver(
+          _CHROMEDRIVER_SERVER_URL,
+          chrome_binary=os.path.join(temp_dir, 'this_file_should_not_exist'),
+          test_name=self.id())
+    except Exception as e:
+      self.assertIn('no chrome binary', e.message)
+      exception_raised = True
+    finally:
+      shutil.rmtree(temp_dir)
+    self.assertTrue(exception_raised)
 
 
 class PerfTest(ChromeDriverBaseTest):
@@ -2884,7 +2948,6 @@
 
     for failure in result.failures + result.errors:
       output['tests'][failure[0].id()]['actual'] = 'FAIL'
-      output['tests'][failure[0].id()]['unexpected'] = True
 
     num_fails = len(result.failures) + len(result.errors)
     output['num_failures_by_type']['FAIL'] = num_fails
diff --git a/chrome/test/data/extensions/api_test/automation/tests/tabs/tab_id.js b/chrome/test/data/extensions/api_test/automation/tests/tabs/tab_id.js
index 49b9f922..da69b1c 100644
--- a/chrome/test/data/extensions/api_test/automation/tests/tabs/tab_id.js
+++ b/chrome/test/data/extensions/api_test/automation/tests/tabs/tab_id.js
@@ -1,15 +1,14 @@
-
 // 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.
 
-function createBackgroundTab(url, callback) {
+function createTabInNewInactiveWindow(url, callback) {
   chrome.tabs.query({ active: true }, function(tabs) {
     chrome.test.assertEq(1, tabs.length);
     var originalActiveTab = tabs[0];
-    createTab(url, function(tab) {
+    chrome.windows.create({"url": url, "focused": false}, function(win) {
       chrome.tabs.update(originalActiveTab.id, { active: true }, function() {
-        callback(tab);
+        callback(win.tabs[0]);
       });
     })
   });
@@ -26,7 +25,7 @@
     getUrlFromConfig('index.html', function(url) {
       // Keep the NTP as the active tab so that we know we're requesting the
       // tab by ID rather than just getting the active tab still.
-      createBackgroundTab(url, function(tab) {
+      createTabInNewInactiveWindow(url, function(tab) {
         chrome.automation.getTree(tab.id, function(rootNode) {
           if (rootNode.docLoaded) {
             assertCorrectTab(rootNode);
diff --git a/chrome/test/data/pdf/basic_test.js b/chrome/test/data/pdf/basic_test.js
index 5de3eea..dbde2de 100644
--- a/chrome/test/data/pdf/basic_test.js
+++ b/chrome/test/data/pdf/basic_test.js
@@ -41,7 +41,7 @@
   function testIgnoreKeyEvents() {
     // Test that the traversal through the shadow DOM works correctly.
     var toolbar = document.getElementById('toolbar');
-    toolbar.$.pageselector.$.input.focus();
+    toolbar.$.pageselector.pageSelector.focus();
     chrome.test.assertTrue(shouldIgnoreKeyEvents(toolbar));
 
     // Test case where the active element has a shadow root of its own.
diff --git a/chrome/test/data/pdf/material_elements_test.js b/chrome/test/data/pdf/material_elements_test.js
index 83d22bc..7c1622d 100644
--- a/chrome/test/data/pdf/material_elements_test.js
+++ b/chrome/test/data/pdf/material_elements_test.js
@@ -39,7 +39,7 @@
         Polymer.Base.create('viewer-page-selector', {docLength: 1234});
     document.body.appendChild(selector);
 
-    var input = selector.$.input;
+    var input = selector.pageSelector;
     // Simulate entering text into `input` and pressing enter.
     function changeInput(newValue) {
       input.value = newValue;
@@ -65,7 +65,8 @@
     chrome.test.assertEq(999, navigatedPages[0]);
     chrome.test.assertEq(1233, navigatedPages[1]);
     chrome.test.assertEq(11, navigatedPages[2]);
-    chrome.test.assertEq(2, navigatedPages[3]);
+    // If the user types 3.14, the . will be ignored but 14 will be captured.
+    chrome.test.assertEq(313, navigatedPages[3]);
 
     chrome.test.succeed();
   },
@@ -78,7 +79,7 @@
         Polymer.Base.create('viewer-page-selector', {docLength: 1234});
     document.body.appendChild(selector);
     chrome.test.assertEq('1234', selector.$.pagelength.textContent);
-    chrome.test.assertEq('4ch', selector.$.pageselector.style.width);
+    chrome.test.assertEq('4ch', selector.pageSelector.style.width);
     chrome.test.succeed();
   },
 
diff --git a/chrome/test/data/safe_browsing/download_protection/navigation_observer/iframe.html b/chrome/test/data/safe_browsing/download_protection/navigation_observer/iframe.html
index 9973fb66..3e0b6e4 100644
--- a/chrome/test/data/safe_browsing/download_protection/navigation_observer/iframe.html
+++ b/chrome/test/data/safe_browsing/download_protection/navigation_observer/iframe.html
@@ -1,9 +1,16 @@
 <html>
   <head>
+    <script>
+      function clickLink(linkId) {
+        var node = document.getElementById(linkId);
+        if (node != null)
+          node.click();
+      }
+    </script>
   </head>
   <body>
     <a id="iframe_direct_download" href="../signed.exe">
       Direct download from an iframe
     </a><br>
   </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/chrome/test/data/safe_browsing/download_protection/navigation_observer/iframe_retargeting.html b/chrome/test/data/safe_browsing/download_protection/navigation_observer/iframe_retargeting.html
index 80eae40..7ec5289 100644
--- a/chrome/test/data/safe_browsing/download_protection/navigation_observer/iframe_retargeting.html
+++ b/chrome/test/data/safe_browsing/download_protection/navigation_observer/iframe_retargeting.html
@@ -1,6 +1,11 @@
 <html>
   <head>
-    <script> 
+    <script>
+      function clickLink(linkId) {
+        var node = document.getElementById(linkId);
+        if (node != null)
+          node.click();
+      }
       function downloadInNewTab() {
         var tab = window.open('');
         tab.opener = null;
@@ -15,4 +20,4 @@
       Open download in new tab frome an iframe
     </a><br>
   </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/chrome/test/data/safe_browsing/download_protection/navigation_observer/navigation_observer_multi_frame_tests.html b/chrome/test/data/safe_browsing/download_protection/navigation_observer/navigation_observer_multi_frame_tests.html
index 363ae10f..a2370760 100644
--- a/chrome/test/data/safe_browsing/download_protection/navigation_observer/navigation_observer_multi_frame_tests.html
+++ b/chrome/test/data/safe_browsing/download_protection/navigation_observer/navigation_observer_multi_frame_tests.html
@@ -1,19 +1,8 @@
 <html>
   <head>
-    <script>
-    // Identify the link by frame id and element id, click on it.
-    function clickLink(frameId, targetId) {
-      var iframe = document.getElementById(frameId);
-      var innerDoc = (iframe.contentDocument) ?
-          iframe.contentDocument : iframe.contentWindow.document;
-      var node = innerDoc.getElementById(targetId);
-      // Click and open link in the same tab.
-      node.click();
-    }
-    </script>
   </head>
   <body>
     <iframe id="iframe1" src="iframe.html"></iframe><br>
     <iframe id="iframe2" src="iframe_retargeting.html"></iframe>
   </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/chrome/test/data/webui/cr_elements/cr_input_test.js b/chrome/test/data/webui/cr_elements/cr_input_test.js
index 54d4ef1..7f89f1de 100644
--- a/chrome/test/data/webui/cr_elements/cr_input_test.js
+++ b/chrome/test/data/webui/cr_elements/cr_input_test.js
@@ -7,12 +7,16 @@
   let input;
 
   setup(function() {
+    regenerateNewInput();
+  });
+
+  function regenerateNewInput() {
     PolymerTest.clearBody();
     crInput = document.createElement('cr-input');
     document.body.appendChild(crInput);
     input = crInput.$.input;
     Polymer.dom.flush();
-  });
+  }
 
   test('AttributesCorrectlySupported', function() {
     const attributesToTest = [
@@ -25,17 +29,30 @@
       ['pattern', 'pattern', '', '[a-z]+'],
       ['readonly', 'readOnly', false, true],
       ['required', 'required', false, true],
-      ['tab-index', 'tabIndex', 0, -1],
+      ['tabindex', 'tabIndex', 0, -1],
       ['type', 'type', 'text', 'password'],
     ];
 
     attributesToTest.forEach(attr => {
+      regenerateNewInput();
       assertEquals(attr[2], input[attr[1]]);
       crInput.setAttribute(attr[0], attr[3]);
       assertEquals(attr[3], input[attr[1]]);
     });
   });
 
+  test('togglingDisableModifiesTabIndexCorrectly', function() {
+    crInput.tabindex = 14;
+    assertEquals('14', crInput.getAttribute('tabindex'));
+    assertEquals(14, input.tabIndex);
+    crInput.disabled = true;
+    assertEquals('-1', crInput.getAttribute('tabindex'));
+    assertEquals(-1, input.tabIndex);
+    crInput.disabled = false;
+    assertEquals('14', crInput.getAttribute('tabindex'));
+    assertEquals(14, input.tabIndex);
+  });
+
   test('placeholderCorrectlyBound', function() {
     assertFalse(input.hasAttribute('placeholder'));
 
diff --git a/chrome/test/data/webui/settings/sync_account_control_test.js b/chrome/test/data/webui/settings/sync_account_control_test.js
index 2eb067a..e3844af4 100644
--- a/chrome/test/data/webui/settings/sync_account_control_test.js
+++ b/chrome/test/data/webui/settings/sync_account_control_test.js
@@ -135,10 +135,11 @@
       assertTrue(!!testElement.$$('#menu'));
       assertFalse(testElement.$$('#menu').open);
       const items = testElement.root.querySelectorAll('.dropdown-item');
-      assertEquals(3, items.length);
+      assertEquals(4, items.length);
       assertTrue(items[0].textContent.includes('foo@foo.com'));
       assertTrue(items[1].textContent.includes('bar@bar.com'));
       assertEquals(items[2].id, 'sign-in-item');
+      assertEquals(items[3].id, 'sign-out-item');
 
       // "sync to" button is showing the correct name and syncs with the
       // correct account when clicked.
diff --git a/chromecast/media/service/DEPS b/chromecast/media/service/DEPS
index 124a72b..0f5a829 100644
--- a/chromecast/media/service/DEPS
+++ b/chromecast/media/service/DEPS
@@ -1,4 +1,5 @@
 include_rules = [
   "+media/mojo",
   "+mojo/public/cpp",
+  "+services/service_manager/public",
 ]
diff --git a/chromecast/media/service/cast_mojo_media_client.cc b/chromecast/media/service/cast_mojo_media_client.cc
index fa707dc..d0be59b 100644
--- a/chromecast/media/service/cast_mojo_media_client.cc
+++ b/chromecast/media/service/cast_mojo_media_client.cc
@@ -43,7 +43,7 @@
     const std::string& audio_device_id) {
   return std::make_unique<CastRenderer>(
       backend_factory_, task_runner, audio_device_id, video_mode_switcher_,
-      video_resolution_policy_, media_resource_tracker_);
+      video_resolution_policy_, media_resource_tracker_, connector_);
 }
 
 std::unique_ptr<::media::CdmFactory> CastMojoMediaClient::CreateCdmFactory(
diff --git a/chromecast/media/service/cast_renderer.cc b/chromecast/media/service/cast_renderer.cc
index b5b1371..bcbd1d1 100644
--- a/chromecast/media/service/cast_renderer.cc
+++ b/chromecast/media/service/cast_renderer.cc
@@ -28,6 +28,7 @@
 #include "media/base/media_log.h"
 #include "media/base/media_resource.h"
 #include "media/base/renderer_client.h"
+#include "services/service_manager/public/cpp/connector.h"
 
 namespace chromecast {
 namespace media {
@@ -55,7 +56,8 @@
     const std::string& audio_device_id,
     VideoModeSwitcher* video_mode_switcher,
     VideoResolutionPolicy* video_resolution_policy,
-    MediaResourceTracker* media_resource_tracker)
+    MediaResourceTracker* media_resource_tracker,
+    service_manager::Connector* connector)
     : backend_factory_(backend_factory),
       task_runner_(task_runner),
       audio_device_id_(audio_device_id.empty()
@@ -64,6 +66,7 @@
       video_mode_switcher_(video_mode_switcher),
       video_resolution_policy_(video_resolution_policy),
       media_resource_tracker_(media_resource_tracker),
+      connector_(connector),
       client_(nullptr),
       cast_cdm_context_(nullptr),
       media_task_runner_factory_(
@@ -111,8 +114,9 @@
   } else {
     content_type = AudioContentType::kMedia;
   }
-  MediaPipelineDeviceParams params(sync_type, backend_task_runner_.get(),
-                                   content_type, audio_device_id_);
+  MediaPipelineDeviceParams params(
+      sync_type, MediaPipelineDeviceParams::AudioStreamType::kAudioStreamNormal,
+      backend_task_runner_.get(), content_type, audio_device_id_, connector_);
 
   if (audio_device_id_ == kTtsAudioDeviceId ||
       audio_device_id_ ==
diff --git a/chromecast/media/service/cast_renderer.h b/chromecast/media/service/cast_renderer.h
index cd4b2d52..b924732 100644
--- a/chromecast/media/service/cast_renderer.h
+++ b/chromecast/media/service/cast_renderer.h
@@ -19,6 +19,10 @@
 class SingleThreadTaskRunner;
 }  // namespace base
 
+namespace service_manager {
+class Connector;
+}  // namespace service_manager
+
 namespace chromecast {
 class TaskRunnerImpl;
 
@@ -36,7 +40,8 @@
                const std::string& audio_device_id,
                VideoModeSwitcher* video_mode_switcher,
                VideoResolutionPolicy* video_resolution_policy,
-               MediaResourceTracker* media_resource_tracker);
+               MediaResourceTracker* media_resource_tracker,
+               service_manager::Connector* connector);
   ~CastRenderer() final;
 
   // ::media::Renderer implementation.
@@ -74,6 +79,7 @@
   VideoModeSwitcher* video_mode_switcher_;
   VideoResolutionPolicy* video_resolution_policy_;
   MediaResourceTracker* media_resource_tracker_;
+  service_manager::Connector* connector_;
   // Must outlive |pipeline_| to properly count resource usage.
   std::unique_ptr<MediaResourceTracker::ScopedUsage> media_resource_usage_;
 
diff --git a/chromecast/public/media/media_pipeline_device_params.h b/chromecast/public/media/media_pipeline_device_params.h
index 47375d3c..78643d43 100644
--- a/chromecast/public/media/media_pipeline_device_params.h
+++ b/chromecast/public/media/media_pipeline_device_params.h
@@ -7,6 +7,10 @@
 
 #include <string>
 
+namespace service_manager {
+class Connector;
+}  // namespace service_manager
+
 namespace chromecast {
 class TaskRunner;
 
@@ -47,6 +51,7 @@
       : sync_type(kModeSyncPts),
         audio_type(kAudioStreamNormal),
         task_runner(task_runner_in),
+        connector(nullptr),
         content_type(content_type_in),
         device_id(device_id_in) {}
 
@@ -57,6 +62,7 @@
       : sync_type(sync_type_in),
         audio_type(kAudioStreamNormal),
         task_runner(task_runner_in),
+        connector(nullptr),
         content_type(content_type_in),
         device_id(device_id_in) {}
 
@@ -64,10 +70,12 @@
                             AudioStreamType audio_type_in,
                             TaskRunner* task_runner_in,
                             AudioContentType content_type_in,
-                            const std::string& device_id_in)
+                            const std::string& device_id_in,
+                            service_manager::Connector* connector_in = nullptr)
       : sync_type(sync_type_in),
         audio_type(audio_type_in),
         task_runner(task_runner_in),
+        connector(connector_in),
         content_type(content_type_in),
         device_id(device_id_in) {}
 
@@ -80,6 +88,9 @@
   // some backends.
   TaskRunner* const task_runner;
 
+  // connector allows the backend to bind to services through ServiceManager.
+  service_manager::Connector* const connector;
+
   // Identifies the content type for volume control.
   const AudioContentType content_type;
   const std::string device_id;
diff --git a/chromeos/BUILD.gn b/chromeos/BUILD.gn
index 7ff4fdf..9d7730d 100644
--- a/chromeos/BUILD.gn
+++ b/chromeos/BUILD.gn
@@ -51,6 +51,7 @@
     "//google_apis",
     "//media/base:video_facing",
     "//net",
+    "//services/network/public/cpp",
     "//skia",  # For components/user_manager
     "//third_party/icu",
     "//third_party/protobuf:protobuf_lite",
diff --git a/chromeos/DEPS b/chromeos/DEPS
index 2043a514..a5f3f90 100644
--- a/chromeos/DEPS
+++ b/chromeos/DEPS
@@ -12,6 +12,7 @@
   "+google_apis/gaia",
   "+media/base/video_facing.h",
   "+net",
+  "+services/network/public",
   "+third_party/cros_system_api",
   "+third_party/protobuf",
 
diff --git a/chromeos/account_manager/account_manager.cc b/chromeos/account_manager/account_manager.cc
index 1fb4eec..c294583 100644
--- a/chromeos/account_manager/account_manager.cc
+++ b/chromeos/account_manager/account_manager.cc
@@ -21,6 +21,7 @@
 #include "google_apis/gaia/gaia_constants.h"
 #include "google_apis/gaia/oauth2_access_token_fetcher_impl.h"
 #include "net/url_request/url_request_context_getter.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
 #include "third_party/protobuf/src/google/protobuf/message_lite.h"
 
 namespace chromeos {
@@ -355,7 +356,7 @@
 std::unique_ptr<OAuth2AccessTokenFetcher>
 AccountManager::CreateAccessTokenFetcher(
     const AccountKey& account_key,
-    net::URLRequestContextGetter* getter,
+    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
     OAuth2AccessTokenConsumer* consumer) const {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
@@ -364,8 +365,8 @@
     return nullptr;
   }
 
-  return std::make_unique<OAuth2AccessTokenFetcherImpl>(consumer, getter,
-                                                        it->second);
+  return std::make_unique<OAuth2AccessTokenFetcherImpl>(
+      consumer, url_loader_factory, it->second);
 }
 
 bool AccountManager::IsTokenAvailable(const AccountKey& account_key) const {
diff --git a/chromeos/account_manager/account_manager.h b/chromeos/account_manager/account_manager.h
index d5fcf4c..1cd8aafe 100644
--- a/chromeos/account_manager/account_manager.h
+++ b/chromeos/account_manager/account_manager.h
@@ -33,7 +33,11 @@
 
 namespace net {
 class URLRequestContextGetter;
-}  // namespace net
+}
+
+namespace network {
+class SharedURLLoaderFactory;
+}
 
 namespace chromeos {
 
@@ -132,7 +136,7 @@
   // |account_key|, otherwise a |nullptr| is returned.
   std::unique_ptr<OAuth2AccessTokenFetcher> CreateAccessTokenFetcher(
       const AccountKey& account_key,
-      net::URLRequestContextGetter* getter,
+      scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
       OAuth2AccessTokenConsumer* consumer) const;
 
   // Returns |true| if an LST is available for |account_key|.
diff --git a/chromeos/components/proximity_auth/BUILD.gn b/chromeos/components/proximity_auth/BUILD.gn
index 7bafc9e..e6770ff 100644
--- a/chromeos/components/proximity_auth/BUILD.gn
+++ b/chromeos/components/proximity_auth/BUILD.gn
@@ -55,6 +55,8 @@
     "//chromeos",
     "//chromeos/components/proximity_auth/logging",
     "//chromeos/components/proximity_auth/public/interfaces",
+    "//chromeos/services/secure_channel/public/cpp/client",
+    "//chromeos/services/secure_channel/public/mojom",
     "//components/account_id",
     "//components/cryptauth",
     "//components/cryptauth/ble",
@@ -113,6 +115,7 @@
     "//chromeos",
     "//chromeos/components/proximity_auth/logging",
     "//chromeos/components/proximity_auth/logging:unit_tests",
+    "//chromeos/services/secure_channel/public/cpp/client:test_support",
     "//components/cryptauth:test_support",
     "//components/prefs:test_support",
     "//components/sync_preferences:test_support",
diff --git a/chromeos/components/proximity_auth/proximity_monitor_impl.cc b/chromeos/components/proximity_auth/proximity_monitor_impl.cc
index df21020a..c857d66 100644
--- a/chromeos/components/proximity_auth/proximity_monitor_impl.cc
+++ b/chromeos/components/proximity_auth/proximity_monitor_impl.cc
@@ -16,6 +16,7 @@
 #include "chromeos/components/proximity_auth/metrics.h"
 #include "chromeos/components/proximity_auth/proximity_auth_pref_manager.h"
 #include "chromeos/components/proximity_auth/proximity_monitor_observer.h"
+#include "chromeos/services/secure_channel/public/cpp/client/client_channel.h"
 #include "device/bluetooth/bluetooth_adapter.h"
 #include "device/bluetooth/bluetooth_adapter_factory.h"
 
@@ -33,13 +34,17 @@
 const int kDefaultRssiThreshold = -70;
 
 ProximityMonitorImpl::ProximityMonitorImpl(
+    cryptauth::RemoteDeviceRef remote_device,
+    chromeos::secure_channel::ClientChannel* channel,
     cryptauth::Connection* connection,
     ProximityAuthPrefManager* pref_manager)
-    : connection_(connection),
+    : remote_device_(remote_device),
+      channel_(channel),
+      connection_(connection),
+      pref_manager_(pref_manager),
       remote_device_is_in_proximity_(false),
       is_active_(false),
       rssi_threshold_(kDefaultRssiThreshold),
-      pref_manager_(pref_manager),
       polling_weak_ptr_factory_(this),
       weak_ptr_factory_(this) {
   if (device::BluetoothAdapterFactory::IsBluetoothSupported()) {
@@ -76,7 +81,7 @@
                                     : metrics::kUnknownProximityValue;
 
   std::string remote_device_model = metrics::kUnknownDeviceModel;
-  cryptauth::RemoteDeviceRef remote_device = connection_->remote_device();
+  cryptauth::RemoteDeviceRef remote_device = remote_device_;
   if (!remote_device.name().empty())
     remote_device_model = remote_device.name();
 
@@ -131,37 +136,69 @@
 void ProximityMonitorImpl::Poll() {
   DCHECK(ShouldPoll());
 
-  std::string address = connection_->GetDeviceAddress();
-  BluetoothDevice* device = bluetooth_adapter_->GetDevice(address);
+  if (base::FeatureList::IsEnabled(chromeos::features::kMultiDeviceApi)) {
+    if (channel_->is_disconnected()) {
+      PA_LOG(ERROR) << "Channel is disconnected.";
+      ClearProximityState();
+      return;
+    }
 
-  if (!device) {
-    PA_LOG(ERROR) << "Unknown Bluetooth device with address " << address;
-    ClearProximityState();
-    return;
-  }
-  if (!device->IsConnected()) {
-    PA_LOG(ERROR) << "Bluetooth device with address " << address
-                  << " is not connected.";
-    ClearProximityState();
-    return;
-  }
+    channel_->GetConnectionMetadata(
+        base::BindOnce(&ProximityMonitorImpl::OnGetConnectionMetadata,
+                       weak_ptr_factory_.GetWeakPtr()));
+  } else {
+    std::string address = connection_->GetDeviceAddress();
+    BluetoothDevice* device = bluetooth_adapter_->GetDevice(address);
 
-  device->GetConnectionInfo(base::Bind(&ProximityMonitorImpl::OnConnectionInfo,
-                                       weak_ptr_factory_.GetWeakPtr()));
+    if (!device) {
+      PA_LOG(ERROR) << "Unknown Bluetooth device with address " << address;
+      ClearProximityState();
+      return;
+    }
+    if (!device->IsConnected()) {
+      PA_LOG(ERROR) << "Bluetooth device with address " << address
+                    << " is not connected.";
+      ClearProximityState();
+      return;
+    }
+
+    device->GetConnectionInfo(
+        base::BindRepeating(&ProximityMonitorImpl::OnConnectionInfo,
+                            weak_ptr_factory_.GetWeakPtr()));
+  }
+}
+
+void ProximityMonitorImpl::OnGetConnectionMetadata(
+    chromeos::secure_channel::mojom::ConnectionMetadataPtr
+        connection_metadata) {
+  DCHECK(base::FeatureList::IsEnabled(chromeos::features::kMultiDeviceApi));
+
+  if (connection_metadata->bluetooth_connection_metadata)
+    OnGetRssi(connection_metadata->bluetooth_connection_metadata->current_rssi);
+  else
+    OnGetRssi(base::nullopt);
 }
 
 void ProximityMonitorImpl::OnConnectionInfo(
     const BluetoothDevice::ConnectionInfo& connection_info) {
+  DCHECK(!base::FeatureList::IsEnabled(chromeos::features::kMultiDeviceApi));
+
+  if (connection_info.rssi == BluetoothDevice::kUnknownPower)
+    OnGetRssi(base::nullopt);
+  else
+    OnGetRssi(connection_info.rssi);
+}
+
+void ProximityMonitorImpl::OnGetRssi(const base::Optional<int32_t>& rssi) {
   if (!is_active_) {
-    PA_LOG(INFO) << "[Proximity] Got connection info after stopping";
+    PA_LOG(INFO) << "Received RSSI after stopping.";
     return;
   }
 
-  if (connection_info.rssi != BluetoothDevice::kUnknownPower) {
-    AddSample(connection_info);
+  if (rssi) {
+    AddSample(*rssi);
   } else {
-    PA_LOG(WARNING) << "[Proximity] Unknown values received from API: "
-                    << connection_info.rssi;
+    PA_LOG(WARNING) << "Received invalid RSSI value.";
     rssi_rolling_average_.reset();
     CheckForProximityStateChange();
   }
@@ -177,14 +214,13 @@
   rssi_rolling_average_.reset();
 }
 
-void ProximityMonitorImpl::AddSample(
-    const BluetoothDevice::ConnectionInfo& connection_info) {
+void ProximityMonitorImpl::AddSample(int32_t rssi) {
   double weight = kRssiSampleWeight;
   if (!rssi_rolling_average_) {
-    rssi_rolling_average_.reset(new double(connection_info.rssi));
+    rssi_rolling_average_.reset(new double(rssi));
   } else {
     *rssi_rolling_average_ =
-        weight * connection_info.rssi + (1 - weight) * (*rssi_rolling_average_);
+        weight * rssi + (1 - weight) * (*rssi_rolling_average_);
   }
 
   CheckForProximityStateChange();
diff --git a/chromeos/components/proximity_auth/proximity_monitor_impl.h b/chromeos/components/proximity_auth/proximity_monitor_impl.h
index 17fca4e..d8153be 100644
--- a/chromeos/components/proximity_auth/proximity_monitor_impl.h
+++ b/chromeos/components/proximity_auth/proximity_monitor_impl.h
@@ -11,14 +11,23 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
+#include "base/optional.h"
+#include "chromeos/chromeos_features.h"
 #include "chromeos/components/proximity_auth/proximity_monitor.h"
+#include "chromeos/services/secure_channel/public/mojom/secure_channel.mojom.h"
 #include "components/cryptauth/connection.h"
 #include "components/cryptauth/remote_device_ref.h"
 #include "device/bluetooth/bluetooth_device.h"
 
+namespace chromeos {
+namespace secure_channel {
+class ClientChannel;
+}  // namespace secure_channel
+}  // namespace chromeos
+
 namespace device {
 class BluetoothAdapter;
-}
+}  // namespace device
 
 namespace proximity_auth {
 
@@ -29,7 +38,9 @@
 class ProximityMonitorImpl : public ProximityMonitor {
  public:
   // The |connection| is not owned, and must outlive |this| instance.
-  ProximityMonitorImpl(cryptauth::Connection* connection,
+  ProximityMonitorImpl(cryptauth::RemoteDeviceRef remote_device,
+                       chromeos::secure_channel::ClientChannel* channel,
+                       cryptauth::Connection* connection,
                        ProximityAuthPrefManager* pref_manager);
   ~ProximityMonitorImpl() override;
 
@@ -62,18 +73,19 @@
   // Polls the connection information.
   void Poll();
 
-  // Callback to received the polled-for connection info.
+  void OnGetConnectionMetadata(
+      chromeos::secure_channel::mojom::ConnectionMetadataPtr
+          connection_metadata);
   void OnConnectionInfo(
       const device::BluetoothDevice::ConnectionInfo& connection_info);
+  void OnGetRssi(const base::Optional<int32_t>& rssi);
 
   // Resets the proximity state to |false|, and clears all member variables
   // tracking the proximity state.
   void ClearProximityState();
 
-  // Updates the proximity state with a new |connection_info| sample of the
-  // current RSSI.
-  void AddSample(
-      const device::BluetoothDevice::ConnectionInfo& connection_info);
+  // Updates the proximity state with a new sample of the current RSSI.
+  void AddSample(int32_t rssi);
 
   // Checks whether the proximity state has changed based on the current
   // samples. Notifies |observers_| on a change.
@@ -83,10 +95,19 @@
   // RSSI value.
   void GetRssiThresholdFromPrefs();
 
-  // The current connection being monitored. Not owned and must outlive this
-  // instance.
+  // Used to get the name of the remote device that ProximitMonitor is
+  // communicating with, for metrics purposes.
+  cryptauth::RemoteDeviceRef remote_device_;
+
+  // Used to communicate with the remote device to gauge its proximity via RSSI
+  // measurement.
+  chromeos::secure_channel::ClientChannel* channel_;
   cryptauth::Connection* connection_;
 
+  // Used to get determine the user pref for how far away the phone is allowed
+  // to be.
+  ProximityAuthPrefManager* pref_manager_;
+
   // The observers attached to the ProximityMonitor.
   base::ObserverList<ProximityMonitorObserver> observers_;
 
@@ -110,10 +131,6 @@
   // measurement.
   std::unique_ptr<double> rssi_rolling_average_;
 
-  // Contains perferences that outlive the lifetime of this object and across
-  // process restarts. Not owned and must outlive this instance.
-  ProximityAuthPrefManager* pref_manager_;
-
   // Used to vend weak pointers for polling. Using a separate factory for these
   // weak pointers allows the weak pointers to be invalidated when polling
   // stops, which effectively cancels the scheduled tasks.
diff --git a/chromeos/components/proximity_auth/proximity_monitor_impl_unittest.cc b/chromeos/components/proximity_auth/proximity_monitor_impl_unittest.cc
index acf782a..7736a7d 100644
--- a/chromeos/components/proximity_auth/proximity_monitor_impl_unittest.cc
+++ b/chromeos/components/proximity_auth/proximity_monitor_impl_unittest.cc
@@ -11,13 +11,16 @@
 #include "base/memory/ptr_util.h"
 #include "base/memory/ref_counted.h"
 #include "base/test/metrics/histogram_tester.h"
+#include "base/test/scoped_feature_list.h"
 #include "base/test/simple_test_tick_clock.h"
 #include "base/test/test_simple_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
+#include "chromeos/chromeos_features.h"
 #include "chromeos/components/proximity_auth/logging/logging.h"
 #include "chromeos/components/proximity_auth/proximity_auth_profile_pref_manager.h"
 #include "chromeos/components/proximity_auth/proximity_monitor_observer.h"
+#include "chromeos/services/secure_channel/public/cpp/client/fake_client_channel.h"
 #include "components/cryptauth/fake_connection.h"
 #include "components/cryptauth/remote_device_ref.h"
 #include "components/cryptauth/remote_device_test_util.h"
@@ -90,13 +93,18 @@
                                  "",
                                  false /* paired */,
                                  true /* connected */),
+        fake_client_channel_(
+            std::make_unique<chromeos::secure_channel::FakeClientChannel>()),
         remote_device_(cryptauth::RemoteDeviceRefBuilder()
                            .SetUserId(kRemoteDeviceUserId)
                            .SetName(kRemoteDeviceName)
                            .Build()),
         connection_(remote_device_),
         pref_manager_(new NiceMock<MockProximityAuthPrefManager>()),
-        monitor_(&connection_, pref_manager_.get()),
+        monitor_(remote_device_,
+                 fake_client_channel_.get(),
+                 &connection_,
+                 pref_manager_.get()),
         task_runner_(new base::TestSimpleTaskRunner()),
         thread_task_runner_handle_(task_runner_) {
     ON_CALL(*bluetooth_adapter_, GetDevice(std::string()))
@@ -110,16 +118,42 @@
 
   ~ProximityAuthProximityMonitorImplTest() override {}
 
+  void SetMultiDeviceApiEnabled() {
+    scoped_feature_list_.InitAndEnableFeature(
+        chromeos::features::kMultiDeviceApi);
+  }
+
   void RunPendingTasks() { task_runner_->RunPendingTasks(); }
 
-  void ProvideConnectionInfo(
-      const BluetoothDevice::ConnectionInfo& connection_info) {
+  void ProvideRssi(base::Optional<int32_t> rssi) {
     RunPendingTasks();
-    connection_info_callback_.Run(connection_info);
 
-    // Reset the callback to ensure that tests correctly only respond at most
-    // once per call to GetConnectionInfo().
-    connection_info_callback_ = BluetoothDevice::ConnectionInfoCallback();
+    if (base::FeatureList::IsEnabled(chromeos::features::kMultiDeviceApi)) {
+      std::vector<chromeos::secure_channel::mojom::ConnectionCreationDetail>
+          creation_details{
+              chromeos::secure_channel::mojom::ConnectionCreationDetail::
+                  REMOTE_DEVICE_USED_BACKGROUND_BLE_ADVERTISING};
+
+      chromeos::secure_channel::mojom::BluetoothConnectionMetadataPtr
+          bluetooth_connection_metadata_ptr;
+      if (rssi) {
+        bluetooth_connection_metadata_ptr =
+            chromeos::secure_channel::mojom::BluetoothConnectionMetadata::New(
+                *rssi);
+      }
+
+      chromeos::secure_channel::mojom::ConnectionMetadataPtr
+          connection_metadata_ptr =
+              chromeos::secure_channel::mojom::ConnectionMetadata::New(
+                  creation_details,
+                  std::move(bluetooth_connection_metadata_ptr));
+      fake_client_channel_->InvokePendingGetConnectionMetadataCallback(
+          std::move(connection_metadata_ptr));
+    } else {
+      ProvideConnectionInfo({rssi ? *rssi : BluetoothDevice::kUnknownPower,
+                             4 /* transmit_power */,
+                             4 /* max_transmit_power */});
+    }
   }
 
  protected:
@@ -129,6 +163,8 @@
   // Mocks used for verifying interactions with the Bluetooth subsystem.
   scoped_refptr<device::MockBluetoothAdapter> bluetooth_adapter_;
   NiceMock<device::MockBluetoothDevice> remote_bluetooth_device_;
+  std::unique_ptr<chromeos::secure_channel::FakeClientChannel>
+      fake_client_channel_;
   cryptauth::RemoteDeviceRef remote_device_;
   cryptauth::FakeConnection connection_;
 
@@ -139,10 +175,23 @@
   ProximityMonitorImpl monitor_;
 
  private:
+  void ProvideConnectionInfo(
+      const BluetoothDevice::ConnectionInfo& connection_info) {
+    DCHECK(!base::FeatureList::IsEnabled(chromeos::features::kMultiDeviceApi));
+
+    connection_info_callback_.Run(connection_info);
+
+    // Reset the callback to ensure that tests correctly only respond at most
+    // once per call to GetConnectionInfo().
+    connection_info_callback_ = BluetoothDevice::ConnectionInfoCallback();
+  }
+
   scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
   base::ThreadTaskRunnerHandle thread_task_runner_handle_;
   BluetoothDevice::ConnectionInfoCallback connection_info_callback_;
   ScopedDisableLoggingForTesting disable_logging_;
+
+  base::test::ScopedFeatureList scoped_feature_list_;
 };
 
 TEST_F(ProximityAuthProximityMonitorImplTest, IsUnlockAllowed_NeverStarted) {
@@ -150,22 +199,51 @@
 }
 
 TEST_F(ProximityAuthProximityMonitorImplTest,
-       IsUnlockAllowed_Started_NoConnectionInfoReceivedYet) {
+       IsUnlockAllowed_Started_NoRssiReceivedYet) {
+  monitor_.Start();
+  EXPECT_FALSE(monitor_.IsUnlockAllowed());
+}
+
+TEST_F(ProximityAuthProximityMonitorImplTest,
+       IsUnlockAllowed_Started_NoRssiReceivedYet_MultiDeviceApiEnabled) {
+  SetMultiDeviceApiEnabled();
+
   monitor_.Start();
   EXPECT_FALSE(monitor_.IsUnlockAllowed());
 }
 
 TEST_F(ProximityAuthProximityMonitorImplTest, IsUnlockAllowed_RssiInRange) {
   monitor_.Start();
-  ProvideConnectionInfo({0, 4, 4});
+  ProvideRssi(4);
+  EXPECT_TRUE(monitor_.IsUnlockAllowed());
+}
+
+TEST_F(ProximityAuthProximityMonitorImplTest,
+       IsUnlockAllowed_RssiInRange_MultiDeviceApiEnabled) {
+  SetMultiDeviceApiEnabled();
+
+  monitor_.Start();
+  ProvideRssi(4);
   EXPECT_TRUE(monitor_.IsUnlockAllowed());
 }
 
 TEST_F(ProximityAuthProximityMonitorImplTest, IsUnlockAllowed_UnknownRssi) {
   monitor_.Start();
 
-  ProvideConnectionInfo({0, 0, 4});
-  ProvideConnectionInfo({BluetoothDevice::kUnknownPower, 0, 4});
+  ProvideRssi(0);
+  ProvideRssi(base::nullopt);
+
+  EXPECT_FALSE(monitor_.IsUnlockAllowed());
+}
+
+TEST_F(ProximityAuthProximityMonitorImplTest,
+       IsUnlockAllowed_UnknownRssi_MultiDeviceApiEnabled) {
+  SetMultiDeviceApiEnabled();
+
+  monitor_.Start();
+
+  ProvideRssi(0);
+  ProvideRssi(base::nullopt);
 
   EXPECT_FALSE(monitor_.IsUnlockAllowed());
 }
@@ -178,20 +256,53 @@
 
   // Simulate receiving an RSSI reading in proximity.
   EXPECT_CALL(observer_, OnProximityStateChanged()).Times(1);
-  ProvideConnectionInfo({kRssiThreshold / 2, 4, 4});
+  ProvideRssi(kRssiThreshold / 2);
   EXPECT_TRUE(monitor_.IsUnlockAllowed());
 
   // Simulate a reading indicating non-proximity.
   EXPECT_CALL(observer_, OnProximityStateChanged()).Times(1);
-  ProvideConnectionInfo({2 * kRssiThreshold, 4, 4});
-  ProvideConnectionInfo({2 * kRssiThreshold, 4, 4});
+  ProvideRssi(kRssiThreshold * 2);
+  ProvideRssi(kRssiThreshold * 2);
+  EXPECT_FALSE(monitor_.IsUnlockAllowed());
+}
+
+TEST_F(ProximityAuthProximityMonitorImplTest,
+       IsUnlockAllowed_InformsObserverOfChanges_MultiDeviceApiEnabled) {
+  SetMultiDeviceApiEnabled();
+
+  // Initially, the device is not in proximity.
+  monitor_.Start();
+  EXPECT_FALSE(monitor_.IsUnlockAllowed());
+
+  // Simulate receiving an RSSI reading in proximity.
+  EXPECT_CALL(observer_, OnProximityStateChanged()).Times(1);
+  ProvideRssi(kRssiThreshold / 2);
+  EXPECT_TRUE(monitor_.IsUnlockAllowed());
+
+  // Simulate a reading indicating non-proximity.
+  EXPECT_CALL(observer_, OnProximityStateChanged()).Times(1);
+  ProvideRssi(kRssiThreshold * 2);
+  ProvideRssi(kRssiThreshold * 2);
   EXPECT_FALSE(monitor_.IsUnlockAllowed());
 }
 
 TEST_F(ProximityAuthProximityMonitorImplTest, IsUnlockAllowed_StartThenStop) {
   monitor_.Start();
 
-  ProvideConnectionInfo({0, 0, 4});
+  ProvideRssi(0);
+  EXPECT_TRUE(monitor_.IsUnlockAllowed());
+
+  monitor_.Stop();
+  EXPECT_FALSE(monitor_.IsUnlockAllowed());
+}
+
+TEST_F(ProximityAuthProximityMonitorImplTest,
+       IsUnlockAllowed_StartThenStop_MultiDeviceApiEnabled) {
+  SetMultiDeviceApiEnabled();
+
+  monitor_.Start();
+
+  ProvideRssi(0);
   EXPECT_TRUE(monitor_.IsUnlockAllowed());
 
   monitor_.Stop();
@@ -201,18 +312,39 @@
 TEST_F(ProximityAuthProximityMonitorImplTest,
        IsUnlockAllowed_StartThenStopThenStartAgain) {
   monitor_.Start();
-  ProvideConnectionInfo({kRssiThreshold / 2, 4, 4});
-  ProvideConnectionInfo({kRssiThreshold / 2, 4, 4});
-  ProvideConnectionInfo({kRssiThreshold / 2, 4, 4});
-  ProvideConnectionInfo({kRssiThreshold / 2, 4, 4});
-  ProvideConnectionInfo({kRssiThreshold / 2, 4, 4});
+  ProvideRssi(kRssiThreshold / 2);
+  ProvideRssi(kRssiThreshold / 2);
+  ProvideRssi(kRssiThreshold / 2);
+  ProvideRssi(kRssiThreshold / 2);
+  ProvideRssi(kRssiThreshold / 2);
   EXPECT_TRUE(monitor_.IsUnlockAllowed());
   monitor_.Stop();
 
   // Restarting the monitor should immediately reset the proximity state, rather
   // than building on the previous rolling average.
   monitor_.Start();
-  ProvideConnectionInfo({kRssiThreshold - 1, 4, 4});
+  ProvideRssi(kRssiThreshold - 1);
+
+  EXPECT_FALSE(monitor_.IsUnlockAllowed());
+}
+
+TEST_F(ProximityAuthProximityMonitorImplTest,
+       IsUnlockAllowed_StartThenStopThenStartAgain_MultiDeviceApiEnabled) {
+  SetMultiDeviceApiEnabled();
+
+  monitor_.Start();
+  ProvideRssi(kRssiThreshold / 2);
+  ProvideRssi(kRssiThreshold / 2);
+  ProvideRssi(kRssiThreshold / 2);
+  ProvideRssi(kRssiThreshold / 2);
+  ProvideRssi(kRssiThreshold / 2);
+  EXPECT_TRUE(monitor_.IsUnlockAllowed());
+  monitor_.Stop();
+
+  // Restarting the monitor should immediately reset the proximity state, rather
+  // than building on the previous rolling average.
+  monitor_.Start();
+  ProvideRssi(kRssiThreshold - 1);
 
   EXPECT_FALSE(monitor_.IsUnlockAllowed());
 }
@@ -220,15 +352,33 @@
 TEST_F(ProximityAuthProximityMonitorImplTest,
        IsUnlockAllowed_RemoteDeviceRemainsInProximity) {
   monitor_.Start();
-  ProvideConnectionInfo({kRssiThreshold / 2 + 1, 4, 4});
-  ProvideConnectionInfo({kRssiThreshold / 2 - 1, 4, 4});
-  ProvideConnectionInfo({kRssiThreshold / 2 + 2, 4, 4});
-  ProvideConnectionInfo({kRssiThreshold / 2 - 3, 4, 4});
+  ProvideRssi(kRssiThreshold / 2 + 1);
+  ProvideRssi(kRssiThreshold / 2 - 1);
+  ProvideRssi(kRssiThreshold / 2 + 2);
+  ProvideRssi(kRssiThreshold / 2 - 3);
 
   EXPECT_TRUE(monitor_.IsUnlockAllowed());
 
   // Brief drops in RSSI should be handled by weighted averaging.
-  ProvideConnectionInfo({kRssiThreshold - 5, 4, 4});
+  ProvideRssi(kRssiThreshold - 5);
+
+  EXPECT_TRUE(monitor_.IsUnlockAllowed());
+}
+
+TEST_F(ProximityAuthProximityMonitorImplTest,
+       IsUnlockAllowed_RemoteDeviceRemainsInProximity_MultiDeviceApiEnabled) {
+  SetMultiDeviceApiEnabled();
+
+  monitor_.Start();
+  ProvideRssi(kRssiThreshold / 2 + 1);
+  ProvideRssi(kRssiThreshold / 2 - 1);
+  ProvideRssi(kRssiThreshold / 2 + 2);
+  ProvideRssi(kRssiThreshold / 2 - 3);
+
+  EXPECT_TRUE(monitor_.IsUnlockAllowed());
+
+  // Brief drops in RSSI should be handled by weighted averaging.
+  ProvideRssi(kRssiThreshold - 5);
 
   EXPECT_TRUE(monitor_.IsUnlockAllowed());
 }
@@ -238,22 +388,49 @@
   monitor_.Start();
 
   // Start with a device in proximity.
-  ProvideConnectionInfo({0, 4, 4});
+  ProvideRssi(0);
   EXPECT_TRUE(monitor_.IsUnlockAllowed());
 
   // Simulate readings for the remote device leaving proximity.
-  ProvideConnectionInfo({-1, 4, 4});
-  ProvideConnectionInfo({-4, 4, 4});
-  ProvideConnectionInfo({0, 4, 4});
-  ProvideConnectionInfo({-10, 4, 4});
-  ProvideConnectionInfo({-15, 4, 4});
-  ProvideConnectionInfo({-20, 4, 4});
-  ProvideConnectionInfo({kRssiThreshold, 4, 4});
-  ProvideConnectionInfo({kRssiThreshold - 10, 4, 4});
-  ProvideConnectionInfo({kRssiThreshold - 20, 4, 4});
-  ProvideConnectionInfo({kRssiThreshold - 20, 4, 4});
-  ProvideConnectionInfo({kRssiThreshold - 20, 4, 4});
-  ProvideConnectionInfo({kRssiThreshold - 20, 4, 4});
+  ProvideRssi(-1);
+  ProvideRssi(-4);
+  ProvideRssi(0);
+  ProvideRssi(-10);
+  ProvideRssi(-15);
+  ProvideRssi(-20);
+  ProvideRssi(kRssiThreshold);
+  ProvideRssi(kRssiThreshold - 10);
+  ProvideRssi(kRssiThreshold - 20);
+  ProvideRssi(kRssiThreshold - 20);
+  ProvideRssi(kRssiThreshold - 20);
+  ProvideRssi(kRssiThreshold - 20);
+
+  EXPECT_FALSE(monitor_.IsUnlockAllowed());
+}
+
+TEST_F(ProximityAuthProximityMonitorImplTest,
+       IsUnlockAllowed_RemoteDeviceLeavesProximity_MultiDeviceApiEnabled) {
+  SetMultiDeviceApiEnabled();
+
+  monitor_.Start();
+
+  // Start with a device in proximity.
+  ProvideRssi(0);
+  EXPECT_TRUE(monitor_.IsUnlockAllowed());
+
+  // Simulate readings for the remote device leaving proximity.
+  ProvideRssi(-1);
+  ProvideRssi(-4);
+  ProvideRssi(0);
+  ProvideRssi(-10);
+  ProvideRssi(-15);
+  ProvideRssi(-20);
+  ProvideRssi(kRssiThreshold);
+  ProvideRssi(kRssiThreshold - 10);
+  ProvideRssi(kRssiThreshold - 20);
+  ProvideRssi(kRssiThreshold - 20);
+  ProvideRssi(kRssiThreshold - 20);
+  ProvideRssi(kRssiThreshold - 20);
 
   EXPECT_FALSE(monitor_.IsUnlockAllowed());
 }
@@ -263,19 +440,41 @@
   monitor_.Start();
 
   // Start with a device out of proximity.
-  ProvideConnectionInfo({2 * kRssiThreshold, 4, 4});
+  ProvideRssi(kRssiThreshold * 2);
   EXPECT_FALSE(monitor_.IsUnlockAllowed());
 
   // Simulate readings for the remote device entering proximity.
-  ProvideConnectionInfo({-15, 4, 4});
-  ProvideConnectionInfo({-8, 4, 4});
-  ProvideConnectionInfo({-12, 4, 4});
-  ProvideConnectionInfo({-18, 4, 4});
-  ProvideConnectionInfo({-7, 4, 4});
-  ProvideConnectionInfo({-3, 4, 4});
-  ProvideConnectionInfo({-2, 4, 4});
-  ProvideConnectionInfo({0, 4, 4});
-  ProvideConnectionInfo({0, 4, 4});
+  ProvideRssi(-15);
+  ProvideRssi(-8);
+  ProvideRssi(-12);
+  ProvideRssi(-18);
+  ProvideRssi(-7);
+  ProvideRssi(-3);
+  ProvideRssi(-2);
+  ProvideRssi(0);
+  ProvideRssi(0);
+
+  EXPECT_TRUE(monitor_.IsUnlockAllowed());
+}
+
+TEST_F(ProximityAuthProximityMonitorImplTest,
+       IsUnlockAllowed_RemoteDeviceEntersProximity_MultiDeviceApiEnabled) {
+  monitor_.Start();
+
+  // Start with a device out of proximity.
+  ProvideRssi(kRssiThreshold * 2);
+  EXPECT_FALSE(monitor_.IsUnlockAllowed());
+
+  // Simulate readings for the remote device entering proximity.
+  ProvideRssi(-15);
+  ProvideRssi(-8);
+  ProvideRssi(-12);
+  ProvideRssi(-18);
+  ProvideRssi(-7);
+  ProvideRssi(-3);
+  ProvideRssi(-2);
+  ProvideRssi(0);
+  ProvideRssi(0);
 
   EXPECT_TRUE(monitor_.IsUnlockAllowed());
 }
@@ -285,7 +484,24 @@
   monitor_.Start();
 
   // Start with the device known to the adapter and in proximity.
-  ProvideConnectionInfo({0, 4, 4});
+  ProvideRssi(0);
+  EXPECT_TRUE(monitor_.IsUnlockAllowed());
+
+  // Simulate it being forgotten.
+  ON_CALL(*bluetooth_adapter_, GetDevice(std::string()))
+      .WillByDefault(Return(nullptr));
+  EXPECT_CALL(observer_, OnProximityStateChanged());
+  RunPendingTasks();
+
+  EXPECT_FALSE(monitor_.IsUnlockAllowed());
+}
+
+TEST_F(ProximityAuthProximityMonitorImplTest,
+       IsUnlockAllowed_DeviceNotKnownToAdapter_MultiDeviceApiEnabled) {
+  monitor_.Start();
+
+  // Start with the device known to the adapter and in proximity.
+  ProvideRssi(0);
   EXPECT_TRUE(monitor_.IsUnlockAllowed());
 
   // Simulate it being forgotten.
@@ -302,7 +518,7 @@
   monitor_.Start();
 
   // Start with the device connected and in proximity.
-  ProvideConnectionInfo({0, 4, 4});
+  ProvideRssi(0);
   EXPECT_TRUE(monitor_.IsUnlockAllowed());
 
   // Simulate it disconnecting.
@@ -314,19 +530,66 @@
 }
 
 TEST_F(ProximityAuthProximityMonitorImplTest,
+       IsUnlockAllowed_DeviceNotConnected_MultiDeviceApiEnabled) {
+  SetMultiDeviceApiEnabled();
+
+  monitor_.Start();
+
+  // Start with the device connected and in proximity.
+  ProvideRssi(0);
+  EXPECT_TRUE(monitor_.IsUnlockAllowed());
+
+  // Simulate it disconnecting.
+  fake_client_channel_->NotifyDisconnected();
+  EXPECT_CALL(observer_, OnProximityStateChanged());
+  RunPendingTasks();
+
+  EXPECT_FALSE(monitor_.IsUnlockAllowed());
+}
+
+TEST_F(ProximityAuthProximityMonitorImplTest,
        IsUnlockAllowed_ConnectionInfoReceivedAfterStopping) {
   monitor_.Start();
   monitor_.Stop();
-  ProvideConnectionInfo({0, 4, 4});
+  ProvideRssi(0);
+  EXPECT_FALSE(monitor_.IsUnlockAllowed());
+}
+
+TEST_F(
+    ProximityAuthProximityMonitorImplTest,
+    IsUnlockAllowed_ConnectionInfoReceivedAfterStopping_MultiDeviceApiEnabled) {
+  SetMultiDeviceApiEnabled();
+
+  monitor_.Start();
+  monitor_.Stop();
+  ProvideRssi(0);
   EXPECT_FALSE(monitor_.IsUnlockAllowed());
 }
 
 TEST_F(ProximityAuthProximityMonitorImplTest,
        RecordProximityMetricsOnAuthSuccess_NormalValues) {
   monitor_.Start();
-  ProvideConnectionInfo({0, 0, 4});
+  ProvideRssi(0);
 
-  ProvideConnectionInfo({-20, 3, 4});
+  ProvideRssi(-20);
+
+  base::HistogramTester histogram_tester;
+  monitor_.RecordProximityMetricsOnAuthSuccess();
+  histogram_tester.ExpectUniqueSample("EasyUnlock.AuthProximity.RollingRssi",
+                                      -6, 1);
+  histogram_tester.ExpectUniqueSample(
+      "EasyUnlock.AuthProximity.RemoteDeviceModelHash",
+      1881443083 /* hash of "LGE Nexus 5" */, 1);
+}
+
+TEST_F(ProximityAuthProximityMonitorImplTest,
+       RecordProximityMetricsOnAuthSuccess_NormalValues_MultiDeviceApiEnabled) {
+  SetMultiDeviceApiEnabled();
+
+  monitor_.Start();
+  ProvideRssi(0);
+
+  ProvideRssi(-20);
 
   base::HistogramTester histogram_tester;
   monitor_.RecordProximityMetricsOnAuthSuccess();
@@ -340,7 +603,21 @@
 TEST_F(ProximityAuthProximityMonitorImplTest,
        RecordProximityMetricsOnAuthSuccess_ClampedValues) {
   monitor_.Start();
-  ProvideConnectionInfo({-99999, 99999, 12345});
+  ProvideRssi(-99999);
+
+  base::HistogramTester histogram_tester;
+  monitor_.RecordProximityMetricsOnAuthSuccess();
+  histogram_tester.ExpectUniqueSample("EasyUnlock.AuthProximity.RollingRssi",
+                                      -100, 1);
+}
+
+TEST_F(
+    ProximityAuthProximityMonitorImplTest,
+    RecordProximityMetricsOnAuthSuccess_ClampedValues_MultiDeviceApiEnabled) {
+  SetMultiDeviceApiEnabled();
+
+  monitor_.Start();
+  ProvideRssi(-99999);
 
   base::HistogramTester histogram_tester;
   monitor_.RecordProximityMetricsOnAuthSuccess();
@@ -351,15 +628,44 @@
 TEST_F(ProximityAuthProximityMonitorImplTest,
        RecordProximityMetricsOnAuthSuccess_UnknownValues) {
   // Note: A device without a recorded name will have "Unknown" as its name.
-  cryptauth::FakeConnection connection(cryptauth::RemoteDeviceRefBuilder()
-                                           .SetUserId(kRemoteDeviceUserId)
-                                           .SetName(std::string())
-                                           .Build());
+  cryptauth::RemoteDeviceRef remote_device = cryptauth::RemoteDeviceRefBuilder()
+                                                 .SetUserId(kRemoteDeviceUserId)
+                                                 .SetName(std::string())
+                                                 .Build();
+  cryptauth::FakeConnection connection(remote_device);
 
-  ProximityMonitorImpl monitor(&connection, pref_manager_.get());
+  ProximityMonitorImpl monitor(remote_device, fake_client_channel_.get(),
+                               &connection, pref_manager_.get());
   monitor.AddObserver(&observer_);
   monitor.Start();
-  ProvideConnectionInfo({127, 127, 127});
+  ProvideRssi(127);
+
+  base::HistogramTester histogram_tester;
+  monitor.RecordProximityMetricsOnAuthSuccess();
+  histogram_tester.ExpectUniqueSample("EasyUnlock.AuthProximity.RollingRssi",
+                                      127, 1);
+  histogram_tester.ExpectUniqueSample(
+      "EasyUnlock.AuthProximity.RemoteDeviceModelHash",
+      -1808066424 /* hash of "Unknown" */, 1);
+}
+
+TEST_F(
+    ProximityAuthProximityMonitorImplTest,
+    RecordProximityMetricsOnAuthSuccess_UnknownValues_MultiDeviceApiEnabled) {
+  SetMultiDeviceApiEnabled();
+
+  // Note: A device without a recorded name will have "Unknown" as its name.
+  cryptauth::RemoteDeviceRef remote_device = cryptauth::RemoteDeviceRefBuilder()
+                                                 .SetUserId(kRemoteDeviceUserId)
+                                                 .SetName(std::string())
+                                                 .Build();
+  cryptauth::FakeConnection connection(remote_device);
+
+  ProximityMonitorImpl monitor(remote_device, fake_client_channel_.get(),
+                               &connection, pref_manager_.get());
+  monitor.AddObserver(&observer_);
+  monitor.Start();
+  ProvideRssi(127);
 
   base::HistogramTester histogram_tester;
   monitor.RecordProximityMetricsOnAuthSuccess();
diff --git a/chromeos/components/proximity_auth/unlock_manager_impl.cc b/chromeos/components/proximity_auth/unlock_manager_impl.cc
index bf99248..d4bed74 100644
--- a/chromeos/components/proximity_auth/unlock_manager_impl.cc
+++ b/chromeos/components/proximity_auth/unlock_manager_impl.cc
@@ -324,7 +324,10 @@
 std::unique_ptr<ProximityMonitor> UnlockManagerImpl::CreateProximityMonitor(
     cryptauth::Connection* connection,
     ProximityAuthPrefManager* pref_manager) {
-  return std::make_unique<ProximityMonitorImpl>(connection, pref_manager);
+  // TODO(crbug.com/752273): Inject a real ClientChannel.
+  return std::make_unique<ProximityMonitorImpl>(connection->remote_device(),
+                                                nullptr /* channel */,
+                                                connection, pref_manager);
 }
 
 void UnlockManagerImpl::SendSignInChallenge() {
diff --git a/chromeos/services/assistant/public/proto/activity_control_settings_ui.proto b/chromeos/services/assistant/public/proto/activity_control_settings_ui.proto
index 20fb41a..1cc93993 100644
--- a/chromeos/services/assistant/public/proto/activity_control_settings_ui.proto
+++ b/chromeos/services/assistant/public/proto/activity_control_settings_ui.proto
@@ -8,8 +8,6 @@
 
 package chromeos.assistant;
 
-import "activity_control_settings_common.proto";
-
 message ActivityControlSettingsUiSelector {
   // An ID that uniquely identifies a single consent screen / client integration
   // with consent flow.
diff --git a/chromeos/services/assistant/public/proto/consent_flow_ui.proto b/chromeos/services/assistant/public/proto/consent_flow_ui.proto
index 1b19c5d..bdc1328 100644
--- a/chromeos/services/assistant/public/proto/consent_flow_ui.proto
+++ b/chromeos/services/assistant/public/proto/consent_flow_ui.proto
@@ -90,6 +90,63 @@
     }
     optional ActivityControlUi activity_control_ui = 1;
 
+    // A screen where we ask the user to confirm their intention to reject
+    // activity control.
+    // The client should only show if user rejects ActivityControlUi.
+    message ActivityControlConfirmRejectUi {
+      // Title for the whole page.
+      //
+      // Required.
+      optional string title = 1;
+
+      // Title for the option to opt in to ActivityControl.
+      //
+      // Required.
+      optional string accept_title = 2;
+
+      // Message for the option to opt in to ActivityControl.
+      //
+      // Required.
+      optional string accept_message = 3;
+
+      // Message for the option to opt in to ActivityControl in its expanded
+      // state. This extra text conveys some fine-print info about what will
+      // happen if the user accepts ActivityControl from this screen.
+      //
+      // Required
+      optional string accept_message_expanded = 4;
+
+      // A button that expands the accept message. In expanded state,
+      // both accept_message and accept_message_expanded are visible.
+      //
+      // Required.
+      optional string button_accept_expand = 5;
+
+      // A button that collapses the accept message. In collapsed state,
+      // accept_message is visible, but accept_message_expanded is not.
+      //
+      // Required.
+      optional string button_accept_collapse = 6;
+
+      // Title for the option to opt out of ActivityControl.
+      //
+      // Required.
+      optional string reject_title = 7;
+
+      // Message for the option to opt out of ActivityControl.
+      //
+      // Required.
+      optional string reject_message = 8;
+
+      // Text of the action button that lets the user commit their decision
+      // to accept or reject ActivityControl from the confirm page.
+      //
+      // Required.
+      optional string button_continue = 9;
+    }
+    optional ActivityControlConfirmRejectUi activity_control_confirm_reject_ui =
+        7;
+
     // Represents the subsection of the ConsentUi that displays and conveys a
     // disclosure that the user's account might be shared with third
     // parties the user invokes in conversation/interaction with the Assistant.
diff --git a/chromeos/services/secure_channel/public/cpp/client/fake_client_channel.cc b/chromeos/services/secure_channel/public/cpp/client/fake_client_channel.cc
index 9f6ce7c91..d773735 100644
--- a/chromeos/services/secure_channel/public/cpp/client/fake_client_channel.cc
+++ b/chromeos/services/secure_channel/public/cpp/client/fake_client_channel.cc
@@ -14,9 +14,16 @@
 
 FakeClientChannel::~FakeClientChannel() = default;
 
+void FakeClientChannel::InvokePendingGetConnectionMetadataCallback(
+    mojom::ConnectionMetadataPtr connection_metadata) {
+  std::move(get_connection_metadata_callback_queue_.front())
+      .Run(std::move(connection_metadata));
+  get_connection_metadata_callback_queue_.pop();
+}
+
 void FakeClientChannel::PerformGetConnectionMetadata(
     base::OnceCallback<void(mojom::ConnectionMetadataPtr)> callback) {
-  std::move(callback).Run(std::move(connection_metadata_for_next_call_));
+  get_connection_metadata_callback_queue_.push(std::move(callback));
 }
 
 void FakeClientChannel::PerformSendMessage(const std::string& payload,
diff --git a/chromeos/services/secure_channel/public/cpp/client/fake_client_channel.h b/chromeos/services/secure_channel/public/cpp/client/fake_client_channel.h
index cf564ca..a149976 100644
--- a/chromeos/services/secure_channel/public/cpp/client/fake_client_channel.h
+++ b/chromeos/services/secure_channel/public/cpp/client/fake_client_channel.h
@@ -5,6 +5,8 @@
 #ifndef CHROMEOS_SERVICES_SECURE_CHANNEL_PUBLIC_CPP_CLIENT_FAKE_CLIENT_CHANNEL_H_
 #define CHROMEOS_SERVICES_SECURE_CHANNEL_PUBLIC_CPP_CLIENT_FAKE_CLIENT_CHANNEL_H_
 
+#include <queue>
+
 #include "base/macros.h"
 #include "chromeos/services/secure_channel/public/cpp/client/client_channel.h"
 #include "chromeos/services/secure_channel/public/mojom/secure_channel.mojom.h"
@@ -22,11 +24,8 @@
   using ClientChannel::NotifyDisconnected;
   using ClientChannel::NotifyMessageReceived;
 
-  void set_connection_metadata_for_next_call(
-      mojom::ConnectionMetadataPtr connection_metadata_for_next_call) {
-    connection_metadata_for_next_call_ =
-        std::move(connection_metadata_for_next_call);
-  }
+  void InvokePendingGetConnectionMetadataCallback(
+      mojom::ConnectionMetadataPtr connection_metadata);
 
   std::vector<std::pair<std::string, base::OnceClosure>>& sent_messages() {
     return sent_messages_;
@@ -41,7 +40,10 @@
   void PerformSendMessage(const std::string& payload,
                           base::OnceClosure on_sent_callback) override;
 
-  mojom::ConnectionMetadataPtr connection_metadata_for_next_call_;
+  // Queues up callbacks passed into PerformGetConnectionMetadata(), to be
+  // invoked later.
+  std::queue<base::OnceCallback<void(mojom::ConnectionMetadataPtr)>>
+      get_connection_metadata_callback_queue_;
   std::vector<std::pair<std::string, base::OnceClosure>> sent_messages_;
 
   DISALLOW_COPY_AND_ASSIGN(FakeClientChannel);
diff --git a/components/arc/common/video_accelerator_struct_traits.cc b/components/arc/common/video_accelerator_struct_traits.cc
index 63ee67d..dfb8d49 100644
--- a/components/arc/common/video_accelerator_struct_traits.cc
+++ b/components/arc/common/video_accelerator_struct_traits.cc
@@ -52,7 +52,9 @@
 CHECK_PROFILE_ENUM(THEORAPROFILE_ANY);
 CHECK_PROFILE_ENUM(THEORAPROFILE_MAX);
 CHECK_PROFILE_ENUM(AV1PROFILE_MIN);
-CHECK_PROFILE_ENUM(AV1PROFILE_PROFILE0);
+CHECK_PROFILE_ENUM(AV1PROFILE_PROFILE_MAIN);
+CHECK_PROFILE_ENUM(AV1PROFILE_PROFILE_HIGH);
+CHECK_PROFILE_ENUM(AV1PROFILE_PROFILE_PRO);
 CHECK_PROFILE_ENUM(AV1PROFILE_MAX);
 CHECK_PROFILE_ENUM(VIDEO_CODEC_PROFILE_MAX);
 
@@ -95,7 +97,9 @@
     case arc::mojom::VideoCodecProfile::DOLBYVISION_PROFILE5:
     case arc::mojom::VideoCodecProfile::DOLBYVISION_PROFILE7:
     case arc::mojom::VideoCodecProfile::THEORAPROFILE_ANY:
-    case arc::mojom::VideoCodecProfile::AV1PROFILE_PROFILE0:
+    case arc::mojom::VideoCodecProfile::AV1PROFILE_PROFILE_MAIN:
+    case arc::mojom::VideoCodecProfile::AV1PROFILE_PROFILE_HIGH:
+    case arc::mojom::VideoCodecProfile::AV1PROFILE_PROFILE_PRO:
       *output = static_cast<media::VideoCodecProfile>(input);
       return true;
   }
diff --git a/components/arc/common/video_common.mojom b/components/arc/common/video_common.mojom
index 968917c0..188a3509 100644
--- a/components/arc/common/video_common.mojom
+++ b/components/arc/common/video_common.mojom
@@ -50,12 +50,12 @@
   THEORAPROFILE_MIN = 23,
   THEORAPROFILE_ANY = THEORAPROFILE_MIN,
   THEORAPROFILE_MAX = THEORAPROFILE_ANY,
-  // TODO(dalecurtis): AV1 profiles are not finalized, this needs updating
-  // before enabling for release. http://crbug.com/784993
   AV1PROFILE_MIN = 24,
-  AV1PROFILE_PROFILE0 = AV1PROFILE_MIN,
-  AV1PROFILE_MAX = AV1PROFILE_PROFILE0,
-  VIDEO_CODEC_PROFILE_MAX = AV1PROFILE_PROFILE0,
+  AV1PROFILE_PROFILE_MAIN = AV1PROFILE_MIN,
+  AV1PROFILE_PROFILE_HIGH = 25,
+  AV1PROFILE_PROFILE_PRO = 26,
+  AV1PROFILE_MAX = AV1PROFILE_PROFILE_PRO,
+  VIDEO_CODEC_PROFILE_MAX = AV1PROFILE_PROFILE_PRO,
 };
 
 [Extensible]
diff --git a/components/component_updater/BUILD.gn b/components/component_updater/BUILD.gn
index 0f854c6..09118f4 100644
--- a/components/component_updater/BUILD.gn
+++ b/components/component_updater/BUILD.gn
@@ -23,6 +23,9 @@
     "pref_names.h",
     "timer.cc",
     "timer.h",
+    "timer_update_scheduler.cc",
+    "timer_update_scheduler.h",
+    "update_scheduler.h",
   ]
 
   deps = [
diff --git a/components/component_updater/component_installer_unittest.cc b/components/component_updater/component_installer_unittest.cc
index daf2ff73..c87f451 100644
--- a/components/component_updater/component_installer_unittest.cc
+++ b/components/component_updater/component_installer_unittest.cc
@@ -168,6 +168,16 @@
   }
 };
 
+class MockUpdateScheduler : public UpdateScheduler {
+ public:
+  MOCK_METHOD4(Schedule,
+               void(const base::TimeDelta& initial_delay,
+                    const base::TimeDelta& delay,
+                    const UserTask& user_task,
+                    const OnStopTaskCallback& on_stop));
+  MOCK_METHOD0(Stop, void());
+};
+
 class ComponentInstallerTest : public testing::Test {
  public:
   ComponentInstallerTest();
@@ -179,6 +189,7 @@
   }
   scoped_refptr<TestConfigurator> configurator() const { return config_; }
   base::OnceClosure quit_closure() { return runloop_.QuitClosure(); }
+  MockUpdateScheduler& scheduler() { return *scheduler_; }
 
  protected:
   void RunThreads();
@@ -189,6 +200,10 @@
 
  private:
   void UnpackComplete(const ComponentUnpacker::Result& result);
+  void Schedule(const base::TimeDelta& initial_delay,
+                const base::TimeDelta& delay,
+                const UpdateScheduler::UserTask& user_task,
+                const UpdateScheduler::OnStopTaskCallback& on_stop);
 
   const scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_ =
       base::ThreadTaskRunnerHandle::Get();
@@ -196,6 +211,7 @@
 
   scoped_refptr<TestConfigurator> config_ =
       base::MakeRefCounted<TestConfigurator>();
+  MockUpdateScheduler* scheduler_ = nullptr;
   scoped_refptr<MockUpdateClient> update_client_ =
       base::MakeRefCounted<MockUpdateClient>();
   std::unique_ptr<ComponentUpdateService> component_updater_;
@@ -204,8 +220,12 @@
 
 ComponentInstallerTest::ComponentInstallerTest() {
   EXPECT_CALL(update_client(), AddObserver(_)).Times(1);
-  component_updater_ =
-      std::make_unique<CrxUpdateService>(config_, update_client_);
+  auto scheduler = std::make_unique<MockUpdateScheduler>();
+  scheduler_ = scheduler.get();
+  ON_CALL(*scheduler_, Schedule(_, _, _, _))
+      .WillByDefault(Invoke(this, &ComponentInstallerTest::Schedule));
+  component_updater_ = std::make_unique<CrxUpdateService>(
+      config_, std::move(scheduler), update_client_);
 }
 
 ComponentInstallerTest::~ComponentInstallerTest() {
@@ -237,6 +257,14 @@
   main_thread_task_runner_->PostTask(FROM_HERE, quit_closure());
 }
 
+void ComponentInstallerTest::Schedule(
+    const base::TimeDelta& initial_delay,
+    const base::TimeDelta& delay,
+    const UpdateScheduler::UserTask& user_task,
+    const UpdateScheduler::OnStopTaskCallback& on_stop) {
+  user_task.Run(base::DoNothing());
+}
+
 }  // namespace
 
 // Tests that the component metadata is propagated from the component installer
@@ -272,6 +300,8 @@
 
   EXPECT_CALL(update_client(), GetCrxUpdateState(id, _)).Times(1);
   EXPECT_CALL(update_client(), Stop()).Times(1);
+  EXPECT_CALL(scheduler(), Schedule(_, _, _, _)).Times(1);
+  EXPECT_CALL(scheduler(), Stop()).Times(1);
 
   auto installer = base::MakeRefCounted<ComponentInstaller>(
       std::make_unique<MockInstallerPolicy>());
@@ -324,6 +354,7 @@
 
   EXPECT_FALSE(base::PathExists(unpack_path));
   EXPECT_CALL(update_client(), Stop()).Times(1);
+  EXPECT_CALL(scheduler(), Stop()).Times(1);
 }
 
 // Tests that the unpack path is removed when the install failed.
@@ -354,6 +385,7 @@
 
   EXPECT_FALSE(base::PathExists(unpack_path));
   EXPECT_CALL(update_client(), Stop()).Times(1);
+  EXPECT_CALL(scheduler(), Stop()).Times(1);
 }
 
 }  // namespace component_updater
diff --git a/components/component_updater/component_updater_service.cc b/components/component_updater/component_updater_service.cc
index 78d2b2ce..861eb51 100644
--- a/components/component_updater/component_updater_service.cc
+++ b/components/component_updater/component_updater_service.cc
@@ -23,7 +23,6 @@
 #include "base/time/time.h"
 #include "base/timer/timer.h"
 #include "components/component_updater/component_updater_service_internal.h"
-#include "components/component_updater/timer.h"
 #include "components/update_client/configurator.h"
 #include "components/update_client/crx_update_item.h"
 #include "components/update_client/update_client.h"
@@ -56,8 +55,11 @@
 ComponentInfo::~ComponentInfo() {}
 
 CrxUpdateService::CrxUpdateService(scoped_refptr<Configurator> config,
+                                   std::unique_ptr<UpdateScheduler> scheduler,
                                    scoped_refptr<UpdateClient> update_client)
-    : config_(config), update_client_(update_client) {
+    : config_(config),
+      scheduler_(std::move(scheduler)),
+      update_client_(update_client) {
   AddObserver(this);
 }
 
@@ -91,18 +93,20 @@
           << "Next update attempt will take place in "
           << config_->NextCheckDelay() << " seconds. ";
 
-  timer_.Start(
+  scheduler_->Schedule(
       base::TimeDelta::FromSeconds(config_->InitialDelay()),
       base::TimeDelta::FromSeconds(config_->NextCheckDelay()),
       base::Bind(base::IgnoreResult(&CrxUpdateService::CheckForUpdates),
-                 base::Unretained(this)));
+                 base::Unretained(this)),
+      // TODO: Stop component update if requested.
+      base::DoNothing());
 }
 
 // Stops the update loop. In flight operations will be completed.
 void CrxUpdateService::Stop() {
   DCHECK(thread_checker_.CalledOnValidThread());
   VLOG(1) << "CrxUpdateService stopping";
-  timer_.Stop();
+  scheduler_->Stop();
   update_client_->Stop();
 }
 
@@ -299,7 +303,8 @@
                      base::TimeTicks::Now()));
 }
 
-bool CrxUpdateService::CheckForUpdates() {
+bool CrxUpdateService::CheckForUpdates(
+    UpdateScheduler::OnFinishedCallback on_finished) {
   DCHECK(thread_checker_.CalledOnValidThread());
 
   // TODO(xiaochu): remove this log after https://crbug.com/851151 is fixed.
@@ -320,24 +325,38 @@
       unsecure_ids.push_back(id);
   }
 
+  if (unsecure_ids.empty() && secure_ids.empty()) {
+    base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+                                                  std::move(on_finished));
+    return true;
+  }
+
+  Callback on_finished_callback = base::BindOnce(
+      [](UpdateScheduler::OnFinishedCallback on_finished,
+         update_client::Error error) { std::move(on_finished).Run(); },
+      std::move(on_finished));
+
   if (!unsecure_ids.empty()) {
-    update_client_->Update(unsecure_ids,
-                           base::BindOnce(&CrxUpdateService::GetCrxComponents,
-                                          base::Unretained(this)),
-                           false,
-                           base::BindOnce(&CrxUpdateService::OnUpdateComplete,
-                                          base::Unretained(this), Callback(),
-                                          base::TimeTicks::Now()));
+    update_client_->Update(
+        unsecure_ids,
+        base::BindOnce(&CrxUpdateService::GetCrxComponents,
+                       base::Unretained(this)),
+        false,
+        base::BindOnce(
+            &CrxUpdateService::OnUpdateComplete, base::Unretained(this),
+            secure_ids.empty() ? std::move(on_finished_callback) : Callback(),
+            base::TimeTicks::Now()));
   }
 
   if (!secure_ids.empty()) {
-    update_client_->Update(secure_ids,
-                           base::BindOnce(&CrxUpdateService::GetCrxComponents,
-                                          base::Unretained(this)),
-                           false,
-                           base::BindOnce(&CrxUpdateService::OnUpdateComplete,
-                                          base::Unretained(this), Callback(),
-                                          base::TimeTicks::Now()));
+    update_client_->Update(
+        secure_ids,
+        base::BindOnce(&CrxUpdateService::GetCrxComponents,
+                       base::Unretained(this)),
+        false,
+        base::BindOnce(&CrxUpdateService::OnUpdateComplete,
+                       base::Unretained(this), std::move(on_finished_callback),
+                       base::TimeTicks::Now()));
   }
 
   return true;
@@ -440,10 +459,13 @@
 // is the job of the browser process.
 // TODO(sorin): consider making this a singleton.
 std::unique_ptr<ComponentUpdateService> ComponentUpdateServiceFactory(
-    scoped_refptr<Configurator> config) {
+    scoped_refptr<Configurator> config,
+    std::unique_ptr<UpdateScheduler> scheduler) {
   DCHECK(config);
+  DCHECK(scheduler);
   auto update_client = update_client::UpdateClientFactory(config);
-  return std::make_unique<CrxUpdateService>(config, std::move(update_client));
+  return std::make_unique<CrxUpdateService>(config, std::move(scheduler),
+                                            std::move(update_client));
 }
 
 }  // namespace component_updater
diff --git a/components/component_updater/component_updater_service.h b/components/component_updater/component_updater_service.h
index 718e7fb..dbb58da 100644
--- a/components/component_updater/component_updater_service.h
+++ b/components/component_updater/component_updater_service.h
@@ -39,6 +39,7 @@
 using Callback = update_client::Callback;
 
 class OnDemandUpdater;
+class UpdateScheduler;
 
 using Configurator = update_client::Configurator;
 using CrxComponent = update_client::CrxComponent;
@@ -175,7 +176,8 @@
 
 // Creates the component updater.
 std::unique_ptr<ComponentUpdateService> ComponentUpdateServiceFactory(
-    scoped_refptr<Configurator> config);
+    scoped_refptr<Configurator> config,
+    std::unique_ptr<UpdateScheduler> scheduler);
 
 }  // namespace component_updater
 
diff --git a/components/component_updater/component_updater_service_internal.h b/components/component_updater/component_updater_service_internal.h
index 1094ffa..84083a1e 100644
--- a/components/component_updater/component_updater_service_internal.h
+++ b/components/component_updater/component_updater_service_internal.h
@@ -13,7 +13,7 @@
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/threading/thread_checker.h"
-#include "components/component_updater/timer.h"
+#include "components/component_updater/update_scheduler.h"
 
 namespace base {
 class TimeTicks;
@@ -37,6 +37,7 @@
 
  public:
   CrxUpdateService(scoped_refptr<Configurator> config,
+                   std::unique_ptr<UpdateScheduler> scheduler,
                    scoped_refptr<UpdateClient> update_client);
   ~CrxUpdateService() override;
 
@@ -65,9 +66,10 @@
   void Start();
   void Stop();
 
-  bool CheckForUpdates();
+  bool CheckForUpdates(UpdateScheduler::OnFinishedCallback on_finished);
 
   void OnDemandUpdateInternal(const std::string& id, Callback callback);
+
   bool OnDemandUpdateWithCooldown(const std::string& id);
 
   bool DoUnregisterComponent(const CrxComponent& component);
@@ -85,11 +87,10 @@
   base::ThreadChecker thread_checker_;
 
   scoped_refptr<Configurator> config_;
+  std::unique_ptr<UpdateScheduler> scheduler_;
 
   scoped_refptr<UpdateClient> update_client_;
 
-  Timer timer_;
-
   // A collection of every registered component.
   using Components = std::map<std::string, CrxComponent>;
   Components components_;
diff --git a/components/component_updater/component_updater_service_unittest.cc b/components/component_updater/component_updater_service_unittest.cc
index c7509e8..28a694ff 100644
--- a/components/component_updater/component_updater_service_unittest.cc
+++ b/components/component_updater/component_updater_service_unittest.cc
@@ -11,6 +11,7 @@
 #include <vector>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
 #include "base/macros.h"
@@ -128,6 +129,16 @@
   MOCK_METHOD2(OnEvent, void(Events event, const std::string&));
 };
 
+class MockUpdateScheduler : public UpdateScheduler {
+ public:
+  MOCK_METHOD4(Schedule,
+               void(const base::TimeDelta& initial_delay,
+                    const base::TimeDelta& delay,
+                    const UserTask& user_task,
+                    const OnStopTaskCallback& on_stop));
+  MOCK_METHOD0(Stop, void());
+};
+
 class ComponentUpdaterTest : public testing::Test {
  public:
   ComponentUpdaterTest();
@@ -144,17 +155,25 @@
   ComponentUpdateService& component_updater() { return *component_updater_; }
   scoped_refptr<TestConfigurator> configurator() const { return config_; }
   base::OnceClosure quit_closure() { return runloop_.QuitClosure(); }
+  MockUpdateScheduler& scheduler() { return *scheduler_; }
   static void ReadyCallback() {}
 
  protected:
   void RunThreads();
 
  private:
+  void RunUpdateTask(const UpdateScheduler::UserTask& user_task);
+  void Schedule(const base::TimeDelta& initial_delay,
+                const base::TimeDelta& delay,
+                const UpdateScheduler::UserTask& user_task,
+                const UpdateScheduler::OnStopTaskCallback& on_stop);
+
   base::test::ScopedTaskEnvironment scoped_task_environment_;
   base::RunLoop runloop_;
 
   scoped_refptr<TestConfigurator> config_ =
       base::MakeRefCounted<TestConfigurator>();
+  MockUpdateScheduler* scheduler_;
   scoped_refptr<MockUpdateClient> update_client_ =
       base::MakeRefCounted<MockUpdateClient>();
   std::unique_ptr<ComponentUpdateService> component_updater_;
@@ -206,13 +225,18 @@
     scoped_refptr<Configurator> config) {
   DCHECK(config);
   return std::make_unique<CrxUpdateService>(
-      config, base::MakeRefCounted<MockUpdateClient>());
+      config, std::make_unique<MockUpdateScheduler>(),
+      base::MakeRefCounted<MockUpdateClient>());
 }
 
 ComponentUpdaterTest::ComponentUpdaterTest() {
   EXPECT_CALL(update_client(), AddObserver(_)).Times(1);
-  component_updater_ =
-      std::make_unique<CrxUpdateService>(config_, update_client_);
+  auto scheduler = std::make_unique<MockUpdateScheduler>();
+  scheduler_ = scheduler.get();
+  ON_CALL(*scheduler_, Schedule(_, _, _, _))
+      .WillByDefault(Invoke(this, &ComponentUpdaterTest::Schedule));
+  component_updater_ = std::make_unique<CrxUpdateService>(
+      config_, std::move(scheduler), update_client_);
 }
 
 ComponentUpdaterTest::~ComponentUpdaterTest() {
@@ -230,10 +254,35 @@
   runloop_.Run();
 }
 
+void ComponentUpdaterTest::RunUpdateTask(
+    const UpdateScheduler::UserTask& user_task) {
+  scoped_task_environment_.GetMainThreadTaskRunner()->PostTask(
+      FROM_HERE, base::BindRepeating(
+                     [](const UpdateScheduler::UserTask& user_task,
+                        ComponentUpdaterTest* test) {
+                       user_task.Run(base::BindOnce(
+                           [](const UpdateScheduler::UserTask& user_task,
+                              ComponentUpdaterTest* test) {
+                             test->RunUpdateTask(user_task);
+                           },
+                           user_task, base::Unretained(test)));
+                     },
+                     user_task, base::Unretained(this)));
+}
+
+void ComponentUpdaterTest::Schedule(
+    const base::TimeDelta& initial_delay,
+    const base::TimeDelta& delay,
+    const UpdateScheduler::UserTask& user_task,
+    const UpdateScheduler::OnStopTaskCallback& on_stop) {
+  RunUpdateTask(user_task);
+}
+
 TEST_F(ComponentUpdaterTest, AddObserver) {
   MockServiceObserver observer;
   EXPECT_CALL(update_client(), AddObserver(&observer)).Times(1);
   EXPECT_CALL(update_client(), Stop()).Times(1);
+  EXPECT_CALL(scheduler(), Stop()).Times(1);
   component_updater().AddObserver(&observer);
 }
 
@@ -241,6 +290,7 @@
   MockServiceObserver observer;
   EXPECT_CALL(update_client(), RemoveObserver(&observer)).Times(1);
   EXPECT_CALL(update_client(), Stop()).Times(1);
+  EXPECT_CALL(scheduler(), Stop()).Times(1);
   component_updater().RemoveObserver(&observer);
 }
 
@@ -297,6 +347,8 @@
 
   EXPECT_CALL(update_client(), IsUpdating(id1)).Times(1);
   EXPECT_CALL(update_client(), Stop()).Times(1);
+  EXPECT_CALL(scheduler(), Schedule(_, _, _, _)).Times(1);
+  EXPECT_CALL(scheduler(), Stop()).Times(1);
 
   EXPECT_TRUE(component_updater().RegisterComponent(crx_component1));
   EXPECT_TRUE(component_updater().RegisterComponent(crx_component2));
@@ -333,8 +385,8 @@
 
   base::HistogramTester ht;
 
-  auto config = configurator();
-  config->SetInitialDelay(3600);
+  // Don't run periodic update task.
+  ON_CALL(scheduler(), Schedule(_, _, _, _)).WillByDefault(Return());
 
   auto& cus = component_updater();
 
@@ -357,6 +409,8 @@
   EXPECT_CALL(update_client(), DoInstall("jebgalgnebhfojomionfpkfelancnnkf", _))
       .WillOnce(Invoke(&loop_handler, &LoopHandler::OnInstall));
   EXPECT_CALL(update_client(), Stop()).Times(1);
+  EXPECT_CALL(scheduler(), Schedule(_, _, _, _)).Times(1);
+  EXPECT_CALL(scheduler(), Stop()).Times(1);
 
   EXPECT_TRUE(cus.RegisterComponent(crx_component));
   OnDemandTester ondemand_tester;
@@ -394,8 +448,8 @@
 
   base::HistogramTester ht;
 
-  auto config = configurator();
-  config->SetInitialDelay(3600);
+  // Don't run periodic update task.
+  ON_CALL(scheduler(), Schedule(_, _, _, _)).WillByDefault(Return());
 
   scoped_refptr<MockInstaller> installer =
       base::MakeRefCounted<MockInstaller>();
@@ -410,6 +464,8 @@
   EXPECT_CALL(update_client(), DoInstall("jebgalgnebhfojomionfpkfelancnnkf", _))
       .WillOnce(Invoke(&loop_handler, &LoopHandler::OnInstall));
   EXPECT_CALL(update_client(), Stop()).Times(1);
+  EXPECT_CALL(scheduler(), Schedule(_, _, _, _)).Times(1);
+  EXPECT_CALL(scheduler(), Stop()).Times(1);
 
   EXPECT_TRUE(component_updater().RegisterComponent(crx_component));
   component_updater().MaybeThrottle(
diff --git a/components/component_updater/timer_update_scheduler.cc b/components/component_updater/timer_update_scheduler.cc
new file mode 100644
index 0000000..5170852
--- /dev/null
+++ b/components/component_updater/timer_update_scheduler.cc
@@ -0,0 +1,27 @@
+// 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/component_updater/timer_update_scheduler.h"
+
+namespace component_updater {
+
+TimerUpdateScheduler::TimerUpdateScheduler() = default;
+TimerUpdateScheduler::~TimerUpdateScheduler() = default;
+
+void TimerUpdateScheduler::Schedule(const base::TimeDelta& initial_delay,
+                                    const base::TimeDelta& delay,
+                                    const UserTask& user_task,
+                                    const OnStopTaskCallback& on_stop) {
+  timer_.Start(
+      initial_delay, delay,
+      base::BindRepeating(
+          [](const UserTask& user_task) { user_task.Run(base::DoNothing()); },
+          user_task));
+}
+
+void TimerUpdateScheduler::Stop() {
+  timer_.Stop();
+}
+
+}  // namespace component_updater
\ No newline at end of file
diff --git a/components/component_updater/timer_update_scheduler.h b/components/component_updater/timer_update_scheduler.h
new file mode 100644
index 0000000..3394572
--- /dev/null
+++ b/components/component_updater/timer_update_scheduler.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_COMPONENT_UPDATER_TIMER_UPDATE_SCHEDULER_H_
+#define COMPONENTS_COMPONENT_UPDATER_TIMER_UPDATE_SCHEDULER_H_
+
+#include "base/callback.h"
+#include "base/macros.h"
+#include "components/component_updater/timer.h"
+#include "components/component_updater/update_scheduler.h"
+
+namespace component_updater {
+
+// Scheduler that uses base::Timer to schedule updates.
+class TimerUpdateScheduler : public UpdateScheduler {
+ public:
+  TimerUpdateScheduler();
+  ~TimerUpdateScheduler() override;
+
+  // UpdateScheduler:
+  void Schedule(const base::TimeDelta& initial_delay,
+                const base::TimeDelta& delay,
+                const UserTask& user_task,
+                const OnStopTaskCallback& on_stop) override;
+  void Stop() override;
+
+ private:
+  Timer timer_;
+  base::RepeatingClosure user_task_;
+
+  DISALLOW_COPY_AND_ASSIGN(TimerUpdateScheduler);
+};
+
+}  // namespace component_updater
+
+#endif  // COMPONENTS_COMPONENT_UPDATER_TIMER_UPDATE_SCHEDULER_H_
diff --git a/components/component_updater/update_scheduler.h b/components/component_updater/update_scheduler.h
new file mode 100644
index 0000000..ce42eed
--- /dev/null
+++ b/components/component_updater/update_scheduler.h
@@ -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.
+
+#ifndef COMPONENTS_COMPONENT_UPDATER_UPDATE_SCHEDULER_H_
+#define COMPONENTS_COMPONENT_UPDATER_UPDATE_SCHEDULER_H_
+
+#include "base/callback_forward.h"
+#include "base/time/time.h"
+
+namespace component_updater {
+
+// Abstract interface for an update task scheduler.
+class UpdateScheduler {
+ public:
+  using OnFinishedCallback = base::OnceCallback<void()>;
+  // Type of task to be run by the scheduler. The task can start asynchronous
+  // operations and must call |on_finished| when all operations have completed.
+  using UserTask =
+      base::RepeatingCallback<void(OnFinishedCallback on_finished)>;
+  using OnStopTaskCallback = base::RepeatingCallback<void()>;
+
+  virtual ~UpdateScheduler() = default;
+
+  // Schedules |user_task| to be run periodically with at least an interval of
+  // |delay|. The first time |user_task| will be run after at least
+  // |initial_delay|. If the execution of |user_task| must be stopped before it
+  // called its |on_finished| callback, |on_stop| will be called.
+  virtual void Schedule(const base::TimeDelta& initial_delay,
+                        const base::TimeDelta& delay,
+                        const UserTask& user_task,
+                        const OnStopTaskCallback& on_stop) = 0;
+  // Stops to periodically run |user_task| previously scheduled with |Schedule|.
+  virtual void Stop() = 0;
+};
+
+}  // namespace component_updater
+
+#endif  // COMPONENTS_COMPONENT_UPDATER_UPDATE_SCHEDULER_H_
diff --git a/components/components_strings.grd b/components/components_strings.grd
index 4ee9c7b..96710cf 100644
--- a/components/components_strings.grd
+++ b/components/components_strings.grd
@@ -197,6 +197,7 @@
       <part file="history_strings.grdp" />
       <part file="login_dialog_strings.grdp" />
       <part file="new_or_sad_tab_strings.grdp" />
+      <part file="nux_google_apps_strings.grdp" />
       <part file="ntp_snippets_strings.grdp" />
       <part file="omnibox_strings.grdp" />
       <part file="page_info_strings.grdp" />
diff --git a/components/drive/DEPS b/components/drive/DEPS
index 0341d6a..effd9116 100644
--- a/components/drive/DEPS
+++ b/components/drive/DEPS
@@ -9,6 +9,7 @@
   "+services/device/public/mojom",
   "+third_party/leveldatabase",
   "+third_party/re2",
+  "+services/network/public/cpp",
 ]
 
 specific_include_rules = {
diff --git a/components/drive/service/drive_api_service.cc b/components/drive/service/drive_api_service.cc
index e5f6548..b00195c 100644
--- a/components/drive/service/drive_api_service.cc
+++ b/components/drive/service/drive_api_service.cc
@@ -23,6 +23,7 @@
 #include "google_apis/drive/request_sender.h"
 #include "google_apis/google_api_keys.h"
 #include "net/url_request/url_request_context_getter.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
 
 using google_apis::AboutResourceCallback;
 using google_apis::AppList;
@@ -267,6 +268,7 @@
 DriveAPIService::DriveAPIService(
     OAuth2TokenService* oauth2_token_service,
     net::URLRequestContextGetter* url_request_context_getter,
+    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
     base::SequencedTaskRunner* blocking_task_runner,
     const GURL& base_url,
     const GURL& base_thumbnail_url,
@@ -274,6 +276,7 @@
     const net::NetworkTrafficAnnotationTag& traffic_annotation)
     : oauth2_token_service_(oauth2_token_service),
       url_request_context_getter_(url_request_context_getter),
+      url_loader_factory_(url_loader_factory),
       blocking_task_runner_(blocking_task_runner),
       url_generator_(base_url,
                      base_thumbnail_url,
@@ -302,7 +305,8 @@
 
   sender_ = std::make_unique<RequestSender>(
       new google_apis::AuthService(oauth2_token_service_, account_id,
-                                   url_request_context_getter_.get(), scopes),
+                                   url_request_context_getter_.get(),
+                                   url_loader_factory_, scopes),
       url_request_context_getter_.get(), blocking_task_runner_.get(),
       custom_user_agent_, traffic_annotation_);
   sender_->auth_service()->AddObserver(this);
diff --git a/components/drive/service/drive_api_service.h b/components/drive/service/drive_api_service.h
index 6a63be3..3ec81ee 100644
--- a/components/drive/service/drive_api_service.h
+++ b/components/drive/service/drive_api_service.h
@@ -41,6 +41,9 @@
 namespace net {
 class URLRequestContextGetter;
 }  // namespace net
+namespace network {
+class SharedURLLoaderFactory;
+}
 
 namespace drive {
 
@@ -95,6 +98,8 @@
  public:
   // |oauth2_token_service| is used for obtaining OAuth2 access tokens.
   // |url_request_context_getter| is used to initialize URLFetcher.
+  // |url_loader_factory| is used to create SimpleURLLoaders used to create
+  // OAuth tokens.
   // |blocking_task_runner| is used to run blocking tasks (like parsing JSON).
   // |base_url| is used to generate URLs for communication with the drive API.
   // |base_thumbnail_url| is used to generate URLs for downloading thumbnail
@@ -103,13 +108,15 @@
   // requests issues through the service if the value is not empty.
   // |traffic_annotation| will be used to annotate the network request that will
   // be created to perform this service.
-  DriveAPIService(OAuth2TokenService* oauth2_token_service,
-                  net::URLRequestContextGetter* url_request_context_getter,
-                  base::SequencedTaskRunner* blocking_task_runner,
-                  const GURL& base_url,
-                  const GURL& base_thumbnail_url,
-                  const std::string& custom_user_agent,
-                  const net::NetworkTrafficAnnotationTag& traffic_annotation);
+  DriveAPIService(
+      OAuth2TokenService* oauth2_token_service,
+      net::URLRequestContextGetter* url_request_context_getter,
+      scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
+      base::SequencedTaskRunner* blocking_task_runner,
+      const GURL& base_url,
+      const GURL& base_thumbnail_url,
+      const std::string& custom_user_agent,
+      const net::NetworkTrafficAnnotationTag& traffic_annotation);
   ~DriveAPIService() override;
 
   // DriveServiceInterface Overrides
@@ -276,6 +283,7 @@
 
   OAuth2TokenService* oauth2_token_service_;
   scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_;
+  scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
   scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_;
   std::unique_ptr<google_apis::RequestSender> sender_;
   std::unique_ptr<google_apis::FilesListRequestRunner>
diff --git a/components/nux_google_apps/BUILD.gn b/components/nux_google_apps/BUILD.gn
new file mode 100644
index 0000000..20286ee
--- /dev/null
+++ b/components/nux_google_apps/BUILD.gn
@@ -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.
+
+import("//build/buildflag_header.gni")
+import("//components/nux_google_apps/features.gni")
+
+# Always required.
+buildflag_header("buildflags") {
+  header = "buildflags.h"
+  flags = [ "ENABLE_NUX_GOOGLE_APPS=$enable_nux_google_apps" ]
+}
+
+if (enable_nux_google_apps) {
+  static_library("nux_google_apps_feature") {
+    sources = [
+      "constants.cc",
+      "constants.h",
+      "webui.cc",
+      "webui.h",
+    ]
+
+    public_deps = [
+      "//base",
+      "//net",
+      "//url",
+    ]
+
+    deps = [
+      "//components/pref_registry",
+      "//components/prefs",
+      "//components/resources",
+      "//components/strings",
+      "//components/variations",
+      "//content/public/browser",
+      "//ui/base",
+    ]
+  }
+}
diff --git a/components/nux_google_apps/DEPS b/components/nux_google_apps/DEPS
new file mode 100644
index 0000000..1a6893c
--- /dev/null
+++ b/components/nux_google_apps/DEPS
@@ -0,0 +1,5 @@
+include_rules = [
+  "+components/grit",
+  "+components/strings/grit/components_strings.h",
+  "+content/public/browser",
+]
diff --git a/components/nux_google_apps/OWNERS b/components/nux_google_apps/OWNERS
new file mode 100644
index 0000000..08ee1a9
--- /dev/null
+++ b/components/nux_google_apps/OWNERS
@@ -0,0 +1 @@
+hcarmona@chromium.org
diff --git a/components/nux_google_apps/README b/components/nux_google_apps/README
new file mode 100644
index 0000000..4218a87
--- /dev/null
+++ b/components/nux_google_apps/README
@@ -0,0 +1,5 @@
+New User Experience Experiment (NUX). Code here will enable new users to
+bookmark popular Google Apps as part of the first run steps.
+
+Feature is initially Windows Only. After collecting stats, we will determine
+how useful it is for users, this data will help decide next steps for component.
diff --git a/components/nux_google_apps/constants.cc b/components/nux_google_apps/constants.cc
new file mode 100644
index 0000000..92d842b
--- /dev/null
+++ b/components/nux_google_apps/constants.cc
@@ -0,0 +1,14 @@
+// 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/nux_google_apps/constants.h"
+
+#include "base/feature_list.h"
+
+namespace nux_google_apps {
+
+extern const base::Feature kNuxGoogleAppsFeature{
+    "NuxGoogleApps", base::FEATURE_DISABLED_BY_DEFAULT};
+
+}  // namespace nux_google_apps
diff --git a/components/nux_google_apps/constants.h b/components/nux_google_apps/constants.h
new file mode 100644
index 0000000..b4a683b
--- /dev/null
+++ b/components/nux_google_apps/constants.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 COMPONENTS_NUX_GOOGLE_APPS_CONSTANTS_H_
+#define COMPONENTS_NUX_GOOGLE_APPS_CONSTANTS_H_
+
+namespace base {
+struct Feature;
+}  // namespace base
+
+namespace nux_google_apps {
+
+extern const base::Feature kNuxGoogleAppsFeature;
+
+}  // namespace nux_google_apps
+
+#endif  // COMPONENTS_NUX_GOOGLE_APPS_CONSTANTS_H_
diff --git a/components/nux_google_apps/features.gni b/components/nux_google_apps/features.gni
new file mode 100644
index 0000000..6896e1e
--- /dev/null
+++ b/components/nux_google_apps/features.gni
@@ -0,0 +1,10 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/config/features.gni")
+
+declare_args() {
+  # Only supported on windows.
+  enable_nux_google_apps = is_win
+}
diff --git a/components/nux_google_apps/resources/BUILD.gn b/components/nux_google_apps/resources/BUILD.gn
new file mode 100644
index 0000000..aa23216
--- /dev/null
+++ b/components/nux_google_apps/resources/BUILD.gn
@@ -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.
+
+import("//third_party/closure_compiler/compile_js.gni")
+
+js_type_check("closure_compile") {
+  deps = [
+    ":apps_chooser",
+    ":nux_google_apps",
+  ]
+}
+
+js_library("apps_chooser") {
+  deps = []
+}
+
+js_library("nux_google_apps") {
+  deps = [
+    ":apps_chooser",
+  ]
+}
diff --git a/components/nux_google_apps/resources/apps_chooser.html b/components/nux_google_apps/resources/apps_chooser.html
new file mode 100644
index 0000000..437954a
--- /dev/null
+++ b/components/nux_google_apps/resources/apps_chooser.html
@@ -0,0 +1,103 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+
+<link rel="import" href="chrome://resources/cr_elements/icons.html">
+<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
+
+<dom-module id="apps-chooser">
+  <template>
+    <style>
+      :host {
+        display: flex;
+        flex-direction: column;
+      }
+
+      .app-icon {
+        -webkit-margin-end: 16px;
+        -webkit-margin-start: 4px;
+      }
+
+      iron-icon {
+        -webkit-margin-end: 48px;
+      }
+
+      [active] iron-icon[icon="cr:check"] {
+        --iron-icon-fill-color: var(--google-blue-600);
+        opacity: unset;
+      }
+
+      iron-icon[icon="cr:check"] {
+        opacity: 0;
+      }
+
+      .gmail {
+        content: -webkit-image-set(
+            url(chrome://welcome/apps/gmail_1x.png) 1x,
+            url(chrome://welcome/apps/gmail_2x.png) 2x);
+      }
+
+      .youtube {
+        content: -webkit-image-set(
+            url(chrome://welcome/apps/youtube_1x.png) 1x,
+            url(chrome://welcome/apps/youtube_2x.png) 2x);
+      }
+
+      .maps {
+        content: -webkit-image-set(
+            url(chrome://welcome/apps/maps_1x.png) 1x,
+            url(chrome://welcome/apps/maps_2x.png) 2x);
+      }
+
+      .translate {
+        content: -webkit-image-set(
+            url(chrome://welcome/apps/translate_1x.png) 1x,
+            url(chrome://welcome/apps/translate_2x.png) 2x);
+      }
+
+      .news {
+        content: -webkit-image-set(
+            url(chrome://welcome/apps/news_1x.png) 1x,
+            url(chrome://welcome/apps/news_2x.png) 2x);
+      }
+
+      .chrome_store {
+        content: -webkit-image-set(
+            url(chrome://welcome/apps/chrome_store_1x.png) 1x,
+            url(chrome://welcome/apps/chrome_store_2x.png) 2x);
+      }
+
+      paper-button:first-of-type {
+        border-top: unset;
+      }
+
+      paper-button {
+        border-radius: 0;
+        border-top: var(--cr-section_-_border-top);
+        display: flex;
+        margin: 0;
+        padding: 12px 0;
+        text-transform: unset;
+      }
+
+      paper-button:not([raised]).keyboard-focus {
+        outline-width: unset;
+        font-weight: unset;
+      }
+
+      .app-name {
+        flex: 1;
+      }
+    </style>
+
+    <template is="dom-repeat" items="[[appList]]">
+      <paper-button toggles noink
+          active$="[[item.selected]]" on-click="onAppClick_">
+        <div class$="[[item.icon]] app-icon"></div>
+        <div class="app-name">[[item.name]]</div>
+        <iron-icon icon="cr:check"></iron-icon>
+      </paper-button>
+    </template>
+  </template>
+  <script src="apps_chooser.js"></script>
+</dom-module>
diff --git a/components/nux_google_apps/resources/apps_chooser.js b/components/nux_google_apps/resources/apps_chooser.js
new file mode 100644
index 0000000..cac520c
--- /dev/null
+++ b/components/nux_google_apps/resources/apps_chooser.js
@@ -0,0 +1,73 @@
+// 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.
+
+/**
+ * @const
+ */
+var nux_google_apps = nux_google_apps || {};
+
+/**
+ * @typedef {{
+ *   item: !{
+ *     name: string,
+ *     icon: string,
+ *     selected: boolean,
+ *   },
+ *   set: function(string, boolean):void
+ * }}
+ */
+nux_google_apps.AppsArrayModel;
+
+Polymer({
+  is: 'apps-chooser',
+  properties: {
+    // TODO(hcarmona): Get this list dynamically.
+    appList: {
+      type: Array,
+      value: function() {
+        return [
+          {
+            name: 'Gmail',
+            icon: 'gmail',
+            selected: true,
+          },
+          {
+            name: 'YouTube',
+            icon: 'youtube',
+            selected: true,
+          },
+          {
+            name: 'Maps',
+            icon: 'maps',
+            selected: true,
+          },
+          {
+            name: 'Translate',
+            icon: 'translate',
+            selected: true,
+          },
+          {
+            name: 'News',
+            icon: 'news',
+            selected: true,
+          },
+          {
+            name: 'Chrome Web Store',
+            icon: 'chrome_store',
+            selected: true,
+          },
+        ];
+      },
+    },
+  },
+
+  /**
+   * Handle toggling the apps selected.
+   * @param {!{model: !nux_google_apps.AppsArrayModel}} e
+   * @private
+   */
+  onAppClick_: function(e) {
+    e.model.set('item.selected', !e.model.item.selected);
+  },
+});
diff --git a/components/nux_google_apps/resources/chrome_store_24dp_1x.png b/components/nux_google_apps/resources/chrome_store_24dp_1x.png
new file mode 100644
index 0000000..9ffad9e
--- /dev/null
+++ b/components/nux_google_apps/resources/chrome_store_24dp_1x.png
Binary files differ
diff --git a/components/nux_google_apps/resources/chrome_store_24dp_2x.png b/components/nux_google_apps/resources/chrome_store_24dp_2x.png
new file mode 100644
index 0000000..4307c07
--- /dev/null
+++ b/components/nux_google_apps/resources/chrome_store_24dp_2x.png
Binary files differ
diff --git a/components/nux_google_apps/resources/gmail_24dp_1x.png b/components/nux_google_apps/resources/gmail_24dp_1x.png
new file mode 100644
index 0000000..220e974
--- /dev/null
+++ b/components/nux_google_apps/resources/gmail_24dp_1x.png
Binary files differ
diff --git a/components/nux_google_apps/resources/gmail_24dp_2x.png b/components/nux_google_apps/resources/gmail_24dp_2x.png
new file mode 100644
index 0000000..2ab3dbd
--- /dev/null
+++ b/components/nux_google_apps/resources/gmail_24dp_2x.png
Binary files differ
diff --git a/components/nux_google_apps/resources/maps_24dp_1x.png b/components/nux_google_apps/resources/maps_24dp_1x.png
new file mode 100644
index 0000000..110bff3
--- /dev/null
+++ b/components/nux_google_apps/resources/maps_24dp_1x.png
Binary files differ
diff --git a/components/nux_google_apps/resources/maps_24dp_2x.png b/components/nux_google_apps/resources/maps_24dp_2x.png
new file mode 100644
index 0000000..041a617
--- /dev/null
+++ b/components/nux_google_apps/resources/maps_24dp_2x.png
Binary files differ
diff --git a/components/nux_google_apps/resources/news_24dp_1x.png b/components/nux_google_apps/resources/news_24dp_1x.png
new file mode 100644
index 0000000..6842ad5
--- /dev/null
+++ b/components/nux_google_apps/resources/news_24dp_1x.png
Binary files differ
diff --git a/components/nux_google_apps/resources/news_24dp_2x.png b/components/nux_google_apps/resources/news_24dp_2x.png
new file mode 100644
index 0000000..4c3598b2
--- /dev/null
+++ b/components/nux_google_apps/resources/news_24dp_2x.png
Binary files differ
diff --git a/components/nux_google_apps/resources/nux_google_apps.html b/components/nux_google_apps/resources/nux_google_apps.html
new file mode 100644
index 0000000..74a77f0f
--- /dev/null
+++ b/components/nux_google_apps/resources/nux_google_apps.html
@@ -0,0 +1,82 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>$i18n{headerText}</title>
+
+<link rel="import" href="chrome://resources/html/polymer.html">
+
+<link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
+<link rel="import" href="chrome://welcome/apps/apps_chooser.html">
+
+<dom-module id="nux-google-apps">
+  <template>
+    <style include="paper-button-style">
+      body {
+        margin: 0;
+      }
+
+      .apps-ask {
+        margin-left: auto;
+        margin-right: auto;
+        margin-top: 116px;
+        max-width: 568px;
+      }
+
+      .chrome-logo {
+        content: -webkit-image-set(
+            url('chrome://welcome/logo.png') 1x,
+            url('chrome://welcome/logo2x.png') 2x);
+        height: 40px;
+        margin-bottom: 36px;
+        width: 40px;
+      }
+
+      h1 {
+        color: #202124;
+        font-size: 28px;
+        opacity: .8;
+        margin-bottom: 16px;
+      }
+
+      .description {
+        color: #5f6368;
+        font-size: 16px;
+        margin-bottom: 24px;
+      }
+
+      apps-chooser {
+        color: #202124;
+        font-size: 14px;
+        margin-bottom: 48px;
+      }
+
+      paper-button {
+        font-size: 14px;
+      }
+
+      .button-bar {
+        display: flex;
+        justify-content: space-between;
+      }
+    </style>
+
+    <div class="apps-ask">
+      <div class="chrome-logo"></div>
+      <h1>$i18n{headerText}</h1>
+      <div class="description">$i18n{nuxDescription}</div>
+
+      <apps-chooser></apps-chooser>
+
+      <div class="button-bar">
+        <paper-button>$i18n{noThanks}</paper-button>
+        <paper-button class="action-button">$i18n{getStarted}</paper-button>
+      </div>
+    </div>
+  </template>
+  <script src="apps/nux_google_apps.js"></script>
+</dom-module>
+
+<nux-google-apps></nux-google-apps>
+<link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css">
+
+</html>
diff --git a/components/nux_google_apps/resources/nux_google_apps.js b/components/nux_google_apps/resources/nux_google_apps.js
new file mode 100644
index 0000000..9f7a8ea
--- /dev/null
+++ b/components/nux_google_apps/resources/nux_google_apps.js
@@ -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.
+
+Polymer({
+  is: 'nux-google-apps',
+});
diff --git a/components/nux_google_apps/resources/translate_24dp_1x.png b/components/nux_google_apps/resources/translate_24dp_1x.png
new file mode 100644
index 0000000..023417f
--- /dev/null
+++ b/components/nux_google_apps/resources/translate_24dp_1x.png
Binary files differ
diff --git a/components/nux_google_apps/resources/translate_24dp_2x.png b/components/nux_google_apps/resources/translate_24dp_2x.png
new file mode 100644
index 0000000..a03417c
--- /dev/null
+++ b/components/nux_google_apps/resources/translate_24dp_2x.png
Binary files differ
diff --git a/components/nux_google_apps/resources/youtube_24dp_1x.png b/components/nux_google_apps/resources/youtube_24dp_1x.png
new file mode 100644
index 0000000..5a346af
--- /dev/null
+++ b/components/nux_google_apps/resources/youtube_24dp_1x.png
Binary files differ
diff --git a/components/nux_google_apps/resources/youtube_24dp_2x.png b/components/nux_google_apps/resources/youtube_24dp_2x.png
new file mode 100644
index 0000000..4d407117
--- /dev/null
+++ b/components/nux_google_apps/resources/youtube_24dp_2x.png
Binary files differ
diff --git a/components/nux_google_apps/webui.cc b/components/nux_google_apps/webui.cc
new file mode 100644
index 0000000..425c242
--- /dev/null
+++ b/components/nux_google_apps/webui.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 "components/nux_google_apps/webui.h"
+
+#include "base/metrics/field_trial_params.h"
+#include "components/grit/components_resources.h"
+#include "components/grit/components_scaled_resources.h"
+#include "components/nux_google_apps/constants.h"
+#include "components/strings/grit/components_strings.h"
+#include "content/public/browser/web_ui_data_source.h"
+
+namespace nux_google_apps {
+
+void AddSources(content::WebUIDataSource* html_source) {
+  // Localized strings.
+  html_source->AddLocalizedString("noThanks", IDS_NO_THANKS);
+  html_source->AddLocalizedString("getStarted",
+                                  IDS_NUX_GOOGLE_APPS_GET_STARTED);
+  html_source->AddLocalizedString("nuxDescription",
+                                  IDS_NUX_GOOGLE_APPS_DESCRIPTION);
+
+  // Add required resources.
+  html_source->AddResourcePath("apps", IDR_NUX_GOOGLE_APPS_HTML);
+  html_source->AddResourcePath("apps/nux_google_apps.js",
+                               IDR_NUX_GOOGLE_APPS_JS);
+
+  html_source->AddResourcePath("apps/apps_chooser.html",
+                               IDR_NUX_GOOGLE_APPS_CHOOSER_HTML);
+  html_source->AddResourcePath("apps/apps_chooser.js",
+                               IDR_NUX_GOOGLE_APPS_CHOOSER_JS);
+
+  // Add icons
+  html_source->AddResourcePath("apps/chrome_store_1x.png",
+                               IDR_NUX_GOOGLE_APPS_CHROME_STORE_1X);
+  html_source->AddResourcePath("apps/chrome_store_2x.png",
+                               IDR_NUX_GOOGLE_APPS_CHROME_STORE_2X);
+  html_source->AddResourcePath("apps/gmail_1x.png",
+                               IDR_NUX_GOOGLE_APPS_GMAIL_1X);
+  html_source->AddResourcePath("apps/gmail_2x.png",
+                               IDR_NUX_GOOGLE_APPS_GMAIL_2X);
+  html_source->AddResourcePath("apps/maps_1x.png", IDR_NUX_GOOGLE_APPS_MAPS_1X);
+  html_source->AddResourcePath("apps/maps_2x.png", IDR_NUX_GOOGLE_APPS_MAPS_2X);
+  html_source->AddResourcePath("apps/news_1x.png", IDR_NUX_GOOGLE_APPS_NEWS_1X);
+  html_source->AddResourcePath("apps/news_2x.png", IDR_NUX_GOOGLE_APPS_NEWS_2X);
+  html_source->AddResourcePath("apps/translate_1x.png",
+                               IDR_NUX_GOOGLE_APPS_TRANSLATE_1X);
+  html_source->AddResourcePath("apps/translate_2x.png",
+                               IDR_NUX_GOOGLE_APPS_TRANSLATE_2X);
+  html_source->AddResourcePath("apps/youtube_1x.png",
+                               IDR_NUX_GOOGLE_APPS_YOUTUBE_1X);
+  html_source->AddResourcePath("apps/youtube_2x.png",
+                               IDR_NUX_GOOGLE_APPS_YOUTUBE_2X);
+}
+
+}  // namespace nux_google_apps
diff --git a/components/nux_google_apps/webui.h b/components/nux_google_apps/webui.h
new file mode 100644
index 0000000..e9c752a1
--- /dev/null
+++ b/components/nux_google_apps/webui.h
@@ -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.
+
+#ifndef COMPONENTS_NUX_GOOGLE_APPS_WEBUI_H_
+#define COMPONENTS_NUX_GOOGLE_APPS_WEBUI_H_
+
+#include "base/macros.h"
+#include "content/public/browser/web_ui_data_source.h"
+
+namespace nux_google_apps {
+
+void AddSources(content::WebUIDataSource* html_source);
+
+}  // namespace nux_google_apps
+
+#endif  // COMPONENTS_NUX_GOOGLE_APPS_WEBUI_H_
diff --git a/components/nux_google_apps_strings.grdp b/components/nux_google_apps_strings.grdp
new file mode 100644
index 0000000..a3610ce
--- /dev/null
+++ b/components/nux_google_apps_strings.grdp
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<grit-part>
+  <message name="IDS_NUX_GOOGLE_APPS_GET_STARTED" desc="Message for a confirmation button that will add the selected apps from a list.">
+    Get started
+  </message>
+  <message name="IDS_NUX_GOOGLE_APPS_DESCRIPTION" desc="Description of what selecting apps and pressing 'Get started' will do.">
+    Get quick access to your favorite Google Apps
+  </message>
+</grit-part>
diff --git a/components/policy/core/DEPS b/components/policy/core/DEPS
index bf2973b..2afec685 100644
--- a/components/policy/core/DEPS
+++ b/components/policy/core/DEPS
@@ -6,4 +6,5 @@
   "+google_apis",
   "+net",
   "+third_party/re2",
+  "+services/network/public/cpp",
 ]
diff --git a/components/policy/core/browser/browser_policy_connector.h b/components/policy/core/browser/browser_policy_connector.h
index 158376a..d7e189c 100644
--- a/components/policy/core/browser/browser_policy_connector.h
+++ b/components/policy/core/browser/browser_policy_connector.h
@@ -10,6 +10,7 @@
 #include <string>
 
 #include "base/macros.h"
+#include "base/memory/ref_counted.h"
 #include "components/policy/core/browser/browser_policy_connector_base.h"
 #include "components/policy/policy_export.h"
 
@@ -20,6 +21,10 @@
 class URLRequestContextGetter;
 }
 
+namespace network {
+class SharedURLLoaderFactory;
+}
+
 namespace policy {
 
 class DeviceManagementService;
@@ -36,7 +41,8 @@
   // tests that don't require the full policy system running.
   virtual void Init(
       PrefService* local_state,
-      scoped_refptr<net::URLRequestContextGetter> request_context) = 0;
+      scoped_refptr<net::URLRequestContextGetter> request_context,
+      scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) = 0;
 
   // Checks whether this device is under any kind of enterprise management.
   virtual bool IsEnterpriseManaged() const = 0;
diff --git a/components/policy/core/common/BUILD.gn b/components/policy/core/common/BUILD.gn
index 922f57e..7fbc0f12 100644
--- a/components/policy/core/common/BUILD.gn
+++ b/components/policy/core/common/BUILD.gn
@@ -158,6 +158,7 @@
     "//extensions/buildflags",
     "//google_apis",
     "//net",
+    "//services/network/public/cpp",
     "//third_party/libxml",
     "//third_party/re2",
     "//url",
@@ -289,6 +290,7 @@
     "//components/policy/proto",
     "//crypto",
     "//net",
+    "//services/network/public/cpp",
     "//testing/gmock",
     "//testing/gtest",
   ]
diff --git a/components/policy/core/common/cloud/cloud_policy_client.cc b/components/policy/core/common/cloud/cloud_policy_client.cc
index 4ac1d00..be4700e 100644
--- a/components/policy/core/common/cloud/cloud_policy_client.cc
+++ b/components/policy/core/common/cloud/cloud_policy_client.cc
@@ -21,6 +21,7 @@
 #include "google_apis/gaia/gaia_constants.h"
 #include "google_apis/gaia/gaia_urls.h"
 #include "net/url_request/url_request_context_getter.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
 
 namespace em = enterprise_management;
 
@@ -100,6 +101,7 @@
     const std::string& brand_code,
     DeviceManagementService* service,
     scoped_refptr<net::URLRequestContextGetter> request_context,
+    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
     SigningService* signing_service,
     DeviceDMTokenCallback device_dm_token_callback)
     : machine_id_(machine_id),
@@ -109,6 +111,7 @@
       signing_service_(signing_service),
       device_dm_token_callback_(device_dm_token_callback),
       request_context_(request_context),
+      url_loader_factory_(url_loader_factory),
       weak_ptr_factory_(this) {}
 
 CloudPolicyClient::~CloudPolicyClient() {
@@ -682,6 +685,11 @@
   return request_context_;
 }
 
+scoped_refptr<network::SharedURLLoaderFactory>
+CloudPolicyClient::GetURLLoaderFactory() {
+  return url_loader_factory_;
+}
+
 int CloudPolicyClient::GetActiveRequestCountForTest() const {
   return request_jobs_.size();
 }
diff --git a/components/policy/core/common/cloud/cloud_policy_client.h b/components/policy/core/common/cloud/cloud_policy_client.h
index 129becb..7562e66 100644
--- a/components/policy/core/common/cloud/cloud_policy_client.h
+++ b/components/policy/core/common/cloud/cloud_policy_client.h
@@ -28,6 +28,9 @@
 namespace net {
 class URLRequestContextGetter;
 }
+namespace network {
+class SharedURLLoaderFactory;
+}
 
 namespace policy {
 
@@ -104,13 +107,15 @@
   // requests. |device_dm_token_callback| is used to retrieve device DMToken for
   // affiliated users. Could be null if it's not possible to use
   // device DMToken for user policy fetches.
-  CloudPolicyClient(const std::string& machine_id,
-                    const std::string& machine_model,
-                    const std::string& brand_code,
-                    DeviceManagementService* service,
-                    scoped_refptr<net::URLRequestContextGetter> request_context,
-                    SigningService* signing_service,
-                    DeviceDMTokenCallback device_dm_token_callback);
+  CloudPolicyClient(
+      const std::string& machine_id,
+      const std::string& machine_model,
+      const std::string& brand_code,
+      DeviceManagementService* service,
+      scoped_refptr<net::URLRequestContextGetter> request_context,
+      scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
+      SigningService* signing_service,
+      DeviceDMTokenCallback device_dm_token_callback);
   virtual ~CloudPolicyClient();
 
   // Sets the DMToken, thereby establishing a registration with the server. A
@@ -349,6 +354,8 @@
 
   scoped_refptr<net::URLRequestContextGetter> GetRequestContext();
 
+  scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory();
+
   // Returns the number of active requests.
   int GetActiveRequestCountForTest() const;
 
@@ -513,7 +520,9 @@
   DeviceDMTokenCallback device_dm_token_callback_;
 
   base::ObserverList<Observer, true> observers_;
+
   scoped_refptr<net::URLRequestContextGetter> request_context_;
+  scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
 
  private:
   void SetClientId(const std::string& client_id);
diff --git a/components/policy/core/common/cloud/cloud_policy_client_registration_helper.cc b/components/policy/core/common/cloud/cloud_policy_client_registration_helper.cc
index e497788..ebc8e26 100644
--- a/components/policy/core/common/cloud/cloud_policy_client_registration_helper.cc
+++ b/components/policy/core/common/cloud/cloud_policy_client_registration_helper.cc
@@ -15,6 +15,7 @@
 #include "google_apis/gaia/google_service_auth_error.h"
 #include "google_apis/gaia/oauth2_token_service.h"
 #include "net/url_request/url_request_context_getter.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
 
 #if !defined(OS_ANDROID)
 #include "google_apis/gaia/oauth2_access_token_consumer.h"
@@ -102,9 +103,11 @@
  public:
   LoginTokenHelper();
 
-  void FetchAccessToken(const std::string& login_refresh_token,
-                        net::URLRequestContextGetter* context,
-                        const StringCallback& callback);
+  void FetchAccessToken(
+      const std::string& login_refresh_token,
+      net::URLRequestContextGetter* context,
+      scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
+      const StringCallback& callback);
 
  private:
   // OAuth2AccessTokenConsumer implementation:
@@ -121,14 +124,15 @@
 void CloudPolicyClientRegistrationHelper::LoginTokenHelper::FetchAccessToken(
     const std::string& login_refresh_token,
     net::URLRequestContextGetter* context,
+    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
     const StringCallback& callback) {
   DCHECK(!oauth2_access_token_fetcher_);
   callback_ = callback;
 
   // Start fetching an OAuth2 access token for the device management and
   // userinfo services.
-  oauth2_access_token_fetcher_.reset(
-      new OAuth2AccessTokenFetcherImpl(this, context, login_refresh_token));
+  oauth2_access_token_fetcher_.reset(new OAuth2AccessTokenFetcherImpl(
+      this, url_loader_factory, login_refresh_token));
   GaiaUrls* gaia_urls = GaiaUrls::GetInstance();
   oauth2_access_token_fetcher_->Start(
       gaia_urls->oauth2_chrome_client_id(),
@@ -153,9 +157,11 @@
     CloudPolicyClient* client,
     enterprise_management::DeviceRegisterRequest::Type registration_type)
     : context_(client->GetRequestContext()),
+      url_loader_factory_(client->GetURLLoaderFactory()),
       client_(client),
       registration_type_(registration_type) {
   DCHECK(context_);
+  DCHECK(url_loader_factory_);
   DCHECK(client_);
 }
 
@@ -207,8 +213,7 @@
   login_token_helper_.reset(
       new CloudPolicyClientRegistrationHelper::LoginTokenHelper());
   login_token_helper_->FetchAccessToken(
-      login_refresh_token,
-      context_.get(),
+      login_refresh_token, context_.get(), url_loader_factory_,
       base::Bind(&CloudPolicyClientRegistrationHelper::OnTokenFetched,
                  base::Unretained(this)));
 }
diff --git a/components/policy/core/common/cloud/cloud_policy_client_registration_helper.h b/components/policy/core/common/cloud/cloud_policy_client_registration_helper.h
index 517c35d..6301ca1 100644
--- a/components/policy/core/common/cloud/cloud_policy_client_registration_helper.h
+++ b/components/policy/core/common/cloud/cloud_policy_client_registration_helper.h
@@ -25,6 +25,10 @@
 class URLRequestContextGetter;
 }
 
+namespace network {
+class SharedURLLoaderFactory;
+}
+
 namespace policy {
 
 // Helper class that registers a CloudPolicyClient. It fetches an OAuth2 token
@@ -108,6 +112,7 @@
   std::string oauth_access_token_;
 
   scoped_refptr<net::URLRequestContextGetter> context_;
+  scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
   CloudPolicyClient* client_;
   enterprise_management::DeviceRegisterRequest::Type registration_type_;
   base::Closure callback_;
diff --git a/components/policy/core/common/cloud/cloud_policy_client_unittest.cc b/components/policy/core/common/cloud/cloud_policy_client_unittest.cc
index bb9e3d1..48adb8a6 100644
--- a/components/policy/core/common/cloud/cloud_policy_client_unittest.cc
+++ b/components/policy/core/common/cloud/cloud_policy_client_unittest.cc
@@ -25,6 +25,7 @@
 #include "components/policy/proto/device_management_backend.pb.h"
 #include "net/url_request/url_request_context_getter.h"
 #include "net/url_request/url_request_test_util.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -270,7 +271,7 @@
         new net::TestURLRequestContextGetter(loop_.task_runner());
     client_ = std::make_unique<CloudPolicyClient>(
         kMachineID, kMachineModel, kBrandCode, &service_, request_context_,
-        &fake_signing_service_,
+        /*url_loader_factory_*/ nullptr, &fake_signing_service_,
         base::BindRepeating(
             &MockDeviceDMTokenCallbackObserver::OnDeviceDMTokenRequested,
             base::Unretained(&device_dmtoken_callback_observer_)));
diff --git a/components/policy/core/common/cloud/mock_cloud_policy_client.cc b/components/policy/core/common/cloud/mock_cloud_policy_client.cc
index 5f41eb4..22d1d6eb 100644
--- a/components/policy/core/common/cloud/mock_cloud_policy_client.cc
+++ b/components/policy/core/common/cloud/mock_cloud_policy_client.cc
@@ -8,6 +8,7 @@
 #include "components/policy/core/common/cloud/mock_cloud_policy_client.h"
 #include "components/policy/proto/device_management_backend.pb.h"
 #include "net/url_request/url_request_context_getter.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
 
 namespace em = enterprise_management;
 
@@ -19,6 +20,7 @@
                         std::string() /* brand_code */,
                         nullptr /* service */,
                         nullptr /* request_context */,
+                        nullptr /* url_loader_factory */,
                         nullptr /* signing_service */,
                         CloudPolicyClient::DeviceDMTokenCallback()) {}
 
diff --git a/components/policy/core/common/cloud/user_cloud_policy_manager.cc b/components/policy/core/common/cloud/user_cloud_policy_manager.cc
index 4723279..868f03e1 100644
--- a/components/policy/core/common/cloud/user_cloud_policy_manager.cc
+++ b/components/policy/core/common/cloud/user_cloud_policy_manager.cc
@@ -20,6 +20,7 @@
 #include "components/policy/core/common/policy_types.h"
 #include "components/policy/policy_constants.h"
 #include "net/url_request/url_request_context_getter.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
 
 namespace em = enterprise_management;
 
@@ -83,11 +84,12 @@
 std::unique_ptr<CloudPolicyClient>
 UserCloudPolicyManager::CreateCloudPolicyClient(
     DeviceManagementService* device_management_service,
-    scoped_refptr<net::URLRequestContextGetter> request_context) {
+    scoped_refptr<net::URLRequestContextGetter> request_context,
+    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) {
   return std::make_unique<CloudPolicyClient>(
       std::string() /* machine_id */, std::string() /* machine_model */,
       std::string() /* brand_code */, device_management_service,
-      request_context, nullptr /* signing_service */,
+      request_context, url_loader_factory, nullptr /* signing_service */,
       CloudPolicyClient::DeviceDMTokenCallback());
 }
 
diff --git a/components/policy/core/common/cloud/user_cloud_policy_manager.h b/components/policy/core/common/cloud/user_cloud_policy_manager.h
index 684cb7a..054cf9d 100644
--- a/components/policy/core/common/cloud/user_cloud_policy_manager.h
+++ b/components/policy/core/common/cloud/user_cloud_policy_manager.h
@@ -25,6 +25,9 @@
 namespace net {
 class URLRequestContextGetter;
 }
+namespace network {
+class SharedURLLoaderFactory;
+}
 
 namespace policy {
 
@@ -75,7 +78,8 @@
   // want to check if the user's domain requires policy).
   static std::unique_ptr<CloudPolicyClient> CreateCloudPolicyClient(
       DeviceManagementService* device_management_service,
-      scoped_refptr<net::URLRequestContextGetter> request_context);
+      scoped_refptr<net::URLRequestContextGetter> request_context,
+      scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory);
 
  private:
   // CloudPolicyManager:
diff --git a/components/policy/core/common/remote_commands/remote_commands_service_unittest.cc b/components/policy/core/common/remote_commands/remote_commands_service_unittest.cc
index 49cf9be..d6e44ba8 100644
--- a/components/policy/core/common/remote_commands/remote_commands_service_unittest.cc
+++ b/components/policy/core/common/remote_commands/remote_commands_service_unittest.cc
@@ -27,6 +27,7 @@
 #include "components/policy/core/common/remote_commands/testing_remote_commands_server.h"
 #include "components/policy/proto/device_management_backend.pb.h"
 #include "net/url_request/url_request_context_getter.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -88,6 +89,7 @@
                           std::string() /* brand_code */,
                           nullptr /* service */,
                           nullptr /* request_context */,
+                          nullptr /* url_loader_factory */,
                           nullptr /* signing_service */,
                           CloudPolicyClient::DeviceDMTokenCallback()),
         server_(server) {
diff --git a/components/resources/BUILD.gn b/components/resources/BUILD.gn
index b240ad23..55bf8ddf 100644
--- a/components/resources/BUILD.gn
+++ b/components/resources/BUILD.gn
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//components/nux_google_apps/features.gni")
 import("//printing/buildflags/buildflags.gni")
 import("//tools/grit/grit_rule.gni")
 import("//third_party/brotli/brotli.gni")
@@ -32,6 +33,7 @@
   defines = [
     "enable_basic_printing=$enable_basic_printing",
     "enable_print_preview=$enable_print_preview",
+    "enable_nux_google_apps=$enable_nux_google_apps",
   ]
 
   deps = [
diff --git a/components/resources/components_resources.grd b/components/resources/components_resources.grd
index 4623e36e..803a4ce 100644
--- a/components/resources/components_resources.grd
+++ b/components/resources/components_resources.grd
@@ -16,6 +16,9 @@
       <part file="net_log_resources.grdp" />
       <part file="neterror_resources.grdp" />
       <part file="ntp_tiles_resources.grdp" />
+      <if expr="enable_nux_google_apps">
+        <part file="nux_google_apps.grdp" />
+      </if>
       <part file="offline_pages_resources.grdp" />
       <part file="password_manager_internals_resources.grdp" />
       <part file="printing_resources.grdp" />
diff --git a/components/resources/nux_google_apps.grdp b/components/resources/nux_google_apps.grdp
new file mode 100644
index 0000000..0218fa6
--- /dev/null
+++ b/components/resources/nux_google_apps.grdp
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<grit-part>
+  <include name="IDR_NUX_GOOGLE_APPS_HTML" file="../nux_google_apps/resources/nux_google_apps.html" type="BINDATA" />
+  <include name="IDR_NUX_GOOGLE_APPS_JS" file="../nux_google_apps/resources/nux_google_apps.js" type="BINDATA" />
+  <include name="IDR_NUX_GOOGLE_APPS_CHOOSER_HTML" file="../nux_google_apps/resources/apps_chooser.html" type="BINDATA" />
+  <include name="IDR_NUX_GOOGLE_APPS_CHOOSER_JS" file="../nux_google_apps/resources/apps_chooser.js" type="BINDATA" />
+  <include name="IDR_NUX_GOOGLE_APPS_CHROME_STORE_1X" file="../nux_google_apps/resources/chrome_store_24dp_1x.png" type="BINDATA" />
+  <include name="IDR_NUX_GOOGLE_APPS_CHROME_STORE_2X" file="../nux_google_apps/resources/chrome_store_24dp_2x.png" type="BINDATA" />
+  <include name="IDR_NUX_GOOGLE_APPS_GMAIL_1X" file="../nux_google_apps/resources/gmail_24dp_1x.png" type="BINDATA" />
+  <include name="IDR_NUX_GOOGLE_APPS_GMAIL_2X" file="../nux_google_apps/resources/gmail_24dp_2x.png" type="BINDATA" />
+  <include name="IDR_NUX_GOOGLE_APPS_MAPS_1X" file="../nux_google_apps/resources/maps_24dp_1x.png" type="BINDATA" />
+  <include name="IDR_NUX_GOOGLE_APPS_MAPS_2X" file="../nux_google_apps/resources/maps_24dp_2x.png" type="BINDATA" />
+  <include name="IDR_NUX_GOOGLE_APPS_NEWS_1X" file="../nux_google_apps/resources/news_24dp_1x.png" type="BINDATA" />
+  <include name="IDR_NUX_GOOGLE_APPS_NEWS_2X" file="../nux_google_apps/resources/news_24dp_2x.png" type="BINDATA" />
+  <include name="IDR_NUX_GOOGLE_APPS_TRANSLATE_1X" file="../nux_google_apps/resources/translate_24dp_1x.png" type="BINDATA" />
+  <include name="IDR_NUX_GOOGLE_APPS_TRANSLATE_2X" file="../nux_google_apps/resources/translate_24dp_2x.png" type="BINDATA" />
+  <include name="IDR_NUX_GOOGLE_APPS_YOUTUBE_1X" file="../nux_google_apps/resources/youtube_24dp_1x.png" type="BINDATA" />
+  <include name="IDR_NUX_GOOGLE_APPS_YOUTUBE_2X" file="../nux_google_apps/resources/youtube_24dp_2x.png" type="BINDATA" />
+</grit-part>
diff --git a/components/services/font/BUILD.gn b/components/services/font/BUILD.gn
index 5ca31f1..f88c119 100644
--- a/components/services/font/BUILD.gn
+++ b/components/services/font/BUILD.gn
@@ -4,6 +4,8 @@
 
 import("//services/service_manager/public/cpp/service.gni")
 import("//services/service_manager/public/service_manifest.gni")
+import("//services/service_manager/public/tools/test/service_test.gni")
+import("//testing/test.gni")
 
 source_set("lib") {
   sources = [
@@ -13,6 +15,7 @@
 
   deps = [
     "//base",
+    "//base/test:fontconfig_util_linux",
     "//components/services/font/public/interfaces",
     "//mojo/public/cpp/bindings",
     "//mojo/public/cpp/system",
@@ -41,3 +44,38 @@
   name = "font_service"
   source = "manifest.json"
 }
+
+service_test("font_service_unittests") {
+  sources = [
+    "font_loader_test.cc",
+    "font_loader_test.h",
+  ]
+
+  catalog = ":font_service_unittests_catalog"
+
+  deps = [
+    "//base",
+    "//base/test:fontconfig_util_linux",
+    "//components/services/font/public/cpp",
+    "//components/services/font/public/interfaces",
+    "//mojo/public/cpp/bindings",
+    "//mojo/public/cpp/system",
+    "//services/service_manager/public/cpp",
+    "//services/service_manager/public/cpp:service_test_support",
+    "//skia",
+  ]
+
+  data_deps = [
+    ":font_service",
+  ]
+}
+
+service_manifest("test_manifest") {
+  name = "font_service_unittests"
+  source = "test_manifest.json"
+}
+
+catalog("font_service_unittests_catalog") {
+  embedded_services = [ ":test_manifest" ]
+  standalone_services = [ ":manifest" ]
+}
diff --git a/components/services/font/OWNERS b/components/services/font/OWNERS
index 0447911a..3d43cf0 100644
--- a/components/services/font/OWNERS
+++ b/components/services/font/OWNERS
@@ -1,4 +1,6 @@
-erg@chromium.org
+drott@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/components/services/font/font_loader_test.cc b/components/services/font/font_loader_test.cc
new file mode 100644
index 0000000..6c449916
--- /dev/null
+++ b/components/services/font/font_loader_test.cc
@@ -0,0 +1,93 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/services/font/font_loader_test.h"
+
+#include <utility>
+
+#include "base/run_loop.h"
+#include "base/test/fontconfig_util_linux.h"
+#include "components/services/font/public/interfaces/constants.mojom.h"
+#include "components/services/font/public/interfaces/font_service.mojom.h"
+#include "services/service_manager/public/cpp/connector.h"
+#include "third_party/skia/include/core/SkFontStyle.h"
+
+namespace {
+bool IsInTestFontDirectory(const char* path) {
+  const char kTestFontsDir[] = "test_fonts";
+  return std::string(path).find(kTestFontsDir) != std::string::npos;
+}
+}  // namespace
+
+namespace font_service {
+
+FontLoaderTest::FontLoaderTest() : ServiceTest("font_service_unittests") {}
+
+FontLoaderTest::~FontLoaderTest() {}
+
+void FontLoaderTest::SetUp() {
+  ServiceTest::SetUp();
+  font_loader_ = std::make_unique<FontLoader>(connector());
+}
+
+TEST_F(FontLoaderTest, BasicMatchingTest) {
+  SkFontStyle styles[] = {
+      SkFontStyle(SkFontStyle::kNormal_Weight, SkFontStyle::kNormal_Width,
+                  SkFontStyle::kUpright_Slant),
+      SkFontStyle(SkFontStyle::kBold_Weight, SkFontStyle::kNormal_Width,
+                  SkFontStyle::kUpright_Slant),
+      SkFontStyle(SkFontStyle::kBold_Weight, SkFontStyle::kNormal_Width,
+                  SkFontStyle::kItalic_Slant)};
+  // See kFontsConfTemplate[] in fontconfig_util_linux.cc for details of which
+  // fonts can be picked. Arial, Times New Roman and Courier New are aliased to
+  // Arimos, Tinos and Cousine ChromeOS open source alternatives when FontConfig
+  // is set up for testing.
+  std::vector<std::vector<std::string>> family_names_expected_names = {
+      {"Arial", "Arimo"},
+      {"Times New Roman", "Tinos"},
+      {"Courier New", "Cousine"}};
+  for (std::vector<std::string> request_family_name :
+       family_names_expected_names) {
+    for (auto& request_style : styles) {
+      SkFontConfigInterface::FontIdentity font_identity;
+      SkFontStyle result_style;
+      SkString result_family_name;
+      font_loader()->matchFamilyName(request_family_name[0].c_str(),
+                                     request_style, &font_identity,
+                                     &result_family_name, &result_style);
+      EXPECT_EQ(request_family_name[1],
+                std::string(result_family_name.c_str()));
+      EXPECT_TRUE(IsInTestFontDirectory(font_identity.fString.c_str()));
+      EXPECT_EQ(result_style, request_style);
+    }
+  }
+}
+
+TEST_F(FontLoaderTest, NotFoundTest) {
+  std::string request_family_name = {"IMPROBABLE_FONT_NAME"};
+  SkFontConfigInterface::FontIdentity font_identity;
+  SkFontStyle result_style;
+  SkString result_family_name;
+  font_loader()->matchFamilyName(request_family_name.c_str(), SkFontStyle(),
+                                 &font_identity, &result_family_name,
+                                 &result_style);
+  EXPECT_EQ("", std::string(result_family_name.c_str()));
+  EXPECT_EQ(0u, font_identity.fID);
+  EXPECT_EQ("", std::string(font_identity.fString.c_str()));
+}
+
+TEST_F(FontLoaderTest, EmptyFontName) {
+  std::string request_family_name = {""};
+  std::string kDefaultFontName = "DejaVu Sans";
+  SkFontConfigInterface::FontIdentity font_identity;
+  SkFontStyle result_style;
+  SkString result_family_name;
+  font_loader()->matchFamilyName(request_family_name.c_str(), SkFontStyle(),
+                                 &font_identity, &result_family_name,
+                                 &result_style);
+  EXPECT_EQ(kDefaultFontName, std::string(result_family_name.c_str()));
+  EXPECT_TRUE(IsInTestFontDirectory(font_identity.fString.c_str()));
+}
+
+}  // namespace font_service
diff --git a/components/services/font/font_loader_test.h b/components/services/font/font_loader_test.h
new file mode 100644
index 0000000..a0a4499
--- /dev/null
+++ b/components/services/font/font_loader_test.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 COMPONENTS_SERVICES_FONT_FONT_LOADER_TEST_H_
+#define COMPONENTS_SERVICES_FONT_FONT_LOADER_TEST_H_
+
+#include <utility>
+
+#include "base/bind.h"
+#include "base/macros.h"
+#include "components/services/font/public/cpp/font_loader.h"
+#include "components/services/font/public/interfaces/font_service.mojom.h"
+#include "mojo/public/cpp/bindings/binding.h"
+#include "services/service_manager/public/cpp/service_test.h"
+
+namespace font_service {
+
+class FontLoaderTest : public service_manager::test::ServiceTest {
+ public:
+  FontLoaderTest();
+  ~FontLoaderTest() override;
+
+  // Overridden from service_manager::test::ServiceTest:
+  void SetUp() override;
+
+ protected:
+  FontLoader* font_loader() { return font_loader_.get(); }
+
+ private:
+  std::unique_ptr<FontLoader> font_loader_;
+
+  DISALLOW_COPY_AND_ASSIGN(FontLoaderTest);
+};
+
+}  // namespace font_service
+
+#endif  // COMPONENTS_SERVICES_FONT_FONT_LOADER_TEST_H_
diff --git a/components/services/font/font_service_app.cc b/components/services/font/font_service_app.cc
index 63ecd06..ee7cd5d 100644
--- a/components/services/font/font_service_app.cc
+++ b/components/services/font/font_service_app.cc
@@ -6,8 +6,10 @@
 
 #include <utility>
 
+#include "base/command_line.h"
 #include "base/files/file.h"
 #include "base/files/file_path.h"
+#include "base/test/fontconfig_util_linux.h"
 #include "mojo/public/cpp/system/platform_handle.h"
 #include "services/service_manager/public/cpp/service_context.h"
 
@@ -35,16 +37,31 @@
   return file;
 }
 
+bool FontConfigTestingEnvironmentEnabled() {
+  return base::CommandLine::ForCurrentProcess()->GetSwitches().count(
+      switches::kFontConfigTestingEnvironment);
+}
+
 }  // namespace
 
 namespace font_service {
 
 FontServiceApp::FontServiceApp() {
+  // TODO(thomasanderson) https://crbug.com/831146: Remove this once a reland of
+  // CL https://chromium-review.googlesource.com/c/chromium/src/+/1009071 lands,
+  // which propagates the FONTCONFIG_FILE environment variable to subprocesses
+  // and thus ensures, child/utility processes receive the correct fontconfig
+  // testing environment.
+  if (FontConfigTestingEnvironmentEnabled())
+    base::SetUpFontconfig();
   registry_.AddInterface(
       base::Bind(&FontServiceApp::Create, base::Unretained(this)));
 }
 
-FontServiceApp::~FontServiceApp() {}
+FontServiceApp::~FontServiceApp() {
+  if (FontConfigTestingEnvironmentEnabled())
+    base::TearDownFontconfig();
+}
 
 void FontServiceApp::OnStart() {}
 
diff --git a/components/services/font/manifest.json b/components/services/font/manifest.json
index 434a7ff3..8463ffe 100644
--- a/components/services/font/manifest.json
+++ b/components/services/font/manifest.json
@@ -5,10 +5,7 @@
   "interface_provider_specs": {
     "service_manager:connector": {
       "provides": {
-        "app": [ "font_service.mojom.FontService" ]
-      },
-      "requires": {
-        "*": [ "app" ]
+        "font_service": [ "font_service.mojom.FontService" ]
       }
     }
   }
diff --git a/components/services/font/test_manifest.json b/components/services/font/test_manifest.json
new file mode 100644
index 0000000..a968987
--- /dev/null
+++ b/components/services/font/test_manifest.json
@@ -0,0 +1,11 @@
+{
+  "name": "font_service_unittests",
+  "display_name": "Font Service Unittests",
+  "interface_provider_specs": {
+    "service_manager:connector": {
+      "requires": {
+        "font_service": [ "font_service" ]
+      }
+    }
+  }
+}
diff --git a/components/signin/DEPS b/components/signin/DEPS
index 20e335b..813a642 100644
--- a/components/signin/DEPS
+++ b/components/signin/DEPS
@@ -13,3 +13,9 @@
   "+net",
   "+sql",
 ]
+
+specific_include_rules = {
+  "test_signin_client\.h": [
+    "+services/network/test"
+  ]
+}
\ No newline at end of file
diff --git a/components/signin/core/browser/fake_profile_oauth2_token_service.cc b/components/signin/core/browser/fake_profile_oauth2_token_service.cc
index 9710636..e7a6cc2 100644
--- a/components/signin/core/browser/fake_profile_oauth2_token_service.cc
+++ b/components/signin/core/browser/fake_profile_oauth2_token_service.cc
@@ -123,6 +123,7 @@
     RequestImpl* request,
     const std::string& account_id,
     net::URLRequestContextGetter* getter,
+    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
     const std::string& client_id,
     const std::string& client_secret,
     const ScopeSet& scopes) {
diff --git a/components/signin/core/browser/fake_profile_oauth2_token_service.h b/components/signin/core/browser/fake_profile_oauth2_token_service.h
index 9edcd08..f8f0d18 100644
--- a/components/signin/core/browser/fake_profile_oauth2_token_service.h
+++ b/components/signin/core/browser/fake_profile_oauth2_token_service.h
@@ -87,12 +87,14 @@
 
  protected:
   // OAuth2TokenService overrides.
-  void FetchOAuth2Token(RequestImpl* request,
-                        const std::string& account_id,
-                        net::URLRequestContextGetter* getter,
-                        const std::string& client_id,
-                        const std::string& client_secret,
-                        const ScopeSet& scopes) override;
+  void FetchOAuth2Token(
+      RequestImpl* request,
+      const std::string& account_id,
+      net::URLRequestContextGetter* getter,
+      scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
+      const std::string& client_id,
+      const std::string& client_secret,
+      const ScopeSet& scopes) override;
 
   void InvalidateAccessTokenImpl(const std::string& account_id,
                                  const std::string& client_id,
diff --git a/components/signin/core/browser/signin_client.h b/components/signin/core/browser/signin_client.h
index fbaf5c8..00be28e 100644
--- a/components/signin/core/browser/signin_client.h
+++ b/components/signin/core/browser/signin_client.h
@@ -29,6 +29,9 @@
 namespace net {
 class URLRequestContextGetter;
 }
+namespace network {
+class SharedURLLoaderFactory;
+}
 
 namespace network {
 class SharedURLLoaderFactory;
diff --git a/components/signin/ios/browser/profile_oauth2_token_service_ios_delegate.h b/components/signin/ios/browser/profile_oauth2_token_service_ios_delegate.h
index 79ae397..5a298de 100644
--- a/components/signin/ios/browser/profile_oauth2_token_service_ios_delegate.h
+++ b/components/signin/ios/browser/profile_oauth2_token_service_ios_delegate.h
@@ -29,6 +29,7 @@
   OAuth2AccessTokenFetcher* CreateAccessTokenFetcher(
       const std::string& account_id,
       net::URLRequestContextGetter* getter,
+      scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
       OAuth2AccessTokenConsumer* consumer) override;
 
   // KeyedService
diff --git a/components/signin/ios/browser/profile_oauth2_token_service_ios_delegate.mm b/components/signin/ios/browser/profile_oauth2_token_service_ios_delegate.mm
index f3089c3..5d620896 100644
--- a/components/signin/ios/browser/profile_oauth2_token_service_ios_delegate.mm
+++ b/components/signin/ios/browser/profile_oauth2_token_service_ios_delegate.mm
@@ -301,6 +301,7 @@
 ProfileOAuth2TokenServiceIOSDelegate::CreateAccessTokenFetcher(
     const std::string& account_id,
     net::URLRequestContextGetter* getter,
+    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
     OAuth2AccessTokenConsumer* consumer) {
   AccountInfo account_info =
       account_tracker_service_->GetAccountInfo(account_id);
diff --git a/components/signin/ios/browser/profile_oauth2_token_service_ios_delegate_unittest.mm b/components/signin/ios/browser/profile_oauth2_token_service_ios_delegate_unittest.mm
index 9131b9b..f14ece7 100644
--- a/components/signin/ios/browser/profile_oauth2_token_service_ios_delegate_unittest.mm
+++ b/components/signin/ios/browser/profile_oauth2_token_service_ios_delegate_unittest.mm
@@ -261,7 +261,8 @@
   scopes.push_back("scope");
   std::unique_ptr<OAuth2AccessTokenFetcher> fetcher1(
       oauth2_delegate_->CreateAccessTokenFetcher(
-          GetAccountId(account1), oauth2_delegate_->GetRequestContext(), this));
+          GetAccountId(account1), oauth2_delegate_->GetRequestContext(),
+          oauth2_delegate_->GetURLLoaderFactory(), this));
   fetcher1->Start("foo", "bar", scopes);
   EXPECT_EQ(0, access_token_success_);
   EXPECT_EQ(0, access_token_failure_);
@@ -284,7 +285,8 @@
   scopes.push_back("scope");
   std::unique_ptr<OAuth2AccessTokenFetcher> fetcher1(
       oauth2_delegate_->CreateAccessTokenFetcher(
-          GetAccountId(account1), oauth2_delegate_->GetRequestContext(), this));
+          GetAccountId(account1), oauth2_delegate_->GetRequestContext(),
+          oauth2_delegate_->GetURLLoaderFactory(), this));
   fetcher1->Start("foo", "bar", scopes);
   EXPECT_EQ(0, access_token_success_);
   EXPECT_EQ(0, access_token_failure_);
diff --git a/components/translate/core/browser/translate_download_manager.cc b/components/translate/core/browser/translate_download_manager.cc
index ee0efd7..e6130e83 100644
--- a/components/translate/core/browser/translate_download_manager.cc
+++ b/components/translate/core/browser/translate_download_manager.cc
@@ -74,6 +74,7 @@
   DCHECK(sequence_checker_.CalledOnValidSequence());
   language_list_.reset(new TranslateLanguageList);
   script_.reset(new TranslateScript);
+  url_loader_factory_ = nullptr;
 }
 
 void TranslateDownloadManager::SetTranslateScriptExpirationDelay(int delay_ms) {
diff --git a/components/translate/core/browser/translate_language_list_unittest.cc b/components/translate/core/browser/translate_language_list_unittest.cc
index 31573d1..6f588f0 100644
--- a/components/translate/core/browser/translate_language_list_unittest.cc
+++ b/components/translate/core/browser/translate_language_list_unittest.cc
@@ -160,6 +160,8 @@
   languages.clear();
   language_list.GetSupportedLanguages(true /* translate_allowed */, &languages);
   EXPECT_EQ(std::vector<std::string>(1, "it"), languages);
+
+  TranslateDownloadManager::GetInstance()->ResetForTesting();
 }
 
 // Check that we don't send any network data when translate is disabled by
@@ -186,6 +188,8 @@
   // language list load.
   EXPECT_FALSE(language_list.HasOngoingLanguageListLoadingForTesting());
   EXPECT_TRUE(test_url_loader_factory.pending_requests()->empty());
+
+  TranslateDownloadManager::GetInstance()->ResetForTesting();
 }
 
 }  // namespace translate
diff --git a/components/translate/core/browser/translate_manager_unittest.cc b/components/translate/core/browser/translate_manager_unittest.cc
index 2b31765..84a4f61 100644
--- a/components/translate/core/browser/translate_manager_unittest.cc
+++ b/components/translate/core/browser/translate_manager_unittest.cc
@@ -432,20 +432,8 @@
       1);
 }
 
-#if defined(OS_IOS)
-#if TARGET_OS_SIMULATOR
-#define MAYBE_OverrideTriggerWithIndiaEnglishExperimentAcceptPrompt \
-  OverrideTriggerWithIndiaEnglishExperimentAcceptPrompt
-#else  // !TARGET_OS_SIMULATOR
-#define MAYBE_OverrideTriggerWithIndiaEnglishExperimentAcceptPrompt \
-  DISABLED_OverrideTriggerWithIndiaEnglishExperimentAcceptPrompt
-#endif  // TARGET_OS_SIMULATOR
-#else   // !defined(OS_IOS)
-#define MAYBE_OverrideTriggerWithIndiaEnglishExperimentAcceptPrompt \
-  OverrideTriggerWithIndiaEnglishExperimentAcceptPrompt
-#endif  // defined(OS_IOS)
 TEST_F(TranslateManagerTest,
-       MAYBE_OverrideTriggerWithIndiaEnglishExperimentAcceptPrompt) {
+       OverrideTriggerWithIndiaEnglishExperimentAcceptPrompt) {
   manager_->set_application_locale("en");
   scoped_feature_list_.InitAndEnableFeatureWithParameters(
       language::kOverrideTranslateTriggerInIndia,
diff --git a/components/translate/core/browser/translate_script_unittest.cc b/components/translate/core/browser/translate_script_unittest.cc
index 0a3805c..866541f 100644
--- a/components/translate/core/browser/translate_script_unittest.cc
+++ b/components/translate/core/browser/translate_script_unittest.cc
@@ -40,7 +40,10 @@
         test_shared_loader_factory_);
   }
 
-  void TearDown() override { script_.reset(); }
+  void TearDown() override {
+    script_.reset();
+    TranslateDownloadManager::GetInstance()->ResetForTesting();
+  }
 
   void Request() {
     script_->Request(
diff --git a/content/browser/background_fetch/background_fetch.proto b/content/browser/background_fetch/background_fetch.proto
index ec387edd..91f2a167 100644
--- a/content/browser/background_fetch/background_fetch.proto
+++ b/content/browser/background_fetch/background_fetch.proto
@@ -28,31 +28,36 @@
 // Developer provided options.
 // https://wicg.github.io/background-fetch/#background-fetch-manager
 //
-// Next Tag: 4
+// Next Tag: 3
 message BackgroundFetchOptions {
   optional string title = 1;
 
-  // https://w3c.github.io/manifest/#icons-member
-  // Note that sizes can have multiple values (e.g. "32x32 64x64").
+  // https://w3c.github.io/manifest/#dom-imageresource
   //
-  // Next Tag: 4
-  message IconDefinition {
+  // Next Tag: 5
+  message ImageResource {
     optional string src = 1;
-    optional string sizes = 2;
-    optional string type = 3;
+
+    // Next Tag: 3
+    message Size {
+      optional int32 width = 1;
+      optional int32 height = 2;
+    }
+
+    repeated Size sizes = 2;
+    optional bytes type = 3;
+
+    // https://w3c.github.io/manifest/#purpose-member
+    enum Purpose {
+      ANY = 1;
+      BADGE = 2;
+    }
+
+    // blink::Manifest::ImageResource::Purpose enum.
+    repeated Purpose purpose = 4;
   }
 
-  // Example value:
-  // icons: {
-  //   src: "icon/lowres.webp"
-  //   sizes: "48x48"
-  //   type: "image/webp"
-  // }
-  // icons: {
-  //   src: "icon/hd_hi.ico"
-  //   sizes: "72x72 96x96 128x128 256x256"
-  // }
-  repeated IconDefinition icons = 2;
+  repeated ImageResource icons = 2;
 
   optional uint64 download_total = 3;
 }
@@ -103,4 +108,4 @@
   optional string serialized_request = 3;
   optional string download_guid = 4;
   optional bool succeeded = 5;
-}
\ No newline at end of file
+}
diff --git a/content/browser/background_fetch/background_fetch_service_unittest.cc b/content/browser/background_fetch/background_fetch_service_unittest.cc
index b791518..5fc825a 100644
--- a/content/browser/background_fetch/background_fetch_service_unittest.cc
+++ b/content/browser/background_fetch/background_fetch_service_unittest.cc
@@ -9,6 +9,7 @@
 #include "base/auto_reset.h"
 #include "base/macros.h"
 #include "base/run_loop.h"
+#include "base/strings/utf_string_conversions.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "base/time/time.h"
 #include "content/browser/background_fetch/background_fetch_context.h"
@@ -23,6 +24,8 @@
 #include "mojo/edk/embedder/embedder.h"
 #include "mojo/public/cpp/bindings/message.h"
 #include "services/network/public/mojom/fetch_api.mojom.h"
+#include "third_party/blink/public/common/manifest/manifest.h"
+#include "ui/gfx/geometry/size.h"
 
 namespace content {
 namespace {
@@ -31,13 +34,13 @@
 const char kExampleDeveloperId[] = "my-background-fetch";
 const char kAlternativeDeveloperId[] = "my-alternative-fetch";
 
-IconDefinition CreateIcon(std::string src,
-                          std::string sizes,
-                          std::string type) {
-  IconDefinition icon;
-  icon.src = std::move(src);
+blink::Manifest::ImageResource CreateIcon(const std::string& src,
+                                          std::vector<gfx::Size> sizes,
+                                          const std::string& type) {
+  blink::Manifest::ImageResource icon;
+  icon.src = GURL(src);
   icon.sizes = std::move(sizes);
-  icon.type = std::move(type);
+  icon.type = base::ASCIIToUTF16(type);
 
   return icon;
 }
@@ -350,8 +353,10 @@
   requests.emplace_back();  // empty, but valid
 
   BackgroundFetchOptions options;
-  options.icons.push_back(CreateIcon("funny_cat.png", "256x256", "image/png"));
-  options.icons.push_back(CreateIcon("silly_cat.gif", "512x512", "image/gif"));
+  options.icons.push_back(
+      CreateIcon("funny_cat.png", {{256, 256}}, "image/png"));
+  options.icons.push_back(
+      CreateIcon("silly_cat.gif", {{512, 512}}, "image/gif"));
   options.title = "My Background Fetch!";
   options.download_total = 9001;
 
@@ -1020,8 +1025,10 @@
   requests.emplace_back();  // empty, but valid
 
   BackgroundFetchOptions options;
-  options.icons.push_back(CreateIcon("funny_cat.png", "256x256", "image/png"));
-  options.icons.push_back(CreateIcon("silly_cat.gif", "512x512", "image/gif"));
+  options.icons.push_back(
+      CreateIcon("funny_cat.png", {{256, 256}}, "image/png"));
+  options.icons.push_back(
+      CreateIcon("silly_cat.gif", {{512, 512}}, "image/gif"));
   options.title = "My Background Fetch!";
   options.download_total = 9001;
 
diff --git a/content/browser/background_fetch/storage/create_metadata_task.cc b/content/browser/background_fetch/storage/create_metadata_task.cc
index d305eb5..bba456b 100644
--- a/content/browser/background_fetch/storage/create_metadata_task.cc
+++ b/content/browser/background_fetch/storage/create_metadata_task.cc
@@ -7,6 +7,7 @@
 #include <utility>
 
 #include "base/strings/string_number_conversions.h"
+#include "base/strings/utf_string_conversions.h"
 #include "content/browser/background_fetch/storage/database_helpers.h"
 #include "content/browser/service_worker/service_worker_context_wrapper.h"
 #include "content/common/service_worker/service_worker_status_code.h"
@@ -75,10 +76,30 @@
   options_proto->set_title(options_.title);
   options_proto->set_download_total(options_.download_total);
   for (const auto& icon : options_.icons) {
-    auto* icon_definition_proto = options_proto->add_icons();
-    icon_definition_proto->set_src(icon.src);
-    icon_definition_proto->set_sizes(icon.sizes);
-    icon_definition_proto->set_type(icon.type);
+    auto* image_resource_proto = options_proto->add_icons();
+
+    image_resource_proto->set_src(icon.src.spec());
+
+    for (const auto& size : icon.sizes) {
+      auto* size_proto = image_resource_proto->add_sizes();
+      size_proto->set_width(size.width());
+      size_proto->set_height(size.height());
+    }
+
+    image_resource_proto->set_type(base::UTF16ToASCII(icon.type));
+
+    for (const auto& purpose : icon.purpose) {
+      switch (purpose) {
+        case blink::Manifest::ImageResource::Purpose::ANY:
+          image_resource_proto->add_purpose(
+              proto::BackgroundFetchOptions_ImageResource_Purpose_ANY);
+          break;
+        case blink::Manifest::ImageResource::Purpose::BADGE:
+          image_resource_proto->add_purpose(
+              proto::BackgroundFetchOptions_ImageResource_Purpose_BADGE);
+          break;
+      }
+    }
   }
 
   // Set other metadata fields.
diff --git a/content/browser/compositor/gpu_process_transport_factory.cc b/content/browser/compositor/gpu_process_transport_factory.cc
index d3dc6c9..ff1001c 100644
--- a/content/browser/compositor/gpu_process_transport_factory.cc
+++ b/content/browser/compositor/gpu_process_transport_factory.cc
@@ -266,7 +266,7 @@
       ozone_platform->GetOverlayManager();
   if (!command_line->HasSwitch(switches::kEnableHardwareOverlays) &&
       overlay_manager->SupportsOverlays()) {
-    enable_overlay_flag = "single-fullscreen,single-on-top,underlay";
+    enable_overlay_flag = "single-fullscreen,single-on-top";
   }
   if (!enable_overlay_flag.empty()) {
     std::unique_ptr<ui::OverlayCandidatesOzone> overlay_candidates =
diff --git a/content/browser/display_cutout_browsertest.cc b/content/browser/display_cutout_browsertest.cc
index 80c3e51..3a5bd08 100644
--- a/content/browser/display_cutout_browsertest.cc
+++ b/content/browser/display_cutout_browsertest.cc
@@ -15,6 +15,7 @@
 #include "content/public/test/test_utils.h"
 #include "content/shell/browser/shell.h"
 #include "content/test/content_browser_test_utils_internal.h"
+#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
 #include "third_party/blink/public/mojom/page/display_cutout.mojom.h"
 
 namespace content {
@@ -50,6 +51,18 @@
   DISALLOW_COPY_AND_ASSIGN(TestWebContentsObserver);
 };
 
+const char kTestHTML[] =
+    "<!DOCTYPE html>"
+    "<style>"
+    "  #target {"
+    "    margin-top: env(safe-area-inset-top);"
+    "    margin-left: env(safe-area-inset-left);"
+    "    margin-bottom: env(safe-area-inset-bottom);"
+    "    margin-right: env(safe-area-inset-right);"
+    "  }"
+    "</style>"
+    "<div id=target></div>";
+
 }  // namespace
 
 class DisplayCutoutBrowserTest : public ContentBrowserTest {
@@ -57,8 +70,13 @@
   DisplayCutoutBrowserTest() {}
 
   void SetUpCommandLine(base::CommandLine* command_line) override {
-    command_line->AppendSwitchASCII("enable-blink-features",
-                                    "DisplayCutoutAPI,CSSViewport");
+    command_line->AppendSwitchASCII(
+        "enable-blink-features",
+        "DisplayCutoutAPI,CSSViewport,CSSEnvironmentVariables");
+  }
+
+  content::RenderFrameHost* MainFrame() {
+    return shell()->web_contents()->GetMainFrame();
   }
 
   void LoadTestPageWithViewportFitFromMeta(const std::string& value) {
@@ -97,6 +115,41 @@
         "document.getElementsByTagName('meta')[0].content = ''");
   }
 
+  void SendSafeAreaToFrame(int top, int left, int bottom, int right) {
+    blink::mojom::DisplayCutoutClientAssociatedPtr client;
+    MainFrame()->GetRemoteAssociatedInterfaces()->GetInterface(&client);
+    client->SetSafeArea(
+        blink::mojom::DisplayCutoutSafeArea::New(top, left, bottom, right));
+  }
+
+  std::string GetCurrentSafeAreaValue(const std::string& name) {
+    std::string value;
+    EXPECT_TRUE(ExecuteScriptAndExtractString(
+        MainFrame(),
+        "(() => {"
+        "const e = document.getElementById('target');"
+        "const style = window.getComputedStyle(e, null);"
+        "window.domAutomationController.send("
+        "  style.getPropertyValue('margin-" +
+            name +
+            "'));"
+            "})();",
+        &value));
+    return value;
+  }
+
+  void LoadTestPageWithData(const std::string& data) {
+    GURL url("https://www.example.com");
+
+    TestNavigationObserver same_tab_observer(shell()->web_contents(), 1);
+#if defined(OS_ANDROID)
+    shell()->LoadDataAsStringWithBaseURL(url, data, url);
+#else
+    shell()->LoadDataWithBaseURL(url, data, url);
+#endif
+    same_tab_observer.Wait();
+  }
+
  private:
   void LoadSubFrameWithData(const std::string& html_data) {
     const std::string data =
@@ -116,18 +169,6 @@
     web_contents->Focus();
   }
 
-  void LoadTestPageWithData(const std::string& data) {
-    GURL url("https://www.example.com");
-
-    TestNavigationObserver same_tab_observer(shell()->web_contents(), 1);
-#if defined(OS_ANDROID)
-    shell()->LoadDataAsStringWithBaseURL(url, data, url);
-#else
-    shell()->LoadDataWithBaseURL(url, data, url);
-#endif
-    same_tab_observer.Wait();
-  }
-
   DISALLOW_COPY_AND_ASSIGN(DisplayCutoutBrowserTest);
 };
 
@@ -238,4 +279,22 @@
   observer.WaitForWantedValue(blink::mojom::ViewportFit::kAuto);
 }
 
+IN_PROC_BROWSER_TEST_F(DisplayCutoutBrowserTest, PublishSafeAreaVariables) {
+  LoadTestPageWithData(kTestHTML);
+
+  // Make sure all the safe areas are currently zero.
+  EXPECT_EQ("0px", GetCurrentSafeAreaValue("top"));
+  EXPECT_EQ("0px", GetCurrentSafeAreaValue("left"));
+  EXPECT_EQ("0px", GetCurrentSafeAreaValue("bottom"));
+  EXPECT_EQ("0px", GetCurrentSafeAreaValue("right"));
+
+  SendSafeAreaToFrame(1, 2, 3, 4);
+
+  // Make sure all the safe ares are correctly set.
+  EXPECT_EQ("1px", GetCurrentSafeAreaValue("top"));
+  EXPECT_EQ("2px", GetCurrentSafeAreaValue("left"));
+  EXPECT_EQ("3px", GetCurrentSafeAreaValue("bottom"));
+  EXPECT_EQ("4px", GetCurrentSafeAreaValue("right"));
+}
+
 }  //  namespace content
diff --git a/content/browser/gpu/gpu_internals_ui.cc b/content/browser/gpu/gpu_internals_ui.cc
index 9efc4c36..ebd34b8e 100644
--- a/content/browser/gpu/gpu_internals_ui.cc
+++ b/content/browser/gpu/gpu_internals_ui.cc
@@ -439,8 +439,12 @@
       return "dolby vision profile 7";
     case gpu::THEORAPROFILE_ANY:
       return "theora";
-    case gpu::AV1PROFILE_PROFILE0:
-      return "av1 profile0";
+    case gpu::AV1PROFILE_PROFILE_MAIN:
+      return "av1 profile main";
+    case gpu::AV1PROFILE_PROFILE_HIGH:
+      return "av1 profile high";
+    case gpu::AV1PROFILE_PROFILE_PRO:
+      return "av1 profile pro";
   }
   NOTREACHED();
   return "";
diff --git a/content/browser/media/cdm_registry_impl_unittest.cc b/content/browser/media/cdm_registry_impl_unittest.cc
index 96547c4f..1a94af7 100644
--- a/content/browser/media/cdm_registry_impl_unittest.cc
+++ b/content/browser/media/cdm_registry_impl_unittest.cc
@@ -21,6 +21,12 @@
 
 namespace content {
 
+namespace {
+
+using VideoCodec = media::VideoCodec;
+using EncryptionMode = media::EncryptionMode;
+using CdmSessionType = media::CdmSessionType;
+
 const char kTestCdmName[] = "Test CDM";
 const char kAlternateCdmName[] = "Alternate CDM";
 const char kTestCdmGuid[] = "62FE9C4B-384E-48FD-B28A-9F6F248BC8CC";
@@ -30,6 +36,28 @@
 const char kTestKeySystem[] = "com.example.somesystem";
 const char kTestFileSystemId[] = "file_system_id";
 
+// Helper function to compare a STL container to an initializer_list.
+template <typename Container, typename T>
+bool StlEquals(const Container a, std::initializer_list<T> b) {
+  return a == Container(b);
+}
+
+#define EXPECT_STL_EQ(a, ...)                 \
+  do {                                        \
+    EXPECT_TRUE(StlEquals(a, {__VA_ARGS__})); \
+  } while (false)
+
+#define EXPECT_VIDEO_CODECS(...) \
+  EXPECT_STL_EQ(cdm.supported_video_codecs, __VA_ARGS__)
+
+#define EXPECT_ENCRYPTION_SCHEMES(...) \
+  EXPECT_STL_EQ(cdm.supported_encryption_schemes, __VA_ARGS__)
+
+#define EXPECT_SESSION_TYPES(...) \
+  EXPECT_STL_EQ(cdm.supported_session_types, __VA_ARGS__)
+
+}  // namespace
+
 // For simplicity and to make failures easier to diagnose, this test uses
 // std::string instead of base::FilePath and std::vector<std::string>.
 class CdmRegistryImplTest : public testing::Test {
@@ -38,19 +66,21 @@
   ~CdmRegistryImplTest() override {}
 
  protected:
-  void Register(const std::string& name,
-                const std::string& version,
-                const std::string& path,
-                const std::vector<media::VideoCodec>& supported_video_codecs,
-                bool supports_persistent_license,
-                const base::flat_set<media::EncryptionMode>& supported_modes,
-                std::string supported_key_system,
-                bool supports_sub_key_systems = false) {
-    cdm_registry_.RegisterCdm(CdmInfo(
-        name, kTestCdmGuid, base::Version(version),
-        base::FilePath::FromUTF8Unsafe(path), kTestFileSystemId,
-        supported_video_codecs, supports_persistent_license, supported_modes,
-        supported_key_system, supports_sub_key_systems));
+  void Register(
+      const std::string& name,
+      const std::string& version,
+      const std::string& path,
+      const std::vector<VideoCodec>& supported_video_codecs,
+      const base::flat_set<CdmSessionType>& supported_session_types,
+      const base::flat_set<EncryptionMode>& supported_encryption_schemes,
+      std::string supported_key_system,
+      bool supports_sub_key_systems = false) {
+    cdm_registry_.RegisterCdm(
+        CdmInfo(name, kTestCdmGuid, base::Version(version),
+                base::FilePath::FromUTF8Unsafe(path), kTestFileSystemId,
+                supported_video_codecs, supported_session_types,
+                supported_encryption_schemes, supported_key_system,
+                supports_sub_key_systems));
   }
 
   bool IsRegistered(const std::string& name, const std::string& version) {
@@ -76,8 +106,10 @@
 
 TEST_F(CdmRegistryImplTest, Register) {
   Register(kTestCdmName, kVersion1, kTestPath,
-           {media::kCodecVP8, media::kCodecVP9}, true,
-           {media::EncryptionMode::kCenc}, kTestKeySystem, true);
+           {media::kCodecVP8, media::kCodecVP9},
+           {CdmSessionType::TEMPORARY_SESSION,
+            CdmSessionType::PERSISTENT_LICENSE_SESSION},
+           {EncryptionMode::kCenc}, kTestKeySystem, true);
   std::vector<CdmInfo> cdms = cdm_registry_.GetAllRegisteredCdms();
   ASSERT_EQ(1u, cdms.size());
   CdmInfo cdm = cdms[0];
@@ -85,42 +117,45 @@
   EXPECT_EQ(kVersion1, cdm.version.GetString());
   EXPECT_EQ(kTestPath, cdm.path.MaybeAsASCII());
   EXPECT_EQ(kTestFileSystemId, cdm.file_system_id);
-  EXPECT_EQ(2u, cdm.supported_video_codecs.size());
-  EXPECT_EQ(media::kCodecVP8, cdm.supported_video_codecs[0]);
-  EXPECT_EQ(media::kCodecVP9, cdm.supported_video_codecs[1]);
-  EXPECT_TRUE(cdm.supports_persistent_license);
-  EXPECT_EQ(1u, cdm.supported_encryption_schemes.size());
-  EXPECT_EQ(
-      1u, cdm.supported_encryption_schemes.count(media::EncryptionMode::kCenc));
+  EXPECT_VIDEO_CODECS(VideoCodec::kCodecVP8, VideoCodec::kCodecVP9);
+  EXPECT_SESSION_TYPES(CdmSessionType::TEMPORARY_SESSION,
+                       CdmSessionType::PERSISTENT_LICENSE_SESSION);
+  EXPECT_ENCRYPTION_SCHEMES(EncryptionMode::kCenc);
   EXPECT_EQ(kTestKeySystem, cdm.supported_key_system);
   EXPECT_TRUE(cdm.supports_sub_key_systems);
 }
 
 TEST_F(CdmRegistryImplTest, ReRegister) {
-  Register(kTestCdmName, kVersion1, "/bb/cc", {}, false,
-           {media::EncryptionMode::kCenc}, kTestKeySystem);
+  Register(kTestCdmName, kVersion1, "/bb/cc", {},
+           {CdmSessionType::TEMPORARY_SESSION}, {EncryptionMode::kCenc},
+           kTestKeySystem);
   EXPECT_TRUE(IsRegistered(kTestCdmName, kVersion1));
 
   // Now register same key system with different values.
-  Register(kTestCdmName, kVersion1, kTestPath, {}, false,
-           {media::EncryptionMode::kCenc}, kTestKeySystem);
+  Register(kTestCdmName, kVersion1, kTestPath, {},
+           {CdmSessionType::TEMPORARY_SESSION}, {EncryptionMode::kCenc},
+           kTestKeySystem);
   EXPECT_TRUE(IsRegistered(kTestCdmName, kVersion1));
 }
 
 TEST_F(CdmRegistryImplTest, MultipleVersions) {
-  Register(kTestCdmName, kVersion1, kTestPath, {}, false,
-           {media::EncryptionMode::kCenc}, kTestKeySystem);
-  Register(kTestCdmName, kVersion2, "/bb/cc", {}, false,
-           {media::EncryptionMode::kCenc}, kTestKeySystem);
+  Register(kTestCdmName, kVersion1, kTestPath, {},
+           {CdmSessionType::TEMPORARY_SESSION}, {EncryptionMode::kCenc},
+           kTestKeySystem);
+  Register(kTestCdmName, kVersion2, "/bb/cc", {},
+           {CdmSessionType::TEMPORARY_SESSION}, {EncryptionMode::kCenc},
+           kTestKeySystem);
   EXPECT_TRUE(IsRegistered(kTestCdmName, kVersion1));
   EXPECT_TRUE(IsRegistered(kTestCdmName, kVersion2));
 }
 
 TEST_F(CdmRegistryImplTest, NewVersionInsertedLast) {
-  Register(kTestCdmName, kVersion1, kTestPath, {}, false,
-           {media::EncryptionMode::kCenc}, kTestKeySystem);
-  Register(kTestCdmName, kVersion2, "/bb/cc", {}, false,
-           {media::EncryptionMode::kCenc}, kTestKeySystem);
+  Register(kTestCdmName, kVersion1, kTestPath, {},
+           {CdmSessionType::TEMPORARY_SESSION}, {EncryptionMode::kCenc},
+           kTestKeySystem);
+  Register(kTestCdmName, kVersion2, "/bb/cc", {},
+           {CdmSessionType::TEMPORARY_SESSION}, {EncryptionMode::kCenc},
+           kTestKeySystem);
 
   const std::vector<std::string> versions = GetVersions(kTestCdmGuid);
   EXPECT_EQ(2u, versions.size());
@@ -129,27 +164,25 @@
 }
 
 TEST_F(CdmRegistryImplTest, DifferentNames) {
-  Register(kTestCdmName, kVersion1, kTestPath, {}, false,
-           {media::EncryptionMode::kCenc}, kTestKeySystem);
-  Register(kAlternateCdmName, kVersion1, kTestPath, {}, false,
-           {media::EncryptionMode::kCbcs}, kTestKeySystem);
+  Register(kTestCdmName, kVersion1, kTestPath, {},
+           {CdmSessionType::TEMPORARY_SESSION}, {EncryptionMode::kCenc},
+           kTestKeySystem);
+  Register(kAlternateCdmName, kVersion1, kTestPath, {},
+           {CdmSessionType::TEMPORARY_SESSION}, {EncryptionMode::kCbcs},
+           kTestKeySystem);
   EXPECT_TRUE(IsRegistered(kTestCdmName, kVersion1));
   EXPECT_TRUE(IsRegistered(kAlternateCdmName, kVersion1));
 }
 
 TEST_F(CdmRegistryImplTest, SupportedEncryptionSchemes) {
-  Register(kTestCdmName, kVersion1, kTestPath, {}, false,
-           {media::EncryptionMode::kCenc, media::EncryptionMode::kCbcs},
-           kTestKeySystem);
+  Register(kTestCdmName, kVersion1, kTestPath, {},
+           {CdmSessionType::TEMPORARY_SESSION},
+           {EncryptionMode::kCenc, EncryptionMode::kCbcs}, kTestKeySystem);
 
   std::vector<CdmInfo> cdms = cdm_registry_.GetAllRegisteredCdms();
   ASSERT_EQ(1u, cdms.size());
   const CdmInfo& cdm = cdms[0];
-  EXPECT_EQ(2u, cdm.supported_encryption_schemes.size());
-  EXPECT_EQ(
-      1u, cdm.supported_encryption_schemes.count(media::EncryptionMode::kCenc));
-  EXPECT_EQ(
-      1u, cdm.supported_encryption_schemes.count(media::EncryptionMode::kCbcs));
+  EXPECT_ENCRYPTION_SCHEMES(EncryptionMode::kCenc, EncryptionMode::kCbcs);
 }
 
 }  // namespace content
diff --git a/content/browser/media/key_system_support_impl.cc b/content/browser/media/key_system_support_impl.cc
index b0e70d2..8e73bcc 100644
--- a/content/browser/media/key_system_support_impl.cc
+++ b/content/browser/media/key_system_support_impl.cc
@@ -56,6 +56,11 @@
   return result;
 }
 
+template <typename T>
+std::vector<T> SetToVector(const base::flat_set<T>& s) {
+  return std::vector<T>(s.begin(), s.end());
+}
+
 }  // namespace
 
 // static
@@ -102,10 +107,9 @@
 
   // Supported codecs and encryption schemes.
   auto capability = media::mojom::KeySystemCapability::New();
-  const auto& schemes = cdm_info->supported_encryption_schemes;
   capability->video_codecs = cdm_info->supported_video_codecs;
   capability->encryption_schemes =
-      std::vector<media::EncryptionMode>(schemes.begin(), schemes.end());
+      SetToVector(cdm_info->supported_encryption_schemes);
 
   if (base::FeatureList::IsEnabled(media::kHardwareSecureDecryption)) {
     capability->hw_secure_video_codecs =
@@ -116,14 +120,7 @@
     NOTIMPLEMENTED();
   }
 
-  // Temporary session is always supported.
-  // TODO(xhwang): Populate this from CdmInfo.
-  capability->session_types.push_back(media::CdmSessionType::TEMPORARY_SESSION);
-
-  if (cdm_info->supports_persistent_license) {
-    capability->session_types.push_back(
-        media::CdmSessionType::PERSISTENT_LICENSE_SESSION);
-  }
+  capability->session_types = SetToVector(cdm_info->supported_session_types);
 
   std::move(callback).Run(true, std::move(capability));
 }
diff --git a/content/browser/media/key_system_support_impl_unittest.cc b/content/browser/media/key_system_support_impl_unittest.cc
index 8c24d9d..377217d 100644
--- a/content/browser/media/key_system_support_impl_unittest.cc
+++ b/content/browser/media/key_system_support_impl_unittest.cc
@@ -60,20 +60,21 @@
     KeySystemSupportImpl::Create(mojo::MakeRequest(&key_system_support_));
   }
 
-  // Registers |key_system| with |supported_video_codecs| and
-  // |supports_persistent_license|. All other values for CdmInfo have some
-  // default value as they're not returned by IsKeySystemSupported().
-  void Register(const std::string& key_system,
-                const std::vector<media::VideoCodec>& supported_video_codecs,
-                bool supports_persistent_license,
-                const base::flat_set<media::EncryptionMode>& supported_modes) {
+  // Registers |key_system| with supported capabilities. All other values for
+  // CdmInfo have some default value as they're not returned by
+  // IsKeySystemSupported().
+  void Register(
+      const std::string& key_system,
+      const std::vector<VideoCodec>& supported_video_codecs,
+      const base::flat_set<CdmSessionType>& supported_session_types,
+      const base::flat_set<EncryptionMode>& supported_encryption_schemes) {
     DVLOG(1) << __func__;
 
     CdmRegistry::GetInstance()->RegisterCdm(
         CdmInfo(key_system, kTestCdmGuid, base::Version(kVersion),
                 base::FilePath::FromUTF8Unsafe(kTestPath), kTestFileSystemId,
-                supported_video_codecs, supports_persistent_license,
-                supported_modes, key_system, false));
+                supported_video_codecs, supported_session_types,
+                supported_encryption_schemes, key_system, false));
   }
 
   // Determines if |key_system| is registered. If it is, updates |codecs_|
@@ -103,7 +104,9 @@
 }
 
 TEST_F(KeySystemSupportTest, OneKeySystem) {
-  Register("KeySystem2", {VideoCodec::kCodecVP8}, true,
+  Register("KeySystem2", {VideoCodec::kCodecVP8},
+           {CdmSessionType::TEMPORARY_SESSION,
+            CdmSessionType::PERSISTENT_LICENSE_SESSION},
            {EncryptionMode::kCenc, EncryptionMode::kCbcs});
 
   EXPECT_TRUE(IsSupported("KeySystem2"));
@@ -114,11 +117,12 @@
 }
 
 TEST_F(KeySystemSupportTest, MultipleKeySystems) {
-  Register("KeySystem3",
-           {media::VideoCodec::kCodecVP8, media::VideoCodec::kCodecVP9}, true,
-           {media::EncryptionMode::kCenc});
-  Register("KeySystem4", {media::VideoCodec::kCodecVP9}, false,
-           {media::EncryptionMode::kCbcs});
+  Register("KeySystem3", {VideoCodec::kCodecVP8, VideoCodec::kCodecVP9},
+           {CdmSessionType::TEMPORARY_SESSION,
+            CdmSessionType::PERSISTENT_LICENSE_SESSION},
+           {EncryptionMode::kCenc});
+  Register("KeySystem4", {VideoCodec::kCodecVP9},
+           {CdmSessionType::TEMPORARY_SESSION}, {EncryptionMode::kCbcs});
 
   EXPECT_TRUE(IsSupported("KeySystem3"));
   EXPECT_VIDEO_CODECS(VideoCodec::kCodecVP8, VideoCodec::kCodecVP9);
@@ -133,8 +137,10 @@
 }
 
 TEST_F(KeySystemSupportTest, MissingKeySystem) {
-  Register("KeySystem5", {media::VideoCodec::kCodecVP8}, true,
-           {media::EncryptionMode::kCenc});
+  Register("KeySystem5", {VideoCodec::kCodecVP8},
+           {CdmSessionType::TEMPORARY_SESSION,
+            CdmSessionType::PERSISTENT_LICENSE_SESSION},
+           {EncryptionMode::kCenc});
 
   EXPECT_FALSE(IsSupported("KeySystem6"));
   EXPECT_FALSE(capability_);
diff --git a/content/browser/webauth/webauth_browsertest.cc b/content/browser/webauth/webauth_browsertest.cc
index 5d6c70e4..3d052c0 100644
--- a/content/browser/webauth/webauth_browsertest.cc
+++ b/content/browser/webauth/webauth_browsertest.cc
@@ -969,18 +969,10 @@
 
 // WebAuthBrowserCtapTest ----------------------------------------------
 
-// A test fixture that enables CTAP only flag.
 class WebAuthBrowserCtapTest : public WebAuthLocalClientBrowserTest {
  public:
   WebAuthBrowserCtapTest() = default;
-
- protected:
-  std::vector<base::Feature> GetFeaturesToEnable() override {
-    return {features::kWebAuth, device::kNewCtap2Device};
-  }
-
- private:
-  base::test::ScopedFeatureList scoped_feature_list_;
+  ~WebAuthBrowserCtapTest() override = default;
 
   DISALLOW_COPY_AND_ASSIGN(WebAuthBrowserCtapTest);
 };
diff --git a/content/common/background_fetch/background_fetch_struct_traits.cc b/content/common/background_fetch/background_fetch_struct_traits.cc
index e6d7be1..0f2d005 100644
--- a/content/common/background_fetch/background_fetch_struct_traits.cc
+++ b/content/common/background_fetch/background_fetch_struct_traits.cc
@@ -8,6 +8,8 @@
 #include "content/common/service_worker/service_worker_fetch_request_mojom_traits.h"
 #include "content/common/service_worker/service_worker_messages.h"
 #include "mojo/public/cpp/bindings/array_data_view.h"
+#include "third_party/blink/public/common/manifest/manifest_mojom_traits.h"
+#include "third_party/blink/public/mojom/manifest/manifest.mojom.h"
 
 namespace mojo {
 
@@ -49,13 +51,4 @@
          data.ReadResponse(&fetch->response);
 }
 
-// static
-bool StructTraits<
-    blink::mojom::IconDefinitionDataView,
-    content::IconDefinition>::Read(blink::mojom::IconDefinitionDataView data,
-                                   content::IconDefinition* definition) {
-  return data.ReadSrc(&definition->src) && data.ReadSizes(&definition->sizes) &&
-         data.ReadType(&definition->type);
-}
-
 }  // namespace mojo
diff --git a/content/common/background_fetch/background_fetch_struct_traits.h b/content/common/background_fetch/background_fetch_struct_traits.h
index aaf094ed..380748db 100644
--- a/content/common/background_fetch/background_fetch_struct_traits.h
+++ b/content/common/background_fetch/background_fetch_struct_traits.h
@@ -11,6 +11,7 @@
 #include "content/common/background_fetch/background_fetch_types.h"
 #include "content/common/content_export.h"
 #include "mojo/public/cpp/bindings/struct_traits.h"
+#include "third_party/blink/public/common/manifest/manifest.h"
 #include "third_party/blink/public/platform/modules/background_fetch/background_fetch.mojom.h"
 
 namespace content {
@@ -24,7 +25,7 @@
 template <>
 struct CONTENT_EXPORT StructTraits<blink::mojom::BackgroundFetchOptionsDataView,
                                    content::BackgroundFetchOptions> {
-  static const std::vector<content::IconDefinition>& icons(
+  static const std::vector<blink::Manifest::ImageResource>& icons(
       const content::BackgroundFetchOptions& options) {
     return options.icons;
   }
@@ -91,23 +92,6 @@
                    content::BackgroundFetchSettledFetch* definition);
 };
 
-template <>
-struct CONTENT_EXPORT StructTraits<blink::mojom::IconDefinitionDataView,
-                                   content::IconDefinition> {
-  static const std::string& src(const content::IconDefinition& definition) {
-    return definition.src;
-  }
-  static const std::string& sizes(const content::IconDefinition& definition) {
-    return definition.sizes;
-  }
-  static const std::string& type(const content::IconDefinition& definition) {
-    return definition.type;
-  }
-
-  static bool Read(blink::mojom::IconDefinitionDataView data,
-                   content::IconDefinition* definition);
-};
-
 }  // namespace mojo
 
 #endif  // CONTENT_BROWSER_BACKGROUND_FETCH_BACKGROUND_FETCH_STRUCT_TRAITS_H_
diff --git a/content/common/background_fetch/background_fetch_struct_traits_unittest.cc b/content/common/background_fetch/background_fetch_struct_traits_unittest.cc
index 3e8c85f..a4d4858 100644
--- a/content/common/background_fetch/background_fetch_struct_traits_unittest.cc
+++ b/content/common/background_fetch/background_fetch_struct_traits_unittest.cc
@@ -6,39 +6,38 @@
 
 #include <utility>
 
+#include "base/strings/utf_string_conversions.h"
 #include "content/common/background_fetch/background_fetch_types.h"
+#include "mojo/public/cpp/base/string16_mojom_traits.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/manifest/manifest.h"
+#include "third_party/blink/public/common/manifest/manifest_mojom_traits.h"
+#include "ui/gfx/geometry/mojo/geometry_struct_traits.h"
+#include "ui/gfx/geometry/size.h"
+#include "url/mojom/url_gurl_mojom_traits.h"
 
 namespace content {
 
 namespace {
 
 // Creates a new IconDefinition object for the given arguments.
-IconDefinition CreateIconDefinition(std::string src,
-                                    std::string sizes,
-                                    std::string type) {
-  IconDefinition definition;
-  definition.src = std::move(src);
-  definition.sizes = std::move(sizes);
-  definition.type = std::move(type);
+blink::Manifest::ImageResource CreateIcon(const std::string& src,
+                                          std::vector<gfx::Size> sizes,
+                                          const std::string& type) {
+  blink::Manifest::ImageResource icon;
+  icon.src = GURL(src);
+  icon.sizes = std::move(sizes);
+  icon.type = base::ASCIIToUTF16(type);
 
-  return definition;
-}
-
-// Returns whether the given IconDefinition objects are identical.
-bool IconDefinitionsAreIdentical(const IconDefinition& left,
-                                 const IconDefinition& right) {
-  return left.src == right.src && left.sizes == right.sizes &&
-         left.type == right.type;
+  return icon;
 }
 
 }  // namespace
 
 TEST(BackgroundFetchStructTraitsTest, BackgroundFetchOptionsRoundtrip) {
   BackgroundFetchOptions options;
-  options.icons = {
-      CreateIconDefinition("my_icon.png", "256x256", "image/png"),
-      CreateIconDefinition("my_small_icon.jpg", "128x128", "image/jpg")};
+  options.icons = {CreateIcon("my_icon.png", {{256, 256}}, "image/png"),
+                   CreateIcon("my_small_icon.jpg", {{128, 128}}, "image/jpg")};
   options.title = "My Background Fetch";
   options.download_total = 9001;
 
@@ -48,10 +47,8 @@
       &roundtrip_options));
 
   ASSERT_EQ(roundtrip_options.icons.size(), options.icons.size());
-  for (size_t i = 0; i < options.icons.size(); ++i) {
-    EXPECT_TRUE(IconDefinitionsAreIdentical(options.icons[i],
-                                            roundtrip_options.icons[i]));
-  }
+  for (size_t i = 0; i < options.icons.size(); ++i)
+    EXPECT_EQ(options.icons[i], roundtrip_options.icons[i]);
 
   EXPECT_EQ(roundtrip_options.title, options.title);
   EXPECT_EQ(roundtrip_options.download_total, options.download_total);
@@ -75,15 +72,14 @@
 }
 
 TEST(BackgroundFetchStructTraitsTest, IconDefinitionRoundtrip) {
-  IconDefinition definition =
-      CreateIconDefinition("my_icon.png", "256x256", "image/png");
+  blink::Manifest::ImageResource icon =
+      CreateIcon("my_icon.png", {{256, 256}}, "image/png");
 
-  IconDefinition roundtrip_definition;
-  ASSERT_TRUE(blink::mojom::IconDefinition::Deserialize(
-      blink::mojom::IconDefinition::Serialize(&definition),
-      &roundtrip_definition));
+  blink::Manifest::ImageResource roundtrip_icon;
+  ASSERT_TRUE(blink::mojom::ManifestImageResource::Deserialize(
+      blink::mojom::ManifestImageResource::Serialize(&icon), &roundtrip_icon));
 
-  EXPECT_TRUE(IconDefinitionsAreIdentical(definition, roundtrip_definition));
+  EXPECT_EQ(icon, roundtrip_icon);
 }
 
 }  // namespace content
diff --git a/content/common/background_fetch/background_fetch_types.cc b/content/common/background_fetch/background_fetch_types.cc
index 13325ef..2d5ba68 100644
--- a/content/common/background_fetch/background_fetch_types.cc
+++ b/content/common/background_fetch/background_fetch_types.cc
@@ -6,12 +6,6 @@
 
 namespace content {
 
-IconDefinition::IconDefinition() = default;
-
-IconDefinition::IconDefinition(const IconDefinition& other) = default;
-
-IconDefinition::~IconDefinition() = default;
-
 BackgroundFetchOptions::BackgroundFetchOptions() = default;
 
 BackgroundFetchOptions::BackgroundFetchOptions(
diff --git a/content/common/background_fetch/background_fetch_types.h b/content/common/background_fetch/background_fetch_types.h
index 685b624c..fd77442 100644
--- a/content/common/background_fetch/background_fetch_types.h
+++ b/content/common/background_fetch/background_fetch_types.h
@@ -11,26 +11,10 @@
 
 #include "content/common/content_export.h"
 #include "content/common/service_worker/service_worker_types.h"
+#include "third_party/blink/public/common/manifest/manifest.h"
 
 namespace content {
 
-// Represents the definition of an icon developers can optionally provide with a
-// Background Fetch fetch. Analogous to the following structure in the spec:
-// https://wicg.github.io/background-fetch/#background-fetch-manager
-//
-// Parsing of the icon definitions as well as fetching an appropriate icon will
-// be done by Blink in the renderer process. The browser process is expected to
-// treat these values as opaque strings.
-struct CONTENT_EXPORT IconDefinition {
-  IconDefinition();
-  IconDefinition(const IconDefinition& other);
-  ~IconDefinition();
-
-  std::string src;
-  std::string sizes;
-  std::string type;
-};
-
 // Represents the optional options a developer can provide when starting a new
 // Background Fetch fetch. Analogous to the following structure in the spec:
 // https://wicg.github.io/background-fetch/#background-fetch-manager
@@ -39,7 +23,7 @@
   BackgroundFetchOptions(const BackgroundFetchOptions& other);
   ~BackgroundFetchOptions();
 
-  std::vector<IconDefinition> icons;
+  std::vector<blink::Manifest::ImageResource> icons;
   std::string title;
   uint64_t download_total = 0;
 };
diff --git a/content/common/media/cdm_info.cc b/content/common/media/cdm_info.cc
index 4e3dbbc..25b947f 100644
--- a/content/common/media/cdm_info.cc
+++ b/content/common/media/cdm_info.cc
@@ -16,7 +16,7 @@
     const base::FilePath& path,
     const std::string& file_system_id,
     const std::vector<media::VideoCodec>& supported_video_codecs,
-    bool supports_persistent_license,
+    const base::flat_set<media::CdmSessionType>& supported_session_types,
     const base::flat_set<media::EncryptionMode>& supported_encryption_schemes,
     const std::string& supported_key_system,
     bool supports_sub_key_systems)
@@ -26,7 +26,7 @@
       path(path),
       file_system_id(file_system_id),
       supported_video_codecs(supported_video_codecs),
-      supports_persistent_license(supports_persistent_license),
+      supported_session_types(supported_session_types),
       supported_encryption_schemes(supported_encryption_schemes),
       supported_key_system(supported_key_system),
       supports_sub_key_systems(supports_sub_key_systems) {
diff --git a/content/common/service_worker/service_worker_provider.mojom b/content/common/service_worker/service_worker_provider.mojom
index a423fb39..ee663f7 100644
--- a/content/common/service_worker/service_worker_provider.mojom
+++ b/content/common/service_worker/service_worker_provider.mojom
@@ -70,3 +70,18 @@
   // may or may not have been one previously), but not the other way around.
   OnControllerChanged(blink.mojom.ControllerServiceWorkerMode mode);
 };
+
+// ServiceWorkerWorkerClientRegistry is a mojo interface for hosting and
+// registering ServiceWorkerWorkerClients. An instance of this interface is
+// implemented by ServiceWorkerProviderContext and lives in the same renderer
+// process as the worker clients.
+// This interface is useful when one needs to register a new worker client
+// for an existing ServiceWorkerProviderContext on non-main thread, i.e. for
+// nested workers.
+interface ServiceWorkerWorkerClientRegistry {
+  // Adds a new ServiceWorkerWorkerClient.
+  RegisterWorkerClient(ServiceWorkerWorkerClient client);
+
+  // Clones this host.
+  CloneWorkerClientRegistry(ServiceWorkerWorkerClientRegistry& host);
+};
diff --git a/content/public/common/cdm_info.h b/content/public/common/cdm_info.h
index c3c2898..c182e942 100644
--- a/content/public/common/cdm_info.h
+++ b/content/public/common/cdm_info.h
@@ -12,6 +12,7 @@
 #include "base/files/file_path.h"
 #include "base/version.h"
 #include "content/common/content_export.h"
+#include "media/base/content_decryption_module.h"
 // TODO(crbug.com/825041): Move EncryptionMode out of decrypt_config and
 // rename it to EncryptionScheme.
 #include "media/base/decrypt_config.h"
@@ -28,7 +29,7 @@
       const base::FilePath& path,
       const std::string& file_system_id,
       const std::vector<media::VideoCodec>& supported_video_codecs,
-      bool supports_persistent_license,
+      const base::flat_set<media::CdmSessionType>& supported_session_types,
       const base::flat_set<media::EncryptionMode>& supported_encryption_schemes,
       const std::string& supported_key_system,
       bool supports_sub_key_systems);
@@ -60,11 +61,10 @@
   // TODO(crbug.com/796725) Find a way to include profiles and levels.
   std::vector<media::VideoCodec> supported_video_codecs;
 
-  // Whether this CDM supports persistent licenses.
-  bool supports_persistent_license;
+  // List of session types supported by the CDM.
+  base::flat_set<media::CdmSessionType> supported_session_types;
 
-  // List of encryption schemes supported by the CDM (e.g. cenc). This is the
-  // set of encryption schemes that the CDM supports.
+  // List of encryption schemes supported by the CDM (e.g. cenc).
   base::flat_set<media::EncryptionMode> supported_encryption_schemes;
 
   // The key system supported by this CDM.
diff --git a/content/renderer/accessibility/blink_ax_tree_source.cc b/content/renderer/accessibility/blink_ax_tree_source.cc
index 2e67e08..4a5a66cd 100644
--- a/content/renderer/accessibility/blink_ax_tree_source.cc
+++ b/content/renderer/accessibility/blink_ax_tree_source.cc
@@ -214,11 +214,22 @@
 
 BlinkAXTreeSource::BlinkAXTreeSource(RenderFrameImpl* render_frame,
                                      ui::AXMode mode)
-    : render_frame_(render_frame), accessibility_mode_(mode), frozen_(false) {}
+    : render_frame_(render_frame),
+      accessibility_mode_(mode),
+      frozen_(false),
+      hidden_(false) {}
 
 BlinkAXTreeSource::~BlinkAXTreeSource() {
 }
 
+void BlinkAXTreeSource::WasHidden() {
+  hidden_ = true;
+}
+
+void BlinkAXTreeSource::WasShown() {
+  hidden_ = false;
+}
+
 void BlinkAXTreeSource::Freeze() {
   CHECK(!frozen_);
   frozen_ = true;
@@ -372,6 +383,9 @@
     std::vector<WebAXObject>* out_children) const {
   CHECK(frozen_);
 
+  if (hidden_)
+    return;
+
   if ((parent.Role() == blink::kWebAXRoleStaticText ||
        parent.Role() == blink::kWebAXRoleLineBreak) &&
       ShouldLoadInlineTextBoxes(parent)) {
@@ -402,6 +416,9 @@
 WebAXObject BlinkAXTreeSource::GetParent(WebAXObject node) const {
   CHECK(frozen_);
 
+  if (hidden_)
+    return WebAXObject();
+
   // Blink returns ignored objects when walking up the parent chain,
   // we have to skip those here. Also, stop when we get to the root
   // element.
@@ -415,6 +432,9 @@
 }
 
 bool BlinkAXTreeSource::IsValid(WebAXObject node) const {
+  if (hidden_ && !node.Equals(root()))
+    return false;
+
   return !node.IsDetached();  // This also checks if it's null.
 }
 
diff --git a/content/renderer/accessibility/blink_ax_tree_source.h b/content/renderer/accessibility/blink_ax_tree_source.h
index 4447c4e..3047243 100644
--- a/content/renderer/accessibility/blink_ax_tree_source.h
+++ b/content/renderer/accessibility/blink_ax_tree_source.h
@@ -42,6 +42,11 @@
   BlinkAXTreeSource(RenderFrameImpl* render_frame, ui::AXMode mode);
   ~BlinkAXTreeSource() override;
 
+  // If the frame is hidden, expose only the root node and skip the
+  // rest of the tree.
+  void WasHidden();
+  void WasShown();
+
   // Freeze caches the document, accessibility root, and current focused
   // object for fast retrieval during a batch of operations. Use
   // ScopedFreezeBlinkAXTreeSource on the stack rather than calling
@@ -130,6 +135,10 @@
   blink::WebDocument document_;
   blink::WebAXObject root_;
   blink::WebAXObject focus_;
+
+  // If the page is hidden, we eliminate everything other than the
+  // root node.
+  bool hidden_;
 };
 
 }  // namespace content
diff --git a/content/renderer/accessibility/render_accessibility_impl.cc b/content/renderer/accessibility/render_accessibility_impl.cc
index 4f9e42c..bf2d709 100644
--- a/content/renderer/accessibility/render_accessibility_impl.cc
+++ b/content/renderer/accessibility/render_accessibility_impl.cc
@@ -125,6 +125,9 @@
     settings->SetInlineTextBoxAccessibilityEnabled(true);
 #endif
 
+  if (render_frame_->IsHidden())
+    tree_source_.WasHidden();
+
   const WebDocument& document = GetMainDocument();
   if (!document.IsNull()) {
     // It's possible that the webview has already loaded a webpage without
@@ -194,8 +197,22 @@
   return handled;
 }
 
+void RenderAccessibilityImpl::WasHidden() {
+  pending_events_.clear();
+  tree_source_.WasHidden();
+  HandleAXEvent(tree_source_.GetRoot(), ax::mojom::Event::kNone);
+}
+
+void RenderAccessibilityImpl::WasShown() {
+  pending_events_.clear();
+  tree_source_.WasShown();
+  HandleAXEvent(tree_source_.GetRoot(), ax::mojom::Event::kNone);
+}
+
 void RenderAccessibilityImpl::HandleWebAccessibilityEvent(
     const blink::WebAXObject& obj, blink::WebAXEvent event) {
+  if (render_frame_->IsHidden())
+    return;
   HandleAXEvent(obj, AXEventFromBlink(event));
 }
 
diff --git a/content/renderer/accessibility/render_accessibility_impl.h b/content/renderer/accessibility/render_accessibility_impl.h
index f2c5d3fb..5471666e 100644
--- a/content/renderer/accessibility/render_accessibility_impl.h
+++ b/content/renderer/accessibility/render_accessibility_impl.h
@@ -75,6 +75,8 @@
   // RenderFrameObserver implementation.
   void AccessibilityModeChanged() override;
   bool OnMessageReceived(const IPC::Message& message) override;
+  void WasHidden() override;
+  void WasShown() override;
 
   // Called when an accessibility notification occurs in Blink.
   void HandleWebAccessibilityEvent(const blink::WebAXObject& obj,
diff --git a/content/renderer/media/stream/media_stream_constraints_util.cc b/content/renderer/media/stream/media_stream_constraints_util.cc
index e406f56..d4111ac35 100644
--- a/content/renderer/media/stream/media_stream_constraints_util.cc
+++ b/content/renderer/media/stream/media_stream_constraints_util.cc
@@ -256,12 +256,13 @@
 
 VideoTrackAdapterSettings SelectVideoTrackAdapterSettings(
     const blink::WebMediaTrackConstraintSet& basic_constraint_set,
-    const ResolutionSet& resolution_set,
-    const NumericRangeSet<double>& frame_rate_set,
+    const media_constraints::ResolutionSet& resolution_set,
+    const media_constraints::NumericRangeSet<double>& frame_rate_set,
     const media::VideoCaptureFormat& source_format) {
-  ResolutionSet::Point resolution = resolution_set.SelectClosestPointToIdeal(
-      basic_constraint_set, source_format.frame_size.height(),
-      source_format.frame_size.width());
+  media_constraints::ResolutionSet::Point resolution =
+      resolution_set.SelectClosestPointToIdeal(
+          basic_constraint_set, source_format.frame_size.height(),
+          source_format.frame_size.width());
   int track_max_height = static_cast<int>(std::round(resolution.height()));
   int track_max_width = static_cast<int>(std::round(resolution.width()));
   double track_min_aspect_ratio =
diff --git a/content/renderer/media/stream/media_stream_constraints_util.h b/content/renderer/media/stream/media_stream_constraints_util.h
index 096ed08f..fd2267d 100644
--- a/content/renderer/media/stream/media_stream_constraints_util.h
+++ b/content/renderer/media/stream/media_stream_constraints_util.h
@@ -19,9 +19,11 @@
 
 namespace content {
 
+namespace media_constraints {
 class ResolutionSet;
 template <typename T>
 class NumericRangeSet;
+}  // namespace media_constraints
 
 // This class represents the output the SelectSettings algorithm for video
 // constraints (see https://w3c.github.io/mediacapture-main/#dfn-selectsettings)
@@ -350,8 +352,8 @@
 // |frame_rate_set| are empty.
 VideoTrackAdapterSettings CONTENT_EXPORT SelectVideoTrackAdapterSettings(
     const blink::WebMediaTrackConstraintSet& basic_constraint_set,
-    const ResolutionSet& resolution_set,
-    const NumericRangeSet<double>& frame_rate_set,
+    const media_constraints::ResolutionSet& resolution_set,
+    const media_constraints::NumericRangeSet<double>& frame_rate_set,
     const media::VideoCaptureFormat& source_format);
 
 // Generic distance function between two values for numeric constraints. Based
diff --git a/content/renderer/media/stream/media_stream_constraints_util_audio.cc b/content/renderer/media/stream/media_stream_constraints_util_audio.cc
index f7ed040..b9f2625 100644
--- a/content/renderer/media/stream/media_stream_constraints_util_audio.cc
+++ b/content/renderer/media/stream/media_stream_constraints_util_audio.cc
@@ -24,6 +24,9 @@
 
 namespace {
 
+template <class T>
+using DiscreteSet = media_constraints::DiscreteSet<T>;
+
 enum BoolConstraint {
   // Constraints not related to audio processing.
   HOTWORD_ENABLED,
@@ -310,29 +313,31 @@
   void ApplyConstraintSet(
       const blink::WebMediaTrackConstraintSet& constraint_set) {
     device_id_set_ = device_id_set_.Intersection(
-        StringSetFromConstraint(constraint_set.device_id));
+        media_constraints::StringSetFromConstraint(constraint_set.device_id));
     if (device_id_set_.IsEmpty()) {
       failed_constraint_name_ = constraint_set.device_id.GetName();
       return;
     }
 
     group_id_set_ = group_id_set_.Intersection(
-        StringSetFromConstraint(constraint_set.group_id));
+        media_constraints::StringSetFromConstraint(constraint_set.group_id));
     if (group_id_set_.IsEmpty()) {
       failed_constraint_name_ = constraint_set.group_id.GetName();
       return;
     }
 
     goog_array_geometry_set_ = goog_array_geometry_set_.Intersection(
-        StringSetFromConstraint(constraint_set.goog_array_geometry));
+        media_constraints::StringSetFromConstraint(
+            constraint_set.goog_array_geometry));
     if (goog_array_geometry_set_.IsEmpty()) {
       failed_constraint_name_ = constraint_set.goog_array_geometry.GetName();
       return;
     }
 
     for (size_t i = 0; i < NUM_BOOL_CONSTRAINTS; ++i) {
-      bool_sets_[i] = bool_sets_[i].Intersection(
-          BoolSetFromConstraint(constraint_set.*kBlinkBoolConstraintFields[i]));
+      bool_sets_[i] =
+          bool_sets_[i].Intersection(media_constraints::BoolSetFromConstraint(
+              constraint_set.*kBlinkBoolConstraintFields[i]));
       if (bool_sets_[i].IsEmpty()) {
         failed_constraint_name_ =
             (constraint_set.*kBlinkBoolConstraintFields[i]).GetName();
@@ -352,7 +357,8 @@
     }
 
     echo_cancellation_type_set_ = echo_cancellation_type_set_.Intersection(
-        StringSetFromConstraint(constraint_set.echo_cancellation_type));
+        media_constraints::StringSetFromConstraint(
+            constraint_set.echo_cancellation_type));
     if (echo_cancellation_type_set_.IsEmpty()) {
       failed_constraint_name_ = constraint_set.echo_cancellation_type.GetName();
       return;
diff --git a/content/renderer/media/stream/media_stream_constraints_util_sets.cc b/content/renderer/media/stream/media_stream_constraints_util_sets.cc
index 9ce80b6..385ff98 100644
--- a/content/renderer/media/stream/media_stream_constraints_util_sets.cc
+++ b/content/renderer/media/stream/media_stream_constraints_util_sets.cc
@@ -10,6 +10,7 @@
 #include "third_party/blink/public/platform/web_media_constraints.h"
 
 namespace content {
+namespace media_constraints {
 
 using Point = ResolutionSet::Point;
 
@@ -553,4 +554,5 @@
   return DiscreteSet<bool>({constraint.Exact()});
 }
 
+}  // namespace media_constraints
 }  // namespace content
diff --git a/content/renderer/media/stream/media_stream_constraints_util_sets.h b/content/renderer/media/stream/media_stream_constraints_util_sets.h
index 28b0760..2350913 100644
--- a/content/renderer/media/stream/media_stream_constraints_util_sets.h
+++ b/content/renderer/media/stream/media_stream_constraints_util_sets.h
@@ -22,6 +22,7 @@
 }
 
 namespace content {
+namespace media_constraints {
 
 // This class template represents a set of candidates suitable for a numeric
 // range-based constraint.
@@ -392,6 +393,7 @@
 ResolutionSet::Point CONTENT_EXPORT operator*(double d,
                                               const ResolutionSet::Point& p);
 
+}  // namespace media_constraints
 }  // namespace content
 
 #endif  // CONTENT_RENDERER_MEDIA_STREAM_MEDIA_STREAM_CONSTRAINTS_UTIL_SETS_H_
diff --git a/content/renderer/media/stream/media_stream_constraints_util_sets_unittest.cc b/content/renderer/media/stream/media_stream_constraints_util_sets_unittest.cc
index 105ae07..62f74c1 100644
--- a/content/renderer/media/stream/media_stream_constraints_util_sets_unittest.cc
+++ b/content/renderer/media/stream/media_stream_constraints_util_sets_unittest.cc
@@ -12,6 +12,7 @@
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace content {
+namespace media_constraints {
 
 using Point = ResolutionSet::Point;
 
@@ -1266,4 +1267,5 @@
   EXPECT_TRUE(intersection.IsEmpty());
 }
 
+}  // namespace media_constraints
 }  // namespace content
diff --git a/content/renderer/media/stream/media_stream_constraints_util_unittest.cc b/content/renderer/media/stream/media_stream_constraints_util_unittest.cc
index 18287087..9b0a9ffd 100644
--- a/content/renderer/media/stream/media_stream_constraints_util_unittest.cc
+++ b/content/renderer/media/stream/media_stream_constraints_util_unittest.cc
@@ -29,7 +29,8 @@
 
 class MediaStreamConstraintsUtilTest : public testing::Test {
  protected:
-  using DoubleRangeSet = NumericRangeSet<double>;
+  using DoubleRangeSet = media_constraints::NumericRangeSet<double>;
+  using ResolutionSet = media_constraints::ResolutionSet;
 };
 
 TEST_F(MediaStreamConstraintsUtilTest, BooleanConstraints) {
diff --git a/content/renderer/media/stream/media_stream_constraints_util_video_content.cc b/content/renderer/media/stream/media_stream_constraints_util_video_content.cc
index dfa2734c8..7fa6b1f 100644
--- a/content/renderer/media/stream/media_stream_constraints_util_video_content.cc
+++ b/content/renderer/media/stream/media_stream_constraints_util_video_content.cc
@@ -39,9 +39,11 @@
 
 namespace {
 
+using ResolutionSet = media_constraints::ResolutionSet;
 using Point = ResolutionSet::Point;
-using StringSet = DiscreteSet<std::string>;
-using BoolSet = DiscreteSet<bool>;
+using StringSet = media_constraints::DiscreteSet<std::string>;
+using BoolSet = media_constraints::DiscreteSet<bool>;
+using DoubleRangeSet = media_constraints::NumericRangeSet<double>;
 
 constexpr double kMinScreenCastAspectRatio =
     static_cast<double>(kMinScreenCastDimension) /
@@ -50,7 +52,6 @@
     static_cast<double>(kMaxScreenCastDimension) /
     static_cast<double>(kMinScreenCastDimension);
 
-using DoubleRangeSet = NumericRangeSet<double>;
 
 class VideoContentCaptureCandidates {
  public:
@@ -69,9 +70,10 @@
             DoubleRangeSet::FromConstraint(constraint_set.frame_rate,
                                            0.0,
                                            kMaxScreenCastFrameRate)),
-        device_id_set_(StringSetFromConstraint(constraint_set.device_id)),
-        noise_reduction_set_(
-            BoolSetFromConstraint(constraint_set.goog_noise_reduction)) {}
+        device_id_set_(media_constraints::StringSetFromConstraint(
+            constraint_set.device_id)),
+        noise_reduction_set_(media_constraints::BoolSetFromConstraint(
+            constraint_set.goog_noise_reduction)) {}
 
   VideoContentCaptureCandidates(VideoContentCaptureCandidates&& other) =
       default;
diff --git a/content/renderer/media/stream/media_stream_constraints_util_video_device.cc b/content/renderer/media/stream/media_stream_constraints_util_video_device.cc
index 7d0eae2..66c6cab 100644
--- a/content/renderer/media/stream/media_stream_constraints_util_video_device.cc
+++ b/content/renderer/media/stream/media_stream_constraints_util_video_device.cc
@@ -21,6 +21,9 @@
 
 namespace {
 
+using ResolutionSet = media_constraints::ResolutionSet;
+using DoubleRangeSet = media_constraints::NumericRangeSet<double>;
+
 // Number of default settings to be used as final tie-breaking criteria for
 // settings that are equally good at satisfying constraints:
 // device ID, power-line frequency, noise reduction, resolution and frame rate.
@@ -125,7 +128,7 @@
   const ResolutionSet& constrained_resolution() const {
     return constrained_resolution_;
   }
-  const NumericRangeSet<double>& constrained_frame_rate() const {
+  const DoubleRangeSet& constrained_frame_rate() const {
     return constrained_frame_rate_;
   }
 
@@ -153,9 +156,8 @@
     auto resolution_intersection = constrained_resolution_.Intersection(
         ResolutionSet::FromConstraintSet(constraint_set));
     auto frame_rate_intersection = constrained_frame_rate_.Intersection(
-        NumericRangeSet<double>::FromConstraint(
-            constraint_set.frame_rate, 0.0,
-            media::limits::kMaxFramesPerSecond));
+        DoubleRangeSet::FromConstraint(constraint_set.frame_rate, 0.0,
+                                       media::limits::kMaxFramesPerSecond));
     if (resolution_intersection.IsEmpty() ||
         frame_rate_intersection.IsEmpty() ||
         frame_rate_intersection.Min().value_or(0.0) > native_frame_rate_) {
@@ -173,7 +175,7 @@
   long native_width_;
   double native_frame_rate_;
   ResolutionSet constrained_resolution_;
-  NumericRangeSet<double> constrained_frame_rate_;
+  DoubleRangeSet constrained_frame_rate_;
 };
 
 VideoCaptureSettings ComputeVideoDeviceCaptureSettings(
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index b81daf2..28c643f 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -3333,13 +3333,20 @@
       ServiceWorkerNetworkProvider::FromWebServiceWorkerNetworkProvider(
           web_provider);
   mojom::ServiceWorkerWorkerClientRequest service_worker_client_request;
+  mojom::ServiceWorkerWorkerClientRegistryPtrInfo
+      service_worker_worker_client_registry_ptr_info;
   mojom::ServiceWorkerContainerHostPtrInfo container_host_ptr_info;
   ServiceWorkerProviderContext* provider_context = provider->context();
   // Some sandboxed iframes are not allowed to use service worker so don't have
   // a real service worker provider, so the provider context is null.
   if (provider_context) {
-    service_worker_client_request =
-        provider_context->CreateWorkerClientRequest();
+    provider_context->CloneWorkerClientRegistry(
+        mojo::MakeRequest(&service_worker_worker_client_registry_ptr_info));
+
+    mojom::ServiceWorkerWorkerClientPtr worker_client_ptr;
+    service_worker_client_request = mojo::MakeRequest(&worker_client_ptr);
+    provider_context->RegisterWorkerClient(std::move(worker_client_ptr));
+
     // TODO(horo): Use this host pointer also when S13nServiceWorker is not
     // enabled once we support navigator.serviceWorker on dedicated workers:
     // crbug.com/371690. Currently we use this only to call
@@ -3352,6 +3359,7 @@
   std::unique_ptr<WorkerFetchContextImpl> worker_fetch_context =
       std::make_unique<WorkerFetchContextImpl>(
           std::move(service_worker_client_request),
+          std::move(service_worker_worker_client_registry_ptr_info),
           std::move(container_host_ptr_info), GetLoaderFactoryBundle()->Clone(),
           GetLoaderFactoryBundle()->CloneWithoutDefaultFactory(),
           GetContentClient()->renderer()->CreateURLLoaderThrottleProvider(
diff --git a/content/renderer/service_worker/service_worker_provider_context.cc b/content/renderer/service_worker/service_worker_provider_context.cc
index efb3de6..610e4b4f 100644
--- a/content/renderer/service_worker/service_worker_provider_context.cc
+++ b/content/renderer/service_worker/service_worker_provider_context.cc
@@ -76,6 +76,10 @@
   //   the shared worker.
   std::vector<mojom::ServiceWorkerWorkerClientPtr> worker_clients;
 
+  // For adding new ServiceWorkerWorkerClients.
+  mojo::BindingSet<mojom::ServiceWorkerWorkerClientRegistry>
+      worker_client_registry_bindings;
+
   // S13nServiceWorker
   // Used in |subresource_loader_factory| to get the connection to the
   // controller service worker. Kept here in order to call
@@ -207,17 +211,22 @@
   state_for_client_->web_service_worker_provider = provider;
 }
 
-mojom::ServiceWorkerWorkerClientRequest
-ServiceWorkerProviderContext::CreateWorkerClientRequest() {
+void ServiceWorkerProviderContext::RegisterWorkerClient(
+    mojom::ServiceWorkerWorkerClientPtr client) {
   DCHECK(main_thread_task_runner_->RunsTasksInCurrentSequence());
   DCHECK(state_for_client_);
-  mojom::ServiceWorkerWorkerClientPtr client;
-  mojom::ServiceWorkerWorkerClientRequest request = mojo::MakeRequest(&client);
   client.set_connection_error_handler(base::BindOnce(
       &ServiceWorkerProviderContext::UnregisterWorkerFetchContext,
       base::Unretained(this), client.get()));
   state_for_client_->worker_clients.push_back(std::move(client));
-  return request;
+}
+
+void ServiceWorkerProviderContext::CloneWorkerClientRegistry(
+    mojom::ServiceWorkerWorkerClientRegistryRequest request) {
+  DCHECK(main_thread_task_runner_->RunsTasksInCurrentSequence());
+  DCHECK(state_for_client_);
+  state_for_client_->worker_client_registry_bindings.AddBinding(
+      this, std::move(request));
 }
 
 mojom::ServiceWorkerContainerHostPtrInfo
diff --git a/content/renderer/service_worker/service_worker_provider_context.h b/content/renderer/service_worker/service_worker_provider_context.h
index bc566e20..da223b8 100644
--- a/content/renderer/service_worker/service_worker_provider_context.h
+++ b/content/renderer/service_worker/service_worker_provider_context.h
@@ -52,7 +52,8 @@
 class CONTENT_EXPORT ServiceWorkerProviderContext
     : public base::RefCountedThreadSafe<ServiceWorkerProviderContext,
                                         ServiceWorkerProviderContextDeleter>,
-      public mojom::ServiceWorkerContainer {
+      public mojom::ServiceWorkerContainer,
+      public mojom::ServiceWorkerWorkerClientRegistry {
  public:
   // Constructor for service worker clients.
   //
@@ -137,15 +138,17 @@
   void SetWebServiceWorkerProvider(
       base::WeakPtr<WebServiceWorkerProviderImpl> provider);
 
-  // For service worker clients. Creates a ServiceWorkerWorkerClientRequest
-  // which can be used to bind with a WorkerFetchContextImpl in a (dedicated or
-  // shared) worker thread and receive SetControllerServiceWorker() method call
-  // from the main thread.
-  // A dedicated worker's WorkerFetchContext calls CreateWorkerClientRequest()
-  // on its parent Document's ServiceWorkerProviderContext. A shared worker's
-  // fetch context calls CreateWorkerClientRequest() on its own
-  // ServiceWorkerProviderContext.
-  mojom::ServiceWorkerWorkerClientRequest CreateWorkerClientRequest();
+  // mojom::ServiceWorkerWorkerClientRegistry:
+  // For service worker clients. ServiceWorkerProviderContext is also a
+  // mojom::ServiceWorkerWorkerHost (or Registry). If it's a provider for a
+  // document, then it tracks all the dedicated workers created from the
+  // document (including nested workers). If it's a provider for a shared
+  // worker, then it tracks only the shared worker itself.
+  void RegisterWorkerClient(
+      mojom::ServiceWorkerWorkerClientPtr client) override;
+  // For cloning the worker host pointer.
+  void CloneWorkerClientRegistry(
+      mojom::ServiceWorkerWorkerClientRegistryRequest request) override;
 
   // S13nServiceWorker:
   // For service worker clients. Creates a ServiceWorkerContainerHostPtrInfo
diff --git a/content/renderer/service_worker/worker_fetch_context_impl.cc b/content/renderer/service_worker/worker_fetch_context_impl.cc
index bc1ebd9..564b94165 100644
--- a/content/renderer/service_worker/worker_fetch_context_impl.cc
+++ b/content/renderer/service_worker/worker_fetch_context_impl.cc
@@ -138,6 +138,8 @@
 
 WorkerFetchContextImpl::WorkerFetchContextImpl(
     mojom::ServiceWorkerWorkerClientRequest service_worker_client_request,
+    mojom::ServiceWorkerWorkerClientRegistryPtrInfo
+        service_worker_worker_client_registry_info,
     mojom::ServiceWorkerContainerHostPtrInfo service_worker_container_host_info,
     std::unique_ptr<network::SharedURLLoaderFactoryInfo> loader_factory_info,
     std::unique_ptr<network::SharedURLLoaderFactoryInfo> fallback_factory_info,
@@ -149,6 +151,8 @@
     std::unique_ptr<service_manager::Connector> service_manager_connection)
     : binding_(this),
       service_worker_client_request_(std::move(service_worker_client_request)),
+      service_worker_worker_client_registry_info_(
+          std::move(service_worker_worker_client_registry_info)),
       service_worker_container_host_info_(
           std::move(service_worker_container_host_info)),
       loader_factory_info_(std::move(loader_factory_info)),
@@ -176,6 +180,7 @@
   // behavior. See https://crbug.com/731604
   auto new_context = std::make_unique<WorkerFetchContextImpl>(
       mojom::ServiceWorkerWorkerClientRequest(),
+      mojom::ServiceWorkerWorkerClientRegistryPtrInfo(),
       mojom::ServiceWorkerContainerHostPtrInfo(), loader_factory_->Clone(),
       fallback_factory_->Clone(),
       throttle_provider_ ? throttle_provider_->Clone() : nullptr,
@@ -203,6 +208,9 @@
   if (service_worker_client_request_.is_pending())
     binding_.Bind(std::move(service_worker_client_request_));
 
+  service_worker_worker_client_registry_.Bind(
+      std::move(service_worker_worker_client_registry_info_));
+
   if (ServiceWorkerUtils::IsServicificationEnabled()) {
     service_worker_container_host_.Bind(
         std::move(service_worker_container_host_info_));
diff --git a/content/renderer/service_worker/worker_fetch_context_impl.h b/content/renderer/service_worker/worker_fetch_context_impl.h
index 8857872..46ab4a4 100644
--- a/content/renderer/service_worker/worker_fetch_context_impl.h
+++ b/content/renderer/service_worker/worker_fetch_context_impl.h
@@ -38,7 +38,11 @@
     : public blink::WebWorkerFetchContext,
       public mojom::ServiceWorkerWorkerClient {
  public:
-  // |loader_factory_info| is used for regular loading by the worker.
+  // |service_worker_client_request| is bound to |this| to receive
+  // OnControllerChanged() notifications.
+  // |service_worker_worker_client_registry_info| is a host pointer to register
+  // a new ServiceWorkerWorkerClient, which is needed when creating a nested
+  // worker. |loader_factory_info| is used for regular loading by the worker.
   //
   // S13nServiceWorker:
   // If the worker is controlled by a service worker, this class makes another
@@ -54,6 +58,8 @@
   // chrome-extension://).
   WorkerFetchContextImpl(
       mojom::ServiceWorkerWorkerClientRequest service_worker_client_request,
+      mojom::ServiceWorkerWorkerClientRegistryPtrInfo
+          service_worker_worker_client_registry_info,
       mojom::ServiceWorkerContainerHostPtrInfo
           service_worker_container_host_info,
       std::unique_ptr<network::SharedURLLoaderFactoryInfo> loader_factory_info,
@@ -125,9 +131,15 @@
   void ResetServiceWorkerURLLoaderFactory();
 
   mojo::Binding<mojom::ServiceWorkerWorkerClient> binding_;
+  mojom::ServiceWorkerWorkerClientRegistryPtr
+      service_worker_worker_client_registry_;
 
   // Bound to |this| on the worker thread.
   mojom::ServiceWorkerWorkerClientRequest service_worker_client_request_;
+  // Consumed on the worker thread to create
+  // |service_worker_worker_client_registry_|.
+  mojom::ServiceWorkerWorkerClientRegistryPtrInfo
+      service_worker_worker_client_registry_info_;
   // Consumed on the worker thread to create |service_worker_container_host_|.
   mojom::ServiceWorkerContainerHostPtrInfo service_worker_container_host_info_;
   // Consumed on the worker thread to create |loader_factory_|.
diff --git a/content/renderer/shared_worker/embedded_shared_worker_stub.cc b/content/renderer/shared_worker/embedded_shared_worker_stub.cc
index 88aef23..62d56e6 100644
--- a/content/renderer/shared_worker/embedded_shared_worker_stub.cc
+++ b/content/renderer/shared_worker/embedded_shared_worker_stub.cc
@@ -355,8 +355,16 @@
           web_network_provider)
           ->provider()
           ->context();
-  mojom::ServiceWorkerWorkerClientRequest request =
-      context->CreateWorkerClientRequest();
+
+  mojom::ServiceWorkerWorkerClientRegistryPtrInfo
+      worker_client_registry_ptr_info;
+  context->CloneWorkerClientRegistry(
+      mojo::MakeRequest(&worker_client_registry_ptr_info));
+
+  mojom::ServiceWorkerWorkerClientPtr worker_client_ptr;
+  mojom::ServiceWorkerWorkerClientRequest worker_client_request =
+      mojo::MakeRequest(&worker_client_ptr);
+  context->RegisterWorkerClient(std::move(worker_client_ptr));
 
   mojom::ServiceWorkerContainerHostPtrInfo container_host_ptr_info;
   if (ServiceWorkerUtils::IsServicificationEnabled())
@@ -375,8 +383,10 @@
   std::unique_ptr<network::SharedURLLoaderFactoryInfo> fallback_factory =
       loader_factories_->Clone();
   auto worker_fetch_context = std::make_unique<WorkerFetchContextImpl>(
-      std::move(request), std::move(container_host_ptr_info),
-      loader_factories_->Clone(), std::move(fallback_factory),
+      std::move(worker_client_request),
+      std::move(worker_client_registry_ptr_info),
+      std::move(container_host_ptr_info), loader_factories_->Clone(),
+      std::move(fallback_factory),
       GetContentClient()->renderer()->CreateURLLoaderThrottleProvider(
           URLLoaderThrottleProviderType::kWorker),
       GetContentClient()
diff --git a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
index 0c1001c9..bc2b3508 100644
--- a/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
+++ b/content/test/gpu/gpu_tests/webgl2_conformance_expectations.py
@@ -933,10 +933,6 @@
     self.Skip('conformance/glsl/bugs/temp-expressions-should-not-crash.html',
         ['linux', 'intel'], bug=540543)  # GPU timeout
 
-    self.Fail('deqp/functional/gles3/fbomultisample.8_samples.html',
-        ['linux', 'intel'], bug=635528)
-
-
     self.Fail('conformance2/textures/misc/tex-subimage3d-pixel-buffer-bug.html',
        ['linux', 'intel'], bug=662644) # WebGL 2.0.1
 
diff --git a/device/base/features.cc b/device/base/features.cc
index 6035bdb6..47d03ae 100644
--- a/device/base/features.cc
+++ b/device/base/features.cc
@@ -22,6 +22,6 @@
 #endif  // defined(OS_LINUX) || defined(OS_CHROMEOS)
 
 const base::Feature kNewCtap2Device{"WebAuthenticationCtap2",
-                                    base::FEATURE_DISABLED_BY_DEFAULT};
+                                    base::FEATURE_ENABLED_BY_DEFAULT};
 
 }  // namespace device
diff --git a/device/bluetooth/dbus/bluetooth_gatt_attribute_helpers.cc b/device/bluetooth/dbus/bluetooth_gatt_attribute_helpers.cc
index 8cfcb37..1aa4070 100644
--- a/device/bluetooth/dbus/bluetooth_gatt_attribute_helpers.cc
+++ b/device/bluetooth/dbus/bluetooth_gatt_attribute_helpers.cc
@@ -12,32 +12,28 @@
 
 namespace bluez {
 
-namespace {
-
-constexpr char kDeviceField[] = "device";
-
-}  // namespace
-
-dbus::ObjectPath ReadDevicePath(dbus::MessageReader* reader) {
+bool ReadOptions(dbus::MessageReader* reader,
+                 std::map<std::string, dbus::MessageReader>* options) {
   dbus::MessageReader array_reader(nullptr);
-  if (!reader->PopArray(&array_reader))
-    return dbus::ObjectPath();
+  if (!reader->PopArray(&array_reader) || options == nullptr)
+    return false;
 
-  // Go through all the keys in the dictionary to find the device key.
+  dbus::MessageReader dict_entry_reader(nullptr);
+  std::string key;
   while (array_reader.HasMoreData()) {
-    dbus::MessageReader dict_entry_reader(nullptr);
-    std::string key;
     if (!array_reader.PopDictEntry(&dict_entry_reader) ||
         !dict_entry_reader.PopString(&key)) {
-      return dbus::ObjectPath();
-    } else if (key == kDeviceField) {
-      dbus::ObjectPath device_path;
-      dict_entry_reader.PopVariantOfObjectPath(&device_path);
-      return device_path;
+      options->clear();
+      return false;
+    }
+
+    options->emplace(key, nullptr);
+    if (!dict_entry_reader.PopVariant(&options->at(key))) {
+      options->clear();
+      return false;
     }
   }
-
-  return dbus::ObjectPath();
+  return true;
 }
 
 }  // namespace bluez
diff --git a/device/bluetooth/dbus/bluetooth_gatt_attribute_helpers.h b/device/bluetooth/dbus/bluetooth_gatt_attribute_helpers.h
index 9b16670f..b1562657 100644
--- a/device/bluetooth/dbus/bluetooth_gatt_attribute_helpers.h
+++ b/device/bluetooth/dbus/bluetooth_gatt_attribute_helpers.h
@@ -5,6 +5,8 @@
 #ifndef DEVICE_BLUETOOTH_DBUS_BLUETOOTH_GATT_ATTRIBUTES_HELPER_H_
 #define DEVICE_BLUETOOTH_DBUS_BLUETOOTH_GATT_ATTRIBUTES_HELPER_H_
 
+#include <map>
+
 #include "dbus/object_path.h"
 
 namespace dbus {
@@ -14,7 +16,8 @@
 namespace bluez {
 
 // Helper methods used from various GATT attribute providers and clients.
-dbus::ObjectPath ReadDevicePath(dbus::MessageReader* reader);
+bool ReadOptions(dbus::MessageReader* reader,
+                 std::map<std::string, dbus::MessageReader>* options);
 
 }  // namespace bluez
 
diff --git a/device/bluetooth/dbus/bluetooth_gatt_characteristic_service_provider_impl.cc b/device/bluetooth/dbus/bluetooth_gatt_characteristic_service_provider_impl.cc
index 51e3820..e70b928 100644
--- a/device/bluetooth/dbus/bluetooth_gatt_characteristic_service_provider_impl.cc
+++ b/device/bluetooth/dbus/bluetooth_gatt_characteristic_service_provider_impl.cc
@@ -267,7 +267,13 @@
   DCHECK(OnOriginThread());
 
   dbus::MessageReader reader(method_call);
-  dbus::ObjectPath device_path = ReadDevicePath(&reader);
+  std::map<std::string, dbus::MessageReader> options;
+  dbus::ObjectPath device_path;
+  ReadOptions(&reader, &options);
+  auto it = options.find(bluetooth_gatt_characteristic::kOptionDevice);
+  if (it != options.end())
+    it->second.PopObjectPath(&device_path);
+
   if (device_path.value().empty()) {
     LOG(WARNING) << "ReadValue called with incorrect parameters: "
                  << method_call->ToString();
@@ -304,7 +310,13 @@
   if (bytes)
     value.assign(bytes, bytes + length);
 
-  dbus::ObjectPath device_path = ReadDevicePath(&reader);
+  std::map<std::string, dbus::MessageReader> options;
+  dbus::ObjectPath device_path;
+  ReadOptions(&reader, &options);
+  auto it = options.find(bluetooth_gatt_characteristic::kOptionDevice);
+  if (it != options.end())
+    it->second.PopObjectPath(&device_path);
+
   if (device_path.value().empty()) {
     LOG(WARNING) << "WriteValue called with incorrect parameters: "
                  << method_call->ToString();
diff --git a/device/bluetooth/dbus/bluetooth_gatt_descriptor_service_provider_impl.cc b/device/bluetooth/dbus/bluetooth_gatt_descriptor_service_provider_impl.cc
index 0eb37f8..26b4aa7 100644
--- a/device/bluetooth/dbus/bluetooth_gatt_descriptor_service_provider_impl.cc
+++ b/device/bluetooth/dbus/bluetooth_gatt_descriptor_service_provider_impl.cc
@@ -252,7 +252,13 @@
   DCHECK(OnOriginThread());
 
   dbus::MessageReader reader(method_call);
-  dbus::ObjectPath device_path = ReadDevicePath(&reader);
+  std::map<std::string, dbus::MessageReader> options;
+  dbus::ObjectPath device_path;
+  ReadOptions(&reader, &options);
+  auto it = options.find(bluetooth_gatt_descriptor::kOptionDevice);
+  if (it != options.end())
+    it->second.PopObjectPath(&device_path);
+
   if (device_path.value().empty()) {
     LOG(WARNING) << "ReadValue called with incorrect parameters: "
                  << method_call->ToString();
@@ -289,7 +295,13 @@
   if (bytes)
     value.assign(bytes, bytes + length);
 
-  dbus::ObjectPath device_path = ReadDevicePath(&reader);
+  std::map<std::string, dbus::MessageReader> options;
+  dbus::ObjectPath device_path;
+  ReadOptions(&reader, &options);
+  auto it = options.find(bluetooth_gatt_descriptor::kOptionDevice);
+  if (it != options.end())
+    it->second.PopObjectPath(&device_path);
+
   if (device_path.value().empty()) {
     LOG(WARNING) << "WriteValue called with incorrect parameters: "
                  << method_call->ToString();
diff --git a/device/fido/get_assertion_handler_unittest.cc b/device/fido/get_assertion_handler_unittest.cc
index 08f6956..c97955e 100644
--- a/device/fido/get_assertion_handler_unittest.cc
+++ b/device/fido/get_assertion_handler_unittest.cc
@@ -53,8 +53,8 @@
         std::move(request_param), get_assertion_cb_.callback());
   }
 
-  void InitFeatureListWithCtapFlag() {
-    scoped_feature_list_.InitAndEnableFeature(kNewCtap2Device);
+  void InitFeatureListAndDisableCtapFlag() {
+    scoped_feature_list_.InitAndDisableFeature(kNewCtap2Device);
   }
 
   test::FakeFidoDiscovery* discovery() const { return discovery_; }
@@ -72,7 +72,6 @@
 };
 
 TEST_F(FidoGetAssertionHandlerTest, TestGetAssertionRequestOnSingleDevice) {
-  InitFeatureListWithCtapFlag();
   auto request_handler = CreateGetAssertionHandler();
   discovery()->WaitForCallToStartAndSimulateSuccess();
   auto device = std::make_unique<MockFidoDevice>();
@@ -95,7 +94,6 @@
 
 // Test a scenario where the connected authenticator is a U2F device.
 TEST_F(FidoGetAssertionHandlerTest, TestU2fSign) {
-  InitFeatureListWithCtapFlag();
   auto request_handler = CreateGetAssertionHandler();
   discovery()->WaitForCallToStartAndSimulateSuccess();
 
@@ -120,6 +118,7 @@
 // Test a scenario where the connected authenticator is a U2F device and
 // "WebAuthenticationCtap2" flag is not enabled.
 TEST_F(FidoGetAssertionHandlerTest, TestU2fSignWithoutCtapFlag) {
+  InitFeatureListAndDisableCtapFlag();
   auto request_handler = CreateGetAssertionHandler();
   discovery()->WaitForCallToStartAndSimulateSuccess();
 
diff --git a/device/fido/get_assertion_task_unittest.cc b/device/fido/get_assertion_task_unittest.cc
index 72a9aad..fc69dd5 100644
--- a/device/fido/get_assertion_task_unittest.cc
+++ b/device/fido/get_assertion_task_unittest.cc
@@ -40,7 +40,6 @@
  public:
   FidoGetAssertionTaskTest() {
     scoped_feature_list_.emplace();
-    scoped_feature_list_->InitAndEnableFeature(kNewCtap2Device);
   }
 
   TestGetAssertionTaskCallbackReceiver& get_assertion_callback_receiver() {
diff --git a/device/fido/make_credential_handler_unittest.cc b/device/fido/make_credential_handler_unittest.cc
index ea9ec0a..f884b1be 100644
--- a/device/fido/make_credential_handler_unittest.cc
+++ b/device/fido/make_credential_handler_unittest.cc
@@ -61,8 +61,8 @@
         cb_.callback());
   }
 
-  void InitFeatureListWithCtapFlag() {
-    scoped_feature_list_.InitAndEnableFeature(kNewCtap2Device);
+  void InitFeatureListAndDisableCtapFlag() {
+    scoped_feature_list_.InitAndDisableFeature(kNewCtap2Device);
   }
 
   test::FakeFidoDiscovery* discovery() const { return discovery_; }
@@ -78,7 +78,6 @@
 };
 
 TEST_F(FidoMakeCredentialHandlerTest, TestCtap2MakeCredentialWithFlagEnabled) {
-  InitFeatureListWithCtapFlag();
   auto request_handler = CreateMakeCredentialHandler();
   discovery()->WaitForCallToStartAndSimulateSuccess();
 
@@ -99,7 +98,6 @@
 
 // Test a scenario where the connected authenticator is a U2F device.
 TEST_F(FidoMakeCredentialHandlerTest, TestU2fRegisterWithFlagEnabled) {
-  InitFeatureListWithCtapFlag();
   auto request_handler = CreateMakeCredentialHandler();
   discovery()->WaitForCallToStartAndSimulateSuccess();
 
@@ -120,6 +118,7 @@
 // Test a scenario where the connected authenticator is a U2F device using a
 // logic that defaults to handling U2F devices.
 TEST_F(FidoMakeCredentialHandlerTest, TestU2fRegisterWithoutFlagEnabled) {
+  InitFeatureListAndDisableCtapFlag();
   auto request_handler = CreateMakeCredentialHandler();
   discovery()->WaitForCallToStartAndSimulateSuccess();
 
diff --git a/device/fido/make_credential_task_unittest.cc b/device/fido/make_credential_task_unittest.cc
index aa328aa6..fa504c5 100644
--- a/device/fido/make_credential_task_unittest.cc
+++ b/device/fido/make_credential_task_unittest.cc
@@ -40,7 +40,6 @@
  public:
   FidoMakeCredentialTaskTest() {
     scoped_feature_list_.emplace();
-    scoped_feature_list_->InitAndEnableFeature(kNewCtap2Device);
   }
 
   std::unique_ptr<MakeCredentialTask> CreateMakeCredentialTask(
diff --git a/device/gamepad/gamepad_device_linux.cc b/device/gamepad/gamepad_device_linux.cc
index 88514ec..8392313 100644
--- a/device/gamepad/gamepad_device_linux.cc
+++ b/device/gamepad/gamepad_device_linux.cc
@@ -12,6 +12,7 @@
 #include <sys/ioctl.h>
 
 #include "base/posix/eintr_wrapper.h"
+#include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
 #include "device/gamepad/gamepad_data_fetcher.h"
@@ -28,6 +29,19 @@
 const int kInvalidEffectId = -1;
 const uint16_t kRumbleMagnitudeMax = 0xffff;
 
+const size_t kSpecialKeys[] = {
+    // Xbox One S pre-FW update reports Xbox button as SystemMainMenu over BT.
+    KEY_MENU,
+    // Power is used for the Guide button on the Nvidia Shield 2015 gamepad.
+    KEY_POWER,
+    // Search is used for the Guide button on the Nvidia Shield 2015 gamepad.
+    KEY_SEARCH,
+    // Start, Back, and Guide buttons are often reported as Consumer Home or
+    // Back.
+    KEY_HOMEPAGE, KEY_BACK,
+};
+const size_t kSpecialKeysLen = base::size(kSpecialKeys);
+
 #define LONG_BITS (CHAR_BIT * sizeof(long))
 #define BITS_TO_LONGS(x) (((x) + LONG_BITS - 1) / LONG_BITS)
 
@@ -62,6 +76,37 @@
   return test_bit(FF_RUMBLE, ffbit);
 }
 
+// Check an evdev device for key codes which sometimes appear on gamepads but
+// aren't reported by joydev. If a special key is found, the corresponding entry
+// of the |has_special_key| vector is set to true. Returns the number of
+// special keys found.
+size_t CheckSpecialKeys(int fd, std::vector<bool>* has_special_key) {
+  DCHECK(has_special_key);
+  unsigned long evbit[BITS_TO_LONGS(EV_MAX)];
+  unsigned long keybit[BITS_TO_LONGS(KEY_MAX)];
+  size_t found_special_keys = 0;
+
+  has_special_key->clear();
+  if (HANDLE_EINTR(ioctl(fd, EVIOCGBIT(0, EV_MAX), evbit)) < 0 ||
+      HANDLE_EINTR(ioctl(fd, EVIOCGBIT(EV_KEY, KEY_MAX), keybit)) < 0) {
+    return 0;
+  }
+
+  if (!test_bit(EV_KEY, evbit)) {
+    return 0;
+  }
+
+  has_special_key->resize(kSpecialKeysLen, false);
+  for (size_t special_index = 0; special_index < kSpecialKeysLen;
+       ++special_index) {
+    (*has_special_key)[special_index] =
+        test_bit(kSpecialKeys[special_index], keybit);
+    ++found_special_keys;
+  }
+
+  return found_special_keys;
+}
+
 bool GetHidrawDevinfo(int fd,
                       GamepadBusType* bus_type,
                       uint16_t* vendor_id,
@@ -123,11 +168,7 @@
 
 GamepadDeviceLinux::GamepadDeviceLinux(const std::string& syspath_prefix)
     : syspath_prefix_(syspath_prefix),
-      joydev_fd_(-1),
-      joydev_index_(-1),
-      evdev_fd_(-1),
-      effect_id_(kInvalidEffectId),
-      hidraw_fd_(-1) {}
+      button_indices_used_(Gamepad::kButtonsLengthCap, false) {}
 
 GamepadDeviceLinux::~GamepadDeviceLinux() = default;
 
@@ -153,7 +194,7 @@
   return supports_force_feedback_ && evdev_fd_ >= 0;
 }
 
-void GamepadDeviceLinux::ReadPadState(Gamepad* pad) const {
+void GamepadDeviceLinux::ReadPadState(Gamepad* pad) {
   if (switch_pro_ && bus_type_ == GAMEPAD_BUS_USB) {
     // When connected over USB, the Switch Pro controller does not correctly
     // report its state over USB HID. Instead, fetch the state using the
@@ -164,8 +205,34 @@
 
   DCHECK_GE(joydev_fd_, 0);
 
-  js_event event;
+  // Read button and axis events from the joydev device.
+  bool pad_updated = ReadJoydevState(pad);
+
+  // Evdev special buttons must be initialized after we have read from joydev
+  // at least once to ensure we do not assign a button index already in use by
+  // joydev.
+  if (!evdev_special_keys_initialized_)
+    InitializeEvdevSpecialKeys();
+
+  // Read button events from the evdev device.
+  if (!special_button_map_.empty()) {
+    if (ReadEvdevSpecialKeys(pad))
+      pad_updated = true;
+  }
+
+  if (pad_updated)
+    pad->timestamp = GamepadDataFetcher::CurrentTimeInMicroseconds();
+}
+
+bool GamepadDeviceLinux::ReadJoydevState(Gamepad* pad) {
+  DCHECK(pad);
+
+  if (joydev_fd_ < 0)
+    return false;
+
+  // Read button and axis events from the joydev device.
   bool pad_updated = false;
+  js_event event;
   while (HANDLE_EINTR(read(joydev_fd_, &event, sizeof(struct js_event))) > 0) {
     size_t item = event.number;
     if (event.type & JS_EVENT_AXIS) {
@@ -184,13 +251,90 @@
       pad->buttons[item].pressed = event.value;
       pad->buttons[item].value = event.value ? 1.0 : 0.0;
 
+      // When a joydev device is opened, synthetic events are generated for
+      // each joystick button and axis with the JS_EVENT_INIT flag set on the
+      // event type. Use this signal to mark these button indices as used.
+      if (event.type & JS_EVENT_INIT)
+        button_indices_used_[item] = true;
+
       if (item >= pad->buttons_length)
         pad->buttons_length = item + 1;
       pad_updated = true;
     }
   }
-  if (pad_updated)
-    pad->timestamp = GamepadDataFetcher::CurrentTimeInMicroseconds();
+  return pad_updated;
+}
+
+void GamepadDeviceLinux::InitializeEvdevSpecialKeys() {
+  if (evdev_fd_ < 0)
+    return;
+
+  // Do some one-time initialization to decide indices for the evdev special
+  // buttons.
+  evdev_special_keys_initialized_ = true;
+  std::vector<bool> special_key_present;
+  size_t unmapped_button_count =
+      CheckSpecialKeys(evdev_fd_, &special_key_present);
+
+  special_button_map_.clear();
+  if (unmapped_button_count > 0) {
+    // Insert special buttons at unused button indices.
+    special_button_map_.resize(kSpecialKeysLen, -1);
+    size_t button_index = 0;
+    for (size_t special_index = 0; special_index < kSpecialKeysLen;
+         ++special_index) {
+      if (!special_key_present[special_index])
+        continue;
+
+      // Advance to the next unused button index.
+      while (button_indices_used_[button_index] &&
+             button_index < Gamepad::kButtonsLengthCap) {
+        ++button_index;
+      }
+      if (button_index >= Gamepad::kButtonsLengthCap)
+        break;
+
+      special_button_map_[special_index] = button_index;
+      button_indices_used_[button_index] = true;
+      ++button_index;
+
+      if (--unmapped_button_count == 0)
+        break;
+    }
+  }
+}
+
+bool GamepadDeviceLinux::ReadEvdevSpecialKeys(Gamepad* pad) {
+  DCHECK(pad);
+
+  if (evdev_fd_ < 0)
+    return false;
+
+  // Read special button events through evdev.
+  bool pad_updated = false;
+  input_event ev;
+  ssize_t bytes_read;
+  while ((bytes_read =
+              HANDLE_EINTR(read(evdev_fd_, &ev, sizeof(input_event)))) > 0) {
+    if (size_t{bytes_read} < sizeof(input_event))
+      break;
+    if (ev.type != EV_KEY)
+      continue;
+
+    for (size_t special_index = 0; special_index < kSpecialKeysLen;
+         ++special_index) {
+      int button_index = special_button_map_[special_index];
+      if (button_index < 0)
+        continue;
+      if (ev.code == kSpecialKeys[special_index]) {
+        pad->buttons[button_index].pressed = ev.value;
+        pad->buttons[button_index].value = ev.value ? 1.0 : 0.0;
+        pad_updated = true;
+      }
+    }
+  }
+
+  return pad_updated;
 }
 
 GamepadStandardMappingFunction GamepadDeviceLinux::GetMappingFunction() const {
@@ -276,6 +420,11 @@
   product_id_.clear();
   version_number_.clear();
   name_.clear();
+
+  // Button indices must be recomputed once the joydev node is closed.
+  button_indices_used_.clear();
+  special_button_map_.clear();
+  evdev_special_keys_initialized_ = false;
 }
 
 bool GamepadDeviceLinux::OpenEvdevNode(const UdevGamepadLinux& pad_info) {
@@ -303,6 +452,16 @@
     evdev_fd_ = -1;
   }
   supports_force_feedback_ = false;
+
+  // Clear any entries in |button_indices_used_| that were taken by evdev.
+  if (!special_button_map_.empty()) {
+    for (int button_index : special_button_map_) {
+      if (button_index >= 0)
+        button_indices_used_[button_index] = false;
+    }
+  }
+  special_button_map_.clear();
+  evdev_special_keys_initialized_ = false;
 }
 
 bool GamepadDeviceLinux::OpenHidrawNode(const UdevGamepadLinux& pad_info) {
diff --git a/device/gamepad/gamepad_device_linux.h b/device/gamepad/gamepad_device_linux.h
index e5a0979..f34df9ef 100644
--- a/device/gamepad/gamepad_device_linux.h
+++ b/device/gamepad/gamepad_device_linux.h
@@ -5,6 +5,10 @@
 #ifndef DEVICE_GAMEPAD_GAMEPAD_DEVICE_LINUX_
 #define DEVICE_GAMEPAD_GAMEPAD_DEVICE_LINUX_
 
+#include <memory>
+#include <string>
+#include <vector>
+
 #include "device/gamepad/abstract_haptic_gamepad.h"
 #include "device/gamepad/dualshock4_controller_linux.h"
 #include "device/gamepad/gamepad_standard_mappings.h"
@@ -48,7 +52,19 @@
   bool SupportsVibration() const;
 
   // Reads the current gamepad state into |pad|.
-  void ReadPadState(Gamepad* pad) const;
+  void ReadPadState(Gamepad* pad);
+
+  // Reads the state of gamepad buttons and axes using joydev. Returns true if
+  // |pad| was updated.
+  bool ReadJoydevState(Gamepad* pad);
+
+  // Discovers and assigns button indices for key codes that are outside the
+  // normal gamepad button range.
+  void InitializeEvdevSpecialKeys();
+
+  // Reads the state of keys outside the normal button range using evdev.
+  // Returns true if |pad| was updated.
+  bool ReadEvdevSpecialKeys(Gamepad* pad);
 
   // Returns true if |pad_info| describes this device.
   bool IsSameDevice(const UdevGamepadLinux& pad_info);
@@ -90,13 +106,17 @@
 
   // The file descriptor for the device's joydev node, or -1 if no joydev node
   // is associated with this device.
-  int joydev_fd_;
+  int joydev_fd_ = -1;
 
   // The index of the device's joydev node, or -1 if unknown.
   // The joydev index is the integer at the end of the joydev node path and is
   // used to assign the gamepad to a slot. For example, a device with path
   // /dev/input/js2 has index 2 and will be assigned to the 3rd gamepad slot.
-  int joydev_index_;
+  int joydev_index_ = -1;
+
+  // Maps from indices in the Gamepad buttons array to a boolean value
+  // indicating whether the button index is already mapped.
+  std::vector<bool> button_indices_used_;
 
   // The vendor ID of the device.
   std::string vendor_id_;
@@ -112,17 +132,25 @@
 
   // The file descriptor for the device's evdev node, or -1 if no evdev node is
   // associated with this device.
-  int evdev_fd_;
+  int evdev_fd_ = -1;
 
   // The ID of the haptic effect stored on the device, or -1 if none is stored.
-  int effect_id_;
+  int effect_id_ = -1;
 
   // True if the device supports rumble effects through the evdev device node.
-  bool supports_force_feedback_;
+  bool supports_force_feedback_ = false;
+
+  // Set to true once the evdev button capabilities have been checked.
+  bool evdev_special_keys_initialized_ = false;
+
+  // Mapping from "special" index (an index within the kSpecialKeys table) to
+  // button index (an index within the Gamepad buttons array), or -1 if the
+  // button is not mapped. Empty if no special buttons are mapped.
+  std::vector<int> special_button_map_;
 
   // The file descriptor for the device's hidraw node, or -1 if no hidraw node
   // is associated with this device.
-  int hidraw_fd_;
+  int hidraw_fd_ = -1;
 
   // The type of the bus through which the device is connected, or
   // GAMEPAD_BUS_UNKNOWN if the bus type could not be determined.
diff --git a/device/gamepad/gamepad_device_mac.h b/device/gamepad/gamepad_device_mac.h
index 4ec2ea42..7c8bc08 100644
--- a/device/gamepad/gamepad_device_mac.h
+++ b/device/gamepad/gamepad_device_mac.h
@@ -58,6 +58,12 @@
   // Stop vibration and release held resources.
   void DoShutdown() override;
 
+  // Initialize button capabilities for |gamepad|.
+  bool AddButtons(Gamepad* gamepad);
+
+  // Initialize axis capabilities for |gamepad|.
+  bool AddAxes(Gamepad* gamepad);
+
   // Return true if this element has a parent collection with a usage page that
   // suggests it could be a gamepad.
   static bool CheckCollection(IOHIDElementRef element);
diff --git a/device/gamepad/gamepad_device_mac.mm b/device/gamepad/gamepad_device_mac.mm
index f94964a..e22246f 100644
--- a/device/gamepad/gamepad_device_mac.mm
+++ b/device/gamepad/gamepad_device_mac.mm
@@ -6,6 +6,7 @@
 
 #include "base/mac/foundation_util.h"
 #include "base/mac/scoped_cftyperef.h"
+#include "base/stl_util.h"
 #include "device/gamepad/gamepad_data_fetcher.h"
 
 #import <Foundation/Foundation.h>
@@ -13,16 +14,40 @@
 namespace {
 
 // http://www.usb.org/developers/hidpage
-const uint32_t kGenericDesktopUsagePage = 0x01;
-const uint32_t kGameControlsUsagePage = 0x05;
-const uint32_t kButtonUsagePage = 0x09;
-const uint32_t kJoystickUsageNumber = 0x04;
-const uint32_t kGameUsageNumber = 0x05;
-const uint32_t kMultiAxisUsageNumber = 0x08;
-const uint32_t kAxisMinimumUsageNumber = 0x30;
+const uint16_t kGenericDesktopUsagePage = 0x01;
+const uint16_t kGameControlsUsagePage = 0x05;
+const uint16_t kButtonUsagePage = 0x09;
+const uint16_t kConsumerUsagePage = 0x0c;
+
+const uint16_t kJoystickUsageNumber = 0x04;
+const uint16_t kGameUsageNumber = 0x05;
+const uint16_t kMultiAxisUsageNumber = 0x08;
+const uint16_t kAxisMinimumUsageNumber = 0x30;
+const uint16_t kSystemMainMenuUsageNumber = 0x85;
+const uint16_t kPowerUsageNumber = 0x30;
+const uint16_t kSearchUsageNumber = 0x0221;
+const uint16_t kHomeUsageNumber = 0x0223;
+const uint16_t kBackUsageNumber = 0x0224;
 
 const int kRumbleMagnitudeMax = 10000;
 
+struct SpecialUsages {
+  const uint16_t usage_page;
+  const uint16_t usage;
+} kSpecialUsages[] = {
+    // Xbox One S pre-FW update reports Xbox button as SystemMainMenu over BT.
+    {kGenericDesktopUsagePage, kSystemMainMenuUsageNumber},
+    // Power is used for the Guide button on the Nvidia Shield 2015 gamepad.
+    {kConsumerUsagePage, kPowerUsageNumber},
+    // Search is used for the Guide button on the Nvidia Shield 2017 gamepad.
+    {kConsumerUsagePage, kSearchUsageNumber},
+    // Start, Back, and Guide buttons are often reported as Consumer Home or
+    // Back.
+    {kConsumerUsagePage, kHomeUsageNumber},
+    {kConsumerUsagePage, kBackUsageNumber},
+};
+const size_t kSpecialUsagesLen = base::size(kSpecialUsages);
+
 float NormalizeAxis(CFIndex value, CFIndex min, CFIndex max) {
   return (2.f * (value - min) / static_cast<float>(max - min)) - 1.f;
 }
@@ -51,14 +76,6 @@
       device_ref_(device_ref),
       ff_device_ref_(nullptr),
       ff_effect_ref_(nullptr) {
-  std::fill(button_elements_, button_elements_ + Gamepad::kButtonsLengthCap,
-            nullptr);
-  std::fill(axis_elements_, axis_elements_ + Gamepad::kAxesLengthCap, nullptr);
-  std::fill(axis_minimums_, axis_minimums_ + Gamepad::kAxesLengthCap, 0);
-  std::fill(axis_maximums_, axis_maximums_ + Gamepad::kAxesLengthCap, 0);
-  std::fill(axis_report_sizes_, axis_report_sizes_ + Gamepad::kAxesLengthCap,
-            0);
-
   if (Dualshock4ControllerMac::IsDualshock4(vendor_id, product_id)) {
     dualshock4_ = std::make_unique<Dualshock4ControllerMac>(device_ref);
   } else if (device_ref) {
@@ -105,18 +122,108 @@
 }
 
 bool GamepadDeviceMac::AddButtonsAndAxes(Gamepad* gamepad) {
+  bool has_buttons = AddButtons(gamepad);
+  bool has_axes = AddAxes(gamepad);
+  gamepad->timestamp = GamepadDataFetcher::CurrentTimeInMicroseconds();
+  return (has_buttons || has_axes);
+}
+
+bool GamepadDeviceMac::AddButtons(Gamepad* gamepad) {
   base::ScopedCFTypeRef<CFArrayRef> elements_cf(IOHIDDeviceCopyMatchingElements(
       device_ref_, nullptr, kIOHIDOptionsTypeNone));
   NSArray* elements = base::mac::CFToNSCast(elements_cf);
   DCHECK(elements);
   DCHECK(gamepad);
-  gamepad->axes_length = 0;
-  gamepad->buttons_length = 0;
-  gamepad->timestamp = GamepadDataFetcher::CurrentTimeInMicroseconds();
-  memset(gamepad->axes, 0, sizeof(gamepad->axes));
   memset(gamepad->buttons, 0, sizeof(gamepad->buttons));
+  std::fill(button_elements_, button_elements_ + Gamepad::kButtonsLengthCap,
+            nullptr);
 
-  bool mapped_all_axes = true;
+  std::vector<IOHIDElementRef> special_element(kSpecialUsagesLen, nullptr);
+  size_t button_count = 0;
+  size_t unmapped_button_count = 0;
+  for (id elem in elements) {
+    IOHIDElementRef element = reinterpret_cast<IOHIDElementRef>(elem);
+    if (!CheckCollection(element))
+      continue;
+
+    uint32_t usage_page = IOHIDElementGetUsagePage(element);
+    uint32_t usage = IOHIDElementGetUsage(element);
+    if (IOHIDElementGetType(element) == kIOHIDElementTypeInput_Button) {
+      if (usage_page == kButtonUsagePage && usage > 0) {
+        size_t button_index = size_t{usage - 1};
+
+        // Ignore buttons with large usage values.
+        if (button_index >= Gamepad::kButtonsLengthCap)
+          continue;
+
+        // Button index already assigned, ignore.
+        if (button_elements_[button_index])
+          continue;
+
+        button_elements_[button_index] = element;
+        button_count = std::max(button_count, button_index + 1);
+      } else {
+        // Check for common gamepad buttons that are not on the Button usage
+        // page. Button indices are assigned in a second pass.
+        for (size_t special_index = 0; special_index < kSpecialUsagesLen;
+             ++special_index) {
+          const auto& special = kSpecialUsages[special_index];
+          if (usage_page == special.usage_page && usage == special.usage) {
+            special_element[special_index] = element;
+            ++unmapped_button_count;
+          }
+        }
+      }
+    }
+  }
+
+  if (unmapped_button_count > 0) {
+    // Insert unmapped buttons at unused button indices.
+    size_t button_index = 0;
+    for (size_t special_index = 0; special_index < kSpecialUsagesLen;
+         ++special_index) {
+      if (!special_element[special_index])
+        continue;
+
+      // Advance to the next unused button index.
+      while (button_index < Gamepad::kButtonsLengthCap &&
+             button_elements_[button_index]) {
+        ++button_index;
+      }
+      if (button_index >= Gamepad::kButtonsLengthCap)
+        break;
+
+      button_elements_[button_index] = special_element[special_index];
+      button_count = std::max(button_count, button_index + 1);
+
+      if (--unmapped_button_count == 0)
+        break;
+    }
+  }
+
+  gamepad->buttons_length = button_count;
+  return gamepad->buttons_length > 0;
+}
+
+bool GamepadDeviceMac::AddAxes(Gamepad* gamepad) {
+  base::ScopedCFTypeRef<CFArrayRef> elements_cf(IOHIDDeviceCopyMatchingElements(
+      device_ref_, nullptr, kIOHIDOptionsTypeNone));
+  NSArray* elements = base::mac::CFToNSCast(elements_cf);
+  DCHECK(elements);
+  DCHECK(gamepad);
+  memset(gamepad->axes, 0, sizeof(gamepad->axes));
+  std::fill(axis_elements_, axis_elements_ + Gamepad::kAxesLengthCap, nullptr);
+  std::fill(axis_minimums_, axis_minimums_ + Gamepad::kAxesLengthCap, 0);
+  std::fill(axis_maximums_, axis_maximums_ + Gamepad::kAxesLengthCap, 0);
+  std::fill(axis_report_sizes_, axis_report_sizes_ + Gamepad::kAxesLengthCap,
+            0);
+
+  // Most axes are mapped so that their index in the Gamepad axes array
+  // corresponds to the usage ID. However, this is not possible when the usage
+  // ID would cause the axis index to exceed the bounds of the axes array.
+  // Axes with large usage IDs are mapped in a second pass.
+  size_t axis_count = 0;
+  size_t unmapped_axis_count = 0;
 
   for (id elem in elements) {
     IOHIDElementRef element = reinterpret_cast<IOHIDElementRef>(elem);
@@ -125,28 +232,27 @@
 
     uint32_t usage_page = IOHIDElementGetUsagePage(element);
     uint32_t usage = IOHIDElementGetUsage(element);
-    if (IOHIDElementGetType(element) == kIOHIDElementTypeInput_Button &&
-        usage_page == kButtonUsagePage) {
-      uint32_t button_index = usage - 1;
-      if (button_index < Gamepad::kButtonsLengthCap) {
-        button_elements_[button_index] = element;
-        gamepad->buttons_length =
-            std::max(gamepad->buttons_length, button_index + 1);
-      }
-    } else if (IOHIDElementGetType(element) == kIOHIDElementTypeInput_Misc) {
-      uint32_t axis_index = usage - kAxisMinimumUsageNumber;
-      if (axis_index < Gamepad::kAxesLengthCap && !axis_elements_[axis_index]) {
-        axis_elements_[axis_index] = element;
-        gamepad->axes_length = std::max(gamepad->axes_length, axis_index + 1);
-      } else {
-        mapped_all_axes = false;
-      }
+    if (IOHIDElementGetType(element) != kIOHIDElementTypeInput_Misc ||
+        usage < kAxisMinimumUsageNumber) {
+      continue;
+    }
+
+    size_t axis_index = size_t{usage - kAxisMinimumUsageNumber};
+    if (axis_index < Gamepad::kAxesLengthCap) {
+      // Axis index already assigned, ignore.
+      if (axis_elements_[axis_index])
+        continue;
+      axis_elements_[axis_index] = element;
+      axis_count = std::max(axis_count, axis_index + 1);
+    } else if (usage_page <= kGameControlsUsagePage) {
+      // Assign an index for this axis in the second pass.
+      ++unmapped_axis_count;
     }
   }
 
-  if (!mapped_all_axes) {
-    // For axes whose usage puts them outside the standard axesLengthCap range.
-    uint32_t next_index = 0;
+  if (unmapped_axis_count > 0) {
+    // Insert unmapped axes at unused axis indices.
+    size_t axis_index = 0;
     for (id elem in elements) {
       IOHIDElementRef element = reinterpret_cast<IOHIDElementRef>(elem);
       if (!CheckCollection(element))
@@ -154,26 +260,35 @@
 
       uint32_t usage_page = IOHIDElementGetUsagePage(element);
       uint32_t usage = IOHIDElementGetUsage(element);
-      if (IOHIDElementGetType(element) == kIOHIDElementTypeInput_Misc &&
-          usage - kAxisMinimumUsageNumber >= Gamepad::kAxesLengthCap &&
-          usage_page <= kGameControlsUsagePage) {
-        for (; next_index < Gamepad::kAxesLengthCap; ++next_index) {
-          if (axis_elements_[next_index] == NULL)
-            break;
-        }
-        if (next_index < Gamepad::kAxesLengthCap) {
-          axis_elements_[next_index] = element;
-          gamepad->axes_length = std::max(gamepad->axes_length, next_index + 1);
-        }
+      if (IOHIDElementGetType(element) != kIOHIDElementTypeInput_Misc ||
+          usage < kAxisMinimumUsageNumber ||
+          usage_page > kGameControlsUsagePage) {
+        continue;
       }
 
-      if (next_index >= Gamepad::kAxesLengthCap)
+      // Ignore axes with small usage IDs that should have been mapped in the
+      // initial pass.
+      if (size_t{usage - kAxisMinimumUsageNumber} < Gamepad::kAxesLengthCap)
+        continue;
+
+      // Advance to the next unused axis index.
+      while (axis_index < Gamepad::kAxesLengthCap &&
+             axis_elements_[axis_index]) {
+        ++axis_index;
+      }
+      if (axis_index >= Gamepad::kAxesLengthCap)
+        break;
+
+      axis_elements_[axis_index] = element;
+      axis_count = std::max(axis_count, axis_index + 1);
+
+      if (--unmapped_axis_count == 0)
         break;
     }
   }
 
-  for (uint32_t axis_index = 0; axis_index < gamepad->axes_length;
-       ++axis_index) {
+  // Fetch the logical range and report size for each axis.
+  for (size_t axis_index = 0; axis_index < axis_count; ++axis_index) {
     IOHIDElementRef element = axis_elements_[axis_index];
     if (element != NULL) {
       CFIndex axis_min = IOHIDElementGetLogicalMin(element);
@@ -191,7 +306,9 @@
       axis_report_sizes_[axis_index] = IOHIDElementGetReportSize(element);
     }
   }
-  return (gamepad->axes_length > 0 || gamepad->buttons_length > 0);
+
+  gamepad->axes_length = axis_count;
+  return gamepad->axes_length > 0;
 }
 
 void GamepadDeviceMac::UpdateGamepadForValue(IOHIDValueRef value,
diff --git a/device/gamepad/raw_input_gamepad_device_win.cc b/device/gamepad/raw_input_gamepad_device_win.cc
index ed31959..d434c8d7 100644
--- a/device/gamepad/raw_input_gamepad_device_win.cc
+++ b/device/gamepad/raw_input_gamepad_device_win.cc
@@ -4,6 +4,7 @@
 
 #include "raw_input_gamepad_device_win.h"
 
+#include "base/stl_util.h"
 #include "device/gamepad/gamepad_data_fetcher.h"
 
 namespace device {
@@ -18,14 +19,41 @@
   return (1 << bits) - 1;
 }
 
-const uint32_t kAxisMinimumUsageNumber = 0x30;
+const uint32_t kGenericDesktopUsagePage = 0x01;
 const uint32_t kGameControlsUsagePage = 0x05;
 const uint32_t kButtonUsagePage = 0x09;
+const uint32_t kConsumerUsagePage = 0x0c;
+
+const uint32_t kAxisMinimumUsageNumber = 0x30;
+const uint32_t kSystemMainMenuUsageNumber = 0x85;
+const uint32_t kPowerUsageNumber = 0x30;
+const uint32_t kSearchUsageNumber = 0x0221;
+const uint32_t kHomeUsageNumber = 0x0223;
+const uint32_t kBackUsageNumber = 0x0224;
 
 // Blacklisted vendor IDs.
 const uint32_t kVendorOculus = 0x2833;
 const uint32_t kVendorBlue = 0xb58e;
 
+// The fetcher will collect all HID usages from the Button usage page and any
+// additional usages listed below.
+struct SpecialUsages {
+  const uint16_t usage_page;
+  const uint16_t usage;
+} kSpecialUsages[] = {
+    // Xbox One S pre-FW update reports Xbox button as SystemMainMenu over BT.
+    {kGenericDesktopUsagePage, kSystemMainMenuUsageNumber},
+    // Power is used for the Guide button on the Nvidia Shield 2015 gamepad.
+    {kConsumerUsagePage, kPowerUsageNumber},
+    // Search is used for the Guide button on the Nvidia Shield 2017 gamepad.
+    {kConsumerUsagePage, kSearchUsageNumber},
+    // Start, Back, and Guide buttons are often reported as Consumer Home or
+    // Back.
+    {kConsumerUsagePage, kHomeUsageNumber},
+    {kConsumerUsagePage, kBackUsageNumber},
+};
+const size_t kSpecialUsagesLen = base::size(kSpecialUsages);
+
 }  // namespace
 
 RawInputGamepadDeviceWin::RawInputGamepadDeviceWin(
@@ -34,6 +62,7 @@
     HidDllFunctionsWin* hid_functions)
     : handle_(device_handle),
       source_id_(source_id),
+      last_update_timestamp_(GamepadDataFetcher::CurrentTimeInMicroseconds()),
       hid_functions_(hid_functions) {
   ::ZeroMemory(buttons_, sizeof(buttons_));
   ::ZeroMemory(axes_, sizeof(axes_));
@@ -87,11 +116,24 @@
 
     if (status == HIDP_STATUS_SUCCESS) {
       // Set each reported button to true.
-      for (uint32_t j = 0; j < buttons_length; j++) {
-        int32_t button_index = usages[j].Usage - 1;
-        if (usages[j].UsagePage == kButtonUsagePage && button_index >= 0 &&
-            button_index < static_cast<int>(Gamepad::kButtonsLengthCap)) {
-          buttons_[button_index] = true;
+      for (size_t j = 0; j < buttons_length; j++) {
+        uint16_t usage_page = usages[j].UsagePage;
+        uint16_t usage = usages[j].Usage;
+        if (usage_page == kButtonUsagePage && usage > 0) {
+          size_t button_index = size_t{usage - 1};
+          if (button_index < Gamepad::kButtonsLengthCap)
+            buttons_[button_index] = true;
+        } else if (usage_page != kButtonUsagePage &&
+                   !special_button_map_.empty()) {
+          for (size_t special_index = 0; special_index < kSpecialUsagesLen;
+               ++special_index) {
+            int button_index = special_button_map_[special_index];
+            if (button_index < 0)
+              continue;
+            const auto& special = kSpecialUsages[special_index];
+            if (usage_page == special.usage_page && usage == special.usage)
+              buttons_[button_index] = true;
+          }
         }
       }
     }
@@ -128,12 +170,14 @@
       }
     }
   }
+
+  last_update_timestamp_ = GamepadDataFetcher::CurrentTimeInMicroseconds();
 }
 
 void RawInputGamepadDeviceWin::ReadPadState(Gamepad* pad) const {
   DCHECK(pad);
 
-  pad->timestamp = GamepadDataFetcher::CurrentTimeInMicroseconds();
+  pad->timestamp = last_update_timestamp_;
   pad->buttons_length = buttons_length_;
   pad->axes_length = axes_length_;
 
@@ -305,16 +349,98 @@
         HidP_Input, button_caps.get(), &button_count, preparsed_data_);
     DCHECK_EQ(HIDP_STATUS_SUCCESS, status);
 
-    for (size_t i = 0; i < button_count; ++i) {
-      if (button_caps[i].Range.UsageMin <= Gamepad::kButtonsLengthCap &&
-          button_caps[i].UsagePage == kButtonUsagePage) {
-        size_t max_index =
-            std::min(Gamepad::kButtonsLengthCap,
-                     static_cast<size_t>(button_caps[i].Range.UsageMax));
-        buttons_length_ = std::max(buttons_length_, max_index);
+    // Keep track of which button indices are in use.
+    std::vector<bool> button_indices_used(Gamepad::kButtonsLengthCap, false);
+
+    // Collect all inputs from the Button usage page.
+    QueryNormalButtonCapabilities(button_caps.get(), button_count,
+                                  &button_indices_used);
+
+    // Check for common gamepad buttons that are not on the Button usage page.
+    QuerySpecialButtonCapabilities(button_caps.get(), button_count,
+                                   &button_indices_used);
+  }
+}
+
+void RawInputGamepadDeviceWin::QueryNormalButtonCapabilities(
+    HIDP_BUTTON_CAPS button_caps[],
+    uint16_t button_count,
+    std::vector<bool>* button_indices_used) {
+  DCHECK(button_caps);
+  DCHECK(button_indices_used);
+
+  // Collect all inputs from the Button usage page and assign button indices
+  // based on the usage value.
+  for (size_t i = 0; i < button_count; ++i) {
+    uint16_t usage_page = button_caps[i].UsagePage;
+    uint16_t usage_min = button_caps[i].Range.UsageMin;
+    uint16_t usage_max = button_caps[i].Range.UsageMax;
+    if (usage_min == 0 || usage_max == 0)
+      continue;
+    size_t button_index_min = size_t{usage_min - 1};
+    size_t button_index_max = size_t{usage_max - 1};
+    if (usage_page == kButtonUsagePage &&
+        button_index_min < Gamepad::kButtonsLengthCap) {
+      button_index_max =
+          std::min(Gamepad::kButtonsLengthCap - 1, button_index_max);
+      buttons_length_ = std::max(buttons_length_, button_index_max + 1);
+      for (size_t j = button_index_min; j <= button_index_max; ++j)
+        (*button_indices_used)[j] = true;
+    }
+  }
+}
+
+void RawInputGamepadDeviceWin::QuerySpecialButtonCapabilities(
+    HIDP_BUTTON_CAPS button_caps[],
+    uint16_t button_count,
+    std::vector<bool>* button_indices_used) {
+  DCHECK(button_caps);
+  DCHECK(button_indices_used);
+
+  // Check for common gamepad buttons that are not on the Button usage page.
+  std::vector<bool> has_special_usage(kSpecialUsagesLen, false);
+  size_t unmapped_button_count = 0;
+  for (size_t i = 0; i < button_count; ++i) {
+    uint16_t usage_page = button_caps[i].UsagePage;
+    uint16_t usage_min = button_caps[i].Range.UsageMin;
+    uint16_t usage_max = button_caps[i].Range.UsageMax;
+    for (size_t special_index = 0; special_index < kSpecialUsagesLen;
+         ++special_index) {
+      const auto& special = kSpecialUsages[special_index];
+      if (usage_page == special.usage_page && usage_min <= special.usage &&
+          usage_max >= special.usage) {
+        has_special_usage[special_index] = true;
+        ++unmapped_button_count;
       }
     }
   }
+
+  special_button_map_.clear();
+  if (unmapped_button_count > 0) {
+    // Insert special buttons at unused button indices.
+    special_button_map_.resize(kSpecialUsagesLen, -1);
+    size_t button_index = 0;
+    for (size_t special_index = 0; special_index < kSpecialUsagesLen;
+         ++special_index) {
+      if (!has_special_usage[special_index])
+        continue;
+
+      // Advance to the next unused button index.
+      while (button_index < Gamepad::kButtonsLengthCap &&
+             (*button_indices_used)[button_index]) {
+        ++button_index;
+      }
+      if (button_index >= Gamepad::kButtonsLengthCap)
+        break;
+
+      special_button_map_[special_index] = button_index;
+      (*button_indices_used)[button_index] = true;
+      ++button_index;
+
+      if (--unmapped_button_count == 0)
+        break;
+    }
+  }
 }
 
 void RawInputGamepadDeviceWin::QueryAxisCapabilities(uint16_t axis_count) {
diff --git a/device/gamepad/raw_input_gamepad_device_win.h b/device/gamepad/raw_input_gamepad_device_win.h
index 20a9781..a23b232 100644
--- a/device/gamepad/raw_input_gamepad_device_win.h
+++ b/device/gamepad/raw_input_gamepad_device_win.h
@@ -13,6 +13,7 @@
 #include <windows.h>
 
 #include <memory>
+#include <vector>
 
 #include "device/gamepad/abstract_haptic_gamepad.h"
 #include "device/gamepad/dualshock4_controller_win.h"
@@ -87,6 +88,12 @@
   // on the device.
   bool QueryDeviceCapabilities();
   void QueryButtonCapabilities(uint16_t button_count);
+  void QueryNormalButtonCapabilities(HIDP_BUTTON_CAPS button_caps[],
+                                     uint16_t button_count,
+                                     std::vector<bool>* button_indices_used);
+  void QuerySpecialButtonCapabilities(HIDP_BUTTON_CAPS button_caps[],
+                                      uint16_t button_count,
+                                      std::vector<bool>* button_indices_used);
   void QueryAxisCapabilities(uint16_t axis_count);
 
   // True if the device described by this object is a valid RawInput gamepad.
@@ -98,6 +105,9 @@
   // The index assigned to this gamepad by the data fetcher.
   int source_id_ = 0;
 
+  // The last time the pad state was updated.
+  int64_t last_update_timestamp_;
+
   // Functions loaded from hid.dll. Not owned.
   HidDllFunctionsWin* hid_functions_ = nullptr;
 
@@ -115,6 +125,11 @@
   size_t buttons_length_ = 0;
   bool buttons_[Gamepad::kButtonsLengthCap];
 
+  // Mapping from "Special" usage index (defined by the kSpecialUsages table)
+  // to an index within the |buttons_| array, or -1 if the special usage is not
+  // mapped for this device.
+  std::vector<int> special_button_map_;
+
   size_t axes_length_ = 0;
   RawGamepadAxis axes_[Gamepad::kAxesLengthCap];
 
diff --git a/extensions/common/api/virtual_keyboard_private.json b/extensions/common/api/virtual_keyboard_private.json
index a8253e7c..d240d8f 100644
--- a/extensions/common/api/virtual_keyboard_private.json
+++ b/extensions/common/api/virtual_keyboard_private.json
@@ -251,10 +251,7 @@
             "name": "boundsList",
             "type": "array",
             "description": "List of rectangles representing regions occluded by the keyboard.",
-            "items": {
-              "type": "object",
-              "$ref": "Bounds"
-            }
+            "items": { "$ref": "Bounds" }
           }
         ]
       }
diff --git a/extensions/shell/browser/shell_oauth2_token_service_delegate.cc b/extensions/shell/browser/shell_oauth2_token_service_delegate.cc
index 759f3e2..c7f4a51 100644
--- a/extensions/shell/browser/shell_oauth2_token_service_delegate.cc
+++ b/extensions/shell/browser/shell_oauth2_token_service_delegate.cc
@@ -34,10 +34,12 @@
 ShellOAuth2TokenServiceDelegate::CreateAccessTokenFetcher(
     const std::string& account_id,
     net::URLRequestContextGetter* getter,
+    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
     OAuth2AccessTokenConsumer* consumer) {
   DCHECK_EQ(account_id, account_id_);
   DCHECK(!refresh_token_.empty());
-  return new OAuth2AccessTokenFetcherImpl(consumer, getter, refresh_token_);
+  return new OAuth2AccessTokenFetcherImpl(consumer, url_loader_factory,
+                                          refresh_token_);
 }
 
 net::URLRequestContextGetter*
diff --git a/extensions/shell/browser/shell_oauth2_token_service_delegate.h b/extensions/shell/browser/shell_oauth2_token_service_delegate.h
index 3a87c07..de8167c 100644
--- a/extensions/shell/browser/shell_oauth2_token_service_delegate.h
+++ b/extensions/shell/browser/shell_oauth2_token_service_delegate.h
@@ -30,6 +30,7 @@
   OAuth2AccessTokenFetcher* CreateAccessTokenFetcher(
       const std::string& account_id,
       net::URLRequestContextGetter* getter,
+      scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
       OAuth2AccessTokenConsumer* consumer) override;
   net::URLRequestContextGetter* GetRequestContext() const override;
 
diff --git a/google_apis/BUILD.gn b/google_apis/BUILD.gn
index 0309ce0..f679a5b 100644
--- a/google_apis/BUILD.gn
+++ b/google_apis/BUILD.gn
@@ -191,6 +191,7 @@
 google_apis_tmpl("google_apis") {
   deps = [
     "//net",
+    "//services/network/public/cpp",
   ]
 }
 
@@ -213,6 +214,8 @@
     "//base",
     "//base/test:test_support",
     "//net:test_support",
+    "//services/network:test_support",
+    "//services/network/public/cpp",
   ]
 
   if (enable_extensions) {
@@ -254,6 +257,7 @@
     ":test_support",
     "//base",
     "//base/test:run_all_unittests",
+    "//mojo/edk",
     "//testing/gmock",
     "//testing/gtest",
   ]
diff --git a/google_apis/DEPS b/google_apis/DEPS
index 54031e7..926008a 100644
--- a/google_apis/DEPS
+++ b/google_apis/DEPS
@@ -4,4 +4,5 @@
   "+crypto",
   "+net",
   "+third_party/ocmock",
+  "+services/network/public/cpp",
 ]
diff --git a/google_apis/drive/auth_service.cc b/google_apis/drive/auth_service.cc
index f1c72035..983c7d3 100644
--- a/google_apis/drive/auth_service.cc
+++ b/google_apis/drive/auth_service.cc
@@ -16,6 +16,7 @@
 #include "google_apis/drive/auth_service_observer.h"
 #include "google_apis/gaia/google_service_auth_error.h"
 #include "net/url_request/url_request_context_getter.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
 
 namespace google_apis {
 
@@ -41,6 +42,7 @@
   AuthRequest(OAuth2TokenService* oauth2_token_service,
               const std::string& account_id,
               net::URLRequestContextGetter* url_request_context_getter,
+              scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
               const AuthStatusCallback& callback,
               const std::vector<std::string>& scopes);
   ~AuthRequest() override;
@@ -64,17 +66,14 @@
     OAuth2TokenService* oauth2_token_service,
     const std::string& account_id,
     net::URLRequestContextGetter* url_request_context_getter,
+    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
     const AuthStatusCallback& callback,
     const std::vector<std::string>& scopes)
-    : OAuth2TokenService::Consumer("auth_service"),
-      callback_(callback) {
+    : OAuth2TokenService::Consumer("auth_service"), callback_(callback) {
   DCHECK(!callback_.is_null());
-  request_ = oauth2_token_service->
-      StartRequestWithContext(
-          account_id,
-          url_request_context_getter,
-          OAuth2TokenService::ScopeSet(scopes.begin(), scopes.end()),
-          this);
+  request_ = oauth2_token_service->StartRequestWithContext(
+      account_id, url_request_context_getter, url_loader_factory,
+      OAuth2TokenService::ScopeSet(scopes.begin(), scopes.end()), this);
 }
 
 AuthRequest::~AuthRequest() {}
@@ -122,10 +121,12 @@
     OAuth2TokenService* oauth2_token_service,
     const std::string& account_id,
     net::URLRequestContextGetter* url_request_context_getter,
+    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
     const std::vector<std::string>& scopes)
     : oauth2_token_service_(oauth2_token_service),
       account_id_(account_id),
       url_request_context_getter_(url_request_context_getter),
+      url_loader_factory_(url_loader_factory),
       scopes_(scopes),
       weak_ptr_factory_(this) {
   DCHECK(oauth2_token_service);
@@ -149,12 +150,10 @@
         FROM_HERE, base::Bind(callback, HTTP_SUCCESS, access_token_));
   } else if (HasRefreshToken()) {
     // We have refresh token, let's get an access token.
-    new AuthRequest(oauth2_token_service_,
-                    account_id_,
-                    url_request_context_getter_.get(),
+    new AuthRequest(oauth2_token_service_, account_id_,
+                    url_request_context_getter_.get(), url_loader_factory_,
                     base::Bind(&AuthService::OnAuthCompleted,
-                               weak_ptr_factory_.GetWeakPtr(),
-                               callback),
+                               weak_ptr_factory_.GetWeakPtr(), callback),
                     scopes_);
   } else {
     base::ThreadTaskRunnerHandle::Get()->PostTask(
diff --git a/google_apis/drive/auth_service.h b/google_apis/drive/auth_service.h
index 55f112d..cb36713 100644
--- a/google_apis/drive/auth_service.h
+++ b/google_apis/drive/auth_service.h
@@ -18,6 +18,9 @@
 namespace net {
 class URLRequestContextGetter;
 }
+namespace network {
+class SharedURLLoaderFactory;
+}
 
 namespace google_apis {
 
@@ -37,6 +40,7 @@
   AuthService(OAuth2TokenService* oauth2_token_service,
               const std::string& account_id,
               net::URLRequestContextGetter* url_request_context_getter,
+              scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
               const std::vector<std::string>& scopes);
   ~AuthService() override;
 
@@ -67,6 +71,7 @@
   OAuth2TokenService* oauth2_token_service_;
   std::string account_id_;
   scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_;
+  scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
   bool has_refresh_token_;
   std::string access_token_;
   std::vector<std::string> scopes_;
diff --git a/google_apis/gaia/DEPS b/google_apis/gaia/DEPS
index f8f20b6..d311b384 100644
--- a/google_apis/gaia/DEPS
+++ b/google_apis/gaia/DEPS
@@ -1,4 +1,15 @@
 include_rules = [
+  "+services/network/public/cpp",
   # Needed to support typemaps of core types for the Identity Service.
   "+mojo/public/cpp/bindings/struct_traits.h",
 ]
+
+specific_include_rules = {
+  r"(fake_oauth2_token_service_delegate\.h"
+  r"|oauth2_access_token_fetcher_impl_unittest\.cc"
+  r"|oauth2_token_service_unittest\.cc"
+  r")": [
+    "+services/network/test/test_url_loader_factory.h",
+    "+mojo/edk",
+  ],
+}
\ No newline at end of file
diff --git a/google_apis/gaia/fake_oauth2_token_service.cc b/google_apis/gaia/fake_oauth2_token_service.cc
index 3ed5a89e..1d57b221 100644
--- a/google_apis/gaia/fake_oauth2_token_service.cc
+++ b/google_apis/gaia/fake_oauth2_token_service.cc
@@ -26,6 +26,7 @@
     RequestImpl* request,
     const std::string& account_id,
     net::URLRequestContextGetter* getter,
+    scoped_refptr<network::SharedURLLoaderFactory> url_factory,
     const std::string& client_id,
     const std::string& client_secret,
     const ScopeSet& scopes) {
diff --git a/google_apis/gaia/fake_oauth2_token_service.h b/google_apis/gaia/fake_oauth2_token_service.h
index 17a4e26..70a8a96 100644
--- a/google_apis/gaia/fake_oauth2_token_service.h
+++ b/google_apis/gaia/fake_oauth2_token_service.h
@@ -6,12 +6,16 @@
 #define GOOGLE_APIS_GAIA_FAKE_OAUTH2_TOKEN_SERVICE_H_
 
 #include "base/macros.h"
+#include "base/memory/ref_counted.h"
 #include "google_apis/gaia/fake_oauth2_token_service_delegate.h"
 #include "google_apis/gaia/oauth2_token_service.h"
 
 namespace net {
 class URLRequestContextGetter;
 }
+namespace network {
+class SharedURLLoaderFactory;
+}
 
 // Do-nothing implementation of OAuth2TokenService.
 class FakeOAuth2TokenService : public OAuth2TokenService {
@@ -35,12 +39,14 @@
 
  protected:
   // OAuth2TokenService overrides.
-  void FetchOAuth2Token(RequestImpl* request,
-                        const std::string& account_id,
-                        net::URLRequestContextGetter* getter,
-                        const std::string& client_id,
-                        const std::string& client_secret,
-                        const ScopeSet& scopes) override;
+  void FetchOAuth2Token(
+      RequestImpl* request,
+      const std::string& account_id,
+      net::URLRequestContextGetter* getter,
+      scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
+      const std::string& client_id,
+      const std::string& client_secret,
+      const ScopeSet& scopes) override;
 
   void InvalidateAccessTokenImpl(const std::string& account_id,
                                  const std::string& client_id,
diff --git a/google_apis/gaia/fake_oauth2_token_service_delegate.cc b/google_apis/gaia/fake_oauth2_token_service_delegate.cc
index 757bf25..4090022 100644
--- a/google_apis/gaia/fake_oauth2_token_service_delegate.cc
+++ b/google_apis/gaia/fake_oauth2_token_service_delegate.cc
@@ -12,8 +12,10 @@
 
 FakeOAuth2TokenServiceDelegate::FakeOAuth2TokenServiceDelegate(
     net::URLRequestContextGetter* request_context)
-    : request_context_(request_context) {
-}
+    : request_context_(request_context),
+      shared_factory_(
+          base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
+              &test_url_loader_factory_)) {}
 
 FakeOAuth2TokenServiceDelegate::~FakeOAuth2TokenServiceDelegate() {
 }
@@ -22,10 +24,11 @@
 FakeOAuth2TokenServiceDelegate::CreateAccessTokenFetcher(
     const std::string& account_id,
     net::URLRequestContextGetter* getter,
+    scoped_refptr<network::SharedURLLoaderFactory> url_factory,
     OAuth2AccessTokenConsumer* consumer) {
   AccountInfoMap::const_iterator it = refresh_tokens_.find(account_id);
   DCHECK(it != refresh_tokens_.end());
-  return new OAuth2AccessTokenFetcherImpl(consumer, getter,
+  return new OAuth2AccessTokenFetcherImpl(consumer, url_factory,
                                           it->second->refresh_token);
 }
 
@@ -110,6 +113,11 @@
   return request_context_.get();
 }
 
+scoped_refptr<network::SharedURLLoaderFactory>
+FakeOAuth2TokenServiceDelegate::GetURLLoaderFactory() const {
+  return shared_factory_;
+}
+
 void FakeOAuth2TokenServiceDelegate::UpdateAuthError(
     const std::string& account_id,
     const GoogleServiceAuthError& error) {
diff --git a/google_apis/gaia/fake_oauth2_token_service_delegate.h b/google_apis/gaia/fake_oauth2_token_service_delegate.h
index 45a80def..6c4cd77 100644
--- a/google_apis/gaia/fake_oauth2_token_service_delegate.h
+++ b/google_apis/gaia/fake_oauth2_token_service_delegate.h
@@ -7,9 +7,16 @@
 
 #include "base/macros.h"
 #include "base/memory/linked_ptr.h"
+#include "base/memory/ref_counted.h"
 #include "google_apis/gaia/google_service_auth_error.h"
 #include "google_apis/gaia/oauth2_token_service_delegate.h"
 #include "net/url_request/url_request_context_getter.h"
+#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
+#include "services/network/test/test_url_loader_factory.h"
+
+namespace network {
+class SharedURLLoaderFactory;
+}
 
 class FakeOAuth2TokenServiceDelegate : public OAuth2TokenServiceDelegate {
  public:
@@ -19,6 +26,7 @@
   OAuth2AccessTokenFetcher* CreateAccessTokenFetcher(
       const std::string& account_id,
       net::URLRequestContextGetter* getter,
+      scoped_refptr<network::SharedURLLoaderFactory> url_factory,
       OAuth2AccessTokenConsumer* consumer) override;
 
   // Overriden to make sure it works on Android.
@@ -38,6 +46,8 @@
   void RevokeCredentials(const std::string& account_id) override;
 
   net::URLRequestContextGetter* GetRequestContext() const override;
+  scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory()
+      const override;
 
   void set_request_context(net::URLRequestContextGetter* request_context) {
     request_context_ = request_context;
@@ -45,6 +55,10 @@
 
   std::string GetRefreshToken(const std::string& account_id) const;
 
+  network::TestURLLoaderFactory* test_url_loader_factory() {
+    return &test_url_loader_factory_;
+  }
+
  private:
   struct AccountInfo {
     AccountInfo(const std::string& refresh_token);
@@ -62,6 +76,9 @@
 
   scoped_refptr<net::URLRequestContextGetter> request_context_;
 
+  network::TestURLLoaderFactory test_url_loader_factory_;
+  scoped_refptr<network::SharedURLLoaderFactory> shared_factory_;
+
   DISALLOW_COPY_AND_ASSIGN(FakeOAuth2TokenServiceDelegate);
 };
 #endif
diff --git a/google_apis/gaia/oauth2_access_token_fetcher_impl.cc b/google_apis/gaia/oauth2_access_token_fetcher_impl.cc
index 32d762a..95dd85a 100644
--- a/google_apis/gaia/oauth2_access_token_fetcher_impl.cc
+++ b/google_apis/gaia/oauth2_access_token_fetcher_impl.cc
@@ -23,32 +23,29 @@
 #include "net/base/load_flags.h"
 #include "net/http/http_status_code.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
-#include "net/url_request/url_fetcher.h"
-#include "net/url_request/url_request_context_getter.h"
 #include "net/url_request/url_request_status.h"
-
-using net::URLFetcher;
-using net::URLFetcherDelegate;
-using net::URLRequestContextGetter;
-using net::URLRequestStatus;
+#include "services/network/public/cpp/resource_request.h"
+#include "services/network/public/cpp/resource_response.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "services/network/public/cpp/simple_url_loader.h"
 
 namespace {
-static const char kGetAccessTokenBodyFormat[] =
+constexpr char kGetAccessTokenBodyFormat[] =
     "client_id=%s&"
     "client_secret=%s&"
     "grant_type=refresh_token&"
     "refresh_token=%s";
 
-static const char kGetAccessTokenBodyWithScopeFormat[] =
+constexpr char kGetAccessTokenBodyWithScopeFormat[] =
     "client_id=%s&"
     "client_secret=%s&"
     "grant_type=refresh_token&"
     "refresh_token=%s&"
     "scope=%s";
 
-static const char kAccessTokenKey[] = "access_token";
-static const char kExpiresInKey[] = "expires_in";
-static const char kErrorKey[] = "error";
+constexpr char kAccessTokenKey[] = "access_token";
+constexpr char kExpiresInKey[] = "expires_in";
+constexpr char kErrorKey[] = "error";
 
 // Enumerated constants for logging server responses on 400 errors, matching
 // RFC 6749.
@@ -81,23 +78,16 @@
   return OAUTH2_ACCESS_ERROR_UNKNOWN;
 }
 
-static GoogleServiceAuthError CreateAuthError(URLRequestStatus status) {
-  CHECK(!status.is_success());
-  if (status.status() == URLRequestStatus::CANCELED) {
-    return GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED);
-  } else {
-    DLOG(WARNING) << "Could not reach Google Accounts servers: errno "
-                  << status.error();
-    return GoogleServiceAuthError::FromConnectionError(status.error());
-  }
+static GoogleServiceAuthError CreateAuthError(int net_error) {
+  CHECK_NE(net_error, net::OK);
+  DLOG(WARNING) << "Could not reach Google Accounts servers: errno "
+                << net_error;
+  return GoogleServiceAuthError::FromConnectionError(net_error);
 }
 
-static std::unique_ptr<URLFetcher> CreateFetcher(
-    URLRequestContextGetter* getter,
+static std::unique_ptr<network::SimpleURLLoader> CreateURLLoader(
     const GURL& url,
-    const std::string& body,
-    URLFetcherDelegate* delegate) {
-  bool empty_body = body.empty();
+    const std::string& body) {
   net::NetworkTrafficAnnotationTag traffic_annotation =
       net::DefineNetworkTrafficAnnotation("oauth2_access_token_fetcher", R"(
         semantics {
@@ -125,33 +115,41 @@
             }
           }
         })");
-  std::unique_ptr<URLFetcher> result = net::URLFetcher::Create(
-      0, url, empty_body ? URLFetcher::GET : URLFetcher::POST, delegate,
-      traffic_annotation);
 
-  gaia::MarkURLFetcherAsGaia(result.get());
-  result->SetRequestContext(getter);
-  result->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES |
-                       net::LOAD_DO_NOT_SAVE_COOKIES);
+  auto resource_request = std::make_unique<network::ResourceRequest>();
+  resource_request->url = url;
+  resource_request->load_flags =
+      net::LOAD_DO_NOT_SEND_COOKIES | net::LOAD_DO_NOT_SAVE_COOKIES;
+  if (!body.empty())
+    resource_request->method = "POST";
+
+  auto url_loader = network::SimpleURLLoader::Create(
+      std::move(resource_request), traffic_annotation);
+
+  if (!body.empty())
+    url_loader->AttachStringForUpload(body,
+                                      "application/x-www-form-urlencoded");
+
+  // We want to receive the body even on error, as it may contain the reason for
+  // failure.
+  url_loader->SetAllowHttpErrorResults(true);
+
   // Fetchers are sometimes cancelled because a network change was detected,
   // especially at startup and after sign-in on ChromeOS. Retrying once should
   // be enough in those cases; let the fetcher retry up to 3 times just in case.
   // http://crbug.com/163710
-  result->SetAutomaticallyRetryOnNetworkChanges(3);
+  url_loader->SetRetryOptions(
+      3, network::SimpleURLLoader::RETRY_ON_NETWORK_CHANGE);
 
-  if (!empty_body)
-    result->SetUploadData("application/x-www-form-urlencoded", body);
-
-  return result;
+  return url_loader;
 }
 
 std::unique_ptr<base::DictionaryValue> ParseGetAccessTokenResponse(
-    const net::URLFetcher* source) {
-  CHECK(source);
+    std::unique_ptr<std::string> data) {
+  if (!data)
+    return nullptr;
 
-  std::string data;
-  source->GetResponseAsString(&data);
-  std::unique_ptr<base::Value> value = base::JSONReader::Read(data);
+  std::unique_ptr<base::Value> value = base::JSONReader::Read(*data);
   if (!value.get() || value->type() != base::Value::Type::DICTIONARY)
     value.reset();
 
@@ -163,16 +161,18 @@
 
 OAuth2AccessTokenFetcherImpl::OAuth2AccessTokenFetcherImpl(
     OAuth2AccessTokenConsumer* consumer,
-    net::URLRequestContextGetter* getter,
+    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
     const std::string& refresh_token)
     : OAuth2AccessTokenFetcher(consumer),
-      getter_(getter),
+      url_loader_factory_(url_loader_factory),
       refresh_token_(refresh_token),
       state_(INITIAL) {}
 
 OAuth2AccessTokenFetcherImpl::~OAuth2AccessTokenFetcherImpl() {}
 
-void OAuth2AccessTokenFetcherImpl::CancelRequest() { fetcher_.reset(); }
+void OAuth2AccessTokenFetcherImpl::CancelRequest() {
+  url_loader_.reset();
+}
 
 void OAuth2AccessTokenFetcherImpl::Start(
     const std::string& client_id,
@@ -187,29 +187,42 @@
 void OAuth2AccessTokenFetcherImpl::StartGetAccessToken() {
   CHECK_EQ(INITIAL, state_);
   state_ = GET_ACCESS_TOKEN_STARTED;
-  fetcher_ = CreateFetcher(getter_, MakeGetAccessTokenUrl(),
-                           MakeGetAccessTokenBody(client_id_, client_secret_,
-                                                  refresh_token_, scopes_),
-                           this);
-  fetcher_->Start();  // OnURLFetchComplete will be called.
+  url_loader_ =
+      CreateURLLoader(MakeGetAccessTokenUrl(),
+                      MakeGetAccessTokenBody(client_id_, client_secret_,
+                                             refresh_token_, scopes_));
+  // It's safe to use Unretained below as the |url_loader_| is owned by |this|.
+  url_loader_->DownloadToString(
+      url_loader_factory_.get(),
+      base::BindOnce(&OAuth2AccessTokenFetcherImpl::OnURLLoadComplete,
+                     base::Unretained(this)),
+      1024 * 1024);
 }
 
 void OAuth2AccessTokenFetcherImpl::EndGetAccessToken(
-    const net::URLFetcher* source) {
+    std::unique_ptr<std::string> response_body) {
   CHECK_EQ(GET_ACCESS_TOKEN_STARTED, state_);
   state_ = GET_ACCESS_TOKEN_DONE;
 
-  URLRequestStatus status = source->GetStatus();
-  int histogram_value =
-      status.is_success() ? source->GetResponseCode() : status.error();
+  bool net_failure = false;
+  int histogram_value;
+  if (url_loader_->ResponseInfo() && url_loader_->ResponseInfo()->headers) {
+    // Note that the SimpleURLLoader reports net::ERR_FAILED for HTTP codes
+    // other than 200s.
+    histogram_value = url_loader_->ResponseInfo()->headers->response_code();
+  } else {
+    histogram_value = url_loader_->NetError();
+    net_failure = true;
+  }
   base::UmaHistogramSparse("Gaia.ResponseCodesForOAuth2AccessToken",
                            histogram_value);
-  if (!status.is_success()) {
-    OnGetTokenFailure(CreateAuthError(status));
+  if (net_failure) {
+    OnGetTokenFailure(CreateAuthError(histogram_value));
     return;
   }
 
-  switch (source->GetResponseCode()) {
+  int response_code = url_loader_->ResponseInfo()->headers->response_code();
+  switch (response_code) {
     case net::HTTP_OK:
       break;
     case net::HTTP_FORBIDDEN:
@@ -222,7 +235,8 @@
       // HTTP_BAD_REQUEST (400) usually contains error as per
       // http://tools.ietf.org/html/rfc6749#section-5.2.
       std::string gaia_error;
-      if (!ParseGetAccessTokenFailureResponse(source, &gaia_error)) {
+      if (!ParseGetAccessTokenFailureResponse(std::move(response_body),
+                                              &gaia_error)) {
         OnGetTokenFailure(
             GoogleServiceAuthError(GoogleServiceAuthError::SERVICE_ERROR));
         return;
@@ -243,14 +257,14 @@
       return;
     }
     default: {
-      if (source->GetResponseCode() >= net::HTTP_INTERNAL_SERVER_ERROR) {
+      if (response_code >= net::HTTP_INTERNAL_SERVER_ERROR) {
         // 5xx is always treated as transient.
         OnGetTokenFailure(GoogleServiceAuthError(
             GoogleServiceAuthError::SERVICE_UNAVAILABLE));
       } else {
         // The other errors are treated as permanent error.
         DLOG(ERROR) << "Unexpected persistent error: http_status="
-                    << source->GetResponseCode();
+                    << response_code;
         OnGetTokenFailure(
             GoogleServiceAuthError::FromInvalidGaiaCredentialsReason(
                 GoogleServiceAuthError::InvalidGaiaCredentialsReason::
@@ -264,7 +278,8 @@
   // Parse out the access token and the expiration time.
   std::string access_token;
   int expires_in;
-  if (!ParseGetAccessTokenSuccessResponse(source, &access_token, &expires_in)) {
+  if (!ParseGetAccessTokenSuccessResponse(std::move(response_body),
+                                          &access_token, &expires_in)) {
     DLOG(WARNING) << "Response doesn't match expected format";
     OnGetTokenFailure(
         GoogleServiceAuthError(GoogleServiceAuthError::SERVICE_UNAVAILABLE));
@@ -289,11 +304,10 @@
   FireOnGetTokenFailure(error);
 }
 
-void OAuth2AccessTokenFetcherImpl::OnURLFetchComplete(
-    const net::URLFetcher* source) {
-  CHECK(source);
+void OAuth2AccessTokenFetcherImpl::OnURLLoadComplete(
+    std::unique_ptr<std::string> response_body) {
   CHECK(state_ == GET_ACCESS_TOKEN_STARTED);
-  EndGetAccessToken(source);
+  EndGetAccessToken(std::move(response_body));
 }
 
 // static
@@ -330,27 +344,24 @@
 
 // static
 bool OAuth2AccessTokenFetcherImpl::ParseGetAccessTokenSuccessResponse(
-    const net::URLFetcher* source,
+    std::unique_ptr<std::string> response_body,
     std::string* access_token,
     int* expires_in) {
   CHECK(access_token);
   std::unique_ptr<base::DictionaryValue> value =
-      ParseGetAccessTokenResponse(source);
-  if (value.get() == NULL)
+      ParseGetAccessTokenResponse(std::move(response_body));
+  if (!value)
     return false;
-
   return value->GetString(kAccessTokenKey, access_token) &&
          value->GetInteger(kExpiresInKey, expires_in);
 }
 
 // static
 bool OAuth2AccessTokenFetcherImpl::ParseGetAccessTokenFailureResponse(
-    const net::URLFetcher* source,
+    std::unique_ptr<std::string> response_body,
     std::string* error) {
   CHECK(error);
   std::unique_ptr<base::DictionaryValue> value =
-      ParseGetAccessTokenResponse(source);
-  if (value.get() == NULL)
-    return false;
-  return value->GetString(kErrorKey, error);
+      ParseGetAccessTokenResponse(std::move(response_body));
+  return value ? value->GetString(kErrorKey, error) : false;
 }
diff --git a/google_apis/gaia/oauth2_access_token_fetcher_impl.h b/google_apis/gaia/oauth2_access_token_fetcher_impl.h
index 9e87596..5003e0d 100644
--- a/google_apis/gaia/oauth2_access_token_fetcher_impl.h
+++ b/google_apis/gaia/oauth2_access_token_fetcher_impl.h
@@ -11,9 +11,9 @@
 
 #include "base/gtest_prod_util.h"
 #include "base/macros.h"
+#include "base/memory/ref_counted.h"
 #include "google_apis/gaia/oauth2_access_token_consumer.h"
 #include "google_apis/gaia/oauth2_access_token_fetcher.h"
-#include "net/url_request/url_fetcher_delegate.h"
 #include "url/gurl.h"
 
 class OAuth2AccessTokenFetcherImplTest;
@@ -22,13 +22,12 @@
 class Time;
 }
 
-namespace net {
-class URLFetcher;
-class URLRequestContextGetter;
+namespace network {
+class SimpleURLLoader;
+class SharedURLLoaderFactory;
 }
 
-// Abstracts the details to get OAuth2 access token token from
-// OAuth2 refresh token.
+// Abstracts the details to get OAuth2 access token from OAuth2 refresh token.
 // See "Using the Refresh Token" section in:
 // http://code.google.com/apis/accounts/docs/OAuth2WebServer.html
 //
@@ -45,12 +44,12 @@
 //
 // This class can handle one request at a time. To parallelize requests,
 // create multiple instances.
-class OAuth2AccessTokenFetcherImpl : public OAuth2AccessTokenFetcher,
-                                     public net::URLFetcherDelegate {
+class OAuth2AccessTokenFetcherImpl : public OAuth2AccessTokenFetcher {
  public:
-  OAuth2AccessTokenFetcherImpl(OAuth2AccessTokenConsumer* consumer,
-                               net::URLRequestContextGetter* getter,
-                               const std::string& refresh_token);
+  OAuth2AccessTokenFetcherImpl(
+      OAuth2AccessTokenConsumer* consumer,
+      scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
+      const std::string& refresh_token);
   ~OAuth2AccessTokenFetcherImpl() override;
 
   // Implementation of OAuth2AccessTokenFetcher
@@ -60,9 +59,6 @@
 
   void CancelRequest() override;
 
-  // Implementation of net::URLFetcherDelegate
-  void OnURLFetchComplete(const net::URLFetcher* source) override;
-
  private:
   enum State {
     INITIAL,
@@ -71,9 +67,11 @@
     ERROR_STATE,
   };
 
+  void OnURLLoadComplete(std::unique_ptr<std::string> response_body);
+
   // Helper methods for the flow.
   void StartGetAccessToken();
-  void EndGetAccessToken(const net::URLFetcher* source);
+  void EndGetAccessToken(std::unique_ptr<std::string> response_body);
 
   // Helper mehtods for reporting back results.
   void OnGetTokenSuccess(const std::string& access_token,
@@ -88,30 +86,45 @@
       const std::string& refresh_token,
       const std::vector<std::string>& scopes);
 
-  static bool ParseGetAccessTokenSuccessResponse(const net::URLFetcher* source,
-                                                 std::string* access_token,
-                                                 int* expires_in);
+  static bool ParseGetAccessTokenSuccessResponse(
+      std::unique_ptr<std::string> response_body,
+      std::string* access_token,
+      int* expires_in);
 
-  static bool ParseGetAccessTokenFailureResponse(const net::URLFetcher* source,
-                                                 std::string* error);
+  static bool ParseGetAccessTokenFailureResponse(
+      std::unique_ptr<std::string> response_body,
+      std::string* error);
 
   // State that is set during construction.
-  net::URLRequestContextGetter* const getter_;
-  std::string refresh_token_;
+  scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
+  const std::string refresh_token_;
   State state_;
 
   // While a fetch is in progress.
-  std::unique_ptr<net::URLFetcher> fetcher_;
+  std::unique_ptr<network::SimpleURLLoader> url_loader_;
   std::string client_id_;
   std::string client_secret_;
   std::vector<std::string> scopes_;
 
   friend class OAuth2AccessTokenFetcherImplTest;
   FRIEND_TEST_ALL_PREFIXES(OAuth2AccessTokenFetcherImplTest,
-                           ParseGetAccessTokenResponse);
+                           ParseGetAccessTokenResponseNoBody);
   FRIEND_TEST_ALL_PREFIXES(OAuth2AccessTokenFetcherImplTest,
-                           MakeGetAccessTokenBody);
-
+                           MakeGetAccessTokenBodyNoScope);
+  FRIEND_TEST_ALL_PREFIXES(OAuth2AccessTokenFetcherImplTest,
+                           MakeGetAccessTokenBodyOneScope);
+  FRIEND_TEST_ALL_PREFIXES(OAuth2AccessTokenFetcherImplTest,
+                           MakeGetAccessTokenBodyMultipleScopes);
+  FRIEND_TEST_ALL_PREFIXES(OAuth2AccessTokenFetcherImplTest,
+                           ParseGetAccessTokenResponseBadJson);
+  FRIEND_TEST_ALL_PREFIXES(OAuth2AccessTokenFetcherImplTest,
+                           ParseGetAccessTokenResponseNoAccessToken);
+  FRIEND_TEST_ALL_PREFIXES(OAuth2AccessTokenFetcherImplTest,
+                           ParseGetAccessTokenResponseSuccess);
+  FRIEND_TEST_ALL_PREFIXES(OAuth2AccessTokenFetcherImplTest,
+                           ParseGetAccessTokenFailure);
+  FRIEND_TEST_ALL_PREFIXES(OAuth2AccessTokenFetcherImplTest,
+                           ParseGetAccessTokenFailureInvalidError);
   DISALLOW_COPY_AND_ASSIGN(OAuth2AccessTokenFetcherImpl);
 };
 
diff --git a/google_apis/gaia/oauth2_access_token_fetcher_impl_unittest.cc b/google_apis/gaia/oauth2_access_token_fetcher_impl_unittest.cc
index 9d3bf952..4c9c8e71 100644
--- a/google_apis/gaia/oauth2_access_token_fetcher_impl_unittest.cc
+++ b/google_apis/gaia/oauth2_access_token_fetcher_impl_unittest.cc
@@ -11,79 +11,42 @@
 
 #include "base/run_loop.h"
 #include "base/test/scoped_task_environment.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "build/build_config.h"
 #include "google_apis/gaia/gaia_urls.h"
 #include "google_apis/gaia/google_service_auth_error.h"
 #include "google_apis/gaia/oauth2_access_token_consumer.h"
+#include "mojo/edk/embedder/embedder.h"
 #include "net/base/net_errors.h"
 #include "net/http/http_status_code.h"
 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
-#include "net/url_request/test_url_fetcher_factory.h"
-#include "net/url_request/url_fetcher.h"
-#include "net/url_request/url_fetcher_delegate.h"
-#include "net/url_request/url_fetcher_factory.h"
-#include "net/url_request/url_request.h"
-#include "net/url_request/url_request_status.h"
-#include "net/url_request/url_request_test_util.h"
+#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
+#include "services/network/test/test_url_loader_factory.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
 
-using net::ScopedURLFetcherFactory;
-using net::TestURLFetcher;
-using net::URLFetcher;
-using net::URLFetcherDelegate;
-using net::URLFetcherFactory;
-using net::URLRequestStatus;
 using testing::_;
-using testing::Return;
 
 namespace {
 
-typedef std::vector<std::string> ScopeList;
+using ScopeList = std::vector<std::string>;
 
-static const char kValidTokenResponse[] =
-    "{"
-    "  \"access_token\": \"at1\","
-    "  \"expires_in\": 3600,"
-    "  \"token_type\": \"Bearer\""
-    "}";
-static const char kTokenResponseNoAccessToken[] =
-    "{"
-    "  \"expires_in\": 3600,"
-    "  \"token_type\": \"Bearer\""
-    "}";
+constexpr char kValidTokenResponse[] = R"(
+    {
+      "access_token": "at1",
+      "expires_in": 3600,
+      "token_type": "Bearer"
+    })";
 
-static const char kValidFailureTokenResponse[] =
-    "{"
-    "  \"error\": \"invalid_grant\""
-    "}";
+constexpr char kTokenResponseNoAccessToken[] = R"(
+    {
+      "expires_in": 3600,
+      "token_type": "Bearer"
+    })";
 
-class MockUrlFetcherFactory : public ScopedURLFetcherFactory,
-                              public URLFetcherFactory {
- public:
-  MockUrlFetcherFactory() : ScopedURLFetcherFactory(this) {}
-  ~MockUrlFetcherFactory() override {}
-
-  MOCK_METHOD5(
-      CreateURLFetcherMock,
-      URLFetcher*(int id,
-                  const GURL& url,
-                  URLFetcher::RequestType request_type,
-                  URLFetcherDelegate* d,
-                  net::NetworkTrafficAnnotationTag traffic_annotation));
-
-  std::unique_ptr<URLFetcher> CreateURLFetcher(
-      int id,
-      const GURL& url,
-      URLFetcher::RequestType request_type,
-      URLFetcherDelegate* d,
-      net::NetworkTrafficAnnotationTag traffic_annotation) override {
-    return std::unique_ptr<URLFetcher>(
-        CreateURLFetcherMock(id, url, request_type, d, traffic_annotation));
-  }
-};
+constexpr char kValidFailureTokenResponse[] = R"(
+    {
+      "error": "invalid_grant"
+    })";
 
 class MockOAuth2AccessTokenConsumer : public OAuth2AccessTokenConsumer {
  public:
@@ -96,186 +59,168 @@
   MOCK_METHOD1(OnGetTokenFailure, void(const GoogleServiceAuthError& error));
 };
 
+class URLLoaderFactoryInterceptor {
+ public:
+  MOCK_METHOD1(Intercept, void(const network::ResourceRequest&));
+};
+
+MATCHER_P(resourceRequestUrlEquals, url, "") {
+  return arg.url == url;
+}
+
 }  // namespace
 
 class OAuth2AccessTokenFetcherImplTest : public testing::Test {
  public:
   OAuth2AccessTokenFetcherImplTest()
-      : request_context_getter_(new net::TestURLRequestContextGetter(
-            base::ThreadTaskRunnerHandle::Get())),
-        fetcher_(&consumer_, request_context_getter_.get(), "refresh_token") {
+      : shared_url_loader_factory_(
+            base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
+                &url_loader_factory_)),
+        fetcher_(&consumer_, shared_url_loader_factory_, "refresh_token") {
+    url_loader_factory_.SetInterceptor(base::BindRepeating(
+        &URLLoaderFactoryInterceptor::Intercept,
+        base::Unretained(&url_loader_factory_interceptor_)));
+    mojo::edk::Init();
     base::RunLoop().RunUntilIdle();
   }
 
-  ~OAuth2AccessTokenFetcherImplTest() override {}
+  ~OAuth2AccessTokenFetcherImplTest() override {
+    shared_url_loader_factory_->Detach();
+  }
 
-  virtual TestURLFetcher* SetupGetAccessToken(bool fetch_succeeds,
-                                              int response_code,
-                                              const std::string& body) {
+  void SetupGetAccessToken(int net_error_code,
+                           net::HttpStatusCode http_response_code,
+                           const std::string& body) {
     GURL url(GaiaUrls::GetInstance()->oauth2_token_url());
-    TestURLFetcher* url_fetcher = new TestURLFetcher(0, url, &fetcher_);
-    net::Error error = fetch_succeeds ? net::OK : net::ERR_FAILED;
-    url_fetcher->set_status(URLRequestStatus::FromError(error));
+    if (net_error_code == net::OK) {
+      url_loader_factory_.AddResponse(url.spec(), body, http_response_code);
+    } else {
+      url_loader_factory_.AddResponse(
+          url, network::ResourceResponseHead(), body,
+          network::URLLoaderCompletionStatus(net_error_code));
+    }
 
-    if (response_code != 0)
-      url_fetcher->set_response_code(response_code);
-
-    if (!body.empty())
-      url_fetcher->SetResponseString(body);
-
-    EXPECT_CALL(factory_, CreateURLFetcherMock(_, url, _, _, _))
-        .WillOnce(Return(url_fetcher));
-    return url_fetcher;
+    EXPECT_CALL(url_loader_factory_interceptor_,
+                Intercept(resourceRequestUrlEquals(url)));
   }
 
  protected:
   base::test::ScopedTaskEnvironment scoped_task_environment_;
-  MockUrlFetcherFactory factory_;
   MockOAuth2AccessTokenConsumer consumer_;
-  scoped_refptr<net::TestURLRequestContextGetter> request_context_getter_;
+  URLLoaderFactoryInterceptor url_loader_factory_interceptor_;
+  network::TestURLLoaderFactory url_loader_factory_;
+  scoped_refptr<network::WeakWrapperSharedURLLoaderFactory>
+      shared_url_loader_factory_;
   OAuth2AccessTokenFetcherImpl fetcher_;
 };
 
 // These four tests time out, see http://crbug.com/113446.
-TEST_F(OAuth2AccessTokenFetcherImplTest,
-       DISABLED_GetAccessTokenRequestFailure) {
-  TestURLFetcher* url_fetcher = SetupGetAccessToken(false, 0, std::string());
+TEST_F(OAuth2AccessTokenFetcherImplTest, GetAccessTokenRequestFailure) {
+  SetupGetAccessToken(net::ERR_FAILED, net::HTTP_OK, std::string());
   EXPECT_CALL(consumer_, OnGetTokenFailure(_)).Times(1);
   fetcher_.Start("client_id", "client_secret", ScopeList());
-  fetcher_.OnURLFetchComplete(url_fetcher);
+  base::RunLoop().RunUntilIdle();
 }
 
-TEST_F(OAuth2AccessTokenFetcherImplTest,
-       DISABLED_GetAccessTokenResponseCodeFailure) {
-  TestURLFetcher* url_fetcher =
-      SetupGetAccessToken(true, net::HTTP_FORBIDDEN, std::string());
+TEST_F(OAuth2AccessTokenFetcherImplTest, GetAccessTokenResponseCodeFailure) {
+  SetupGetAccessToken(net::OK, net::HTTP_FORBIDDEN, std::string());
   EXPECT_CALL(consumer_, OnGetTokenFailure(_)).Times(1);
   fetcher_.Start("client_id", "client_secret", ScopeList());
-  fetcher_.OnURLFetchComplete(url_fetcher);
+  base::RunLoop().RunUntilIdle();
 }
 
-TEST_F(OAuth2AccessTokenFetcherImplTest, DISABLED_Success) {
-  TestURLFetcher* url_fetcher =
-      SetupGetAccessToken(true, net::HTTP_OK, kValidTokenResponse);
+TEST_F(OAuth2AccessTokenFetcherImplTest, Success) {
+  SetupGetAccessToken(net::OK, net::HTTP_OK, kValidTokenResponse);
   EXPECT_CALL(consumer_, OnGetTokenSuccess("at1", _)).Times(1);
   fetcher_.Start("client_id", "client_secret", ScopeList());
-  fetcher_.OnURLFetchComplete(url_fetcher);
+  base::RunLoop().RunUntilIdle();
 }
 
-TEST_F(OAuth2AccessTokenFetcherImplTest, DISABLED_MakeGetAccessTokenBody) {
-  {  // No scope.
-    std::string body =
-        "client_id=cid1&"
-        "client_secret=cs1&"
-        "grant_type=refresh_token&"
-        "refresh_token=rt1";
-    EXPECT_EQ(body,
-              OAuth2AccessTokenFetcherImpl::MakeGetAccessTokenBody(
-                  "cid1", "cs1", "rt1", ScopeList()));
-  }
-
-  {  // One scope.
-    std::string body =
-        "client_id=cid1&"
-        "client_secret=cs1&"
-        "grant_type=refresh_token&"
-        "refresh_token=rt1&"
-        "scope=https://www.googleapis.com/foo";
-    ScopeList scopes;
-    scopes.push_back("https://www.googleapis.com/foo");
-    EXPECT_EQ(body,
-              OAuth2AccessTokenFetcherImpl::MakeGetAccessTokenBody(
-                  "cid1", "cs1", "rt1", scopes));
-  }
-
-  {  // Multiple scopes.
-    std::string body =
-        "client_id=cid1&"
-        "client_secret=cs1&"
-        "grant_type=refresh_token&"
-        "refresh_token=rt1&"
-        "scope=https://www.googleapis.com/foo+"
-        "https://www.googleapis.com/bar+"
-        "https://www.googleapis.com/baz";
-    ScopeList scopes;
-    scopes.push_back("https://www.googleapis.com/foo");
-    scopes.push_back("https://www.googleapis.com/bar");
-    scopes.push_back("https://www.googleapis.com/baz");
-    EXPECT_EQ(body,
-              OAuth2AccessTokenFetcherImpl::MakeGetAccessTokenBody(
-                  "cid1", "cs1", "rt1", scopes));
-  }
+TEST_F(OAuth2AccessTokenFetcherImplTest, MakeGetAccessTokenBodyNoScope) {
+  std::string body =
+      "client_id=cid1&"
+      "client_secret=cs1&"
+      "grant_type=refresh_token&"
+      "refresh_token=rt1";
+  EXPECT_EQ(body, OAuth2AccessTokenFetcherImpl::MakeGetAccessTokenBody(
+                      "cid1", "cs1", "rt1", ScopeList()));
 }
 
-// http://crbug.com/114215
-#if defined(OS_WIN)
-#define MAYBE_ParseGetAccessTokenResponse DISABLED_ParseGetAccessTokenResponse
-#else
-#define MAYBE_ParseGetAccessTokenResponse ParseGetAccessTokenResponse
-#endif  // defined(OS_WIN)
-TEST_F(OAuth2AccessTokenFetcherImplTest, MAYBE_ParseGetAccessTokenResponse) {
-  {  // No body.
-    TestURLFetcher url_fetcher(0, GURL("http://www.google.com"), NULL);
+TEST_F(OAuth2AccessTokenFetcherImplTest, MakeGetAccessTokenBodyOneScope) {
+  std::string body =
+      "client_id=cid1&"
+      "client_secret=cs1&"
+      "grant_type=refresh_token&"
+      "refresh_token=rt1&"
+      "scope=https://www.googleapis.com/foo";
+  ScopeList scopes = {"https://www.googleapis.com/foo"};
+  EXPECT_EQ(body, OAuth2AccessTokenFetcherImpl::MakeGetAccessTokenBody(
+                      "cid1", "cs1", "rt1", scopes));
+}
 
-    std::string at;
-    int expires_in;
-    EXPECT_FALSE(
-        OAuth2AccessTokenFetcherImpl::ParseGetAccessTokenSuccessResponse(
-            &url_fetcher, &at, &expires_in));
-    EXPECT_TRUE(at.empty());
-  }
-  {  // Bad json.
-    TestURLFetcher url_fetcher(0, GURL("http://www.google.com"), NULL);
-    url_fetcher.SetResponseString("foo");
+TEST_F(OAuth2AccessTokenFetcherImplTest, MakeGetAccessTokenBodyMultipleScopes) {
+  std::string body =
+      "client_id=cid1&"
+      "client_secret=cs1&"
+      "grant_type=refresh_token&"
+      "refresh_token=rt1&"
+      "scope=https://www.googleapis.com/foo+"
+      "https://www.googleapis.com/bar+"
+      "https://www.googleapis.com/baz";
+  ScopeList scopes = {"https://www.googleapis.com/foo",
+                      "https://www.googleapis.com/bar",
+                      "https://www.googleapis.com/baz"};
+  EXPECT_EQ(body, OAuth2AccessTokenFetcherImpl::MakeGetAccessTokenBody(
+                      "cid1", "cs1", "rt1", scopes));
+}
 
-    std::string at;
-    int expires_in;
-    EXPECT_FALSE(
-        OAuth2AccessTokenFetcherImpl::ParseGetAccessTokenSuccessResponse(
-            &url_fetcher, &at, &expires_in));
-    EXPECT_TRUE(at.empty());
-  }
-  {  // Valid json: access token missing.
-    TestURLFetcher url_fetcher(0, GURL("http://www.google.com"), NULL);
-    url_fetcher.SetResponseString(kTokenResponseNoAccessToken);
+TEST_F(OAuth2AccessTokenFetcherImplTest, ParseGetAccessTokenResponseNoBody) {
+  std::string at;
+  int expires_in;
+  auto empty_body = std::make_unique<std::string>("");
+  EXPECT_FALSE(OAuth2AccessTokenFetcherImpl::ParseGetAccessTokenSuccessResponse(
+      std::move(empty_body), &at, &expires_in));
+  EXPECT_TRUE(at.empty());
+}
 
-    std::string at;
-    int expires_in;
-    EXPECT_FALSE(
-        OAuth2AccessTokenFetcherImpl::ParseGetAccessTokenSuccessResponse(
-            &url_fetcher, &at, &expires_in));
-    EXPECT_TRUE(at.empty());
-  }
-  {  // Valid json: all good.
-    TestURLFetcher url_fetcher(0, GURL("http://www.google.com"), NULL);
-    url_fetcher.SetResponseString(kValidTokenResponse);
+TEST_F(OAuth2AccessTokenFetcherImplTest, ParseGetAccessTokenResponseBadJson) {
+  std::string at;
+  int expires_in;
+  EXPECT_FALSE(OAuth2AccessTokenFetcherImpl::ParseGetAccessTokenSuccessResponse(
+      std::make_unique<std::string>("foo"), &at, &expires_in));
+  EXPECT_TRUE(at.empty());
+}
 
-    std::string at;
-    int expires_in;
-    EXPECT_TRUE(
-        OAuth2AccessTokenFetcherImpl::ParseGetAccessTokenSuccessResponse(
-            &url_fetcher, &at, &expires_in));
-    EXPECT_EQ("at1", at);
-    EXPECT_EQ(3600, expires_in);
-  }
-  {  // Valid json: invalid error response.
-    TestURLFetcher url_fetcher(0, GURL("http://www.google.com"), NULL);
-    url_fetcher.SetResponseString(kTokenResponseNoAccessToken);
+TEST_F(OAuth2AccessTokenFetcherImplTest,
+       ParseGetAccessTokenResponseNoAccessToken) {
+  std::string at;
+  int expires_in;
+  EXPECT_FALSE(OAuth2AccessTokenFetcherImpl::ParseGetAccessTokenSuccessResponse(
+      std::make_unique<std::string>(kTokenResponseNoAccessToken), &at,
+      &expires_in));
+  EXPECT_TRUE(at.empty());
+}
 
-    std::string error;
-    EXPECT_FALSE(
-        OAuth2AccessTokenFetcherImpl::ParseGetAccessTokenFailureResponse(
-            &url_fetcher, &error));
-    EXPECT_TRUE(error.empty());
-  }
-  {  // Valid json: error response.
-    TestURLFetcher url_fetcher(0, GURL("http://www.google.com"), NULL);
-    url_fetcher.SetResponseString(kValidFailureTokenResponse);
+TEST_F(OAuth2AccessTokenFetcherImplTest, ParseGetAccessTokenResponseSuccess) {
+  std::string at;
+  int expires_in;
+  EXPECT_TRUE(OAuth2AccessTokenFetcherImpl::ParseGetAccessTokenSuccessResponse(
+      std::make_unique<std::string>(kValidTokenResponse), &at, &expires_in));
+  EXPECT_EQ("at1", at);
+  EXPECT_EQ(3600, expires_in);
+}
 
-    std::string error;
-    EXPECT_TRUE(
-        OAuth2AccessTokenFetcherImpl::ParseGetAccessTokenFailureResponse(
-            &url_fetcher, &error));
-    EXPECT_EQ("invalid_grant", error);
-  }
+TEST_F(OAuth2AccessTokenFetcherImplTest,
+       ParseGetAccessTokenFailureInvalidError) {
+  std::string error;
+  EXPECT_FALSE(OAuth2AccessTokenFetcherImpl::ParseGetAccessTokenFailureResponse(
+      std::make_unique<std::string>(kTokenResponseNoAccessToken), &error));
+  EXPECT_TRUE(error.empty());
+}
+
+TEST_F(OAuth2AccessTokenFetcherImplTest, ParseGetAccessTokenFailure) {
+  std::string error;
+  EXPECT_TRUE(OAuth2AccessTokenFetcherImpl::ParseGetAccessTokenFailureResponse(
+      std::make_unique<std::string>(kValidFailureTokenResponse), &error));
+  EXPECT_EQ("invalid_grant", error);
 }
diff --git a/google_apis/gaia/oauth2_token_service.cc b/google_apis/gaia/oauth2_token_service.cc
index 542435c..8b50814 100644
--- a/google_apis/gaia/oauth2_token_service.cc
+++ b/google_apis/gaia/oauth2_token_service.cc
@@ -24,6 +24,7 @@
 #include "google_apis/gaia/oauth2_access_token_fetcher_impl.h"
 #include "google_apis/gaia/oauth2_token_service_delegate.h"
 #include "net/url_request/url_request_context_getter.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
 
 int OAuth2TokenService::max_fetch_retry_num_ = 5;
 
@@ -124,6 +125,7 @@
       OAuth2TokenService* oauth2_token_service,
       const std::string& account_id,
       net::URLRequestContextGetter* getter,
+      scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
       const std::string& client_id,
       const std::string& client_secret,
       const ScopeSet& scopes,
@@ -159,6 +161,7 @@
   Fetcher(OAuth2TokenService* oauth2_token_service,
           const std::string& account_id,
           net::URLRequestContextGetter* getter,
+          scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
           const std::string& client_id,
           const std::string& client_secret,
           const OAuth2TokenService::ScopeSet& scopes,
@@ -175,6 +178,7 @@
   // (whichever comes first).
   OAuth2TokenService* const oauth2_token_service_;
   scoped_refptr<net::URLRequestContextGetter> getter_;
+  scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
   const std::string account_id_;
   const ScopeSet scopes_;
   std::vector<base::WeakPtr<RequestImpl> > waiting_requests_;
@@ -203,13 +207,14 @@
     OAuth2TokenService* oauth2_token_service,
     const std::string& account_id,
     net::URLRequestContextGetter* getter,
+    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
     const std::string& client_id,
     const std::string& client_secret,
     const OAuth2TokenService::ScopeSet& scopes,
     base::WeakPtr<RequestImpl> waiting_request) {
   std::unique_ptr<OAuth2TokenService::Fetcher> fetcher = base::WrapUnique(
-      new Fetcher(oauth2_token_service, account_id, getter, client_id,
-                  client_secret, scopes, waiting_request));
+      new Fetcher(oauth2_token_service, account_id, getter, url_loader_factory,
+                  client_id, client_secret, scopes, waiting_request));
 
   fetcher->Start();
   return fetcher;
@@ -219,12 +224,14 @@
     OAuth2TokenService* oauth2_token_service,
     const std::string& account_id,
     net::URLRequestContextGetter* getter,
+    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
     const std::string& client_id,
     const std::string& client_secret,
     const OAuth2TokenService::ScopeSet& scopes,
     base::WeakPtr<RequestImpl> waiting_request)
     : oauth2_token_service_(oauth2_token_service),
       getter_(getter),
+      url_loader_factory_(url_loader_factory),
       account_id_(account_id),
       scopes_(scopes),
       retry_number_(0),
@@ -243,7 +250,7 @@
 
 void OAuth2TokenService::Fetcher::Start() {
   fetcher_.reset(oauth2_token_service_->CreateAccessTokenFetcher(
-      account_id_, getter_.get(), this));
+      account_id_, getter_.get(), url_loader_factory_, this));
   DCHECK(fetcher_);
 
   // Stop the timer before starting the fetch, as defense in depth against the
@@ -420,12 +427,9 @@
     const OAuth2TokenService::ScopeSet& scopes,
     OAuth2TokenService::Consumer* consumer) {
   return StartRequestForClientWithContext(
-      account_id,
-      GetRequestContext(),
+      account_id, GetRequestContext(), delegate_->GetURLLoaderFactory(),
       GaiaUrls::GetInstance()->oauth2_chrome_client_id(),
-      GaiaUrls::GetInstance()->oauth2_chrome_client_secret(),
-      scopes,
-      consumer);
+      GaiaUrls::GetInstance()->oauth2_chrome_client_secret(), scopes, consumer);
 }
 
 std::unique_ptr<OAuth2TokenService::Request>
@@ -436,12 +440,8 @@
     const OAuth2TokenService::ScopeSet& scopes,
     OAuth2TokenService::Consumer* consumer) {
   return StartRequestForClientWithContext(
-      account_id,
-      GetRequestContext(),
-      client_id,
-      client_secret,
-      scopes,
-      consumer);
+      account_id, GetRequestContext(), delegate_->GetURLLoaderFactory(),
+      client_id, client_secret, scopes, consumer);
 }
 
 net::URLRequestContextGetter* OAuth2TokenService::GetRequestContext() const {
@@ -452,21 +452,20 @@
 OAuth2TokenService::StartRequestWithContext(
     const std::string& account_id,
     net::URLRequestContextGetter* getter,
+    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
     const ScopeSet& scopes,
     Consumer* consumer) {
   return StartRequestForClientWithContext(
-      account_id,
-      getter,
+      account_id, getter, url_loader_factory,
       GaiaUrls::GetInstance()->oauth2_chrome_client_id(),
-      GaiaUrls::GetInstance()->oauth2_chrome_client_secret(),
-      scopes,
-      consumer);
+      GaiaUrls::GetInstance()->oauth2_chrome_client_secret(), scopes, consumer);
 }
 
 std::unique_ptr<OAuth2TokenService::Request>
 OAuth2TokenService::StartRequestForClientWithContext(
     const std::string& account_id,
     net::URLRequestContextGetter* getter,
+    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
     const std::string& client_id,
     const std::string& client_secret,
     const ScopeSet& scopes,
@@ -500,22 +499,20 @@
     InformConsumerWithCacheEntry(cache_entry, request.get(),
                                  request_parameters);
   } else {
-    FetchOAuth2Token(request.get(),
-                     account_id,
-                     getter,
-                     client_id,
-                     client_secret,
-                     scopes);
+    FetchOAuth2Token(request.get(), account_id, getter, url_loader_factory,
+                     client_id, client_secret, scopes);
   }
   return std::move(request);
 }
 
-void OAuth2TokenService::FetchOAuth2Token(RequestImpl* request,
-                                          const std::string& account_id,
-                                          net::URLRequestContextGetter* getter,
-                                          const std::string& client_id,
-                                          const std::string& client_secret,
-                                          const ScopeSet& scopes) {
+void OAuth2TokenService::FetchOAuth2Token(
+    RequestImpl* request,
+    const std::string& account_id,
+    net::URLRequestContextGetter* getter,
+    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
+    const std::string& client_id,
+    const std::string& client_secret,
+    const ScopeSet& scopes) {
   // If there is already a pending fetcher for |scopes| and |account_id|,
   // simply register this |request| for those results rather than starting
   // a new fetcher.
@@ -528,21 +525,18 @@
     return;
   }
 
-  pending_fetchers_[request_parameters] =
-      Fetcher::CreateAndStart(this,
-                              account_id,
-                              getter,
-                              client_id,
-                              client_secret,
-                              scopes,
-                              request->AsWeakPtr());
+  pending_fetchers_[request_parameters] = Fetcher::CreateAndStart(
+      this, account_id, getter, url_loader_factory, client_id, client_secret,
+      scopes, request->AsWeakPtr());
 }
 
 OAuth2AccessTokenFetcher* OAuth2TokenService::CreateAccessTokenFetcher(
     const std::string& account_id,
     net::URLRequestContextGetter* getter,
+    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
     OAuth2AccessTokenConsumer* consumer) {
-  return delegate_->CreateAccessTokenFetcher(account_id, getter, consumer);
+  return delegate_->CreateAccessTokenFetcher(account_id, getter,
+                                             url_loader_factory, consumer);
 }
 
 void OAuth2TokenService::InformConsumerWithCacheEntry(
diff --git a/google_apis/gaia/oauth2_token_service.h b/google_apis/gaia/oauth2_token_service.h
index 9f279c52..4b8bc85 100644
--- a/google_apis/gaia/oauth2_token_service.h
+++ b/google_apis/gaia/oauth2_token_service.h
@@ -14,6 +14,7 @@
 
 #include "base/gtest_prod_util.h"
 #include "base/macros.h"
+#include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
 #include "base/sequence_checker.h"
@@ -25,6 +26,9 @@
 namespace net {
 class URLRequestContextGetter;
 }
+namespace network {
+class SharedURLLoaderFactory;
+}
 
 class GoogleServiceAuthError;
 class OAuth2AccessTokenFetcher;
@@ -180,6 +184,7 @@
   std::unique_ptr<Request> StartRequestWithContext(
       const std::string& account_id,
       net::URLRequestContextGetter* getter,
+      scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
       const ScopeSet& scopes,
       Consumer* consumer);
 
@@ -287,17 +292,20 @@
 
   // Fetches an OAuth token for the specified client/scopes. Virtual so it can
   // be overridden for tests and for platform-specific behavior.
-  virtual void FetchOAuth2Token(RequestImpl* request,
-                                const std::string& account_id,
-                                net::URLRequestContextGetter* getter,
-                                const std::string& client_id,
-                                const std::string& client_secret,
-                                const ScopeSet& scopes);
+  virtual void FetchOAuth2Token(
+      RequestImpl* request,
+      const std::string& account_id,
+      net::URLRequestContextGetter* getter,
+      scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
+      const std::string& client_id,
+      const std::string& client_secret,
+      const ScopeSet& scopes);
 
   // Create an access token fetcher for the given account id.
   OAuth2AccessTokenFetcher* CreateAccessTokenFetcher(
       const std::string& account_id,
       net::URLRequestContextGetter* getter,
+      scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
       OAuth2AccessTokenConsumer* consumer);
 
   // Invalidates the |access_token| issued for |account_id|, |client_id| and
@@ -346,6 +354,7 @@
   std::unique_ptr<Request> StartRequestForClientWithContext(
       const std::string& account_id,
       net::URLRequestContextGetter* getter,
+      scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
       const std::string& client_id,
       const std::string& client_secret,
       const ScopeSet& scopes,
diff --git a/google_apis/gaia/oauth2_token_service_delegate.cc b/google_apis/gaia/oauth2_token_service_delegate.cc
index 9b77071..aa0bce3c 100644
--- a/google_apis/gaia/oauth2_token_service_delegate.cc
+++ b/google_apis/gaia/oauth2_token_service_delegate.cc
@@ -5,6 +5,7 @@
 #include "google_apis/gaia/oauth2_token_service_delegate.h"
 
 #include "google_apis/gaia/oauth2_token_service.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
 
 // static
 const char OAuth2TokenServiceDelegate::kInvalidRefreshToken[] =
@@ -101,6 +102,11 @@
   return nullptr;
 }
 
+scoped_refptr<network::SharedURLLoaderFactory>
+OAuth2TokenServiceDelegate::GetURLLoaderFactory() const {
+  return nullptr;
+}
+
 GoogleServiceAuthError OAuth2TokenServiceDelegate::GetAuthError(
     const std::string& account_id) const {
   return GoogleServiceAuthError::AuthErrorNone();
diff --git a/google_apis/gaia/oauth2_token_service_delegate.h b/google_apis/gaia/oauth2_token_service_delegate.h
index a65589bd..d3f51328 100644
--- a/google_apis/gaia/oauth2_token_service_delegate.h
+++ b/google_apis/gaia/oauth2_token_service_delegate.h
@@ -6,6 +6,7 @@
 #define GOOGLE_APIS_GAIA_OAUTH2_TOKEN_SERVICE_DELEGATE_H_
 
 #include "base/macros.h"
+#include "base/memory/ref_counted.h"
 #include "base/observer_list.h"
 #include "google_apis/gaia/gaia_auth_util.h"
 #include "google_apis/gaia/oauth2_token_service.h"
@@ -14,6 +15,9 @@
 namespace net {
 class URLRequestContextGetter;
 }
+namespace network {
+class SharedURLLoaderFactory;
+}
 
 // Abstract base class to fetch and maintain refresh tokens from various
 // entities. Concrete subclasses should implement RefreshTokenIsAvailable and
@@ -41,6 +45,7 @@
   virtual OAuth2AccessTokenFetcher* CreateAccessTokenFetcher(
       const std::string& account_id,
       net::URLRequestContextGetter* getter,
+      scoped_refptr<network::SharedURLLoaderFactory> url_factory,
       OAuth2AccessTokenConsumer* consumer) = 0;
 
   virtual bool RefreshTokenIsAvailable(const std::string& account_id) const = 0;
@@ -63,6 +68,8 @@
                                  const std::string& refresh_token) {}
   virtual void RevokeCredentials(const std::string& account_id) {}
   virtual net::URLRequestContextGetter* GetRequestContext() const;
+  virtual scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory()
+      const;
 
   bool ValidateAccountId(const std::string& account_id) const;
 
diff --git a/google_apis/gaia/oauth2_token_service_request_unittest.cc b/google_apis/gaia/oauth2_token_service_request_unittest.cc
index 2c6f828..c49d30f0 100644
--- a/google_apis/gaia/oauth2_token_service_request_unittest.cc
+++ b/google_apis/gaia/oauth2_token_service_request_unittest.cc
@@ -87,12 +87,14 @@
   }
 
  protected:
-  void FetchOAuth2Token(RequestImpl* request,
-                        const std::string& account_id,
-                        net::URLRequestContextGetter* getter,
-                        const std::string& client_id,
-                        const std::string& client_secret,
-                        const ScopeSet& scopes) override;
+  void FetchOAuth2Token(
+      RequestImpl* request,
+      const std::string& account_id,
+      net::URLRequestContextGetter* getter,
+      scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
+      const std::string& client_id,
+      const std::string& client_secret,
+      const ScopeSet& scopes) override;
 
   void InvalidateAccessTokenImpl(const std::string& account_id,
                                  const std::string& client_id,
@@ -129,6 +131,7 @@
     RequestImpl* request,
     const std::string& account_id,
     net::URLRequestContextGetter* getter,
+    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
     const std::string& client_id,
     const std::string& client_secret,
     const ScopeSet& scopes) {
diff --git a/google_apis/gaia/oauth2_token_service_unittest.cc b/google_apis/gaia/oauth2_token_service_unittest.cc
index 324a5a3..0c73d1b 100644
--- a/google_apis/gaia/oauth2_token_service_unittest.cc
+++ b/google_apis/gaia/oauth2_token_service_unittest.cc
@@ -11,11 +11,13 @@
 #include "base/run_loop.h"
 #include "google_apis/gaia/fake_oauth2_token_service_delegate.h"
 #include "google_apis/gaia/gaia_constants.h"
+#include "google_apis/gaia/gaia_urls.h"
 #include "google_apis/gaia/google_service_auth_error.h"
 #include "google_apis/gaia/oauth2_access_token_consumer.h"
 #include "google_apis/gaia/oauth2_access_token_fetcher_impl.h"
 #include "google_apis/gaia/oauth2_token_service.h"
 #include "google_apis/gaia/oauth2_token_service_test_util.h"
+#include "mojo/edk/embedder/embedder.h"
 #include "net/http/http_status_code.h"
 #include "net/url_request/test_url_fetcher_factory.h"
 #include "net/url_request/url_fetcher_delegate.h"
@@ -35,11 +37,15 @@
 
   void OnGetTokenFailure(const OAuth2TokenService::Request* request,
                          const GoogleServiceAuthError& error) override {
+    if (retry_counter_ <= 0)
+      return;
+    retry_counter_--;
     TestingOAuth2TokenServiceConsumer::OnGetTokenFailure(request, error);
     request_ = oauth2_service_->StartRequest(
         account_id_, OAuth2TokenService::ScopeSet(), this);
   }
 
+  int retry_counter_ = 2;
   OAuth2TokenService* oauth2_service_;
   std::string account_id_;
   std::unique_ptr<OAuth2TokenService::Request> request_;
@@ -65,10 +71,12 @@
 class OAuth2TokenServiceTest : public testing::Test {
  public:
   void SetUp() override {
-    oauth2_service_.reset(new TestOAuth2TokenService(
-        std::make_unique<FakeOAuth2TokenServiceDelegate>(
-            new net::TestURLRequestContextGetter(
-                message_loop_.task_runner()))));
+    mojo::edk::Init();
+    auto delegate = std::make_unique<FakeOAuth2TokenServiceDelegate>(
+        new net::TestURLRequestContextGetter(message_loop_.task_runner()));
+    test_url_loader_factory_ = delegate->test_url_loader_factory();
+    oauth2_service_ =
+        std::make_unique<TestOAuth2TokenService>(std::move(delegate));
     account_id_ = "test_user@gmail.com";
   }
 
@@ -77,9 +85,15 @@
     base::RunLoop().RunUntilIdle();
   }
 
+  void SimulateOAuthTokenResponse(const std::string& token,
+                                  net::HttpStatusCode status = net::HTTP_OK) {
+    test_url_loader_factory_->AddResponse(
+        GaiaUrls::GetInstance()->oauth2_token_url().spec(), token, status);
+  }
+
  protected:
   base::MessageLoopForIO message_loop_;  // net:: stuff needs IO message loop.
-  net::TestURLFetcherFactory factory_;
+  network::TestURLLoaderFactory* test_url_loader_factory_ = nullptr;
   std::unique_ptr<TestOAuth2TokenService> oauth2_service_;
   std::string account_id_;
   TestingOAuth2TokenServiceConsumer consumer_;
@@ -101,18 +115,14 @@
   std::unique_ptr<OAuth2TokenService::Request> request(
       oauth2_service_->StartRequest(account_id_, OAuth2TokenService::ScopeSet(),
                                     &consumer_));
+
+  EXPECT_EQ(0, consumer_.number_of_successful_tokens_);
+  SimulateOAuthTokenResponse("", net::HTTP_UNAUTHORIZED);
   base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(0, consumer_.number_of_successful_tokens_);
-  EXPECT_EQ(0, consumer_.number_of_errors_);
-  net::TestURLFetcher* fetcher = factory_.GetFetcherByID(0);
-  ASSERT_TRUE(fetcher);
-  fetcher->set_response_code(net::HTTP_UNAUTHORIZED);
-  fetcher->SetResponseString(std::string());
-  fetcher->delegate()->OnURLFetchComplete(fetcher);
-  EXPECT_EQ(0, consumer_.number_of_successful_tokens_);
   EXPECT_EQ(1, consumer_.number_of_errors_);
-  EXPECT_EQ(fetcher, factory_.GetFetcherByID(0));
+  EXPECT_EQ(0, test_url_loader_factory_->NumPending());
 }
 
 TEST_F(OAuth2TokenServiceTest, SuccessWithoutCaching) {
@@ -121,15 +131,12 @@
   std::unique_ptr<OAuth2TokenService::Request> request(
       oauth2_service_->StartRequest(account_id_, OAuth2TokenService::ScopeSet(),
                                     &consumer_));
-  base::RunLoop().RunUntilIdle();
-
   EXPECT_EQ(0, consumer_.number_of_successful_tokens_);
   EXPECT_EQ(0, consumer_.number_of_errors_);
-  net::TestURLFetcher* fetcher = factory_.GetFetcherByID(0);
-  ASSERT_TRUE(fetcher);
-  fetcher->set_response_code(net::HTTP_OK);
-  fetcher->SetResponseString(GetValidTokenResponse("token", 3600));
-  fetcher->delegate()->OnURLFetchComplete(fetcher);
+
+  SimulateOAuthTokenResponse(GetValidTokenResponse("token", 3600));
+  base::RunLoop().RunUntilIdle();
+
   EXPECT_EQ(1, consumer_.number_of_successful_tokens_);
   EXPECT_EQ(0, consumer_.number_of_errors_);
   EXPECT_EQ("token", consumer_.last_token_);
@@ -149,17 +156,13 @@
       account_id_, "refreshToken");
 
   // First request.
+  SimulateOAuthTokenResponse(GetValidTokenResponse("token", 3600));
   std::unique_ptr<OAuth2TokenService::Request> request(
       oauth2_service_->StartRequest(account_id_, scopes1, &consumer_));
-  base::RunLoop().RunUntilIdle();
-
   EXPECT_EQ(0, consumer_.number_of_successful_tokens_);
   EXPECT_EQ(0, consumer_.number_of_errors_);
-  net::TestURLFetcher* fetcher = factory_.GetFetcherByID(0);
-  ASSERT_TRUE(fetcher);
-  fetcher->set_response_code(net::HTTP_OK);
-  fetcher->SetResponseString(GetValidTokenResponse("token", 3600));
-  fetcher->delegate()->OnURLFetchComplete(fetcher);
+  base::RunLoop().RunUntilIdle();
+
   EXPECT_EQ(1, consumer_.number_of_successful_tokens_);
   EXPECT_EQ(0, consumer_.number_of_errors_);
   EXPECT_EQ("token", consumer_.last_token_);
@@ -176,16 +179,13 @@
   EXPECT_EQ("token", consumer_.last_token_);
 
   // Third request to a new set of scopes, should return another token.
+  SimulateOAuthTokenResponse(GetValidTokenResponse("token2", 3600));
   std::unique_ptr<OAuth2TokenService::Request> request3(
       oauth2_service_->StartRequest(account_id_, scopes2, &consumer_));
-  base::RunLoop().RunUntilIdle();
   EXPECT_EQ(2, consumer_.number_of_successful_tokens_);
   EXPECT_EQ(0, consumer_.number_of_errors_);
-  fetcher = factory_.GetFetcherByID(0);
-  ASSERT_TRUE(fetcher);
-  fetcher->set_response_code(net::HTTP_OK);
-  fetcher->SetResponseString(GetValidTokenResponse("token2", 3600));
-  fetcher->delegate()->OnURLFetchComplete(fetcher);
+  base::RunLoop().RunUntilIdle();
+
   EXPECT_EQ(3, consumer_.number_of_successful_tokens_);
   EXPECT_EQ(0, consumer_.number_of_errors_);
   EXPECT_EQ("token2", consumer_.last_token_);
@@ -196,35 +196,27 @@
       account_id_, "refreshToken");
 
   // First request.
+  SimulateOAuthTokenResponse(GetValidTokenResponse("token", 0));
   std::unique_ptr<OAuth2TokenService::Request> request(
       oauth2_service_->StartRequest(account_id_, OAuth2TokenService::ScopeSet(),
                                     &consumer_));
-  base::RunLoop().RunUntilIdle();
   EXPECT_EQ(0, consumer_.number_of_successful_tokens_);
   EXPECT_EQ(0, consumer_.number_of_errors_);
-  net::TestURLFetcher* fetcher = factory_.GetFetcherByID(0);
-  ASSERT_TRUE(fetcher);
-  fetcher->set_response_code(net::HTTP_OK);
-  fetcher->SetResponseString(GetValidTokenResponse("token", 0));
-  fetcher->delegate()->OnURLFetchComplete(fetcher);
+  base::RunLoop().RunUntilIdle();
+
   EXPECT_EQ(1, consumer_.number_of_successful_tokens_);
   EXPECT_EQ(0, consumer_.number_of_errors_);
   EXPECT_EQ("token", consumer_.last_token_);
 
   // Second request must try to access the network as the token has expired.
+  SimulateOAuthTokenResponse("", net::HTTP_UNAUTHORIZED);  // Network failure.
   std::unique_ptr<OAuth2TokenService::Request> request2(
       oauth2_service_->StartRequest(account_id_, OAuth2TokenService::ScopeSet(),
                                     &consumer_));
-  base::RunLoop().RunUntilIdle();
   EXPECT_EQ(1, consumer_.number_of_successful_tokens_);
   EXPECT_EQ(0, consumer_.number_of_errors_);
+  base::RunLoop().RunUntilIdle();
 
-  // Network failure.
-  fetcher = factory_.GetFetcherByID(0);
-  ASSERT_TRUE(fetcher);
-  fetcher->set_response_code(net::HTTP_UNAUTHORIZED);
-  fetcher->SetResponseString(std::string());
-  fetcher->delegate()->OnURLFetchComplete(fetcher);
   EXPECT_EQ(1, consumer_.number_of_successful_tokens_);
   EXPECT_EQ(1, consumer_.number_of_errors_);
 }
@@ -234,34 +226,25 @@
       account_id_, "refreshToken");
 
   // First request.
+  SimulateOAuthTokenResponse(GetValidTokenResponse("token", 0));
   std::unique_ptr<OAuth2TokenService::Request> request(
       oauth2_service_->StartRequest(account_id_, OAuth2TokenService::ScopeSet(),
                                     &consumer_));
-  base::RunLoop().RunUntilIdle();
   EXPECT_EQ(0, consumer_.number_of_successful_tokens_);
   EXPECT_EQ(0, consumer_.number_of_errors_);
-  net::TestURLFetcher* fetcher = factory_.GetFetcherByID(0);
-  ASSERT_TRUE(fetcher);
-  fetcher->set_response_code(net::HTTP_OK);
-  fetcher->SetResponseString(GetValidTokenResponse("token", 0));
-  fetcher->delegate()->OnURLFetchComplete(fetcher);
+  base::RunLoop().RunUntilIdle();
   EXPECT_EQ(1, consumer_.number_of_successful_tokens_);
   EXPECT_EQ(0, consumer_.number_of_errors_);
   EXPECT_EQ("token", consumer_.last_token_);
 
   // Second request must try to access the network as the token has expired.
+  SimulateOAuthTokenResponse(GetValidTokenResponse("another token", 0));
   std::unique_ptr<OAuth2TokenService::Request> request2(
       oauth2_service_->StartRequest(account_id_, OAuth2TokenService::ScopeSet(),
                                     &consumer_));
-  base::RunLoop().RunUntilIdle();
   EXPECT_EQ(1, consumer_.number_of_successful_tokens_);
   EXPECT_EQ(0, consumer_.number_of_errors_);
-
-  fetcher = factory_.GetFetcherByID(0);
-  ASSERT_TRUE(fetcher);
-  fetcher->set_response_code(net::HTTP_OK);
-  fetcher->SetResponseString(GetValidTokenResponse("another token", 0));
-  fetcher->delegate()->OnURLFetchComplete(fetcher);
+  base::RunLoop().RunUntilIdle();
   EXPECT_EQ(2, consumer_.number_of_successful_tokens_);
   EXPECT_EQ(0, consumer_.number_of_errors_);
   EXPECT_EQ("another token", consumer_.last_token_);
@@ -277,14 +260,12 @@
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(0, consumer_.number_of_successful_tokens_);
   EXPECT_EQ(0, consumer_.number_of_errors_);
-  net::TestURLFetcher* fetcher = factory_.GetFetcherByID(0);
-  ASSERT_TRUE(fetcher);
+  EXPECT_EQ(1, test_url_loader_factory_->NumPending());
 
   request.reset();
 
-  fetcher->set_response_code(net::HTTP_OK);
-  fetcher->SetResponseString(GetValidTokenResponse("token", 3600));
-  fetcher->delegate()->OnURLFetchComplete(fetcher);
+  SimulateOAuthTokenResponse(GetValidTokenResponse("token", 3600));
+
   EXPECT_EQ(0, consumer_.number_of_successful_tokens_);
   EXPECT_EQ(0, consumer_.number_of_errors_);
 }
@@ -293,15 +274,11 @@
   oauth2_service_->GetFakeOAuth2TokenServiceDelegate()->UpdateCredentials(
       account_id_, "refreshToken");
 
+  SimulateOAuthTokenResponse(GetValidTokenResponse("token", 3600));
   std::unique_ptr<OAuth2TokenService::Request> request(
       oauth2_service_->StartRequest(account_id_, OAuth2TokenService::ScopeSet(),
                                     &consumer_));
   base::RunLoop().RunUntilIdle();
-  net::TestURLFetcher* fetcher = factory_.GetFetcherByID(0);
-  ASSERT_TRUE(fetcher);
-  fetcher->set_response_code(net::HTTP_OK);
-  fetcher->SetResponseString(GetValidTokenResponse("token", 3600));
-  fetcher->delegate()->OnURLFetchComplete(fetcher);
   EXPECT_EQ(1, consumer_.number_of_successful_tokens_);
   EXPECT_EQ(0, consumer_.number_of_errors_);
   EXPECT_EQ("token", consumer_.last_token_);
@@ -328,11 +305,9 @@
 
   request.reset();
 
-  net::TestURLFetcher* fetcher = factory_.GetFetcherByID(0);
-  ASSERT_TRUE(fetcher);
-  fetcher->set_response_code(net::HTTP_OK);
-  fetcher->SetResponseString(GetValidTokenResponse("token", 3600));
-  fetcher->delegate()->OnURLFetchComplete(fetcher);
+  SimulateOAuthTokenResponse(GetValidTokenResponse("token", 3600));
+  base::RunLoop().RunUntilIdle();
+
   EXPECT_EQ(1, consumer_.number_of_successful_tokens_);
   EXPECT_EQ(0, consumer_.number_of_errors_);
 }
@@ -344,12 +319,8 @@
   std::unique_ptr<OAuth2TokenService::Request> request(
       oauth2_service_->StartRequest(account_id_, OAuth2TokenService::ScopeSet(),
                                     &consumer_));
+  SimulateOAuthTokenResponse(GetValidTokenResponse("token", 3600));
   base::RunLoop().RunUntilIdle();
-  net::TestURLFetcher* fetcher = factory_.GetFetcherByID(0);
-  ASSERT_TRUE(fetcher);
-  fetcher->set_response_code(net::HTTP_OK);
-  fetcher->SetResponseString(GetValidTokenResponse("token", 3600));
-  fetcher->delegate()->OnURLFetchComplete(fetcher);
   EXPECT_EQ(1, consumer_.number_of_successful_tokens_);
   EXPECT_EQ(0, consumer_.number_of_errors_);
   EXPECT_EQ("token", consumer_.last_token_);
@@ -378,8 +349,7 @@
   std::unique_ptr<OAuth2TokenService::Request> request(
       oauth2_service_->StartRequest(account_id_, scopes, &consumer_));
   base::RunLoop().RunUntilIdle();
-  net::TestURLFetcher* fetcher1 = factory_.GetFetcherByID(0);
-  ASSERT_TRUE(fetcher1);
+  ASSERT_EQ(1, test_url_loader_factory_->NumPending());
 
   // Note |request| is still pending when the refresh token changes.
   oauth2_service_->GetFakeOAuth2TokenServiceDelegate()->UpdateCredentials(
@@ -392,17 +362,25 @@
       oauth2_service_->StartRequest(account_id_, scopes1, &consumer2));
   base::RunLoop().RunUntilIdle();
 
-  net::TestURLFetcher* fetcher2 = factory_.GetFetcherByID(0);
-  fetcher2->set_response_code(net::HTTP_OK);
-  fetcher2->SetResponseString(GetValidTokenResponse("second token", 3600));
-  fetcher2->delegate()->OnURLFetchComplete(fetcher2);
+  std::vector<network::TestURLLoaderFactory::PendingRequest>* pending_requests =
+      test_url_loader_factory_->pending_requests();
+  ASSERT_EQ(2U, pending_requests->size());
+  network::TestURLLoaderFactory::PendingRequest second_request =
+      std::move((*pending_requests)[1]);
+  network::TestURLLoaderFactory::PendingRequest first_request =
+      std::move((*pending_requests)[0]);
+  pending_requests->clear();
+
+  network::TestURLLoaderFactory::SimulateResponse(
+      std::move(second_request), GetValidTokenResponse("second token", 3600));
+  base::RunLoop().RunUntilIdle();
   EXPECT_EQ(1, consumer2.number_of_successful_tokens_);
   EXPECT_EQ(0, consumer2.number_of_errors_);
   EXPECT_EQ("second token", consumer2.last_token_);
 
-  fetcher1->set_response_code(net::HTTP_OK);
-  fetcher1->SetResponseString(GetValidTokenResponse("first token", 3600));
-  fetcher1->delegate()->OnURLFetchComplete(fetcher1);
+  network::TestURLLoaderFactory::SimulateResponse(
+      std::move(first_request), GetValidTokenResponse("first token", 3600));
+  base::RunLoop().RunUntilIdle();
   EXPECT_EQ(1, consumer_.number_of_successful_tokens_);
   EXPECT_EQ(0, consumer_.number_of_errors_);
   EXPECT_EQ("first token", consumer_.last_token_);
@@ -433,23 +411,11 @@
   std::unique_ptr<OAuth2TokenService::Request> request(
       oauth2_service_->StartRequest(account_id_, OAuth2TokenService::ScopeSet(),
                                     &consumer));
-  base::RunLoop().RunUntilIdle();
   EXPECT_EQ(0, consumer.number_of_successful_tokens_);
   EXPECT_EQ(0, consumer.number_of_errors_);
 
-  net::TestURLFetcher* fetcher = factory_.GetFetcherByID(0);
-  ASSERT_TRUE(fetcher);
-  fetcher->set_response_code(net::HTTP_UNAUTHORIZED);
-  fetcher->SetResponseString(std::string());
-  fetcher->delegate()->OnURLFetchComplete(fetcher);
-  EXPECT_EQ(0, consumer.number_of_successful_tokens_);
-  EXPECT_EQ(1, consumer.number_of_errors_);
-
-  fetcher = factory_.GetFetcherByID(0);
-  ASSERT_TRUE(fetcher);
-  fetcher->set_response_code(net::HTTP_UNAUTHORIZED);
-  fetcher->SetResponseString(std::string());
-  fetcher->delegate()->OnURLFetchComplete(fetcher);
+  SimulateOAuthTokenResponse("", net::HTTP_UNAUTHORIZED);
+  base::RunLoop().RunUntilIdle();
   EXPECT_EQ(0, consumer.number_of_successful_tokens_);
   EXPECT_EQ(2, consumer.number_of_errors_);
 }
@@ -466,11 +432,10 @@
 
   EXPECT_EQ(0, consumer_.number_of_successful_tokens_);
   EXPECT_EQ(0, consumer_.number_of_errors_);
-  net::TestURLFetcher* fetcher = factory_.GetFetcherByID(0);
-  ASSERT_TRUE(fetcher);
-  fetcher->set_response_code(net::HTTP_OK);
-  fetcher->SetResponseString(GetValidTokenResponse("token", 3600));
-  fetcher->delegate()->OnURLFetchComplete(fetcher);
+
+  SimulateOAuthTokenResponse(GetValidTokenResponse("token", 3600));
+  base::RunLoop().RunUntilIdle();
+
   EXPECT_EQ(1, consumer_.number_of_successful_tokens_);
   EXPECT_EQ(0, consumer_.number_of_errors_);
   EXPECT_EQ("token", consumer_.last_token_);
@@ -486,19 +451,23 @@
   EXPECT_EQ(0, consumer_.number_of_errors_);
   EXPECT_EQ("token", consumer_.last_token_);
 
+  // Clear previous response so the token request will be pending and we can
+  // simulate a response after it started.
+  test_url_loader_factory_->ClearResponses();
+
   // Invalidating the token should return a new token on the next request.
   oauth2_service_->InvalidateAccessToken(account_id_, scopes,
                                          consumer_.last_token_);
   std::unique_ptr<OAuth2TokenService::Request> request3(
       oauth2_service_->StartRequest(account_id_, scopes, &consumer_));
   base::RunLoop().RunUntilIdle();
+
   EXPECT_EQ(2, consumer_.number_of_successful_tokens_);
   EXPECT_EQ(0, consumer_.number_of_errors_);
-  fetcher = factory_.GetFetcherByID(0);
-  ASSERT_TRUE(fetcher);
-  fetcher->set_response_code(net::HTTP_OK);
-  fetcher->SetResponseString(GetValidTokenResponse("token2", 3600));
-  fetcher->delegate()->OnURLFetchComplete(fetcher);
+
+  SimulateOAuthTokenResponse(GetValidTokenResponse("token2", 3600));
+  base::RunLoop().RunUntilIdle();
+
   EXPECT_EQ(3, consumer_.number_of_successful_tokens_);
   EXPECT_EQ(0, consumer_.number_of_errors_);
   EXPECT_EQ("token2", consumer_.last_token_);
@@ -640,12 +609,9 @@
       kEmail, "refreshToken");
   std::unique_ptr<OAuth2TokenService::Request> request(
       oauth2_service_->StartRequest(kEmail, scope_list, &consumer_));
+  SimulateOAuthTokenResponse(GetValidTokenResponse("token", 3600));
   base::RunLoop().RunUntilIdle();
-  net::TestURLFetcher* fetcher = factory_.GetFetcherByID(0);
-  ASSERT_TRUE(fetcher);
-  fetcher->set_response_code(net::HTTP_OK);
-  fetcher->SetResponseString(GetValidTokenResponse("token", 3600));
-  fetcher->delegate()->OnURLFetchComplete(fetcher);
+
   EXPECT_EQ(1, consumer_.number_of_successful_tokens_);
   EXPECT_EQ(0, consumer_.number_of_errors_);
   EXPECT_EQ("token", consumer_.last_token_);
@@ -657,13 +623,9 @@
   EXPECT_EQ(0, (int)oauth2_service_->token_cache_.size());
   oauth2_service_->GetFakeOAuth2TokenServiceDelegate()->UpdateCredentials(
       kEmail, "refreshToken");
+  SimulateOAuthTokenResponse(GetValidTokenResponse("another token", 3600));
   request = oauth2_service_->StartRequest(kEmail, scope_list, &consumer_);
   base::RunLoop().RunUntilIdle();
-  fetcher = factory_.GetFetcherByID(0);
-  // ASSERT_TRUE(fetcher);
-  fetcher->set_response_code(net::HTTP_OK);
-  fetcher->SetResponseString(GetValidTokenResponse("another token", 3600));
-  fetcher->delegate()->OnURLFetchComplete(fetcher);
   EXPECT_EQ(2, consumer_.number_of_successful_tokens_);
   EXPECT_EQ(0, consumer_.number_of_errors_);
   EXPECT_EQ("another token", consumer_.last_token_);
diff --git a/gpu/config/gpu_info.h b/gpu/config/gpu_info.h
index 97cdd5c9..57fb9b9 100644
--- a/gpu/config/gpu_info.h
+++ b/gpu/config/gpu_info.h
@@ -54,8 +54,10 @@
   DOLBYVISION_PROFILE5,
   DOLBYVISION_PROFILE7,
   THEORAPROFILE_ANY,
-  AV1PROFILE_PROFILE0,
-  VIDEO_CODEC_PROFILE_MAX = AV1PROFILE_PROFILE0,
+  AV1PROFILE_PROFILE_MAIN,
+  AV1PROFILE_PROFILE_HIGH,
+  AV1PROFILE_PROFILE_PRO,
+  VIDEO_CODEC_PROFILE_MAX = AV1PROFILE_PROFILE_PRO,
 };
 
 // Specification of a decoding profile supported by a hardware decoder.
diff --git a/gpu/ipc/common/gpu_info.mojom b/gpu/ipc/common/gpu_info.mojom
index 931494c..8add144 100644
--- a/gpu/ipc/common/gpu_info.mojom
+++ b/gpu/ipc/common/gpu_info.mojom
@@ -48,7 +48,9 @@
   DOLBYVISION_PROFILE5,
   DOLBYVISION_PROFILE7,
   THEORAPROFILE_ANY,
-  AV1PROFILE_PROFILE0,
+  AV1PROFILE_PROFILE_MAIN,
+  AV1PROFILE_PROFILE_HIGH,
+  AV1PROFILE_PROFILE_PRO,
 };
 
 // gpu::VideoDecodeAcceleratorSupportedProfile
diff --git a/gpu/ipc/common/gpu_info_struct_traits.cc b/gpu/ipc/common/gpu_info_struct_traits.cc
index f47d7b2..3e7ca57 100644
--- a/gpu/ipc/common/gpu_info_struct_traits.cc
+++ b/gpu/ipc/common/gpu_info_struct_traits.cc
@@ -79,8 +79,12 @@
       return gpu::mojom::VideoCodecProfile::DOLBYVISION_PROFILE7;
     case gpu::VideoCodecProfile::THEORAPROFILE_ANY:
       return gpu::mojom::VideoCodecProfile::THEORAPROFILE_ANY;
-    case gpu::VideoCodecProfile::AV1PROFILE_PROFILE0:
-      return gpu::mojom::VideoCodecProfile::AV1PROFILE_PROFILE0;
+    case gpu::VideoCodecProfile::AV1PROFILE_PROFILE_MAIN:
+      return gpu::mojom::VideoCodecProfile::AV1PROFILE_PROFILE_MAIN;
+    case gpu::VideoCodecProfile::AV1PROFILE_PROFILE_HIGH:
+      return gpu::mojom::VideoCodecProfile::AV1PROFILE_PROFILE_HIGH;
+    case gpu::VideoCodecProfile::AV1PROFILE_PROFILE_PRO:
+      return gpu::mojom::VideoCodecProfile::AV1PROFILE_PROFILE_PRO;
   }
   NOTREACHED() << "Invalid VideoCodecProfile:" << video_codec_profile;
   return gpu::mojom::VideoCodecProfile::VIDEO_CODEC_PROFILE_UNKNOWN;
@@ -166,8 +170,14 @@
     case gpu::mojom::VideoCodecProfile::THEORAPROFILE_ANY:
       *out = gpu::VideoCodecProfile::THEORAPROFILE_ANY;
       return true;
-    case gpu::mojom::VideoCodecProfile::AV1PROFILE_PROFILE0:
-      *out = gpu::VideoCodecProfile::AV1PROFILE_PROFILE0;
+    case gpu::mojom::VideoCodecProfile::AV1PROFILE_PROFILE_MAIN:
+      *out = gpu::VideoCodecProfile::AV1PROFILE_PROFILE_MAIN;
+      return true;
+    case gpu::mojom::VideoCodecProfile::AV1PROFILE_PROFILE_HIGH:
+      *out = gpu::VideoCodecProfile::AV1PROFILE_PROFILE_HIGH;
+      return true;
+    case gpu::mojom::VideoCodecProfile::AV1PROFILE_PROFILE_PRO:
+      *out = gpu::VideoCodecProfile::AV1PROFILE_PROFILE_PRO;
       return true;
   }
   NOTREACHED() << "Invalid VideoCodecProfile: " << input;
diff --git a/gpu/vulkan/generate_bindings.py b/gpu/vulkan/generate_bindings.py
index 41337de..28234d0 100755
--- a/gpu/vulkan/generate_bindings.py
+++ b/gpu/vulkan/generate_bindings.py
@@ -12,7 +12,6 @@
 from subprocess import call
 
 VULKAN_DEVICE_FUNCTIONS = [
-{ 'name': 'vkAcquireNextImageKHR' },
 { 'name': 'vkAllocateCommandBuffers' },
 { 'name': 'vkAllocateDescriptorSets' },
 { 'name': 'vkCreateCommandPool' },
@@ -25,7 +24,6 @@
 { 'name': 'vkCreateSampler' },
 { 'name': 'vkCreateSemaphore' },
 { 'name': 'vkCreateShaderModule' },
-{ 'name': 'vkCreateSwapchainKHR' },
 { 'name': 'vkDestroyCommandPool' },
 { 'name': 'vkDestroyDescriptorPool' },
 { 'name': 'vkDestroyDescriptorSetLayout' },
@@ -37,19 +35,16 @@
 { 'name': 'vkDestroySampler' },
 { 'name': 'vkDestroySemaphore' },
 { 'name': 'vkDestroyShaderModule' },
-{ 'name': 'vkDestroySwapchainKHR' },
 { 'name': 'vkFreeCommandBuffers' },
 { 'name': 'vkFreeDescriptorSets' },
 { 'name': 'vkGetDeviceQueue' },
 { 'name': 'vkGetFenceStatus' },
-{ 'name': 'vkGetSwapchainImagesKHR' },
 { 'name': 'vkResetFences' },
 { 'name': 'vkUpdateDescriptorSets' },
 { 'name': 'vkWaitForFences' },
 ]
 
 VULKAN_QUEUE_FUNCTIONS = [
-{ 'name': 'vkQueuePresentKHR' },
 { 'name': 'vkQueueSubmit' },
 { 'name': 'vkQueueWaitIdle' },
 ]
@@ -65,6 +60,14 @@
 { 'name': 'vkResetCommandBuffer' },
 ]
 
+VULKAN_SWAPCHAIN_FUNCTIONS = [
+{ 'name': 'vkAcquireNextImageKHR' },
+{ 'name': 'vkCreateSwapchainKHR' },
+{ 'name': 'vkDestroySwapchainKHR' },
+{ 'name': 'vkGetSwapchainImagesKHR' },
+{ 'name': 'vkQueuePresentKHR' },
+]
+
 SELF_LOCATION = os.path.dirname(os.path.abspath(__file__))
 
 LICENSE_AND_HEADER = """\
@@ -81,7 +84,7 @@
 """
 
 def GenerateHeaderFile(file, device_functions, queue_functions,
-                       command_buffer_functions):
+                       command_buffer_functions, swapchain_functions):
   """Generates gpu/vulkan/vulkan_function_pointers.h"""
 
   file.write(LICENSE_AND_HEADER +
@@ -105,8 +108,9 @@
   VulkanFunctionPointers();
   ~VulkanFunctionPointers();
 
-  // This function assumes that vkGetDeviceProcAddr has been populated.
+  // These functions assume that vkGetDeviceProcAddr has been populated.
   bool BindDeviceFunctionPointers(VkDevice vk_device);
+  bool BindSwapchainFunctionPointers(VkDevice vk_device);
 
   base::NativeLibrary vulkan_loader_library_ = nullptr;
 
@@ -159,15 +163,19 @@
   for func in command_buffer_functions:
     file.write('  PFN_' + func['name'] + ' ' + func['name'] + ' = nullptr;\n')
 
+  for func in swapchain_functions:
+    file.write('  PFN_' + func['name'] + ' ' + func['name'] + ' = nullptr;\n')
+
   file.write("""\
 };
 
 }  // namespace gpu
 
-#endif  // GPU_VULKAN_VULKAN_FUNCTION_POINTERS_H_""")
+#endif  // GPU_VULKAN_VULKAN_FUNCTION_POINTERS_H_
+""")
 
 def GenerateSourceFile(file, device_functions, queue_functions,
-                       command_buffer_functions):
+                       command_buffer_functions, swapchain_functions):
   """Generates gpu/vulkan/vulkan_function_pointers.cc"""
 
   file.write(LICENSE_AND_HEADER +
@@ -223,7 +231,23 @@
   return true;
 }
 
-}  // namespace gpu""")
+bool VulkanFunctionPointers::BindSwapchainFunctionPointers(VkDevice vk_device) {
+""")
+
+  for func in swapchain_functions:
+    file.write('  ' + func['name'] + ' = reinterpret_cast<PFN_' + func['name'] +
+      '>(vkGetDeviceProcAddr(vk_device, "' + func['name'] + '"));\n')
+    file.write('  if (!' + func['name'] + ')\n')
+    file.write('    return false;\n\n')
+
+  file.write("""\
+
+
+  return true;
+}
+
+}  // namespace gpu
+""")
 
 def main(argv):
   """This is the main function."""
@@ -244,14 +268,16 @@
   header_file = open(
       os.path.join(directory, 'vulkan_function_pointers.h'), 'wb')
   GenerateHeaderFile(header_file, VULKAN_DEVICE_FUNCTIONS,
-                     VULKAN_QUEUE_FUNCTIONS, VULKAN_COMMAND_BUFFER_FUNCTIONS)
+                     VULKAN_QUEUE_FUNCTIONS, VULKAN_COMMAND_BUFFER_FUNCTIONS,
+                     VULKAN_SWAPCHAIN_FUNCTIONS)
   header_file.close()
   ClangFormat(header_file.name)
 
   source_file = open(
       os.path.join(directory, 'vulkan_function_pointers.cc'), 'wb')
   GenerateSourceFile(source_file, VULKAN_DEVICE_FUNCTIONS,
-                     VULKAN_QUEUE_FUNCTIONS, VULKAN_COMMAND_BUFFER_FUNCTIONS)
+                     VULKAN_QUEUE_FUNCTIONS, VULKAN_COMMAND_BUFFER_FUNCTIONS,
+                     VULKAN_SWAPCHAIN_FUNCTIONS)
   source_file.close()
   ClangFormat(source_file.name)
 
diff --git a/gpu/vulkan/vulkan_device_queue.cc b/gpu/vulkan/vulkan_device_queue.cc
index 3ecffb0..034c729 100644
--- a/gpu/vulkan/vulkan_device_queue.cc
+++ b/gpu/vulkan/vulkan_device_queue.cc
@@ -23,6 +23,7 @@
 
 bool VulkanDeviceQueue::Initialize(
     uint32_t options,
+    const std::vector<const char*>& required_extensions,
     const GetPresentationSupportCallback& get_presentation_support) {
   VulkanFunctionPointers* vulkan_function_pointers =
       gpu::GetVulkanFunctionPointers();
@@ -94,8 +95,6 @@
   queue_create_info.queueCount = 1;
   queue_create_info.pQueuePriorities = &queue_priority;
 
-  const char* device_extensions[] = {VK_KHR_SWAPCHAIN_EXTENSION_NAME};
-
   std::vector<const char*> enabled_layer_names;
 #if DCHECK_IS_ON()
   uint32_t num_device_layers = 0;
@@ -125,22 +124,33 @@
   }
 #endif
 
+  std::vector<const char*> enabled_extensions;
+  enabled_extensions.insert(std::end(enabled_extensions),
+                            std::begin(required_extensions),
+                            std::end(required_extensions));
+
   VkDeviceCreateInfo device_create_info = {};
   device_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
   device_create_info.queueCreateInfoCount = 1;
   device_create_info.pQueueCreateInfos = &queue_create_info;
   device_create_info.enabledLayerCount = enabled_layer_names.size();
   device_create_info.ppEnabledLayerNames = enabled_layer_names.data();
-  device_create_info.enabledExtensionCount = arraysize(device_extensions);
-  device_create_info.ppEnabledExtensionNames = device_extensions;
+  device_create_info.enabledExtensionCount = enabled_extensions.size();
+  device_create_info.ppEnabledExtensionNames = enabled_extensions.data();
 
   result = vulkan_function_pointers->vkCreateDevice(
       vk_physical_device_, &device_create_info, nullptr, &vk_device_);
   if (VK_SUCCESS != result)
     return false;
 
+  enabled_extensions_ = gfx::ExtensionSet(std::begin(enabled_extensions),
+                                          std::end(enabled_extensions));
+
   vulkan_function_pointers->BindDeviceFunctionPointers(vk_device_);
 
+  if (gfx::HasExtension(enabled_extensions_, VK_KHR_SWAPCHAIN_EXTENSION_NAME))
+    vulkan_function_pointers->BindSwapchainFunctionPointers(vk_device_);
+
   vulkan_function_pointers->vkGetDeviceQueue(vk_device_, queue_index, 0,
                                              &vk_queue_);
 
diff --git a/gpu/vulkan/vulkan_device_queue.h b/gpu/vulkan/vulkan_device_queue.h
index c4b54d66..5d5b8fb6 100644
--- a/gpu/vulkan/vulkan_device_queue.h
+++ b/gpu/vulkan/vulkan_device_queue.h
@@ -13,6 +13,7 @@
 #include "base/logging.h"
 #include "base/macros.h"
 #include "gpu/vulkan/vulkan_export.h"
+#include "ui/gfx/extension_set.h"
 
 namespace gpu {
 
@@ -34,8 +35,13 @@
                                    uint32_t queue_family_index)>;
   bool Initialize(
       uint32_t options,
+      const std::vector<const char*>& required_extensions,
       const GetPresentationSupportCallback& get_presentation_support);
 
+  const gfx::ExtensionSet& enabled_extensions() const {
+    return enabled_extensions_;
+  }
+
   void Destroy();
 
   VkPhysicalDevice GetVulkanPhysicalDevice() const {
@@ -61,6 +67,7 @@
   std::unique_ptr<gpu::VulkanCommandPool> CreateCommandPool();
 
  private:
+  gfx::ExtensionSet enabled_extensions_;
   VkPhysicalDevice vk_physical_device_ = VK_NULL_HANDLE;
   VkDevice vk_device_ = VK_NULL_HANDLE;
   VkQueue vk_queue_ = VK_NULL_HANDLE;
diff --git a/gpu/vulkan/vulkan_function_pointers.cc b/gpu/vulkan/vulkan_function_pointers.cc
index d8cde1a..66d2ea4b 100644
--- a/gpu/vulkan/vulkan_function_pointers.cc
+++ b/gpu/vulkan/vulkan_function_pointers.cc
@@ -24,11 +24,6 @@
 
 bool VulkanFunctionPointers::BindDeviceFunctionPointers(VkDevice vk_device) {
   // Device functions
-  vkAcquireNextImageKHR = reinterpret_cast<PFN_vkAcquireNextImageKHR>(
-      vkGetDeviceProcAddr(vk_device, "vkAcquireNextImageKHR"));
-  if (!vkAcquireNextImageKHR)
-    return false;
-
   vkAllocateCommandBuffers = reinterpret_cast<PFN_vkAllocateCommandBuffers>(
       vkGetDeviceProcAddr(vk_device, "vkAllocateCommandBuffers"));
   if (!vkAllocateCommandBuffers)
@@ -90,11 +85,6 @@
   if (!vkCreateShaderModule)
     return false;
 
-  vkCreateSwapchainKHR = reinterpret_cast<PFN_vkCreateSwapchainKHR>(
-      vkGetDeviceProcAddr(vk_device, "vkCreateSwapchainKHR"));
-  if (!vkCreateSwapchainKHR)
-    return false;
-
   vkDestroyCommandPool = reinterpret_cast<PFN_vkDestroyCommandPool>(
       vkGetDeviceProcAddr(vk_device, "vkDestroyCommandPool"));
   if (!vkDestroyCommandPool)
@@ -151,11 +141,6 @@
   if (!vkDestroyShaderModule)
     return false;
 
-  vkDestroySwapchainKHR = reinterpret_cast<PFN_vkDestroySwapchainKHR>(
-      vkGetDeviceProcAddr(vk_device, "vkDestroySwapchainKHR"));
-  if (!vkDestroySwapchainKHR)
-    return false;
-
   vkFreeCommandBuffers = reinterpret_cast<PFN_vkFreeCommandBuffers>(
       vkGetDeviceProcAddr(vk_device, "vkFreeCommandBuffers"));
   if (!vkFreeCommandBuffers)
@@ -176,11 +161,6 @@
   if (!vkGetFenceStatus)
     return false;
 
-  vkGetSwapchainImagesKHR = reinterpret_cast<PFN_vkGetSwapchainImagesKHR>(
-      vkGetDeviceProcAddr(vk_device, "vkGetSwapchainImagesKHR"));
-  if (!vkGetSwapchainImagesKHR)
-    return false;
-
   vkResetFences = reinterpret_cast<PFN_vkResetFences>(
       vkGetDeviceProcAddr(vk_device, "vkResetFences"));
   if (!vkResetFences)
@@ -197,11 +177,6 @@
     return false;
 
   // Queue functions
-  vkQueuePresentKHR = reinterpret_cast<PFN_vkQueuePresentKHR>(
-      vkGetDeviceProcAddr(vk_device, "vkQueuePresentKHR"));
-  if (!vkQueuePresentKHR)
-    return false;
-
   vkQueueSubmit = reinterpret_cast<PFN_vkQueueSubmit>(
       vkGetDeviceProcAddr(vk_device, "vkQueueSubmit"));
   if (!vkQueueSubmit)
@@ -256,4 +231,33 @@
   return true;
 }
 
-}  // namespace gpu
\ No newline at end of file
+bool VulkanFunctionPointers::BindSwapchainFunctionPointers(VkDevice vk_device) {
+  vkAcquireNextImageKHR = reinterpret_cast<PFN_vkAcquireNextImageKHR>(
+      vkGetDeviceProcAddr(vk_device, "vkAcquireNextImageKHR"));
+  if (!vkAcquireNextImageKHR)
+    return false;
+
+  vkCreateSwapchainKHR = reinterpret_cast<PFN_vkCreateSwapchainKHR>(
+      vkGetDeviceProcAddr(vk_device, "vkCreateSwapchainKHR"));
+  if (!vkCreateSwapchainKHR)
+    return false;
+
+  vkDestroySwapchainKHR = reinterpret_cast<PFN_vkDestroySwapchainKHR>(
+      vkGetDeviceProcAddr(vk_device, "vkDestroySwapchainKHR"));
+  if (!vkDestroySwapchainKHR)
+    return false;
+
+  vkGetSwapchainImagesKHR = reinterpret_cast<PFN_vkGetSwapchainImagesKHR>(
+      vkGetDeviceProcAddr(vk_device, "vkGetSwapchainImagesKHR"));
+  if (!vkGetSwapchainImagesKHR)
+    return false;
+
+  vkQueuePresentKHR = reinterpret_cast<PFN_vkQueuePresentKHR>(
+      vkGetDeviceProcAddr(vk_device, "vkQueuePresentKHR"));
+  if (!vkQueuePresentKHR)
+    return false;
+
+  return true;
+}
+
+}  // namespace gpu
diff --git a/gpu/vulkan/vulkan_function_pointers.h b/gpu/vulkan/vulkan_function_pointers.h
index c028b670..418b8ba 100644
--- a/gpu/vulkan/vulkan_function_pointers.h
+++ b/gpu/vulkan/vulkan_function_pointers.h
@@ -26,8 +26,9 @@
   VulkanFunctionPointers();
   ~VulkanFunctionPointers();
 
-  // This function assumes that vkGetDeviceProcAddr has been populated.
+  // These functions assume that vkGetDeviceProcAddr has been populated.
   bool BindDeviceFunctionPointers(VkDevice vk_device);
+  bool BindSwapchainFunctionPointers(VkDevice vk_device);
 
   base::NativeLibrary vulkan_loader_library_ = nullptr;
 
@@ -59,7 +60,6 @@
       vkGetPhysicalDeviceSurfaceCapabilitiesKHR = nullptr;
 
   // Device functions
-  PFN_vkAcquireNextImageKHR vkAcquireNextImageKHR = nullptr;
   PFN_vkAllocateCommandBuffers vkAllocateCommandBuffers = nullptr;
   PFN_vkAllocateDescriptorSets vkAllocateDescriptorSets = nullptr;
   PFN_vkCreateCommandPool vkCreateCommandPool = nullptr;
@@ -72,7 +72,6 @@
   PFN_vkCreateSampler vkCreateSampler = nullptr;
   PFN_vkCreateSemaphore vkCreateSemaphore = nullptr;
   PFN_vkCreateShaderModule vkCreateShaderModule = nullptr;
-  PFN_vkCreateSwapchainKHR vkCreateSwapchainKHR = nullptr;
   PFN_vkDestroyCommandPool vkDestroyCommandPool = nullptr;
   PFN_vkDestroyDescriptorPool vkDestroyDescriptorPool = nullptr;
   PFN_vkDestroyDescriptorSetLayout vkDestroyDescriptorSetLayout = nullptr;
@@ -84,18 +83,15 @@
   PFN_vkDestroySampler vkDestroySampler = nullptr;
   PFN_vkDestroySemaphore vkDestroySemaphore = nullptr;
   PFN_vkDestroyShaderModule vkDestroyShaderModule = nullptr;
-  PFN_vkDestroySwapchainKHR vkDestroySwapchainKHR = nullptr;
   PFN_vkFreeCommandBuffers vkFreeCommandBuffers = nullptr;
   PFN_vkFreeDescriptorSets vkFreeDescriptorSets = nullptr;
   PFN_vkGetDeviceQueue vkGetDeviceQueue = nullptr;
   PFN_vkGetFenceStatus vkGetFenceStatus = nullptr;
-  PFN_vkGetSwapchainImagesKHR vkGetSwapchainImagesKHR = nullptr;
   PFN_vkResetFences vkResetFences = nullptr;
   PFN_vkUpdateDescriptorSets vkUpdateDescriptorSets = nullptr;
   PFN_vkWaitForFences vkWaitForFences = nullptr;
 
   // Queue functions
-  PFN_vkQueuePresentKHR vkQueuePresentKHR = nullptr;
   PFN_vkQueueSubmit vkQueueSubmit = nullptr;
   PFN_vkQueueWaitIdle vkQueueWaitIdle = nullptr;
 
@@ -108,8 +104,13 @@
   PFN_vkCmdPipelineBarrier vkCmdPipelineBarrier = nullptr;
   PFN_vkEndCommandBuffer vkEndCommandBuffer = nullptr;
   PFN_vkResetCommandBuffer vkResetCommandBuffer = nullptr;
+  PFN_vkAcquireNextImageKHR vkAcquireNextImageKHR = nullptr;
+  PFN_vkCreateSwapchainKHR vkCreateSwapchainKHR = nullptr;
+  PFN_vkDestroySwapchainKHR vkDestroySwapchainKHR = nullptr;
+  PFN_vkGetSwapchainImagesKHR vkGetSwapchainImagesKHR = nullptr;
+  PFN_vkQueuePresentKHR vkQueuePresentKHR = nullptr;
 };
 
 }  // namespace gpu
 
-#endif  // GPU_VULKAN_VULKAN_FUNCTION_POINTERS_H_
\ No newline at end of file
+#endif  // GPU_VULKAN_VULKAN_FUNCTION_POINTERS_H_
diff --git a/gpu/vulkan/vulkan_implementation.cc b/gpu/vulkan/vulkan_implementation.cc
index cee1aaf4..c0a54c9 100644
--- a/gpu/vulkan/vulkan_implementation.cc
+++ b/gpu/vulkan/vulkan_implementation.cc
@@ -21,7 +21,10 @@
   auto callback = base::BindRepeating(
       &VulkanImplementation::GetPhysicalDevicePresentationSupport,
       base::Unretained(vulkan_implementation));
-  if (!device_queue->Initialize(option, callback)) {
+  std::vector<const char*> required_extensions =
+      vulkan_implementation->GetRequiredDeviceExtensions();
+  if (!device_queue->Initialize(option, std::move(required_extensions),
+                                callback)) {
     device_queue->Destroy();
     return nullptr;
   }
diff --git a/gpu/vulkan/vulkan_implementation.h b/gpu/vulkan/vulkan_implementation.h
index 9dd4268..064841f 100644
--- a/gpu/vulkan/vulkan_implementation.h
+++ b/gpu/vulkan/vulkan_implementation.h
@@ -37,6 +37,8 @@
       const std::vector<VkQueueFamilyProperties>& queue_family_properties,
       uint32_t queue_family_index) = 0;
 
+  virtual std::vector<const char*> GetRequiredDeviceExtensions() = 0;
+
  private:
   DISALLOW_COPY_AND_ASSIGN(VulkanImplementation);
 };
diff --git a/gpu/vulkan/vulkan_implementation_android.cc b/gpu/vulkan/vulkan_implementation_android.cc
index 885a051..c989e7a 100644
--- a/gpu/vulkan/vulkan_implementation_android.cc
+++ b/gpu/vulkan/vulkan_implementation_android.cc
@@ -16,8 +16,8 @@
 VulkanImplementationAndroid::~VulkanImplementationAndroid() {}
 
 bool VulkanImplementationAndroid::InitializeVulkanInstance() {
-  std::vector<const char*> required_extensions;
-  required_extensions.push_back(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME);
+  std::vector<const char*> required_extensions = {
+      VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_ANDROID_SURFACE_EXTENSION_NAME};
 
   VulkanFunctionPointers* vulkan_function_pointers =
       gpu::GetVulkanFunctionPointers();
@@ -78,4 +78,9 @@
   return true;
 }
 
+std::vector<const char*>
+VulkanImplementationAndroid::GetRequiredDeviceExtensions() {
+  return {VK_KHR_SWAPCHAIN_EXTENSION_NAME};
+}
+
 }  // namespace gpu
diff --git a/gpu/vulkan/vulkan_implementation_android.h b/gpu/vulkan/vulkan_implementation_android.h
index 541431c..efb0f584 100644
--- a/gpu/vulkan/vulkan_implementation_android.h
+++ b/gpu/vulkan/vulkan_implementation_android.h
@@ -28,6 +28,7 @@
       VkPhysicalDevice device,
       const std::vector<VkQueueFamilyProperties>& queue_family_properties,
       uint32_t queue_family_index) override;
+  std::vector<const char*> GetRequiredDeviceExtensions() override;
 
  private:
   VulkanInstance vulkan_instance_;
diff --git a/gpu/vulkan/vulkan_instance.cc b/gpu/vulkan/vulkan_instance.cc
index 16f6421..b53f333 100644
--- a/gpu/vulkan/vulkan_instance.cc
+++ b/gpu/vulkan/vulkan_instance.cc
@@ -88,11 +88,10 @@
   app_info.pApplicationName = "Chromium";
   app_info.apiVersion = VK_MAKE_VERSION(1, 0, 2);
 
-  std::vector<const char*> enabled_ext_names;
-  enabled_ext_names.push_back(VK_KHR_SURFACE_EXTENSION_NAME);
-  enabled_ext_names.insert(std::end(enabled_ext_names),
-                           std::begin(required_extensions),
-                           std::end(required_extensions));
+  std::vector<const char*> enabled_extensions;
+  enabled_extensions.insert(std::end(enabled_extensions),
+                            std::begin(required_extensions),
+                            std::end(required_extensions));
 
   uint32_t num_instance_exts = 0;
   result = vulkan_function_pointers->vkEnumerateInstanceExtensionProperties(
@@ -116,7 +115,7 @@
     if (strcmp(ext_property.extensionName,
                VK_EXT_DEBUG_REPORT_EXTENSION_NAME) == 0) {
       debug_report_enabled_ = true;
-      enabled_ext_names.push_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME);
+      enabled_extensions.push_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME);
     }
   }
 
@@ -158,8 +157,8 @@
   instance_create_info.pApplicationInfo = &app_info;
   instance_create_info.enabledLayerCount = enabled_layer_names.size();
   instance_create_info.ppEnabledLayerNames = enabled_layer_names.data();
-  instance_create_info.enabledExtensionCount = enabled_ext_names.size();
-  instance_create_info.ppEnabledExtensionNames = enabled_ext_names.data();
+  instance_create_info.enabledExtensionCount = enabled_extensions.size();
+  instance_create_info.ppEnabledExtensionNames = enabled_extensions.data();
 
   result = vulkan_function_pointers->vkCreateInstance(&instance_create_info,
                                                       nullptr, &vk_instance_);
@@ -168,6 +167,9 @@
     return false;
   }
 
+  enabled_extensions_ = gfx::ExtensionSet(std::begin(enabled_extensions),
+                                          std::end(enabled_extensions));
+
 #if DCHECK_IS_ON()
   // Register our error logging function.
   if (debug_report_enabled_) {
@@ -215,13 +217,6 @@
   if (!vulkan_function_pointers->vkDestroyInstance)
     return false;
 
-  vulkan_function_pointers->vkDestroySurfaceKHR =
-      reinterpret_cast<PFN_vkDestroySurfaceKHR>(
-          vulkan_function_pointers->vkGetInstanceProcAddr(
-              vk_instance_, "vkDestroySurfaceKHR"));
-  if (!vulkan_function_pointers->vkDestroySurfaceKHR)
-    return false;
-
   vulkan_function_pointers->vkEnumerateDeviceLayerProperties =
       reinterpret_cast<PFN_vkEnumerateDeviceLayerProperties>(
           vulkan_function_pointers->vkGetInstanceProcAddr(
@@ -250,26 +245,35 @@
   if (!vulkan_function_pointers->vkGetPhysicalDeviceQueueFamilyProperties)
     return false;
 
-  vulkan_function_pointers->vkGetPhysicalDeviceSurfaceCapabilitiesKHR =
-      reinterpret_cast<PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR>(
-          vulkan_function_pointers->vkGetInstanceProcAddr(
-              vk_instance_, "vkGetPhysicalDeviceSurfaceCapabilitiesKHR"));
-  if (!vulkan_function_pointers->vkGetPhysicalDeviceSurfaceCapabilitiesKHR)
-    return false;
+  if (gfx::HasExtension(enabled_extensions_, VK_KHR_SURFACE_EXTENSION_NAME)) {
+    vulkan_function_pointers->vkDestroySurfaceKHR =
+        reinterpret_cast<PFN_vkDestroySurfaceKHR>(
+            vulkan_function_pointers->vkGetInstanceProcAddr(
+                vk_instance_, "vkDestroySurfaceKHR"));
+    if (!vulkan_function_pointers->vkDestroySurfaceKHR)
+      return false;
 
-  vulkan_function_pointers->vkGetPhysicalDeviceSurfaceFormatsKHR =
-      reinterpret_cast<PFN_vkGetPhysicalDeviceSurfaceFormatsKHR>(
-          vulkan_function_pointers->vkGetInstanceProcAddr(
-              vk_instance_, "vkGetPhysicalDeviceSurfaceFormatsKHR"));
-  if (!vulkan_function_pointers->vkGetPhysicalDeviceSurfaceFormatsKHR)
-    return false;
+    vulkan_function_pointers->vkGetPhysicalDeviceSurfaceCapabilitiesKHR =
+        reinterpret_cast<PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR>(
+            vulkan_function_pointers->vkGetInstanceProcAddr(
+                vk_instance_, "vkGetPhysicalDeviceSurfaceCapabilitiesKHR"));
+    if (!vulkan_function_pointers->vkGetPhysicalDeviceSurfaceCapabilitiesKHR)
+      return false;
 
-  vulkan_function_pointers->vkGetPhysicalDeviceSurfaceSupportKHR =
-      reinterpret_cast<PFN_vkGetPhysicalDeviceSurfaceSupportKHR>(
-          vulkan_function_pointers->vkGetInstanceProcAddr(
-              vk_instance_, "vkGetPhysicalDeviceSurfaceSupportKHR"));
-  if (!vulkan_function_pointers->vkGetPhysicalDeviceSurfaceSupportKHR)
-    return false;
+    vulkan_function_pointers->vkGetPhysicalDeviceSurfaceFormatsKHR =
+        reinterpret_cast<PFN_vkGetPhysicalDeviceSurfaceFormatsKHR>(
+            vulkan_function_pointers->vkGetInstanceProcAddr(
+                vk_instance_, "vkGetPhysicalDeviceSurfaceFormatsKHR"));
+    if (!vulkan_function_pointers->vkGetPhysicalDeviceSurfaceFormatsKHR)
+      return false;
+
+    vulkan_function_pointers->vkGetPhysicalDeviceSurfaceSupportKHR =
+        reinterpret_cast<PFN_vkGetPhysicalDeviceSurfaceSupportKHR>(
+            vulkan_function_pointers->vkGetInstanceProcAddr(
+                vk_instance_, "vkGetPhysicalDeviceSurfaceSupportKHR"));
+    if (!vulkan_function_pointers->vkGetPhysicalDeviceSurfaceSupportKHR)
+      return false;
+  }
 
   return true;
 }
diff --git a/gpu/vulkan/vulkan_instance.h b/gpu/vulkan/vulkan_instance.h
index 22dadcf..af9f502 100644
--- a/gpu/vulkan/vulkan_instance.h
+++ b/gpu/vulkan/vulkan_instance.h
@@ -11,6 +11,7 @@
 #include "base/logging.h"
 #include "base/macros.h"
 #include "gpu/vulkan/vulkan_export.h"
+#include "ui/gfx/extension_set.h"
 
 namespace gpu {
 
@@ -24,10 +25,15 @@
 
   void Destroy();
 
+  const gfx::ExtensionSet& enabled_extensions() const {
+    return enabled_extensions_;
+  }
+
   VkInstance vk_instance() { return vk_instance_; }
 
  private:
   VkInstance vk_instance_ = VK_NULL_HANDLE;
+  gfx::ExtensionSet enabled_extensions_;
   bool debug_report_enabled_ = false;
 #if DCHECK_IS_ON()
   VkDebugReportCallbackEXT error_callback_ = VK_NULL_HANDLE;
diff --git a/gpu/vulkan/x/vulkan_implementation_x11.cc b/gpu/vulkan/x/vulkan_implementation_x11.cc
index 8ab7297..43d89bdb 100644
--- a/gpu/vulkan/x/vulkan_implementation_x11.cc
+++ b/gpu/vulkan/x/vulkan_implementation_x11.cc
@@ -21,8 +21,8 @@
 VulkanImplementationX11::~VulkanImplementationX11() {}
 
 bool VulkanImplementationX11::InitializeVulkanInstance() {
-  std::vector<const char*> required_extensions;
-  required_extensions.push_back(VK_KHR_XLIB_SURFACE_EXTENSION_NAME);
+  std::vector<const char*> required_extensions = {
+      VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_XLIB_SURFACE_EXTENSION_NAME};
 
   VulkanFunctionPointers* vulkan_function_pointers =
       gpu::GetVulkanFunctionPointers();
@@ -91,4 +91,9 @@
           DefaultVisual(x_display_, DefaultScreen(x_display_))));
 }
 
+std::vector<const char*>
+VulkanImplementationX11::GetRequiredDeviceExtensions() {
+  return {VK_KHR_SWAPCHAIN_EXTENSION_NAME};
+}
+
 }  // namespace gpu
diff --git a/gpu/vulkan/x/vulkan_implementation_x11.h b/gpu/vulkan/x/vulkan_implementation_x11.h
index 4d7798d..5d4f96aa 100644
--- a/gpu/vulkan/x/vulkan_implementation_x11.h
+++ b/gpu/vulkan/x/vulkan_implementation_x11.h
@@ -30,6 +30,7 @@
       VkPhysicalDevice device,
       const std::vector<VkQueueFamilyProperties>& queue_family_properties,
       uint32_t queue_family_index) override;
+  std::vector<const char*> GetRequiredDeviceExtensions() override;
 
  private:
   XDisplay* const x_display_;
diff --git a/infra/config/global/cr-buildbucket.cfg b/infra/config/global/cr-buildbucket.cfg
index 2dd3ebaa..21ac7b05 100644
--- a/infra/config/global/cr-buildbucket.cfg
+++ b/infra/config/global/cr-buildbucket.cfg
@@ -597,21 +597,41 @@
     }
 
     builders {
+      name: "Android FYI 32 dEQP Vk Release (Pixel 2)"
+      mixins: "android-gpu-fyi-ci"
+    }
+
+    builders {
       name: "Android FYI 32 Vk Release (Nexus 5X)"
       mixins: "android-gpu-fyi-ci"
     }
 
     builders {
+      name: "Android FYI 32 Vk Release (Pixel 2)"
+      mixins: "android-gpu-fyi-ci"
+    }
+
+    builders {
       name: "Android FYI 64 dEQP Vk Release (Nexus 5X)"
       mixins: "android-gpu-fyi-ci"
     }
 
     builders {
+      name: "Android FYI 64 dEQP Vk Release (Pixel 2)"
+      mixins: "android-gpu-fyi-ci"
+    }
+
+    builders {
       name: "Android FYI 64 Vk Release (Nexus 5X)"
       mixins: "android-gpu-fyi-ci"
     }
 
     builders {
+      name: "Android FYI 64 Vk Release (Pixel 2)"
+      mixins: "android-gpu-fyi-ci"
+    }
+
+    builders {
       name: "Android FYI dEQP Release (Nexus 5X)"
       mixins: "android-gpu-fyi-ci"
     }
@@ -1738,7 +1758,7 @@
     builders {
       name: "Mac deterministic"
       dimensions: "os:Mac-10.13"
-      dimensions: "cores:4"
+      dimensions: "cores:"
       mixins: "fyi-ci"
       mixins: "deterministic"
     }
@@ -1749,7 +1769,7 @@
     }
     builders {
       name: "Mac Swarm"
-      dimensions: "os:Mac-10.12.2"
+      dimensions: "os:Mac-10.13"
       mixins: "swarm-ci"
     }
     builders {
@@ -1775,7 +1795,6 @@
     builders {
       name: "Linux Swarm"
       dimensions: "os:Ubuntu-14.04"
-      dimensions: "cores:16"
       mixins: "swarm-ci"
     }
     builders {
@@ -1819,7 +1838,7 @@
     builders {
       name: "Mac deterministic (dbg)"
       dimensions: "os:Mac-10.13"
-      dimensions: "cores:4"
+      dimensions: "cores:"
       mixins: "fyi-ci"
       mixins: "deterministic"
     }
diff --git a/infra/config/global/luci-milo.cfg b/infra/config/global/luci-milo.cfg
index bee39621..933eca24 100644
--- a/infra/config/global/luci-milo.cfg
+++ b/infra/config/global/luci-milo.cfg
@@ -605,46 +605,55 @@
   }
   builders {
     name: "buildbot/chromium.memory/Linux ChromiumOS MSan Builder"
+    name: "buildbucket/luci.chromium.ci/Linux ChromiumOS MSan Builder"
     category: "chromium.memory|linux|cros"
     short_name: "bld"
   }
   builders {
     name: "buildbot/chromium.memory/Linux ChromiumOS MSan Tests"
+    name: "buildbucket/luci.chromium.ci/Linux ChromiumOS MSan Tests"
     category: "chromium.memory|linux|cros"
     short_name: "tst"
   }
   builders {
     name: "buildbot/chromium.memory/Linux MSan Builder"
+    name: "buildbucket/luci.chromium.ci/Linux MSan Builder"
     category: "chromium.memory|linux|msan"
     short_name: "bld"
   }
   builders {
     name: "buildbot/chromium.memory/Linux MSan Tests"
+    name: "buildbucket/luci.chromium.ci/Linux MSan Tests"
     category: "chromium.memory|linux|msan"
     short_name: "tst"
   }
   builders {
     name: "buildbot/chromium.memory/Linux CFI"
+    name: "buildbucket/luci.chromium.ci/Linux CFI"
     category: "chromium.memory|linux"
     short_name: "cfi"
   }
   builders {
     name: "buildbot/chromium.memory/Mac ASan 64 Builder"
+    name: "buildbucket/luci.chromium.ci/Mac ASan 64 Builder"
     category: "chromium.memory|asan|mac"
     short_name: "bld"
   }
   builders {
     name: "buildbot/chromium.memory/Mac ASan 64 Tests (1)"
+    name: "buildbucket/luci.chromium.ci/Mac ASan 64 Tests (1)"
     category: "chromium.memory|asan|mac"
     short_name: "tst"
   }
   builders {
     name: "buildbot/chromium.memory/Linux Chromium OS ASan LSan Builder"
+    name: "buildbucket/luci.chromium.ci/Linux Chromium OS ASan LSan Builder"
     category: "chromium.memory|asan|cros"
     short_name: "bld"
   }
   builders {
     name: "buildbot/chromium.memory/Linux Chromium OS ASan LSan Tests (1)"
+    name: "buildbucket/luci.chromium.ci/Linux Chromium OS ASan LSan Tests (1)"
     category: "chromium.memory|asan|cros"
     short_name: "tst"
   }
@@ -3249,6 +3258,16 @@
     short_name: "N5X"
   }
   builders {
+    name: "buildbucket/luci.chromium.ci/Android FYI 32 Vk Release (Pixel 2)"
+    category: "Android|vk|P32"
+    short_name: "P2"
+  }
+  builders {
+    name: "buildbucket/luci.chromium.ci/Android FYI 64 Vk Release (Pixel 2)"
+    category: "Android|vk|P64"
+    short_name: "P2"
+  }
+  builders {
     name: "buildbucket/luci.chromium.ci/Android FYI dEQP Release (Nexus 5X)"
     category: "Android|dqp|M64"
     short_name: "N5X"
@@ -3263,6 +3282,16 @@
     category: "Android|dqp|vk|O64"
     short_name: "N5X"
   }
+  builders {
+    name: "buildbucket/luci.chromium.ci/Android FYI 32 dEQP Vk Release (Pixel 2)"
+    category: "Android|dqp|vk|P32"
+    short_name: "P2"
+  }
+  builders {
+    name: "buildbucket/luci.chromium.ci/Android FYI 64 dEQP Vk Release (Pixel 2)"
+    category: "Android|dqp|vk|P64"
+    short_name: "P2"
+  }
 }
 
 consoles {
diff --git a/infra/config/global/luci-scheduler.cfg b/infra/config/global/luci-scheduler.cfg
index 25cfddf8..fba5843 100644
--- a/infra/config/global/luci-scheduler.cfg
+++ b/infra/config/global/luci-scheduler.cfg
@@ -64,9 +64,13 @@
   triggers: "Android CFI"
   triggers: "Android Cronet Builder"
   triggers: "Android FYI 32 Vk Release (Nexus 5X)"
+  triggers: "Android FYI 32 Vk Release (Pixel 2)"
   triggers: "Android FYI 32 dEQP Vk Release (Nexus 5X)"
+  triggers: "Android FYI 32 dEQP Vk Release (Pixel 2)"
   triggers: "Android FYI 64 Vk Release (Nexus 5X)"
+  triggers: "Android FYI 64 Vk Release (Pixel 2)"
   triggers: "Android FYI 64 dEQP Vk Release (Nexus 5X)"
+  triggers: "Android FYI 64 dEQP Vk Release (Pixel 2)"
   triggers: "Android FYI Release (NVIDIA Shield TV)"
   triggers: "Android FYI Release (Nexus 5)"
   triggers: "Android FYI Release (Nexus 5X)"
@@ -301,12 +305,12 @@
 }
 
 job {
-  id: "Android FYI 64 dEQP Vk Release (Nexus 5X)"
+  id: "Android FYI 32 dEQP Vk Release (Pixel 2)"
   acl_sets: "default"
   buildbucket: {
     server: "cr-buildbucket.appspot.com"
     bucket: "luci.chromium.ci"
-    builder: "Android FYI 64 dEQP Vk Release (Nexus 5X)"
+    builder: "Android FYI 32 dEQP Vk Release (Pixel 2)"
   }
 }
 
@@ -321,6 +325,36 @@
 }
 
 job {
+  id: "Android FYI 32 Vk Release (Pixel 2)"
+  acl_sets: "default"
+  buildbucket: {
+    server: "cr-buildbucket.appspot.com"
+    bucket: "luci.chromium.ci"
+    builder: "Android FYI 32 Vk Release (Pixel 2)"
+  }
+}
+
+job {
+  id: "Android FYI 64 dEQP Vk Release (Nexus 5X)"
+  acl_sets: "default"
+  buildbucket: {
+    server: "cr-buildbucket.appspot.com"
+    bucket: "luci.chromium.ci"
+    builder: "Android FYI 64 dEQP Vk Release (Nexus 5X)"
+  }
+}
+
+job {
+  id: "Android FYI 64 dEQP Vk Release (Pixel 2)"
+  acl_sets: "default"
+  buildbucket: {
+    server: "cr-buildbucket.appspot.com"
+    bucket: "luci.chromium.ci"
+    builder: "Android FYI 64 dEQP Vk Release (Pixel 2)"
+  }
+}
+
+job {
   id: "Android FYI 64 Vk Release (Nexus 5X)"
   acl_sets: "default"
   buildbucket: {
@@ -331,6 +365,16 @@
 }
 
 job {
+  id: "Android FYI 64 Vk Release (Pixel 2)"
+  acl_sets: "default"
+  buildbucket: {
+    server: "cr-buildbucket.appspot.com"
+    bucket: "luci.chromium.ci"
+    builder: "Android FYI 64 Vk Release (Pixel 2)"
+  }
+}
+
+job {
   id: "Android FYI dEQP Release (Nexus 5X)"
   acl_sets: "default"
   buildbucket: {
diff --git a/ios/chrome/browser/application_context_impl.cc b/ios/chrome/browser/application_context_impl.cc
index 557f58b..c65c203 100644
--- a/ios/chrome/browser/application_context_impl.cc
+++ b/ios/chrome/browser/application_context_impl.cc
@@ -18,6 +18,7 @@
 #include "base/time/default_clock.h"
 #include "base/time/default_tick_clock.h"
 #include "components/component_updater/component_updater_service.h"
+#include "components/component_updater/timer_update_scheduler.h"
 #include "components/gcm_driver/gcm_client_factory.h"
 #include "components/gcm_driver/gcm_desktop_utils.h"
 #include "components/gcm_driver/gcm_driver.h"
@@ -314,7 +315,8 @@
     // be registered and Start() needs to be called.
     component_updater_ = component_updater::ComponentUpdateServiceFactory(
         component_updater::MakeIOSComponentUpdaterConfigurator(
-            base::CommandLine::ForCurrentProcess()));
+            base::CommandLine::ForCurrentProcess()),
+        std::make_unique<component_updater::TimerUpdateScheduler>());
   }
   return component_updater_.get();
 }
diff --git a/ios/web/web_state/navigation_context_impl_unittest.mm b/ios/web/web_state/navigation_context_impl_unittest.mm
index 59fd758..8a57457 100644
--- a/ios/web/web_state/navigation_context_impl_unittest.mm
+++ b/ios/web/web_state/navigation_context_impl_unittest.mm
@@ -160,7 +160,7 @@
   EXPECT_EQ(WKNavigationTypeOther, context->GetWKNavigationType());
 
   // SetErrorPage
-  NSError* error = [[NSError alloc] init];
+  NSError* error = [[NSError alloc] initWithDomain:@"" code:0 userInfo:nil];
   context->SetError(error);
   EXPECT_EQ(new_url, context->GetUrl());
   EXPECT_TRUE(context->IsSameDocument());
diff --git a/ios/web/web_state/ui/crw_wk_navigation_states_unittest.mm b/ios/web/web_state/ui/crw_wk_navigation_states_unittest.mm
index 78e1709..a326129 100644
--- a/ios/web/web_state/ui/crw_wk_navigation_states_unittest.mm
+++ b/ios/web/web_state/ui/crw_wk_navigation_states_unittest.mm
@@ -122,7 +122,7 @@
           nullptr /*web_state*/, GURL(kTestUrl2), /*has_user_gesture=*/false,
           ui::PageTransition::PAGE_TRANSITION_GENERATED,
           /*is_renderer_initiated=*/true);
-  NSError* error = [[NSError alloc] init];
+  NSError* error = [[NSError alloc] initWithDomain:@"" code:0 userInfo:nil];
   context2->SetError(error);
   [states_ setContext:std::move(context2) forNavigation:navigation1_];
   EXPECT_FALSE([states_ contextForNavigation:navigation2_]);
diff --git a/ios/web_view/internal/signin/ios_web_view_signin_client.mm b/ios/web_view/internal/signin/ios_web_view_signin_client.mm
index 2c4d469..f286122 100644
--- a/ios/web_view/internal/signin/ios_web_view_signin_client.mm
+++ b/ios/web_view/internal/signin/ios_web_view_signin_client.mm
@@ -7,6 +7,7 @@
 #include "components/signin/core/browser/cookie_settings_util.h"
 #include "components/signin/core/browser/signin_cookie_change_subscription.h"
 #include "google_apis/gaia/gaia_auth_fetcher.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
diff --git a/media/base/mime_util_internal.cc b/media/base/mime_util_internal.cc
index 22a0657..9137e88 100644
--- a/media/base/mime_util_internal.cc
+++ b/media/base/mime_util_internal.cc
@@ -783,7 +783,10 @@
         case Codec::AV1: {
 #if BUILDFLAG(ENABLE_AV1_DECODER)
           if (base::FeatureList::IsEnabled(kAv1Decoder)) {
-            out_result->video_profile = AV1PROFILE_PROFILE0;
+            // TODO(dalecurtis): This needs updating to parse the actual profile
+            // from the provided codec string before enabling for release.
+            // http://crbug.com/784607
+            out_result->video_profile = AV1PROFILE_PROFILE_MAIN;
             break;
           }
 #endif
diff --git a/media/base/video_codecs.cc b/media/base/video_codecs.cc
index 4257b52..83421d7 100644
--- a/media/base/video_codecs.cc
+++ b/media/base/video_codecs.cc
@@ -94,8 +94,12 @@
       return "dolby vision profile 7";
     case THEORAPROFILE_ANY:
       return "theora";
-    case AV1PROFILE_PROFILE0:
-      return "av1 profile0";
+    case AV1PROFILE_PROFILE_MAIN:
+      return "av1 profile main";
+    case AV1PROFILE_PROFILE_HIGH:
+      return "av1 profile high";
+    case AV1PROFILE_PROFILE_PRO:
+      return "av1 profile pro";
   }
   NOTREACHED();
   return "";
diff --git a/media/base/video_codecs.h b/media/base/video_codecs.h
index 0788788..edb9228 100644
--- a/media/base/video_codecs.h
+++ b/media/base/video_codecs.h
@@ -88,12 +88,12 @@
   THEORAPROFILE_MIN = 23,
   THEORAPROFILE_ANY = THEORAPROFILE_MIN,
   THEORAPROFILE_MAX = THEORAPROFILE_ANY,
-  // TODO(dalecurtis): AV1 profiles are not finalized, this needs updating
-  // before enabling for release. http://crbug.com/784993
   AV1PROFILE_MIN = 24,
-  AV1PROFILE_PROFILE0 = AV1PROFILE_MIN,
-  AV1PROFILE_MAX = AV1PROFILE_PROFILE0,
-  VIDEO_CODEC_PROFILE_MAX = AV1PROFILE_PROFILE0,
+  AV1PROFILE_PROFILE_MAIN = AV1PROFILE_MIN,
+  AV1PROFILE_PROFILE_HIGH = 25,
+  AV1PROFILE_PROFILE_PRO = 26,
+  AV1PROFILE_MAX = AV1PROFILE_PROFILE_PRO,
+  VIDEO_CODEC_PROFILE_MAX = AV1PROFILE_PROFILE_PRO,
 };
 
 struct CodecProfileLevel {
diff --git a/media/base/video_decoder_config.cc b/media/base/video_decoder_config.cc
index 8d879d7..a9f7d4a 100644
--- a/media/base/video_decoder_config.cc
+++ b/media/base/video_decoder_config.cc
@@ -48,7 +48,9 @@
       return kCodecDolbyVision;
     case THEORAPROFILE_ANY:
       return kCodecTheora;
-    case AV1PROFILE_PROFILE0:
+    case AV1PROFILE_PROFILE_MAIN:
+    case AV1PROFILE_PROFILE_HIGH:
+    case AV1PROFILE_PROFILE_PRO:
       return kCodecAV1;
   }
   NOTREACHED();
diff --git a/media/ffmpeg/ffmpeg_common.cc b/media/ffmpeg/ffmpeg_common.cc
index caa2647c..e299bbf3 100644
--- a/media/ffmpeg/ffmpeg_common.cc
+++ b/media/ffmpeg/ffmpeg_common.cc
@@ -497,7 +497,7 @@
       break;
     case kCodecAV1:
       format = PIXEL_FORMAT_I420;
-      profile = AV1PROFILE_PROFILE0;
+      profile = AV1PROFILE_PROFILE_MAIN;
       break;
 #if BUILDFLAG(ENABLE_HEVC_DEMUXING)
     case kCodecHEVC:
diff --git a/media/filters/chunk_demuxer.cc b/media/filters/chunk_demuxer.cc
index a25c888..4518add 100644
--- a/media/filters/chunk_demuxer.cc
+++ b/media/filters/chunk_demuxer.cc
@@ -52,6 +52,34 @@
     }                                                                   \
   }
 
+namespace {
+
+// Helper to attempt construction of a StreamParser specific to |type| and
+// |codecs|.
+// TODO(wolenetz): Consider relocating this to StreamParserFactory in
+// conjunction with updating StreamParserFactory's isTypeSupported() to also
+// parse codecs, rather than require preparsed vector.
+std::unique_ptr<media::StreamParser> CreateParserForTypeAndCodecs(
+    const std::string& type,
+    const std::string& codecs,
+    media::MediaLog* media_log) {
+  std::vector<std::string> parsed_codec_ids;
+  media::SplitCodecsToVector(codecs, &parsed_codec_ids, false);
+  return media::StreamParserFactory::Create(type, parsed_codec_ids, media_log);
+}
+
+// Helper to calculate the expected codecs parsed from initialization segments
+// for a few mime types that have an implicit codec.
+std::string ExpectedCodecs(const std::string& type, const std::string& codecs) {
+  if (codecs == "" && type == "audio/aac")
+    return "aac";
+  if (codecs == "" && (type == "audio/mpeg" || type == "audio/mp3"))
+    return "mp3";
+  return codecs;
+}
+
+}  // namespace
+
 namespace media {
 
 ChunkDemuxerStream::ChunkDemuxerStream(Type type,
@@ -228,6 +256,7 @@
 }
 
 bool ChunkDemuxerStream::UpdateAudioConfig(const AudioDecoderConfig& config,
+                                           bool allow_codec_change,
                                            MediaLog* media_log) {
   DCHECK(config.IsValidConfig());
   DCHECK_EQ(type_, AUDIO);
@@ -245,10 +274,11 @@
     return true;
   }
 
-  return SBSTREAM_OP(UpdateAudioConfig(config));
+  return SBSTREAM_OP(UpdateAudioConfig(config, allow_codec_change));
 }
 
 bool ChunkDemuxerStream::UpdateVideoConfig(const VideoDecoderConfig& config,
+                                           bool allow_codec_change,
                                            MediaLog* media_log) {
   DCHECK(config.IsValidConfig());
   DCHECK_EQ(type_, VIDEO);
@@ -260,7 +290,7 @@
     return true;
   }
 
-  return SBSTREAM_OP(UpdateVideoConfig(config));
+  return SBSTREAM_OP(UpdateVideoConfig(config, allow_codec_change));
 }
 
 void ChunkDemuxerStream::UpdateTextConfig(const TextTrackConfig& config,
@@ -627,12 +657,8 @@
   // needed. See https://crbug.com/786975.
   CHECK(!init_cb_.is_null());
 
-  std::vector<std::string> parsed_codec_ids;
-  media::SplitCodecsToVector(codecs, &parsed_codec_ids, false);
-
   std::unique_ptr<media::StreamParser> stream_parser(
-      StreamParserFactory::Create(type, parsed_codec_ids, media_log_));
-
+      CreateParserForTypeAndCodecs(type, codecs, media_log_));
   if (!stream_parser) {
     DVLOG(1) << __func__ << " failed: unsupported mime_type=" << type
              << " codecs=" << codecs;
@@ -663,16 +689,10 @@
   CHECK(*insert_result.first == id);
   CHECK(insert_result.second);  // Only true if insertion succeeded.
 
-  std::string expected_sbs_codecs = codecs;
-  if (codecs == "" && type == "audio/aac")
-    expected_sbs_codecs = "aac";
-  if (codecs == "" && (type == "audio/mpeg" || type == "audio/mp3"))
-    expected_sbs_codecs = "mp3";
-
   source_state->Init(base::BindOnce(&ChunkDemuxer::OnSourceInitDone,
                                     base::Unretained(this), id),
-                     expected_sbs_codecs, encrypted_media_init_data_cb_,
-                     new_text_track_cb);
+                     ExpectedCodecs(type, codecs),
+                     encrypted_media_init_data_cb_, new_text_track_cb);
 
   // TODO(wolenetz): Change to DCHECKs once less verification in release build
   // is needed. See https://crbug.com/786975.
@@ -940,6 +960,51 @@
   host_->OnBufferedTimeRangesChanged(GetBufferedRanges_Locked());
 }
 
+bool ChunkDemuxer::CanChangeTypeTo(const std::string& id,
+                                   const std::string& type,
+                                   const std::string& codecs) {
+  // Note, Chromium currently will not compare type's codec parameters, if any,
+  // with previous type of the SourceBuffer.
+  // TODO(wolenetz): Consider returning false if the codec parameters
+  // are ever made to be precise such that they signal number of tracks of
+  // various media types differ from the first initialization segment (if
+  // received already). Switching to an audio-only container, when the first
+  // initialization segment only contained non-audio tracks, is one example we
+  // could enforce earlier here.
+
+  DVLOG(1) << __func__ << " id=" << id << " mime_type=" << type
+           << " codecs=" << codecs;
+  base::AutoLock auto_lock(lock_);
+
+  DCHECK(IsValidId(id));
+
+  // CanChangeType() doesn't care if there has or hasn't been received a first
+  // initialization segment for the source buffer corresponding to |id|.
+
+  std::unique_ptr<media::StreamParser> stream_parser(
+      CreateParserForTypeAndCodecs(type, codecs, media_log_));
+  return !!stream_parser;
+}
+
+void ChunkDemuxer::ChangeType(const std::string& id,
+                              const std::string& type,
+                              const std::string& codecs) {
+  DVLOG(1) << __func__ << " id=" << id << " mime_type=" << type
+           << " codecs=" << codecs;
+
+  base::AutoLock auto_lock(lock_);
+
+  DCHECK(state_ == INITIALIZING || state_ == INITIALIZED) << state_;
+  DCHECK(IsValidId(id));
+
+  std::unique_ptr<media::StreamParser> stream_parser(
+      CreateParserForTypeAndCodecs(type, codecs, media_log_));
+  // Caller should query CanChangeType() first to protect from failing this.
+  DCHECK(stream_parser);
+  source_state_map_[id]->ChangeType(std::move(stream_parser),
+                                    ExpectedCodecs(type, codecs));
+}
+
 double ChunkDemuxer::GetDuration() {
   base::AutoLock auto_lock(lock_);
   return GetDuration_Locked();
diff --git a/media/filters/chunk_demuxer.h b/media/filters/chunk_demuxer.h
index 8554705..15f586d 100644
--- a/media/filters/chunk_demuxer.h
+++ b/media/filters/chunk_demuxer.h
@@ -103,10 +103,16 @@
                                 base::TimeDelta start_pts);
 
   // Called when midstream config updates occur.
+  // For audio and video, if the codec is allowed to change, the caller should
+  // set |allow_codec_change| to true.
   // Returns true if the new config is accepted.
   // Returns false if the new config should trigger an error.
-  bool UpdateAudioConfig(const AudioDecoderConfig& config, MediaLog* media_log);
-  bool UpdateVideoConfig(const VideoDecoderConfig& config, MediaLog* media_log);
+  bool UpdateAudioConfig(const AudioDecoderConfig& config,
+                         bool allow_codec_change,
+                         MediaLog* media_log);
+  bool UpdateVideoConfig(const VideoDecoderConfig& config,
+                         bool allow_codec_change,
+                         MediaLog* media_log);
   void UpdateTextConfig(const TextTrackConfig& config, MediaLog* media_log);
 
   void MarkEndOfStream();
@@ -283,6 +289,23 @@
   void Remove(const std::string& id, base::TimeDelta start,
               base::TimeDelta end);
 
+  // Returns whether or not the source buffer associated with |id| can change
+  // its parser type to one which parses |type| and |codecs|.  |type| indicates
+  // the MIME type for the data that we intend to append for this |id|.
+  bool CanChangeTypeTo(const std::string& id,
+                       const std::string& type,
+                       const std::string& codecs);
+
+  // For the source buffer associated with |id|, changes its parser type to one
+  // which parses |type| and |codecs|.  |type| indicates the MIME type for the
+  // data that we intend to append for this |id|.  Caller must first ensure
+  // CanChangeTypeTo() returns true for the same parameters.  Caller must also
+  // ensure that ResetParserState() is done before calling this, to flush any
+  // pending frames.
+  void ChangeType(const std::string& id,
+                  const std::string& type,
+                  const std::string& codecs);
+
   // If the buffer is full, attempts to try to free up space, as specified in
   // the "Coded Frame Eviction Algorithm" in the Media Source Extensions Spec.
   // Returns false iff buffer is still full after running eviction.
diff --git a/media/filters/frame_processor_unittest.cc b/media/filters/frame_processor_unittest.cc
index 837973c..0989f0e 100644
--- a/media/filters/frame_processor_unittest.cc
+++ b/media/filters/frame_processor_unittest.cc
@@ -352,15 +352,16 @@
                                           CHANNEL_LAYOUT_STEREO, 1000,
                                           EmptyExtraData(), Unencrypted());
         frame_processor_->OnPossibleAudioConfigUpdate(decoder_config);
-        ASSERT_TRUE(audio_->UpdateAudioConfig(decoder_config, &media_log_));
+        ASSERT_TRUE(
+            audio_->UpdateAudioConfig(decoder_config, false, &media_log_));
         break;
       }
       case DemuxerStream::VIDEO: {
         ASSERT_FALSE(video_);
         video_.reset(
             new ChunkDemuxerStream(DemuxerStream::VIDEO, "2", range_api_));
-        ASSERT_TRUE(
-            video_->UpdateVideoConfig(TestVideoConfig::Normal(), &media_log_));
+        ASSERT_TRUE(video_->UpdateVideoConfig(TestVideoConfig::Normal(), false,
+                                              &media_log_));
         break;
       }
       // TODO(wolenetz): Test text coded frame processing.
diff --git a/media/filters/source_buffer_state.cc b/media/filters/source_buffer_state.cc
index 9e57f7f1..2c86688c 100644
--- a/media/filters/source_buffer_state.cc
+++ b/media/filters/source_buffer_state.cc
@@ -155,42 +155,24 @@
   init_cb_ = std::move(init_cb);
   encrypted_media_init_data_cb_ = encrypted_media_init_data_cb;
   new_text_track_cb_ = new_text_track_cb;
-
-  std::vector<std::string> expected_codecs_parsed;
-  SplitCodecsToVector(expected_codecs, &expected_codecs_parsed, false);
-
-  std::vector<AudioCodec> expected_acodecs;
-  std::vector<VideoCodec> expected_vcodecs;
-  for (const auto& codec_id : expected_codecs_parsed) {
-    AudioCodec acodec = StringToAudioCodec(codec_id);
-    if (acodec != kUnknownAudioCodec) {
-      expected_audio_codecs_.push_back(acodec);
-      continue;
-    }
-    VideoCodec vcodec = StringToVideoCodec(codec_id);
-    if (vcodec != kUnknownVideoCodec) {
-      expected_video_codecs_.push_back(vcodec);
-      continue;
-    }
-    MEDIA_LOG(INFO, media_log_) << "Unrecognized media codec: " << codec_id;
-  }
-
   state_ = PENDING_PARSER_CONFIG;
-  stream_parser_->Init(
-      base::BindOnce(&SourceBufferState::OnSourceInitDone,
-                     base::Unretained(this)),
-      base::BindRepeating(&SourceBufferState::OnNewConfigs,
-                          base::Unretained(this), expected_codecs),
-      base::BindRepeating(&SourceBufferState::OnNewBuffers,
-                          base::Unretained(this)),
-      new_text_track_cb_.is_null(),
-      base::BindRepeating(&SourceBufferState::OnEncryptedMediaInitData,
-                          base::Unretained(this)),
-      base::BindRepeating(&SourceBufferState::OnNewMediaSegment,
-                          base::Unretained(this)),
-      base::BindRepeating(&SourceBufferState::OnEndOfMediaSegment,
-                          base::Unretained(this)),
-      media_log_);
+  InitializeParser(expected_codecs);
+}
+
+void SourceBufferState::ChangeType(
+    std::unique_ptr<StreamParser> new_stream_parser,
+    const std::string& new_expected_codecs) {
+  DCHECK_GE(state_, PENDING_PARSER_CONFIG);
+  DCHECK_NE(state_, PENDING_PARSER_INIT);
+  DCHECK(!parsing_media_segment_);
+
+  // If this source buffer has already handled an initialization segment, avoid
+  // running |init_cb_| again later.
+  if (state_ == PARSER_INITIALIZED)
+    state_ = PENDING_PARSER_RECONFIG;
+
+  stream_parser_ = std::move(new_stream_parser);
+  InitializeParser(new_expected_codecs);
 }
 
 void SourceBufferState::SetSequenceMode(bool sequence_mode) {
@@ -558,6 +540,46 @@
   return false;
 }
 
+void SourceBufferState::InitializeParser(const std::string& expected_codecs) {
+  expected_audio_codecs_.clear();
+  expected_video_codecs_.clear();
+
+  std::vector<std::string> expected_codecs_parsed;
+  SplitCodecsToVector(expected_codecs, &expected_codecs_parsed, false);
+
+  std::vector<AudioCodec> expected_acodecs;
+  std::vector<VideoCodec> expected_vcodecs;
+  for (const auto& codec_id : expected_codecs_parsed) {
+    AudioCodec acodec = StringToAudioCodec(codec_id);
+    if (acodec != kUnknownAudioCodec) {
+      expected_audio_codecs_.push_back(acodec);
+      continue;
+    }
+    VideoCodec vcodec = StringToVideoCodec(codec_id);
+    if (vcodec != kUnknownVideoCodec) {
+      expected_video_codecs_.push_back(vcodec);
+      continue;
+    }
+    MEDIA_LOG(INFO, media_log_) << "Unrecognized media codec: " << codec_id;
+  }
+
+  stream_parser_->Init(
+      base::BindOnce(&SourceBufferState::OnSourceInitDone,
+                     base::Unretained(this)),
+      base::BindRepeating(&SourceBufferState::OnNewConfigs,
+                          base::Unretained(this), expected_codecs),
+      base::BindRepeating(&SourceBufferState::OnNewBuffers,
+                          base::Unretained(this)),
+      new_text_track_cb_.is_null(),
+      base::BindRepeating(&SourceBufferState::OnEncryptedMediaInitData,
+                          base::Unretained(this)),
+      base::BindRepeating(&SourceBufferState::OnNewMediaSegment,
+                          base::Unretained(this)),
+      base::BindRepeating(&SourceBufferState::OnEndOfMediaSegment,
+                          base::Unretained(this)),
+      media_log_);
+}
+
 bool SourceBufferState::OnNewConfigs(
     std::string expected_codecs,
     std::unique_ptr<MediaTracks> tracks,
@@ -589,6 +611,11 @@
   std::vector<AudioCodec> expected_acodecs = expected_audio_codecs_;
   std::vector<VideoCodec> expected_vcodecs = expected_video_codecs_;
 
+  // TODO(wolenetz): Once codec strictness is relaxed, we can change
+  // |allow_codec_changes| to always be true. Until then, we only allow codec
+  // changes on explicit ChangeType().
+  const bool allow_codec_changes = state_ == PENDING_PARSER_RECONFIG;
+
   FrameProcessor::TrackIdChanges track_id_changes;
   for (const auto& track : tracks->tracks()) {
     const auto& track_id = track->bytestream_track_id();
@@ -648,7 +675,8 @@
 
       track->set_id(stream->media_track_id());
       frame_processor_->OnPossibleAudioConfigUpdate(audio_config);
-      success &= stream->UpdateAudioConfig(audio_config, media_log_);
+      success &= stream->UpdateAudioConfig(audio_config, allow_codec_changes,
+                                           media_log_);
     } else if (track->type() == MediaTrack::Video) {
       VideoDecoderConfig video_config = tracks->getVideoConfig(track_id);
       DVLOG(1) << "Video track_id=" << track_id
@@ -703,7 +731,8 @@
       }
 
       track->set_id(stream->media_track_id());
-      success &= stream->UpdateVideoConfig(video_config, media_log_);
+      success &= stream->UpdateVideoConfig(video_config, allow_codec_changes,
+                                           media_log_);
     } else {
       MEDIA_LOG(ERROR, media_log_) << "Error: unsupported media track type "
                                    << track->type();
@@ -811,6 +840,8 @@
   if (success) {
     if (state_ == PENDING_PARSER_CONFIG)
       state_ = PENDING_PARSER_INIT;
+    if (state_ == PENDING_PARSER_RECONFIG)
+      state_ = PENDING_PARSER_REINIT;
     DCHECK(!init_segment_received_cb_.is_null());
     init_segment_received_cb_.Run(std::move(tracks));
   }
@@ -935,9 +966,15 @@
 
 void SourceBufferState::OnSourceInitDone(
     const StreamParser::InitParameters& params) {
-  DCHECK_EQ(state_, PENDING_PARSER_INIT);
+  // We've either yet-to-run |init_cb_| if pending init, or we've previously
+  // run it if pending reinit.
+  DCHECK((!init_cb_.is_null() && state_ == PENDING_PARSER_INIT) ||
+         (init_cb_.is_null() && state_ == PENDING_PARSER_REINIT));
+  State old_state = state_;
   state_ = PARSER_INITIALIZED;
-  std::move(init_cb_).Run(params);
+
+  if (old_state == PENDING_PARSER_INIT)
+    std::move(init_cb_).Run(params);
 }
 
 }  // namespace media
diff --git a/media/filters/source_buffer_state.h b/media/filters/source_buffer_state.h
index 3c5986f..7bac0c56 100644
--- a/media/filters/source_buffer_state.h
+++ b/media/filters/source_buffer_state.h
@@ -50,6 +50,12 @@
                 encrypted_media_init_data_cb,
             const NewTextTrackCB& new_text_track_cb);
 
+  // Reconfigures this source buffer to use |new_stream_parser|. Caller must
+  // first ensure that ResetParserState() was done to flush any pending frames
+  // from the old stream parser.
+  void ChangeType(std::unique_ptr<StreamParser> new_stream_parser,
+                  const std::string& new_expected_codecs);
+
   // Appends new data to the StreamParser.
   // Returns true if the data was successfully appended. Returns false if an
   // error occurred. |*timestamp_offset| is used and possibly updated by the
@@ -145,16 +151,30 @@
       const SourceBufferParseWarningCB& parse_warning_cb);
 
  private:
-  // State advances through this list. The intent is to ensure at least one
-  // config is received prior to parser calling initialization callback, and
-  // that such initialization callback occurs at most once per parser.
+  // State advances through this list to PARSER_INITIALIZED.
+  // The intent is to ensure at least one config is received prior to parser
+  // calling initialization callback, and that such initialization callback
+  // occurs at most once per parser.
+  // PENDING_PARSER_RECONFIG occurs if State had reached PARSER_INITIALIZED
+  // before changing to a new StreamParser in ChangeType(). In such case, State
+  // would then advance to PENDING_PARSER_REINIT, then PARSER_INITIALIZED upon
+  // the next initialization segment parsed, but would not run the
+  // initialization callback in this case (since such would already have
+  // occurred on the initial transition from PENDING_PARSER_INIT to
+  // PARSER_INITIALIZED.)
   enum State {
     UNINITIALIZED = 0,
     PENDING_PARSER_CONFIG,
     PENDING_PARSER_INIT,
-    PARSER_INITIALIZED
+    PARSER_INITIALIZED,
+    PENDING_PARSER_RECONFIG,
+    PENDING_PARSER_REINIT
   };
 
+  // Initializes |stream_parser_|. Also, updates |expected_audio_codecs| and
+  // |expected_video_codecs|.
+  void InitializeParser(const std::string& expected_codecs);
+
   // Called by the |stream_parser_| when a new initialization segment is
   // encountered.
   // Returns true on a successful call. Returns false if an error occurred while
diff --git a/media/filters/source_buffer_stream.cc b/media/filters/source_buffer_stream.cc
index d8d17d7..8b01731 100644
--- a/media/filters/source_buffer_stream.cc
+++ b/media/filters/source_buffer_stream.cc
@@ -1976,13 +1976,21 @@
 
 template <typename RangeClass>
 bool SourceBufferStream<RangeClass>::UpdateAudioConfig(
-    const AudioDecoderConfig& config) {
+    const AudioDecoderConfig& config,
+    bool allow_codec_change) {
   DCHECK(!audio_configs_.empty());
   DCHECK(video_configs_.empty());
   DVLOG(3) << "UpdateAudioConfig.";
 
-  if (audio_configs_[0].codec() != config.codec()) {
-    MEDIA_LOG(ERROR, media_log_) << "Audio codec changes not allowed.";
+  if (!allow_codec_change &&
+      audio_configs_[append_config_index_].codec() != config.codec()) {
+    // TODO(wolenetz): When we relax addSourceBuffer() and changeType() codec
+    // strictness, codec changes should be allowed even without changing the
+    // bytestream.
+    // TODO(wolenetz): Remove "experimental" from this error message when
+    // changeType() ships without needing experimental blink flag.
+    MEDIA_LOG(ERROR, media_log_) << "Audio codec changes not allowed unless "
+                                    "using experimental changeType().";
     return false;
   }
 
@@ -2004,13 +2012,21 @@
 
 template <typename RangeClass>
 bool SourceBufferStream<RangeClass>::UpdateVideoConfig(
-    const VideoDecoderConfig& config) {
+    const VideoDecoderConfig& config,
+    bool allow_codec_change) {
   DCHECK(!video_configs_.empty());
   DCHECK(audio_configs_.empty());
   DVLOG(3) << "UpdateVideoConfig.";
 
-  if (video_configs_[0].codec() != config.codec()) {
-    MEDIA_LOG(ERROR, media_log_) << "Video codec changes not allowed.";
+  if (!allow_codec_change &&
+      video_configs_[append_config_index_].codec() != config.codec()) {
+    // TODO(wolenetz): When we relax addSourceBuffer() and changeType() codec
+    // strictness, codec changes should be allowed even without changing the
+    // bytestream.
+    // TODO(wolenetz): Remove "experimental" from this error message when
+    // changeType() ships without needing experimental blink flag.
+    MEDIA_LOG(ERROR, media_log_) << "Video codec changes not allowed unless "
+                                    "using experimental changeType()";
     return false;
   }
 
diff --git a/media/filters/source_buffer_stream.h b/media/filters/source_buffer_stream.h
index a50e7c36..590d88d 100644
--- a/media/filters/source_buffer_stream.h
+++ b/media/filters/source_buffer_stream.h
@@ -164,11 +164,17 @@
 
   // Notifies this object that the audio config has changed and buffers in
   // future Append() calls should be associated with this new config.
-  bool UpdateAudioConfig(const AudioDecoderConfig& config);
+  // If the codec is allowed to change, the caller should set
+  // |allow_codec_change| to true.
+  bool UpdateAudioConfig(const AudioDecoderConfig& config,
+                         bool allow_codec_change);
 
   // Notifies this object that the video config has changed and buffers in
   // future Append() calls should be associated with this new config.
-  bool UpdateVideoConfig(const VideoDecoderConfig& config);
+  // If the codec is allowed to change, the caller should set
+  // |allow_codec_change| to true.
+  bool UpdateVideoConfig(const VideoDecoderConfig& config,
+                         bool allow_codec_change);
 
   // Returns the largest distance between two adjacent buffers in this stream,
   // or an estimate if no two adjacent buffers have been appended to the stream
diff --git a/media/filters/source_buffer_stream_unittest.cc b/media/filters/source_buffer_stream_unittest.cc
index 0d1b79a..9b57c0a 100644
--- a/media/filters/source_buffer_stream_unittest.cc
+++ b/media/filters/source_buffer_stream_unittest.cc
@@ -3472,7 +3472,7 @@
   CheckVideoConfig(video_config_);
 
   // Signal a config change.
-  STREAM_OP(UpdateVideoConfig(new_config));
+  STREAM_OP(UpdateVideoConfig(new_config, false));
 
   // Make sure updating the config doesn't change anything since new_config
   // should not be associated with the buffer GetNextBuffer() will return.
@@ -3508,7 +3508,7 @@
 
   Seek(0);
   NewCodedFrameGroupAppend(0, 5, &kDataA);
-  STREAM_OP(UpdateVideoConfig(new_config));
+  STREAM_OP(UpdateVideoConfig(new_config, false));
   NewCodedFrameGroupAppend(5, 5, &kDataB);
 
   // Seek to the start of the buffers with the new config and make sure a
@@ -4709,7 +4709,7 @@
   NewCodedFrameGroupAppend("0K 3K 6K");
 
   // Update the configuration.
-  STREAM_OP(UpdateAudioConfig(new_config));
+  STREAM_OP(UpdateAudioConfig(new_config, false));
 
   // We haven't read any buffers at this point, so the config for the next
   // buffer at time 0 should still be the original config.
@@ -4969,7 +4969,7 @@
   // Append a few buffers, with a config change in the middle.
   VideoDecoderConfig new_config = TestVideoConfig::Large();
   NewCodedFrameGroupAppend("2000K 2010 2020D10");
-  STREAM_OP(UpdateVideoConfig(new_config));
+  STREAM_OP(UpdateVideoConfig(new_config, false));
   NewCodedFrameGroupAppend("2030K 2040 2050D10");
   CheckExpectedRangesByTimestamp("{ [2000,2060) }");
 
diff --git a/media/formats/mp4/box_definitions.cc b/media/formats/mp4/box_definitions.cc
index a9f747e..800fb69 100644
--- a/media/formats/mp4/box_definitions.cc
+++ b/media/formats/mp4/box_definitions.cc
@@ -842,12 +842,11 @@
 #if BUILDFLAG(ENABLE_AV1_DECODER)
     case FOURCC_AV01: {
       DVLOG(2) << __func__ << " reading AV1 configuration.";
-      // TODO(dalecurtis): AV1 profiles are not finalized, this needs updating
-      // to read the actual profile and configuration before enabling for
-      // release. http://crbug.com/784993
+      // TODO(dalecurtis): This needs updating to read the actual profile and
+      // configuration before enabling for release. http://crbug.com/784993
       frame_bitstream_converter = nullptr;
       video_codec = kCodecAV1;
-      video_codec_profile = AV1PROFILE_PROFILE0;
+      video_codec_profile = AV1PROFILE_PROFILE_MAIN;
       break;
     }
 #endif
diff --git a/media/formats/webm/webm_video_client.cc b/media/formats/webm/webm_video_client.cc
index 61bc28ed..813a086 100644
--- a/media/formats/webm/webm_video_client.cc
+++ b/media/formats/webm/webm_video_client.cc
@@ -66,11 +66,11 @@
     profile = GetVP9CodecProfile(codec_private);
 #if BUILDFLAG(ENABLE_AV1_DECODER)
   } else if (codec_id == "V_AV1") {
-    // TODO(dalecurtis): AV1 profiles are not finalized, this needs updating
-    // to read the actual profile and configuration before enabling for
+    // TODO(dalecurtis): AV1 profiles in WebM are not finalized, this needs
+    // updating to read the actual profile and configuration before enabling for
     // release. http://crbug.com/784993
     video_codec = kCodecAV1;
-    profile = AV1PROFILE_PROFILE0;
+    profile = AV1PROFILE_PROFILE_MAIN;
 #endif
   } else {
     MEDIA_LOG(ERROR, media_log_) << "Unsupported video codec_id " << codec_id;
diff --git a/media/gpu/gpu_video_accelerator_util.cc b/media/gpu/gpu_video_accelerator_util.cc
index edd8bb1..0ebcbbfb 100644
--- a/media/gpu/gpu_video_accelerator_util.cc
+++ b/media/gpu/gpu_video_accelerator_util.cc
@@ -33,7 +33,9 @@
 STATIC_ASSERT_ENUM_MATCH(HEVCPROFILE_MAIN);
 STATIC_ASSERT_ENUM_MATCH(HEVCPROFILE_MAIN10);
 STATIC_ASSERT_ENUM_MATCH(HEVCPROFILE_MAIN_STILL_PICTURE);
-STATIC_ASSERT_ENUM_MATCH(AV1PROFILE_PROFILE0);
+STATIC_ASSERT_ENUM_MATCH(AV1PROFILE_PROFILE_MAIN);
+STATIC_ASSERT_ENUM_MATCH(AV1PROFILE_PROFILE_HIGH);
+STATIC_ASSERT_ENUM_MATCH(AV1PROFILE_PROFILE_PRO);
 STATIC_ASSERT_ENUM_MATCH(VIDEO_CODEC_PROFILE_MAX);
 
 // static
diff --git a/media/remoting/proto_enum_utils.cc b/media/remoting/proto_enum_utils.cc
index e16c112..784b1e3 100644
--- a/media/remoting/proto_enum_utils.cc
+++ b/media/remoting/proto_enum_utils.cc
@@ -285,7 +285,9 @@
     CASE_RETURN_OTHER(DOLBYVISION_PROFILE5);
     CASE_RETURN_OTHER(DOLBYVISION_PROFILE7);
     CASE_RETURN_OTHER(THEORAPROFILE_ANY);
-    CASE_RETURN_OTHER(AV1PROFILE_PROFILE0);
+    CASE_RETURN_OTHER(AV1PROFILE_PROFILE_MAIN);
+    CASE_RETURN_OTHER(AV1PROFILE_PROFILE_HIGH);
+    CASE_RETURN_OTHER(AV1PROFILE_PROFILE_PRO);
   }
   return base::nullopt;  // Not a 'default' to ensure compile-time checks.
 }
@@ -320,7 +322,9 @@
     CASE_RETURN_OTHER(DOLBYVISION_PROFILE5);
     CASE_RETURN_OTHER(DOLBYVISION_PROFILE7);
     CASE_RETURN_OTHER(THEORAPROFILE_ANY);
-    CASE_RETURN_OTHER(AV1PROFILE_PROFILE0);
+    CASE_RETURN_OTHER(AV1PROFILE_PROFILE_MAIN);
+    CASE_RETURN_OTHER(AV1PROFILE_PROFILE_HIGH);
+    CASE_RETURN_OTHER(AV1PROFILE_PROFILE_PRO);
   }
   return base::nullopt;  // Not a 'default' to ensure compile-time checks.
 }
diff --git a/media/remoting/rpc.proto b/media/remoting/rpc.proto
index 2893696..66c02a3 100644
--- a/media/remoting/rpc.proto
+++ b/media/remoting/rpc.proto
@@ -186,7 +186,9 @@
     DOLBYVISION_PROFILE5 = 21;
     DOLBYVISION_PROFILE7 = 22;
     THEORAPROFILE_ANY = 23;
-    AV1PROFILE_PROFILE0 = 24;
+    AV1PROFILE_PROFILE_MAIN = 24;
+    AV1PROFILE_PROFILE_HIGH = 25;
+    AV1PROFILE_PROFILE_PRO = 26;
   };
 
   // Proto version of media::VideoPixelFormat.
diff --git a/net/BUILD.gn b/net/BUILD.gn
index 3833b66..faa1f0f1 100644
--- a/net/BUILD.gn
+++ b/net/BUILD.gn
@@ -1467,50 +1467,6 @@
       "third_party/quic/core/tls_handshaker.h",
       "third_party/quic/core/tls_server_handshaker.cc",
       "third_party/quic/core/tls_server_handshaker.h",
-      "third_party/quic/http/decoder/payload_decoders/quic_http_altsvc_payload_decoder.cc",
-      "third_party/quic/http/decoder/payload_decoders/quic_http_altsvc_payload_decoder.h",
-      "third_party/quic/http/decoder/payload_decoders/quic_http_continuation_payload_decoder.cc",
-      "third_party/quic/http/decoder/payload_decoders/quic_http_continuation_payload_decoder.h",
-      "third_party/quic/http/decoder/payload_decoders/quic_http_data_payload_decoder.cc",
-      "third_party/quic/http/decoder/payload_decoders/quic_http_data_payload_decoder.h",
-      "third_party/quic/http/decoder/payload_decoders/quic_http_goaway_payload_decoder.cc",
-      "third_party/quic/http/decoder/payload_decoders/quic_http_goaway_payload_decoder.h",
-      "third_party/quic/http/decoder/payload_decoders/quic_http_headers_payload_decoder.cc",
-      "third_party/quic/http/decoder/payload_decoders/quic_http_headers_payload_decoder.h",
-      "third_party/quic/http/decoder/payload_decoders/quic_http_ping_payload_decoder.cc",
-      "third_party/quic/http/decoder/payload_decoders/quic_http_ping_payload_decoder.h",
-      "third_party/quic/http/decoder/payload_decoders/quic_http_priority_payload_decoder.cc",
-      "third_party/quic/http/decoder/payload_decoders/quic_http_priority_payload_decoder.h",
-      "third_party/quic/http/decoder/payload_decoders/quic_http_push_promise_payload_decoder.cc",
-      "third_party/quic/http/decoder/payload_decoders/quic_http_push_promise_payload_decoder.h",
-      "third_party/quic/http/decoder/payload_decoders/quic_http_rst_stream_payload_decoder.cc",
-      "third_party/quic/http/decoder/payload_decoders/quic_http_rst_stream_payload_decoder.h",
-      "third_party/quic/http/decoder/payload_decoders/quic_http_settings_payload_decoder.cc",
-      "third_party/quic/http/decoder/payload_decoders/quic_http_settings_payload_decoder.h",
-      "third_party/quic/http/decoder/payload_decoders/quic_http_unknown_payload_decoder.cc",
-      "third_party/quic/http/decoder/payload_decoders/quic_http_unknown_payload_decoder.h",
-      "third_party/quic/http/decoder/payload_decoders/quic_http_window_update_payload_decoder.cc",
-      "third_party/quic/http/decoder/payload_decoders/quic_http_window_update_payload_decoder.h",
-      "third_party/quic/http/decoder/quic_http_decode_buffer.cc",
-      "third_party/quic/http/decoder/quic_http_decode_buffer.h",
-      "third_party/quic/http/decoder/quic_http_decode_status.cc",
-      "third_party/quic/http/decoder/quic_http_decode_status.h",
-      "third_party/quic/http/decoder/quic_http_decode_structures.cc",
-      "third_party/quic/http/decoder/quic_http_decode_structures.h",
-      "third_party/quic/http/decoder/quic_http_frame_decoder.cc",
-      "third_party/quic/http/decoder/quic_http_frame_decoder.h",
-      "third_party/quic/http/decoder/quic_http_frame_decoder_adapter.cc",
-      "third_party/quic/http/decoder/quic_http_frame_decoder_adapter.h",
-      "third_party/quic/http/decoder/quic_http_frame_decoder_listener.cc",
-      "third_party/quic/http/decoder/quic_http_frame_decoder_listener.h",
-      "third_party/quic/http/decoder/quic_http_frame_decoder_state.cc",
-      "third_party/quic/http/decoder/quic_http_frame_decoder_state.h",
-      "third_party/quic/http/decoder/quic_http_structure_decoder.cc",
-      "third_party/quic/http/decoder/quic_http_structure_decoder.h",
-      "third_party/quic/http/quic_http_constants.cc",
-      "third_party/quic/http/quic_http_constants.h",
-      "third_party/quic/http/quic_http_structures.cc",
-      "third_party/quic/http/quic_http_structures.h",
       "third_party/quic/platform/api/quic_aligned.h",
       "third_party/quic/platform/api/quic_arraysize.h",
       "third_party/quic/platform/api/quic_bug_tracker.h",
@@ -5064,51 +5020,6 @@
     "third_party/quic/core/quic_headers_stream_test.cc",
     "third_party/quic/core/quic_ietf_framer_test.cc",
     "third_party/quic/core/tls_handshaker_test.cc",
-    "third_party/quic/http/decoder/payload_decoders/quic_http_altsvc_payload_decoder_test.cc",
-    "third_party/quic/http/decoder/payload_decoders/quic_http_continuation_payload_decoder_test.cc",
-    "third_party/quic/http/decoder/payload_decoders/quic_http_data_payload_decoder_test.cc",
-    "third_party/quic/http/decoder/payload_decoders/quic_http_goaway_payload_decoder_test.cc",
-    "third_party/quic/http/decoder/payload_decoders/quic_http_headers_payload_decoder_test.cc",
-    "third_party/quic/http/decoder/payload_decoders/quic_http_payload_decoder_base_test_util.cc",
-    "third_party/quic/http/decoder/payload_decoders/quic_http_payload_decoder_base_test_util.h",
-    "third_party/quic/http/decoder/payload_decoders/quic_http_ping_payload_decoder_test.cc",
-    "third_party/quic/http/decoder/payload_decoders/quic_http_priority_payload_decoder_test.cc",
-    "third_party/quic/http/decoder/payload_decoders/quic_http_push_promise_payload_decoder_test.cc",
-    "third_party/quic/http/decoder/payload_decoders/quic_http_rst_stream_payload_decoder_test.cc",
-    "third_party/quic/http/decoder/payload_decoders/quic_http_settings_payload_decoder_test.cc",
-    "third_party/quic/http/decoder/payload_decoders/quic_http_unknown_payload_decoder_test.cc",
-    "third_party/quic/http/decoder/payload_decoders/quic_http_window_update_payload_decoder_test.cc",
-    "third_party/quic/http/decoder/quic_http_decode_buffer_test.cc",
-    "third_party/quic/http/decoder/quic_http_frame_decoder_listener_test_util.cc",
-    "third_party/quic/http/decoder/quic_http_frame_decoder_listener_test_util.h",
-    "third_party/quic/http/decoder/quic_http_frame_decoder_state_test_util.cc",
-    "third_party/quic/http/decoder/quic_http_frame_decoder_state_test_util.h",
-    "third_party/quic/http/decoder/quic_http_frame_decoder_test.cc",
-    "third_party/quic/http/decoder/quic_http_structure_decoder_test.cc",
-    "third_party/quic/http/decoder/quic_http_structure_decoder_test_util.cc",
-    "third_party/quic/http/decoder/quic_http_structure_decoder_test_util.h",
-    "third_party/quic/http/quic_http_constants_test.cc",
-    "third_party/quic/http/quic_http_constants_test_util.cc",
-    "third_party/quic/http/quic_http_constants_test_util.h",
-    "third_party/quic/http/quic_http_structures_test.cc",
-    "third_party/quic/http/quic_http_structures_test_util.cc",
-    "third_party/quic/http/quic_http_structures_test_util.h",
-    "third_party/quic/http/test_tools/quic_http_frame_parts.cc",
-    "third_party/quic/http/test_tools/quic_http_frame_parts.h",
-    "third_party/quic/http/test_tools/quic_http_frame_parts_collector.cc",
-    "third_party/quic/http/test_tools/quic_http_frame_parts_collector.h",
-    "third_party/quic/http/test_tools/quic_http_frame_parts_collector_listener.cc",
-    "third_party/quic/http/test_tools/quic_http_frame_parts_collector_listener.h",
-    "third_party/quic/http/tools/quic_http_frame_builder.cc",
-    "third_party/quic/http/tools/quic_http_frame_builder.h",
-    "third_party/quic/http/tools/quic_http_random_decoder_test.cc",
-    "third_party/quic/http/tools/quic_http_random_decoder_test.h",
-    "third_party/quic/http/tools/quic_http_random_util.cc",
-    "third_party/quic/http/tools/quic_http_random_util.h",
-    "third_party/quic/test_tools/quic_test_utils_test.cc",
-    "third_party/quic/test_tools/simple_session_notifier_test.cc",
-    "third_party/quic/test_tools/simulator/quic_endpoint_test.cc",
-    "third_party/quic/test_tools/simulator/simulator_test.cc",
 
     #    "third_party/quic/core/quic_multipath_received_packet_manager_test.cc",
     #    "third_party/quic/core/quic_multipath_transmissions_map_test.cc",
diff --git a/net/dns/mdns_client_unittest.cc b/net/dns/mdns_client_unittest.cc
index cc8469d..6256a45a 100644
--- a/net/dns/mdns_client_unittest.cc
+++ b/net/dns/mdns_client_unittest.cc
@@ -373,16 +373,16 @@
   DISALLOW_COPY_AND_ASSIGN(MockClock);
 };
 
-class MockTimer : public base::MockTimer {
+class MockTimer : public base::MockOneShotTimer {
  public:
-  MockTimer() : base::MockTimer(false, false) {}
+  MockTimer() {}
   ~MockTimer() override = default;
 
   void Start(const base::Location& posted_from,
              base::TimeDelta delay,
              const base::Closure& user_task) override {
     StartObserver(posted_from, delay, user_task);
-    base::MockTimer::Start(posted_from, delay, user_task);
+    base::MockOneShotTimer::Start(posted_from, delay, user_task);
   }
 
   // StartObserver is invoked when MockTimer::Start() is called.
diff --git a/net/http/bidirectional_stream_unittest.cc b/net/http/bidirectional_stream_unittest.cc
index cd7dd3a..7186dfb 100644
--- a/net/http/bidirectional_stream_unittest.cc
+++ b/net/http/bidirectional_stream_unittest.cc
@@ -377,9 +377,9 @@
 };
 
 // A Timer that does not start a delayed task unless the timer is fired.
-class MockTimer : public base::MockTimer {
+class MockTimer : public base::MockOneShotTimer {
  public:
-  MockTimer() : base::MockTimer(false, false) {}
+  MockTimer() {}
   ~MockTimer() override = default;
 
   void Start(const base::Location& posted_from,
@@ -387,7 +387,7 @@
              const base::Closure& user_task) override {
     // Sets a maximum delay, so the timer does not fire unless it is told to.
     base::TimeDelta infinite_delay = base::TimeDelta::Max();
-    base::MockTimer::Start(posted_from, infinite_delay, user_task);
+    base::MockOneShotTimer::Start(posted_from, infinite_delay, user_task);
   }
 
  private:
diff --git a/net/quic/chromium/quic_chromium_client_session_peer.cc b/net/quic/chromium/quic_chromium_client_session_peer.cc
index a0f9658e..469d411 100644
--- a/net/quic/chromium/quic_chromium_client_session_peer.cc
+++ b/net/quic/chromium/quic_chromium_client_session_peer.cc
@@ -9,15 +9,6 @@
 
 namespace net {
 namespace test {
-
-// static
-void QuicChromiumClientSessionPeer::SetMaxOpenStreams(
-    QuicChromiumClientSession* session,
-    size_t max_streams,
-    size_t default_streams) {
-  session->config()->SetMaxStreamsPerConnection(max_streams, default_streams);
-}
-
 // static
 void QuicChromiumClientSessionPeer::SetHostname(
     QuicChromiumClientSession* session,
diff --git a/net/quic/chromium/quic_chromium_client_session_peer.h b/net/quic/chromium/quic_chromium_client_session_peer.h
index b0f7dc0..c572662 100644
--- a/net/quic/chromium/quic_chromium_client_session_peer.h
+++ b/net/quic/chromium/quic_chromium_client_session_peer.h
@@ -21,10 +21,6 @@
 
 class QuicChromiumClientSessionPeer {
  public:
-  static void SetMaxOpenStreams(QuicChromiumClientSession* session,
-                                size_t max_streams,
-                                size_t default_streams);
-
   static void SetHostname(QuicChromiumClientSession* session,
                           const std::string& hostname);
 
diff --git a/net/quic/chromium/quic_network_transaction_unittest.cc b/net/quic/chromium/quic_network_transaction_unittest.cc
index 5a4b160..73c8999a 100644
--- a/net/quic/chromium/quic_network_transaction_unittest.cc
+++ b/net/quic/chromium/quic_network_transaction_unittest.cc
@@ -2061,6 +2061,10 @@
 }
 
 TEST_P(QuicNetworkTransactionTest, GoAwayWithConnectionMigrationOnPortsOnly) {
+  if (version_ == quic::QUIC_VERSION_99) {
+    // Not available under version 99
+    return;
+  }
   MockQuicData mock_quic_data;
   quic::QuicStreamOffset header_stream_offset = 0;
   mock_quic_data.AddWrite(
diff --git a/net/reporting/reporting_delivery_agent.cc b/net/reporting/reporting_delivery_agent.cc
index 467bfd9..238d37d 100644
--- a/net/reporting/reporting_delivery_agent.cc
+++ b/net/reporting/reporting_delivery_agent.cc
@@ -64,7 +64,7 @@
 
   ~ReportingDeliveryAgentImpl() override { context_->RemoveObserver(this); }
 
-  void SetTimerForTesting(std::unique_ptr<base::Timer> timer) override {
+  void SetTimerForTesting(std::unique_ptr<base::OneShotTimer> timer) override {
     DCHECK(!timer_->IsRunning());
     timer_ = std::move(timer);
   }
@@ -240,7 +240,7 @@
 
   ReportingContext* context_;
 
-  std::unique_ptr<base::Timer> timer_;
+  std::unique_ptr<base::OneShotTimer> timer_;
 
   // Tracks OriginGroup tuples for which there is a pending delivery running.
   // (Would be an unordered_set, but there's no hash on pair.)
diff --git a/net/reporting/reporting_delivery_agent.h b/net/reporting/reporting_delivery_agent.h
index d071b7e..bd15443 100644
--- a/net/reporting/reporting_delivery_agent.h
+++ b/net/reporting/reporting_delivery_agent.h
@@ -11,7 +11,7 @@
 #include "net/base/net_export.h"
 
 namespace base {
-class Timer;
+class OneShotTimer;
 }  // namespace base
 
 namespace net {
@@ -55,9 +55,11 @@
 
   virtual ~ReportingDeliveryAgent();
 
-  // Replaces the internal Timer used for scheduling report delivery attempts
-  // with a caller-specified one so that unittests can provide a MockTimer.
-  virtual void SetTimerForTesting(std::unique_ptr<base::Timer> timer) = 0;
+  // Replaces the internal OneShotTimer used for scheduling report delivery
+  // attempts with a caller-specified one so that unittests can provide a
+  // MockOneShotTimer.
+  virtual void SetTimerForTesting(
+      std::unique_ptr<base::OneShotTimer> timer) = 0;
 };
 
 }  // namespace net
diff --git a/net/reporting/reporting_garbage_collector.cc b/net/reporting/reporting_garbage_collector.cc
index bb66cb0..e56cd90 100644
--- a/net/reporting/reporting_garbage_collector.cc
+++ b/net/reporting/reporting_garbage_collector.cc
@@ -34,7 +34,7 @@
     context_->RemoveObserver(this);
   }
 
-  void SetTimerForTesting(std::unique_ptr<base::Timer> timer) override {
+  void SetTimerForTesting(std::unique_ptr<base::OneShotTimer> timer) override {
     timer_ = std::move(timer);
   }
 
@@ -76,7 +76,7 @@
   }
 
   ReportingContext* context_;
-  std::unique_ptr<base::Timer> timer_;
+  std::unique_ptr<base::OneShotTimer> timer_;
 };
 
 }  // namespace
diff --git a/net/reporting/reporting_garbage_collector.h b/net/reporting/reporting_garbage_collector.h
index 228f14e..b56d4d5 100644
--- a/net/reporting/reporting_garbage_collector.h
+++ b/net/reporting/reporting_garbage_collector.h
@@ -10,7 +10,7 @@
 #include "net/base/net_export.h"
 
 namespace base {
-class Timer;
+class OneShotTimer;
 }  // namespace base
 
 namespace net {
@@ -28,9 +28,11 @@
 
   virtual ~ReportingGarbageCollector();
 
-  // Replaces the internal Timer used for scheduling garbage collection passes
-  // with a caller-specified one so that unittests can provide a MockTimer.
-  virtual void SetTimerForTesting(std::unique_ptr<base::Timer> timer) = 0;
+  // Replaces the internal OneShotTimer used for scheduling garbage collection
+  // passes with a caller-specified one so that unittests can provide a
+  // MockOneShotTimer.
+  virtual void SetTimerForTesting(
+      std::unique_ptr<base::OneShotTimer> timer) = 0;
 };
 
 }  // namespace net
diff --git a/net/reporting/reporting_test_util.cc b/net/reporting/reporting_test_util.cc
index a23535f..316b9e2 100644
--- a/net/reporting/reporting_test_util.cc
+++ b/net/reporting/reporting_test_util.cc
@@ -175,11 +175,8 @@
           std::make_unique<TestReportingUploader>(),
           std::make_unique<TestReportingDelegate>()),
       rand_counter_(0),
-      delivery_timer_(new base::MockTimer(/* retain_user_task= */ false,
-                                          /* is_repeating= */ false)),
-      garbage_collection_timer_(
-          new base::MockTimer(/* retain_user_task= */ false,
-                              /* is_repeating= */ false)) {
+      delivery_timer_(new base::MockOneShotTimer()),
+      garbage_collection_timer_(new base::MockOneShotTimer()) {
   garbage_collector()->SetTimerForTesting(
       base::WrapUnique(garbage_collection_timer_));
   delivery_agent()->SetTimerForTesting(base::WrapUnique(delivery_timer_));
diff --git a/net/reporting/reporting_test_util.h b/net/reporting/reporting_test_util.h
index b5edf6b..db8c396 100644
--- a/net/reporting/reporting_test_util.h
+++ b/net/reporting/reporting_test_util.h
@@ -22,7 +22,7 @@
 class GURL;
 
 namespace base {
-class MockTimer;
+class MockOneShotTimer;
 class SimpleTestClock;
 class SimpleTestTickClock;
 class Value;
@@ -145,8 +145,8 @@
                        const ReportingPolicy& policy);
   ~TestReportingContext();
 
-  base::MockTimer* test_delivery_timer() { return delivery_timer_; }
-  base::MockTimer* test_garbage_collection_timer() {
+  base::MockOneShotTimer* test_delivery_timer() { return delivery_timer_; }
+  base::MockOneShotTimer* test_garbage_collection_timer() {
     return garbage_collection_timer_;
   }
   TestReportingUploader* test_uploader() {
@@ -164,8 +164,8 @@
   // Owned by the DeliveryAgent and GarbageCollector, respectively, but
   // referenced here to preserve type:
 
-  base::MockTimer* delivery_timer_;
-  base::MockTimer* garbage_collection_timer_;
+  base::MockOneShotTimer* delivery_timer_;
+  base::MockOneShotTimer* garbage_collection_timer_;
 
   DISALLOW_COPY_AND_ASSIGN(TestReportingContext);
 };
@@ -191,8 +191,10 @@
 
   base::SimpleTestClock* clock() { return &clock_; }
   base::SimpleTestTickClock* tick_clock() { return &tick_clock_; }
-  base::MockTimer* delivery_timer() { return context_->test_delivery_timer(); }
-  base::MockTimer* garbage_collection_timer() {
+  base::MockOneShotTimer* delivery_timer() {
+    return context_->test_delivery_timer();
+  }
+  base::MockOneShotTimer* garbage_collection_timer() {
     return context_->test_garbage_collection_timer();
   }
   TestReportingUploader* uploader() { return context_->test_uploader(); }
diff --git a/net/third_party/quic/core/chlo_extractor_test.cc b/net/third_party/quic/core/chlo_extractor_test.cc
index 5b06f91..92f6457 100644
--- a/net/third_party/quic/core/chlo_extractor_test.cc
+++ b/net/third_party/quic/core/chlo_extractor_test.cc
@@ -47,7 +47,6 @@
 class ChloExtractorTest : public QuicTest {
  public:
   ChloExtractorTest() {
-    SetQuicReloadableFlag(quic_respect_ietf_header, true);
     header_.destination_connection_id = 42;
     header_.destination_connection_id_length = PACKET_8BYTE_CONNECTION_ID;
     header_.version_flag = true;
diff --git a/net/third_party/quic/core/congestion_control/general_loss_algorithm.cc b/net/third_party/quic/core/congestion_control/general_loss_algorithm.cc
index 1f8cd1e..a284b200 100644
--- a/net/third_party/quic/core/congestion_control/general_loss_algorithm.cc
+++ b/net/third_party/quic/core/congestion_control/general_loss_algorithm.cc
@@ -37,9 +37,7 @@
                             ? kDefaultAdaptiveLossDelayShift
                             : kDefaultLossDelayShift),
       largest_previously_acked_(0),
-      largest_lost_(0),
-      detect_loss_incrementally_(
-          GetQuicReloadableFlag(quic_incremental_loss_detection)) {}
+      largest_lost_(0) {}
 
 LossDetectionType GeneralLossAlgorithm::GetLossDetectionType() const {
   return loss_type_;
@@ -70,8 +68,7 @@
                max_rtt + (max_rtt >> reordering_shift_));
   QuicPacketNumber packet_number = unacked_packets.GetLeastUnacked();
   QuicUnackedPacketMap::const_iterator it = unacked_packets.begin();
-  if (detect_loss_incrementally_ && largest_lost_ >= packet_number) {
-    QUIC_FLAG_COUNT(quic_reloadable_flag_quic_incremental_loss_detection);
+  if (largest_lost_ >= packet_number) {
     if (largest_lost_ > unacked_packets.largest_sent_packet()) {
       QUIC_BUG << "largest_lost: " << largest_lost_
                << " is greater than largest_sent_packet: "
@@ -129,7 +126,7 @@
     }
   }
   largest_previously_acked_ = largest_newly_acked;
-  if (detect_loss_incrementally_ && !packets_lost->empty()) {
+  if (!packets_lost->empty()) {
     DCHECK_LT(largest_lost_, packets_lost->back().packet_number);
     largest_lost_ = packets_lost->back().packet_number;
   }
diff --git a/net/third_party/quic/core/congestion_control/general_loss_algorithm.h b/net/third_party/quic/core/congestion_control/general_loss_algorithm.h
index 5b089dc1..3409279f 100644
--- a/net/third_party/quic/core/congestion_control/general_loss_algorithm.h
+++ b/net/third_party/quic/core/congestion_control/general_loss_algorithm.h
@@ -71,9 +71,6 @@
   // The largest lost packet.
   QuicPacketNumber largest_lost_;
 
-  // Latched value of quic_reloadable_flag_quic_incremental_loss_detection.
-  const bool detect_loss_incrementally_;
-
   DISALLOW_COPY_AND_ASSIGN(GeneralLossAlgorithm);
 };
 
diff --git a/net/third_party/quic/core/congestion_control/general_loss_algorithm_test.cc b/net/third_party/quic/core/congestion_control/general_loss_algorithm_test.cc
index ef20e3b..2cf0945 100644
--- a/net/third_party/quic/core/congestion_control/general_loss_algorithm_test.cc
+++ b/net/third_party/quic/core/congestion_control/general_loss_algorithm_test.cc
@@ -156,19 +156,11 @@
             loss_algorithm_.GetLossTimeout());
 
   clock_.AdvanceTime(rtt_stats_.smoothed_rtt());
-  if (GetQuicReloadableFlag(quic_incremental_loss_detection)) {
-    VerifyLosses(kNumSentPackets, {3});
-  } else {
-    VerifyLosses(kNumSentPackets, {1, 2, 3});
-  }
+  VerifyLosses(kNumSentPackets, {3});
   EXPECT_EQ(clock_.Now() + 0.25 * rtt_stats_.smoothed_rtt(),
             loss_algorithm_.GetLossTimeout());
   clock_.AdvanceTime(0.25 * rtt_stats_.smoothed_rtt());
-  if (GetQuicReloadableFlag(quic_incremental_loss_detection)) {
-    VerifyLosses(kNumSentPackets, {4});
-  } else {
-    VerifyLosses(kNumSentPackets, {1, 2, 3, 4});
-  }
+  VerifyLosses(kNumSentPackets, {4});
   EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
 }
 
diff --git a/net/third_party/quic/core/congestion_control/send_algorithm_interface.cc b/net/third_party/quic/core/congestion_control/send_algorithm_interface.cc
index 51037e2..814927d 100644
--- a/net/third_party/quic/core/congestion_control/send_algorithm_interface.cc
+++ b/net/third_party/quic/core/congestion_control/send_algorithm_interface.cc
@@ -33,7 +33,7 @@
                            initial_congestion_window, max_congestion_window,
                            random);
     case kPCC:
-      if (GetQuicReloadableFlag(quic_enable_pcc)) {
+      if (GetQuicReloadableFlag(quic_enable_pcc2)) {
         return CreatePccSender(clock, rtt_stats, unacked_packets, random, stats,
                                initial_congestion_window,
                                max_congestion_window);
diff --git a/net/third_party/quic/core/crypto/crypto_handshake_message.cc b/net/third_party/quic/core/crypto/crypto_handshake_message.cc
index d4d1777..f8bb9d3 100644
--- a/net/third_party/quic/core/crypto/crypto_handshake_message.cc
+++ b/net/third_party/quic/core/crypto/crypto_handshake_message.cc
@@ -281,7 +281,6 @@
       case kCFCW:
       case kSFCW:
       case kIRTT:
-      case kMSPC:
       case kMIDS:
       case kSCLS:
       case kTCID:
diff --git a/net/third_party/quic/core/crypto/crypto_protocol.h b/net/third_party/quic/core/crypto/crypto_protocol.h
index 4745e4ff..5faeb36 100644
--- a/net/third_party/quic/core/crypto/crypto_protocol.h
+++ b/net/third_party/quic/core/crypto/crypto_protocol.h
@@ -195,7 +195,6 @@
 const QuicTag kCLOP = TAG('C', 'L', 'O', 'P');   // Client connection options
 const QuicTag kICSL = TAG('I', 'C', 'S', 'L');   // Idle network timeout
 const QuicTag kSCLS = TAG('S', 'C', 'L', 'S');   // Silently close on timeout
-const QuicTag kMSPC = TAG('M', 'S', 'P', 'C');   // Max streams per connection.
 const QuicTag kMIDS = TAG('M', 'I', 'D', 'S');   // Max incoming dynamic streams
 const QuicTag kIRTT = TAG('I', 'R', 'T', 'T');   // Estimated initial RTT in us.
 const QuicTag kSNI  = TAG('S', 'N', 'I', '\0');  // Server name
diff --git a/net/third_party/quic/core/crypto/quic_crypto_client_config.h b/net/third_party/quic/core/crypto/quic_crypto_client_config.h
index 972122bc..21bf66b 100644
--- a/net/third_party/quic/core/crypto/quic_crypto_client_config.h
+++ b/net/third_party/quic/core/crypto/quic_crypto_client_config.h
@@ -343,6 +343,10 @@
     user_agent_id_ = user_agent_id;
   }
 
+  // Returns the user_agent_id that will be provided in the client hello
+  // handshake message.
+  const QuicString& user_agent_id() const { return user_agent_id_; }
+
   // Saves the |alpn| that will be passed in QUIC's CHLO message.
   void set_alpn(const QuicString& alpn) { alpn_ = alpn; }
 
diff --git a/net/third_party/quic/core/crypto/transport_parameters.cc b/net/third_party/quic/core/crypto/transport_parameters.cc
index 799f5ee..388c64c 100644
--- a/net/third_party/quic/core/crypto/transport_parameters.cc
+++ b/net/third_party/quic/core/crypto/transport_parameters.cc
@@ -4,6 +4,7 @@
 
 #include "net/third_party/quic/core/crypto/transport_parameters.h"
 
+#include "net/third_party/quic/core/crypto/crypto_framer.h"
 #include "third_party/boringssl/src/include/openssl/bytestring.h"
 
 namespace quic {
@@ -14,18 +15,22 @@
 // draft-ietf-quic-transport-08 section 7.4. When parameters are encoded, one of
 // these enum values is used to indicate which parameter is encoded.
 enum TransportParameterId : uint16_t {
-  kInitialMaxStreamData = 0,
-  kInitialMaxData = 1,
-  kInitialMaxBidiStreams = 2,
-  kIdleTimeout = 3,
-  kMaxPacketSize = 5,
-  kStatelessResetToken = 6,
-  kAckDelayExponent = 7,
-  kInitialMaxUniStreams = 8,
+  kInitialMaxStreamDataId = 0,
+  kInitialMaxDataId = 1,
+  kInitialMaxBidiStreamsId = 2,
+  kIdleTimeoutId = 3,
+  kMaxPacketSizeId = 5,
+  kStatelessResetTokenId = 6,
+  kAckDelayExponentId = 7,
+  kInitialMaxUniStreamsId = 8,
 
   kMaxKnownParameterId = 9,
 };
 
+// Value for the TransportParameterId to use for non-standard Google QUIC params
+// in Transport Parameters.
+const uint16_t kGoogleQuicParamId = 18257;
+
 // The following constants define minimum and maximum allowed values for some of
 // the parameters. These come from draft-ietf-quic-transport-08 section 7.4.1.
 const uint16_t kMaxAllowedIdleTimeout = 600;
@@ -40,16 +45,14 @@
 // used to keep track of which parameter have been seen so far, and that bitmask
 // will be compared to this mask to check that all of the required parameters
 // were present.
-static constexpr uint16_t kRequiredParamsMask =
-    (1 << kInitialMaxStreamData) | (1 << kInitialMaxData) | (1 << kIdleTimeout);
+static constexpr uint16_t kRequiredParamsMask = (1 << kInitialMaxStreamDataId) |
+                                                (1 << kInitialMaxDataId) |
+                                                (1 << kIdleTimeoutId);
 
 }  // namespace
 
 TransportParameters::TransportParameters() = default;
 
-TransportParameters::TransportParameters(
-    const TransportParameters& transport_params) = default;
-
 TransportParameters::~TransportParameters() = default;
 
 bool TransportParameters::is_valid() const {
@@ -100,16 +103,16 @@
   // required parameters
   if (!CBB_add_u16_length_prefixed(cbb.get(), &params) ||
       // initial_max_stream_data
-      !CBB_add_u16(&params, kInitialMaxStreamData) ||
+      !CBB_add_u16(&params, kInitialMaxStreamDataId) ||
       !CBB_add_u16_length_prefixed(&params, &initial_max_stream_data_param) ||
       !CBB_add_u32(&initial_max_stream_data_param,
                    in.initial_max_stream_data) ||
       // initial_max_data
-      !CBB_add_u16(&params, kInitialMaxData) ||
+      !CBB_add_u16(&params, kInitialMaxDataId) ||
       !CBB_add_u16_length_prefixed(&params, &initial_max_data_param) ||
       !CBB_add_u32(&initial_max_data_param, in.initial_max_data) ||
       // idle_timeout
-      !CBB_add_u16(&params, kIdleTimeout) ||
+      !CBB_add_u16(&params, kIdleTimeoutId) ||
       !CBB_add_u16_length_prefixed(&params, &idle_timeout_param) ||
       !CBB_add_u16(&idle_timeout_param, in.idle_timeout)) {
     return false;
@@ -117,7 +120,7 @@
 
   CBB stateless_reset_token_param;
   if (!in.stateless_reset_token.empty()) {
-    if (!CBB_add_u16(&params, kStatelessResetToken) ||
+    if (!CBB_add_u16(&params, kStatelessResetTokenId) ||
         !CBB_add_u16_length_prefixed(&params, &stateless_reset_token_param) ||
         !CBB_add_bytes(&stateless_reset_token_param,
                        in.stateless_reset_token.data(),
@@ -128,7 +131,7 @@
 
   CBB initial_max_bidi_streams_param;
   if (in.initial_max_bidi_streams.present) {
-    if (!CBB_add_u16(&params, kInitialMaxBidiStreams) ||
+    if (!CBB_add_u16(&params, kInitialMaxBidiStreamsId) ||
         !CBB_add_u16_length_prefixed(&params,
                                      &initial_max_bidi_streams_param) ||
         !CBB_add_u16(&initial_max_bidi_streams_param,
@@ -138,7 +141,7 @@
   }
   CBB initial_max_uni_streams_param;
   if (in.initial_max_uni_streams.present) {
-    if (!CBB_add_u16(&params, kInitialMaxUniStreams) ||
+    if (!CBB_add_u16(&params, kInitialMaxUniStreamsId) ||
         !CBB_add_u16_length_prefixed(&params, &initial_max_uni_streams_param) ||
         !CBB_add_u16(&initial_max_uni_streams_param,
                      in.initial_max_uni_streams.value)) {
@@ -147,7 +150,7 @@
   }
   CBB max_packet_size_param;
   if (in.max_packet_size.present) {
-    if (!CBB_add_u16(&params, kMaxPacketSize) ||
+    if (!CBB_add_u16(&params, kMaxPacketSizeId) ||
         !CBB_add_u16_length_prefixed(&params, &max_packet_size_param) ||
         !CBB_add_u16(&max_packet_size_param, in.max_packet_size.value)) {
       return false;
@@ -155,12 +158,25 @@
   }
   CBB ack_delay_exponent_param;
   if (in.ack_delay_exponent.present) {
-    if (!CBB_add_u16(&params, kAckDelayExponent) ||
+    if (!CBB_add_u16(&params, kAckDelayExponentId) ||
         !CBB_add_u16_length_prefixed(&params, &ack_delay_exponent_param) ||
         !CBB_add_u8(&ack_delay_exponent_param, in.ack_delay_exponent.value)) {
       return false;
     }
   }
+  CBB google_quic_params;
+  if (in.google_quic_params) {
+    const QuicData& serialized_google_quic_params =
+        in.google_quic_params->GetSerialized(in.perspective);
+    if (!CBB_add_u16(&params, kGoogleQuicParamId) ||
+        !CBB_add_u16_length_prefixed(&params, &google_quic_params) ||
+        !CBB_add_bytes(&google_quic_params,
+                       reinterpret_cast<const uint8_t*>(
+                           serialized_google_quic_params.data()),
+                       serialized_google_quic_params.length())) {
+      return false;
+    }
+  }
   if (!CBB_flush(cbb.get())) {
     return false;
   }
@@ -195,6 +211,7 @@
   out->perspective = perspective;
 
   uint32_t present_params = 0;
+  bool has_google_quic_params = false;
   CBS params;
   if (!CBS_get_u16_length_prefixed(&cbs, &params)) {
     return false;
@@ -214,57 +231,67 @@
       present_params |= mask;
     }
     switch (param_id) {
-      case kInitialMaxStreamData:
+      case kInitialMaxStreamDataId:
         if (!CBS_get_u32(&value, &out->initial_max_stream_data) ||
             CBS_len(&value) != 0) {
           return false;
         }
         break;
-      case kInitialMaxData:
+      case kInitialMaxDataId:
         if (!CBS_get_u32(&value, &out->initial_max_data) ||
             CBS_len(&value) != 0) {
           return false;
         }
         break;
-      case kInitialMaxBidiStreams:
+      case kInitialMaxBidiStreamsId:
         if (!CBS_get_u16(&value, &out->initial_max_bidi_streams.value) ||
             CBS_len(&value) != 0) {
           return false;
         }
         out->initial_max_bidi_streams.present = true;
         break;
-      case kIdleTimeout:
+      case kIdleTimeoutId:
         if (!CBS_get_u16(&value, &out->idle_timeout) || CBS_len(&value) != 0) {
           return false;
         }
         break;
-      case kMaxPacketSize:
+      case kMaxPacketSizeId:
         if (!CBS_get_u16(&value, &out->max_packet_size.value) ||
             CBS_len(&value) != 0) {
           return false;
         }
         out->max_packet_size.present = true;
         break;
-      case kStatelessResetToken:
+      case kStatelessResetTokenId:
         if (CBS_len(&value) == 0) {
           return false;
         }
         out->stateless_reset_token.assign(CBS_data(&value),
                                           CBS_data(&value) + CBS_len(&value));
         break;
-      case kAckDelayExponent:
+      case kAckDelayExponentId:
         if (!CBS_get_u8(&value, &out->ack_delay_exponent.value) ||
             CBS_len(&value) != 0) {
           return false;
         }
         out->ack_delay_exponent.present = true;
         break;
-      case kInitialMaxUniStreams:
+      case kInitialMaxUniStreamsId:
         if (!CBS_get_u16(&value, &out->initial_max_uni_streams.value) ||
             CBS_len(&value) != 0) {
           return false;
         }
         out->initial_max_uni_streams.present = true;
+        break;
+      case kGoogleQuicParamId:
+        if (has_google_quic_params) {
+          return false;
+        }
+        has_google_quic_params = true;
+        QuicStringPiece serialized_params(
+            reinterpret_cast<const char*>(CBS_data(&value)), CBS_len(&value));
+        out->google_quic_params =
+            CryptoFramer::ParseMessage(serialized_params, perspective);
     }
   }
   if ((present_params & kRequiredParamsMask) != kRequiredParamsMask) {
diff --git a/net/third_party/quic/core/crypto/transport_parameters.h b/net/third_party/quic/core/crypto/transport_parameters.h
index 9e9962b9..cc5f4017 100644
--- a/net/third_party/quic/core/crypto/transport_parameters.h
+++ b/net/third_party/quic/core/crypto/transport_parameters.h
@@ -5,8 +5,10 @@
 #ifndef NET_THIRD_PARTY_QUIC_CORE_CRYPTO_TRANSPORT_PARAMETERS_H_
 #define NET_THIRD_PARTY_QUIC_CORE_CRYPTO_TRANSPORT_PARAMETERS_H_
 
+#include <memory>
 #include <vector>
 
+#include "net/third_party/quic/core/crypto/crypto_handshake_message.h"
 #include "net/third_party/quic/core/quic_types.h"
 #include "net/third_party/quic/core/quic_versions.h"
 
@@ -17,7 +19,6 @@
 // section 6.4 of draft-ietf-quic-transport-11.
 struct QUIC_EXPORT_PRIVATE TransportParameters {
   TransportParameters();
-  TransportParameters(const TransportParameters& transport_params);
   ~TransportParameters();
 
   // When |perspective| is Perspective::IS_CLIENT, this struct is being used in
@@ -59,6 +60,11 @@
   OptionalParam<uint16_t> max_packet_size;
   OptionalParam<uint8_t> ack_delay_exponent;
 
+  // Transport parameters used by Google QUIC but not IETF QUIC. This is
+  // serialized into a TransportParameter struct with a TransportParameterId of
+  // 18257.
+  std::unique_ptr<CryptoHandshakeMessage> google_quic_params;
+
   // Returns true if the contents of this struct are valid.
   bool is_valid() const;
 };
diff --git a/net/third_party/quic/core/crypto/transport_parameters_test.cc b/net/third_party/quic/core/crypto/transport_parameters_test.cc
index 5e5468e..20856a6 100644
--- a/net/third_party/quic/core/crypto/transport_parameters_test.cc
+++ b/net/third_party/quic/core/crypto/transport_parameters_test.cc
@@ -5,6 +5,7 @@
 #include "net/third_party/quic/core/crypto/transport_parameters.h"
 
 #include "net/third_party/quic/platform/api/quic_arraysize.h"
+#include "net/third_party/quic/platform/api/quic_ptr_util.h"
 #include "net/third_party/quic/platform/api/quic_test.h"
 #include "third_party/boringssl/src/include/openssl/mem.h"
 
@@ -89,14 +90,18 @@
   EXPECT_TRUE(empty_params.is_valid());
 
   {
-    TransportParameters params = empty_params;
+    TransportParameters params;
+    params.perspective = Perspective::IS_CLIENT;
+    EXPECT_TRUE(params.is_valid());
     params.idle_timeout = 600;
     EXPECT_TRUE(params.is_valid());
     params.idle_timeout = 601;
     EXPECT_FALSE(params.is_valid());
   }
   {
-    TransportParameters params = empty_params;
+    TransportParameters params;
+    params.perspective = Perspective::IS_CLIENT;
+    EXPECT_TRUE(params.is_valid());
     params.max_packet_size.present = true;
     params.max_packet_size.value = 0;
     EXPECT_FALSE(params.is_valid());
@@ -108,7 +113,9 @@
     EXPECT_FALSE(params.is_valid());
   }
   {
-    TransportParameters params = empty_params;
+    TransportParameters params;
+    params.perspective = Perspective::IS_CLIENT;
+    EXPECT_TRUE(params.is_valid());
     params.ack_delay_exponent.present = true;
     params.ack_delay_exponent.value = 0;
     EXPECT_TRUE(params.is_valid());
@@ -397,5 +404,43 @@
                                         Perspective::IS_SERVER, &out_params));
 }
 
+TEST_F(TransportParametersTest, CryptoHandshakeMessageRoundtrip) {
+  TransportParameters orig_params;
+  orig_params.perspective = Perspective::IS_CLIENT;
+  orig_params.initial_max_stream_data = 12;
+  orig_params.initial_max_data = 34;
+  orig_params.idle_timeout = 56;
+
+  orig_params.google_quic_params = QuicMakeUnique<CryptoHandshakeMessage>();
+  const std::string kTestString = "test string";
+  orig_params.google_quic_params->SetStringPiece(42, kTestString);
+  const uint32_t kTestValue = 12;
+  orig_params.google_quic_params->SetValue(1337, kTestValue);
+
+  std::vector<uint8_t> serialized;
+  ASSERT_TRUE(SerializeTransportParameters(orig_params, &serialized));
+
+  TransportParameters new_params;
+  ASSERT_TRUE(ParseTransportParameters(serialized.data(), serialized.size(),
+                                       Perspective::IS_CLIENT, &new_params));
+
+  ASSERT_NE(new_params.google_quic_params.get(), nullptr);
+  EXPECT_EQ(new_params.google_quic_params->tag(),
+            orig_params.google_quic_params->tag());
+  QuicStringPiece test_string;
+  EXPECT_TRUE(new_params.google_quic_params->GetStringPiece(42, &test_string));
+  EXPECT_EQ(test_string, kTestString);
+  uint32_t test_value;
+  EXPECT_EQ(new_params.google_quic_params->GetUint32(1337, &test_value),
+            QUIC_NO_ERROR);
+  EXPECT_EQ(test_value, kTestValue);
+  LOG(ERROR) << "Original params:"
+             << orig_params.google_quic_params->DebugString(
+                    Perspective::IS_CLIENT);
+  LOG(ERROR) << "New params:"
+             << new_params.google_quic_params->DebugString(
+                    Perspective::IS_CLIENT);
+}
+
 }  // namespace test
 }  // namespace quic
diff --git a/net/third_party/quic/core/end_to_end_test.cc b/net/third_party/quic/core/end_to_end_test.cc
index 5c140828..8fd7c73c 100644
--- a/net/third_party/quic/core/end_to_end_test.cc
+++ b/net/third_party/quic/core/end_to_end_test.cc
@@ -394,7 +394,7 @@
     // client as well according to the test parameter.
     copt.push_back(GetParam().congestion_control_tag);
     if (GetParam().congestion_control_tag == kTPCC &&
-        GetQuicReloadableFlag(quic_enable_pcc)) {
+        GetQuicReloadableFlag(quic_enable_pcc2)) {
       copt.push_back(kTPCC);
     }
 
@@ -440,7 +440,6 @@
   void StartServer() {
     SetQuicReloadableFlag(quic_use_cheap_stateless_rejects,
                           GetParam().use_cheap_stateless_reject);
-    SetQuicReloadableFlag(quic_respect_ietf_header, true);
 
     auto* test_server = new QuicTestServer(
         crypto_test_utils::ProofSourceForTesting(), server_config_,
@@ -2584,9 +2583,7 @@
   const size_t kNumMaxStreams = 10;
 
   EndToEndTestServerPush() : EndToEndTest() {
-    client_config_.SetMaxStreamsPerConnection(kNumMaxStreams, kNumMaxStreams);
     client_config_.SetMaxIncomingDynamicStreamsToSend(kNumMaxStreams);
-    server_config_.SetMaxStreamsPerConnection(kNumMaxStreams, kNumMaxStreams);
     server_config_.SetMaxIncomingDynamicStreamsToSend(kNumMaxStreams);
     support_server_push_ = true;
   }
diff --git a/net/third_party/quic/core/frames/quic_ack_frame.cc b/net/third_party/quic/core/frames/quic_ack_frame.cc
index 76df5d7..f09c002 100644
--- a/net/third_party/quic/core/frames/quic_ack_frame.cc
+++ b/net/third_party/quic/core/frames/quic_ack_frame.cc
@@ -241,8 +241,8 @@
   return packet_number_deque_.back().max() - 1;
 }
 
-size_t PacketNumberQueue::NumPacketsSlow() const {
-  int n_packets = 0;
+QuicPacketCount PacketNumberQueue::NumPacketsSlow() const {
+  QuicPacketCount n_packets = 0;
   for (net::Interval<QuicPacketNumber> interval : packet_number_deque_) {
     n_packets += interval.Length();
   }
diff --git a/net/third_party/quic/core/frames/quic_ack_frame.h b/net/third_party/quic/core/frames/quic_ack_frame.h
index 56785b1a..9624ba2d 100644
--- a/net/third_party/quic/core/frames/quic_ack_frame.h
+++ b/net/third_party/quic/core/frames/quic_ack_frame.h
@@ -66,7 +66,7 @@
 
   // Returns the number of unique packets stored in the queue. Inefficient; only
   // exposed for testing.
-  size_t NumPacketsSlow() const;
+  QuicPacketCount NumPacketsSlow() const;
 
   // Returns the number of disjoint packet number intervals contained in the
   // queue.
diff --git a/net/third_party/quic/core/frames/quic_ietf_blocked_frame.cc b/net/third_party/quic/core/frames/quic_ietf_blocked_frame.cc
deleted file mode 100644
index 0dcc476f..0000000
--- a/net/third_party/quic/core/frames/quic_ietf_blocked_frame.cc
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright (c) 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "net/third_party/quic/core/frames/quic_ietf_blocked_frame.h"
-
-namespace quic {
-
-QuicIetfBlockedFrame::QuicIetfBlockedFrame() {}
-
-QuicIetfBlockedFrame::QuicIetfBlockedFrame(QuicControlFrameId control_frame_id,
-                                           QuicStreamOffset offset)
-    : QuicControlFrame(control_frame_id), offset(offset) {}
-
-std::ostream& operator<<(std::ostream& os, const QuicIetfBlockedFrame& frame) {
-  os << "{ control_frame_id: " << frame.control_frame_id
-     << ", offset: " << frame.offset << " }\n";
-  return os;
-}
-
-}  // namespace quic
diff --git a/net/third_party/quic/core/frames/quic_ietf_blocked_frame.h b/net/third_party/quic/core/frames/quic_ietf_blocked_frame.h
deleted file mode 100644
index f80d1ea..0000000
--- a/net/third_party/quic/core/frames/quic_ietf_blocked_frame.h
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright (c) 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_THIRD_PARTY_QUIC_CORE_FRAMES_QUIC_IETF_BLOCKED_FRAME_H_
-#define NET_THIRD_PARTY_QUIC_CORE_FRAMES_QUIC_IETF_BLOCKED_FRAME_H_
-
-#include <ostream>
-
-#include "net/third_party/quic/core/frames/quic_control_frame.h"
-
-namespace quic {
-
-// IETF format BLOCKED frame.
-// The sender uses the BLOCKED frame to inform the receiver that the
-// sender is unable to send data because of connection-level flow control.
-struct QUIC_EXPORT_PRIVATE QuicIetfBlockedFrame : public QuicControlFrame {
-  QuicIetfBlockedFrame();
-  QuicIetfBlockedFrame(QuicControlFrameId control_frame_id,
-                       QuicStreamOffset offset);
-
-  friend QUIC_EXPORT_PRIVATE std::ostream& operator<<(
-      std::ostream& os,
-      const QuicIetfBlockedFrame& frame);
-
-  // Offset at which the BLOCKED applies
-  QuicStreamOffset offset;
-};
-
-}  // namespace quic
-
-#endif  // NET_THIRD_PARTY_QUIC_CORE_FRAMES_QUIC_IETF_BLOCKED_FRAME_H_
diff --git a/net/third_party/quic/core/quic_config.cc b/net/third_party/quic/core/quic_config.cc
index ad89fec..b516ac8 100644
--- a/net/third_party/quic/core/quic_config.cc
+++ b/net/third_party/quic/core/quic_config.cc
@@ -14,6 +14,7 @@
 #include "net/third_party/quic/platform/api/quic_flag_utils.h"
 #include "net/third_party/quic/platform/api/quic_flags.h"
 #include "net/third_party/quic/platform/api/quic_logging.h"
+#include "net/third_party/quic/platform/api/quic_ptr_util.h"
 #include "net/third_party/quic/platform/api/quic_string.h"
 #include "net/third_party/quic/platform/api/quic_string_piece.h"
 
@@ -398,11 +399,7 @@
       client_connection_options_(kCLOP, PRESENCE_OPTIONAL),
       idle_network_timeout_seconds_(kICSL, PRESENCE_REQUIRED),
       silent_close_(kSCLS, PRESENCE_OPTIONAL),
-      do_not_use_mspc_(GetQuicReloadableFlag(quic_no_mspc)),
-      max_streams_per_connection_(kMSPC, PRESENCE_OPTIONAL),
-      max_incoming_dynamic_streams_(
-          kMIDS,
-          do_not_use_mspc_ ? PRESENCE_REQUIRED : PRESENCE_OPTIONAL),
+      max_incoming_dynamic_streams_(kMIDS, PRESENCE_REQUIRED),
       bytes_for_connection_id_(kTCID, PRESENCE_OPTIONAL),
       initial_round_trip_time_us_(kIRTT, PRESENCE_OPTIONAL),
       initial_stream_flow_control_window_bytes_(kSFCW, PRESENCE_OPTIONAL),
@@ -411,9 +408,6 @@
       alternate_server_address_(kASAD, PRESENCE_OPTIONAL),
       support_max_header_list_size_(kSMHL, PRESENCE_OPTIONAL),
       stateless_reset_token_(kSRST, PRESENCE_OPTIONAL) {
-  if (do_not_use_mspc_) {
-    QUIC_FLAG_COUNT(quic_reloadable_flag_quic_no_mspc);
-  }
   SetDefaults();
 }
 
@@ -506,15 +500,6 @@
   return silent_close_.GetUint32() > 0;
 }
 
-void QuicConfig::SetMaxStreamsPerConnection(size_t max_streams,
-                                            size_t default_streams) {
-  max_streams_per_connection_.set(max_streams, default_streams);
-}
-
-uint32_t QuicConfig::MaxStreamsPerConnection() const {
-  return max_streams_per_connection_.GetUint32();
-}
-
 void QuicConfig::SetMaxIncomingDynamicStreamsToSend(
     uint32_t max_incoming_dynamic_streams) {
   max_incoming_dynamic_streams_.SetSendValue(max_incoming_dynamic_streams);
@@ -659,8 +644,7 @@
 bool QuicConfig::negotiated() const {
   // TODO(ianswett): Add the negotiated parameters once and iterate over all
   // of them in negotiated, ToHandshakeMessage, and ProcessPeerHello.
-  return idle_network_timeout_seconds_.negotiated() &&
-         max_streams_per_connection_.negotiated();
+  return idle_network_timeout_seconds_.negotiated();
 }
 
 void QuicConfig::SetCreateSessionTagIndicators(QuicTagVector tags) {
@@ -675,8 +659,6 @@
   idle_network_timeout_seconds_.set(kMaximumIdleTimeoutSecs,
                                     kDefaultIdleTimeoutSecs);
   silent_close_.set(1, 0);
-  SetMaxStreamsPerConnection(kDefaultMaxStreamsPerConnection,
-                             kDefaultMaxStreamsPerConnection);
   SetMaxIncomingDynamicStreamsToSend(kDefaultMaxStreamsPerConnection);
   max_time_before_crypto_handshake_ =
       QuicTime::Delta::FromSeconds(kMaxTimeForCryptoHandshakeSecs);
@@ -694,7 +676,6 @@
 void QuicConfig::ToHandshakeMessage(CryptoHandshakeMessage* out) const {
   idle_network_timeout_seconds_.ToHandshakeMessage(out);
   silent_close_.ToHandshakeMessage(out);
-  max_streams_per_connection_.ToHandshakeMessage(out);
   max_incoming_dynamic_streams_.ToHandshakeMessage(out);
   bytes_for_connection_id_.ToHandshakeMessage(out);
   initial_round_trip_time_us_.ToHandshakeMessage(out);
@@ -723,10 +704,6 @@
         silent_close_.ProcessPeerHello(peer_hello, hello_type, error_details);
   }
   if (error == QUIC_NO_ERROR) {
-    error = max_streams_per_connection_.ProcessPeerHello(peer_hello, hello_type,
-                                                         error_details);
-  }
-  if (error == QUIC_NO_ERROR) {
     error = max_incoming_dynamic_streams_.ProcessPeerHello(
         peer_hello, hello_type, error_details);
   }
@@ -789,6 +766,14 @@
   }
   params->initial_max_bidi_streams.present = true;
   params->initial_max_bidi_streams.value = initial_max_streams;
+
+  if (!params->google_quic_params) {
+    params->google_quic_params = QuicMakeUnique<CryptoHandshakeMessage>();
+  }
+  silent_close_.ToHandshakeMessage(params->google_quic_params.get());
+  initial_round_trip_time_us_.ToHandshakeMessage(
+      params->google_quic_params.get());
+  connection_options_.ToHandshakeMessage(params->google_quic_params.get());
   return true;
 }
 
@@ -801,6 +786,26 @@
   if (error != QUIC_NO_ERROR) {
     return error;
   }
+  const CryptoHandshakeMessage* peer_params = params.google_quic_params.get();
+  if (!peer_params) {
+    return QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND;
+  }
+  error =
+      silent_close_.ProcessPeerHello(*peer_params, hello_type, error_details);
+  if (error != QUIC_NO_ERROR) {
+    return error;
+  }
+  error = initial_round_trip_time_us_.ProcessPeerHello(*peer_params, hello_type,
+                                                       error_details);
+  if (error != QUIC_NO_ERROR) {
+    return error;
+  }
+  error = connection_options_.ProcessPeerHello(*peer_params, hello_type,
+                                               error_details);
+  if (error != QUIC_NO_ERROR) {
+    return error;
+  }
+
   initial_stream_flow_control_window_bytes_.SetReceivedValue(
       params.initial_max_stream_data);
   initial_session_flow_control_window_bytes_.SetReceivedValue(
diff --git a/net/third_party/quic/core/quic_config.h b/net/third_party/quic/core/quic_config.h
index 7111f0e..e0e8809f8 100644
--- a/net/third_party/quic/core/quic_config.h
+++ b/net/third_party/quic/core/quic_config.h
@@ -305,10 +305,6 @@
 
   bool SilentClose() const;
 
-  void SetMaxStreamsPerConnection(size_t max_streams, size_t default_streams);
-
-  uint32_t MaxStreamsPerConnection() const;
-
   void SetMaxIncomingDynamicStreamsToSend(
       uint32_t max_incoming_dynamic_streams);
 
@@ -437,8 +433,6 @@
                                            HelloType hello_type,
                                            QuicString* error_details);
 
-  bool do_not_use_mspc() { return do_not_use_mspc_; }
-
  private:
   friend class test::QuicConfigPeer;
 
@@ -462,11 +456,6 @@
   QuicNegotiableUint32 idle_network_timeout_seconds_;
   // Whether to use silent close.  Defaults to 0 (false) and is otherwise true.
   QuicNegotiableUint32 silent_close_;
-  // Latched value of quic_reloadable_flag_quic_no_mspc.
-  const bool do_not_use_mspc_;
-  // Maximum number of streams that the connection can support.
-  // TODO(rch): Remove when removing quic_reloadable_flag_quic_no_mspc.
-  QuicNegotiableUint32 max_streams_per_connection_;
   // Maximum number of incoming dynamic streams that the connection can support.
   QuicFixedUint32 max_incoming_dynamic_streams_;
   // The number of bytes required for the connection ID.
diff --git a/net/third_party/quic/core/quic_config_test.cc b/net/third_party/quic/core/quic_config_test.cc
index 064fb75..c23e76dd 100644
--- a/net/third_party/quic/core/quic_config_test.cc
+++ b/net/third_party/quic/core/quic_config_test.cc
@@ -32,7 +32,6 @@
       kInitialSessionFlowControlWindowForTest);
   config_.SetIdleNetworkTimeout(QuicTime::Delta::FromSeconds(5),
                                 QuicTime::Delta::FromSeconds(2));
-  config_.SetMaxStreamsPerConnection(4, 2);
   CryptoHandshakeMessage msg;
   config_.ToHandshakeMessage(&msg);
 
@@ -41,10 +40,6 @@
   EXPECT_EQ(QUIC_NO_ERROR, error);
   EXPECT_EQ(5u, value);
 
-  error = msg.GetUint32(kMSPC, &value);
-  EXPECT_EQ(QUIC_NO_ERROR, error);
-  EXPECT_EQ(4u, value);
-
   error = msg.GetUint32(kSFCW, &value);
   EXPECT_EQ(QUIC_NO_ERROR, error);
   EXPECT_EQ(kInitialStreamFlowControlWindowForTest, value);
@@ -61,8 +56,6 @@
   client_config.SetIdleNetworkTimeout(
       QuicTime::Delta::FromSeconds(2 * kMaximumIdleTimeoutSecs),
       QuicTime::Delta::FromSeconds(kMaximumIdleTimeoutSecs));
-  client_config.SetMaxStreamsPerConnection(2 * kDefaultMaxStreamsPerConnection,
-                                           kDefaultMaxStreamsPerConnection);
   client_config.SetInitialRoundTripTimeUsToSend(10 * kNumMicrosPerMilli);
   client_config.SetInitialStreamFlowControlWindowToSend(
       2 * kInitialStreamFlowControlWindowForTest);
@@ -91,7 +84,6 @@
   EXPECT_TRUE(config_.negotiated());
   EXPECT_EQ(QuicTime::Delta::FromSeconds(kMaximumIdleTimeoutSecs),
             config_.IdleNetworkTimeout());
-  EXPECT_EQ(kDefaultMaxStreamsPerConnection, config_.MaxStreamsPerConnection());
   EXPECT_EQ(10 * kNumMicrosPerMilli, config_.ReceivedInitialRoundTripTimeUs());
   EXPECT_TRUE(config_.HasReceivedConnectionOptions());
   EXPECT_EQ(2u, config_.ReceivedConnectionOptions().size());
@@ -114,8 +106,6 @@
   server_config.SetIdleNetworkTimeout(
       QuicTime::Delta::FromSeconds(kMaximumIdleTimeoutSecs / 2),
       QuicTime::Delta::FromSeconds(kMaximumIdleTimeoutSecs / 2));
-  server_config.SetMaxStreamsPerConnection(kDefaultMaxStreamsPerConnection / 2,
-                                           kDefaultMaxStreamsPerConnection / 2);
   server_config.SetInitialRoundTripTimeUsToSend(10 * kNumMicrosPerMilli);
   server_config.SetInitialStreamFlowControlWindowToSend(
       2 * kInitialStreamFlowControlWindowForTest);
@@ -132,8 +122,6 @@
   EXPECT_TRUE(config_.negotiated());
   EXPECT_EQ(QuicTime::Delta::FromSeconds(kMaximumIdleTimeoutSecs / 2),
             config_.IdleNetworkTimeout());
-  EXPECT_EQ(kDefaultMaxStreamsPerConnection / 2,
-            config_.MaxStreamsPerConnection());
   EXPECT_EQ(10 * kNumMicrosPerMilli, config_.ReceivedInitialRoundTripTimeUs());
   EXPECT_EQ(config_.ReceivedInitialStreamFlowControlWindowBytes(),
             2 * kInitialStreamFlowControlWindowForTest);
diff --git a/net/third_party/quic/core/quic_connection.cc b/net/third_party/quic/core/quic_connection.cc
index e39cce5..0fab70d 100644
--- a/net/third_party/quic/core/quic_connection.cc
+++ b/net/third_party/quic/core/quic_connection.cc
@@ -210,7 +210,6 @@
               perspective),
       current_packet_content_(NO_FRAMES_RECEIVED),
       is_current_packet_connectivity_probing_(false),
-      current_peer_migration_type_(NO_CHANGE),
       current_effective_peer_migration_type_(NO_CHANGE),
       helper_(helper),
       alarm_factory_(alarm_factory),
@@ -223,8 +222,6 @@
       connection_id_(connection_id),
       peer_address_(initial_peer_address),
       direct_peer_address_(initial_peer_address),
-      active_peer_migration_type_(NO_CHANGE),
-      highest_packet_sent_before_peer_migration_(0),
       active_effective_peer_migration_type_(NO_CHANGE),
       highest_packet_sent_before_effective_peer_migration_(0),
       last_packet_decrypted_(false),
@@ -297,7 +294,8 @@
           clock_,
           &stats_,
           GetQuicReloadableFlag(quic_default_to_bbr) ? kBBR : kCubicBytes,
-          kNack),
+          kNack,
+          this),
       version_negotiation_state_(START_NEGOTIATION),
       perspective_(perspective),
       connected_(true),
@@ -320,9 +318,10 @@
       supports_release_time_(writer->SupportsReleaseTime()),
       pace_time_into_future_(QuicTime::Delta::FromMilliseconds(
           GetQuicFlag(FLAGS_quic_pace_time_into_future_ms))),
-      enable_server_proxy_(GetQuicReloadableFlag(quic_enable_server_proxy2)),
       deprecate_scheduler_(
-          GetQuicReloadableFlag(quic_deprecate_scoped_scheduler2)) {
+          GetQuicReloadableFlag(quic_deprecate_scoped_scheduler2)),
+      no_send_alarm_in_process_packet_if_write_blocked_(GetQuicReloadableFlag(
+          quic_no_send_alarm_in_process_packet_if_write_blocked)) {
   if (ack_mode_ == ACK_DECIMATION) {
     QUIC_FLAG_COUNT(quic_reloadable_flag_quic_enable_ack_decimation);
   }
@@ -503,6 +502,15 @@
   return false;
 }
 
+QuicString QuicConnection::DebugStringForAckProcessing() const {
+  return QuicStrCat(
+      "{sent_packet_manager: ",
+      sent_packet_manager_.DebugStringForAckProcessing(),
+      ", largest_seen_pkn_with_ack: ", largest_seen_packet_with_ack_,
+      ", max_generated_pkn: ", packet_generator_.packet_number(),
+      ", framer: ", framer_.VerboseDebugString(), "}");
+}
+
 void QuicConnection::OnError(QuicFramer* framer) {
   // Packets that we can not or have not decrypted are dropped.
   // TODO(rch): add stats to measure this.
@@ -751,7 +759,6 @@
 
 QuicSocketAddress QuicConnection::GetEffectivePeerAddressFromCurrentPacket()
     const {
-  DCHECK(enable_server_proxy_);
   // By default, the connection is not proxied, and the effective peer address
   // is the packet's source address, i.e. the direct peer address.
   return last_packet_source_address_;
@@ -772,66 +779,38 @@
   // Initialize the current packet content stats.
   current_packet_content_ = NO_FRAMES_RECEIVED;
   is_current_packet_connectivity_probing_ = false;
+  current_effective_peer_migration_type_ = NO_CHANGE;
 
-  if (!enable_server_proxy_) {
-    current_peer_migration_type_ = NO_CHANGE;
-
-    AddressChangeType peer_migration_type =
-        QuicUtils::DetermineAddressChangeType(peer_address_,
-                                              last_packet_source_address_);
-    // Initiate connection migration if a non-reordered packet is received from
-    // a new address.
-    if (header.packet_number > received_packet_manager_.GetLargestObserved() &&
-        peer_migration_type != NO_CHANGE) {
-      QUIC_DLOG(INFO) << ENDPOINT << "Peer's ip:port changed from "
-                      << peer_address_.ToString() << " to "
-                      << last_packet_source_address_.ToString();
-      if (perspective_ == Perspective::IS_CLIENT) {
-        peer_address_ = last_packet_source_address_;
-      } else if (active_peer_migration_type_ == NO_CHANGE) {
-        // Only migrate connection to a new peer address if there is no
-        // pending change underway.
-        // Cache the current migration change type, which will start peer
-        // migration immediately if this packet is not a connectivity probing
-        // packet.
-        current_peer_migration_type_ = peer_migration_type;
-      }
+  if (perspective_ == Perspective::IS_CLIENT) {
+    if (header.packet_number > received_packet_manager_.GetLargestObserved()) {
+      // Update peer_address_ and effective_peer_address_ immediately for
+      // client connections.
+      direct_peer_address_ = last_packet_source_address_;
+      effective_peer_address_ = GetEffectivePeerAddressFromCurrentPacket();
     }
   } else {
-    current_effective_peer_migration_type_ = NO_CHANGE;
+    // At server, remember the address change type of effective_peer_address
+    // in current_effective_peer_migration_type_. But this variable alone
+    // doesn't necessarily starts a migration. A migration will be started
+    // later, once the current packet is confirmed to meet the following
+    // conditions:
+    // 1) current_effective_peer_migration_type_ is not NO_CHANGE.
+    // 2) The current packet is not a connectivity probing.
+    // 3) The current packet is not reordered, i.e. its packet number is the
+    //    largest of this connection so far.
+    // Once the above conditions are confirmed, a new migration will start
+    // even if there is an active migration underway.
+    current_effective_peer_migration_type_ =
+        QuicUtils::DetermineAddressChangeType(
+            effective_peer_address_,
+            GetEffectivePeerAddressFromCurrentPacket());
 
-    if (perspective_ == Perspective::IS_CLIENT) {
-      if (header.packet_number >
-          received_packet_manager_.GetLargestObserved()) {
-        // Update peer_address_ and effective_peer_address_ immediately for
-        // client connections.
-        direct_peer_address_ = last_packet_source_address_;
-        effective_peer_address_ = GetEffectivePeerAddressFromCurrentPacket();
-      }
-    } else {
-      // At server, remember the address change type of effective_peer_address
-      // in current_effective_peer_migration_type_. But this variable alone
-      // doesn't necessarily starts a migration. A migration will be started
-      // later, once the current packet is confirmed to meet the following
-      // conditions:
-      // 1) current_effective_peer_migration_type_ is not NO_CHANGE.
-      // 2) The current packet is not a connectivity probing.
-      // 3) The current packet is not reordered, i.e. its packet number is the
-      //    largest of this connection so far.
-      // Once the above conditions are confirmed, a new migration will start
-      // even if there is an active migration underway.
-      current_effective_peer_migration_type_ =
-          QuicUtils::DetermineAddressChangeType(
-              effective_peer_address_,
-              GetEffectivePeerAddressFromCurrentPacket());
-
-      QUIC_DLOG_IF(INFO, current_effective_peer_migration_type_ != NO_CHANGE)
-          << ENDPOINT << "Effective peer's ip:port changed from "
-          << effective_peer_address_.ToString() << " to "
-          << GetEffectivePeerAddressFromCurrentPacket().ToString()
-          << ", active_effective_peer_migration_type is "
-          << active_effective_peer_migration_type_;
-    }
+    QUIC_DLOG_IF(INFO, current_effective_peer_migration_type_ != NO_CHANGE)
+        << ENDPOINT << "Effective peer's ip:port changed from "
+        << effective_peer_address_.ToString() << " to "
+        << GetEffectivePeerAddressFromCurrentPacket().ToString()
+        << ", active_effective_peer_migration_type is "
+        << active_effective_peer_migration_type_;
   }
 
   --stats_.packets_dropped;
@@ -958,10 +937,15 @@
     return true;
   }
 
-  if (largest_acked > packet_generator_.packet_number()) {
+  QuicPacketNumber largest_sent_packet = packet_generator_.packet_number();
+  if (GetQuicReloadableFlag(quic_validate_ack_largest_observed)) {
+    QUIC_FLAG_COUNT(quic_reloadable_flag_quic_validate_ack_largest_observed);
+    largest_sent_packet = sent_packet_manager_.GetLargestSentPacket();
+  }
+  if (largest_acked > largest_sent_packet) {
     QUIC_DLOG(WARNING) << ENDPOINT
                        << "Peer's observed unsent packet:" << largest_acked
-                       << " vs " << packet_generator_.packet_number();
+                       << " vs " << largest_sent_packet;
     // We got an error for data we have not sent.
     CloseConnection(QUIC_INVALID_ACK_DATA, "Largest observed too high.",
                     ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
@@ -1309,26 +1293,16 @@
     visitor_->OnConnectivityProbeReceived(last_packet_destination_address_,
                                           last_packet_source_address_);
   } else {
-    if (!enable_server_proxy_) {
-      if (current_peer_migration_type_ != NO_CHANGE) {
-        StartPeerMigration(current_peer_migration_type_);
-      }
-    } else {
-      if (last_header_.packet_number ==
-          received_packet_manager_.GetLargestObserved()) {
-        direct_peer_address_ = last_packet_source_address_;
-        if (current_effective_peer_migration_type_ != NO_CHANGE) {
-          StartEffectivePeerMigration(current_effective_peer_migration_type_);
-        }
+    if (last_header_.packet_number ==
+        received_packet_manager_.GetLargestObserved()) {
+      direct_peer_address_ = last_packet_source_address_;
+      if (current_effective_peer_migration_type_ != NO_CHANGE) {
+        StartEffectivePeerMigration(current_effective_peer_migration_type_);
       }
     }
   }
 
-  if (!enable_server_proxy_) {
-    current_peer_migration_type_ = NO_CHANGE;
-  } else {
-    current_effective_peer_migration_type_ = NO_CHANGE;
-  }
+  current_effective_peer_migration_type_ = NO_CHANGE;
 
   // An ack will be sent if a missing retransmittable packet was received;
   const bool was_missing =
@@ -1488,7 +1462,13 @@
   // Now that we have received an ack, we might be able to send packets which
   // are queued locally, or drain streams which are blocked.
   if (defer_send_in_response_to_packets_) {
-    send_alarm_->Update(clock_->ApproximateNow(), QuicTime::Delta::Zero());
+    if (!no_send_alarm_in_process_packet_if_write_blocked_ ||
+        !writer_->IsWriteBlocked()) {
+      send_alarm_->Update(clock_->ApproximateNow(), QuicTime::Delta::Zero());
+    } else {
+      QUIC_FLAG_COUNT(
+          quic_reloadable_flag_quic_no_send_alarm_in_process_packet_if_write_blocked);  // NOLINT
+    }
   } else {
     WriteAndBundleAcksIfNotBlocked();
   }
@@ -1641,27 +1621,20 @@
     self_address_ = last_packet_destination_address_;
   }
 
-  if (!enable_server_proxy_) {
-    if (!peer_address_.IsInitialized()) {
-      peer_address_ = last_packet_source_address_;
-    }
-  } else {
-    if (!direct_peer_address_.IsInitialized()) {
-      direct_peer_address_ = last_packet_source_address_;
-    }
+  if (!direct_peer_address_.IsInitialized()) {
+    direct_peer_address_ = last_packet_source_address_;
+  }
 
-    if (!effective_peer_address_.IsInitialized()) {
-      QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_enable_server_proxy2, 1, 3);
-      const QuicSocketAddress effective_peer_addr =
-          GetEffectivePeerAddressFromCurrentPacket();
+  if (!effective_peer_address_.IsInitialized()) {
+    const QuicSocketAddress effective_peer_addr =
+        GetEffectivePeerAddressFromCurrentPacket();
 
-      // effective_peer_address_ must be initialized at the beginning of the
-      // first packet processed(here). If effective_peer_addr is uninitialized,
-      // just set effective_peer_address_ to the direct peer address.
-      effective_peer_address_ = effective_peer_addr.IsInitialized()
-                                    ? effective_peer_addr
-                                    : direct_peer_address_;
-    }
+    // effective_peer_address_ must be initialized at the beginning of the
+    // first packet processed(here). If effective_peer_addr is uninitialized,
+    // just set effective_peer_address_ to the direct peer address.
+    effective_peer_address_ = effective_peer_addr.IsInitialized()
+                                  ? effective_peer_addr
+                                  : direct_peer_address_;
   }
 
   stats_.bytes_received += packet.length();
@@ -1700,28 +1673,20 @@
   }
 
   ++stats_.packets_processed;
-  if (!enable_server_proxy_) {
-    if (active_peer_migration_type_ != NO_CHANGE &&
-        sent_packet_manager_.GetLargestObserved() >
-            highest_packet_sent_before_peer_migration_) {
-      if (perspective_ == Perspective::IS_SERVER) {
-        OnPeerMigrationValidated();
-      }
-    }
-  } else {
-    QUIC_DLOG_IF(INFO, active_effective_peer_migration_type_ != NO_CHANGE)
-        << "sent_packet_manager_.GetLargestObserved() = "
-        << sent_packet_manager_.GetLargestObserved()
-        << ", highest_packet_sent_before_effective_peer_migration_ = "
-        << highest_packet_sent_before_effective_peer_migration_;
-    if (active_effective_peer_migration_type_ != NO_CHANGE &&
-        sent_packet_manager_.GetLargestObserved() >
-            highest_packet_sent_before_effective_peer_migration_) {
-      if (perspective_ == Perspective::IS_SERVER) {
-        OnEffectivePeerMigrationValidated();
-      }
+
+  QUIC_DLOG_IF(INFO, active_effective_peer_migration_type_ != NO_CHANGE)
+      << "sent_packet_manager_.GetLargestObserved() = "
+      << sent_packet_manager_.GetLargestObserved()
+      << ", highest_packet_sent_before_effective_peer_migration_ = "
+      << highest_packet_sent_before_effective_peer_migration_;
+  if (active_effective_peer_migration_type_ != NO_CHANGE &&
+      sent_packet_manager_.GetLargestObserved() >
+          highest_packet_sent_before_effective_peer_migration_) {
+    if (perspective_ == Perspective::IS_SERVER) {
+      OnEffectivePeerMigrationValidated();
     }
   }
+
   MaybeProcessUndecryptablePackets();
   MaybeSendInResponseToPacket();
   SetPingAlarm();
@@ -3027,49 +2992,7 @@
   DCHECK(!mtu_discovery_alarm_->IsSet());
 }
 
-void QuicConnection::OnPeerMigrationValidated() {
-  DCHECK(!enable_server_proxy_);
-  if (active_peer_migration_type_ == NO_CHANGE) {
-    QUIC_BUG << "No migration underway.";
-    return;
-  }
-  highest_packet_sent_before_peer_migration_ = 0;
-  active_peer_migration_type_ = NO_CHANGE;
-}
-
-// TODO(b/77906482): Modify method to start migration whenever a new IP address
-// is seen
-// from a packet with sequence number > the one that triggered the previous
-// migration. This should happen even if a migration is underway, since the
-// most recent migration is the one that we should pay attention to.
-void QuicConnection::StartPeerMigration(AddressChangeType peer_migration_type) {
-  DCHECK(!enable_server_proxy_);
-  // TODO(fayang): Currently, all peer address change type are allowed. Need to
-  // add a method ShouldAllowPeerAddressChange(PeerAddressChangeType type) to
-  // determine whether |type| is allowed.
-  if (active_peer_migration_type_ != NO_CHANGE ||
-      peer_migration_type == NO_CHANGE) {
-    QUIC_BUG << "Migration underway or no new migration started.";
-    return;
-  }
-  QUIC_DLOG(INFO) << ENDPOINT << "Peer's ip:port changed from "
-                  << peer_address_.ToString() << " to "
-                  << last_packet_source_address_.ToString()
-                  << ", migrating connection.";
-
-  highest_packet_sent_before_peer_migration_ =
-      sent_packet_manager_.GetLargestSentPacket();
-  peer_address_ = last_packet_source_address_;
-  active_peer_migration_type_ = peer_migration_type;
-
-  // TODO(b/77907041): Move these calls to OnPeerMigrationValidated. Rename
-  // OnConnectionMigration methods to OnPeerMigration.
-  OnConnectionMigration(peer_migration_type);
-}
-
 void QuicConnection::OnEffectivePeerMigrationValidated() {
-  DCHECK(enable_server_proxy_);
-  QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_enable_server_proxy2, 3, 3);
   if (active_effective_peer_migration_type_ == NO_CHANGE) {
     QUIC_BUG << "No migration underway.";
     return;
@@ -3078,13 +3001,7 @@
   active_effective_peer_migration_type_ = NO_CHANGE;
 }
 
-// TODO(wub): Modify method to start migration whenever a new IP address is seen
-// from a packet with sequence number > the one that triggered the previous
-// migration. This should happen even if a migration is underway, since the
-// most recent migration is the one that we should pay attention to.
 void QuicConnection::StartEffectivePeerMigration(AddressChangeType type) {
-  DCHECK(enable_server_proxy_);
-  QUIC_FLAG_COUNT_N(quic_reloadable_flag_quic_enable_server_proxy2, 2, 3);
   // TODO(fayang): Currently, all peer address change type are allowed. Need to
   // add a method ShouldAllowPeerAddressChange(PeerAddressChangeType type) to
   // determine whether |type| is allowed.
@@ -3113,16 +3030,7 @@
 }
 
 bool QuicConnection::IsCurrentPacketConnectivityProbing() const {
-  if (enable_server_proxy_) {
-    return is_current_packet_connectivity_probing_;
-  }
-
-  if (current_packet_content_ != SECOND_FRAME_IS_PADDING) {
-    return false;
-  }
-
-  return last_packet_source_address_ != peer_address_ ||
-         last_packet_destination_address_ != self_address_;
+  return is_current_packet_connectivity_probing_;
 }
 
 bool QuicConnection::ack_frame_updated() const {
@@ -3229,42 +3137,29 @@
   if (type == SECOND_FRAME_IS_PADDING) {
     if (current_packet_content_ == FIRST_FRAME_IS_PING) {
       current_packet_content_ = SECOND_FRAME_IS_PADDING;
-      if (enable_server_proxy_) {
-        if (perspective_ == Perspective::IS_SERVER) {
-          is_current_packet_connectivity_probing_ =
-              current_effective_peer_migration_type_ != NO_CHANGE;
-        } else {
-          is_current_packet_connectivity_probing_ =
-              (last_packet_source_address_ != peer_address_) ||
-              (last_packet_destination_address_ != self_address_);
-        }
+      if (perspective_ == Perspective::IS_SERVER) {
+        is_current_packet_connectivity_probing_ =
+            current_effective_peer_migration_type_ != NO_CHANGE;
+      } else {
+        is_current_packet_connectivity_probing_ =
+            (last_packet_source_address_ != peer_address_) ||
+            (last_packet_destination_address_ != self_address_);
       }
       return;
     }
   }
 
   current_packet_content_ = NOT_PADDED_PING;
-  if (!enable_server_proxy_) {
-    if (current_peer_migration_type_ == NO_CHANGE) {
-      return;
+  if (last_header_.packet_number ==
+      received_packet_manager_.GetLargestObserved()) {
+    direct_peer_address_ = last_packet_source_address_;
+    if (current_effective_peer_migration_type_ != NO_CHANGE) {
+      // Start effective peer migration immediately when the current packet is
+      // confirmed not a connectivity probing packet.
+      StartEffectivePeerMigration(current_effective_peer_migration_type_);
     }
-
-    // Start peer migration immediately when the current packet is confirmed not
-    // a connectivity probing packet.
-    StartPeerMigration(current_peer_migration_type_);
-    current_peer_migration_type_ = NO_CHANGE;
-  } else {
-    if (last_header_.packet_number ==
-        received_packet_manager_.GetLargestObserved()) {
-      direct_peer_address_ = last_packet_source_address_;
-      if (current_effective_peer_migration_type_ != NO_CHANGE) {
-        // Start effective peer migration immediately when the current packet is
-        // confirmed not a connectivity probing packet.
-        StartEffectivePeerMigration(current_effective_peer_migration_type_);
-      }
-    }
-    current_effective_peer_migration_type_ = NO_CHANGE;
   }
+  current_effective_peer_migration_type_ = NO_CHANGE;
 }
 
 void QuicConnection::MaybeEnableSessionDecidesWhatToWrite() {
diff --git a/net/third_party/quic/core/quic_connection.h b/net/third_party/quic/core/quic_connection.h
index fbd5258..0007237 100644
--- a/net/third_party/quic/core/quic_connection.h
+++ b/net/third_party/quic/core/quic_connection.h
@@ -31,6 +31,7 @@
 #include "net/third_party/quic/core/quic_alarm_factory.h"
 #include "net/third_party/quic/core/quic_blocked_writer_interface.h"
 #include "net/third_party/quic/core/quic_connection_stats.h"
+#include "net/third_party/quic/core/quic_debug_info_provider_interface.h"
 #include "net/third_party/quic/core/quic_framer.h"
 #include "net/third_party/quic/core/quic_one_block_arena.h"
 #include "net/third_party/quic/core/quic_packet_creator.h"
@@ -307,7 +308,8 @@
 };
 
 class QUIC_EXPORT_PRIVATE QuicConnection
-    : public QuicFramerVisitorInterface,
+    : public QuicDebugInfoProviderInterface,
+      public QuicFramerVisitorInterface,
       public QuicBlockedWriterInterface,
       public QuicPacketGenerator::DelegateInterface,
       public QuicSentPacketManager::NetworkChangeVisitor {
@@ -451,6 +453,9 @@
     return framer_.supported_versions();
   }
 
+  // From QuicConnectionDebugInfoProviderInterface
+  QuicString DebugStringForAckProcessing() const override;
+
   // From QuicFramerVisitorInterface
   void OnError(QuicFramer* framer) override;
   bool OnProtocolVersionMismatch(ParsedQuicVersion received_version) override;
@@ -542,19 +547,9 @@
     packet_generator_.set_debug_delegate(visitor);
   }
   const QuicSocketAddress& self_address() const { return self_address_; }
-  const QuicSocketAddress& peer_address() const {
-    if (enable_server_proxy_) {
-      return direct_peer_address_;
-    }
-    return peer_address_;
-  }
+  const QuicSocketAddress& peer_address() const { return direct_peer_address_; }
   const QuicSocketAddress& effective_peer_address() const {
-    if (enable_server_proxy_) {
-      return effective_peer_address_;
-    }
-    QUIC_BUG << "effective_peer_address() should only be called when "
-                "enable_server_proxy_ is true.";
-    return peer_address_;
+    return effective_peer_address_;
   }
   QuicConnectionId connection_id() const { return connection_id_; }
   const QuicClock* clock() const { return clock_; }
@@ -795,8 +790,6 @@
     per_packet_options_ = options;
   }
 
-  bool IsServerProxyEnabled() const { return enable_server_proxy_; }
-
   bool IsPathDegrading() const { return is_path_degrading_; }
 
   bool deprecate_scheduler() const { return deprecate_scheduler_; }
@@ -809,13 +802,6 @@
   // cannot be written immediately.
   virtual void SendOrQueuePacket(SerializedPacket* packet);
 
-  // Called after a packet is received from a new peer address and is decrypted.
-  // Starts validation of peer's address change.
-  virtual void StartPeerMigration(AddressChangeType peer_migration_type);
-
-  // Called when a peer address migration is validated.
-  virtual void OnPeerMigrationValidated();
-
   // Called after a packet is received from a new effective peer address and is
   // decrypted. Starts validation of effective peer's address change. Calls
   // OnConnectionMigration as soon as the address changed.
@@ -851,10 +837,6 @@
   // Returns the current per-packet options for the connection.
   PerPacketOptions* per_packet_options() { return per_packet_options_; }
 
-  AddressChangeType active_peer_migration_type() {
-    return active_peer_migration_type_;
-  }
-
   AddressChangeType active_effective_peer_migration_type() const {
     return active_effective_peer_migration_type_;
   }
@@ -1022,12 +1004,6 @@
   // true as soon as |current_packet_content_| is set to
   // SECOND_FRAME_IS_PADDING.
   bool is_current_packet_connectivity_probing_;
-  // Caches the current peer migration type if a peer migration might be
-  // initiated. As soon as the current packet is confirmed not a connectivity
-  // probe, peer migration will start.
-  // TODO(wub): Remove once quic_reloadable_flag_quic_enable_server_proxy2 is
-  // deprecated.
-  AddressChangeType current_peer_migration_type_;
   // Caches the current effective peer migration type if a effective peer
   // migration might be initiated. As soon as the current packet is confirmed
   // not a connectivity probe, effective peer migration will start.
@@ -1058,17 +1034,6 @@
   // proxy if the connection is proxied.
   QuicSocketAddress effective_peer_address_;
 
-  // Records change type when the peer initiates migration to a new peer
-  // address. Reset to NO_CHANGE after peer migration is validated.
-  // TODO(wub): Remove once quic_reloadable_flag_quic_enable_server_proxy2 is
-  // deprecated.
-  AddressChangeType active_peer_migration_type_;
-
-  // Records highest sent packet number when peer migration is started.
-  // TODO(wub): Remove once quic_reloadable_flag_quic_enable_server_proxy2 is
-  // deprecated.
-  QuicPacketNumber highest_packet_sent_before_peer_migration_;
-
   // Records change type when the effective peer initiates migration to a new
   // address. Reset to NO_CHANGE after effective peer migration is validated.
   AddressChangeType active_effective_peer_migration_type_;
@@ -1338,14 +1303,15 @@
   // supports_release_time_ is true.
   const QuicTime::Delta pace_time_into_future_;
 
-  // Latched value of quic_reloadable_flag_quic_enable_server_proxy2.
-  const bool enable_server_proxy_;
-
   // Latched value of quic_reloadable_flag_quic_deprecate_scoped_scheduler2.
   // TODO(fayang): Remove ScopedRetransmissionScheduler when deprecating
   // quic_reloadable_flag_quic_deprecate_scoped_scheduler2.
   const bool deprecate_scheduler_;
 
+  // Latched value of
+  // quic_reloadable_flag_quic_no_send_alarm_in_process_packet_if_write_blocked.
+  const bool no_send_alarm_in_process_packet_if_write_blocked_;
+
   DISALLOW_COPY_AND_ASSIGN(QuicConnection);
 };
 
diff --git a/net/third_party/quic/core/quic_connection_test.cc b/net/third_party/quic/core/quic_connection_test.cc
index 75dede98..22096f6e 100644
--- a/net/third_party/quic/core/quic_connection_test.cc
+++ b/net/third_party/quic/core/quic_connection_test.cc
@@ -788,7 +788,6 @@
         connection_id_length_(PACKET_8BYTE_CONNECTION_ID),
         notifier_(&connection_) {
     SetQuicFlag(&FLAGS_quic_supports_tls_handshake, true);
-    SetQuicReloadableFlag(quic_respect_ietf_header, true);
     connection_.set_defer_send_in_response_to_packets(GetParam().ack_response ==
                                                       AckResponse::kDefer);
     QuicFramerPeer::SetLastSerializedConnectionId(
@@ -1325,17 +1324,13 @@
   EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
   set_perspective(Perspective::IS_SERVER);
   QuicPacketCreatorPeer::SetSendVersionInPacket(creator_, false);
-  if (GetQuicReloadableFlag(quic_enable_server_proxy2)) {
-    // Clear direct_peer_address.
-    QuicConnectionPeer::SetDirectPeerAddress(&connection_, QuicSocketAddress());
-    // Clear effective_peer_address, it is the same as direct_peer_address for
-    // this test.
-    QuicConnectionPeer::SetEffectivePeerAddress(&connection_,
-                                                QuicSocketAddress());
-  } else {
-    // Clear peer_address.
-    QuicConnectionPeer::SetPeerAddress(&connection_, QuicSocketAddress());
-  }
+
+  // Clear direct_peer_address.
+  QuicConnectionPeer::SetDirectPeerAddress(&connection_, QuicSocketAddress());
+  // Clear effective_peer_address, it is the same as direct_peer_address for
+  // this test.
+  QuicConnectionPeer::SetEffectivePeerAddress(&connection_,
+                                              QuicSocketAddress());
 
   QuicPacketCreatorPeer::SetPacketNumber(&peer_creator_, 5);
   QuicStreamFrame stream_frame(1u, false, 0u, QuicStringPiece());
@@ -1346,9 +1341,7 @@
   ProcessFramePacketWithAddresses(QuicFrame(&stream_frame), kSelfAddress,
                                   kNewPeerAddress);
   EXPECT_EQ(kNewPeerAddress, connection_.peer_address());
-  if (GetQuicReloadableFlag(quic_enable_server_proxy2)) {
-    EXPECT_EQ(kNewPeerAddress, connection_.effective_peer_address());
-  }
+  EXPECT_EQ(kNewPeerAddress, connection_.effective_peer_address());
 
   // Decrease packet number to simulate out-of-order packets.
   QuicPacketCreatorPeer::SetPacketNumber(&peer_creator_, 4);
@@ -1357,9 +1350,7 @@
   ProcessFramePacketWithAddresses(QuicFrame(&stream_frame), kSelfAddress,
                                   kPeerAddress);
   EXPECT_EQ(kNewPeerAddress, connection_.peer_address());
-  if (GetQuicReloadableFlag(quic_enable_server_proxy2)) {
-    EXPECT_EQ(kNewPeerAddress, connection_.effective_peer_address());
-  }
+  EXPECT_EQ(kNewPeerAddress, connection_.effective_peer_address());
 }
 
 TEST_P(QuicConnectionTest, PeerAddressChangeAtServer) {
@@ -1368,28 +1359,20 @@
   QuicPacketCreatorPeer::SetSendVersionInPacket(creator_, false);
   EXPECT_EQ(Perspective::IS_SERVER, connection_.perspective());
 
-  if (GetQuicReloadableFlag(quic_enable_server_proxy2)) {
-    // Clear direct_peer_address.
-    QuicConnectionPeer::SetDirectPeerAddress(&connection_, QuicSocketAddress());
-    // Clear effective_peer_address, it is the same as direct_peer_address for
-    // this test.
-    QuicConnectionPeer::SetEffectivePeerAddress(&connection_,
-                                                QuicSocketAddress());
-    EXPECT_FALSE(connection_.effective_peer_address().IsInitialized());
-  } else {
-    // Clear peer_address.
-    QuicConnectionPeer::SetPeerAddress(&connection_, QuicSocketAddress());
-    EXPECT_FALSE(connection_.peer_address().IsInitialized());
-  }
+  // Clear direct_peer_address.
+  QuicConnectionPeer::SetDirectPeerAddress(&connection_, QuicSocketAddress());
+  // Clear effective_peer_address, it is the same as direct_peer_address for
+  // this test.
+  QuicConnectionPeer::SetEffectivePeerAddress(&connection_,
+                                              QuicSocketAddress());
+  EXPECT_FALSE(connection_.effective_peer_address().IsInitialized());
 
   QuicStreamFrame stream_frame(1u, false, 0u, QuicStringPiece());
   EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(AnyNumber());
   ProcessFramePacketWithAddresses(QuicFrame(&stream_frame), kSelfAddress,
                                   kPeerAddress);
   EXPECT_EQ(kPeerAddress, connection_.peer_address());
-  if (GetQuicReloadableFlag(quic_enable_server_proxy2)) {
-    EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
-  }
+  EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
 
   // Process another packet with a different peer address on server side will
   // start connection migration.
@@ -1399,16 +1382,10 @@
   ProcessFramePacketWithAddresses(QuicFrame(&stream_frame), kSelfAddress,
                                   kNewPeerAddress);
   EXPECT_EQ(kNewPeerAddress, connection_.peer_address());
-  if (GetQuicReloadableFlag(quic_enable_server_proxy2)) {
-    EXPECT_EQ(kNewPeerAddress, connection_.effective_peer_address());
-  }
+  EXPECT_EQ(kNewPeerAddress, connection_.effective_peer_address());
 }
 
 TEST_P(QuicConnectionTest, EffectivePeerAddressChangeAtServer) {
-  if (!GetQuicReloadableFlag(quic_enable_server_proxy2)) {
-    return;
-  }
-
   EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
   set_perspective(Perspective::IS_SERVER);
   QuicPacketCreatorPeer::SetSendVersionInPacket(creator_, false);
@@ -1496,28 +1473,20 @@
   QuicPacketCreatorPeer::SetSendVersionInPacket(creator_, false);
   EXPECT_EQ(Perspective::IS_SERVER, connection_.perspective());
 
-  if (GetQuicReloadableFlag(quic_enable_server_proxy2)) {
-    // Clear direct_peer_address.
-    QuicConnectionPeer::SetDirectPeerAddress(&connection_, QuicSocketAddress());
-    // Clear effective_peer_address, it is the same as direct_peer_address for
-    // this test.
-    QuicConnectionPeer::SetEffectivePeerAddress(&connection_,
-                                                QuicSocketAddress());
-    EXPECT_FALSE(connection_.effective_peer_address().IsInitialized());
-  } else {
-    // Clear peer_address.
-    QuicConnectionPeer::SetPeerAddress(&connection_, QuicSocketAddress());
-    EXPECT_FALSE(connection_.peer_address().IsInitialized());
-  }
+  // Clear direct_peer_address.
+  QuicConnectionPeer::SetDirectPeerAddress(&connection_, QuicSocketAddress());
+  // Clear effective_peer_address, it is the same as direct_peer_address for
+  // this test.
+  QuicConnectionPeer::SetEffectivePeerAddress(&connection_,
+                                              QuicSocketAddress());
+  EXPECT_FALSE(connection_.effective_peer_address().IsInitialized());
 
   QuicStreamFrame stream_frame(1u, false, 0u, QuicStringPiece());
   EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(AnyNumber());
   ProcessFramePacketWithAddresses(QuicFrame(&stream_frame), kSelfAddress,
                                   kPeerAddress);
   EXPECT_EQ(kPeerAddress, connection_.peer_address());
-  if (GetQuicReloadableFlag(quic_enable_server_proxy2)) {
-    EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
-  }
+  EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
 
   EXPECT_CALL(visitor_, OnConnectionMigration(PORT_CHANGE)).Times(0);
   EXPECT_CALL(visitor_, OnConnectivityProbeReceived(_, _)).Times(0);
@@ -1536,9 +1505,7 @@
 
   EXPECT_FALSE(connection_.IsCurrentPacketConnectivityProbing());
   EXPECT_EQ(kPeerAddress, connection_.peer_address());
-  if (GetQuicReloadableFlag(quic_enable_server_proxy2)) {
-    EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
-  }
+  EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
 }
 
 TEST_P(QuicConnectionTest, WriteOutOfOrderQueuedPackets) {
@@ -1606,28 +1573,20 @@
   QuicPacketCreatorPeer::SetSendVersionInPacket(creator_, false);
   EXPECT_EQ(Perspective::IS_SERVER, connection_.perspective());
 
-  if (GetQuicReloadableFlag(quic_enable_server_proxy2)) {
-    // Clear direct_peer_address.
-    QuicConnectionPeer::SetDirectPeerAddress(&connection_, QuicSocketAddress());
-    // Clear effective_peer_address, it is the same as direct_peer_address for
-    // this test.
-    QuicConnectionPeer::SetEffectivePeerAddress(&connection_,
-                                                QuicSocketAddress());
-    EXPECT_FALSE(connection_.effective_peer_address().IsInitialized());
-  } else {
-    // Clear peer_address.
-    QuicConnectionPeer::SetPeerAddress(&connection_, QuicSocketAddress());
-    EXPECT_FALSE(connection_.peer_address().IsInitialized());
-  }
+  // Clear direct_peer_address.
+  QuicConnectionPeer::SetDirectPeerAddress(&connection_, QuicSocketAddress());
+  // Clear effective_peer_address, it is the same as direct_peer_address for
+  // this test.
+  QuicConnectionPeer::SetEffectivePeerAddress(&connection_,
+                                              QuicSocketAddress());
+  EXPECT_FALSE(connection_.effective_peer_address().IsInitialized());
 
   QuicStreamFrame stream_frame(1u, false, 0u, QuicStringPiece());
   EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(AnyNumber());
   ProcessFramePacketWithAddresses(QuicFrame(&stream_frame), kSelfAddress,
                                   kPeerAddress);
   EXPECT_EQ(kPeerAddress, connection_.peer_address());
-  if (GetQuicReloadableFlag(quic_enable_server_proxy2)) {
-    EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
-  }
+  EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
 
   EXPECT_CALL(visitor_, OnConnectionMigration(PORT_CHANGE)).Times(0);
   EXPECT_CALL(visitor_, OnConnectivityProbeReceived(_, _)).Times(1);
@@ -1649,9 +1608,7 @@
 
   EXPECT_TRUE(connection_.IsCurrentPacketConnectivityProbing());
   EXPECT_EQ(kPeerAddress, connection_.peer_address());
-  if (GetQuicReloadableFlag(quic_enable_server_proxy2)) {
-    EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
-  }
+  EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
 
   // Process another packet with the old peer address on server side will not
   // start peer migration.
@@ -1659,9 +1616,7 @@
   ProcessFramePacketWithAddresses(QuicFrame(&stream_frame), kSelfAddress,
                                   kPeerAddress);
   EXPECT_EQ(kPeerAddress, connection_.peer_address());
-  if (GetQuicReloadableFlag(quic_enable_server_proxy2)) {
-    EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
-  }
+  EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
 }
 
 TEST_P(QuicConnectionTest, ReceiveReorderedConnectivityProbingAtServer) {
@@ -1670,19 +1625,13 @@
   QuicPacketCreatorPeer::SetSendVersionInPacket(creator_, false);
   EXPECT_EQ(Perspective::IS_SERVER, connection_.perspective());
 
-  if (GetQuicReloadableFlag(quic_enable_server_proxy2)) {
-    // Clear direct_peer_address.
-    QuicConnectionPeer::SetDirectPeerAddress(&connection_, QuicSocketAddress());
-    // Clear effective_peer_address, it is the same as direct_peer_address for
-    // this test.
-    QuicConnectionPeer::SetEffectivePeerAddress(&connection_,
-                                                QuicSocketAddress());
-    EXPECT_FALSE(connection_.effective_peer_address().IsInitialized());
-  } else {
-    // Clear peer_address.
-    QuicConnectionPeer::SetPeerAddress(&connection_, QuicSocketAddress());
-    EXPECT_FALSE(connection_.peer_address().IsInitialized());
-  }
+  // Clear direct_peer_address.
+  QuicConnectionPeer::SetDirectPeerAddress(&connection_, QuicSocketAddress());
+  // Clear effective_peer_address, it is the same as direct_peer_address for
+  // this test.
+  QuicConnectionPeer::SetEffectivePeerAddress(&connection_,
+                                              QuicSocketAddress());
+  EXPECT_FALSE(connection_.effective_peer_address().IsInitialized());
 
   QuicPacketCreatorPeer::SetPacketNumber(&peer_creator_, 5);
   QuicStreamFrame stream_frame(1u, false, 0u, QuicStringPiece());
@@ -1690,9 +1639,7 @@
   ProcessFramePacketWithAddresses(QuicFrame(&stream_frame), kSelfAddress,
                                   kPeerAddress);
   EXPECT_EQ(kPeerAddress, connection_.peer_address());
-  if (GetQuicReloadableFlag(quic_enable_server_proxy2)) {
-    EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
-  }
+  EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
 
   // Decrease packet number to simulate out-of-order packets.
   QuicPacketCreatorPeer::SetPacketNumber(&peer_creator_, 4);
@@ -1718,9 +1665,7 @@
 
   EXPECT_TRUE(connection_.IsCurrentPacketConnectivityProbing());
   EXPECT_EQ(kPeerAddress, connection_.peer_address());
-  if (GetQuicReloadableFlag(quic_enable_server_proxy2)) {
-    EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
-  }
+  EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
 }
 
 TEST_P(QuicConnectionTest, MigrateAfterProbingAtServer) {
@@ -1729,28 +1674,20 @@
   QuicPacketCreatorPeer::SetSendVersionInPacket(creator_, false);
   EXPECT_EQ(Perspective::IS_SERVER, connection_.perspective());
 
-  if (GetQuicReloadableFlag(quic_enable_server_proxy2)) {
-    // Clear direct_peer_address.
-    QuicConnectionPeer::SetDirectPeerAddress(&connection_, QuicSocketAddress());
-    // Clear effective_peer_address, it is the same as direct_peer_address for
-    // this test.
-    QuicConnectionPeer::SetEffectivePeerAddress(&connection_,
-                                                QuicSocketAddress());
-    EXPECT_FALSE(connection_.effective_peer_address().IsInitialized());
-  } else {
-    // Clear peer_address.
-    QuicConnectionPeer::SetPeerAddress(&connection_, QuicSocketAddress());
-    EXPECT_FALSE(connection_.peer_address().IsInitialized());
-  }
+  // Clear direct_peer_address.
+  QuicConnectionPeer::SetDirectPeerAddress(&connection_, QuicSocketAddress());
+  // Clear effective_peer_address, it is the same as direct_peer_address for
+  // this test.
+  QuicConnectionPeer::SetEffectivePeerAddress(&connection_,
+                                              QuicSocketAddress());
+  EXPECT_FALSE(connection_.effective_peer_address().IsInitialized());
 
   QuicStreamFrame stream_frame(1u, false, 0u, QuicStringPiece());
   EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(AnyNumber());
   ProcessFramePacketWithAddresses(QuicFrame(&stream_frame), kSelfAddress,
                                   kPeerAddress);
   EXPECT_EQ(kPeerAddress, connection_.peer_address());
-  if (GetQuicReloadableFlag(quic_enable_server_proxy2)) {
-    EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
-  }
+  EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
 
   EXPECT_CALL(visitor_, OnConnectionMigration(PORT_CHANGE)).Times(0);
   EXPECT_CALL(visitor_, OnConnectivityProbeReceived(_, _)).Times(1);
@@ -1769,9 +1706,7 @@
       clock_.Now()));
   ProcessReceivedPacket(kSelfAddress, kNewPeerAddress, *received);
   EXPECT_EQ(kPeerAddress, connection_.peer_address());
-  if (GetQuicReloadableFlag(quic_enable_server_proxy2)) {
-    EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
-  }
+  EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
 
   // Process another non-probing packet with the new peer address on server
   // side will start peer migration.
@@ -1780,9 +1715,7 @@
   ProcessFramePacketWithAddresses(QuicFrame(&stream_frame), kSelfAddress,
                                   kNewPeerAddress);
   EXPECT_EQ(kNewPeerAddress, connection_.peer_address());
-  if (GetQuicReloadableFlag(quic_enable_server_proxy2)) {
-    EXPECT_EQ(kNewPeerAddress, connection_.effective_peer_address());
-  }
+  EXPECT_EQ(kNewPeerAddress, connection_.effective_peer_address());
 }
 
 TEST_P(QuicConnectionTest, ReceivePaddedPingAtClient) {
@@ -1790,28 +1723,20 @@
   set_perspective(Perspective::IS_CLIENT);
   EXPECT_EQ(Perspective::IS_CLIENT, connection_.perspective());
 
-  if (GetQuicReloadableFlag(quic_enable_server_proxy2)) {
-    // Clear direct_peer_address.
-    QuicConnectionPeer::SetDirectPeerAddress(&connection_, QuicSocketAddress());
-    // Clear effective_peer_address, it is the same as direct_peer_address for
-    // this test.
-    QuicConnectionPeer::SetEffectivePeerAddress(&connection_,
-                                                QuicSocketAddress());
-    EXPECT_FALSE(connection_.effective_peer_address().IsInitialized());
-  } else {
-    // Clear peer_address.
-    QuicConnectionPeer::SetPeerAddress(&connection_, QuicSocketAddress());
-    EXPECT_FALSE(connection_.peer_address().IsInitialized());
-  }
+  // Clear direct_peer_address.
+  QuicConnectionPeer::SetDirectPeerAddress(&connection_, QuicSocketAddress());
+  // Clear effective_peer_address, it is the same as direct_peer_address for
+  // this test.
+  QuicConnectionPeer::SetEffectivePeerAddress(&connection_,
+                                              QuicSocketAddress());
+  EXPECT_FALSE(connection_.effective_peer_address().IsInitialized());
 
   QuicStreamFrame stream_frame(1u, false, 0u, QuicStringPiece());
   EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(AnyNumber());
   ProcessFramePacketWithAddresses(QuicFrame(&stream_frame), kSelfAddress,
                                   kPeerAddress);
   EXPECT_EQ(kPeerAddress, connection_.peer_address());
-  if (GetQuicReloadableFlag(quic_enable_server_proxy2)) {
-    EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
-  }
+  EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
 
   // Client takes all padded PING packet as speculative connectivity
   // probing packet, and reports to visitor.
@@ -1829,9 +1754,7 @@
 
   EXPECT_FALSE(connection_.IsCurrentPacketConnectivityProbing());
   EXPECT_EQ(kPeerAddress, connection_.peer_address());
-  if (GetQuicReloadableFlag(quic_enable_server_proxy2)) {
-    EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
-  }
+  EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
 }
 
 TEST_P(QuicConnectionTest, ReceiveConnectivityProbingAtClient) {
@@ -1839,28 +1762,20 @@
   set_perspective(Perspective::IS_CLIENT);
   EXPECT_EQ(Perspective::IS_CLIENT, connection_.perspective());
 
-  if (GetQuicReloadableFlag(quic_enable_server_proxy2)) {
-    // Clear direct_peer_address.
-    QuicConnectionPeer::SetDirectPeerAddress(&connection_, QuicSocketAddress());
-    // Clear effective_peer_address, it is the same as direct_peer_address for
-    // this test.
-    QuicConnectionPeer::SetEffectivePeerAddress(&connection_,
-                                                QuicSocketAddress());
-    EXPECT_FALSE(connection_.effective_peer_address().IsInitialized());
-  } else {
-    // Clear peer_address.
-    QuicConnectionPeer::SetPeerAddress(&connection_, QuicSocketAddress());
-    EXPECT_FALSE(connection_.peer_address().IsInitialized());
-  }
+  // Clear direct_peer_address.
+  QuicConnectionPeer::SetDirectPeerAddress(&connection_, QuicSocketAddress());
+  // Clear effective_peer_address, it is the same as direct_peer_address for
+  // this test.
+  QuicConnectionPeer::SetEffectivePeerAddress(&connection_,
+                                              QuicSocketAddress());
+  EXPECT_FALSE(connection_.effective_peer_address().IsInitialized());
 
   QuicStreamFrame stream_frame(1u, false, 0u, QuicStringPiece());
   EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(AnyNumber());
   ProcessFramePacketWithAddresses(QuicFrame(&stream_frame), kSelfAddress,
                                   kPeerAddress);
   EXPECT_EQ(kPeerAddress, connection_.peer_address());
-  if (GetQuicReloadableFlag(quic_enable_server_proxy2)) {
-    EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
-  }
+  EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
 
   // Process a padded PING packet with a different self address on client side
   // is effectively receiving a connectivity probing.
@@ -1881,9 +1796,7 @@
 
   EXPECT_TRUE(connection_.IsCurrentPacketConnectivityProbing());
   EXPECT_EQ(kPeerAddress, connection_.peer_address());
-  if (GetQuicReloadableFlag(quic_enable_server_proxy2)) {
-    EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
-  }
+  EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
 }
 
 TEST_P(QuicConnectionTest, PeerAddressChangeAtClient) {
@@ -1891,28 +1804,20 @@
   set_perspective(Perspective::IS_CLIENT);
   EXPECT_EQ(Perspective::IS_CLIENT, connection_.perspective());
 
-  if (GetQuicReloadableFlag(quic_enable_server_proxy2)) {
-    // Clear direct_peer_address.
-    QuicConnectionPeer::SetDirectPeerAddress(&connection_, QuicSocketAddress());
-    // Clear effective_peer_address, it is the same as direct_peer_address for
-    // this test.
-    QuicConnectionPeer::SetEffectivePeerAddress(&connection_,
-                                                QuicSocketAddress());
-    EXPECT_FALSE(connection_.effective_peer_address().IsInitialized());
-  } else {
-    // Clear peer_address.
-    QuicConnectionPeer::SetPeerAddress(&connection_, QuicSocketAddress());
-    EXPECT_FALSE(connection_.peer_address().IsInitialized());
-  }
+  // Clear direct_peer_address.
+  QuicConnectionPeer::SetDirectPeerAddress(&connection_, QuicSocketAddress());
+  // Clear effective_peer_address, it is the same as direct_peer_address for
+  // this test.
+  QuicConnectionPeer::SetEffectivePeerAddress(&connection_,
+                                              QuicSocketAddress());
+  EXPECT_FALSE(connection_.effective_peer_address().IsInitialized());
 
   QuicStreamFrame stream_frame(1u, false, 0u, QuicStringPiece());
   EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(AnyNumber());
   ProcessFramePacketWithAddresses(QuicFrame(&stream_frame), kSelfAddress,
                                   kPeerAddress);
   EXPECT_EQ(kPeerAddress, connection_.peer_address());
-  if (GetQuicReloadableFlag(quic_enable_server_proxy2)) {
-    EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
-  }
+  EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
 
   // Process another packet with a different peer address on client side will
   // only update peer address.
@@ -1922,9 +1827,7 @@
   ProcessFramePacketWithAddresses(QuicFrame(&stream_frame), kSelfAddress,
                                   kNewPeerAddress);
   EXPECT_EQ(kNewPeerAddress, connection_.peer_address());
-  if (GetQuicReloadableFlag(quic_enable_server_proxy2)) {
-    EXPECT_EQ(kNewPeerAddress, connection_.effective_peer_address());
-  }
+  EXPECT_EQ(kNewPeerAddress, connection_.effective_peer_address());
 }
 
 TEST_P(QuicConnectionTest, MaxPacketSize) {
@@ -3197,6 +3100,45 @@
   EXPECT_EQ(1u, writer_->packets_write_attempts());
 }
 
+TEST_P(QuicConnectionTest, NoSendAlarmAfterProcessPacketWhenWriteBlocked) {
+  // We are testing the behavior of
+  // quic_reloadable_flag_quic_no_send_alarm_in_process_packet_if_write_blocked,
+  // which only takes effect when ack_response == AckResponse::kDefer.
+  if (GetParam().ack_response != AckResponse::kDefer) {
+    return;
+  }
+
+  EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
+
+  // Block the connection.
+  BlockOnNextWrite();
+  connection_.SendStreamDataWithString(3, "foo", 0, NO_FIN);
+  EXPECT_TRUE(writer_->IsWriteBlocked());
+  EXPECT_EQ(1u, connection_.NumQueuedPackets());
+  EXPECT_FALSE(connection_.GetSendAlarm()->IsSet());
+
+  EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
+  // Process packet number 1. Can not call ProcessPacket or ProcessDataPacket
+  // here, because they will fire the alarm after QuicConnection::ProcessPacket
+  // is returned.
+  const QuicPacketNumber received_packet_num = 1;
+  const bool has_stop_waiting = false;
+  const EncryptionLevel level = ENCRYPTION_NONE;
+  std::unique_ptr<QuicPacket> packet(
+      ConstructDataPacket(received_packet_num, has_stop_waiting));
+  char buffer[kMaxPacketSize];
+  size_t encrypted_length = peer_framer_.EncryptPayload(
+      level, received_packet_num, *packet, buffer, kMaxPacketSize);
+  connection_.ProcessUdpPacket(
+      kSelfAddress, kPeerAddress,
+      QuicReceivedPacket(buffer, encrypted_length, clock_.Now(), false));
+
+  EXPECT_TRUE(writer_->IsWriteBlocked());
+  EXPECT_NE(GetQuicReloadableFlag(
+                quic_no_send_alarm_in_process_packet_if_write_blocked),
+            connection_.GetSendAlarm()->IsSet());
+}
+
 TEST_P(QuicConnectionTest, NoLimitPacketsPerNack) {
   EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
   int offset = 0;
@@ -5782,6 +5724,11 @@
 }
 
 TEST_P(QuicConnectionTest, GoAway) {
+  if (GetParam().version.transport_version == QUIC_VERSION_99) {
+    // GoAway is not available in version 99.
+    return;
+  }
+
   EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
 
   QuicGoAwayFrame goaway;
@@ -7041,6 +6988,18 @@
   EXPECT_TRUE(connection_.IsValidStatelessResetToken(kTestToken));
 }
 
+TEST_P(QuicConnectionTest, WriteBlockedWithInvalidAck) {
+  SetQuicReloadableFlag(quic_validate_ack_largest_observed, true);
+  EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
+  EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_INVALID_ACK_DATA, _, _));
+
+  BlockOnNextWrite();
+  connection_.SendStreamDataWithString(5, "foo", 0, FIN);
+  // This causes connection to be closed because packet 1 has not been sent yet.
+  QuicAckFrame frame = InitAckFrame(1);
+  ProcessAckPacket(1, &frame);
+}
+
 }  // namespace
 }  // namespace test
 }  // namespace quic
diff --git a/net/third_party/quic/core/quic_crypto_client_stream.cc b/net/third_party/quic/core/quic_crypto_client_stream.cc
index 08662aa1..58fdfa4 100644
--- a/net/third_party/quic/core/quic_crypto_client_stream.cc
+++ b/net/third_party/quic/core/quic_crypto_client_stream.cc
@@ -46,7 +46,8 @@
     case PROTOCOL_TLS1_3:
       handshaker_ = QuicMakeUnique<TlsClientHandshaker>(
           this, session, server_id, crypto_config->proof_verifier(),
-          crypto_config->ssl_ctx(), verify_context);
+          crypto_config->ssl_ctx(), verify_context,
+          crypto_config->user_agent_id());
       break;
     case PROTOCOL_UNSUPPORTED:
       QUIC_BUG << "Attempting to create QuicCryptoClientStream for unknown "
diff --git a/net/third_party/quic/core/quic_crypto_client_stream_test.cc b/net/third_party/quic/core/quic_crypto_client_stream_test.cc
index e45f50e1..8af9ac8 100644
--- a/net/third_party/quic/core/quic_crypto_client_stream_test.cc
+++ b/net/third_party/quic/core/quic_crypto_client_stream_test.cc
@@ -41,7 +41,6 @@
         server_id_(kServerHostname, kServerPort, net::PRIVACY_MODE_DISABLED),
         crypto_config_(crypto_test_utils::ProofVerifierForTesting(),
                        TlsClientHandshaker::CreateSslCtx()) {
-    SetQuicReloadableFlag(quic_respect_ietf_header, true);
     CreateConnection();
   }
 
@@ -138,7 +137,6 @@
 
   const QuicConfig* config = session_->config();
   EXPECT_EQ(kMaximumIdleTimeoutSecs, config->IdleNetworkTimeout().ToSeconds());
-  EXPECT_EQ(kDefaultMaxStreamsPerConnection, config->MaxStreamsPerConnection());
 
   const QuicCryptoNegotiatedParameters& crypto_params(
       stream()->crypto_negotiated_params());
@@ -391,7 +389,6 @@
         server_compressed_certs_cache_(
             QuicCompressedCertsCache::kQuicCompressedCertsCacheSize),
         server_id_(kServerHostname, kServerPort, net::PRIVACY_MODE_DISABLED) {
-    SetQuicReloadableFlag(quic_respect_ietf_header, true);
     TestQuicSpdyClientSession* client_session = nullptr;
     CreateClientSessionForTest(server_id_,
                                /* supports_stateless_rejects= */ true,
diff --git a/net/third_party/quic/core/quic_crypto_server_stream_test.cc b/net/third_party/quic/core/quic_crypto_server_stream_test.cc
index 85c8ca5..0f3d8f92 100644
--- a/net/third_party/quic/core/quic_crypto_server_stream_test.cc
+++ b/net/third_party/quic/core/quic_crypto_server_stream_test.cc
@@ -91,7 +91,6 @@
   // Initializes the crypto server stream state for testing.  May be
   // called multiple times.
   void InitializeServer() {
-    SetQuicReloadableFlag(quic_respect_ietf_header, true);
     TestQuicSpdyServerSession* server_session = nullptr;
     helpers_.push_back(QuicMakeUnique<NiceMock<MockQuicConnectionHelper>>());
     alarm_factories_.push_back(QuicMakeUnique<MockAlarmFactory>());
diff --git a/net/third_party/quic/core/quic_data_reader.cc b/net/third_party/quic/core/quic_data_reader.cc
index e80e038..f31cb7f 100644
--- a/net/third_party/quic/core/quic_data_reader.cc
+++ b/net/third_party/quic/core/quic_data_reader.cc
@@ -10,6 +10,7 @@
 #include "net/third_party/quic/platform/api/quic_flags.h"
 #include "net/third_party/quic/platform/api/quic_logging.h"
 #include "net/third_party/quic/platform/api/quic_str_cat.h"
+#include "net/third_party/quic/platform/api/quic_text_utils.h"
 
 namespace quic {
 
@@ -285,4 +286,9 @@
   return QuicStrCat(" { length: ", len_, ", position: ", pos_, " }");
 }
 
+QuicString QuicDataReader::VerboseDebugString() const {
+  return QuicStrCat(" {length: ", len_, ", position: ", pos_, " data:\n",
+                    QuicTextUtils::HexDump(QuicStringPiece(data_, len_)), " }");
+}
+
 }  // namespace quic
diff --git a/net/third_party/quic/core/quic_data_reader.h b/net/third_party/quic/core/quic_data_reader.h
index 6b2724eb..2832c470 100644
--- a/net/third_party/quic/core/quic_data_reader.h
+++ b/net/third_party/quic/core/quic_data_reader.h
@@ -140,6 +140,8 @@
 
   QuicString DebugString() const;
 
+  QuicString VerboseDebugString() const;
+
  private:
   // Returns true if the underlying buffer has enough room to read the given
   // amount of bytes.
diff --git a/net/third_party/quic/core/quic_debug_info_provider_interface.h b/net/third_party/quic/core/quic_debug_info_provider_interface.h
new file mode 100644
index 0000000..9d7afa3
--- /dev/null
+++ b/net/third_party/quic/core/quic_debug_info_provider_interface.h
@@ -0,0 +1,23 @@
+// 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.
+
+#ifndef NET_THIRD_PARTY_QUIC_CORE_QUIC_DEBUG_INFO_PROVIDER_INTERFACE_H_
+#define NET_THIRD_PARTY_QUIC_CORE_QUIC_DEBUG_INFO_PROVIDER_INTERFACE_H_
+
+#include "net/third_party/quic/platform/api/quic_export.h"
+#include "net/third_party/quic/platform/api/quic_string.h"
+
+namespace quic {
+
+class QUIC_EXPORT_PRIVATE QuicDebugInfoProviderInterface {
+ public:
+  virtual ~QuicDebugInfoProviderInterface() {}
+
+  // Get ack processing related debug information of the connection.
+  virtual QuicString DebugStringForAckProcessing() const = 0;
+};
+
+}  // namespace quic
+
+#endif  // NET_THIRD_PARTY_QUIC_CORE_QUIC_DEBUG_INFO_PROVIDER_INTERFACE_H_
diff --git a/net/third_party/quic/core/quic_dispatcher.cc b/net/third_party/quic/core/quic_dispatcher.cc
index 385723a..394e14e 100644
--- a/net/third_party/quic/core/quic_dispatcher.cc
+++ b/net/third_party/quic/core/quic_dispatcher.cc
@@ -138,7 +138,7 @@
     creator_.Flush();
     DCHECK_EQ(1u, collector_.packets()->size());
     time_wait_list_manager_->AddConnectionIdToTimeWait(
-        connection_id_, framer_->version(), framer_->last_packet_is_ietf_quic(),
+        connection_id_, framer_->last_packet_is_ietf_quic(),
         QuicTimeWaitListManager::SEND_TERMINATION_PACKETS,
         collector_.packets());
   }
@@ -167,7 +167,7 @@
       creator_.Flush();
     }
     time_wait_list_manager_->AddConnectionIdToTimeWait(
-        connection_id_, framer_->version(), framer_->last_packet_is_ietf_quic(),
+        connection_id_, framer_->last_packet_is_ietf_quic(),
         QuicTimeWaitListManager::SEND_TERMINATION_PACKETS,
         collector_.packets());
     DCHECK(time_wait_list_manager_->IsConnectionIdInTimeWait(connection_id_));
@@ -362,9 +362,11 @@
   }
 
   if (time_wait_list_manager_->IsConnectionIdInTimeWait(connection_id)) {
-    // Set the framer's version based on the recorded version for this
-    // connection and continue processing for non-public-reset packets.
-    return HandlePacketForTimeWait(header);
+    // This connection ID is already in time-wait state.
+    time_wait_list_manager_->ProcessPacket(current_self_address_,
+                                           current_peer_address_,
+                                           header.destination_connection_id);
+    return false;
   }
 
   // The packet has an unknown connection ID.
@@ -398,16 +400,6 @@
 
 bool QuicDispatcher::OnUnauthenticatedHeader(const QuicPacketHeader& header) {
   QuicConnectionId connection_id = header.destination_connection_id;
-
-  if (time_wait_list_manager_->IsConnectionIdInTimeWait(
-          header.destination_connection_id)) {
-    // This connection ID is already in time-wait state.
-    time_wait_list_manager_->ProcessPacket(current_self_address_,
-                                           current_peer_address_,
-                                           header.destination_connection_id);
-    return false;
-  }
-
   // Packet's connection ID is unknown.  Apply the validity checks.
   QuicPacketFate fate = ValidityChecks(header);
   if (fate == kFateProcess) {
@@ -441,7 +433,7 @@
         QUIC_DLOG(INFO) << "Adding connection ID " << connection_id
                         << "to time-wait list.";
         StatelesslyTerminateConnection(
-            connection_id, framer_.version(), framer()->GetLastPacketFormat(),
+            connection_id, framer()->GetLastPacketFormat(),
             QUIC_HANDSHAKE_FAILED, "Reject connection",
             quic::QuicTimeWaitListManager::SEND_STATELESS_RESET);
       }
@@ -535,8 +527,7 @@
     action = QuicTimeWaitListManager::DO_NOTHING;
   }
   time_wait_list_manager_->AddConnectionIdToTimeWait(
-      it->first, connection->version(),
-      connection->transport_version() > QUIC_VERSION_43, action,
+      it->first, connection->transport_version() > QUIC_VERSION_43, action,
       connection->termination_packets());
   session_map_.erase(it);
 }
@@ -643,7 +634,6 @@
 
 void QuicDispatcher::StatelesslyTerminateConnection(
     QuicConnectionId connection_id,
-    const ParsedQuicVersion& version,
     PacketHeaderFormat format,
     QuicErrorCode error_code,
     const QuicString& error_details,
@@ -658,7 +648,7 @@
   }
 
   time_wait_list_manager_->AddConnectionIdToTimeWait(
-      connection_id, version, format != GOOGLE_QUIC_PACKET, action,
+      connection_id, format != GOOGLE_QUIC_PACKET, action,
       /*termination_packets=*/nullptr);
 }
 
@@ -829,7 +819,7 @@
     QuicConnectionId connection_id,
     BufferedPacketList early_arrived_packets) {
   StatelesslyTerminateConnection(
-      connection_id, framer_.version(),
+      connection_id,
       early_arrived_packets.ietf_quic ? IETF_QUIC_LONG_HEADER_PACKET
                                       : GOOGLE_QUIC_PACKET,
       QUIC_HANDSHAKE_FAILED, "Packets buffered for too long",
@@ -909,9 +899,8 @@
   if (!accept_new_connections_) {
     // Don't any create new connection.
     StatelesslyTerminateConnection(
-        current_connection_id(), framer_.version(),
-        framer()->GetLastPacketFormat(), QUIC_HANDSHAKE_FAILED,
-        "Stop accepting new connections",
+        current_connection_id(), framer()->GetLastPacketFormat(),
+        QUIC_HANDSHAKE_FAILED, "Stop accepting new connections",
         quic::QuicTimeWaitListManager::SEND_STATELESS_RESET);
     // Time wait list will reject the packet correspondingly.
     time_wait_list_manager()->ProcessPacket(current_self_address(),
@@ -963,22 +952,6 @@
   return true;
 }
 
-bool QuicDispatcher::HandlePacketForTimeWait(const QuicPacketHeader& header) {
-  if (header.reset_flag) {
-    // Public reset packets do not have packet numbers, so ignore the packet.
-    return false;
-  }
-
-  // Switch the framer to the correct version, so that the packet number can
-  // be parsed correctly.
-  framer_.set_version(time_wait_list_manager_->GetQuicVersionFromConnectionId(
-      header.destination_connection_id));
-
-  // Continue parsing the packet to extract the packet number.  Then
-  // send it to the time wait manager in OnUnathenticatedHeader.
-  return true;
-}
-
 QuicPacketWriter* QuicDispatcher::CreatePerConnectionWriter() {
   return new QuicPerConnectionPacketWriter(writer_.get());
 }
diff --git a/net/third_party/quic/core/quic_dispatcher.h b/net/third_party/quic/core/quic_dispatcher.h
index ca49a301..9393fcc 100644
--- a/net/third_party/quic/core/quic_dispatcher.h
+++ b/net/third_party/quic/core/quic_dispatcher.h
@@ -331,7 +331,6 @@
   // list with |action|.
   void StatelesslyTerminateConnection(
       QuicConnectionId connection_id,
-      const ParsedQuicVersion& version,
       PacketHeaderFormat format,
       QuicErrorCode error_code,
       const QuicString& error_details,
@@ -348,8 +347,6 @@
 
   typedef QuicUnorderedSet<QuicConnectionId> QuicConnectionIdSet;
 
-  bool HandlePacketForTimeWait(const QuicPacketHeader& header);
-
   // Attempts to reject the connection statelessly, if stateless rejects are
   // possible and if the current packet contains a CHLO message.  Determines a
   // fate which describes what subsequent processing should be performed on the
diff --git a/net/third_party/quic/core/quic_dispatcher_test.cc b/net/third_party/quic/core/quic_dispatcher_test.cc
index 67a3fa7..4c8e140 100644
--- a/net/third_party/quic/core/quic_dispatcher_test.cc
+++ b/net/third_party/quic/core/quic_dispatcher_test.cc
@@ -216,9 +216,7 @@
         time_wait_list_manager_(nullptr),
         session1_(nullptr),
         session2_(nullptr),
-        store_(nullptr) {
-    SetQuicReloadableFlag(quic_respect_ietf_header, true);
-  }
+        store_(nullptr) {}
 
   void SetUp() override {
     dispatcher_->InitializeWithWriter(new QuicDefaultPacketWriter(1));
@@ -562,8 +560,7 @@
   // wait list manager.
   EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, connection_id))
       .Times(1);
-  EXPECT_CALL(*time_wait_list_manager_,
-              AddConnectionIdToTimeWait(_, _, _, _, _))
+  EXPECT_CALL(*time_wait_list_manager_, AddConnectionIdToTimeWait(_, _, _, _))
       .Times(0);
   ProcessPacket(client_address, connection_id, true, "data");
 }
@@ -579,8 +576,7 @@
       .Times(0);
   EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, connection_id))
       .Times(1);
-  EXPECT_CALL(*time_wait_list_manager_,
-              AddConnectionIdToTimeWait(_, _, _, _, _))
+  EXPECT_CALL(*time_wait_list_manager_, AddConnectionIdToTimeWait(_, _, _, _))
       .Times(1);
   ProcessPacket(client_address, connection_id, false, SerializeCHLO());
 }
@@ -596,8 +592,7 @@
               CreateQuicSession(1, client_address, QuicStringPiece("hq")))
       .Times(0);
   EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, _)).Times(0);
-  EXPECT_CALL(*time_wait_list_manager_,
-              AddConnectionIdToTimeWait(_, _, _, _, _))
+  EXPECT_CALL(*time_wait_list_manager_, AddConnectionIdToTimeWait(_, _, _, _))
       .Times(0);
   ProcessPacket(client_address, 1, true, SerializeCHLO());
 }
@@ -642,8 +637,7 @@
       .Times(0);
   EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, 1)).Times(1);
   EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, 2)).Times(1);
-  EXPECT_CALL(*time_wait_list_manager_,
-              AddConnectionIdToTimeWait(_, _, _, _, _))
+  EXPECT_CALL(*time_wait_list_manager_, AddConnectionIdToTimeWait(_, _, _, _))
       .Times(2);
   // A packet whose packet number is one to large to be allowed to start a
   // connection.
@@ -1183,15 +1177,13 @@
   if (CurrentSupportedVersions()[0].transport_version > QUIC_VERSION_43) {
     // This IETF packet has invalid connection ID length.
     EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, _)).Times(0);
-    EXPECT_CALL(*time_wait_list_manager_,
-                AddConnectionIdToTimeWait(_, _, _, _, _))
+    EXPECT_CALL(*time_wait_list_manager_, AddConnectionIdToTimeWait(_, _, _, _))
         .Times(0);
   } else {
     // This GQUIC packet is considered as IETF QUIC packet with short header
     // with unacceptable packet number.
     EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, _)).Times(1);
-    EXPECT_CALL(*time_wait_list_manager_,
-                AddConnectionIdToTimeWait(_, _, _, _, _))
+    EXPECT_CALL(*time_wait_list_manager_, AddConnectionIdToTimeWait(_, _, _, _))
         .Times(1);
   }
   ProcessPacket(client_address, connection_id, true, "data",
@@ -2114,7 +2106,7 @@
     InSequence s;
     EXPECT_CALL(check, Call(1));
     EXPECT_CALL(*time_wait_list_manager_,
-                AddConnectionIdToTimeWait(conn_id, _, _, _, _));
+                AddConnectionIdToTimeWait(conn_id, _, _, _));
     EXPECT_CALL(*time_wait_list_manager_,
                 ProcessPacket(_, client_addr_, conn_id));
 
@@ -2242,7 +2234,7 @@
     EXPECT_CALL(*dispatcher_, CreateQuicSession(conn_id_2, client_addr_, _))
         .Times(0);
     EXPECT_CALL(*time_wait_list_manager_,
-                AddConnectionIdToTimeWait(conn_id_2, _, _, _, _));
+                AddConnectionIdToTimeWait(conn_id_2, _, _, _));
     EXPECT_CALL(*time_wait_list_manager_,
                 ProcessPacket(_, client_addr_, conn_id_2));
 
@@ -2256,7 +2248,7 @@
 
     EXPECT_CALL(check, Call(4));
     EXPECT_CALL(*time_wait_list_manager_,
-                AddConnectionIdToTimeWait(conn_id_1, _, _, _, _));
+                AddConnectionIdToTimeWait(conn_id_1, _, _, _));
     EXPECT_CALL(*time_wait_list_manager_,
                 ProcessPacket(_, client_addr_, conn_id_1));
   }
@@ -2316,7 +2308,7 @@
                 CreateQuicSession(conn_id_1, client_addr_, QuicStringPiece()))
         .Times(0);
     EXPECT_CALL(*time_wait_list_manager_,
-                AddConnectionIdToTimeWait(conn_id_1, _, _, _, _));
+                AddConnectionIdToTimeWait(conn_id_1, _, _, _));
     EXPECT_CALL(*time_wait_list_manager_,
                 ProcessPacket(_, client_addr_, conn_id_1));
   }
diff --git a/net/third_party/quic/core/quic_flags_list.h b/net/third_party/quic/core/quic_flags_list.h
index 980d623..0ce2bc5 100644
--- a/net/third_party/quic/core/quic_flags_list.h
+++ b/net/third_party/quic/core/quic_flags_list.h
@@ -69,7 +69,7 @@
 QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_enable_3rtos, false)
 
 // If true, enable experiment for testing PCC congestion-control.
-QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_enable_pcc, false)
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_enable_pcc2, false)
 
 // When true, defaults to BBR congestion control instead of Cubic.
 QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_default_to_bbr, false)
@@ -118,16 +118,10 @@
     FLAGS_quic_reloadable_flag_quic_clear_queued_packets_before_sending_connectivity_probing,
     false)
 
-// If true, enable server proxy support in QUIC.
-QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_enable_server_proxy2, true)
-
 // When true, set the initial congestion control window from connection options
 // in QuicSentPacketManager rather than TcpCubicSenderBytes.
 QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_unified_iw_options, false)
 
-// If true, do not use QUIC's MSPC handshake tag and instead require MIDS.
-QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_no_mspc, true)
-
 // Number of packets that the pacing sender allows in bursts during pacing.
 QUIC_FLAG(int32_t, FLAGS_quic_lumpy_pacing_size, 1)
 
@@ -135,14 +129,6 @@
 // pacing.
 QUIC_FLAG(double, FLAGS_quic_lumpy_pacing_cwnd_fraction, 0.25f)
 
-// If true, respect IETF QUIC header format.
-QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_respect_ietf_header, true)
-
-// If true, detect losses from last largest lost packet number.
-QUIC_FLAG(bool,
-          FLAGS_quic_reloadable_flag_quic_incremental_loss_detection,
-          true)
-
 // Default enables QUIC ack decimation and adds a connection option to disable
 // it.
 QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_enable_ack_decimation, false)
@@ -151,13 +137,6 @@
 // retransmission timeout, instead of 2.
 QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_one_rto, false)
 
-// Modify QuicVersionManager so that the QuicTransportVersionVector returned by
-// GetSupportedTransportVersions contains a unique list of entries.
-QUIC_FLAG(
-    bool,
-    FLAGS_quic_reloadable_flag_quic_version_manager_dedupe_transport_versions,
-    true)
-
 // When true, the NRTT QUIC connection option causes receivers to ignore
 // incoming initial RTT values.
 QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_no_irtt, false)
@@ -173,9 +152,6 @@
 // at least one non app-limited sample.
 QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_bbr_slower_startup2, true)
 
-// If true, use deframer from third_party/http2 instead of third_party/quic/http
-QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_enable_h2_deframer, true)
-
 // If true, put ScopedRetransmissionScheduler's functionality to
 // ScopedPacketFlusher.
 QUIC_FLAG(bool,
@@ -202,3 +178,21 @@
     bool,
     FLAGS_quic_reloadable_flag_quic_export_connection_write_packet_results,
     true)
+
+// If true, enable extra CHECKs in ack processing to debug b/110029150.
+QUIC_FLAG(bool,
+          FLAGS_quic_reloadable_flag_quic_extra_checks_in_ack_processing,
+          false)
+
+// If true, close connection if largest observed in ack frame is greater than
+// largest sent packet.
+QUIC_FLAG(bool,
+          FLAGS_quic_reloadable_flag_quic_validate_ack_largest_observed,
+          false)
+
+// If true, QuicConnection::ProcessPacket will not set send alarm if it is write
+// blocked.
+QUIC_FLAG(
+    bool,
+    FLAGS_quic_reloadable_flag_quic_no_send_alarm_in_process_packet_if_write_blocked,
+    false)
diff --git a/net/third_party/quic/core/quic_framer.cc b/net/third_party/quic/core/quic_framer.cc
index 3e48a6d..a67e500 100644
--- a/net/third_party/quic/core/quic_framer.cc
+++ b/net/third_party/quic/core/quic_framer.cc
@@ -31,6 +31,7 @@
 #include "net/third_party/quic/platform/api/quic_ptr_util.h"
 #include "net/third_party/quic/platform/api/quic_str_cat.h"
 #include "net/third_party/quic/platform/api/quic_string.h"
+#include "net/third_party/quic/platform/api/quic_string_utils.h"
 #include "net/third_party/quic/platform/api/quic_text_utils.h"
 
 using std::string;
@@ -239,6 +240,21 @@
   return static_cast<uint8_t>(length - kConnectionIdLengthAdjustment);
 }
 
+class TrackedDataReader : public QuicDataReader {
+ public:
+  TrackedDataReader(const char* data,
+                    const size_t len,
+                    Endianness endianness,
+                    QuicDataReader** preader)
+      : QuicDataReader(data, len, endianness), preader_(preader) {
+    *preader_ = this;
+  }
+  ~TrackedDataReader() { *preader_ = nullptr; }
+
+ private:
+  QuicDataReader** preader_;
+};
+
 }  // namespace
 
 QuicFramer::QuicFramer(const ParsedQuicVersionVector& supported_versions,
@@ -262,7 +278,8 @@
       last_timestamp_(QuicTime::Delta::Zero()),
       data_producer_(nullptr),
       use_incremental_ack_processing_(
-          GetQuicReloadableFlag(quic_use_incremental_ack_processing4)) {
+          GetQuicReloadableFlag(quic_use_incremental_ack_processing4)),
+      decrypted_payload_reader_(nullptr) {
   if (use_incremental_ack_processing_) {
     QUIC_FLAG_COUNT(quic_reloadable_flag_quic_use_incremental_ack_processing4);
   }
@@ -658,6 +675,35 @@
           return 0;
         }
         break;
+      case APPLICATION_CLOSE_FRAME:
+        set_detailed_error(
+            "Attempt to append APPLICATION_CLOSE frame and not in version 99.");
+        return RaiseError(QUIC_INTERNAL_ERROR);
+      case NEW_CONNECTION_ID_FRAME:
+        set_detailed_error(
+            "Attempt to append NEW_CONNECTION_ID frame and not in version 99.");
+        return RaiseError(QUIC_INTERNAL_ERROR);
+      case MAX_STREAM_ID_FRAME:
+        set_detailed_error(
+            "Attempt to append MAX_STREAM_ID frame and not in version 99.");
+        return RaiseError(QUIC_INTERNAL_ERROR);
+      case STREAM_ID_BLOCKED_FRAME:
+        set_detailed_error(
+            "Attempt to append STREAM_ID_BLOCKED frame and not in version 99.");
+        return RaiseError(QUIC_INTERNAL_ERROR);
+      case PATH_RESPONSE_FRAME:
+        set_detailed_error(
+            "Attempt to append PATH_RESPONSE frame and not in version 99.");
+        return RaiseError(QUIC_INTERNAL_ERROR);
+      case PATH_CHALLENGE_FRAME:
+        set_detailed_error(
+            "Attempt to append PATH_CHALLENGE frame and not in version 99.");
+        return RaiseError(QUIC_INTERNAL_ERROR);
+      case STOP_SENDING_FRAME:
+        set_detailed_error(
+            "Attempt to append STOP_SENDING frame and not in version 99.");
+        return RaiseError(QUIC_INTERNAL_ERROR);
+
       default:
         RaiseError(QUIC_INVALID_FRAME_DATA);
         QUIC_BUG << "QUIC_INVALID_FRAME_DATA";
@@ -710,12 +756,9 @@
         }
         break;
       case STOP_WAITING_FRAME:
-        if (!AppendStopWaitingFrame(header, *frame.stop_waiting_frame,
-                                    &writer)) {
-          QUIC_BUG << "AppendStopWaitingFrame failed";
-          return 0;
-        }
-        break;
+        set_detailed_error(
+            "Attempt to append STOP WAITING frame in version 99.");
+        return RaiseError(QUIC_INTERNAL_ERROR);
       case MTU_DISCOVERY_FRAME:
         // MTU discovery frames are serialized as ping frames.
         QUIC_FALLTHROUGH_INTENDED;
@@ -736,11 +779,8 @@
         }
         break;
       case GOAWAY_FRAME:
-        if (!AppendGoAwayFrame(*frame.goaway_frame, &writer)) {
-          QUIC_BUG << "AppendGoAwayFrame failed";
-          return 0;
-        }
-        break;
+        set_detailed_error("Attempt to append GOAWAY frame in version 99.");
+        return RaiseError(QUIC_INTERNAL_ERROR);
       case WINDOW_UPDATE_FRAME:
         // Depending on whether there is a stream ID or not, will be either a
         // MAX STREAM DATA frame or a MAX DATA frame.
@@ -1018,13 +1058,11 @@
   last_packet_is_ietf_quic_ = false;
   if (perspective_ == Perspective::IS_CLIENT) {
     last_packet_is_ietf_quic_ = version_.transport_version > QUIC_VERSION_43;
-  } else if (GetQuicReloadableFlag(quic_respect_ietf_header) &&
-             !reader.IsDoneReading()) {
+  } else if (!reader.IsDoneReading()) {
     uint8_t type = reader.PeekByte();
     last_packet_is_ietf_quic_ = QuicUtils::IsIetfPacketHeader(type);
   }
   if (last_packet_is_ietf_quic_) {
-    QUIC_FLAG_COUNT(quic_reloadable_flag_quic_respect_ietf_header);
     QUIC_DVLOG(1) << ENDPOINT << "Processing IETF QUIC packet.";
     reader.set_endianness(NETWORK_BYTE_ORDER);
   }
@@ -1187,7 +1225,8 @@
     set_detailed_error("Unable to decrypt payload.");
     return RaiseError(QUIC_DECRYPTION_FAILURE);
   }
-  QuicDataReader reader(decrypted_buffer, decrypted_length, endianness());
+  TrackedDataReader reader(decrypted_buffer, decrypted_length, endianness(),
+                           &decrypted_payload_reader_);
 
   // Update the largest packet number after we have decrypted the packet
   // so we are confident is not attacker controlled.
@@ -1249,7 +1288,8 @@
     return RaiseError(QUIC_DECRYPTION_FAILURE);
   }
 
-  QuicDataReader reader(decrypted_buffer, decrypted_length, endianness());
+  TrackedDataReader reader(decrypted_buffer, decrypted_length, endianness(),
+                           &decrypted_payload_reader_);
 
   // Update the largest packet number after we have decrypted the packet
   // so we are confident is not attacker controlled.
@@ -2225,62 +2265,6 @@
           }
           break;
         }
-        case IETF_TEMP_GOAWAY_FRAME: {
-          // temporary, for testing
-          QuicGoAwayFrame goaway_frame;
-          if (!ProcessGoAwayFrame(reader, &goaway_frame)) {
-            return RaiseError(QUIC_INVALID_GOAWAY_DATA);
-          }
-          if (!visitor_->OnGoAwayFrame(goaway_frame)) {
-            QUIC_DVLOG(1) << ENDPOINT
-                          << "Visitor asked to stop further processing.";
-            // Returning true since there was no parsing error.
-            return true;
-          }
-          break;
-        }
-        case IETF_TEMP_WINDOW_UPDATE_FRAME: {
-          // temporary, for testing
-          QuicWindowUpdateFrame window_update_frame;
-          if (!ProcessWindowUpdateFrame(reader, &window_update_frame)) {
-            return RaiseError(QUIC_INVALID_WINDOW_UPDATE_DATA);
-          }
-          if (!visitor_->OnWindowUpdateFrame(window_update_frame)) {
-            QUIC_DVLOG(1) << ENDPOINT
-                          << "Visitor asked to stop further processing.";
-            // Returning true since there was no parsing error.
-            return true;
-          }
-          break;
-        }
-        case IETF_TEMP_STOP_WAITING_FRAME: {
-          // temporary, for testing
-          QuicStopWaitingFrame stop_waiting_frame;
-          if (!ProcessStopWaitingFrame(reader, header, &stop_waiting_frame)) {
-            return RaiseError(QUIC_INVALID_STOP_WAITING_DATA);
-          }
-          if (!visitor_->OnStopWaitingFrame(stop_waiting_frame)) {
-            QUIC_DVLOG(1) << ENDPOINT
-                          << "Visitor asked to stop further processing.";
-            // Returning true since there was no parsing error.
-            return true;
-          }
-          continue;
-        }
-        case IETF_TEMP_BLOCKED_FRAME: {
-          // temporary, for testing
-          QuicBlockedFrame blocked_frame;
-          if (!ProcessBlockedFrame(reader, &blocked_frame)) {
-            return RaiseError(QUIC_INVALID_BLOCKED_DATA);
-          }
-          if (!visitor_->OnBlockedFrame(blocked_frame)) {
-            QUIC_DVLOG(1) << ENDPOINT
-                          << "Visitor asked to stop further processing.";
-            // Returning true since there was no parsing error.
-            return true;
-          }
-          continue;
-        }
 
         default:
           set_detailed_error("Illegal frame type.");
@@ -2728,18 +2712,6 @@
   //  +1 because AddRange implementation requires [low,high)
   QuicPacketNumber block_high = largest_acked + 1;
   QuicPacketNumber block_low = largest_acked - ack_block_value;
-  if (use_incremental_ack_processing_) {
-    if (!visitor_->OnAckRange(block_low, block_high,
-                              /* last_range= */ (ack_block_count == 0))) {
-      // The visitor suppresses further processing of the packet. Although
-      // this is not a parsing error, returns false as this is in middle
-      // of processing an ACK frame.
-      set_detailed_error("Visitor suppresses further processing of ACK frame.");
-      return false;
-    }
-  } else {
-    ack_frame->packets.AddRange(block_low, block_high);
-  }
 
   // ack_block_value is the number of packets preceding the
   // largest_acked packet which are in the block being acked. Thus,
@@ -2753,28 +2725,64 @@
     return false;
   }
 
+  if (use_incremental_ack_processing_) {
+    if (!visitor_->OnAckRange(block_low, block_high,
+                              /* last_range= */ (ack_block_count == 0))) {
+      // The visitor suppresses further processing of the packet. Although
+      // this is not a parsing error, returns false as this is in middle
+      // of processing an ACK frame.
+      set_detailed_error("Visitor suppresses further processing of ACK frame.");
+      return false;
+    }
+  } else {
+    ack_frame->packets.AddRange(block_low, block_high);
+  }
+
   while (ack_block_count != 0) {
     uint64_t gap_block_value;
-
     // Get the sizes of the gap and ack blocks,
     if (!reader->ReadVarInt62(&gap_block_value)) {
       set_detailed_error("Unable to read gap block value.");
       return false;
     }
+    // It's an error if the gap is larger than the space from packet
+    // number 0 to the start of the block that's just been acked, PLUS
+    // there must be space for at least 1 packet to be acked. For
+    // example, if block_low is 10 and gap_block_value is 9, it means
+    // the gap block is 10 packets long, leaving no room for a packet
+    // to be acked. Thus, gap_block_value+2 can not be larger than
+    // block_low.
+    // The test is written this way to detect wrap-arounds.
+    if ((gap_block_value + 2) > block_low) {
+      set_detailed_error(
+          QuicStrCat("Underflow with gap block length ", gap_block_value + 1,
+                     " previous ack block start is ", block_low, ".")
+              .c_str());
+      return false;
+    }
 
-    // Slide block_high down to be the high end of the next ack
-    // block. It needs to be decremented by the length of the previous
-    // ack block and by the length of the gap (+2 since both values
-    // are the length-1).
-    block_high -= ack_block_value + gap_block_value + 2;
+    // Adjust block_high to be the top of the next ack block.
+    // There is a gap of |gap_block_value| packets between the bottom
+    // of ack block N and top of block N+1.  Note that gap_block_value
+    // is he size of the gap minus 1 (per the QUIC protocol), and
+    // block_high is the packet number of the first packet of the gap
+    // (per the implementation of OnAckRange/AddAckRange, below).
+    block_high = block_low - 1 - gap_block_value;
 
     if (!reader->ReadVarInt62(&ack_block_value)) {
       set_detailed_error("Unable to read ack block value.");
       return false;
     }
+    if (ack_block_value > (block_high - 1)) {
+      set_detailed_error(
+          QuicStrCat("Underflow with ack block length ", ack_block_value + 1,
+                     " latest ack block end is ", block_high - 1, ".")
+              .c_str());
+      return false;
+    }
     // Calculate the low end of the new nth ack block. The +1 is
     // because the encoded value is the blocksize-1.
-    block_low = block_high - ack_block_value - 1;
+    block_low = block_high - 1 - ack_block_value;
     if (use_incremental_ack_processing_) {
       if (!visitor_->OnAckRange(block_low, block_high,
                                 /*last_range=*/(ack_block_count == 1))) {
@@ -2923,14 +2931,8 @@
 
 bool QuicFramer::ProcessBlockedFrame(QuicDataReader* reader,
                                      QuicBlockedFrame* frame) {
-  // TODO(fkastenholz): replace with DCHECK_NE(QUIC_VERSION_99,
-  // version_.transport_version) << ...
-  // when support for IETF blocked/stream-blocked frame is
-  // complete and we remove IETF_TEMP_BLOCKED_FRAME
-  if (version_.transport_version == QUIC_VERSION_99) {
-    // IETF STREAM BLOCKED is closest analog
-    return ProcessStreamBlockedFrame(reader, frame);
-  }
+  DCHECK_NE(QUIC_VERSION_99, version_.transport_version)
+      << "Attempt to process non-IETF frames but version is 99";
 
   if (!reader->ReadUInt32(&frame->stream_id)) {
     set_detailed_error("Unable to read stream_id.");
@@ -3406,6 +3408,36 @@
     case MTU_DISCOVERY_FRAME:
       type_byte = static_cast<uint8_t>(PING_FRAME);
       break;
+
+    case APPLICATION_CLOSE_FRAME:
+      set_detailed_error(
+          "Attempt to append APPLICATION_CLOSE frame and not in version 99.");
+      return RaiseError(QUIC_INTERNAL_ERROR);
+    case NEW_CONNECTION_ID_FRAME:
+      set_detailed_error(
+          "Attempt to append NEW_CONNECTION_ID frame and not in version 99.");
+      return RaiseError(QUIC_INTERNAL_ERROR);
+    case MAX_STREAM_ID_FRAME:
+      set_detailed_error(
+          "Attempt to append MAX_STREAM_ID frame and not in version 99.");
+      return RaiseError(QUIC_INTERNAL_ERROR);
+    case STREAM_ID_BLOCKED_FRAME:
+      set_detailed_error(
+          "Attempt to append STREAM_ID_BLOCKED frame and not in version 99.");
+      return RaiseError(QUIC_INTERNAL_ERROR);
+    case PATH_RESPONSE_FRAME:
+      set_detailed_error(
+          "Attempt to append PATH_RESPONSE frame and not in version 99.");
+      return RaiseError(QUIC_INTERNAL_ERROR);
+    case PATH_CHALLENGE_FRAME:
+      set_detailed_error(
+          "Attempt to append PATH_CHALLENGE frame and not in version 99.");
+      return RaiseError(QUIC_INTERNAL_ERROR);
+    case STOP_SENDING_FRAME:
+      set_detailed_error(
+          "Attempt to append STOP_SENDING frame and not in version 99.");
+      return RaiseError(QUIC_INTERNAL_ERROR);
+
     default:
       type_byte = static_cast<uint8_t>(frame.type);
       break;
@@ -3429,11 +3461,12 @@
       type_byte = IETF_CONNECTION_CLOSE;
       break;
     case GOAWAY_FRAME:
-      type_byte = IETF_TEMP_GOAWAY_FRAME;
-      break;
+      set_detailed_error(
+          "Attempt to create non-version-99 GOAWAY frame in version 99.");
+      return RaiseError(QUIC_INTERNAL_ERROR);
     case WINDOW_UPDATE_FRAME:
-      // Depending on whether there is a stream ID or not, will be either a MAX
-      // STREAM DATA frame or a MAX DATA frame.
+      // Depending on whether there is a stream ID or not, will be either a
+      // MAX_STREAM_DATA frame or a MAX_DATA frame.
       if (frame.window_update_frame->stream_id == 0) {
         type_byte = IETF_MAX_DATA;
       } else {
@@ -3448,8 +3481,9 @@
       }
       break;
     case STOP_WAITING_FRAME:
-      type_byte = IETF_TEMP_STOP_WAITING_FRAME;
-      break;
+      set_detailed_error(
+          "Attempt to append type byte of STOP WAITING frame in version 99.");
+      return RaiseError(QUIC_INTERNAL_ERROR);
     case PING_FRAME:
       type_byte = IETF_PING;
       break;
@@ -4620,4 +4654,17 @@
   return true;
 }
 
+QuicString QuicFramer::VerboseDebugString() const {
+  QuicString str =
+      QuicStrCat("{ version:", ParsedQuicVersionToString(version_));
+
+  if (decrypted_payload_reader_ != nullptr) {
+    QuicStrAppend(&str, " decrypted_payload_reader:",
+                  decrypted_payload_reader_->VerboseDebugString());
+  }
+
+  QuicStrAppend(&str, "\n}");
+  return str;
+}
+
 }  // namespace quic
diff --git a/net/third_party/quic/core/quic_framer.h b/net/third_party/quic/core/quic_framer.h
index 750ac8a..ebe80535 100644
--- a/net/third_party/quic/core/quic_framer.h
+++ b/net/third_party/quic/core/quic_framer.h
@@ -470,6 +470,8 @@
     return version_.transport_version == QUIC_VERSION_99;
   }
 
+  QuicString VerboseDebugString() const;
+
  private:
   friend class test::QuicFramerPeer;
 
@@ -794,6 +796,11 @@
   // Latched value of quic_reloadable_flag_quic_use_incremental_ack_processing4.
   const bool use_incremental_ack_processing_;
 
+  // If the framer is processing a decrypted payload of a data packet,
+  // |decrypted_payload_reader_| will be set to the reader of that payload,
+  // otherwise nullptr.
+  QuicDataReader* decrypted_payload_reader_;
+
   DISALLOW_COPY_AND_ASSIGN(QuicFramer);
 };
 
diff --git a/net/third_party/quic/core/quic_framer_test.cc b/net/third_party/quic/core/quic_framer_test.cc
index ce9b712..40b840f 100644
--- a/net/third_party/quic/core/quic_framer_test.cc
+++ b/net/third_party/quic/core/quic_framer_test.cc
@@ -53,6 +53,11 @@
 const QuicStreamOffset kStreamOffset = UINT64_C(0x3A98FEDC32107654);
 const QuicPublicResetNonceProof kNonceProof = UINT64_C(0xABCDEF0123456789);
 
+// In testing that we can ack the full range of packets...
+// This is the largest packet number that can be represented in IETF QUIC
+// varint62 format.
+const QuicPacketNumber kLargestIetfLargestObserved =
+    UINT64_C(0x3fffffffffffffff);
 // Encodings for the two bits in a VarInt62 that
 // describe the length of the VarInt61. For binary packet
 // formats in this file, the convention is to code the
@@ -381,7 +386,6 @@
                 start_,
                 Perspective::IS_SERVER) {
     SetQuicFlag(&FLAGS_quic_supports_tls_handshake, true);
-    SetQuicReloadableFlag(quic_respect_ietf_header, true);
     framer_.set_version(version_);
     framer_.SetDecrypter(ENCRYPTION_NONE,
                          std::unique_ptr<QuicDecrypter>(decrypter_));
@@ -3054,6 +3058,265 @@
   CheckFramingBoundaries(fragments, QUIC_INVALID_ACK_DATA);
 }
 
+// This test checks that the ack frame processor correctly identifies
+// and handles the case where the third ack block's gap is larger than the
+// available space in the ack range.
+TEST_P(QuicFramerTest, ThirdAckBlockUnderflowGap) {
+  if (framer_.transport_version() != QUIC_VERSION_99) {
+    // for now, only v99
+    return;
+  }
+  // clang-format off
+  PacketFragments packet99 = {
+      // type (short header, 4 byte packet number)
+      {"",
+       {0x32}},
+      // connection_id
+      {"",
+       {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
+      // packet number
+      {"",
+       {0x12, 0x34, 0x56, 0x78}},
+       // frame type (ack frame)
+       {"",
+        {0x0d}},
+       // largest acked
+       {"Unable to read largest acked.",
+        {kVarInt62OneByte  + 63}},
+       // Zero delta time.
+       {"Unable to read ack delay time.",
+        {kVarInt62OneByte + 0x00}},
+       // Ack block count (2 -- 2 blocks after the first)
+       {"Unable to read ack block count.",
+        {kVarInt62OneByte + 0x02}},
+       // first ack block length.
+       {"Unable to read first ack block length.",
+        {kVarInt62OneByte + 13}},  // Ack 14 packets, range 50..63 (inclusive)
+
+       {"Unable to read gap block value.",
+        {kVarInt62OneByte + 9}},  // Gap 10 packets, 40..49 (inclusive)
+       {"Unable to read ack block value.",
+        {kVarInt62OneByte + 9}},  // Ack 10 packets, 30..39 (inclusive)
+       {"Unable to read gap block value.",
+        {kVarInt62OneByte + 29}},  // A gap of 30 packets (0..29 inclusive)
+                                   // should be too big, leaving no room
+                                   // for the ack.
+       {"Underflow with gap block length 30 previous ack block start is 30.",
+        {kVarInt62OneByte + 10}},  // Don't care
+  };
+  // clang-format on
+
+  std::unique_ptr<QuicEncryptedPacket> encrypted(
+      AssemblePacketFromFragments(packet99));
+  EXPECT_FALSE(framer_.ProcessPacket(*encrypted));
+  EXPECT_EQ(
+      framer_.detailed_error(),
+      "Underflow with gap block length 30 previous ack block start is 30.");
+  CheckFramingBoundaries(packet99, QUIC_INVALID_ACK_DATA);
+}
+
+// This test checks that the ack frame processor correctly identifies
+// and handles the case where the third ack block's length is larger than the
+// available space in the ack range.
+TEST_P(QuicFramerTest, ThirdAckBlockUnderflowAck) {
+  if (framer_.transport_version() != QUIC_VERSION_99) {
+    // for now, only v99
+    return;
+  }
+  // clang-format off
+  PacketFragments packet99 = {
+      // type (short header, 4 byte packet number)
+      {"",
+       {0x32}},
+      // connection_id
+      {"",
+       {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
+      // packet number
+      {"",
+       {0x12, 0x34, 0x56, 0x78}},
+       // frame type (ack frame)
+       {"",
+        {0x0d}},
+       // largest acked
+       {"Unable to read largest acked.",
+        {kVarInt62OneByte  + 63}},
+       // Zero delta time.
+       {"Unable to read ack delay time.",
+        {kVarInt62OneByte + 0x00}},
+       // Ack block count (2 -- 2 blocks after the first)
+       {"Unable to read ack block count.",
+        {kVarInt62OneByte + 0x02}},
+       // first ack block length.
+       {"Unable to read first ack block length.",
+        {kVarInt62OneByte + 13}},  // only 50 packet numbers "left"
+
+       {"Unable to read gap block value.",
+        {kVarInt62OneByte + 10}},  // Only 40 packet numbers left
+       {"Unable to read ack block value.",
+        {kVarInt62OneByte + 10}},  // only 30 packet numbers left.
+       {"Unable to read gap block value.",
+        {kVarInt62OneByte + 1}},  // Gap is OK, 29 packet numbers left
+      {"Unable to read ack block value.",
+        {kVarInt62OneByte + 30}},  // Use up all 30, should be an error
+  };
+  // clang-format on
+
+  std::unique_ptr<QuicEncryptedPacket> encrypted(
+      AssemblePacketFromFragments(packet99));
+  EXPECT_FALSE(framer_.ProcessPacket(*encrypted));
+  EXPECT_EQ(framer_.detailed_error(),
+            "Underflow with ack block length 31 latest ack block end is 25.");
+  CheckFramingBoundaries(packet99, QUIC_INVALID_ACK_DATA);
+}
+
+// Tests a variety of ack block wrap scenarios. For example, if the
+// N-1th block causes packet 0 to be acked, then a gap would wrap
+// around to 0x3fffffff ffffffff... Make sure we detect this
+// condition.
+TEST_P(QuicFramerTest, AckBlockUnderflowGapWrap) {
+  if (framer_.transport_version() != QUIC_VERSION_99) {
+    // for now, only v99
+    return;
+  }
+  // clang-format off
+  PacketFragments packet99 = {
+      // type (short header, 4 byte packet number)
+      {"",
+       {0x32}},
+      // connection_id
+      {"",
+       {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
+      // packet number
+      {"",
+       {0x12, 0x34, 0x56, 0x78}},
+       // frame type (ack frame)
+       {"",
+        {0x0d}},
+       // largest acked
+       {"Unable to read largest acked.",
+        {kVarInt62OneByte  + 10}},
+       // Zero delta time.
+       {"Unable to read ack delay time.",
+        {kVarInt62OneByte + 0x00}},
+       // Ack block count (1 -- 1 blocks after the first)
+       {"Unable to read ack block count.",
+        {kVarInt62OneByte + 1}},
+       // first ack block length.
+       {"Unable to read first ack block length.",
+        {kVarInt62OneByte + 9}},  // Ack packets 1..10 (inclusive)
+
+       {"Unable to read gap block value.",
+        {kVarInt62OneByte + 1}},  // Gap of 2 packets (-1...0), should wrap
+       {"Underflow with gap block length 2 previous ack block start is 1.",
+        {kVarInt62OneByte + 9}},  // irrelevant
+  };
+  // clang-format on
+
+  std::unique_ptr<QuicEncryptedPacket> encrypted(
+      AssemblePacketFromFragments(packet99));
+  EXPECT_FALSE(framer_.ProcessPacket(*encrypted));
+  EXPECT_EQ(framer_.detailed_error(),
+            "Underflow with gap block length 2 previous ack block start is 1.");
+  CheckFramingBoundaries(packet99, QUIC_INVALID_ACK_DATA);
+}
+
+// As AckBlockUnderflowGapWrap, but in this test, it's the ack
+// component of the ack-block that causes the wrap, not the gap.
+TEST_P(QuicFramerTest, AckBlockUnderflowAckWrap) {
+  if (framer_.transport_version() != QUIC_VERSION_99) {
+    // for now, only v99
+    return;
+  }
+  // clang-format off
+  PacketFragments packet99 = {
+      // type (short header, 4 byte packet number)
+      {"",
+       {0x32}},
+      // connection_id
+      {"",
+       {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
+      // packet number
+      {"",
+       {0x12, 0x34, 0x56, 0x78}},
+       // frame type (ack frame)
+       {"",
+        {0x0d}},
+       // largest acked
+       {"Unable to read largest acked.",
+        {kVarInt62OneByte  + 10}},
+       // Zero delta time.
+       {"Unable to read ack delay time.",
+        {kVarInt62OneByte + 0x00}},
+       // Ack block count (1 -- 1 blocks after the first)
+       {"Unable to read ack block count.",
+        {kVarInt62OneByte + 1}},
+       // first ack block length.
+       {"Unable to read first ack block length.",
+        {kVarInt62OneByte + 6}},  // Ack packets 4..10 (inclusive)
+
+       {"Unable to read gap block value.",
+        {kVarInt62OneByte + 1}},  // Gap of 2 packets (2..3)
+       {"Unable to read ack block value.",
+        {kVarInt62OneByte + 9}},  // Should wrap.
+  };
+  // clang-format on
+
+  std::unique_ptr<QuicEncryptedPacket> encrypted(
+      AssemblePacketFromFragments(packet99));
+  EXPECT_FALSE(framer_.ProcessPacket(*encrypted));
+  EXPECT_EQ(framer_.detailed_error(),
+            "Underflow with ack block length 10 latest ack block end is 1.");
+  CheckFramingBoundaries(packet99, QUIC_INVALID_ACK_DATA);
+}
+
+// An ack block that acks the entire range, 0...0x3fffffffffffffff
+TEST_P(QuicFramerTest, AckBlockAcksEverything) {
+  if (framer_.transport_version() != QUIC_VERSION_99) {
+    // for now, only v99
+    return;
+  }
+  // clang-format off
+  PacketFragments packet99 = {
+      // type (short header, 4 byte packet number)
+      {"",
+       {0x32}},
+      // connection_id
+      {"",
+       {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
+      // packet number
+      {"",
+       {0x12, 0x34, 0x56, 0x78}},
+       // frame type (ack frame)
+       {"",
+        {0x0d}},
+       // largest acked
+       {"Unable to read largest acked.",
+        {kVarInt62EightBytes  + 0x3f, 0xff, 0xff, 0xff,
+         0xff, 0xff, 0xff, 0xff}},
+       // Zero delta time.
+       {"Unable to read ack delay time.",
+        {kVarInt62OneByte + 0x00}},
+       // Ack block count No additional blocks
+       {"Unable to read ack block count.",
+        {kVarInt62OneByte + 0}},
+       // first ack block length.
+       {"Unable to read first ack block length.",
+        {kVarInt62EightBytes  + 0x3f, 0xff, 0xff, 0xff,
+         0xff, 0xff, 0xff, 0xff}},
+  };
+  // clang-format on
+
+  std::unique_ptr<QuicEncryptedPacket> encrypted(
+      AssemblePacketFromFragments(packet99));
+  EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
+  EXPECT_EQ(1u, visitor_.ack_frames_.size());
+  const QuicAckFrame& frame = *visitor_.ack_frames_[0];
+  EXPECT_EQ(1u, frame.packets.NumIntervals());
+  EXPECT_EQ(kLargestIetfLargestObserved, LargestAcked(frame));
+  // +1 because it's 0..Largest, inclusive.
+  EXPECT_EQ(kLargestIetfLargestObserved + 1, frame.packets.NumPacketsSlow());
+}
+
 // This test looks for a malformed ack where
 //  - There is a largest-acked value (that is, the frame is acking
 //    something,
@@ -3801,7 +4064,7 @@
 }
 
 TEST_P(QuicFramerTest, NewStopWaitingFrame) {
-  if (version_.transport_version > QUIC_VERSION_43) {
+  if (version_.transport_version == QUIC_VERSION_99) {
     return;
   }
   // clang-format off
@@ -3853,7 +4116,7 @@
        {0x12, 0x34, 0x56, 0x78}},
       // frame type (stop waiting frame)
       {"",
-       {0xf2}},
+       {0x06}},
       // least packet number awaiting an ack, delta from packet number.
       {"Unable to read least unacked delta.",
         {0x00, 0x00, 0x00, 0x08}}
@@ -3883,7 +4146,7 @@
 }
 
 TEST_P(QuicFramerTest, InvalidNewStopWaitingFrame) {
-  if (version_.transport_version > QUIC_VERSION_43) {
+  if (version_.transport_version == QUIC_VERSION_99) {
     return;
   }
   // clang-format off
@@ -3923,7 +4186,7 @@
     // packet number
     0x12, 0x34, 0x56, 0x78,
     // frame type (stop waiting frame)
-    0xf2,
+    0x06,
     // least packet number awaiting an ack, delta from packet number.
     0x57, 0x78, 0x9A, 0xA8,
   };
@@ -4295,6 +4558,10 @@
 }
 
 TEST_P(QuicFramerTest, GoAwayFrame) {
+  if (framer_.transport_version() == QUIC_VERSION_99) {
+    // This frame is not supported in version 99.
+    return;
+  }
   // clang-format off
   PacketFragments packet = {
       // public flags (8 byte connection_id)
@@ -4390,47 +4657,12 @@
          'n'}
       }
   };
-
-  PacketFragments packet99 = {
-      // type (short header, 4 byte packet number)
-      {"",
-       {0x32}},
-      // connection_id
-      {"",
-       {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
-      // packet number
-      {"",
-       {0x12, 0x34, 0x9A, 0xBC}},
-      // frame type (go away frame)
-      {"",
-       {0xf0}},
-      // error code
-      {"Unable to read go away error code.",
-       {0x00, 0x00, 0x00, 0x09}},
-      // stream id
-      {"Unable to read last good stream id.",
-       {0x01, 0x02, 0x03, 0x04}},
-      // stream id
-      {"Unable to read goaway reason.",
-       {
-         // error details length
-         0x0, 0x0d,
-         // error details
-         'b',  'e',  'c',  'a',
-         'u',  's',  'e',  ' ',
-         'I',  ' ',  'c',  'a',
-         'n'}
-      }
-  };
   // clang-format on
 
   PacketFragments& fragments =
-      framer_.transport_version() == QUIC_VERSION_99
-          ? packet99
-          : (framer_.transport_version() > QUIC_VERSION_43
-                 ? packet44
-                 : (framer_.transport_version() > QUIC_VERSION_38 ? packet39
-                                                                  : packet));
+      framer_.transport_version() > QUIC_VERSION_43
+          ? packet44
+          : (framer_.transport_version() > QUIC_VERSION_38 ? packet39 : packet);
   std::unique_ptr<QuicEncryptedPacket> encrypted(
       AssemblePacketFromFragments(fragments));
   EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
@@ -4449,6 +4681,11 @@
 }
 
 TEST_P(QuicFramerTest, WindowUpdateFrame) {
+  if (framer_.transport_version() == QUIC_VERSION_99) {
+    // This frame is not in version 99, see MaxDataFrame and MaxStreamDataFrame
+    // for Version 99 equivalents.
+    return;
+  }
   // clang-format off
   PacketFragments packet = {
       // public flags (8 byte connection_id)
@@ -4516,36 +4753,12 @@
         0x32, 0x10, 0x76, 0x54}},
   };
 
-  PacketFragments packet99 = {
-      // type (short header, 4 byte packet number)
-      {"",
-       {0x32}},
-      // connection_id
-      {"",
-       {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
-      // packet number
-      {"",
-       {0x12, 0x34, 0x56, 0x78}},
-      // frame type (window update frame)
-      {"",
-       {0xf1}},
-      // stream id
-      {"Unable to read stream_id.",
-       {0x01, 0x02, 0x03, 0x04}},
-      // byte offset
-      {"Unable to read window byte_offset.",
-       {0x3A, 0x98, 0xFE, 0xDC,
-        0x32, 0x10, 0x76, 0x54}},
-  };
   // clang-format on
 
   PacketFragments& fragments =
-      framer_.transport_version() == QUIC_VERSION_99
-          ? packet99
-          : (framer_.transport_version() > QUIC_VERSION_43
-                 ? packet44
-                 : (framer_.transport_version() > QUIC_VERSION_38 ? packet39
-                                                                  : packet));
+      framer_.transport_version() > QUIC_VERSION_43
+          ? packet44
+          : (framer_.transport_version() > QUIC_VERSION_38 ? packet39 : packet);
   std::unique_ptr<QuicEncryptedPacket> encrypted(
       AssemblePacketFromFragments(fragments));
   EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
@@ -6997,25 +7210,10 @@
     0x00, 0x00, 0x00, 0x08,
   };
 
-  unsigned char packet44[] = {
-    // type (short header, 4 byte packet number)
-    0x32,
-    // connection_id
-    0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
-    // packet number
-    0x12, 0x34, 0x56, 0x78,
-
-    // frame type (stop waiting frame)
-    0xf2,
-    // least packet number awaiting an ack, delta from packet number.
-    0x00, 0x00, 0x00, 0x08,
-  };
   // clang-format on
 
   unsigned char* p = packet;
-  if (framer_.transport_version() > QUIC_VERSION_43) {
-    p = packet44;
-  } else if (framer_.transport_version() > QUIC_VERSION_38) {
+  if (framer_.transport_version() > QUIC_VERSION_38) {
     p = packet39;
   }
 
@@ -7024,7 +7222,7 @@
 
   test::CompareCharArraysWithHexError(
       "constructed packet", data->data(), data->length(), AsChars(p),
-      framer_.transport_version() > QUIC_VERSION_43 ? QUIC_ARRAYSIZE(packet44)
+      framer_.transport_version() > QUIC_VERSION_38 ? QUIC_ARRAYSIZE(packet39)
                                                     : QUIC_ARRAYSIZE(packet));
 }
 
@@ -7647,6 +7845,10 @@
 }
 
 TEST_P(QuicFramerTest, BuildGoAwayPacket) {
+  if (framer_.transport_version() == QUIC_VERSION_99) {
+    // This frame type is not supported in version 99.
+    return;
+  }
   QuicPacketHeader header;
   header.destination_connection_id = kConnectionId;
   header.reset_flag = false;
@@ -7730,36 +7932,11 @@
     'n',
   };
 
-  unsigned char packet99[] = {
-    // type (short header, 4 byte packet number)
-    0x32,
-    // connection_id
-    0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
-    // packet number
-    0x12, 0x34, 0x56, 0x78,
-
-    // frame type (go away frame)
-    0xf0,
-    // error code
-    0x05, 0x06, 0x07, 0x08,
-    // stream id
-    0x01, 0x02, 0x03, 0x04,
-    // error details length
-    0x00, 0x0d,
-    // error details
-    'b',  'e',  'c',  'a',
-    'u',  's',  'e',  ' ',
-    'I',  ' ',  'c',  'a',
-    'n',
-  };
   // clang-format on
 
   unsigned char* p = packet;
   size_t p_size = QUIC_ARRAYSIZE(packet);
-  if (framer_.transport_version() == QUIC_VERSION_99) {
-    p = packet99;
-    p_size = QUIC_ARRAYSIZE(packet99);
-  } else if (framer_.transport_version() > QUIC_VERSION_43) {
+  if (framer_.transport_version() > QUIC_VERSION_43) {
     p = packet44;
     p_size = QUIC_ARRAYSIZE(packet44);
   } else if (framer_.transport_version() > QUIC_VERSION_38) {
@@ -7774,6 +7951,10 @@
 }
 
 TEST_P(QuicFramerTest, BuildTruncatedGoAwayPacket) {
+  if (framer_.transport_version() == QUIC_VERSION_99) {
+    // This frame type is not supported in version 99.
+    return;
+  }
   QuicPacketHeader header;
   header.destination_connection_id = kConnectionId;
   header.reset_flag = false;
@@ -7940,65 +8121,11 @@
     'A',  'A',  'A',  'A',  'A',  'A',  'A',  'A',
     'A',  'A',  'A',  'A',  'A',  'A',  'A',  'A',
   };
-
-  unsigned char packet99[] = {
-    // type (short header, 4 byte packet number)
-    0x32,
-    // connection_id
-    0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
-    // packet number
-    0x12, 0x34, 0x56, 0x78,
-
-    // frame type (go away frame)
-    0xf0,
-    // error code
-    0x05, 0x06, 0x07, 0x08,
-    // stream id
-    0x01, 0x02, 0x03, 0x04,
-    // error details length
-    0x01, 0x00,
-    // error details (truncated to 256 bytes)
-    'A',  'A',  'A',  'A',  'A',  'A',  'A',  'A',
-    'A',  'A',  'A',  'A',  'A',  'A',  'A',  'A',
-    'A',  'A',  'A',  'A',  'A',  'A',  'A',  'A',
-    'A',  'A',  'A',  'A',  'A',  'A',  'A',  'A',
-    'A',  'A',  'A',  'A',  'A',  'A',  'A',  'A',
-    'A',  'A',  'A',  'A',  'A',  'A',  'A',  'A',
-    'A',  'A',  'A',  'A',  'A',  'A',  'A',  'A',
-    'A',  'A',  'A',  'A',  'A',  'A',  'A',  'A',
-    'A',  'A',  'A',  'A',  'A',  'A',  'A',  'A',
-    'A',  'A',  'A',  'A',  'A',  'A',  'A',  'A',
-    'A',  'A',  'A',  'A',  'A',  'A',  'A',  'A',
-    'A',  'A',  'A',  'A',  'A',  'A',  'A',  'A',
-    'A',  'A',  'A',  'A',  'A',  'A',  'A',  'A',
-    'A',  'A',  'A',  'A',  'A',  'A',  'A',  'A',
-    'A',  'A',  'A',  'A',  'A',  'A',  'A',  'A',
-    'A',  'A',  'A',  'A',  'A',  'A',  'A',  'A',
-    'A',  'A',  'A',  'A',  'A',  'A',  'A',  'A',
-    'A',  'A',  'A',  'A',  'A',  'A',  'A',  'A',
-    'A',  'A',  'A',  'A',  'A',  'A',  'A',  'A',
-    'A',  'A',  'A',  'A',  'A',  'A',  'A',  'A',
-    'A',  'A',  'A',  'A',  'A',  'A',  'A',  'A',
-    'A',  'A',  'A',  'A',  'A',  'A',  'A',  'A',
-    'A',  'A',  'A',  'A',  'A',  'A',  'A',  'A',
-    'A',  'A',  'A',  'A',  'A',  'A',  'A',  'A',
-    'A',  'A',  'A',  'A',  'A',  'A',  'A',  'A',
-    'A',  'A',  'A',  'A',  'A',  'A',  'A',  'A',
-    'A',  'A',  'A',  'A',  'A',  'A',  'A',  'A',
-    'A',  'A',  'A',  'A',  'A',  'A',  'A',  'A',
-    'A',  'A',  'A',  'A',  'A',  'A',  'A',  'A',
-    'A',  'A',  'A',  'A',  'A',  'A',  'A',  'A',
-    'A',  'A',  'A',  'A',  'A',  'A',  'A',  'A',
-    'A',  'A',  'A',  'A',  'A',  'A',  'A',  'A',
-  };
   // clang-format on
 
   unsigned char* p = packet;
   size_t p_size = QUIC_ARRAYSIZE(packet);
-  if (framer_.transport_version() == QUIC_VERSION_99) {
-    p = packet99;
-    p_size = QUIC_ARRAYSIZE(packet99);
-  } else if (framer_.transport_version() > QUIC_VERSION_43) {
+  if (framer_.transport_version() > QUIC_VERSION_43) {
     p = packet44;
     p_size = QUIC_ARRAYSIZE(packet44);
   } else if (framer_.transport_version() > QUIC_VERSION_38) {
diff --git a/net/third_party/quic/core/quic_iovector.h b/net/third_party/quic/core/quic_iovector.h
deleted file mode 100644
index bc9cccc..0000000
--- a/net/third_party/quic/core/quic_iovector.h
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_THIRD_PARTY_QUIC_CORE_QUIC_IOVECTOR_H_
-#define NET_THIRD_PARTY_QUIC_CORE_QUIC_IOVECTOR_H_
-
-#include <cstddef>
-
-#include "net/base/iovec.h"
-#include "net/third_party/quic/platform/api/quic_export.h"
-
-namespace quic {
-
-// Convenience wrapper to wrap an iovec array and the total length, which must
-// be less than or equal to the actual total length of the iovecs.
-struct QUIC_EXPORT_PRIVATE QuicIOVector {
-  QuicIOVector(const struct iovec* iov, int iov_count, size_t total_length)
-      : iov(iov), iov_count(iov_count), total_length(total_length) {}
-
-  const struct iovec* iov;
-  const int iov_count;
-  const size_t total_length;
-};
-
-}  // namespace quic
-
-#endif  // NET_THIRD_PARTY_QUIC_CORE_QUIC_IOVECTOR_H_
diff --git a/net/third_party/quic/core/quic_packet_creator_test.cc b/net/third_party/quic/core/quic_packet_creator_test.cc
index 7ecd3027..9f0b91e 100644
--- a/net/third_party/quic/core/quic_packet_creator_test.cc
+++ b/net/third_party/quic/core/quic_packet_creator_test.cc
@@ -145,7 +145,6 @@
         data_("foo"),
         creator_(connection_id_, &client_framer_, &delegate_, &producer_),
         serialized_packet_(creator_.NoPacket()) {
-    SetQuicReloadableFlag(quic_respect_ietf_header, true);
     creator_.SetEncrypter(ENCRYPTION_INITIAL, QuicMakeUnique<NullEncrypter>(
                                                   Perspective::IS_CLIENT));
     creator_.SetEncrypter(
diff --git a/net/third_party/quic/core/quic_packet_generator_test.cc b/net/third_party/quic/core/quic_packet_generator_test.cc
index fa409234..b82b0c9 100644
--- a/net/third_party/quic/core/quic_packet_generator_test.cc
+++ b/net/third_party/quic/core/quic_packet_generator_test.cc
@@ -151,7 +151,6 @@
                 Perspective::IS_CLIENT),
         generator_(42, &framer_, &random_generator_, &delegate_, &producer_),
         creator_(QuicPacketGeneratorPeer::GetPacketCreator(&generator_)) {
-    SetQuicReloadableFlag(quic_respect_ietf_header, true);
     creator_->SetEncrypter(
         ENCRYPTION_FORWARD_SECURE,
         QuicMakeUnique<NullEncrypter>(Perspective::IS_CLIENT));
@@ -710,7 +709,9 @@
   // Send some data and a control frame
   MakeIOVector("quux", &iov_);
   generator_.ConsumeData(3, &iov_, 1u, iov_.iov_len, 0, NO_FIN);
-  generator_.AddControlFrame(QuicFrame(CreateGoAwayFrame()));
+  if (framer_.transport_version() != QUIC_VERSION_99) {
+    generator_.AddControlFrame(QuicFrame(CreateGoAwayFrame()));
+  }
   EXPECT_TRUE(generator_.HasPendingStreamFramesOfStream(3));
 
   // All five frames will be flushed out in a single packet.
@@ -723,7 +724,11 @@
 
   PacketContents contents;
   contents.num_ack_frames = 1;
-  contents.num_goaway_frames = 1;
+  if (framer_.transport_version() != QUIC_VERSION_99) {
+    contents.num_goaway_frames = 1;
+  } else {
+    contents.num_goaway_frames = 0;
+  }
   contents.num_rst_stream_frames = 1;
   contents.num_stream_frames = 1;
   CheckPacketContains(contents, 0);
@@ -759,7 +764,9 @@
       generator_.ConsumeData(3, &iov_, 1u, iov_.iov_len, 0, FIN);
   EXPECT_EQ(data_len, consumed.bytes_consumed);
   EXPECT_TRUE(consumed.fin_consumed);
-  generator_.AddControlFrame(QuicFrame(CreateGoAwayFrame()));
+  if (framer_.transport_version() != QUIC_VERSION_99) {
+    generator_.AddControlFrame(QuicFrame(CreateGoAwayFrame()));
+  }
 
   generator_.Flush();
   EXPECT_FALSE(generator_.HasQueuedFrames());
@@ -774,7 +781,11 @@
 
   // The second should have the remainder of the stream data.
   PacketContents contents2;
-  contents2.num_goaway_frames = 1;
+  if (framer_.transport_version() != QUIC_VERSION_99) {
+    contents2.num_goaway_frames = 1;
+  } else {
+    contents2.num_goaway_frames = 0;
+  }
   contents2.num_stream_frames = 1;
   CheckPacketContains(contents2, 1);
 }
diff --git a/net/third_party/quic/core/quic_sent_packet_manager.cc b/net/third_party/quic/core/quic_sent_packet_manager.cc
index 065b2ef..567f8938 100644
--- a/net/third_party/quic/core/quic_sent_packet_manager.cc
+++ b/net/third_party/quic/core/quic_sent_packet_manager.cc
@@ -5,7 +5,7 @@
 #include "net/third_party/quic/core/quic_sent_packet_manager.h"
 
 #include <algorithm>
-#include <string>
+#include <sstream>
 
 #include "net/quic/chromium/quic_utils_chromium.h"
 #include "net/third_party/quic/core/congestion_control/general_loss_algorithm.h"
@@ -59,6 +59,20 @@
     QuicConnectionStats* stats,
     CongestionControlType congestion_control_type,
     LossDetectionType loss_type)
+    : QuicSentPacketManager(perspective,
+                            clock,
+                            stats,
+                            congestion_control_type,
+                            loss_type,
+                            this) {}
+
+QuicSentPacketManager::QuicSentPacketManager(
+    Perspective perspective,
+    const QuicClock* clock,
+    QuicConnectionStats* stats,
+    CongestionControlType congestion_control_type,
+    LossDetectionType loss_type,
+    QuicDebugInfoProviderInterface* debug_info_provider)
     : unacked_packets_(),
       perspective_(perspective),
       clock_(clock),
@@ -93,12 +107,25 @@
       delayed_ack_time_(
           QuicTime::Delta::FromMilliseconds(kDefaultDelayedAckTimeMs)),
       rtt_updated_(false),
+      extra_checks_in_ack_processing_(
+          GetQuicReloadableFlag(quic_extra_checks_in_ack_processing)),
+      debug_info_provider_(debug_info_provider),
       acked_packets_iter_(last_ack_frame_.packets.rbegin()) {
   SetSendAlgorithm(congestion_control_type);
 }
 
 QuicSentPacketManager::~QuicSentPacketManager() {}
 
+QuicString QuicSentPacketManager::DebugStringForAckProcessing() const {
+  std::ostringstream s;
+  s << "{ last_ack_frame: " << last_ack_frame_
+    << ", largest_observed: " << GetLargestObserved()
+    << ", least_unacked: " << unacked_packets_.GetLeastUnacked()
+    << ", unacked_packets_size: " << unacked_packets_.Size()
+    << ", packets_acked: " << packets_acked_ << " }";
+  return s.str();
+}
+
 void QuicSentPacketManager::SetFromConfig(const QuicConfig& config) {
   if (config.HasReceivedInitialRoundTripTimeUs() &&
       config.ReceivedInitialRoundTripTimeUs() > 0) {
@@ -144,7 +171,7 @@
               config.HasClientRequestedIndependentOption(kQBIC,
                                                          perspective_))) {
     SetSendAlgorithm(kCubicBytes);
-  } else if (GetQuicReloadableFlag(quic_enable_pcc) &&
+  } else if (GetQuicReloadableFlag(quic_enable_pcc2) &&
              config.HasClientRequestedIndependentOption(kTPCC, perspective_)) {
     SetSendAlgorithm(kPCC);
   }
@@ -532,8 +559,16 @@
 QuicPacketNumber QuicSentPacketManager::GetNewestRetransmission(
     QuicPacketNumber packet_number,
     const QuicTransmissionInfo& transmission_info) const {
+  const QuicPacketNumber original_packet_number = packet_number;
   QuicPacketNumber retransmission = transmission_info.retransmission;
   while (retransmission != 0) {
+    if (extra_checks_in_ack_processing_) {
+      CHECK(unacked_packets_.Contains(retransmission))
+          << "Retransmisstted pkn out of bound. original_pkn: "
+          << original_packet_number << ", last_retrans_pkn: " << packet_number
+          << ", oob_retrans_pkn: " << retransmission
+          << " Context:" << debug_info_provider_->DebugStringForAckProcessing();
+    }
     packet_number = retransmission;
     retransmission =
         unacked_packets_.GetTransmissionInfo(retransmission).retransmission;
@@ -1061,6 +1096,11 @@
   // Reverse packets_acked_ so that it is in ascending order.
   reverse(packets_acked_.begin(), packets_acked_.end());
   for (AckedPacket& acked_packet : packets_acked_) {
+    if (extra_checks_in_ack_processing_) {
+      CHECK(unacked_packets_.Contains(acked_packet.packet_number))
+          << "Acked pkn out of bound. pkn: " << acked_packet.packet_number
+          << " Context:" << debug_info_provider_->DebugStringForAckProcessing();
+    }
     QuicTransmissionInfo* info =
         unacked_packets_.GetMutableTransmissionInfo(acked_packet.packet_number);
     if (!QuicUtils::IsAckable(info->state)) {
diff --git a/net/third_party/quic/core/quic_sent_packet_manager.h b/net/third_party/quic/core/quic_sent_packet_manager.h
index 3cc31155..8204598 100644
--- a/net/third_party/quic/core/quic_sent_packet_manager.h
+++ b/net/third_party/quic/core/quic_sent_packet_manager.h
@@ -19,6 +19,7 @@
 #include "net/third_party/quic/core/congestion_control/pacing_sender.h"
 #include "net/third_party/quic/core/congestion_control/rtt_stats.h"
 #include "net/third_party/quic/core/congestion_control/send_algorithm_interface.h"
+#include "net/third_party/quic/core/quic_debug_info_provider_interface.h"
 #include "net/third_party/quic/core/quic_packets.h"
 #include "net/third_party/quic/core/quic_pending_retransmission.h"
 #include "net/third_party/quic/core/quic_sustained_bandwidth_recorder.h"
@@ -45,7 +46,8 @@
 // retransmittable data associated with each packet. If a packet is
 // retransmitted, it will keep track of each version of a packet so that if a
 // previous transmission is acked, the data will not be retransmitted.
-class QUIC_EXPORT_PRIVATE QuicSentPacketManager {
+class QUIC_EXPORT_PRIVATE QuicSentPacketManager
+    : public QuicDebugInfoProviderInterface {
  public:
   // Interface which gets callbacks from the QuicSentPacketManager at
   // interesting points.  Implementations must not mutate the state of
@@ -89,8 +91,19 @@
                         QuicConnectionStats* stats,
                         CongestionControlType congestion_control_type,
                         LossDetectionType loss_type);
+
+  QuicSentPacketManager(Perspective perspective,
+                        const QuicClock* clock,
+                        QuicConnectionStats* stats,
+                        CongestionControlType congestion_control_type,
+                        LossDetectionType loss_type,
+                        QuicDebugInfoProviderInterface* debug_info_provider);
+
   virtual ~QuicSentPacketManager();
 
+  // From QuicDebugInfoProviderInterface
+  QuicString DebugStringForAckProcessing() const override;
+
   virtual void SetFromConfig(const QuicConfig& config);
 
   // Pass the CachedNetworkParameters to the send algorithm.
@@ -331,6 +344,10 @@
     delayed_ack_time_ = delayed_ack_time;
   }
 
+  const QuicUnackedPacketMap& unacked_packets() const {
+    return unacked_packets_;
+  }
+
  private:
   friend class test::QuicConnectionPeer;
   friend class test::QuicSentPacketManagerPeer;
@@ -555,6 +572,10 @@
   // when quic_reloadable_flag_quic_use_incremental_ack_processing4 is true.
   bool rtt_updated_;
 
+  // Latched value of quic_reloadable_flag_quic_extra_checks_in_ack_processing.
+  const bool extra_checks_in_ack_processing_;
+  QuicDebugInfoProviderInterface* debug_info_provider_;
+
   // A reverse iterator of last_ack_frame_.packets. This is reset in
   // OnAckRangeStart, and gradually moves in OnAckRange. This is only used
   // when quic_reloadable_flag_quic_use_incremental_ack_processing4 is true.
diff --git a/net/third_party/quic/core/quic_server_session_base_test.cc b/net/third_party/quic/core/quic_server_session_base_test.cc
index a6fe3cc4..538c1bf 100644
--- a/net/third_party/quic/core/quic_server_session_base_test.cc
+++ b/net/third_party/quic/core/quic_server_session_base_test.cc
@@ -131,7 +131,6 @@
                        TlsServerHandshaker::CreateSslCtx()),
         compressed_certs_cache_(
             QuicCompressedCertsCache::kQuicCompressedCertsCacheSize) {
-    config_.SetMaxStreamsPerConnection(kMaxStreamsForTest, kMaxStreamsForTest);
     config_.SetMaxIncomingDynamicStreamsToSend(kMaxStreamsForTest);
     QuicConfigPeer::SetReceivedMaxIncomingDynamicStreams(&config_,
                                                          kMaxStreamsForTest);
diff --git a/net/third_party/quic/core/quic_session.cc b/net/third_party/quic/core/quic_session.cc
index 129d6e2..4ba6e45 100644
--- a/net/third_party/quic/core/quic_session.cc
+++ b/net/third_party/quic/core/quic_session.cc
@@ -553,11 +553,8 @@
   connection_->SetFromConfig(config_);
 
   uint32_t max_streams = 0;
-  if (config_.do_not_use_mspc() ||
-      config_.HasReceivedMaxIncomingDynamicStreams()) {
+  if (config_.HasReceivedMaxIncomingDynamicStreams()) {
     max_streams = config_.ReceivedMaxIncomingDynamicStreams();
-  } else {
-    max_streams = config_.MaxStreamsPerConnection();
   }
   set_max_open_outgoing_streams(max_streams);
   if (perspective() == Perspective::IS_SERVER) {
diff --git a/net/third_party/quic/core/quic_session_test.cc b/net/third_party/quic/core/quic_session_test.cc
index da6314fe..41b8fe65 100644
--- a/net/third_party/quic/core/quic_session_test.cc
+++ b/net/third_party/quic/core/quic_session_test.cc
@@ -721,6 +721,10 @@
 }
 
 TEST_P(QuicSessionTestServer, SendGoAway) {
+  if (transport_version() == QUIC_VERSION_99) {
+    // GoAway frames are not in version 99
+    return;
+  }
   MockPacketWriter* writer = static_cast<MockPacketWriter*>(
       QuicConnectionPeer::GetWriter(session_.connection()));
   EXPECT_CALL(*writer, WritePacket(_, _, _, _, _))
diff --git a/net/third_party/quic/core/quic_spdy_client_session_test.cc b/net/third_party/quic/core/quic_spdy_client_session_test.cc
index 426a3ea..36595c6 100644
--- a/net/third_party/quic/core/quic_spdy_client_session_test.cc
+++ b/net/third_party/quic/core/quic_spdy_client_session_test.cc
@@ -83,7 +83,6 @@
   }
 
   void Initialize() {
-    SetQuicReloadableFlag(quic_respect_ietf_header, true);
     session_.reset();
     connection_ = new PacketSavingConnection(&helper_, &alarm_factory_,
                                              Perspective::IS_CLIENT,
diff --git a/net/third_party/quic/core/quic_spdy_session.cc b/net/third_party/quic/core/quic_spdy_session.cc
index 68ca7a95..87f6ff5 100644
--- a/net/third_party/quic/core/quic_spdy_session.cc
+++ b/net/third_party/quic/core/quic_spdy_session.cc
@@ -291,17 +291,10 @@
       frame_len_(0),
       uncompressed_frame_len_(0),
       supports_push_promise_(perspective() == Perspective::IS_CLIENT),
-      use_h2_deframer_(GetQuicReloadableFlag(quic_enable_h2_deframer)),
       spdy_framer_(spdy::SpdyFramer::ENABLE_COMPRESSION),
       spdy_framer_visitor_(new SpdyFramerVisitor(this)) {
-  if (use_h2_deframer_) {
-    QUIC_FLAG_COUNT(quic_reloadable_flag_quic_enable_h2_deframer);
-    h2_deframer_.set_visitor(spdy_framer_visitor_.get());
-    h2_deframer_.set_debug_visitor(spdy_framer_visitor_.get());
-  } else {
-    hq_deframer_.set_visitor(spdy_framer_visitor_.get());
-    hq_deframer_.set_debug_visitor(spdy_framer_visitor_.get());
-  }
+  h2_deframer_.set_visitor(spdy_framer_visitor_.get());
+  h2_deframer_.set_debug_visitor(spdy_framer_visitor_.get());
   spdy_framer_.set_debug_visitor(spdy_framer_visitor_.get());
 }
 
@@ -393,11 +386,7 @@
 }
 
 size_t QuicSpdySession::ProcessHeaderData(const struct iovec& iov) {
-  if (use_h2_deframer_) {
-    return h2_deframer_.ProcessInput(static_cast<char*>(iov.iov_base),
-                                     iov.iov_len);
-  }
-  return hq_deframer_.ProcessInput(static_cast<char*>(iov.iov_base),
+  return h2_deframer_.ProcessInput(static_cast<char*>(iov.iov_base),
                                    iov.iov_len);
 }
 
@@ -584,15 +573,9 @@
 
 void QuicSpdySession::SetHpackDecoderDebugVisitor(
     std::unique_ptr<QuicHpackDebugVisitor> visitor) {
-  if (use_h2_deframer_) {
-    h2_deframer_.SetDecoderHeaderTableDebugVisitor(
-        QuicMakeUnique<HeaderTableDebugVisitor>(
-            connection()->helper()->GetClock(), std::move(visitor)));
-  } else {
-    hq_deframer_.SetDecoderHeaderTableDebugVisitor(
-        QuicMakeUnique<HeaderTableDebugVisitor>(
-            connection()->helper()->GetClock(), std::move(visitor)));
-  }
+  h2_deframer_.SetDecoderHeaderTableDebugVisitor(
+      QuicMakeUnique<HeaderTableDebugVisitor>(
+          connection()->helper()->GetClock(), std::move(visitor)));
 }
 
 void QuicSpdySession::UpdateHeaderEncoderTableSize(uint32_t value) {
diff --git a/net/third_party/quic/core/quic_spdy_session.h b/net/third_party/quic/core/quic_spdy_session.h
index d9d7d9f..ec29258 100644
--- a/net/third_party/quic/core/quic_spdy_session.h
+++ b/net/third_party/quic/core/quic_spdy_session.h
@@ -13,7 +13,6 @@
 #include "net/third_party/quic/core/quic_headers_stream.h"
 #include "net/third_party/quic/core/quic_session.h"
 #include "net/third_party/quic/core/quic_spdy_stream.h"
-#include "net/third_party/quic/http/decoder/quic_http_frame_decoder_adapter.h"
 #include "net/third_party/quic/platform/api/quic_export.h"
 #include "net/third_party/quic/platform/api/quic_string.h"
 #include "net/third_party/quic/platform/api/quic_string_piece.h"
@@ -183,13 +182,8 @@
   // Sets how much encoded data the hpack decoder of h2_deframer_ is willing to
   // buffer.
   void set_max_decode_buffer_size_bytes(size_t max_decode_buffer_size_bytes) {
-    if (use_h2_deframer_) {
-      h2_deframer_.GetHpackDecoder()->set_max_decode_buffer_size_bytes(
-          max_decode_buffer_size_bytes);
-    } else {
-      hq_deframer_.GetHpackDecoder()->set_max_decode_buffer_size_bytes(
-          max_decode_buffer_size_bytes);
-    }
+    h2_deframer_.GetHpackDecoder()->set_max_decode_buffer_size_bytes(
+        max_decode_buffer_size_bytes);
   }
 
   void set_max_uncompressed_header_bytes(
@@ -241,12 +235,8 @@
 
   bool supports_push_promise_;
 
-  // TODO(rch): remove |use_h2_deframer_| and |hq_deframer_| when
-  // FLAGS_quic_reloadable_flag_quic_enable_h2_deframer is deprecated.
-  const bool use_h2_deframer_;
   spdy::SpdyFramer spdy_framer_;
   http2::Http2DecoderAdapter h2_deframer_;
-  QuicHttpDecoderAdapter hq_deframer_;
   std::unique_ptr<SpdyFramerVisitor> spdy_framer_visitor_;
 
   DISALLOW_COPY_AND_ASSIGN(QuicSpdySession);
diff --git a/net/third_party/quic/core/quic_spdy_session_test.cc b/net/third_party/quic/core/quic_spdy_session_test.cc
index 92e0b2e..6396669c3 100644
--- a/net/third_party/quic/core/quic_spdy_session_test.cc
+++ b/net/third_party/quic/core/quic_spdy_session_test.cc
@@ -782,6 +782,10 @@
 }
 
 TEST_P(QuicSpdySessionTestServer, SendGoAway) {
+  if (transport_version() == QUIC_VERSION_99) {
+    // GoAway frames are not in version 99
+    return;
+  }
   MockPacketWriter* writer = static_cast<MockPacketWriter*>(
       QuicConnectionPeer::GetWriter(session_.connection()));
   EXPECT_CALL(*writer, WritePacket(_, _, _, _, _))
diff --git a/net/third_party/quic/core/quic_time_wait_list_manager.cc b/net/third_party/quic/core/quic_time_wait_list_manager.cc
index 4de5249c..2963f9e7 100644
--- a/net/third_party/quic/core/quic_time_wait_list_manager.cc
+++ b/net/third_party/quic/core/quic_time_wait_list_manager.cc
@@ -93,7 +93,6 @@
 
 void QuicTimeWaitListManager::AddConnectionIdToTimeWait(
     QuicConnectionId connection_id,
-    ParsedQuicVersion version,
     bool ietf_quic,
     TimeWaitAction action,
     std::vector<std::unique_ptr<QuicEncryptedPacket>>* termination_packets) {
@@ -109,8 +108,8 @@
   TrimTimeWaitListIfNeeded();
   DCHECK_LT(num_connections(),
             static_cast<size_t>(FLAGS_quic_time_wait_list_max_connections));
-  ConnectionIdData data(num_packets, version, ietf_quic,
-                        clock_->ApproximateNow(), action);
+  ConnectionIdData data(num_packets, ietf_quic, clock_->ApproximateNow(),
+                        action);
   if (termination_packets != nullptr) {
     data.termination_packets.swap(*termination_packets);
   }
@@ -125,13 +124,6 @@
   return QuicContainsKey(connection_id_map_, connection_id);
 }
 
-ParsedQuicVersion QuicTimeWaitListManager::GetQuicVersionFromConnectionId(
-    QuicConnectionId connection_id) {
-  ConnectionIdMap::iterator it = connection_id_map_.find(connection_id);
-  DCHECK(it != connection_id_map_.end());
-  return (it->second).version;
-}
-
 void QuicTimeWaitListManager::OnBlockedWriterCanWrite() {
   while (!pending_packets_queue_.empty()) {
     QueuedPacket* queued_packet = pending_packets_queue_.front().get();
@@ -325,12 +317,10 @@
 
 QuicTimeWaitListManager::ConnectionIdData::ConnectionIdData(
     int num_packets,
-    ParsedQuicVersion version,
     bool ietf_quic,
     QuicTime time_added,
     TimeWaitAction action)
     : num_packets(num_packets),
-      version(version),
       ietf_quic(ietf_quic),
       time_added(time_added),
       action(action) {}
diff --git a/net/third_party/quic/core/quic_time_wait_list_manager.h b/net/third_party/quic/core/quic_time_wait_list_manager.h
index d5726be9..3e96692b 100644
--- a/net/third_party/quic/core/quic_time_wait_list_manager.h
+++ b/net/third_party/quic/core/quic_time_wait_list_manager.h
@@ -72,14 +72,12 @@
 
   // Adds the given connection_id to time wait state for time_wait_period_.
   // If |termination_packets| are provided, copies of these packets will be sent
-  // when a packet with this connection ID is processed. If no termination
-  // packets are provided, then a PUBLIC_RESET will be sent with the specified
-  // |version|. Any termination packets will be move from |termination_packets|
-  // and will become owned by the manager. |action| specifies what the time wait
-  // list manager should do when processing packets of the connection.
+  // when a packet with this connection ID is processed. Any termination packets
+  // will be move from |termination_packets| and will become owned by the
+  // manager. |action| specifies what the time wait list manager should do when
+  // processing packets of the connection.
   virtual void AddConnectionIdToTimeWait(
       QuicConnectionId connection_id,
-      ParsedQuicVersion version,
       bool ietf_quic,
       TimeWaitAction action,
       std::vector<std::unique_ptr<QuicEncryptedPacket>>* termination_packets);
@@ -111,11 +109,6 @@
   // the size is under the configured maximum.
   void TrimTimeWaitListIfNeeded();
 
-  // Given a ConnectionId that exists in the time wait list, returns the
-  // ParsedQuicVersion associated with it.
-  ParsedQuicVersion GetQuicVersionFromConnectionId(
-      QuicConnectionId connection_id);
-
   // The number of connections on the time-wait list.
   size_t num_connections() const { return connection_id_map_.size(); }
 
@@ -184,7 +177,6 @@
   // connection_id.
   struct ConnectionIdData {
     ConnectionIdData(int num_packets,
-                     ParsedQuicVersion version,
                      bool ietf_quic,
                      QuicTime time_added,
                      TimeWaitAction action);
@@ -195,7 +187,6 @@
     ~ConnectionIdData();
 
     int num_packets;
-    ParsedQuicVersion version;
     bool ietf_quic;
     QuicTime time_added;
     // These packets may contain CONNECTION_CLOSE frames, or SREJ messages.
diff --git a/net/third_party/quic/core/quic_time_wait_list_manager_test.cc b/net/third_party/quic/core/quic_time_wait_list_manager_test.cc
index c30764d..fe4314d3 100644
--- a/net/third_party/quic/core/quic_time_wait_list_manager_test.cc
+++ b/net/third_party/quic/core/quic_time_wait_list_manager_test.cc
@@ -110,8 +110,7 @@
     termination_packets.push_back(std::unique_ptr<QuicEncryptedPacket>(
         new QuicEncryptedPacket(nullptr, 0, false)));
     time_wait_list_manager_.AddConnectionIdToTimeWait(
-        connection_id, QuicVersionMax(), false,
-        QuicTimeWaitListManager::SEND_TERMINATION_PACKETS,
+        connection_id, false, QuicTimeWaitListManager::SEND_TERMINATION_PACKETS,
         &termination_packets);
   }
 
@@ -121,8 +120,8 @@
       QuicTimeWaitListManager::TimeWaitAction action,
       std::vector<std::unique_ptr<QuicEncryptedPacket>>* packets) {
     time_wait_list_manager_.AddConnectionIdToTimeWait(
-        connection_id, version, version.transport_version > QUIC_VERSION_43,
-        action, packets);
+        connection_id, version.transport_version > QUIC_VERSION_43, action,
+        packets);
   }
 
   bool IsConnectionIdInTimeWait(QuicConnectionId connection_id) {
@@ -398,39 +397,6 @@
   time_wait_list_manager_.OnBlockedWriterCanWrite();
 }
 
-TEST_F(QuicTimeWaitListManagerTest, GetQuicVersionFromMap) {
-  const int kConnectionId1 = 123;
-  const int kConnectionId2 = 456;
-  const int kConnectionId3 = 789;
-
-  EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(kConnectionId1));
-  EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(kConnectionId2));
-  EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(kConnectionId3));
-  AddConnectionId(kConnectionId1, QuicVersionMin(),
-                  QuicTimeWaitListManager::SEND_STATELESS_RESET, nullptr);
-  const size_t kConnectionCloseLength = 100;
-  std::vector<std::unique_ptr<QuicEncryptedPacket>> termination_packets;
-  termination_packets.push_back(
-      std::unique_ptr<QuicEncryptedPacket>(new QuicEncryptedPacket(
-          new char[kConnectionCloseLength], kConnectionCloseLength, true)));
-  AddConnectionId(kConnectionId2, QuicVersionMax(),
-                  QuicTimeWaitListManager::SEND_TERMINATION_PACKETS,
-                  &termination_packets);
-  AddConnectionId(kConnectionId3, QuicVersionMax(),
-                  QuicTimeWaitListManager::SEND_TERMINATION_PACKETS,
-                  &termination_packets);
-
-  EXPECT_EQ(QuicTransportVersionMin(),
-            QuicTimeWaitListManagerPeer::GetQuicVersionFromConnectionId(
-                &time_wait_list_manager_, kConnectionId1));
-  EXPECT_EQ(QuicTransportVersionMax(),
-            QuicTimeWaitListManagerPeer::GetQuicVersionFromConnectionId(
-                &time_wait_list_manager_, kConnectionId2));
-  EXPECT_EQ(QuicTransportVersionMax(),
-            QuicTimeWaitListManagerPeer::GetQuicVersionFromConnectionId(
-                &time_wait_list_manager_, kConnectionId3));
-}
-
 TEST_F(QuicTimeWaitListManagerTest, AddConnectionIdTwice) {
   // Add connection_ids such that their expiry time is time_wait_period_.
   epoll_server_.set_now_in_usec(0);
diff --git a/net/third_party/quic/core/quic_types.h b/net/third_party/quic/core/quic_types.h
index 9270f48..3433361 100644
--- a/net/third_party/quic/core/quic_types.h
+++ b/net/third_party/quic/core/quic_types.h
@@ -198,12 +198,6 @@
   // whether the frame is a stream frame or not, and then examine each
   // bit specifically when/as needed.
   IETF_STREAM = 0x10,
-
-  // Temporary, for testing only. To be removed when Version 99 is finalized.
-  IETF_TEMP_GOAWAY_FRAME = 0xf0,
-  IETF_TEMP_WINDOW_UPDATE_FRAME = 0xf1,
-  IETF_TEMP_STOP_WAITING_FRAME = 0xf2,
-  IETF_TEMP_BLOCKED_FRAME = 0xf3
 };
 // Masks for the bits that indicate the frame is a Stream frame vs the
 // bits used as flags.
diff --git a/net/third_party/quic/core/quic_unacked_packet_map.h b/net/third_party/quic/core/quic_unacked_packet_map.h
index 8729f04..ce8bec5 100644
--- a/net/third_party/quic/core/quic_unacked_packet_map.h
+++ b/net/third_party/quic/core/quic_unacked_packet_map.h
@@ -39,6 +39,15 @@
                      QuicTime sent_time,
                      bool set_in_flight);
 
+  // Returns true iff |packet_number| is in the map.
+  bool Contains(QuicPacketNumber packet_number) const {
+    return packet_number >= least_unacked_ &&
+           packet_number < least_unacked_ + unacked_packets_.size();
+  }
+
+  // Returns the number of packets in the map.
+  size_t Size() const { return unacked_packets_.size(); }
+
   // Returns true if the packet |packet_number| is unacked.
   bool IsUnacked(QuicPacketNumber packet_number) const;
 
diff --git a/net/third_party/quic/core/quic_version_manager.cc b/net/third_party/quic/core/quic_version_manager.cc
index b2213f91..0a71f0e 100644
--- a/net/third_party/quic/core/quic_version_manager.cc
+++ b/net/third_party/quic/core/quic_version_manager.cc
@@ -60,16 +60,12 @@
   filtered_transport_versions_.clear();
   for (ParsedQuicVersion version : filtered_supported_versions_) {
     auto transport_version = version.transport_version;
-    if (!GetQuicReloadableFlag(
-            quic_version_manager_dedupe_transport_versions) ||
-        std::find(filtered_transport_versions_.begin(),
+    if (std::find(filtered_transport_versions_.begin(),
                   filtered_transport_versions_.end(),
                   transport_version) == filtered_transport_versions_.end()) {
       filtered_transport_versions_.push_back(transport_version);
     }
   }
-  QUIC_FLAG_COUNT(
-      quic_reloadable_flag_quic_version_manager_dedupe_transport_versions);
 }
 
 }  // namespace quic
diff --git a/net/third_party/quic/core/tls_client_handshaker.cc b/net/third_party/quic/core/tls_client_handshaker.cc
index 6696da6..943b844 100644
--- a/net/third_party/quic/core/tls_client_handshaker.cc
+++ b/net/third_party/quic/core/tls_client_handshaker.cc
@@ -42,11 +42,13 @@
                                          const QuicServerId& server_id,
                                          ProofVerifier* proof_verifier,
                                          SSL_CTX* ssl_ctx,
-                                         ProofVerifyContext* verify_context)
+                                         ProofVerifyContext* verify_context,
+                                         const QuicString& user_agent_id)
     : TlsHandshaker(stream, session, ssl_ctx),
       server_id_(server_id),
       proof_verifier_(proof_verifier),
       verify_context_(verify_context),
+      user_agent_id_(user_agent_id),
       crypto_negotiated_params_(new QuicCryptoNegotiatedParameters) {}
 
 TlsClientHandshaker::~TlsClientHandshaker() {
@@ -102,6 +104,7 @@
   if (!session()->config()->FillTransportParameters(&params)) {
     return false;
   }
+  params.google_quic_params->SetStringPiece(kUAID, user_agent_id_);
 
   std::vector<uint8_t> param_bytes;
   return SerializeTransportParameters(params, &param_bytes) &&
diff --git a/net/third_party/quic/core/tls_client_handshaker.h b/net/third_party/quic/core/tls_client_handshaker.h
index e4d57f4..b6d5021 100644
--- a/net/third_party/quic/core/tls_client_handshaker.h
+++ b/net/third_party/quic/core/tls_client_handshaker.h
@@ -28,7 +28,8 @@
                       ProofVerifier* proof_verifier,
                       SSL_CTX* ssl_ctx,
                       // Takes ownership of |verify_context|.
-                      ProofVerifyContext* verify_context);
+                      ProofVerifyContext* verify_context,
+                      const QuicString& user_agent_id);
 
   ~TlsClientHandshaker() override;
 
@@ -106,6 +107,8 @@
   ProofVerifier* proof_verifier_;
   std::unique_ptr<ProofVerifyContext> verify_context_;
 
+  QuicString user_agent_id_;
+
   // ProofVerifierCallback used for async certificate verification. This object
   // is owned by |proof_verifier_|.
   ProofVerifierCallbackImpl* proof_verify_callback_ = nullptr;
diff --git a/net/third_party/quic/core/tls_handshaker_test.cc b/net/third_party/quic/core/tls_handshaker_test.cc
index db9ab2a0..9a793e81 100644
--- a/net/third_party/quic/core/tls_handshaker_test.cc
+++ b/net/third_party/quic/core/tls_handshaker_test.cc
@@ -190,7 +190,8 @@
             QuicServerId("test.example.com", 443),
             proof_verifier_.get(),
             ssl_ctx_.get(),
-            crypto_test_utils::ProofVerifyContextForTesting())) {}
+            crypto_test_utils::ProofVerifyContextForTesting(),
+            "quic-tester")) {}
 
   ~TestQuicCryptoClientStream() override = default;
 
diff --git a/net/third_party/quic/http/decoder/payload_decoders/quic_http_altsvc_payload_decoder.cc b/net/third_party/quic/http/decoder/payload_decoders/quic_http_altsvc_payload_decoder.cc
deleted file mode 100644
index d8c8e6b..0000000
--- a/net/third_party/quic/http/decoder/payload_decoders/quic_http_altsvc_payload_decoder.cc
+++ /dev/null
@@ -1,155 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "net/third_party/quic/http/decoder/payload_decoders/quic_http_altsvc_payload_decoder.h"
-
-#include <stddef.h>
-
-#include "base/logging.h"
-#include "base/macros.h"
-#include "net/third_party/quic/http/decoder/quic_http_decode_buffer.h"
-#include "net/third_party/quic/http/decoder/quic_http_frame_decoder_listener.h"
-#include "net/third_party/quic/http/quic_http_constants.h"
-#include "net/third_party/quic/http/quic_http_structures.h"
-#include "net/third_party/quic/platform/api/quic_bug_tracker.h"
-#include "net/third_party/quic/platform/api/quic_fallthrough.h"
-
-namespace quic {
-
-std::ostream& operator<<(std::ostream& out,
-                         QuicHttpAltSvcQuicHttpPayloadDecoder::PayloadState v) {
-  switch (v) {
-    case QuicHttpAltSvcQuicHttpPayloadDecoder::PayloadState::
-        kStartDecodingStruct:
-      return out << "kStartDecodingStruct";
-    case QuicHttpAltSvcQuicHttpPayloadDecoder::PayloadState::
-        kMaybeDecodedStruct:
-      return out << "kMaybeDecodedStruct";
-    case QuicHttpAltSvcQuicHttpPayloadDecoder::PayloadState::kDecodingStrings:
-      return out << "kDecodingStrings";
-    case QuicHttpAltSvcQuicHttpPayloadDecoder::PayloadState::
-        kResumeDecodingStruct:
-      return out << "kResumeDecodingStruct";
-  }
-  // Since the value doesn't come over the wire, only a programming bug should
-  // result in reaching this point.
-  int unknown = static_cast<int>(v);
-  QUIC_BUG << "Invalid QuicHttpAltSvcQuicHttpPayloadDecoder::PayloadState: "
-           << unknown;
-  return out << "QuicHttpAltSvcQuicHttpPayloadDecoder::PayloadState(" << unknown
-             << ")";
-}
-
-QuicHttpDecodeStatus QuicHttpAltSvcQuicHttpPayloadDecoder::StartDecodingPayload(
-    QuicHttpFrameDecoderState* state,
-    QuicHttpDecodeBuffer* db) {
-  DVLOG(2) << "QuicHttpAltSvcQuicHttpPayloadDecoder::StartDecodingPayload: "
-           << state->frame_header();
-  DCHECK_EQ(QuicHttpFrameType::ALTSVC, state->frame_header().type);
-  DCHECK_LE(db->Remaining(), state->frame_header().payload_length);
-  DCHECK_EQ(0, state->frame_header().flags);
-
-  state->InitializeRemainders();
-  payload_state_ = PayloadState::kStartDecodingStruct;
-
-  return ResumeDecodingPayload(state, db);
-}
-
-QuicHttpDecodeStatus
-QuicHttpAltSvcQuicHttpPayloadDecoder::ResumeDecodingPayload(
-    QuicHttpFrameDecoderState* state,
-    QuicHttpDecodeBuffer* db) {
-  const QuicHttpFrameHeader& frame_header = state->frame_header();
-  DVLOG(2) << "QuicHttpAltSvcQuicHttpPayloadDecoder::ResumeDecodingPayload: "
-           << frame_header;
-  DCHECK_EQ(QuicHttpFrameType::ALTSVC, frame_header.type);
-  DCHECK_LE(state->remaining_payload(), frame_header.payload_length);
-  DCHECK_LE(db->Remaining(), state->remaining_payload());
-  DCHECK_NE(PayloadState::kMaybeDecodedStruct, payload_state_);
-  QuicHttpDecodeStatus status = QuicHttpDecodeStatus::kDecodeError;
-  while (true) {
-    DVLOG(2) << "QuicHttpAltSvcQuicHttpPayloadDecoder::ResumeDecodingPayload "
-                "payload_state_="
-             << payload_state_;
-    switch (payload_state_) {
-      case PayloadState::kStartDecodingStruct:
-        status = state->StartDecodingStructureInPayload(&altsvc_fields_, db);
-        QUIC_FALLTHROUGH_INTENDED;
-
-      case PayloadState::kMaybeDecodedStruct:
-        if (status == QuicHttpDecodeStatus::kDecodeDone &&
-            altsvc_fields_.origin_length <= state->remaining_payload()) {
-          size_t origin_length = altsvc_fields_.origin_length;
-          size_t value_length = state->remaining_payload() - origin_length;
-          state->listener()->OnAltSvcStart(frame_header, origin_length,
-                                           value_length);
-        } else if (status != QuicHttpDecodeStatus::kDecodeDone) {
-          DCHECK(state->remaining_payload() > 0 ||
-                 status == QuicHttpDecodeStatus::kDecodeError)
-              << "\nremaining_payload: " << state->remaining_payload()
-              << "\nstatus: " << status << "\nheader: " << frame_header;
-          // Assume in progress.
-          payload_state_ = PayloadState::kResumeDecodingStruct;
-          return status;
-        } else {
-          // The origin's length is longer than the remaining payload.
-          DCHECK_GT(altsvc_fields_.origin_length, state->remaining_payload());
-          return state->ReportFrameSizeError();
-        }
-        QUIC_FALLTHROUGH_INTENDED;
-
-      case PayloadState::kDecodingStrings:
-        return DecodeStrings(state, db);
-
-      case PayloadState::kResumeDecodingStruct:
-        status = state->ResumeDecodingStructureInPayload(&altsvc_fields_, db);
-        payload_state_ = PayloadState::kMaybeDecodedStruct;
-        continue;
-    }
-    QUIC_BUG << "PayloadState: " << payload_state_;
-  }
-}
-
-QuicHttpDecodeStatus QuicHttpAltSvcQuicHttpPayloadDecoder::DecodeStrings(
-    QuicHttpFrameDecoderState* state,
-    QuicHttpDecodeBuffer* db) {
-  DVLOG(2) << "QuicHttpAltSvcQuicHttpPayloadDecoder::DecodeStrings "
-              "remaining_payload="
-           << state->remaining_payload()
-           << ", db->Remaining=" << db->Remaining();
-  // Note that we don't explicitly keep track of exactly how far through the
-  // origin; instead we compute it from how much is left of the original
-  // payload length and the decoded total length of the origin.
-  size_t origin_length = altsvc_fields_.origin_length;
-  size_t value_length = state->frame_header().payload_length - origin_length -
-                        QuicHttpAltSvcFields::EncodedSize();
-  if (state->remaining_payload() > value_length) {
-    size_t remaining_origin_length = state->remaining_payload() - value_length;
-    size_t avail = db->MinLengthRemaining(remaining_origin_length);
-    state->listener()->OnAltSvcOriginData(db->cursor(), avail);
-    db->AdvanceCursor(avail);
-    state->ConsumePayload(avail);
-    if (remaining_origin_length > avail) {
-      payload_state_ = PayloadState::kDecodingStrings;
-      return QuicHttpDecodeStatus::kDecodeInProgress;
-    }
-  }
-  // All that is left is the value string.
-  DCHECK_LE(state->remaining_payload(), value_length);
-  DCHECK_LE(db->Remaining(), state->remaining_payload());
-  if (db->HasData()) {
-    size_t avail = db->Remaining();
-    state->listener()->OnAltSvcValueData(db->cursor(), avail);
-    db->AdvanceCursor(avail);
-    state->ConsumePayload(avail);
-  }
-  if (state->remaining_payload() == 0) {
-    state->listener()->OnAltSvcEnd();
-    return QuicHttpDecodeStatus::kDecodeDone;
-  }
-  payload_state_ = PayloadState::kDecodingStrings;
-  return QuicHttpDecodeStatus::kDecodeInProgress;
-}
-
-}  // namespace quic
diff --git a/net/third_party/quic/http/decoder/payload_decoders/quic_http_altsvc_payload_decoder.h b/net/third_party/quic/http/decoder/payload_decoders/quic_http_altsvc_payload_decoder.h
deleted file mode 100644
index 72e2526c..0000000
--- a/net/third_party/quic/http/decoder/payload_decoders/quic_http_altsvc_payload_decoder.h
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_THIRD_PARTY_QUIC_HTTP_DECODER_PAYLOAD_DECODERS_QUIC_HTTP_ALTSVC_PAYLOAD_DECODER_H_
-#define NET_THIRD_PARTY_QUIC_HTTP_DECODER_PAYLOAD_DECODERS_QUIC_HTTP_ALTSVC_PAYLOAD_DECODER_H_
-
-// Decodes the payload of a ALTSVC frame.
-// See http://g3doc/gfe/quic/http/decoder/payload_decoders/README.md for info
-// about payload decoders.
-
-#include "net/third_party/quic/http/decoder/quic_http_decode_buffer.h"
-#include "net/third_party/quic/http/decoder/quic_http_decode_status.h"
-#include "net/third_party/quic/http/decoder/quic_http_frame_decoder_state.h"
-#include "net/third_party/quic/http/quic_http_structures.h"
-#include "net/third_party/quic/platform/api/quic_export.h"
-
-namespace quic {
-namespace test {
-class QuicHttpAltSvcQuicHttpPayloadDecoderPeer;
-}  // namespace test
-
-class QUIC_EXPORT_PRIVATE QuicHttpAltSvcQuicHttpPayloadDecoder {
- public:
-  // States during decoding of a ALTSVC frame.
-  enum class PayloadState {
-    // Start decoding the fixed size structure at the start of an ALTSVC
-    // frame (QuicHttpAltSvcFields).
-    kStartDecodingStruct,
-
-    // Handle the QuicHttpDecodeStatus returned from starting or resuming the
-    // decoding of QuicHttpAltSvcFields. If complete, calls OnAltSvcStart.
-    kMaybeDecodedStruct,
-
-    // Reports the value of the std::strings (origin and value) of an ALTSVC
-    // frame
-    // to the listener.
-    kDecodingStrings,
-
-    // The initial decode buffer wasn't large enough for the
-    // QuicHttpAltSvcFields,
-    // so this state resumes the decoding when ResumeDecodingPayload is called
-    // later with a new QuicHttpDecodeBuffer.
-    kResumeDecodingStruct,
-  };
-
-  // Starts the decoding of a ALTSVC frame's payload, and completes it if the
-  // entire payload is in the provided decode buffer.
-  QuicHttpDecodeStatus StartDecodingPayload(QuicHttpFrameDecoderState* state,
-                                            QuicHttpDecodeBuffer* db);
-
-  // Resumes decoding a ALTSVC frame's payload that has been split across
-  // decode buffers.
-  QuicHttpDecodeStatus ResumeDecodingPayload(QuicHttpFrameDecoderState* state,
-                                             QuicHttpDecodeBuffer* db);
-
- private:
-  friend class test::QuicHttpAltSvcQuicHttpPayloadDecoderPeer;
-
-  // Implements state kDecodingStrings.
-  QuicHttpDecodeStatus DecodeStrings(QuicHttpFrameDecoderState* state,
-                                     QuicHttpDecodeBuffer* db);
-
-  QuicHttpAltSvcFields altsvc_fields_;
-  PayloadState payload_state_;
-};
-
-}  // namespace quic
-
-#endif  // NET_THIRD_PARTY_QUIC_HTTP_DECODER_PAYLOAD_DECODERS_QUIC_HTTP_ALTSVC_PAYLOAD_DECODER_H_
diff --git a/net/third_party/quic/http/decoder/payload_decoders/quic_http_altsvc_payload_decoder_test.cc b/net/third_party/quic/http/decoder/payload_decoders/quic_http_altsvc_payload_decoder_test.cc
deleted file mode 100644
index d112b274..0000000
--- a/net/third_party/quic/http/decoder/payload_decoders/quic_http_altsvc_payload_decoder_test.cc
+++ /dev/null
@@ -1,136 +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 "net/third_party/quic/http/decoder/payload_decoders/quic_http_altsvc_payload_decoder.h"
-
-#include <stddef.h>
-
-#include <cstdint>
-
-#include "base/logging.h"
-#include "net/third_party/quic/http/decoder/payload_decoders/quic_http_payload_decoder_base_test_util.h"
-#include "net/third_party/quic/http/decoder/quic_http_frame_decoder_listener.h"
-#include "net/third_party/quic/http/quic_http_constants.h"
-#include "net/third_party/quic/http/quic_http_structures_test_util.h"
-#include "net/third_party/quic/http/test_tools/quic_http_frame_parts.h"
-#include "net/third_party/quic/http/test_tools/quic_http_frame_parts_collector.h"
-#include "net/third_party/quic/http/tools/quic_http_frame_builder.h"
-#include "net/third_party/quic/http/tools/quic_http_random_decoder_test.h"
-#include "net/third_party/quic/platform/api/quic_string.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace quic {
-namespace test {
-
-// Provides friend access to an instance of the payload decoder, and also
-// provides info to aid in testing.
-class QuicHttpAltSvcQuicHttpPayloadDecoderPeer {
- public:
-  static constexpr QuicHttpFrameType FrameType() {
-    return QuicHttpFrameType::ALTSVC;
-  }
-
-  // Returns the mask of flags that affect the decoding of the payload (i.e.
-  // flags that that indicate the presence of certain fields or padding).
-  static constexpr uint8_t FlagsAffectingPayloadDecoding() { return 0; }
-
-  static void Randomize(QuicHttpAltSvcQuicHttpPayloadDecoder* p,
-                        QuicTestRandomBase* rng) {
-    CorruptEnum(&p->payload_state_, rng);
-    test::Randomize(&p->altsvc_fields_, rng);
-    VLOG(1)
-        << "QuicHttpAltSvcQuicHttpPayloadDecoderPeer::Randomize altsvc_fields_="
-        << p->altsvc_fields_;
-  }
-};
-
-namespace {
-
-struct Listener : public QuicHttpFramePartsCollector {
-  void OnAltSvcStart(const QuicHttpFrameHeader& header,
-                     size_t origin_length,
-                     size_t value_length) override {
-    VLOG(1) << "OnAltSvcStart header: " << header
-            << "; origin_length=" << origin_length
-            << "; value_length=" << value_length;
-    StartFrame(header)->OnAltSvcStart(header, origin_length, value_length);
-  }
-
-  void OnAltSvcOriginData(const char* data, size_t len) override {
-    VLOG(1) << "OnAltSvcOriginData: len=" << len;
-    CurrentFrame()->OnAltSvcOriginData(data, len);
-  }
-
-  void OnAltSvcValueData(const char* data, size_t len) override {
-    VLOG(1) << "OnAltSvcValueData: len=" << len;
-    CurrentFrame()->OnAltSvcValueData(data, len);
-  }
-
-  void OnAltSvcEnd() override {
-    VLOG(1) << "OnAltSvcEnd";
-    EndFrame()->OnAltSvcEnd();
-  }
-
-  void OnFrameSizeError(const QuicHttpFrameHeader& header) override {
-    VLOG(1) << "OnFrameSizeError: " << header;
-    FrameError(header)->OnFrameSizeError(header);
-  }
-};
-
-class QuicHttpAltSvcQuicHttpPayloadDecoderTest
-    : public AbstractQuicHttpPayloadDecoderTest<
-          QuicHttpAltSvcQuicHttpPayloadDecoder,
-          QuicHttpAltSvcQuicHttpPayloadDecoderPeer,
-          Listener> {};
-
-// Confirm we get an error if the payload is not long enough to hold
-// QuicHttpAltSvcFields and the indicated length of origin.
-TEST_F(QuicHttpAltSvcQuicHttpPayloadDecoderTest, Truncated) {
-  QuicHttpFrameBuilder fb;
-  fb.Append(
-      QuicHttpAltSvcFields{0xffff});  // The longest possible origin length.
-  fb.Append("Too little origin!");
-  EXPECT_TRUE(
-      VerifyDetectsFrameSizeError(0, fb.buffer(), /*approve_size*/ nullptr));
-}
-
-class QuicHttpAltSvcPayloadLengthTests
-    : public QuicHttpAltSvcQuicHttpPayloadDecoderTest,
-      public ::testing::WithParamInterface<
-          ::testing::tuple<uint16_t, uint32_t>> {
- protected:
-  QuicHttpAltSvcPayloadLengthTests()
-      : origin_length_(::testing::get<0>(GetParam())),
-        value_length_(::testing::get<1>(GetParam())) {
-    VLOG(1) << "################  origin_length_=" << origin_length_
-            << "   value_length_=" << value_length_ << "  ################";
-  }
-
-  const uint16_t origin_length_;
-  const uint32_t value_length_;
-};
-
-INSTANTIATE_TEST_CASE_P(VariousOriginAndValueLengths,
-                        QuicHttpAltSvcPayloadLengthTests,
-                        ::testing::Combine(::testing::Values(0, 1, 3, 65535),
-                                           ::testing::Values(0, 1, 3, 65537)));
-
-TEST_P(QuicHttpAltSvcPayloadLengthTests, ValidOriginAndValueLength) {
-  QuicString origin = Random().RandString(origin_length_);
-  QuicString value = Random().RandString(value_length_);
-  QuicHttpFrameBuilder fb;
-  fb.Append(QuicHttpAltSvcFields{origin_length_});
-  fb.Append(origin);
-  fb.Append(value);
-  QuicHttpFrameHeader header(fb.size(), QuicHttpFrameType::ALTSVC, RandFlags(),
-                             RandStreamId());
-  set_frame_header(header);
-  QuicHttpFrameParts expected(header);
-  expected.SetAltSvcExpected(origin, value);
-  ASSERT_TRUE(DecodePayloadAndValidateSeveralWays(fb.buffer(), expected));
-}
-
-}  // namespace
-}  // namespace test
-}  // namespace quic
diff --git a/net/third_party/quic/http/decoder/payload_decoders/quic_http_continuation_payload_decoder.cc b/net/third_party/quic/http/decoder/payload_decoders/quic_http_continuation_payload_decoder.cc
deleted file mode 100644
index c87823c2..0000000
--- a/net/third_party/quic/http/decoder/payload_decoders/quic_http_continuation_payload_decoder.cc
+++ /dev/null
@@ -1,65 +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 "net/third_party/quic/http/decoder/payload_decoders/quic_http_continuation_payload_decoder.h"
-
-#include <stddef.h>
-
-#include <cstdint>
-
-#include "base/logging.h"
-#include "net/third_party/quic/http/decoder/quic_http_decode_buffer.h"
-#include "net/third_party/quic/http/decoder/quic_http_frame_decoder_listener.h"
-#include "net/third_party/quic/http/quic_http_constants.h"
-#include "net/third_party/quic/http/quic_http_structures.h"
-
-namespace quic {
-
-QuicHttpDecodeStatus
-QuicHttpContinuationQuicHttpPayloadDecoder::StartDecodingPayload(
-    QuicHttpFrameDecoderState* state,
-    QuicHttpDecodeBuffer* db) {
-  const QuicHttpFrameHeader& frame_header = state->frame_header();
-  const uint32_t total_length = frame_header.payload_length;
-
-  DVLOG(2)
-      << "QuicHttpContinuationQuicHttpPayloadDecoder::StartDecodingPayload: "
-      << frame_header;
-  DCHECK_EQ(QuicHttpFrameType::CONTINUATION, frame_header.type);
-  DCHECK_LE(db->Remaining(), total_length);
-  DCHECK_EQ(0,
-            frame_header.flags & ~(QuicHttpFrameFlag::QUIC_HTTP_END_HEADERS));
-
-  state->InitializeRemainders();
-  state->listener()->OnContinuationStart(frame_header);
-  return ResumeDecodingPayload(state, db);
-}
-
-QuicHttpDecodeStatus
-QuicHttpContinuationQuicHttpPayloadDecoder::ResumeDecodingPayload(
-    QuicHttpFrameDecoderState* state,
-    QuicHttpDecodeBuffer* db) {
-  DVLOG(2)
-      << "QuicHttpContinuationQuicHttpPayloadDecoder::ResumeDecodingPayload"
-      << "  remaining_payload=" << state->remaining_payload()
-      << "  db->Remaining=" << db->Remaining();
-  DCHECK_EQ(QuicHttpFrameType::CONTINUATION, state->frame_header().type);
-  DCHECK_LE(state->remaining_payload(), state->frame_header().payload_length);
-  DCHECK_LE(db->Remaining(), state->remaining_payload());
-
-  size_t avail = db->Remaining();
-  DCHECK_LE(avail, state->remaining_payload());
-  if (avail > 0) {
-    state->listener()->OnHpackFragment(db->cursor(), avail);
-    db->AdvanceCursor(avail);
-    state->ConsumePayload(avail);
-  }
-  if (state->remaining_payload() == 0) {
-    state->listener()->OnContinuationEnd();
-    return QuicHttpDecodeStatus::kDecodeDone;
-  }
-  return QuicHttpDecodeStatus::kDecodeInProgress;
-}
-
-}  // namespace quic
diff --git a/net/third_party/quic/http/decoder/payload_decoders/quic_http_continuation_payload_decoder.h b/net/third_party/quic/http/decoder/payload_decoders/quic_http_continuation_payload_decoder.h
deleted file mode 100644
index 7c3f0938..0000000
--- a/net/third_party/quic/http/decoder/payload_decoders/quic_http_continuation_payload_decoder.h
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_THIRD_PARTY_QUIC_HTTP_DECODER_PAYLOAD_DECODERS_QUIC_HTTP_CONTINUATION_PAYLOAD_DECODER_H_
-#define NET_THIRD_PARTY_QUIC_HTTP_DECODER_PAYLOAD_DECODERS_QUIC_HTTP_CONTINUATION_PAYLOAD_DECODER_H_
-
-// Decodes the payload of a CONTINUATION frame.
-// See http://g3doc/gfe/quic/http/decoder/payload_decoders/README.md for info
-// about payload decoders.
-
-#include "net/third_party/quic/http/decoder/quic_http_decode_buffer.h"
-#include "net/third_party/quic/http/decoder/quic_http_decode_status.h"
-#include "net/third_party/quic/http/decoder/quic_http_frame_decoder_state.h"
-#include "net/third_party/quic/platform/api/quic_export.h"
-
-namespace quic {
-
-class QUIC_EXPORT_PRIVATE QuicHttpContinuationQuicHttpPayloadDecoder {
- public:
-  // Starts the decoding of a CONTINUATION frame's payload, and completes
-  // it if the entire payload is in the provided decode buffer.
-  QuicHttpDecodeStatus StartDecodingPayload(QuicHttpFrameDecoderState* state,
-                                            QuicHttpDecodeBuffer* db);
-
-  // Resumes decoding a CONTINUATION frame's payload that has been split across
-  // decode buffers.
-  QuicHttpDecodeStatus ResumeDecodingPayload(QuicHttpFrameDecoderState* state,
-                                             QuicHttpDecodeBuffer* db);
-};
-
-}  // namespace quic
-
-#endif  // NET_THIRD_PARTY_QUIC_HTTP_DECODER_PAYLOAD_DECODERS_QUIC_HTTP_CONTINUATION_PAYLOAD_DECODER_H_
diff --git a/net/third_party/quic/http/decoder/payload_decoders/quic_http_continuation_payload_decoder_test.cc b/net/third_party/quic/http/decoder/payload_decoders/quic_http_continuation_payload_decoder_test.cc
deleted file mode 100644
index 8c513f0aa2..0000000
--- a/net/third_party/quic/http/decoder/payload_decoders/quic_http_continuation_payload_decoder_test.cc
+++ /dev/null
@@ -1,97 +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 "net/third_party/quic/http/decoder/payload_decoders/quic_http_continuation_payload_decoder.h"
-
-#include <stddef.h>
-
-#include <cstdint>
-#include <type_traits>
-
-#include "base/logging.h"
-#include "net/third_party/quic/http/decoder/payload_decoders/quic_http_payload_decoder_base_test_util.h"
-#include "net/third_party/quic/http/decoder/quic_http_frame_decoder_listener.h"
-#include "net/third_party/quic/http/quic_http_constants.h"
-#include "net/third_party/quic/http/quic_http_structures.h"
-#include "net/third_party/quic/http/test_tools/quic_http_frame_parts.h"
-#include "net/third_party/quic/http/test_tools/quic_http_frame_parts_collector.h"
-#include "net/third_party/quic/http/tools/quic_http_random_decoder_test.h"
-#include "net/third_party/quic/platform/api/quic_string.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace quic {
-namespace test {
-
-// Provides friend access to an instance of the payload decoder, and also
-// provides info to aid in testing.
-class QuicHttpContinuationQuicHttpPayloadDecoderPeer {
- public:
-  static constexpr QuicHttpFrameType FrameType() {
-    return QuicHttpFrameType::CONTINUATION;
-  }
-
-  // Returns the mask of flags that affect the decoding of the payload (i.e.
-  // flags that that indicate the presence of certain fields or padding).
-  static constexpr uint8_t FlagsAffectingPayloadDecoding() { return 0; }
-
-  static void Randomize(QuicHttpContinuationQuicHttpPayloadDecoder* p,
-                        QuicTestRandomBase* rng) {
-    // QuicHttpContinuationQuicHttpPayloadDecoder has no fields,
-    // so there is nothing to randomize.
-    static_assert(
-        std::is_empty<QuicHttpContinuationQuicHttpPayloadDecoder>::value,
-        "Need to randomize fields of "
-        "QuicHttpContinuationQuicHttpPayloadDecoder");
-  }
-};
-
-namespace {
-
-struct Listener : public QuicHttpFramePartsCollector {
-  void OnContinuationStart(const QuicHttpFrameHeader& header) override {
-    VLOG(1) << "OnContinuationStart: " << header;
-    StartFrame(header)->OnContinuationStart(header);
-  }
-
-  void OnHpackFragment(const char* data, size_t len) override {
-    VLOG(1) << "OnHpackFragment: len=" << len;
-    CurrentFrame()->OnHpackFragment(data, len);
-  }
-
-  void OnContinuationEnd() override {
-    VLOG(1) << "OnContinuationEnd";
-    EndFrame()->OnContinuationEnd();
-  }
-};
-
-class QuicHttpContinuationQuicHttpPayloadDecoderTest
-    : public AbstractQuicHttpPayloadDecoderTest<
-          QuicHttpContinuationQuicHttpPayloadDecoder,
-          QuicHttpContinuationQuicHttpPayloadDecoderPeer,
-          Listener>,
-      public ::testing::WithParamInterface<uint32_t> {
- protected:
-  QuicHttpContinuationQuicHttpPayloadDecoderTest() : length_(GetParam()) {
-    VLOG(1) << "################  length_=" << length_ << "  ################";
-  }
-
-  const uint32_t length_;
-};
-
-INSTANTIATE_TEST_CASE_P(VariousLengths,
-                        QuicHttpContinuationQuicHttpPayloadDecoderTest,
-                        ::testing::Values(0, 1, 2, 3, 4, 5, 6));
-
-TEST_P(QuicHttpContinuationQuicHttpPayloadDecoderTest, ValidLength) {
-  QuicString hpack_payload = Random().RandString(length_);
-  QuicHttpFrameHeader frame_header(length_, QuicHttpFrameType::CONTINUATION,
-                                   RandFlags(), RandStreamId());
-  set_frame_header(frame_header);
-  QuicHttpFrameParts expected(frame_header, hpack_payload);
-  EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(hpack_payload, expected));
-}
-
-}  // namespace
-}  // namespace test
-}  // namespace quic
diff --git a/net/third_party/quic/http/decoder/payload_decoders/quic_http_data_payload_decoder.cc b/net/third_party/quic/http/decoder/payload_decoders/quic_http_data_payload_decoder.cc
deleted file mode 100644
index 419fcf9..0000000
--- a/net/third_party/quic/http/decoder/payload_decoders/quic_http_data_payload_decoder.cc
+++ /dev/null
@@ -1,135 +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 "net/third_party/quic/http/decoder/payload_decoders/quic_http_data_payload_decoder.h"
-
-#include <stddef.h>
-
-#include <cstdint>
-
-#include "base/logging.h"
-#include "base/macros.h"
-#include "net/third_party/quic/http/decoder/quic_http_decode_buffer.h"
-#include "net/third_party/quic/http/decoder/quic_http_frame_decoder_listener.h"
-#include "net/third_party/quic/http/quic_http_constants.h"
-#include "net/third_party/quic/http/quic_http_structures.h"
-#include "net/third_party/quic/platform/api/quic_bug_tracker.h"
-#include "net/third_party/quic/platform/api/quic_fallthrough.h"
-
-namespace quic {
-
-std::ostream& operator<<(std::ostream& out,
-                         QuicHttpDataQuicHttpPayloadDecoder::PayloadState v) {
-  switch (v) {
-    case QuicHttpDataQuicHttpPayloadDecoder::PayloadState::kReadPadLength:
-      return out << "kReadPadLength";
-    case QuicHttpDataQuicHttpPayloadDecoder::PayloadState::kReadPayload:
-      return out << "kReadPayload";
-    case QuicHttpDataQuicHttpPayloadDecoder::PayloadState::kSkipPadding:
-      return out << "kSkipPadding";
-  }
-  // Since the value doesn't come over the wire, only a programming bug should
-  // result in reaching this point.
-  int unknown = static_cast<int>(v);
-  QUIC_BUG << "Invalid QuicHttpDataQuicHttpPayloadDecoder::PayloadState: "
-           << unknown;
-  return out << "QuicHttpDataQuicHttpPayloadDecoder::PayloadState(" << unknown
-             << ")";
-}
-
-QuicHttpDecodeStatus QuicHttpDataQuicHttpPayloadDecoder::StartDecodingPayload(
-    QuicHttpFrameDecoderState* state,
-    QuicHttpDecodeBuffer* db) {
-  const QuicHttpFrameHeader& frame_header = state->frame_header();
-  const uint32_t total_length = frame_header.payload_length;
-
-  DVLOG(2) << "QuicHttpDataQuicHttpPayloadDecoder::StartDecodingPayload: "
-           << frame_header;
-  DCHECK_EQ(QuicHttpFrameType::DATA, frame_header.type);
-  DCHECK_LE(db->Remaining(), total_length);
-  DCHECK_EQ(0, frame_header.flags & ~(QuicHttpFrameFlag::QUIC_HTTP_END_STREAM |
-                                      QuicHttpFrameFlag::QUIC_HTTP_PADDED));
-
-  // Special case for the hoped for common case: unpadded and fits fully into
-  // the decode buffer. TO BE SEEN if that is true. It certainly requires that
-  // the transport buffers be large (e.g. >> 16KB typically).
-  // TODO(jamessynge) Add counters.
-  DVLOG(2) << "StartDecodingPayload total_length=" << total_length;
-  if (!frame_header.IsPadded()) {
-    DVLOG(2) << "StartDecodingPayload !IsPadded";
-    if (db->Remaining() == total_length) {
-      DVLOG(2) << "StartDecodingPayload all present";
-      // Note that we don't cache the listener field so that the callee can
-      // replace it if the frame is bad.
-      // If this case is common enough, consider combining the 3 callbacks
-      // into one.
-      state->listener()->OnDataStart(frame_header);
-      if (total_length > 0) {
-        state->listener()->OnDataPayload(db->cursor(), total_length);
-        db->AdvanceCursor(total_length);
-      }
-      state->listener()->OnDataEnd();
-      return QuicHttpDecodeStatus::kDecodeDone;
-    }
-    payload_state_ = PayloadState::kReadPayload;
-  } else {
-    payload_state_ = PayloadState::kReadPadLength;
-  }
-  state->InitializeRemainders();
-  state->listener()->OnDataStart(frame_header);
-  return ResumeDecodingPayload(state, db);
-}
-
-QuicHttpDecodeStatus QuicHttpDataQuicHttpPayloadDecoder::ResumeDecodingPayload(
-    QuicHttpFrameDecoderState* state,
-    QuicHttpDecodeBuffer* db) {
-  DVLOG(2) << "QuicHttpDataQuicHttpPayloadDecoder::ResumeDecodingPayload "
-              "payload_state_="
-           << payload_state_;
-  const QuicHttpFrameHeader& frame_header = state->frame_header();
-  DCHECK_EQ(QuicHttpFrameType::DATA, frame_header.type);
-  DCHECK_LE(state->remaining_payload_and_padding(),
-            frame_header.payload_length);
-  DCHECK_LE(db->Remaining(), state->remaining_payload_and_padding());
-  QuicHttpDecodeStatus status;
-  size_t avail;
-  switch (payload_state_) {
-    case PayloadState::kReadPadLength:
-      // ReadPadLength handles the OnPadLength callback, and updating the
-      // remaining_payload and remaining_padding fields. If the amount of
-      // padding is too large to fit in the frame's payload, ReadPadLength
-      // instead calls OnPaddingTooLong and returns kDecodeError.
-      status = state->ReadPadLength(db, /*report_pad_length*/ true);
-      if (status != QuicHttpDecodeStatus::kDecodeDone) {
-        return status;
-      }
-      QUIC_FALLTHROUGH_INTENDED;
-
-    case PayloadState::kReadPayload:
-      avail = state->AvailablePayload(db);
-      if (avail > 0) {
-        state->listener()->OnDataPayload(db->cursor(), avail);
-        db->AdvanceCursor(avail);
-        state->ConsumePayload(avail);
-      }
-      if (state->remaining_payload() > 0) {
-        payload_state_ = PayloadState::kReadPayload;
-        return QuicHttpDecodeStatus::kDecodeInProgress;
-      }
-      QUIC_FALLTHROUGH_INTENDED;
-
-    case PayloadState::kSkipPadding:
-      // SkipPadding handles the OnPadding callback.
-      if (state->SkipPadding(db)) {
-        state->listener()->OnDataEnd();
-        return QuicHttpDecodeStatus::kDecodeDone;
-      }
-      payload_state_ = PayloadState::kSkipPadding;
-      return QuicHttpDecodeStatus::kDecodeInProgress;
-  }
-  QUIC_BUG << "PayloadState: " << payload_state_;
-  return QuicHttpDecodeStatus::kDecodeError;
-}
-
-}  // namespace quic
diff --git a/net/third_party/quic/http/decoder/payload_decoders/quic_http_data_payload_decoder.h b/net/third_party/quic/http/decoder/payload_decoders/quic_http_data_payload_decoder.h
deleted file mode 100644
index 136b264..0000000
--- a/net/third_party/quic/http/decoder/payload_decoders/quic_http_data_payload_decoder.h
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_THIRD_PARTY_QUIC_HTTP_DECODER_PAYLOAD_DECODERS_QUIC_HTTP_DATA_PAYLOAD_DECODER_H_
-#define NET_THIRD_PARTY_QUIC_HTTP_DECODER_PAYLOAD_DECODERS_QUIC_HTTP_DATA_PAYLOAD_DECODER_H_
-
-// Decodes the payload of a DATA frame.
-// See http://g3doc/gfe/quic/http/decoder/payload_decoders/README.md for info
-// about payload decoders.
-
-#include "net/third_party/quic/http/decoder/quic_http_decode_buffer.h"
-#include "net/third_party/quic/http/decoder/quic_http_decode_status.h"
-#include "net/third_party/quic/http/decoder/quic_http_frame_decoder_state.h"
-#include "net/third_party/quic/platform/api/quic_export.h"
-
-namespace quic {
-namespace test {
-class QuicHttpDataQuicHttpPayloadDecoderPeer;
-}  // namespace test
-
-class QUIC_EXPORT_PRIVATE QuicHttpDataQuicHttpPayloadDecoder {
- public:
-  // States during decoding of a DATA frame.
-  enum class PayloadState {
-    // The frame is padded and we need to read the PAD_LENGTH field (1 byte),
-    // and then call OnPadLength
-    kReadPadLength,
-
-    // Report the non-padding portion of the payload to the listener's
-    // OnDataPayload method.
-    kReadPayload,
-
-    // The decoder has finished with the non-padding portion of the payload,
-    // and is now ready to skip the trailing padding, if the frame has any.
-    kSkipPadding,
-  };
-
-  // Starts decoding a DATA frame's payload, and completes it if
-  // the entire payload is in the provided decode buffer.
-  QuicHttpDecodeStatus StartDecodingPayload(QuicHttpFrameDecoderState* state,
-                                            QuicHttpDecodeBuffer* db);
-
-  // Resumes decoding a DATA frame's payload that has been split across
-  // decode buffers.
-  QuicHttpDecodeStatus ResumeDecodingPayload(QuicHttpFrameDecoderState* state,
-                                             QuicHttpDecodeBuffer* db);
-
- private:
-  friend class test::QuicHttpDataQuicHttpPayloadDecoderPeer;
-
-  PayloadState payload_state_;
-};
-
-}  // namespace quic
-
-#endif  // NET_THIRD_PARTY_QUIC_HTTP_DECODER_PAYLOAD_DECODERS_QUIC_HTTP_DATA_PAYLOAD_DECODER_H_
diff --git a/net/third_party/quic/http/decoder/payload_decoders/quic_http_data_payload_decoder_test.cc b/net/third_party/quic/http/decoder/payload_decoders/quic_http_data_payload_decoder_test.cc
deleted file mode 100644
index 3b27da47..0000000
--- a/net/third_party/quic/http/decoder/payload_decoders/quic_http_data_payload_decoder_test.cc
+++ /dev/null
@@ -1,126 +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 "net/third_party/quic/http/decoder/payload_decoders/quic_http_data_payload_decoder.h"
-
-#include <stddef.h>
-
-#include <cstdint>
-
-#include "base/logging.h"
-#include "net/third_party/quic/http/decoder/payload_decoders/quic_http_payload_decoder_base_test_util.h"
-#include "net/third_party/quic/http/decoder/quic_http_frame_decoder_listener.h"
-#include "net/third_party/quic/http/quic_http_constants.h"
-#include "net/third_party/quic/http/quic_http_structures.h"
-#include "net/third_party/quic/http/quic_http_structures_test_util.h"
-#include "net/third_party/quic/http/test_tools/quic_http_frame_parts.h"
-#include "net/third_party/quic/http/test_tools/quic_http_frame_parts_collector.h"
-#include "net/third_party/quic/http/tools/quic_http_frame_builder.h"
-#include "net/third_party/quic/http/tools/quic_http_random_decoder_test.h"
-#include "net/third_party/quic/platform/api/quic_string.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using ::testing::AssertionResult;
-
-namespace quic {
-namespace test {
-
-// Provides friend access to an instance of the payload decoder, and also
-// provides info to aid in testing.
-class QuicHttpDataQuicHttpPayloadDecoderPeer {
- public:
-  static constexpr QuicHttpFrameType FrameType() {
-    return QuicHttpFrameType::DATA;
-  }
-
-  // Returns the mask of flags that affect the decoding of the payload (i.e.
-  // flags that that indicate the presence of certain fields or padding).
-  static constexpr uint8_t FlagsAffectingPayloadDecoding() {
-    return QuicHttpFrameFlag::QUIC_HTTP_PADDED;
-  }
-
-  static void Randomize(QuicHttpDataQuicHttpPayloadDecoder* p,
-                        QuicTestRandomBase* rng) {
-    VLOG(1) << "QuicHttpDataQuicHttpPayloadDecoderPeer::Randomize";
-    CorruptEnum(&p->payload_state_, rng);
-  }
-};
-
-namespace {
-
-struct Listener : public QuicHttpFramePartsCollector {
-  void OnDataStart(const QuicHttpFrameHeader& header) override {
-    VLOG(1) << "OnDataStart: " << header;
-    StartFrame(header)->OnDataStart(header);
-  }
-
-  void OnDataPayload(const char* data, size_t len) override {
-    VLOG(1) << "OnDataPayload: len=" << len;
-    CurrentFrame()->OnDataPayload(data, len);
-  }
-
-  void OnDataEnd() override {
-    VLOG(1) << "OnDataEnd";
-    EndFrame()->OnDataEnd();
-  }
-
-  void OnPadLength(size_t pad_length) override {
-    VLOG(1) << "OnPadLength: " << pad_length;
-    CurrentFrame()->OnPadLength(pad_length);
-  }
-
-  void OnPadding(const char* padding, size_t skipped_length) override {
-    VLOG(1) << "OnPadding: " << skipped_length;
-    CurrentFrame()->OnPadding(padding, skipped_length);
-  }
-
-  void OnPaddingTooLong(const QuicHttpFrameHeader& header,
-                        size_t missing_length) override {
-    VLOG(1) << "OnPaddingTooLong: " << header
-            << "    missing_length: " << missing_length;
-    EndFrame()->OnPaddingTooLong(header, missing_length);
-  }
-};
-
-class QuicHttpDataQuicHttpPayloadDecoderTest
-    : public AbstractPaddableQuicHttpPayloadDecoderTest<
-          QuicHttpDataQuicHttpPayloadDecoder,
-          QuicHttpDataQuicHttpPayloadDecoderPeer,
-          Listener> {
- protected:
-  AssertionResult CreateAndDecodeDataOfSize(size_t data_size) {
-    Reset();
-    // Boost logging when the data and *trailing* padding are both 3 bytes long,
-    // as this size of a string has both a beginning, middle and end when
-    // segmented into 1 byte long buffers, so should exercise all the paths.
-    // But we don't want to do extra logging all the time as it is expensive.
-    uint8_t flags = RandFlags();
-
-    QuicString data_payload = Random().RandString(data_size);
-    frame_builder_.Append(data_payload);
-    MaybeAppendTrailingPadding();
-
-    QuicHttpFrameHeader frame_header(
-        frame_builder_.size(), QuicHttpFrameType::DATA, flags, RandStreamId());
-    set_frame_header(frame_header);
-    ScrubFlagsOfHeader(&frame_header);
-    QuicHttpFrameParts expected(frame_header, data_payload, total_pad_length_);
-    VERIFY_AND_RETURN_SUCCESS(
-        DecodePayloadAndValidateSeveralWays(frame_builder_.buffer(), expected));
-  }
-};
-
-INSTANTIATE_TEST_CASE_P(VariousPadLengths,
-                        QuicHttpDataQuicHttpPayloadDecoderTest,
-                        ::testing::Values(0, 1, 2, 3, 4, 254, 255, 256));
-
-TEST_P(QuicHttpDataQuicHttpPayloadDecoderTest, VariousDataPayloadSizes) {
-  for (size_t data_size : {0, 1, 2, 3, 255, 256, 1024}) {
-    EXPECT_TRUE(CreateAndDecodeDataOfSize(data_size));
-  }
-}
-
-}  // namespace
-}  // namespace test
-}  // namespace quic
diff --git a/net/third_party/quic/http/decoder/payload_decoders/quic_http_goaway_payload_decoder.cc b/net/third_party/quic/http/decoder/payload_decoders/quic_http_goaway_payload_decoder.cc
deleted file mode 100644
index 052e13db..0000000
--- a/net/third_party/quic/http/decoder/payload_decoders/quic_http_goaway_payload_decoder.cc
+++ /dev/null
@@ -1,126 +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 "net/third_party/quic/http/decoder/payload_decoders/quic_http_goaway_payload_decoder.h"
-
-#include <stddef.h>
-
-#include "base/logging.h"
-#include "base/macros.h"
-#include "net/third_party/quic/http/decoder/quic_http_decode_buffer.h"
-#include "net/third_party/quic/http/decoder/quic_http_frame_decoder_listener.h"
-#include "net/third_party/quic/http/quic_http_constants.h"
-#include "net/third_party/quic/http/quic_http_structures.h"
-#include "net/third_party/quic/platform/api/quic_bug_tracker.h"
-#include "net/third_party/quic/platform/api/quic_fallthrough.h"
-
-namespace quic {
-
-std::ostream& operator<<(std::ostream& out,
-                         QuicHttpGoAwayQuicHttpPayloadDecoder::PayloadState v) {
-  switch (v) {
-    case QuicHttpGoAwayQuicHttpPayloadDecoder::PayloadState::
-        kStartDecodingFixedFields:
-      return out << "kStartDecodingFixedFields";
-    case QuicHttpGoAwayQuicHttpPayloadDecoder::PayloadState::
-        kHandleFixedFieldsStatus:
-      return out << "kHandleFixedFieldsStatus";
-    case QuicHttpGoAwayQuicHttpPayloadDecoder::PayloadState::kReadOpaqueData:
-      return out << "kReadOpaqueData";
-    case QuicHttpGoAwayQuicHttpPayloadDecoder::PayloadState::
-        kResumeDecodingFixedFields:
-      return out << "kResumeDecodingFixedFields";
-  }
-  // Since the value doesn't come over the wire, only a programming bug should
-  // result in reaching this point.
-  int unknown = static_cast<int>(v);
-  QUIC_BUG << "Invalid QuicHttpGoAwayQuicHttpPayloadDecoder::PayloadState: "
-           << unknown;
-  return out << "QuicHttpGoAwayQuicHttpPayloadDecoder::PayloadState(" << unknown
-             << ")";
-}
-
-QuicHttpDecodeStatus QuicHttpGoAwayQuicHttpPayloadDecoder::StartDecodingPayload(
-    QuicHttpFrameDecoderState* state,
-    QuicHttpDecodeBuffer* db) {
-  DVLOG(2) << "QuicHttpGoAwayQuicHttpPayloadDecoder::StartDecodingPayload: "
-           << state->frame_header();
-  DCHECK_EQ(QuicHttpFrameType::GOAWAY, state->frame_header().type);
-  DCHECK_LE(db->Remaining(), state->frame_header().payload_length);
-  DCHECK_EQ(0, state->frame_header().flags);
-
-  state->InitializeRemainders();
-  payload_state_ = PayloadState::kStartDecodingFixedFields;
-  return ResumeDecodingPayload(state, db);
-}
-
-QuicHttpDecodeStatus
-QuicHttpGoAwayQuicHttpPayloadDecoder::ResumeDecodingPayload(
-    QuicHttpFrameDecoderState* state,
-    QuicHttpDecodeBuffer* db) {
-  DVLOG(2) << "QuicHttpGoAwayQuicHttpPayloadDecoder::ResumeDecodingPayload: "
-              "remaining_payload="
-           << state->remaining_payload()
-           << ", db->Remaining=" << db->Remaining();
-
-  const QuicHttpFrameHeader& frame_header = state->frame_header();
-  DCHECK_EQ(QuicHttpFrameType::GOAWAY, frame_header.type);
-  DCHECK_LE(db->Remaining(), frame_header.payload_length);
-  DCHECK_NE(PayloadState::kHandleFixedFieldsStatus, payload_state_);
-
-  QuicHttpDecodeStatus status = QuicHttpDecodeStatus::kDecodeError;
-  size_t avail;
-  while (true) {
-    DVLOG(2) << "QuicHttpGoAwayQuicHttpPayloadDecoder::ResumeDecodingPayload "
-                "payload_state_="
-             << payload_state_;
-    switch (payload_state_) {
-      case PayloadState::kStartDecodingFixedFields:
-        status = state->StartDecodingStructureInPayload(&goaway_fields_, db);
-        QUIC_FALLTHROUGH_INTENDED;
-
-      case PayloadState::kHandleFixedFieldsStatus:
-        if (status == QuicHttpDecodeStatus::kDecodeDone) {
-          state->listener()->OnGoAwayStart(frame_header, goaway_fields_);
-        } else {
-          // Not done decoding the structure. Either we've got more payload
-          // to decode, or we've run out because the payload is too short,
-          // in which case OnFrameSizeError will have already been called.
-          DCHECK((status == QuicHttpDecodeStatus::kDecodeInProgress &&
-                  state->remaining_payload() > 0) ||
-                 (status == QuicHttpDecodeStatus::kDecodeError &&
-                  state->remaining_payload() == 0))
-              << "\n status=" << status
-              << "; remaining_payload=" << state->remaining_payload();
-          payload_state_ = PayloadState::kResumeDecodingFixedFields;
-          return status;
-        }
-        QUIC_FALLTHROUGH_INTENDED;
-
-      case PayloadState::kReadOpaqueData:
-        // The opaque data is all the remains to be decoded, so anything left
-        // in the decode buffer is opaque data.
-        avail = db->Remaining();
-        if (avail > 0) {
-          state->listener()->OnGoAwayOpaqueData(db->cursor(), avail);
-          db->AdvanceCursor(avail);
-          state->ConsumePayload(avail);
-        }
-        if (state->remaining_payload() > 0) {
-          payload_state_ = PayloadState::kReadOpaqueData;
-          return QuicHttpDecodeStatus::kDecodeInProgress;
-        }
-        state->listener()->OnGoAwayEnd();
-        return QuicHttpDecodeStatus::kDecodeDone;
-
-      case PayloadState::kResumeDecodingFixedFields:
-        status = state->ResumeDecodingStructureInPayload(&goaway_fields_, db);
-        payload_state_ = PayloadState::kHandleFixedFieldsStatus;
-        continue;
-    }
-    QUIC_BUG << "PayloadState: " << payload_state_;
-  }
-}
-
-}  // namespace quic
diff --git a/net/third_party/quic/http/decoder/payload_decoders/quic_http_goaway_payload_decoder.h b/net/third_party/quic/http/decoder/payload_decoders/quic_http_goaway_payload_decoder.h
deleted file mode 100644
index 50e8b273..0000000
--- a/net/third_party/quic/http/decoder/payload_decoders/quic_http_goaway_payload_decoder.h
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_THIRD_PARTY_QUIC_HTTP_DECODER_PAYLOAD_DECODERS_QUIC_HTTP_GOAWAY_PAYLOAD_DECODER_H_
-#define NET_THIRD_PARTY_QUIC_HTTP_DECODER_PAYLOAD_DECODERS_QUIC_HTTP_GOAWAY_PAYLOAD_DECODER_H_
-
-// Decodes the payload of a GOAWAY frame.
-// See http://g3doc/gfe/quic/http/decoder/payload_decoders/README.md for info
-// about payload decoders.
-
-// TODO(jamessynge): Sweep through all payload decoders, changing the names of
-// the PayloadState enums so that they are really states, and not actions.
-
-#include "net/third_party/quic/http/decoder/quic_http_decode_buffer.h"
-#include "net/third_party/quic/http/decoder/quic_http_decode_status.h"
-#include "net/third_party/quic/http/decoder/quic_http_frame_decoder_state.h"
-#include "net/third_party/quic/http/quic_http_structures.h"
-#include "net/third_party/quic/platform/api/quic_export.h"
-
-namespace quic {
-namespace test {
-class QuicHttpGoAwayQuicHttpPayloadDecoderPeer;
-}  // namespace test
-
-class QUIC_EXPORT_PRIVATE QuicHttpGoAwayQuicHttpPayloadDecoder {
- public:
-  // States during decoding of a GOAWAY frame.
-  enum class PayloadState {
-    // At the start of the GOAWAY frame payload, ready to start decoding the
-    // fixed size fields into goaway_fields_.
-    kStartDecodingFixedFields,
-
-    // Handle the QuicHttpDecodeStatus returned from starting or resuming the
-    // decoding of QuicHttpGoAwayFields into goaway_fields_. If complete,
-    // calls OnGoAwayStart.
-    kHandleFixedFieldsStatus,
-
-    // Report the Opaque Data portion of the payload to the listener's
-    // OnGoAwayOpaqueData method, and call OnGoAwayEnd when the end of the
-    // payload is reached.
-    kReadOpaqueData,
-
-    // The fixed size fields weren't all available when the decoder first
-    // tried to decode them (state kStartDecodingFixedFields); this state
-    // resumes the decoding when ResumeDecodingPayload is called later.
-    kResumeDecodingFixedFields,
-  };
-
-  // Starts the decoding of a GOAWAY frame's payload, and completes it if
-  // the entire payload is in the provided decode buffer.
-  QuicHttpDecodeStatus StartDecodingPayload(QuicHttpFrameDecoderState* state,
-                                            QuicHttpDecodeBuffer* db);
-
-  // Resumes decoding a GOAWAY frame's payload that has been split across
-  // decode buffers.
-  QuicHttpDecodeStatus ResumeDecodingPayload(QuicHttpFrameDecoderState* state,
-                                             QuicHttpDecodeBuffer* db);
-
- private:
-  friend class test::QuicHttpGoAwayQuicHttpPayloadDecoderPeer;
-
-  QuicHttpGoAwayFields goaway_fields_;
-  PayloadState payload_state_;
-};
-
-}  // namespace quic
-
-#endif  // NET_THIRD_PARTY_QUIC_HTTP_DECODER_PAYLOAD_DECODERS_QUIC_HTTP_GOAWAY_PAYLOAD_DECODER_H_
diff --git a/net/third_party/quic/http/decoder/payload_decoders/quic_http_goaway_payload_decoder_test.cc b/net/third_party/quic/http/decoder/payload_decoders/quic_http_goaway_payload_decoder_test.cc
deleted file mode 100644
index 43d072b..0000000
--- a/net/third_party/quic/http/decoder/payload_decoders/quic_http_goaway_payload_decoder_test.cc
+++ /dev/null
@@ -1,120 +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 "net/third_party/quic/http/decoder/payload_decoders/quic_http_goaway_payload_decoder.h"
-
-#include <stddef.h>
-
-#include <cstdint>
-
-#include "base/logging.h"
-#include "net/third_party/quic/http/decoder/payload_decoders/quic_http_payload_decoder_base_test_util.h"
-#include "net/third_party/quic/http/decoder/quic_http_frame_decoder_listener.h"
-#include "net/third_party/quic/http/quic_http_constants.h"
-#include "net/third_party/quic/http/quic_http_structures_test_util.h"
-#include "net/third_party/quic/http/test_tools/quic_http_frame_parts.h"
-#include "net/third_party/quic/http/test_tools/quic_http_frame_parts_collector.h"
-#include "net/third_party/quic/http/tools/quic_http_frame_builder.h"
-#include "net/third_party/quic/http/tools/quic_http_random_decoder_test.h"
-#include "net/third_party/quic/platform/api/quic_string.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace quic {
-namespace test {
-
-class QuicHttpGoAwayQuicHttpPayloadDecoderPeer {
- public:
-  static constexpr QuicHttpFrameType FrameType() {
-    return QuicHttpFrameType::GOAWAY;
-  }
-
-  // Returns the mask of flags that affect the decoding of the payload (i.e.
-  // flags that that indicate the presence of certain fields or padding).
-  static constexpr uint8_t FlagsAffectingPayloadDecoding() { return 0; }
-
-  static void Randomize(QuicHttpGoAwayQuicHttpPayloadDecoder* p,
-                        QuicTestRandomBase* rng) {
-    CorruptEnum(&p->payload_state_, rng);
-    test::Randomize(&p->goaway_fields_, rng);
-    VLOG(1)
-        << "QuicHttpGoAwayQuicHttpPayloadDecoderPeer::Randomize goaway_fields: "
-        << p->goaway_fields_;
-  }
-};
-
-namespace {
-
-struct Listener : public QuicHttpFramePartsCollector {
-  void OnGoAwayStart(const QuicHttpFrameHeader& header,
-                     const QuicHttpGoAwayFields& goaway) override {
-    VLOG(1) << "OnGoAwayStart header: " << header << "; goaway: " << goaway;
-    StartFrame(header)->OnGoAwayStart(header, goaway);
-  }
-
-  void OnGoAwayOpaqueData(const char* data, size_t len) override {
-    VLOG(1) << "OnGoAwayOpaqueData: len=" << len;
-    CurrentFrame()->OnGoAwayOpaqueData(data, len);
-  }
-
-  void OnGoAwayEnd() override {
-    VLOG(1) << "OnGoAwayEnd";
-    EndFrame()->OnGoAwayEnd();
-  }
-
-  void OnFrameSizeError(const QuicHttpFrameHeader& header) override {
-    VLOG(1) << "OnFrameSizeError: " << header;
-    FrameError(header)->OnFrameSizeError(header);
-  }
-};
-
-class QuicHttpGoAwayQuicHttpPayloadDecoderTest
-    : public AbstractQuicHttpPayloadDecoderTest<
-          QuicHttpGoAwayQuicHttpPayloadDecoder,
-          QuicHttpGoAwayQuicHttpPayloadDecoderPeer,
-          Listener> {};
-
-// Confirm we get an error if the payload is not long enough to hold
-// QuicHttpGoAwayFields.
-TEST_F(QuicHttpGoAwayQuicHttpPayloadDecoderTest, Truncated) {
-  auto approve_size = [](size_t size) {
-    return size != QuicHttpGoAwayFields::EncodedSize();
-  };
-  QuicHttpFrameBuilder fb;
-  fb.Append(QuicHttpGoAwayFields(123, QuicHttpErrorCode::ENHANCE_YOUR_CALM));
-  EXPECT_TRUE(VerifyDetectsFrameSizeError(0, fb.buffer(), approve_size));
-}
-
-class QuicHttpGoAwayOpaqueDataLengthTests
-    : public QuicHttpGoAwayQuicHttpPayloadDecoderTest,
-      public ::testing::WithParamInterface<uint32_t> {
- protected:
-  QuicHttpGoAwayOpaqueDataLengthTests() : length_(GetParam()) {
-    VLOG(1) << "################  length_=" << length_ << "  ################";
-  }
-
-  const uint32_t length_;
-};
-
-INSTANTIATE_TEST_CASE_P(VariousLengths,
-                        QuicHttpGoAwayOpaqueDataLengthTests,
-                        ::testing::Values(0, 1, 2, 3, 4, 5, 6));
-
-TEST_P(QuicHttpGoAwayOpaqueDataLengthTests, ValidLength) {
-  QuicHttpGoAwayFields goaway;
-  Randomize(&goaway, RandomPtr());
-  QuicString opaque_bytes = Random().RandString(length_);
-  QuicHttpFrameBuilder fb;
-  fb.Append(goaway);
-  fb.Append(opaque_bytes);
-  QuicHttpFrameHeader header(fb.size(), QuicHttpFrameType::GOAWAY, RandFlags(),
-                             RandStreamId());
-  set_frame_header(header);
-  QuicHttpFrameParts expected(header, opaque_bytes);
-  expected.opt_goaway = goaway;
-  ASSERT_TRUE(DecodePayloadAndValidateSeveralWays(fb.buffer(), expected));
-}
-
-}  // namespace
-}  // namespace test
-}  // namespace quic
diff --git a/net/third_party/quic/http/decoder/payload_decoders/quic_http_headers_payload_decoder.cc b/net/third_party/quic/http/decoder/payload_decoders/quic_http_headers_payload_decoder.cc
deleted file mode 100644
index d88b649f..0000000
--- a/net/third_party/quic/http/decoder/payload_decoders/quic_http_headers_payload_decoder.cc
+++ /dev/null
@@ -1,188 +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 "net/third_party/quic/http/decoder/payload_decoders/quic_http_headers_payload_decoder.h"
-
-#include <stddef.h>
-
-#include <cstdint>
-
-#include "base/logging.h"
-#include "base/macros.h"
-#include "net/third_party/quic/http/decoder/quic_http_decode_buffer.h"
-#include "net/third_party/quic/http/decoder/quic_http_frame_decoder_listener.h"
-#include "net/third_party/quic/http/quic_http_constants.h"
-#include "net/third_party/quic/http/quic_http_structures.h"
-#include "net/third_party/quic/platform/api/quic_bug_tracker.h"
-#include "net/third_party/quic/platform/api/quic_fallthrough.h"
-
-namespace quic {
-
-std::ostream& operator<<(
-    std::ostream& out,
-    QuicHttpHeadersQuicHttpPayloadDecoder::PayloadState v) {
-  switch (v) {
-    case QuicHttpHeadersQuicHttpPayloadDecoder::PayloadState::kReadPadLength:
-      return out << "kReadPadLength";
-    case QuicHttpHeadersQuicHttpPayloadDecoder::PayloadState::
-        kStartDecodingPriorityFields:
-      return out << "kStartDecodingPriorityFields";
-    case QuicHttpHeadersQuicHttpPayloadDecoder::PayloadState::
-        kResumeDecodingPriorityFields:
-      return out << "kResumeDecodingPriorityFields";
-    case QuicHttpHeadersQuicHttpPayloadDecoder::PayloadState::kReadPayload:
-      return out << "kReadPayload";
-    case QuicHttpHeadersQuicHttpPayloadDecoder::PayloadState::kSkipPadding:
-      return out << "kSkipPadding";
-  }
-  // Since the value doesn't come over the wire, only a programming bug should
-  // result in reaching this point.
-  int unknown = static_cast<int>(v);
-  QUIC_BUG << "Invalid QuicHttpHeadersQuicHttpPayloadDecoder::PayloadState: "
-           << unknown;
-  return out << "QuicHttpHeadersQuicHttpPayloadDecoder::PayloadState("
-             << unknown << ")";
-}
-
-QuicHttpDecodeStatus
-QuicHttpHeadersQuicHttpPayloadDecoder::StartDecodingPayload(
-    QuicHttpFrameDecoderState* state,
-    QuicHttpDecodeBuffer* db) {
-  const QuicHttpFrameHeader& frame_header = state->frame_header();
-  const uint32_t total_length = frame_header.payload_length;
-
-  DVLOG(2) << "QuicHttpHeadersQuicHttpPayloadDecoder::StartDecodingPayload: "
-           << frame_header;
-
-  DCHECK_EQ(QuicHttpFrameType::HEADERS, frame_header.type);
-  DCHECK_LE(db->Remaining(), total_length);
-  DCHECK_EQ(0, frame_header.flags & ~(QuicHttpFrameFlag::QUIC_HTTP_END_STREAM |
-                                      QuicHttpFrameFlag::QUIC_HTTP_END_HEADERS |
-                                      QuicHttpFrameFlag::QUIC_HTTP_PADDED |
-                                      QuicHttpFrameFlag::QUIC_HTTP_PRIORITY));
-
-  // Special case for HEADERS frames that contain only the HPQUIC_HTTP_ACK block
-  // (fragment or whole) and that fit fully into the decode buffer.
-  // Why? Unencoded browser GET requests are typically under 1K and
-  // HPQUIC_HTTP_ACK commonly shrinks request headers by 80%, so we can expect
-  // this to be common.
-  // TODO(jamessynge) Add counters here and to Spdy for determining how
-  // common this situation is. A possible approach is to create a
-  // QuicHttpFrameDecoderListener that counts the callbacks and then forwards
-  // them on to another listener, which makes it easy to add and remove
-  // counting on a connection or even frame basis.
-
-  // QUIC_HTTP_PADDED and QUIC_HTTP_PRIORITY both extra steps to decode, but if
-  // neither flag is set then we can decode faster.
-  const auto payload_flags = QuicHttpFrameFlag::QUIC_HTTP_PADDED |
-                             QuicHttpFrameFlag::QUIC_HTTP_PRIORITY;
-  if (!frame_header.HasAnyFlags(payload_flags)) {
-    DVLOG(2) << "StartDecodingPayload !IsPadded && !HasPriority";
-    if (db->Remaining() == total_length) {
-      DVLOG(2) << "StartDecodingPayload all present";
-      // Note that we don't cache the listener field so that the callee can
-      // replace it if the frame is bad.
-      // If this case is common enough, consider combining the 3 callbacks
-      // into one, especially if QUIC_HTTP_END_HEADERS is also set.
-      state->listener()->OnHeadersStart(frame_header);
-      if (total_length > 0) {
-        state->listener()->OnHpackFragment(db->cursor(), total_length);
-        db->AdvanceCursor(total_length);
-      }
-      state->listener()->OnHeadersEnd();
-      return QuicHttpDecodeStatus::kDecodeDone;
-    }
-    payload_state_ = PayloadState::kReadPayload;
-  } else if (frame_header.IsPadded()) {
-    payload_state_ = PayloadState::kReadPadLength;
-  } else {
-    DCHECK(frame_header.HasPriority()) << frame_header;
-    payload_state_ = PayloadState::kStartDecodingPriorityFields;
-  }
-  state->InitializeRemainders();
-  state->listener()->OnHeadersStart(frame_header);
-  return ResumeDecodingPayload(state, db);
-}
-
-QuicHttpDecodeStatus
-QuicHttpHeadersQuicHttpPayloadDecoder::ResumeDecodingPayload(
-    QuicHttpFrameDecoderState* state,
-    QuicHttpDecodeBuffer* db) {
-  DVLOG(2) << "QuicHttpHeadersQuicHttpPayloadDecoder::ResumeDecodingPayload "
-           << "remaining_payload=" << state->remaining_payload()
-           << "; db->Remaining=" << db->Remaining();
-
-  const QuicHttpFrameHeader& frame_header = state->frame_header();
-
-  DCHECK_EQ(QuicHttpFrameType::HEADERS, frame_header.type);
-  DCHECK_LE(state->remaining_payload_and_padding(),
-            frame_header.payload_length);
-  DCHECK_LE(db->Remaining(), state->remaining_payload_and_padding());
-  QuicHttpDecodeStatus status;
-  size_t avail;
-  while (true) {
-    DVLOG(2) << "QuicHttpHeadersQuicHttpPayloadDecoder::ResumeDecodingPayload "
-                "payload_state_="
-             << payload_state_;
-    switch (payload_state_) {
-      case PayloadState::kReadPadLength:
-        // ReadPadLength handles the OnPadLength callback, and updating the
-        // remaining_payload and remaining_padding fields. If the amount of
-        // padding is too large to fit in the frame's payload, ReadPadLength
-        // instead calls OnPaddingTooLong and returns kDecodeError.
-        status = state->ReadPadLength(db, /*report_pad_length*/ true);
-        if (status != QuicHttpDecodeStatus::kDecodeDone) {
-          return status;
-        }
-        if (!frame_header.HasPriority()) {
-          payload_state_ = PayloadState::kReadPayload;
-          continue;
-        }
-        QUIC_FALLTHROUGH_INTENDED;
-
-      case PayloadState::kStartDecodingPriorityFields:
-        status = state->StartDecodingStructureInPayload(&priority_fields_, db);
-        if (status != QuicHttpDecodeStatus::kDecodeDone) {
-          payload_state_ = PayloadState::kResumeDecodingPriorityFields;
-          return status;
-        }
-        state->listener()->OnHeadersPriority(priority_fields_);
-        QUIC_FALLTHROUGH_INTENDED;
-
-      case PayloadState::kReadPayload:
-        avail = state->AvailablePayload(db);
-        if (avail > 0) {
-          state->listener()->OnHpackFragment(db->cursor(), avail);
-          db->AdvanceCursor(avail);
-          state->ConsumePayload(avail);
-        }
-        if (state->remaining_payload() > 0) {
-          payload_state_ = PayloadState::kReadPayload;
-          return QuicHttpDecodeStatus::kDecodeInProgress;
-        }
-        QUIC_FALLTHROUGH_INTENDED;
-
-      case PayloadState::kSkipPadding:
-        // SkipPadding handles the OnPadding callback.
-        if (state->SkipPadding(db)) {
-          state->listener()->OnHeadersEnd();
-          return QuicHttpDecodeStatus::kDecodeDone;
-        }
-        payload_state_ = PayloadState::kSkipPadding;
-        return QuicHttpDecodeStatus::kDecodeInProgress;
-
-      case PayloadState::kResumeDecodingPriorityFields:
-        status = state->ResumeDecodingStructureInPayload(&priority_fields_, db);
-        if (status != QuicHttpDecodeStatus::kDecodeDone) {
-          return status;
-        }
-        state->listener()->OnHeadersPriority(priority_fields_);
-        payload_state_ = PayloadState::kReadPayload;
-        continue;
-    }
-    QUIC_BUG << "PayloadState: " << payload_state_;
-  }
-}
-
-}  // namespace quic
diff --git a/net/third_party/quic/http/decoder/payload_decoders/quic_http_headers_payload_decoder.h b/net/third_party/quic/http/decoder/payload_decoders/quic_http_headers_payload_decoder.h
deleted file mode 100644
index 38cdb587..0000000
--- a/net/third_party/quic/http/decoder/payload_decoders/quic_http_headers_payload_decoder.h
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_THIRD_PARTY_QUIC_HTTP_DECODER_PAYLOAD_DECODERS_QUIC_HTTP_HEADERS_PAYLOAD_DECODER_H_
-#define NET_THIRD_PARTY_QUIC_HTTP_DECODER_PAYLOAD_DECODERS_QUIC_HTTP_HEADERS_PAYLOAD_DECODER_H_
-
-// Decodes the payload of a HEADERS frame.
-// See http://g3doc/gfe/quic/http/decoder/payload_decoders/README.md for info
-// about payload decoders.
-
-#include "net/third_party/quic/http/decoder/quic_http_decode_buffer.h"
-#include "net/third_party/quic/http/decoder/quic_http_decode_status.h"
-#include "net/third_party/quic/http/decoder/quic_http_frame_decoder_state.h"
-#include "net/third_party/quic/http/quic_http_structures.h"
-#include "net/third_party/quic/platform/api/quic_export.h"
-
-namespace quic {
-namespace test {
-class QuicHttpHeadersQuicHttpPayloadDecoderPeer;
-}  // namespace test
-
-class QUIC_EXPORT_PRIVATE QuicHttpHeadersQuicHttpPayloadDecoder {
- public:
-  // States during decoding of a HEADERS frame, unless the fast path kicks
-  // in, in which case the state machine will be bypassed.
-  enum class PayloadState {
-    // The QUIC_HTTP_PADDED flag is set, and we now need to read the Pad Length
-    // field
-    // (the first byte of the payload, after the common frame header).
-    kReadPadLength,
-
-    // The QUIC_HTTP_PRIORITY flag is set, and we now need to read the fixed
-    // size priority
-    // fields (E, Stream Dependency, Weight) into priority_fields_.  Calls on
-    // OnHeadersPriority if completely decodes those fields.
-    kStartDecodingPriorityFields,
-
-    // The decoder passes the non-padding portion of the remaining payload
-    // (i.e. the HPQUIC_HTTP_ACK block fragment) to the listener's
-    // OnHpackFragment method.
-    kReadPayload,
-
-    // The decoder has finished with the HPQUIC_HTTP_ACK block fragment, and is
-    // now
-    // ready to skip the trailing padding, if the frame has any.
-    kSkipPadding,
-
-    // The fixed size fields weren't all available when the decoder first tried
-    // to decode them (state kStartDecodingPriorityFields); this state resumes
-    // the decoding when ResumeDecodingPayload is called later.
-    kResumeDecodingPriorityFields,
-  };
-
-  // Starts the decoding of a HEADERS frame's payload, and completes it if
-  // the entire payload is in the provided decode buffer.
-  QuicHttpDecodeStatus StartDecodingPayload(QuicHttpFrameDecoderState* state,
-                                            QuicHttpDecodeBuffer* db);
-
-  // Resumes decoding a HEADERS frame's payload that has been split across
-  // decode buffers.
-  QuicHttpDecodeStatus ResumeDecodingPayload(QuicHttpFrameDecoderState* state,
-                                             QuicHttpDecodeBuffer* db);
-
- private:
-  friend class test::QuicHttpHeadersQuicHttpPayloadDecoderPeer;
-
-  PayloadState payload_state_;
-  QuicHttpPriorityFields priority_fields_;
-};
-
-}  // namespace quic
-
-#endif  // NET_THIRD_PARTY_QUIC_HTTP_DECODER_PAYLOAD_DECODERS_QUIC_HTTP_HEADERS_PAYLOAD_DECODER_H_
diff --git a/net/third_party/quic/http/decoder/payload_decoders/quic_http_headers_payload_decoder_test.cc b/net/third_party/quic/http/decoder/payload_decoders/quic_http_headers_payload_decoder_test.cc
deleted file mode 100644
index 8cf0f0b..0000000
--- a/net/third_party/quic/http/decoder/payload_decoders/quic_http_headers_payload_decoder_test.cc
+++ /dev/null
@@ -1,172 +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 "net/third_party/quic/http/decoder/payload_decoders/quic_http_headers_payload_decoder.h"
-
-#include <stddef.h>
-
-#include <cstdint>
-
-#include "base/logging.h"
-#include "net/third_party/quic/http/decoder/payload_decoders/quic_http_payload_decoder_base_test_util.h"
-#include "net/third_party/quic/http/decoder/quic_http_frame_decoder_listener.h"
-#include "net/third_party/quic/http/quic_http_constants.h"
-#include "net/third_party/quic/http/quic_http_structures_test_util.h"
-#include "net/third_party/quic/http/test_tools/quic_http_frame_parts.h"
-#include "net/third_party/quic/http/test_tools/quic_http_frame_parts_collector.h"
-#include "net/third_party/quic/http/tools/quic_http_frame_builder.h"
-#include "net/third_party/quic/http/tools/quic_http_random_decoder_test.h"
-#include "net/third_party/quic/platform/api/quic_string.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace quic {
-namespace test {
-
-class QuicHttpHeadersQuicHttpPayloadDecoderPeer {
- public:
-  static constexpr QuicHttpFrameType FrameType() {
-    return QuicHttpFrameType::HEADERS;
-  }
-
-  // Returns the mask of flags that affect the decoding of the payload (i.e.
-  // flags that that indicate the presence of certain fields or padding).
-  static constexpr uint8_t FlagsAffectingPayloadDecoding() {
-    return QuicHttpFrameFlag::QUIC_HTTP_PADDED |
-           QuicHttpFrameFlag::QUIC_HTTP_PRIORITY;
-  }
-
-  static void Randomize(QuicHttpHeadersQuicHttpPayloadDecoder* p,
-                        QuicTestRandomBase* rng) {
-    CorruptEnum(&p->payload_state_, rng);
-    test::Randomize(&p->priority_fields_, rng);
-    VLOG(1) << "QuicHttpHeadersQuicHttpPayloadDecoderPeer::Randomize "
-               "priority_fields_: "
-            << p->priority_fields_;
-  }
-};
-
-namespace {
-
-// Listener handles all On* methods that are expected to be called. If any other
-// On* methods of QuicHttpFrameDecoderListener is called then the test fails;
-// this is achieved by way of FailingQuicHttpFrameDecoderListener, the base
-// class of QuicHttpFramePartsCollector. These On* methods make use of
-// StartFrame, EndFrame, etc. of the base class to create and access to
-// QuicHttpFrameParts instance(s) that will record the details. After decoding,
-// the test validation code can access the FramePart instance(s) via the public
-// methods of QuicHttpFramePartsCollector.
-struct Listener : public QuicHttpFramePartsCollector {
-  void OnHeadersStart(const QuicHttpFrameHeader& header) override {
-    VLOG(1) << "OnHeadersStart: " << header;
-    StartFrame(header)->OnHeadersStart(header);
-  }
-
-  void OnHeadersPriority(const QuicHttpPriorityFields& priority) override {
-    VLOG(1) << "OnHeadersPriority: " << priority;
-    CurrentFrame()->OnHeadersPriority(priority);
-  }
-
-  void OnHpackFragment(const char* data, size_t len) override {
-    VLOG(1) << "OnHpackFragment: len=" << len;
-    CurrentFrame()->OnHpackFragment(data, len);
-  }
-
-  void OnHeadersEnd() override {
-    VLOG(1) << "OnHeadersEnd";
-    EndFrame()->OnHeadersEnd();
-  }
-
-  void OnPadLength(size_t pad_length) override {
-    VLOG(1) << "OnPadLength: " << pad_length;
-    CurrentFrame()->OnPadLength(pad_length);
-  }
-
-  void OnPadding(const char* padding, size_t skipped_length) override {
-    VLOG(1) << "OnPadding: " << skipped_length;
-    CurrentFrame()->OnPadding(padding, skipped_length);
-  }
-
-  void OnPaddingTooLong(const QuicHttpFrameHeader& header,
-                        size_t missing_length) override {
-    VLOG(1) << "OnPaddingTooLong: " << header
-            << "; missing_length: " << missing_length;
-    FrameError(header)->OnPaddingTooLong(header, missing_length);
-  }
-
-  void OnFrameSizeError(const QuicHttpFrameHeader& header) override {
-    VLOG(1) << "OnFrameSizeError: " << header;
-    FrameError(header)->OnFrameSizeError(header);
-  }
-};
-
-class QuicHttpHeadersQuicHttpPayloadDecoderTest
-    : public AbstractPaddableQuicHttpPayloadDecoderTest<
-          QuicHttpHeadersQuicHttpPayloadDecoder,
-          QuicHttpHeadersQuicHttpPayloadDecoderPeer,
-          Listener> {};
-
-INSTANTIATE_TEST_CASE_P(VariousPadLengths,
-                        QuicHttpHeadersQuicHttpPayloadDecoderTest,
-                        ::testing::Values(0, 1, 2, 3, 4, 254, 255, 256));
-
-// Decode various sizes of (fake) HPQUIC_HTTP_ACK payload, both with and without
-// the QUIC_HTTP_PRIORITY flag set.
-TEST_P(QuicHttpHeadersQuicHttpPayloadDecoderTest, VariousHpackPayloadSizes) {
-  for (size_t hpack_size : {0, 1, 2, 3, 255, 256, 1024}) {
-    LOG(INFO) << "###########   hpack_size = " << hpack_size << "  ###########";
-    QuicHttpPriorityFields priority(RandStreamId(), 1 + Random().Rand8(),
-                                    Random().OneIn(2));
-
-    for (bool has_priority : {false, true}) {
-      Reset();
-      ASSERT_EQ(IsPadded() ? 1u : 0u, frame_builder_.size());
-      uint8_t flags = RandFlags();
-      if (has_priority) {
-        flags |= QuicHttpFrameFlag::QUIC_HTTP_PRIORITY;
-        frame_builder_.Append(priority);
-      }
-
-      QuicString hpack_payload = Random().RandString(hpack_size);
-      frame_builder_.Append(hpack_payload);
-
-      MaybeAppendTrailingPadding();
-      QuicHttpFrameHeader frame_header(frame_builder_.size(),
-                                       QuicHttpFrameType::HEADERS, flags,
-                                       RandStreamId());
-      set_frame_header(frame_header);
-      ScrubFlagsOfHeader(&frame_header);
-      QuicHttpFrameParts expected(frame_header, hpack_payload,
-                                  total_pad_length_);
-      if (has_priority) {
-        expected.opt_priority = priority;
-      }
-      EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(frame_builder_.buffer(),
-                                                      expected));
-    }
-  }
-}
-
-// Confirm we get an error if the QUIC_HTTP_PRIORITY flag is set but the payload
-// is not long enough, regardless of the amount of (valid) padding.
-TEST_P(QuicHttpHeadersQuicHttpPayloadDecoderTest, Truncated) {
-  auto approve_size = [](size_t size) {
-    return size != QuicHttpPriorityFields::EncodedSize();
-  };
-  QuicHttpFrameBuilder fb;
-  fb.Append(QuicHttpPriorityFields(RandStreamId(), 1 + Random().Rand8(),
-                                   Random().OneIn(2)));
-  EXPECT_TRUE(VerifyDetectsMultipleFrameSizeErrors(
-      QuicHttpFrameFlag::QUIC_HTTP_PRIORITY, fb.buffer(), approve_size,
-      total_pad_length_));
-}
-
-// Confirm we get an error if the QUIC_HTTP_PADDED flag is set but the payload
-// is not long enough to hold even the Pad Length amount of padding.
-TEST_P(QuicHttpHeadersQuicHttpPayloadDecoderTest, PaddingTooLong) {
-  EXPECT_TRUE(VerifyDetectsPaddingTooLong());
-}
-
-}  // namespace
-}  // namespace test
-}  // namespace quic
diff --git a/net/third_party/quic/http/decoder/payload_decoders/quic_http_payload_decoder_base_test_util.cc b/net/third_party/quic/http/decoder/payload_decoders/quic_http_payload_decoder_base_test_util.cc
deleted file mode 100644
index efaa1c2..0000000
--- a/net/third_party/quic/http/decoder/payload_decoders/quic_http_payload_decoder_base_test_util.cc
+++ /dev/null
@@ -1,105 +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 "net/third_party/quic/http/decoder/payload_decoders/quic_http_payload_decoder_base_test_util.h"
-
-#include "base/logging.h"
-#include "net/third_party/quic/http/decoder/quic_http_decode_buffer.h"
-#include "net/third_party/quic/http/decoder/quic_http_decode_status.h"
-#include "net/third_party/quic/http/decoder/quic_http_frame_decoder_state_test_util.h"
-#include "net/third_party/quic/http/quic_http_structures.h"
-#include "net/third_party/quic/http/quic_http_structures_test_util.h"
-#include "net/third_party/quic/http/tools/quic_http_random_decoder_test.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace quic {
-namespace test {
-QuicHttpPayloadDecoderBaseTest::QuicHttpPayloadDecoderBaseTest() {
-  // If the test adds more data after the frame payload,
-  // stop as soon as the payload is decoded.
-  stop_decode_on_done_ = true;
-  frame_header_is_set_ = false;
-  Randomize(&frame_header_, RandomPtr());
-}
-
-QuicHttpDecodeStatus QuicHttpPayloadDecoderBaseTest::StartDecoding(
-    QuicHttpDecodeBuffer* db) {
-  DVLOG(2) << "StartDecoding, db->Remaining=" << db->Remaining();
-  // Make sure sub-class has set frame_header_ so that we can inject it
-  // into the payload decoder below.
-  if (!frame_header_is_set_) {
-    ADD_FAILURE() << "frame_header_ is not set";
-    return QuicHttpDecodeStatus::kDecodeError;
-  }
-  // The contract with the payload decoders is that they won't receive a
-  // decode buffer that extends beyond the end of the frame.
-  if (db->Remaining() > frame_header_.payload_length) {
-    ADD_FAILURE() << "QuicHttpDecodeBuffer has too much data: "
-                  << db->Remaining() << " > " << frame_header_.payload_length;
-    return QuicHttpDecodeStatus::kDecodeError;
-  }
-
-  // Prepare the payload decoder.
-  PrepareQuicHttpPayloadDecoder();
-
-  // Reconstruct the QuicHttpFrameDecoderState, prepare the listener, and add it
-  // to the QuicHttpFrameDecoderState.
-  QuicReconstructObject(&frame_decoder_state_, RandomPtr());
-  frame_decoder_state_.set_listener(PrepareListener());
-
-  // Make sure that a listener was provided.
-  if (frame_decoder_state_.listener() == nullptr) {
-    ADD_FAILURE() << "PrepareListener must return a listener.";
-    return QuicHttpDecodeStatus::kDecodeError;
-  }
-
-  // Now that nothing in the payload decoder should be valid, inject the
-  // QuicHttpFrameHeader whose payload we're about to decode. That header is the
-  // only state that a payload decoder should expect is valid when its Start
-  // method is called.
-  QuicHttpFrameDecoderStatePeer::set_frame_header(frame_header_,
-                                                  &frame_decoder_state_);
-  QuicHttpDecodeStatus status = StartDecodingPayload(db);
-  if (status != QuicHttpDecodeStatus::kDecodeInProgress) {
-    // Keep track of this so that a concrete test can verify that both fast
-    // and slow decoding paths have been tested.
-    ++fast_decode_count_;
-  }
-  return status;
-}
-
-QuicHttpDecodeStatus QuicHttpPayloadDecoderBaseTest::ResumeDecoding(
-    QuicHttpDecodeBuffer* db) {
-  DVLOG(2) << "ResumeDecoding, db->Remaining=" << db->Remaining();
-  QuicHttpDecodeStatus status = ResumeDecodingPayload(db);
-  if (status != QuicHttpDecodeStatus::kDecodeInProgress) {
-    // Keep track of this so that a concrete test can verify that both fast
-    // and slow decoding paths have been tested.
-    ++slow_decode_count_;
-  }
-  return status;
-}
-
-::testing::AssertionResult
-QuicHttpPayloadDecoderBaseTest::DecodePayloadAndValidateSeveralWays(
-    QuicStringPiece payload,
-    const Validator& validator) {
-  VERIFY_TRUE(frame_header_is_set_);
-  // Cap the payload to be decoded at the declared payload length. This is
-  // required by the decoders' preconditions; they are designed on the
-  // assumption that they're never passed more than they're permitted to
-  // consume.
-  // Note that it is OK if the payload is too short; the validator may be
-  // designed to check for that.
-  if (payload.size() > frame_header_.payload_length) {
-    payload = QuicStringPiece(payload.data(), frame_header_.payload_length);
-  }
-  QuicHttpDecodeBuffer db(payload);
-  ResetDecodeSpeedCounters();
-  const bool kMayReturnZeroOnFirst = false;
-  return DecodeAndValidateSeveralWays(&db, kMayReturnZeroOnFirst, validator);
-}
-
-}  // namespace test
-}  // namespace quic
diff --git a/net/third_party/quic/http/decoder/payload_decoders/quic_http_payload_decoder_base_test_util.h b/net/third_party/quic/http/decoder/payload_decoders/quic_http_payload_decoder_base_test_util.h
deleted file mode 100644
index 1a3f7ea..0000000
--- a/net/third_party/quic/http/decoder/payload_decoders/quic_http_payload_decoder_base_test_util.h
+++ /dev/null
@@ -1,473 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_THIRD_PARTY_QUIC_HTTP_DECODER_PAYLOAD_DECODERS_QUIC_HTTP_PAYLOAD_DECODER_BASE_TEST_UTIL_H_
-#define NET_THIRD_PARTY_QUIC_HTTP_DECODER_PAYLOAD_DECODERS_QUIC_HTTP_PAYLOAD_DECODER_BASE_TEST_UTIL_H_
-
-// Base class for testing concrete payload decoder classes.
-
-#include <stddef.h>
-
-#include "base/logging.h"
-#include "net/third_party/quic/http/decoder/quic_http_decode_buffer.h"
-#include "net/third_party/quic/http/decoder/quic_http_decode_status.h"
-#include "net/third_party/quic/http/decoder/quic_http_frame_decoder_listener.h"
-#include "net/third_party/quic/http/decoder/quic_http_frame_decoder_state.h"
-#include "net/third_party/quic/http/quic_http_constants.h"
-#include "net/third_party/quic/http/quic_http_constants_test_util.h"
-#include "net/third_party/quic/http/quic_http_structures.h"
-#include "net/third_party/quic/http/test_tools/quic_http_frame_parts.h"
-#include "net/third_party/quic/http/tools/quic_http_frame_builder.h"
-#include "net/third_party/quic/http/tools/quic_http_random_decoder_test.h"
-#include "net/third_party/quic/platform/api/quic_reconstruct_object.h"
-#include "net/third_party/quic/platform/api/quic_string.h"
-#include "net/third_party/quic/platform/api/quic_string_piece.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace quic {
-namespace test {
-
-// Base class for tests of payload decoders. Below this there is a templated
-// sub-class that adds a bunch of type specific features.
-class QuicHttpPayloadDecoderBaseTest : public QuicHttpRandomDecoderTest {
- protected:
-  QuicHttpPayloadDecoderBaseTest();
-
-  // Virtual functions to be implemented by the test classes for the individual
-  // payload decoders...
-
-  // Start decoding the payload.
-  virtual QuicHttpDecodeStatus StartDecodingPayload(
-      QuicHttpDecodeBuffer* db) = 0;
-
-  // Resume decoding the payload.
-  virtual QuicHttpDecodeStatus ResumeDecodingPayload(
-      QuicHttpDecodeBuffer* db) = 0;
-
-  // In support of ensuring that we're really accessing and updating the
-  // decoder, prepare the decoder by, for example, overwriting the decoder.
-  virtual void PrepareQuicHttpPayloadDecoder() = 0;
-
-  // Get the listener to be inserted into the QuicHttpFrameDecoderState, ready
-  // for listening (e.g. reset if it is a QuicHttpFramePartsCollector).
-  virtual QuicHttpFrameDecoderListener* PrepareListener() = 0;
-
-  // Record a frame header for use on each call to StartDecoding.
-  void set_frame_header(const QuicHttpFrameHeader& header) {
-    EXPECT_EQ(0, InvalidFlagMaskForFrameType(header.type) & header.flags);
-    if (!frame_header_is_set_ || frame_header_ != header) {
-      VLOG(2) << "set_frame_header: " << frame_header_;
-    }
-    frame_header_ = header;
-    frame_header_is_set_ = true;
-  }
-
-  const QuicHttpFrameHeader& frame_header() const {
-    CHECK(frame_header_is_set_);
-    return frame_header_;
-  }
-
-  QuicHttpFrameDecoderState* mutable_state() { return &frame_decoder_state_; }
-
-  // Randomize the payload decoder, sets the payload decoder's frame_header_,
-  // then start decoding the payload. Called by QuicHttpRandomDecoderTest. This
-  // method is final so that we can always perform certain actions when
-  // QuicHttpRandomDecoderTest starts the decoding of a payload, such as
-  // randomizing the the payload decoder, injecting the frame header and
-  // counting fast decoding cases. Sub-classes must implement
-  // StartDecodingPayload to perform their initial decoding of a frame's
-  // payload.
-  QuicHttpDecodeStatus StartDecoding(QuicHttpDecodeBuffer* db) final;
-
-  // Called by QuicHttpRandomDecoderTest. This method is final so that we can
-  // always perform certain actions when QuicHttpRandomDecoderTest calls it,
-  // such as counting slow decode cases. Sub-classes must implement
-  // ResumeDecodingPayload to continue decoding the frame's payload, which must
-  // not all be in one buffer.
-  QuicHttpDecodeStatus ResumeDecoding(QuicHttpDecodeBuffer* db) final;
-
-  // Given the specified payload (without the common frame header), decode
-  // it with several partitionings of the payload.
-  ::testing::AssertionResult DecodePayloadAndValidateSeveralWays(
-      QuicStringPiece payload,
-      const Validator& validator);
-
-  // TODO(jamessynge): Add helper method for verifying these are both non-zero,
-  // and call the new method from tests that expect successful decoding.
-  void ResetDecodeSpeedCounters() {
-    fast_decode_count_ = 0;
-    slow_decode_count_ = 0;
-  }
-
-  // Count of payloads that are full decoded by StartDecodingPayload, or that
-  // an error was detected by StartDecodingPayload.
-  size_t fast_decode_count_ = 0;
-
-  // Count of payloads that require calling ResumeDecodingPayload in order to
-  // decode them completely (or to detect an error during decoding).
-  size_t slow_decode_count_ = 0;
-
- private:
-  bool frame_header_is_set_ = false;
-  QuicHttpFrameHeader frame_header_;
-  QuicHttpFrameDecoderState frame_decoder_state_;
-};
-
-// Base class for payload decoders of type Decoder, with corresponding test
-// peer of type DecoderPeer, and using class Listener as the implementation
-// of QuicHttpFrameDecoderListenerInterface to be used during decoding.
-// Typically Listener is a sub-class of QuicHttpFramePartsCollector.
-// SupportedFrameType is set to false only for
-// QuicHttpUnknownQuicHttpPayloadDecoder.
-template <class Decoder,
-          class DecoderPeer,
-          class Listener,
-          bool SupportedFrameType = true>
-class AbstractQuicHttpPayloadDecoderTest
-    : public QuicHttpPayloadDecoderBaseTest {
- protected:
-  // An ApproveSize function returns true to approve decoding the specified
-  // size of payload, else false to skip that size. Typically used for negative
-  // tests; for example, decoding a SETTINGS frame at all sizes except for
-  // multiples of 6.
-  typedef std::function<bool(size_t size)> ApproveSize;
-
-  AbstractQuicHttpPayloadDecoderTest() {}
-
-  // These tests are in setup rather than the constructor for two reasons:
-  // 1) Constructors are not allowed to fail, so gUnit documents that EXPECT_*
-  //    and ASSERT_* are not allowed in constructors, and should instead be in
-  //    SetUp if they are needed before the body of the test is executed.
-  // 2) To allow the sub-class constructor to make any desired modifications to
-  //    the DecoderPeer before these tests are executed; in particular,
-  //    QuicHttpUnknownQuicHttpPayloadDecoderPeer has not got a fixed frame
-  //    type, but it is instead set during the test's constructor.
-  void SetUp() override {
-    QuicHttpPayloadDecoderBaseTest::SetUp();
-
-    // Confirm that DecoderPeer et al returns sensible values. Using auto as the
-    // variable type so that no (narrowing) conversions take place that hide
-    // problems; i.e. if someone changes KnownFlagsMaskForFrameType so that it
-    // doesn't return a uint8, and has bits above the low-order 8 bits set, this
-    // bit of paranoia should detect the problem before we get too far.
-    auto frame_type = DecoderPeer::FrameType();
-    if (SupportedFrameType) {
-      EXPECT_TRUE(IsSupportedQuicHttpFrameType(frame_type)) << frame_type;
-    } else {
-      EXPECT_FALSE(IsSupportedQuicHttpFrameType(frame_type)) << frame_type;
-    }
-
-    auto known_flags = KnownFlagsMaskForFrameType(frame_type);
-    EXPECT_EQ(known_flags, known_flags & 0xff);
-
-    auto flags_to_avoid = DecoderPeer::FlagsAffectingPayloadDecoding();
-    EXPECT_EQ(flags_to_avoid, flags_to_avoid & known_flags);
-  }
-
-  void PrepareQuicHttpPayloadDecoder() override {
-    QuicDefaultReconstructObject(&payload_decoder_, RandomPtr());
-  }
-
-  QuicHttpFrameDecoderListener* PrepareListener() override {
-    listener_.Reset();
-    return &listener_;
-  }
-
-  // Returns random flags, but only those valid for the frame type, yet not
-  // those that the DecoderPeer says will affect the decoding of the payload
-  // (e.g. the PRIORTY flag on a HEADERS frame or QUIC_HTTP_PADDED on DATA
-  // frames).
-  uint8_t RandFlags() {
-    return Random().Rand8() &
-           KnownFlagsMaskForFrameType(DecoderPeer::FrameType()) &
-           ~DecoderPeer::FlagsAffectingPayloadDecoding();
-  }
-
-  // Start decoding the payload.
-  QuicHttpDecodeStatus StartDecodingPayload(QuicHttpDecodeBuffer* db) override {
-    DVLOG(2) << "StartDecodingPayload, db->Remaining=" << db->Remaining();
-    return payload_decoder_.StartDecodingPayload(mutable_state(), db);
-  }
-
-  // Resume decoding the payload.
-  QuicHttpDecodeStatus ResumeDecodingPayload(
-      QuicHttpDecodeBuffer* db) override {
-    DVLOG(2) << "ResumeDecodingPayload, db->Remaining=" << db->Remaining();
-    return payload_decoder_.ResumeDecodingPayload(mutable_state(), db);
-  }
-
-  // Decode one frame's payload and confirm that the listener recorded the
-  // expected QuicHttpFrameParts instance, and only QuicHttpFrameParts instance.
-  // The payload will be decoded several times with different partitionings of
-  // the payload, and after each the validator will be called.
-  AssertionResult DecodePayloadAndValidateSeveralWays(
-      QuicStringPiece payload,
-      const QuicHttpFrameParts& expected) {
-    auto validator = [&expected, this]() -> AssertionResult {
-      VERIFY_FALSE(listener_.IsInProgress());
-      VERIFY_EQ(1u, listener_.size());
-      VERIFY_AND_RETURN_SUCCESS(expected.VerifyEquals(*listener_.frame(0)));
-    };
-    return QuicHttpPayloadDecoderBaseTest::DecodePayloadAndValidateSeveralWays(
-        payload, ValidateDoneAndEmpty(validator));
-  }
-
-  // Decode one frame's payload, expecting that the final status will be
-  // kDecodeError, and that OnFrameSizeError will have been called on the
-  // listener. The payload will be decoded several times with different
-  // partitionings of the payload. The type WrappedValidator is either
-  // QuicHttpRandomDecoderTest::Validator,
-  // QuicHttpRandomDecoderTest::NoArgValidator or std::nullptr_t (not extra
-  // validation).
-  template <typename WrappedValidator>
-  ::testing::AssertionResult VerifyDetectsFrameSizeError(
-      QuicStringPiece payload,
-      const QuicHttpFrameHeader& header,
-      WrappedValidator wrapped_validator) {
-    set_frame_header(header);
-    // If wrapped_validator is not a QuicHttpRandomDecoderTest::Validator, make
-    // it so.
-    Validator validator = ToValidator(wrapped_validator);
-    // And wrap that validator in another which will check that we've reached
-    // the expected state of kDecodeError with OnFrameSizeError having been
-    // called by the payload decoder.
-    validator = [header, validator, this](
-                    const QuicHttpDecodeBuffer& input,
-                    QuicHttpDecodeStatus status) -> ::testing::AssertionResult {
-      DVLOG(2) << "VerifyDetectsFrameSizeError validator; status=" << status
-               << "; input.Remaining=" << input.Remaining();
-      VERIFY_EQ(QuicHttpDecodeStatus::kDecodeError, status);
-      VERIFY_FALSE(listener_.IsInProgress());
-      VERIFY_EQ(1u, listener_.size());
-      const QuicHttpFrameParts* frame = listener_.frame(0);
-      VERIFY_EQ(header, frame->frame_header);
-      VERIFY_TRUE(frame->has_frame_size_error);
-      // Verify did not get OnPaddingTooLong, as we should only ever produce
-      // one of these two errors for a single frame.
-      VERIFY_FALSE(frame->opt_missing_length);
-      return validator(input, status);
-    };
-    VERIFY_AND_RETURN_SUCCESS(
-        QuicHttpPayloadDecoderBaseTest::DecodePayloadAndValidateSeveralWays(
-            payload, validator));
-  }
-
-  // Confirm that we get OnFrameSizeError when trying to decode unpadded_payload
-  // at all sizes from zero to unpadded_payload.size(), except those sizes not
-  // approved by approve_size.
-  // If total_pad_length is greater than zero, then that amount of padding
-  // is added to the payload (including the Pad Length field).
-  // The flags will be required_flags, QUIC_HTTP_PADDED if total_pad_length > 0,
-  // and some randomly selected flag bits not excluded by
-  // FlagsAffectingPayloadDecoding.
-  ::testing::AssertionResult VerifyDetectsMultipleFrameSizeErrors(
-      uint8_t required_flags,
-      QuicStringPiece unpadded_payload,
-      const ApproveSize& approve_size,
-      int total_pad_length) {
-    // required_flags should come from those that are defined for the frame
-    // type AND are those that affect the decoding of the payload (otherwise,
-    // the flag shouldn't be required).
-    QuicHttpFrameType frame_type = DecoderPeer::FrameType();
-    VERIFY_EQ(required_flags,
-              required_flags & KnownFlagsMaskForFrameType(frame_type));
-    VERIFY_EQ(required_flags,
-              required_flags & DecoderPeer::FlagsAffectingPayloadDecoding());
-
-    if (0 != (QuicHttpFrameFlag::QUIC_HTTP_PADDED &
-              KnownFlagsMaskForFrameType(frame_type))) {
-      // Frame type supports padding.
-      if (total_pad_length == 0) {
-        required_flags &= ~QuicHttpFrameFlag::QUIC_HTTP_PADDED;
-      } else {
-        required_flags |= QuicHttpFrameFlag::QUIC_HTTP_PADDED;
-      }
-    } else {
-      VERIFY_EQ(0, total_pad_length);
-    }
-
-    bool validated = false;
-    for (size_t real_payload_size = 0;
-         real_payload_size <= unpadded_payload.size(); ++real_payload_size) {
-      if (approve_size != nullptr && !approve_size(real_payload_size)) {
-        continue;
-      }
-      VLOG(1) << "real_payload_size=" << real_payload_size;
-      uint8_t flags = required_flags | RandFlags();
-      QuicHttpFrameBuilder fb;
-      if (total_pad_length > 0) {
-        // total_pad_length_ includes the size of the Pad Length field, and thus
-        // ranges from 0 (no QUIC_HTTP_PADDED flag) to 256 (Pad Length == 255).
-        fb.AppendUInt8(total_pad_length - 1);
-      }
-      // Append a subset of the unpadded_payload, which the decoder should
-      // determine is not a valid amount.
-      fb.Append(unpadded_payload.substr(0, real_payload_size));
-      if (total_pad_length > 0) {
-        fb.AppendZeroes(total_pad_length - 1);
-      }
-      // We choose a random stream id because the payload decoders aren't
-      // checking stream ids.
-      uint32_t stream_id = RandStreamId();
-      QuicHttpFrameHeader header(fb.size(), frame_type, flags, stream_id);
-      VERIFY_SUCCESS(VerifyDetectsFrameSizeError(fb.buffer(), header, nullptr));
-      validated = true;
-    }
-    VERIFY_TRUE(validated);
-    return ::testing::AssertionSuccess();
-  }
-
-  // As above, but for frames without padding.
-  ::testing::AssertionResult VerifyDetectsFrameSizeError(
-      uint8_t required_flags,
-      QuicStringPiece unpadded_payload,
-      const ApproveSize& approve_size) {
-    QuicHttpFrameType frame_type = DecoderPeer::FrameType();
-    uint8_t known_flags = KnownFlagsMaskForFrameType(frame_type);
-    VERIFY_EQ(0, known_flags & QuicHttpFrameFlag::QUIC_HTTP_PADDED);
-    VERIFY_EQ(0, required_flags & QuicHttpFrameFlag::QUIC_HTTP_PADDED);
-    VERIFY_AND_RETURN_SUCCESS(VerifyDetectsMultipleFrameSizeErrors(
-        required_flags, unpadded_payload, approve_size, 0));
-  }
-
-  Listener listener_;
-  union {
-    // Confirm at compile time that Decoder can be in an anonymous union,
-    // i.e. complain loudly if Decoder has members that prevent this, as it
-    // becomes annoying and possibly difficult to deal with non-anonymous
-    // unions and such union members.
-    Decoder payload_decoder_;
-  };
-};
-
-// A base class for tests parameterized by the total number of bytes of
-// padding, including the Pad Length field (i.e. a total_pad_length of 0
-// means unpadded as there is then no room for the Pad Length field).
-// The frame type must support padding.
-template <class Decoder, class DecoderPeer, class Listener>
-class AbstractPaddableQuicHttpPayloadDecoderTest
-    : public AbstractQuicHttpPayloadDecoderTest<Decoder, DecoderPeer, Listener>,
-      public ::testing::WithParamInterface<int> {
-  typedef AbstractQuicHttpPayloadDecoderTest<Decoder, DecoderPeer, Listener>
-      Base;
-
- protected:
-  using Base::RandStreamId;
-  using Base::Random;
-  using Base::listener_;
-  using Base::set_frame_header;
-  typedef typename Base::Validator Validator;
-
-  AbstractPaddableQuicHttpPayloadDecoderTest() : total_pad_length_(GetParam()) {
-    LOG(INFO) << "total_pad_length_ = " << total_pad_length_;
-  }
-
-  // Note that total_pad_length_ includes the size of the Pad Length field,
-  // and thus ranges from 0 (no QUIC_HTTP_PADDED flag) to 256 (Pad Length ==
-  // 255).
-  bool IsPadded() const { return total_pad_length_ > 0; }
-
-  // Value of the Pad Length field. Only call if IsPadded.
-  size_t pad_length() const {
-    EXPECT_TRUE(IsPadded());
-    return total_pad_length_ - 1;
-  }
-
-  // Clear the frame builder and add the Pad Length field if appropriate.
-  void Reset() {
-    frame_builder_ = QuicHttpFrameBuilder();
-    if (IsPadded()) {
-      frame_builder_.AppendUInt8(pad_length());
-    }
-  }
-
-  void MaybeAppendTrailingPadding() {
-    if (IsPadded()) {
-      frame_builder_.AppendZeroes(pad_length());
-    }
-  }
-
-  uint8_t RandFlags() {
-    uint8_t flags = Base::RandFlags();
-    if (IsPadded()) {
-      flags |= QuicHttpFrameFlag::QUIC_HTTP_PADDED;
-    } else {
-      flags &= ~QuicHttpFrameFlag::QUIC_HTTP_PADDED;
-    }
-    return flags;
-  }
-
-  // Verify that we get OnPaddingTooLong when decoding payload, and that the
-  // amount of missing padding is as specified. header.IsPadded must be true,
-  // and the payload must be empty or the PadLength field must be too large.
-  ::testing::AssertionResult VerifyDetectsPaddingTooLong(
-      QuicStringPiece payload,
-      const QuicHttpFrameHeader& header,
-      size_t expected_missing_length) {
-    set_frame_header(header);
-    auto& listener = listener_;
-    Validator validator =
-        [header, expected_missing_length, &listener](
-            const QuicHttpDecodeBuffer& input,
-            QuicHttpDecodeStatus status) -> ::testing::AssertionResult {
-      VERIFY_EQ(QuicHttpDecodeStatus::kDecodeError, status);
-      VERIFY_FALSE(listener.IsInProgress());
-      VERIFY_EQ(1u, listener.size());
-      const QuicHttpFrameParts* frame = listener.frame(0);
-      VERIFY_EQ(header, frame->frame_header);
-      VERIFY_TRUE(frame->opt_missing_length);
-      VERIFY_EQ(expected_missing_length, frame->opt_missing_length.value());
-      // Verify did not get OnFrameSizeError.
-      VERIFY_FALSE(frame->has_frame_size_error);
-      return ::testing::AssertionSuccess();
-    };
-    VERIFY_AND_RETURN_SUCCESS(
-        QuicHttpPayloadDecoderBaseTest::DecodePayloadAndValidateSeveralWays(
-            payload, validator));
-  }
-
-  // Verifies that we get OnPaddingTooLong for a padded frame payload whose
-  // (randomly selected) payload length is less than total_pad_length_.
-  // Flags will be selected at random, except QUIC_HTTP_PADDED will be set and
-  // flags_to_avoid will not be set. The stream id is selected at random.
-  ::testing::AssertionResult VerifyDetectsPaddingTooLong() {
-    uint8_t flags = RandFlags() | QuicHttpFrameFlag::QUIC_HTTP_PADDED;
-
-    // Create an all padding payload for total_pad_length_.
-    int payload_length = 0;
-    QuicHttpFrameBuilder fb;
-    if (IsPadded()) {
-      fb.AppendUInt8(pad_length());
-      fb.AppendZeroes(pad_length());
-      VLOG(1) << "fb.size=" << fb.size();
-      // Pick a random length for the payload that is shorter than neccesary.
-      payload_length = Random().Uniform(fb.size());
-    }
-
-    VLOG(1) << "payload_length=" << payload_length;
-    QuicString payload = fb.buffer().substr(0, payload_length);
-
-    // The missing length is the amount we cut off the end, unless
-    // payload_length is zero, in which case the decoder knows only that 1
-    // byte, the Pad Length field, is missing.
-    size_t missing_length =
-        payload_length == 0 ? 1 : fb.size() - payload_length;
-    VLOG(1) << "missing_length=" << missing_length;
-
-    const QuicHttpFrameHeader header(payload_length, DecoderPeer::FrameType(),
-                                     flags, RandStreamId());
-    VERIFY_AND_RETURN_SUCCESS(
-        VerifyDetectsPaddingTooLong(payload, header, missing_length));
-  }
-
-  // total_pad_length_ includes the size of the Pad Length field, and thus
-  // ranges from 0 (no QUIC_HTTP_PADDED flag) to 256 (Pad Length == 255).
-  const size_t total_pad_length_;
-  QuicHttpFrameBuilder frame_builder_;
-};
-
-}  // namespace test
-}  // namespace quic
-
-#endif  // NET_THIRD_PARTY_QUIC_HTTP_DECODER_PAYLOAD_DECODERS_QUIC_HTTP_PAYLOAD_DECODER_BASE_TEST_UTIL_H_
diff --git a/net/third_party/quic/http/decoder/payload_decoders/quic_http_ping_payload_decoder.cc b/net/third_party/quic/http/decoder/payload_decoders/quic_http_ping_payload_decoder.cc
deleted file mode 100644
index 30f39a2..0000000
--- a/net/third_party/quic/http/decoder/payload_decoders/quic_http_ping_payload_decoder.cc
+++ /dev/null
@@ -1,95 +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 "net/third_party/quic/http/decoder/payload_decoders/quic_http_ping_payload_decoder.h"
-
-#include <cstdint>
-
-#include "base/logging.h"
-#include "net/third_party/quic/http/decoder/quic_http_frame_decoder_listener.h"
-#include "net/third_party/quic/http/quic_http_constants.h"
-
-namespace quic {
-namespace {
-constexpr auto kOpaqueSize = QuicHttpPingFields::EncodedSize();
-}
-
-QuicHttpDecodeStatus QuicHttpPingQuicHttpPayloadDecoder::StartDecodingPayload(
-    QuicHttpFrameDecoderState* state,
-    QuicHttpDecodeBuffer* db) {
-  const QuicHttpFrameHeader& frame_header = state->frame_header();
-  const uint32_t total_length = frame_header.payload_length;
-
-  DVLOG(2) << "QuicHttpPingQuicHttpPayloadDecoder::StartDecodingPayload: "
-           << frame_header;
-  DCHECK_EQ(QuicHttpFrameType::PING, frame_header.type);
-  DCHECK_LE(db->Remaining(), total_length);
-  DCHECK_EQ(0, frame_header.flags & ~(QuicHttpFrameFlag::QUIC_HTTP_ACK));
-
-  // Is the payload entirely in the decode buffer and is it the correct size?
-  // Given the size of the header and payload (17 bytes total), this is most
-  // likely the case the vast majority of the time.
-  if (db->Remaining() == kOpaqueSize && total_length == kOpaqueSize) {
-    // Special case this situation as it allows us to avoid any copying;
-    // the other path makes two copies, first into the buffer in
-    // QuicHttpStructureDecoder as it accumulates the 8 bytes of opaque data,
-    // and a second copy into the QuicHttpPingFields member of in this class.
-    // This supports the claim that this decoder is (mostly) non-buffering.
-    static_assert(sizeof(QuicHttpPingFields) == kOpaqueSize,
-                  "If not, then can't enter this block!");
-    auto* ping = reinterpret_cast<const QuicHttpPingFields*>(db->cursor());
-    if (frame_header.IsAck()) {
-      state->listener()->OnPingAck(frame_header, *ping);
-    } else {
-      state->listener()->OnPing(frame_header, *ping);
-    }
-    db->AdvanceCursor(kOpaqueSize);
-    return QuicHttpDecodeStatus::kDecodeDone;
-  }
-  state->InitializeRemainders();
-  return HandleStatus(
-      state, state->StartDecodingStructureInPayload(&ping_fields_, db));
-}
-
-QuicHttpDecodeStatus QuicHttpPingQuicHttpPayloadDecoder::ResumeDecodingPayload(
-    QuicHttpFrameDecoderState* state,
-    QuicHttpDecodeBuffer* db) {
-  DVLOG(2) << "ResumeDecodingPayload: remaining_payload="
-           << state->remaining_payload();
-  DCHECK_EQ(QuicHttpFrameType::PING, state->frame_header().type);
-  DCHECK_LE(db->Remaining(), state->frame_header().payload_length);
-  return HandleStatus(
-      state, state->ResumeDecodingStructureInPayload(&ping_fields_, db));
-}
-
-QuicHttpDecodeStatus QuicHttpPingQuicHttpPayloadDecoder::HandleStatus(
-    QuicHttpFrameDecoderState* state,
-    QuicHttpDecodeStatus status) {
-  DVLOG(2) << "HandleStatus: status=" << status
-           << "; remaining_payload=" << state->remaining_payload();
-  if (status == QuicHttpDecodeStatus::kDecodeDone) {
-    if (state->remaining_payload() == 0) {
-      const QuicHttpFrameHeader& frame_header = state->frame_header();
-      if (frame_header.IsAck()) {
-        state->listener()->OnPingAck(frame_header, ping_fields_);
-      } else {
-        state->listener()->OnPing(frame_header, ping_fields_);
-      }
-      return QuicHttpDecodeStatus::kDecodeDone;
-    }
-    // Payload is too long.
-    return state->ReportFrameSizeError();
-  }
-  // Not done decoding the structure. Either we've got more payload to decode,
-  // or we've run out because the payload is too short.
-  DCHECK((status == QuicHttpDecodeStatus::kDecodeInProgress &&
-          state->remaining_payload() > 0) ||
-         (status == QuicHttpDecodeStatus::kDecodeError &&
-          state->remaining_payload() == 0))
-      << "\n status=" << status
-      << "; remaining_payload=" << state->remaining_payload();
-  return status;
-}
-
-}  // namespace quic
diff --git a/net/third_party/quic/http/decoder/payload_decoders/quic_http_ping_payload_decoder.h b/net/third_party/quic/http/decoder/payload_decoders/quic_http_ping_payload_decoder.h
deleted file mode 100644
index 6b287a1..0000000
--- a/net/third_party/quic/http/decoder/payload_decoders/quic_http_ping_payload_decoder.h
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_THIRD_PARTY_QUIC_HTTP_DECODER_PAYLOAD_DECODERS_QUIC_HTTP_PING_PAYLOAD_DECODER_H_
-#define NET_THIRD_PARTY_QUIC_HTTP_DECODER_PAYLOAD_DECODERS_QUIC_HTTP_PING_PAYLOAD_DECODER_H_
-
-// Decodes the payload of a PING frame; for the RFC, see:
-//     http://httpwg.org/specs/rfc7540.html#PING
-//
-// For info about payload decoders, see:
-//     http://g3doc/gfe/quic/http/decoder/payload_decoders/README.md
-
-#include "net/third_party/quic/http/decoder/quic_http_decode_buffer.h"
-#include "net/third_party/quic/http/decoder/quic_http_decode_status.h"
-#include "net/third_party/quic/http/decoder/quic_http_frame_decoder_state.h"
-#include "net/third_party/quic/http/quic_http_structures.h"
-#include "net/third_party/quic/platform/api/quic_export.h"
-
-namespace quic {
-namespace test {
-class QuicHttpPingQuicHttpPayloadDecoderPeer;
-}  // namespace test
-
-class QUIC_EXPORT_PRIVATE QuicHttpPingQuicHttpPayloadDecoder {
- public:
-  // Starts the decoding of a PING frame's payload, and completes it if the
-  // entire payload is in the provided decode buffer.
-  QuicHttpDecodeStatus StartDecodingPayload(QuicHttpFrameDecoderState* state,
-                                            QuicHttpDecodeBuffer* db);
-
-  // Resumes decoding a PING frame's payload that has been split across
-  // decode buffers.
-  QuicHttpDecodeStatus ResumeDecodingPayload(QuicHttpFrameDecoderState* state,
-                                             QuicHttpDecodeBuffer* db);
-
- private:
-  friend class test::QuicHttpPingQuicHttpPayloadDecoderPeer;
-
-  QuicHttpDecodeStatus HandleStatus(QuicHttpFrameDecoderState* state,
-                                    QuicHttpDecodeStatus status);
-
-  QuicHttpPingFields ping_fields_;
-};
-
-}  // namespace quic
-
-#endif  // NET_THIRD_PARTY_QUIC_HTTP_DECODER_PAYLOAD_DECODERS_QUIC_HTTP_PING_PAYLOAD_DECODER_H_
diff --git a/net/third_party/quic/http/decoder/payload_decoders/quic_http_ping_payload_decoder_test.cc b/net/third_party/quic/http/decoder/payload_decoders/quic_http_ping_payload_decoder_test.cc
deleted file mode 100644
index ef0efe9d..0000000
--- a/net/third_party/quic/http/decoder/payload_decoders/quic_http_ping_payload_decoder_test.cc
+++ /dev/null
@@ -1,122 +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 "net/third_party/quic/http/decoder/payload_decoders/quic_http_ping_payload_decoder.h"
-
-#include <stddef.h>
-
-#include <cstdint>
-
-#include "base/logging.h"
-#include "net/third_party/quic/http/decoder/payload_decoders/quic_http_payload_decoder_base_test_util.h"
-#include "net/third_party/quic/http/decoder/quic_http_frame_decoder_listener.h"
-#include "net/third_party/quic/http/quic_http_constants.h"
-#include "net/third_party/quic/http/quic_http_structures_test_util.h"
-#include "net/third_party/quic/http/test_tools/quic_http_frame_parts.h"
-#include "net/third_party/quic/http/test_tools/quic_http_frame_parts_collector.h"
-#include "net/third_party/quic/http/tools/quic_http_frame_builder.h"
-#include "net/third_party/quic/http/tools/quic_http_random_decoder_test.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace quic {
-namespace test {
-
-class QuicHttpPingQuicHttpPayloadDecoderPeer {
- public:
-  static constexpr QuicHttpFrameType FrameType() {
-    return QuicHttpFrameType::PING;
-  }
-
-  // Returns the mask of flags that affect the decoding of the payload (i.e.
-  // flags that that indicate the presence of certain fields or padding).
-  static constexpr uint8_t FlagsAffectingPayloadDecoding() { return 0; }
-
-  static void Randomize(QuicHttpPingQuicHttpPayloadDecoder* p,
-                        QuicTestRandomBase* rng) {
-    VLOG(1) << "QuicHttpPingQuicHttpPayloadDecoderPeer::Randomize";
-    test::Randomize(&p->ping_fields_, rng);
-  }
-};
-
-namespace {
-
-struct Listener : public QuicHttpFramePartsCollector {
-  void OnPing(const QuicHttpFrameHeader& header,
-              const QuicHttpPingFields& ping) override {
-    VLOG(1) << "OnPing: " << header << "; " << ping;
-    StartAndEndFrame(header)->OnPing(header, ping);
-  }
-
-  void OnPingAck(const QuicHttpFrameHeader& header,
-                 const QuicHttpPingFields& ping) override {
-    VLOG(1) << "OnPingAck: " << header << "; " << ping;
-    StartAndEndFrame(header)->OnPingAck(header, ping);
-  }
-
-  void OnFrameSizeError(const QuicHttpFrameHeader& header) override {
-    VLOG(1) << "OnFrameSizeError: " << header;
-    FrameError(header)->OnFrameSizeError(header);
-  }
-};
-
-class QuicHttpPingQuicHttpPayloadDecoderTest
-    : public AbstractQuicHttpPayloadDecoderTest<
-          QuicHttpPingQuicHttpPayloadDecoder,
-          QuicHttpPingQuicHttpPayloadDecoderPeer,
-          Listener> {
- protected:
-  QuicHttpPingFields RandPingFields() {
-    QuicHttpPingFields fields;
-    test::Randomize(&fields, RandomPtr());
-    return fields;
-  }
-};
-
-// Confirm we get an error if the payload is not the correct size to hold
-// exactly one QuicHttpPingFields.
-TEST_F(QuicHttpPingQuicHttpPayloadDecoderTest, WrongSize) {
-  auto approve_size = [](size_t size) {
-    return size != QuicHttpPingFields::EncodedSize();
-  };
-  QuicHttpFrameBuilder fb;
-  fb.Append(RandPingFields());
-  fb.Append(RandPingFields());
-  fb.Append(RandPingFields());
-  EXPECT_TRUE(VerifyDetectsFrameSizeError(0, fb.buffer(), approve_size));
-}
-
-TEST_F(QuicHttpPingQuicHttpPayloadDecoderTest, Ping) {
-  for (int n = 0; n < 100; ++n) {
-    QuicHttpPingFields fields = RandPingFields();
-    QuicHttpFrameBuilder fb;
-    fb.Append(fields);
-    QuicHttpFrameHeader header(fb.size(), QuicHttpFrameType::PING,
-                               RandFlags() & ~QuicHttpFrameFlag::QUIC_HTTP_ACK,
-                               RandStreamId());
-    set_frame_header(header);
-    QuicHttpFrameParts expected(header);
-    expected.opt_ping = fields;
-    EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(fb.buffer(), expected));
-  }
-}
-
-TEST_F(QuicHttpPingQuicHttpPayloadDecoderTest, PingAck) {
-  for (int n = 0; n < 100; ++n) {
-    QuicHttpPingFields fields;
-    Randomize(&fields, RandomPtr());
-    QuicHttpFrameBuilder fb;
-    fb.Append(fields);
-    QuicHttpFrameHeader header(fb.size(), QuicHttpFrameType::PING,
-                               RandFlags() | QuicHttpFrameFlag::QUIC_HTTP_ACK,
-                               RandStreamId());
-    set_frame_header(header);
-    QuicHttpFrameParts expected(header);
-    expected.opt_ping = fields;
-    EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(fb.buffer(), expected));
-  }
-}
-
-}  // namespace
-}  // namespace test
-}  // namespace quic
diff --git a/net/third_party/quic/http/decoder/payload_decoders/quic_http_priority_payload_decoder.cc b/net/third_party/quic/http/decoder/payload_decoders/quic_http_priority_payload_decoder.cc
deleted file mode 100644
index defa735..0000000
--- a/net/third_party/quic/http/decoder/payload_decoders/quic_http_priority_payload_decoder.cc
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "net/third_party/quic/http/decoder/payload_decoders/quic_http_priority_payload_decoder.h"
-
-#include "base/logging.h"
-#include "net/third_party/quic/http/decoder/quic_http_decode_buffer.h"
-#include "net/third_party/quic/http/decoder/quic_http_frame_decoder_listener.h"
-#include "net/third_party/quic/http/quic_http_constants.h"
-#include "net/third_party/quic/http/quic_http_structures.h"
-
-namespace quic {
-
-QuicHttpDecodeStatus
-QuicHttpPriorityQuicHttpPayloadDecoder::StartDecodingPayload(
-    QuicHttpFrameDecoderState* state,
-    QuicHttpDecodeBuffer* db) {
-  DVLOG(2) << "QuicHttpPriorityQuicHttpPayloadDecoder::StartDecodingPayload: "
-           << state->frame_header();
-  DCHECK_EQ(QuicHttpFrameType::QUIC_HTTP_PRIORITY, state->frame_header().type);
-  DCHECK_LE(db->Remaining(), state->frame_header().payload_length);
-  // QUIC_HTTP_PRIORITY frames have no flags.
-  DCHECK_EQ(0, state->frame_header().flags);
-  state->InitializeRemainders();
-  return HandleStatus(
-      state, state->StartDecodingStructureInPayload(&priority_fields_, db));
-}
-
-QuicHttpDecodeStatus
-QuicHttpPriorityQuicHttpPayloadDecoder::ResumeDecodingPayload(
-    QuicHttpFrameDecoderState* state,
-    QuicHttpDecodeBuffer* db) {
-  DVLOG(2) << "QuicHttpPriorityQuicHttpPayloadDecoder::ResumeDecodingPayload"
-           << "  remaining_payload=" << state->remaining_payload()
-           << "  db->Remaining=" << db->Remaining();
-  DCHECK_EQ(QuicHttpFrameType::QUIC_HTTP_PRIORITY, state->frame_header().type);
-  DCHECK_LE(db->Remaining(), state->frame_header().payload_length);
-  return HandleStatus(
-      state, state->ResumeDecodingStructureInPayload(&priority_fields_, db));
-}
-
-QuicHttpDecodeStatus QuicHttpPriorityQuicHttpPayloadDecoder::HandleStatus(
-    QuicHttpFrameDecoderState* state,
-    QuicHttpDecodeStatus status) {
-  if (status == QuicHttpDecodeStatus::kDecodeDone) {
-    if (state->remaining_payload() == 0) {
-      state->listener()->OnPriorityFrame(state->frame_header(),
-                                         priority_fields_);
-      return QuicHttpDecodeStatus::kDecodeDone;
-    }
-    // Payload is too long.
-    return state->ReportFrameSizeError();
-  }
-  // Not done decoding the structure. Either we've got more payload to decode,
-  // or we've run out because the payload is too short, in which case
-  // OnFrameSizeError will have already been called.
-  DCHECK((status == QuicHttpDecodeStatus::kDecodeInProgress &&
-          state->remaining_payload() > 0) ||
-         (status == QuicHttpDecodeStatus::kDecodeError &&
-          state->remaining_payload() == 0))
-      << "\n status=" << status
-      << "; remaining_payload=" << state->remaining_payload();
-  return status;
-}
-
-}  // namespace quic
diff --git a/net/third_party/quic/http/decoder/payload_decoders/quic_http_priority_payload_decoder.h b/net/third_party/quic/http/decoder/payload_decoders/quic_http_priority_payload_decoder.h
deleted file mode 100644
index adb9851..0000000
--- a/net/third_party/quic/http/decoder/payload_decoders/quic_http_priority_payload_decoder.h
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_THIRD_PARTY_QUIC_HTTP_DECODER_PAYLOAD_DECODERS_QUIC_HTTP_PRIORITY_PAYLOAD_DECODER_H_
-#define NET_THIRD_PARTY_QUIC_HTTP_DECODER_PAYLOAD_DECODERS_QUIC_HTTP_PRIORITY_PAYLOAD_DECODER_H_
-
-// Decodes the payload of a QUIC_HTTP_PRIORITY frame.
-// See http://g3doc/gfe/quic/http/decoder/payload_decoders/README.md for info
-// about payload decoders.
-
-#include "net/third_party/quic/http/decoder/quic_http_decode_buffer.h"
-#include "net/third_party/quic/http/decoder/quic_http_decode_status.h"
-#include "net/third_party/quic/http/decoder/quic_http_frame_decoder_state.h"
-#include "net/third_party/quic/http/quic_http_structures.h"
-#include "net/third_party/quic/platform/api/quic_export.h"
-
-namespace quic {
-namespace test {
-class QuicHttpPriorityQuicHttpPayloadDecoderPeer;
-}  // namespace test
-
-class QUIC_EXPORT_PRIVATE QuicHttpPriorityQuicHttpPayloadDecoder {
- public:
-  // Starts the decoding of a QUIC_HTTP_PRIORITY frame's payload, and completes
-  // it if the entire payload is in the provided decode buffer.
-  QuicHttpDecodeStatus StartDecodingPayload(QuicHttpFrameDecoderState* state,
-                                            QuicHttpDecodeBuffer* db);
-
-  // Resumes decoding a QUIC_HTTP_PRIORITY frame that has been split across
-  // decode buffers.
-  QuicHttpDecodeStatus ResumeDecodingPayload(QuicHttpFrameDecoderState* state,
-                                             QuicHttpDecodeBuffer* db);
-
- private:
-  friend class test::QuicHttpPriorityQuicHttpPayloadDecoderPeer;
-
-  // Determines whether to report the QUIC_HTTP_PRIORITY to the listener, wait
-  // for more input, or to report a Frame Size Error.
-  QuicHttpDecodeStatus HandleStatus(QuicHttpFrameDecoderState* state,
-                                    QuicHttpDecodeStatus status);
-
-  QuicHttpPriorityFields priority_fields_;
-};
-
-}  // namespace quic
-
-#endif  // NET_THIRD_PARTY_QUIC_HTTP_DECODER_PAYLOAD_DECODERS_QUIC_HTTP_PRIORITY_PAYLOAD_DECODER_H_
diff --git a/net/third_party/quic/http/decoder/payload_decoders/quic_http_priority_payload_decoder_test.cc b/net/third_party/quic/http/decoder/payload_decoders/quic_http_priority_payload_decoder_test.cc
deleted file mode 100644
index 376f989..0000000
--- a/net/third_party/quic/http/decoder/payload_decoders/quic_http_priority_payload_decoder_test.cc
+++ /dev/null
@@ -1,98 +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 "net/third_party/quic/http/decoder/payload_decoders/quic_http_priority_payload_decoder.h"
-
-#include <stddef.h>
-
-#include <cstdint>
-
-#include "base/logging.h"
-#include "net/third_party/quic/http/decoder/payload_decoders/quic_http_payload_decoder_base_test_util.h"
-#include "net/third_party/quic/http/decoder/quic_http_frame_decoder_listener.h"
-#include "net/third_party/quic/http/quic_http_constants.h"
-#include "net/third_party/quic/http/quic_http_structures_test_util.h"
-#include "net/third_party/quic/http/test_tools/quic_http_frame_parts.h"
-#include "net/third_party/quic/http/test_tools/quic_http_frame_parts_collector.h"
-#include "net/third_party/quic/http/tools/quic_http_frame_builder.h"
-#include "net/third_party/quic/http/tools/quic_http_random_decoder_test.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace quic {
-namespace test {
-
-class QuicHttpPriorityQuicHttpPayloadDecoderPeer {
- public:
-  static constexpr QuicHttpFrameType FrameType() {
-    return QuicHttpFrameType::QUIC_HTTP_PRIORITY;
-  }
-
-  // Returns the mask of flags that affect the decoding of the payload (i.e.
-  // flags that that indicate the presence of certain fields or padding).
-  static constexpr uint8_t FlagsAffectingPayloadDecoding() { return 0; }
-
-  static void Randomize(QuicHttpPriorityQuicHttpPayloadDecoder* p,
-                        QuicTestRandomBase* rng) {
-    VLOG(1) << "QuicHttpPriorityQuicHttpPayloadDecoderPeer::Randomize";
-    test::Randomize(&p->priority_fields_, rng);
-  }
-};
-
-namespace {
-
-struct Listener : public QuicHttpFramePartsCollector {
-  void OnPriorityFrame(const QuicHttpFrameHeader& header,
-                       const QuicHttpPriorityFields& priority_fields) override {
-    VLOG(1) << "OnPriority: " << header << "; " << priority_fields;
-    StartAndEndFrame(header)->OnPriorityFrame(header, priority_fields);
-  }
-
-  void OnFrameSizeError(const QuicHttpFrameHeader& header) override {
-    VLOG(1) << "OnFrameSizeError: " << header;
-    FrameError(header)->OnFrameSizeError(header);
-  }
-};
-
-class QuicHttpPriorityQuicHttpPayloadDecoderTest
-    : public AbstractQuicHttpPayloadDecoderTest<
-          QuicHttpPriorityQuicHttpPayloadDecoder,
-          QuicHttpPriorityQuicHttpPayloadDecoderPeer,
-          Listener> {
- protected:
-  QuicHttpPriorityFields RandPriorityFields() {
-    QuicHttpPriorityFields fields;
-    test::Randomize(&fields, RandomPtr());
-    return fields;
-  }
-};
-
-// Confirm we get an error if the payload is not the correct size to hold
-// exactly one QuicHttpPriorityFields.
-TEST_F(QuicHttpPriorityQuicHttpPayloadDecoderTest, WrongSize) {
-  auto approve_size = [](size_t size) {
-    return size != QuicHttpPriorityFields::EncodedSize();
-  };
-  QuicHttpFrameBuilder fb;
-  fb.Append(RandPriorityFields());
-  fb.Append(RandPriorityFields());
-  EXPECT_TRUE(VerifyDetectsFrameSizeError(0, fb.buffer(), approve_size));
-}
-
-TEST_F(QuicHttpPriorityQuicHttpPayloadDecoderTest, VariousPayloads) {
-  for (int n = 0; n < 100; ++n) {
-    QuicHttpPriorityFields fields = RandPriorityFields();
-    QuicHttpFrameBuilder fb;
-    fb.Append(fields);
-    QuicHttpFrameHeader header(fb.size(), QuicHttpFrameType::QUIC_HTTP_PRIORITY,
-                               RandFlags(), RandStreamId());
-    set_frame_header(header);
-    QuicHttpFrameParts expected(header);
-    expected.opt_priority = fields;
-    EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(fb.buffer(), expected));
-  }
-}
-
-}  // namespace
-}  // namespace test
-}  // namespace quic
diff --git a/net/third_party/quic/http/decoder/payload_decoders/quic_http_push_promise_payload_decoder.cc b/net/third_party/quic/http/decoder/payload_decoders/quic_http_push_promise_payload_decoder.cc
deleted file mode 100644
index 82c0f30..0000000
--- a/net/third_party/quic/http/decoder/payload_decoders/quic_http_push_promise_payload_decoder.cc
+++ /dev/null
@@ -1,180 +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 "net/third_party/quic/http/decoder/payload_decoders/quic_http_push_promise_payload_decoder.h"
-
-#include <stddef.h>
-
-#include <cstdint>
-
-#include "base/logging.h"
-#include "base/macros.h"
-#include "net/third_party/quic/http/decoder/quic_http_decode_buffer.h"
-#include "net/third_party/quic/http/decoder/quic_http_frame_decoder_listener.h"
-#include "net/third_party/quic/http/quic_http_constants.h"
-#include "net/third_party/quic/http/quic_http_structures.h"
-#include "net/third_party/quic/platform/api/quic_bug_tracker.h"
-#include "net/third_party/quic/platform/api/quic_fallthrough.h"
-
-namespace quic {
-
-std::ostream& operator<<(
-    std::ostream& out,
-    QuicHttpPushPromiseQuicHttpPayloadDecoder::PayloadState v) {
-  switch (v) {
-    case QuicHttpPushPromiseQuicHttpPayloadDecoder::PayloadState::
-        kReadPadLength:
-      return out << "kReadPadLength";
-    case QuicHttpPushPromiseQuicHttpPayloadDecoder::PayloadState::
-        kStartDecodingPushPromiseFields:
-      return out << "kStartDecodingPushPromiseFields";
-    case QuicHttpPushPromiseQuicHttpPayloadDecoder::PayloadState::kReadPayload:
-      return out << "kReadPayload";
-    case QuicHttpPushPromiseQuicHttpPayloadDecoder::PayloadState::kSkipPadding:
-      return out << "kSkipPadding";
-    case QuicHttpPushPromiseQuicHttpPayloadDecoder::PayloadState::
-        kResumeDecodingPushPromiseFields:
-      return out << "kResumeDecodingPushPromiseFields";
-  }
-  return out << static_cast<int>(v);
-}
-
-QuicHttpDecodeStatus
-QuicHttpPushPromiseQuicHttpPayloadDecoder::StartDecodingPayload(
-    QuicHttpFrameDecoderState* state,
-    QuicHttpDecodeBuffer* db) {
-  const QuicHttpFrameHeader& frame_header = state->frame_header();
-  const uint32_t total_length = frame_header.payload_length;
-
-  DVLOG(2)
-      << "QuicHttpPushPromiseQuicHttpPayloadDecoder::StartDecodingPayload: "
-      << frame_header;
-
-  DCHECK_EQ(QuicHttpFrameType::PUSH_PROMISE, frame_header.type);
-  DCHECK_LE(db->Remaining(), total_length);
-  DCHECK_EQ(0, frame_header.flags & ~(QuicHttpFrameFlag::QUIC_HTTP_END_HEADERS |
-                                      QuicHttpFrameFlag::QUIC_HTTP_PADDED));
-
-  if (!frame_header.IsPadded()) {
-    // If it turns out that PUSH_PROMISE frames without padding are sufficiently
-    // common, and that they are usually short enough that they fit entirely
-    // into one QuicHttpDecodeBuffer, we can detect that here and implement a
-    // special case, avoiding the state machine in ResumeDecodingPayload.
-    payload_state_ = PayloadState::kStartDecodingPushPromiseFields;
-  } else {
-    payload_state_ = PayloadState::kReadPadLength;
-  }
-  state->InitializeRemainders();
-  return ResumeDecodingPayload(state, db);
-}
-
-QuicHttpDecodeStatus
-QuicHttpPushPromiseQuicHttpPayloadDecoder::ResumeDecodingPayload(
-    QuicHttpFrameDecoderState* state,
-    QuicHttpDecodeBuffer* db) {
-  DVLOG(2) << "QuicHttpUnknownQuicHttpPayloadDecoder::ResumeDecodingPayload"
-           << "  remaining_payload=" << state->remaining_payload()
-           << "  db->Remaining=" << db->Remaining();
-
-  const QuicHttpFrameHeader& frame_header = state->frame_header();
-  DCHECK_EQ(QuicHttpFrameType::PUSH_PROMISE, frame_header.type);
-  DCHECK_LE(state->remaining_payload(), frame_header.payload_length);
-  DCHECK_LE(db->Remaining(), frame_header.payload_length);
-
-  QuicHttpDecodeStatus status;
-  while (true) {
-    DVLOG(2) << "QuicHttpPushPromiseQuicHttpPayloadDecoder::"
-                "ResumeDecodingPayload payload_state_="
-             << payload_state_;
-    switch (payload_state_) {
-      case PayloadState::kReadPadLength:
-        DCHECK_EQ(state->remaining_payload(), frame_header.payload_length);
-        // ReadPadLength handles the OnPadLength callback, and updating the
-        // remaining_payload and remaining_padding fields. If the amount of
-        // padding is too large to fit in the frame's payload, ReadPadLength
-        // instead calls OnPaddingTooLong and returns kDecodeError.
-        // Suppress the call to OnPadLength because we haven't yet called
-        // OnPushPromiseStart, which needs to wait until we've decoded the
-        // Promised Stream ID.
-        status = state->ReadPadLength(db, /*report_pad_length*/ false);
-        if (status != QuicHttpDecodeStatus::kDecodeDone) {
-          payload_state_ = PayloadState::kReadPadLength;
-          return status;
-        }
-        QUIC_FALLTHROUGH_INTENDED;
-
-      case PayloadState::kStartDecodingPushPromiseFields:
-        status =
-            state->StartDecodingStructureInPayload(&push_promise_fields_, db);
-        if (status != QuicHttpDecodeStatus::kDecodeDone) {
-          payload_state_ = PayloadState::kResumeDecodingPushPromiseFields;
-          return status;
-        }
-        // Finished decoding the Promised Stream ID. Can now tell the listener
-        // that we're starting to decode a PUSH_PROMISE frame.
-        ReportPushPromise(state);
-        QUIC_FALLTHROUGH_INTENDED;
-
-      case PayloadState::kReadPayload:
-        DCHECK_LT(state->remaining_payload(), frame_header.payload_length);
-        DCHECK_LE(state->remaining_payload(),
-                  frame_header.payload_length -
-                      QuicHttpPushPromiseFields::EncodedSize());
-        DCHECK_LE(
-            state->remaining_payload(),
-            frame_header.payload_length -
-                QuicHttpPushPromiseFields::EncodedSize() -
-                (frame_header.IsPadded() ? (1 + state->remaining_padding())
-                                         : 0));
-        {
-          size_t avail = state->AvailablePayload(db);
-          state->listener()->OnHpackFragment(db->cursor(), avail);
-          db->AdvanceCursor(avail);
-          state->ConsumePayload(avail);
-        }
-        if (state->remaining_payload() > 0) {
-          payload_state_ = PayloadState::kReadPayload;
-          return QuicHttpDecodeStatus::kDecodeInProgress;
-        }
-        QUIC_FALLTHROUGH_INTENDED;
-
-      case PayloadState::kSkipPadding:
-        // SkipPadding handles the OnPadding callback.
-        if (state->SkipPadding(db)) {
-          state->listener()->OnPushPromiseEnd();
-          return QuicHttpDecodeStatus::kDecodeDone;
-        }
-        payload_state_ = PayloadState::kSkipPadding;
-        return QuicHttpDecodeStatus::kDecodeInProgress;
-
-      case PayloadState::kResumeDecodingPushPromiseFields:
-        status =
-            state->ResumeDecodingStructureInPayload(&push_promise_fields_, db);
-        if (status == QuicHttpDecodeStatus::kDecodeDone) {
-          // Finished decoding the Promised Stream ID. Can now tell the listener
-          // that we're starting to decode a PUSH_PROMISE frame.
-          ReportPushPromise(state);
-          payload_state_ = PayloadState::kReadPayload;
-          continue;
-        }
-        payload_state_ = PayloadState::kResumeDecodingPushPromiseFields;
-        return status;
-    }
-    QUIC_BUG << "PayloadState: " << payload_state_;
-  }
-}
-
-void QuicHttpPushPromiseQuicHttpPayloadDecoder::ReportPushPromise(
-    QuicHttpFrameDecoderState* state) {
-  const QuicHttpFrameHeader& frame_header = state->frame_header();
-  if (frame_header.IsPadded()) {
-    state->listener()->OnPushPromiseStart(frame_header, push_promise_fields_,
-                                          1 + state->remaining_padding());
-  } else {
-    state->listener()->OnPushPromiseStart(frame_header, push_promise_fields_,
-                                          0);
-  }
-}
-
-}  // namespace quic
diff --git a/net/third_party/quic/http/decoder/payload_decoders/quic_http_push_promise_payload_decoder.h b/net/third_party/quic/http/decoder/payload_decoders/quic_http_push_promise_payload_decoder.h
deleted file mode 100644
index 46bb3ba..0000000
--- a/net/third_party/quic/http/decoder/payload_decoders/quic_http_push_promise_payload_decoder.h
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_THIRD_PARTY_QUIC_HTTP_DECODER_PAYLOAD_DECODERS_QUIC_HTTP_PUSH_PROMISE_PAYLOAD_DECODER_H_
-#define NET_THIRD_PARTY_QUIC_HTTP_DECODER_PAYLOAD_DECODERS_QUIC_HTTP_PUSH_PROMISE_PAYLOAD_DECODER_H_
-
-// Decodes the payload of a PUSH_PROMISE frame.
-// See http://g3doc/gfe/quic/http/decoder/payload_decoders/README.md for info
-// about payload decoders.
-
-#include "net/third_party/quic/http/decoder/quic_http_decode_buffer.h"
-#include "net/third_party/quic/http/decoder/quic_http_decode_status.h"
-#include "net/third_party/quic/http/decoder/quic_http_frame_decoder_state.h"
-#include "net/third_party/quic/http/quic_http_structures.h"
-#include "net/third_party/quic/platform/api/quic_export.h"
-
-namespace quic {
-namespace test {
-class QuicHttpPushPromiseQuicHttpPayloadDecoderPeer;
-}  // namespace test
-
-class QUIC_EXPORT_PRIVATE QuicHttpPushPromiseQuicHttpPayloadDecoder {
- public:
-  // States during decoding of a PUSH_PROMISE frame.
-  enum class PayloadState {
-    // The frame is padded and we need to read the PAD_LENGTH field (1 byte).
-    kReadPadLength,
-
-    // Ready to start decoding the fixed size fields of the PUSH_PROMISE
-    // frame into push_promise_fields_.
-    kStartDecodingPushPromiseFields,
-
-    // The decoder has already called OnPushPromiseStart, and is now reporting
-    // the HPQUIC_HTTP_ACK block fragment to the listener's OnHpackFragment
-    // method.
-    kReadPayload,
-
-    // The decoder has finished with the HPQUIC_HTTP_ACK block fragment, and is
-    // now
-    // ready to skip the trailing padding, if the frame has any.
-    kSkipPadding,
-
-    // The fixed size fields weren't all available when the decoder first tried
-    // to decode them (state kStartDecodingPushPromiseFields); this state
-    // resumes the decoding when ResumeDecodingPayload is called later.
-    kResumeDecodingPushPromiseFields,
-  };
-
-  // Starts the decoding of a PUSH_PROMISE frame's payload, and completes it if
-  // the entire payload is in the provided decode buffer.
-  QuicHttpDecodeStatus StartDecodingPayload(QuicHttpFrameDecoderState* state,
-                                            QuicHttpDecodeBuffer* db);
-
-  // Resumes decoding a PUSH_PROMISE frame's payload that has been split across
-  // decode buffers.
-  QuicHttpDecodeStatus ResumeDecodingPayload(QuicHttpFrameDecoderState* state,
-                                             QuicHttpDecodeBuffer* db);
-
- private:
-  friend class test::QuicHttpPushPromiseQuicHttpPayloadDecoderPeer;
-
-  void ReportPushPromise(QuicHttpFrameDecoderState* state);
-
-  PayloadState payload_state_;
-  QuicHttpPushPromiseFields push_promise_fields_;
-};
-
-}  // namespace quic
-
-#endif  // NET_THIRD_PARTY_QUIC_HTTP_DECODER_PAYLOAD_DECODERS_QUIC_HTTP_PUSH_PROMISE_PAYLOAD_DECODER_H_
diff --git a/net/third_party/quic/http/decoder/payload_decoders/quic_http_push_promise_payload_decoder_test.cc b/net/third_party/quic/http/decoder/payload_decoders/quic_http_push_promise_payload_decoder_test.cc
deleted file mode 100644
index 6e13e2b..0000000
--- a/net/third_party/quic/http/decoder/payload_decoders/quic_http_push_promise_payload_decoder_test.cc
+++ /dev/null
@@ -1,147 +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 "net/third_party/quic/http/decoder/payload_decoders/quic_http_push_promise_payload_decoder.h"
-
-#include <stddef.h>
-
-#include <cstdint>
-
-#include "base/logging.h"
-#include "net/third_party/quic/http/decoder/payload_decoders/quic_http_payload_decoder_base_test_util.h"
-#include "net/third_party/quic/http/decoder/quic_http_frame_decoder_listener.h"
-#include "net/third_party/quic/http/quic_http_constants.h"
-#include "net/third_party/quic/http/quic_http_structures_test_util.h"
-#include "net/third_party/quic/http/test_tools/quic_http_frame_parts.h"
-#include "net/third_party/quic/http/test_tools/quic_http_frame_parts_collector.h"
-#include "net/third_party/quic/http/tools/quic_http_frame_builder.h"
-#include "net/third_party/quic/http/tools/quic_http_random_decoder_test.h"
-#include "net/third_party/quic/platform/api/quic_string.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace quic {
-namespace test {
-
-// Provides friend access to an instance of the payload decoder, and also
-// provides info to aid in testing.
-class QuicHttpPushPromiseQuicHttpPayloadDecoderPeer {
- public:
-  static constexpr QuicHttpFrameType FrameType() {
-    return QuicHttpFrameType::PUSH_PROMISE;
-  }
-
-  // Returns the mask of flags that affect the decoding of the payload (i.e.
-  // flags that that indicate the presence of certain fields or padding).
-  static constexpr uint8_t FlagsAffectingPayloadDecoding() {
-    return QuicHttpFrameFlag::QUIC_HTTP_PADDED;
-  }
-
-  static void Randomize(QuicHttpPushPromiseQuicHttpPayloadDecoder* p,
-                        QuicTestRandomBase* rng) {
-    VLOG(1) << "QuicHttpPushPromiseQuicHttpPayloadDecoderPeer::Randomize";
-    CorruptEnum(&p->payload_state_, rng);
-    test::Randomize(&p->push_promise_fields_, rng);
-  }
-};
-
-namespace {
-
-// Listener listens for only those methods expected by the payload decoder
-// under test, and forwards them onto the QuicHttpFrameParts instance for the
-// current frame.
-struct Listener : public QuicHttpFramePartsCollector {
-  void OnPushPromiseStart(const QuicHttpFrameHeader& header,
-                          const QuicHttpPushPromiseFields& promise,
-                          size_t total_padding_length) override {
-    VLOG(1) << "OnPushPromiseStart header: " << header
-            << "  promise: " << promise
-            << "  total_padding_length: " << total_padding_length;
-    EXPECT_EQ(QuicHttpFrameType::PUSH_PROMISE, header.type);
-    StartFrame(header)->OnPushPromiseStart(header, promise,
-                                           total_padding_length);
-  }
-
-  void OnHpackFragment(const char* data, size_t len) override {
-    VLOG(1) << "OnHpackFragment: len=" << len;
-    CurrentFrame()->OnHpackFragment(data, len);
-  }
-
-  void OnPushPromiseEnd() override {
-    VLOG(1) << "OnPushPromiseEnd";
-    EndFrame()->OnPushPromiseEnd();
-  }
-
-  void OnPadding(const char* padding, size_t skipped_length) override {
-    VLOG(1) << "OnPadding: " << skipped_length;
-    CurrentFrame()->OnPadding(padding, skipped_length);
-  }
-
-  void OnPaddingTooLong(const QuicHttpFrameHeader& header,
-                        size_t missing_length) override {
-    VLOG(1) << "OnPaddingTooLong: " << header
-            << "; missing_length: " << missing_length;
-    FrameError(header)->OnPaddingTooLong(header, missing_length);
-  }
-
-  void OnFrameSizeError(const QuicHttpFrameHeader& header) override {
-    VLOG(1) << "OnFrameSizeError: " << header;
-    FrameError(header)->OnFrameSizeError(header);
-  }
-};
-
-class QuicHttpPushPromiseQuicHttpPayloadDecoderTest
-    : public AbstractPaddableQuicHttpPayloadDecoderTest<
-          QuicHttpPushPromiseQuicHttpPayloadDecoder,
-          QuicHttpPushPromiseQuicHttpPayloadDecoderPeer,
-          Listener> {};
-
-INSTANTIATE_TEST_CASE_P(VariousPadLengths,
-                        QuicHttpPushPromiseQuicHttpPayloadDecoderTest,
-                        ::testing::Values(0, 1, 2, 3, 4, 254, 255, 256));
-
-// Payload contains the required QuicHttpPushPromiseFields, followed by some
-// (fake) HPQUIC_HTTP_ACK payload.
-TEST_P(QuicHttpPushPromiseQuicHttpPayloadDecoderTest,
-       VariousHpackPayloadSizes) {
-  for (size_t hpack_size : {0, 1, 2, 3, 255, 256, 1024}) {
-    LOG(INFO) << "###########   hpack_size = " << hpack_size << "  ###########";
-    Reset();
-    QuicString hpack_payload = Random().RandString(hpack_size);
-    QuicHttpPushPromiseFields push_promise{RandStreamId()};
-    frame_builder_.Append(push_promise);
-    frame_builder_.Append(hpack_payload);
-    MaybeAppendTrailingPadding();
-    QuicHttpFrameHeader frame_header(frame_builder_.size(),
-                                     QuicHttpFrameType::PUSH_PROMISE,
-                                     RandFlags(), RandStreamId());
-    set_frame_header(frame_header);
-    QuicHttpFrameParts expected(frame_header, hpack_payload, total_pad_length_);
-    expected.opt_push_promise = push_promise;
-    EXPECT_TRUE(
-        DecodePayloadAndValidateSeveralWays(frame_builder_.buffer(), expected));
-  }
-}
-
-// Confirm we get an error if the payload is not long enough for the required
-// portion of the payload, regardless of the amount of (valid) padding.
-TEST_P(QuicHttpPushPromiseQuicHttpPayloadDecoderTest, Truncated) {
-  auto approve_size = [](size_t size) {
-    return size != QuicHttpPushPromiseFields::EncodedSize();
-  };
-  QuicHttpPushPromiseFields push_promise{RandStreamId()};
-  QuicHttpFrameBuilder fb;
-  fb.Append(push_promise);
-  EXPECT_TRUE(VerifyDetectsMultipleFrameSizeErrors(0, fb.buffer(), approve_size,
-                                                   total_pad_length_));
-}
-
-// Confirm we get an error if the QUIC_HTTP_PADDED flag is set but the payload
-// is not long enough to hold even the Pad Length amount of padding.
-TEST_P(QuicHttpPushPromiseQuicHttpPayloadDecoderTest, PaddingTooLong) {
-  EXPECT_TRUE(VerifyDetectsPaddingTooLong());
-}
-
-}  // namespace
-}  // namespace test
-}  // namespace quic
diff --git a/net/third_party/quic/http/decoder/payload_decoders/quic_http_rst_stream_payload_decoder.cc b/net/third_party/quic/http/decoder/payload_decoders/quic_http_rst_stream_payload_decoder.cc
deleted file mode 100644
index 3f76029..0000000
--- a/net/third_party/quic/http/decoder/payload_decoders/quic_http_rst_stream_payload_decoder.cc
+++ /dev/null
@@ -1,70 +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 "net/third_party/quic/http/decoder/payload_decoders/quic_http_rst_stream_payload_decoder.h"
-
-#include "base/logging.h"
-#include "net/third_party/quic/http/decoder/quic_http_decode_buffer.h"
-#include "net/third_party/quic/http/decoder/quic_http_frame_decoder_listener.h"
-#include "net/third_party/quic/http/quic_http_constants.h"
-#include "net/third_party/quic/http/quic_http_structures.h"
-
-namespace quic {
-
-QuicHttpDecodeStatus
-QuicHttpRstStreamQuicHttpPayloadDecoder::StartDecodingPayload(
-    QuicHttpFrameDecoderState* state,
-    QuicHttpDecodeBuffer* db) {
-  DVLOG(2) << "QuicHttpRstStreamQuicHttpPayloadDecoder::StartDecodingPayload: "
-           << state->frame_header();
-  DCHECK_EQ(QuicHttpFrameType::RST_STREAM, state->frame_header().type);
-  DCHECK_LE(db->Remaining(), state->frame_header().payload_length);
-  // RST_STREAM has no flags.
-  DCHECK_EQ(0, state->frame_header().flags);
-  state->InitializeRemainders();
-  return HandleStatus(
-      state, state->StartDecodingStructureInPayload(&rst_stream_fields_, db));
-}
-
-QuicHttpDecodeStatus
-QuicHttpRstStreamQuicHttpPayloadDecoder::ResumeDecodingPayload(
-    QuicHttpFrameDecoderState* state,
-    QuicHttpDecodeBuffer* db) {
-  DVLOG(2) << "QuicHttpRstStreamQuicHttpPayloadDecoder::ResumeDecodingPayload"
-           << "  remaining_payload=" << state->remaining_payload()
-           << "  db->Remaining=" << db->Remaining();
-  DCHECK_EQ(QuicHttpFrameType::RST_STREAM, state->frame_header().type);
-  DCHECK_LE(db->Remaining(), state->frame_header().payload_length);
-  return HandleStatus(
-      state, state->ResumeDecodingStructureInPayload(&rst_stream_fields_, db));
-}
-
-QuicHttpDecodeStatus QuicHttpRstStreamQuicHttpPayloadDecoder::HandleStatus(
-    QuicHttpFrameDecoderState* state,
-    QuicHttpDecodeStatus status) {
-  DVLOG(2) << "HandleStatus: status=" << status
-           << "; remaining_payload=" << state->remaining_payload();
-  if (status == QuicHttpDecodeStatus::kDecodeDone) {
-    if (state->remaining_payload() == 0) {
-      state->listener()->OnRstStream(state->frame_header(),
-                                     rst_stream_fields_.error_code);
-      return QuicHttpDecodeStatus::kDecodeDone;
-    }
-    // Payload is too long.
-    return state->ReportFrameSizeError();
-  }
-  // Not done decoding the structure. Either we've got more payload to decode,
-  // or we've run out because the payload is too short, in which case
-  // OnFrameSizeError will have already been called by the
-  // QuicHttpFrameDecoderState.
-  DCHECK((status == QuicHttpDecodeStatus::kDecodeInProgress &&
-          state->remaining_payload() > 0) ||
-         (status == QuicHttpDecodeStatus::kDecodeError &&
-          state->remaining_payload() == 0))
-      << "\n status=" << status
-      << "; remaining_payload=" << state->remaining_payload();
-  return status;
-}
-
-}  // namespace quic
diff --git a/net/third_party/quic/http/decoder/payload_decoders/quic_http_rst_stream_payload_decoder.h b/net/third_party/quic/http/decoder/payload_decoders/quic_http_rst_stream_payload_decoder.h
deleted file mode 100644
index 756cdb91..0000000
--- a/net/third_party/quic/http/decoder/payload_decoders/quic_http_rst_stream_payload_decoder.h
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_THIRD_PARTY_QUIC_HTTP_DECODER_PAYLOAD_DECODERS_QUIC_HTTP_RST_STREAM_PAYLOAD_DECODER_H_
-#define NET_THIRD_PARTY_QUIC_HTTP_DECODER_PAYLOAD_DECODERS_QUIC_HTTP_RST_STREAM_PAYLOAD_DECODER_H_
-
-// Decodes the payload of a RST_STREAM frame.
-// See http://g3doc/gfe/quic/http/decoder/payload_decoders/README.md for info
-// about payload decoders.
-
-#include "net/third_party/quic/http/decoder/quic_http_decode_buffer.h"
-#include "net/third_party/quic/http/decoder/quic_http_decode_status.h"
-#include "net/third_party/quic/http/decoder/quic_http_frame_decoder_state.h"
-#include "net/third_party/quic/http/quic_http_structures.h"
-#include "net/third_party/quic/platform/api/quic_export.h"
-
-namespace quic {
-namespace test {
-class QuicHttpRstStreamQuicHttpPayloadDecoderPeer;
-}  // namespace test
-
-class QUIC_EXPORT_PRIVATE QuicHttpRstStreamQuicHttpPayloadDecoder {
- public:
-  // Starts the decoding of a RST_STREAM frame's payload, and completes it if
-  // the entire payload is in the provided decode buffer.
-  QuicHttpDecodeStatus StartDecodingPayload(QuicHttpFrameDecoderState* state,
-                                            QuicHttpDecodeBuffer* db);
-
-  // Resumes decoding a RST_STREAM frame's payload that has been split across
-  // decode buffers.
-  QuicHttpDecodeStatus ResumeDecodingPayload(QuicHttpFrameDecoderState* state,
-                                             QuicHttpDecodeBuffer* db);
-
- private:
-  friend class test::QuicHttpRstStreamQuicHttpPayloadDecoderPeer;
-
-  QuicHttpDecodeStatus HandleStatus(QuicHttpFrameDecoderState* state,
-                                    QuicHttpDecodeStatus status);
-
-  QuicHttpRstStreamFields rst_stream_fields_;
-};
-
-}  // namespace quic
-
-#endif  // NET_THIRD_PARTY_QUIC_HTTP_DECODER_PAYLOAD_DECODERS_QUIC_HTTP_RST_STREAM_PAYLOAD_DECODER_H_
diff --git a/net/third_party/quic/http/decoder/payload_decoders/quic_http_rst_stream_payload_decoder_test.cc b/net/third_party/quic/http/decoder/payload_decoders/quic_http_rst_stream_payload_decoder_test.cc
deleted file mode 100644
index 1df2b7f..0000000
--- a/net/third_party/quic/http/decoder/payload_decoders/quic_http_rst_stream_payload_decoder_test.cc
+++ /dev/null
@@ -1,100 +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 "net/third_party/quic/http/decoder/payload_decoders/quic_http_rst_stream_payload_decoder.h"
-
-#include <stddef.h>
-
-#include <cstdint>
-
-#include "base/logging.h"
-#include "net/third_party/quic/http/decoder/payload_decoders/quic_http_payload_decoder_base_test_util.h"
-#include "net/third_party/quic/http/decoder/quic_http_frame_decoder_listener.h"
-#include "net/third_party/quic/http/quic_http_constants.h"
-#include "net/third_party/quic/http/quic_http_constants_test_util.h"
-#include "net/third_party/quic/http/quic_http_structures_test_util.h"
-#include "net/third_party/quic/http/test_tools/quic_http_frame_parts.h"
-#include "net/third_party/quic/http/test_tools/quic_http_frame_parts_collector.h"
-#include "net/third_party/quic/http/tools/quic_http_frame_builder.h"
-#include "net/third_party/quic/http/tools/quic_http_random_decoder_test.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace quic {
-namespace test {
-
-class QuicHttpRstStreamQuicHttpPayloadDecoderPeer {
- public:
-  static constexpr QuicHttpFrameType FrameType() {
-    return QuicHttpFrameType::RST_STREAM;
-  }
-
-  // Returns the mask of flags that affect the decoding of the payload (i.e.
-  // flags that that indicate the presence of certain fields or padding).
-  static constexpr uint8_t FlagsAffectingPayloadDecoding() { return 0; }
-
-  static void Randomize(QuicHttpRstStreamQuicHttpPayloadDecoder* p,
-                        QuicTestRandomBase* rng) {
-    VLOG(1) << "QuicHttpRstStreamQuicHttpPayloadDecoderPeer::Randomize";
-    test::Randomize(&p->rst_stream_fields_, rng);
-  }
-};
-
-namespace {
-
-struct Listener : public QuicHttpFramePartsCollector {
-  void OnRstStream(const QuicHttpFrameHeader& header,
-                   QuicHttpErrorCode error_code) override {
-    VLOG(1) << "OnRstStream: " << header << "; error_code=" << error_code;
-    StartAndEndFrame(header)->OnRstStream(header, error_code);
-  }
-
-  void OnFrameSizeError(const QuicHttpFrameHeader& header) override {
-    VLOG(1) << "OnFrameSizeError: " << header;
-    FrameError(header)->OnFrameSizeError(header);
-  }
-};
-
-class QuicHttpRstStreamQuicHttpPayloadDecoderTest
-    : public AbstractQuicHttpPayloadDecoderTest<
-          QuicHttpRstStreamQuicHttpPayloadDecoder,
-          QuicHttpRstStreamQuicHttpPayloadDecoderPeer,
-          Listener> {
- protected:
-  QuicHttpRstStreamFields RandRstStreamFields() {
-    QuicHttpRstStreamFields fields;
-    test::Randomize(&fields, RandomPtr());
-    return fields;
-  }
-};
-
-// Confirm we get an error if the payload is not the correct size to hold
-// exactly one QuicHttpRstStreamFields.
-TEST_F(QuicHttpRstStreamQuicHttpPayloadDecoderTest, WrongSize) {
-  auto approve_size = [](size_t size) {
-    return size != QuicHttpRstStreamFields::EncodedSize();
-  };
-  QuicHttpFrameBuilder fb;
-  fb.Append(RandRstStreamFields());
-  fb.Append(RandRstStreamFields());
-  fb.Append(RandRstStreamFields());
-  EXPECT_TRUE(VerifyDetectsFrameSizeError(0, fb.buffer(), approve_size));
-}
-
-TEST_F(QuicHttpRstStreamQuicHttpPayloadDecoderTest, AllErrors) {
-  for (auto error_code : AllQuicHttpErrorCodes()) {
-    QuicHttpRstStreamFields fields{error_code};
-    QuicHttpFrameBuilder fb;
-    fb.Append(fields);
-    QuicHttpFrameHeader header(fb.size(), QuicHttpFrameType::RST_STREAM,
-                               RandFlags(), RandStreamId());
-    set_frame_header(header);
-    QuicHttpFrameParts expected(header);
-    expected.opt_rst_stream_error_code = error_code;
-    EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(fb.buffer(), expected));
-  }
-}
-
-}  // namespace
-}  // namespace test
-}  // namespace quic
diff --git a/net/third_party/quic/http/decoder/payload_decoders/quic_http_settings_payload_decoder.cc b/net/third_party/quic/http/decoder/payload_decoders/quic_http_settings_payload_decoder.cc
deleted file mode 100644
index 63ec83e7..0000000
--- a/net/third_party/quic/http/decoder/payload_decoders/quic_http_settings_payload_decoder.cc
+++ /dev/null
@@ -1,110 +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 "net/third_party/quic/http/decoder/payload_decoders/quic_http_settings_payload_decoder.h"
-
-#include <cstdint>
-
-#include "base/logging.h"
-#include "net/third_party/quic/http/decoder/quic_http_decode_buffer.h"
-#include "net/third_party/quic/http/decoder/quic_http_frame_decoder_listener.h"
-#include "net/third_party/quic/http/quic_http_constants.h"
-#include "net/third_party/quic/http/quic_http_structures.h"
-
-namespace quic {
-
-QuicHttpDecodeStatus
-QuicHttpQuicHttpSettingsQuicHttpPayloadDecoder::StartDecodingPayload(
-    QuicHttpFrameDecoderState* state,
-    QuicHttpDecodeBuffer* db) {
-  const QuicHttpFrameHeader& frame_header = state->frame_header();
-  const uint32_t total_length = frame_header.payload_length;
-
-  DVLOG(2) << "QuicHttpQuicHttpSettingsQuicHttpPayloadDecoder::"
-              "StartDecodingPayload: "
-           << frame_header;
-  DCHECK_EQ(QuicHttpFrameType::SETTINGS, frame_header.type);
-  DCHECK_LE(db->Remaining(), total_length);
-  DCHECK_EQ(0, frame_header.flags & ~(QuicHttpFrameFlag::QUIC_HTTP_ACK));
-
-  if (frame_header.IsAck()) {
-    if (total_length == 0) {
-      state->listener()->OnSettingsAck(frame_header);
-      return QuicHttpDecodeStatus::kDecodeDone;
-    } else {
-      state->InitializeRemainders();
-      return state->ReportFrameSizeError();
-    }
-  } else {
-    state->InitializeRemainders();
-    state->listener()->OnSettingsStart(frame_header);
-    return StartDecodingSettings(state, db);
-  }
-}
-
-QuicHttpDecodeStatus
-QuicHttpQuicHttpSettingsQuicHttpPayloadDecoder::ResumeDecodingPayload(
-    QuicHttpFrameDecoderState* state,
-    QuicHttpDecodeBuffer* db) {
-  DVLOG(2)
-      << "QuicHttpQuicHttpSettingsQuicHttpPayloadDecoder::ResumeDecodingPayload"
-      << "  remaining_payload=" << state->remaining_payload()
-      << "  db->Remaining=" << db->Remaining();
-  DCHECK_EQ(QuicHttpFrameType::SETTINGS, state->frame_header().type);
-  DCHECK_LE(db->Remaining(), state->frame_header().payload_length);
-
-  QuicHttpDecodeStatus status =
-      state->ResumeDecodingStructureInPayload(&setting_fields_, db);
-  if (status == QuicHttpDecodeStatus::kDecodeDone) {
-    state->listener()->OnSetting(setting_fields_);
-    return StartDecodingSettings(state, db);
-  }
-  return HandleNotDone(state, db, status);
-}
-
-QuicHttpDecodeStatus
-QuicHttpQuicHttpSettingsQuicHttpPayloadDecoder::StartDecodingSettings(
-    QuicHttpFrameDecoderState* state,
-    QuicHttpDecodeBuffer* db) {
-  DVLOG(2)
-      << "QuicHttpQuicHttpSettingsQuicHttpPayloadDecoder::StartDecodingSettings"
-      << "  remaining_payload=" << state->remaining_payload()
-      << "  db->Remaining=" << db->Remaining();
-  while (state->remaining_payload() > 0) {
-    QuicHttpDecodeStatus status =
-        state->StartDecodingStructureInPayload(&setting_fields_, db);
-    if (status == QuicHttpDecodeStatus::kDecodeDone) {
-      state->listener()->OnSetting(setting_fields_);
-      continue;
-    }
-    return HandleNotDone(state, db, status);
-  }
-  DVLOG(2) << "LEAVING "
-              "QuicHttpQuicHttpSettingsQuicHttpPayloadDecoder::"
-              "StartDecodingSettings"
-           << "\n\tdb->Remaining=" << db->Remaining()
-           << "\n\t remaining_payload=" << state->remaining_payload();
-  state->listener()->OnSettingsEnd();
-  return QuicHttpDecodeStatus::kDecodeDone;
-}
-
-QuicHttpDecodeStatus
-QuicHttpQuicHttpSettingsQuicHttpPayloadDecoder::HandleNotDone(
-    QuicHttpFrameDecoderState* state,
-    QuicHttpDecodeBuffer* db,
-    QuicHttpDecodeStatus status) {
-  // Not done decoding the structure. Either we've got more payload to decode,
-  // or we've run out because the payload is too short, in which case
-  // OnFrameSizeError will have already been called.
-  DCHECK((status == QuicHttpDecodeStatus::kDecodeInProgress &&
-          state->remaining_payload() > 0) ||
-         (status == QuicHttpDecodeStatus::kDecodeError &&
-          state->remaining_payload() == 0))
-      << "\n status=" << status
-      << "; remaining_payload=" << state->remaining_payload()
-      << "; db->Remaining=" << db->Remaining();
-  return status;
-}
-
-}  // namespace quic
diff --git a/net/third_party/quic/http/decoder/payload_decoders/quic_http_settings_payload_decoder.h b/net/third_party/quic/http/decoder/payload_decoders/quic_http_settings_payload_decoder.h
deleted file mode 100644
index 1d33fe0..0000000
--- a/net/third_party/quic/http/decoder/payload_decoders/quic_http_settings_payload_decoder.h
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_THIRD_PARTY_QUIC_HTTP_DECODER_PAYLOAD_DECODERS_QUIC_HTTP_SETTINGS_PAYLOAD_DECODER_H_
-#define NET_THIRD_PARTY_QUIC_HTTP_DECODER_PAYLOAD_DECODERS_QUIC_HTTP_SETTINGS_PAYLOAD_DECODER_H_
-
-// Decodes the payload of a SETTINGS frame; for the RFC, see:
-//     http://httpwg.org/specs/rfc7540.html#SETTINGS
-//
-// For info about payload decoders, see:
-//     http://g3doc/gfe/quic/http/decoder/payload_decoders/README.md
-
-#include "net/third_party/quic/http/decoder/quic_http_decode_buffer.h"
-#include "net/third_party/quic/http/decoder/quic_http_decode_status.h"
-#include "net/third_party/quic/http/decoder/quic_http_frame_decoder_state.h"
-#include "net/third_party/quic/http/quic_http_structures.h"
-#include "net/third_party/quic/platform/api/quic_export.h"
-
-namespace quic {
-namespace test {
-class QuicHttpQuicHttpSettingsQuicHttpPayloadDecoderPeer;
-}  // namespace test
-
-class QUIC_EXPORT_PRIVATE QuicHttpQuicHttpSettingsQuicHttpPayloadDecoder {
- public:
-  // Starts the decoding of a SETTINGS frame's payload, and completes it if
-  // the entire payload is in the provided decode buffer.
-  QuicHttpDecodeStatus StartDecodingPayload(QuicHttpFrameDecoderState* state,
-                                            QuicHttpDecodeBuffer* db);
-
-  // Resumes decoding a SETTINGS frame that has been split across decode
-  // buffers.
-  QuicHttpDecodeStatus ResumeDecodingPayload(QuicHttpFrameDecoderState* state,
-                                             QuicHttpDecodeBuffer* db);
-
- private:
-  friend class test::QuicHttpQuicHttpSettingsQuicHttpPayloadDecoderPeer;
-
-  // Decodes as many settings as are available in the decode buffer, starting at
-  // the first byte of one setting; if a single setting is split across buffers,
-  // ResumeDecodingPayload will handle starting from where the previous call
-  // left off, and then will call StartDecodingSettings.
-  QuicHttpDecodeStatus StartDecodingSettings(QuicHttpFrameDecoderState* state,
-                                             QuicHttpDecodeBuffer* db);
-
-  // Decoding a single SETTING returned a status other than kDecodeDone; this
-  // method just brings together the DCHECKs to reduce duplication.
-  QuicHttpDecodeStatus HandleNotDone(QuicHttpFrameDecoderState* state,
-                                     QuicHttpDecodeBuffer* db,
-                                     QuicHttpDecodeStatus status);
-
-  QuicHttpSettingFields setting_fields_;
-};
-
-}  // namespace quic
-
-#endif  // NET_THIRD_PARTY_QUIC_HTTP_DECODER_PAYLOAD_DECODERS_QUIC_HTTP_SETTINGS_PAYLOAD_DECODER_H_
diff --git a/net/third_party/quic/http/decoder/payload_decoders/quic_http_settings_payload_decoder_test.cc b/net/third_party/quic/http/decoder/payload_decoders/quic_http_settings_payload_decoder_test.cc
deleted file mode 100644
index e57aa56..0000000
--- a/net/third_party/quic/http/decoder/payload_decoders/quic_http_settings_payload_decoder_test.cc
+++ /dev/null
@@ -1,170 +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 "net/third_party/quic/http/decoder/payload_decoders/quic_http_settings_payload_decoder.h"
-
-#include <stddef.h>
-
-#include <cstdint>
-#include <vector>
-
-#include "base/logging.h"
-#include "net/third_party/quic/http/decoder/payload_decoders/quic_http_payload_decoder_base_test_util.h"
-#include "net/third_party/quic/http/decoder/quic_http_frame_decoder_listener.h"
-#include "net/third_party/quic/http/quic_http_constants.h"
-#include "net/third_party/quic/http/quic_http_constants_test_util.h"
-#include "net/third_party/quic/http/quic_http_structures_test_util.h"
-#include "net/third_party/quic/http/test_tools/quic_http_frame_parts.h"
-#include "net/third_party/quic/http/test_tools/quic_http_frame_parts_collector.h"
-#include "net/third_party/quic/http/tools/quic_http_frame_builder.h"
-#include "net/third_party/quic/http/tools/quic_http_random_decoder_test.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace quic {
-namespace test {
-
-class QuicHttpQuicHttpSettingsQuicHttpPayloadDecoderPeer {
- public:
-  static constexpr QuicHttpFrameType FrameType() {
-    return QuicHttpFrameType::SETTINGS;
-  }
-
-  // Returns the mask of flags that affect the decoding of the payload (i.e.
-  // flags that that indicate the presence of certain fields or padding).
-  static constexpr uint8_t FlagsAffectingPayloadDecoding() {
-    return QuicHttpFrameFlag::QUIC_HTTP_ACK;
-  }
-
-  static void Randomize(QuicHttpQuicHttpSettingsQuicHttpPayloadDecoder* p,
-                        QuicTestRandomBase* rng) {
-    VLOG(1) << "QuicHttpQuicHttpSettingsQuicHttpPayloadDecoderPeer::Randomize";
-    test::Randomize(&p->setting_fields_, rng);
-  }
-};
-
-namespace {
-
-struct Listener : public QuicHttpFramePartsCollector {
-  void OnSettingsStart(const QuicHttpFrameHeader& header) override {
-    VLOG(1) << "OnSettingsStart: " << header;
-    EXPECT_EQ(QuicHttpFrameType::SETTINGS, header.type) << header;
-    EXPECT_EQ(QuicHttpFrameFlag(), header.flags) << header;
-    StartFrame(header)->OnSettingsStart(header);
-  }
-
-  void OnSetting(const QuicHttpSettingFields& setting_fields) override {
-    VLOG(1) << "QuicHttpSettingFields: setting_fields=" << setting_fields;
-    CurrentFrame()->OnSetting(setting_fields);
-  }
-
-  void OnSettingsEnd() override {
-    VLOG(1) << "OnSettingsEnd";
-    EndFrame()->OnSettingsEnd();
-  }
-
-  void OnSettingsAck(const QuicHttpFrameHeader& header) override {
-    VLOG(1) << "OnSettingsAck: " << header;
-    StartAndEndFrame(header)->OnSettingsAck(header);
-  }
-
-  void OnFrameSizeError(const QuicHttpFrameHeader& header) override {
-    VLOG(1) << "OnFrameSizeError: " << header;
-    FrameError(header)->OnFrameSizeError(header);
-  }
-};
-
-class QuicHttpQuicHttpSettingsQuicHttpPayloadDecoderTest
-    : public AbstractQuicHttpPayloadDecoderTest<
-          QuicHttpQuicHttpSettingsQuicHttpPayloadDecoder,
-          QuicHttpQuicHttpSettingsQuicHttpPayloadDecoderPeer,
-          Listener> {
- protected:
-  QuicHttpSettingFields RandSettingsFields() {
-    QuicHttpSettingFields fields;
-    test::Randomize(&fields, RandomPtr());
-    return fields;
-  }
-};
-
-// Confirm we get an error if the SETTINGS payload is not the correct size
-// to hold exactly zero or more whole QuicHttpSettingFields.
-TEST_F(QuicHttpQuicHttpSettingsQuicHttpPayloadDecoderTest, SettingsWrongSize) {
-  auto approve_size = [](size_t size) {
-    // Should get an error if size is not an integral multiple of the size
-    // of one setting.
-    return 0 != (size % QuicHttpSettingFields::EncodedSize());
-  };
-  QuicHttpFrameBuilder fb;
-  fb.Append(RandSettingsFields());
-  fb.Append(RandSettingsFields());
-  fb.Append(RandSettingsFields());
-  EXPECT_TRUE(VerifyDetectsFrameSizeError(0, fb.buffer(), approve_size));
-}
-
-// Confirm we get an error if the SETTINGS QUIC_HTTP_ACK payload is not empty.
-TEST_F(QuicHttpQuicHttpSettingsQuicHttpPayloadDecoderTest,
-       SettingsAkcWrongSize) {
-  auto approve_size = [](size_t size) { return size != 0; };
-  QuicHttpFrameBuilder fb;
-  fb.Append(RandSettingsFields());
-  fb.Append(RandSettingsFields());
-  fb.Append(RandSettingsFields());
-  EXPECT_TRUE(VerifyDetectsFrameSizeError(QuicHttpFrameFlag::QUIC_HTTP_ACK,
-                                          fb.buffer(), approve_size));
-}
-
-// SETTINGS must have stream_id==0, but the payload decoder doesn't check that.
-TEST_F(QuicHttpQuicHttpSettingsQuicHttpPayloadDecoderTest, SettingsAck) {
-  for (int stream_id = 0; stream_id < 3; ++stream_id) {
-    QuicHttpFrameHeader header(0, QuicHttpFrameType::SETTINGS,
-                               RandFlags() | QuicHttpFrameFlag::QUIC_HTTP_ACK,
-                               stream_id);
-    set_frame_header(header);
-    QuicHttpFrameParts expected(header);
-    EXPECT_TRUE(DecodePayloadAndValidateSeveralWays("", expected));
-  }
-}
-
-// Try several values of each known SETTINGS parameter.
-TEST_F(QuicHttpQuicHttpSettingsQuicHttpPayloadDecoderTest, OneRealSetting) {
-  std::vector<uint32_t> values = {0, 1, 0xffffffff, Random().Rand32()};
-  for (auto param : AllQuicHttpSettingsParameters()) {
-    for (uint32_t value : values) {
-      QuicHttpSettingFields fields(param, value);
-      QuicHttpFrameBuilder fb;
-      fb.Append(fields);
-      QuicHttpFrameHeader header(fb.size(), QuicHttpFrameType::SETTINGS,
-                                 RandFlags(), RandStreamId());
-      set_frame_header(header);
-      QuicHttpFrameParts expected(header);
-      expected.settings.push_back(fields);
-      EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(fb.buffer(), expected));
-    }
-  }
-}
-
-// Decode a SETTINGS frame with lots of fields.
-TEST_F(QuicHttpQuicHttpSettingsQuicHttpPayloadDecoderTest, ManySettings) {
-  const size_t num_settings = 100;
-  const size_t size = QuicHttpSettingFields::EncodedSize() * num_settings;
-  QuicHttpFrameHeader header(
-      size, QuicHttpFrameType::SETTINGS,
-      RandFlags(),  // & ~QuicHttpFrameFlag::QUIC_HTTP_ACK,
-      RandStreamId());
-  set_frame_header(header);
-  QuicHttpFrameParts expected(header);
-  QuicHttpFrameBuilder fb;
-  for (size_t n = 0; n < num_settings; ++n) {
-    QuicHttpSettingFields fields(static_cast<QuicHttpSettingsParameter>(n),
-                                 Random().Rand32());
-    fb.Append(fields);
-    expected.settings.push_back(fields);
-  }
-  ASSERT_EQ(size, fb.size());
-  EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(fb.buffer(), expected));
-}
-
-}  // namespace
-}  // namespace test
-}  // namespace quic
diff --git a/net/third_party/quic/http/decoder/payload_decoders/quic_http_unknown_payload_decoder.cc b/net/third_party/quic/http/decoder/payload_decoders/quic_http_unknown_payload_decoder.cc
deleted file mode 100644
index ddd024e..0000000
--- a/net/third_party/quic/http/decoder/payload_decoders/quic_http_unknown_payload_decoder.cc
+++ /dev/null
@@ -1,58 +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 "net/third_party/quic/http/decoder/payload_decoders/quic_http_unknown_payload_decoder.h"
-
-#include <stddef.h>
-
-#include "base/logging.h"
-#include "net/third_party/quic/http/decoder/quic_http_decode_buffer.h"
-#include "net/third_party/quic/http/decoder/quic_http_frame_decoder_listener.h"
-#include "net/third_party/quic/http/quic_http_constants.h"
-#include "net/third_party/quic/http/quic_http_structures.h"
-
-namespace quic {
-
-QuicHttpDecodeStatus
-QuicHttpUnknownQuicHttpPayloadDecoder::StartDecodingPayload(
-    QuicHttpFrameDecoderState* state,
-    QuicHttpDecodeBuffer* db) {
-  const QuicHttpFrameHeader& frame_header = state->frame_header();
-
-  DVLOG(2) << "QuicHttpUnknownQuicHttpPayloadDecoder::StartDecodingPayload: "
-           << frame_header;
-  DCHECK(!IsSupportedQuicHttpFrameType(frame_header.type)) << frame_header;
-  DCHECK_LE(db->Remaining(), frame_header.payload_length);
-
-  state->InitializeRemainders();
-  state->listener()->OnUnknownStart(frame_header);
-  return ResumeDecodingPayload(state, db);
-}
-
-QuicHttpDecodeStatus
-QuicHttpUnknownQuicHttpPayloadDecoder::ResumeDecodingPayload(
-    QuicHttpFrameDecoderState* state,
-    QuicHttpDecodeBuffer* db) {
-  DVLOG(2) << "QuicHttpUnknownQuicHttpPayloadDecoder::ResumeDecodingPayload "
-           << "remaining_payload=" << state->remaining_payload()
-           << "; db->Remaining=" << db->Remaining();
-  DCHECK(!IsSupportedQuicHttpFrameType(state->frame_header().type))
-      << state->frame_header();
-  DCHECK_LE(state->remaining_payload(), state->frame_header().payload_length);
-  DCHECK_LE(db->Remaining(), state->remaining_payload());
-
-  size_t avail = db->Remaining();
-  if (avail > 0) {
-    state->listener()->OnUnknownPayload(db->cursor(), avail);
-    db->AdvanceCursor(avail);
-    state->ConsumePayload(avail);
-  }
-  if (state->remaining_payload() == 0) {
-    state->listener()->OnUnknownEnd();
-    return QuicHttpDecodeStatus::kDecodeDone;
-  }
-  return QuicHttpDecodeStatus::kDecodeInProgress;
-}
-
-}  // namespace quic
diff --git a/net/third_party/quic/http/decoder/payload_decoders/quic_http_unknown_payload_decoder.h b/net/third_party/quic/http/decoder/payload_decoders/quic_http_unknown_payload_decoder.h
deleted file mode 100644
index 6282bb1..0000000
--- a/net/third_party/quic/http/decoder/payload_decoders/quic_http_unknown_payload_decoder.h
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_THIRD_PARTY_QUIC_HTTP_DECODER_PAYLOAD_DECODERS_QUIC_HTTP_UNKNOWN_PAYLOAD_DECODER_H_
-#define NET_THIRD_PARTY_QUIC_HTTP_DECODER_PAYLOAD_DECODERS_QUIC_HTTP_UNKNOWN_PAYLOAD_DECODER_H_
-
-// Decodes the payload of a frame whose type unknown.  According to the HTTP/2
-// specification (http://httpwg.org/specs/rfc7540.html#FrameHeader):
-//     Implementations MUST ignore and discard any frame that has
-//     a type that is unknown.
-//
-// See http://g3doc/gfe/quic/http/decoder/payload_decoders/README.md for info
-// about payload decoders.
-
-#include "net/third_party/quic/http/decoder/quic_http_decode_buffer.h"
-#include "net/third_party/quic/http/decoder/quic_http_decode_status.h"
-#include "net/third_party/quic/http/decoder/quic_http_frame_decoder_state.h"
-#include "net/third_party/quic/platform/api/quic_export.h"
-
-namespace quic {
-
-class QUIC_EXPORT_PRIVATE QuicHttpUnknownQuicHttpPayloadDecoder {
- public:
-  // Starts decoding a payload of unknown type; just passes it to the listener.
-  QuicHttpDecodeStatus StartDecodingPayload(QuicHttpFrameDecoderState* state,
-                                            QuicHttpDecodeBuffer* db);
-
-  // Resumes decoding a payload of unknown type that has been split across
-  // decode buffers.
-  QuicHttpDecodeStatus ResumeDecodingPayload(QuicHttpFrameDecoderState* state,
-                                             QuicHttpDecodeBuffer* db);
-};
-
-}  // namespace quic
-
-#endif  // NET_THIRD_PARTY_QUIC_HTTP_DECODER_PAYLOAD_DECODERS_QUIC_HTTP_UNKNOWN_PAYLOAD_DECODER_H_
diff --git a/net/third_party/quic/http/decoder/payload_decoders/quic_http_unknown_payload_decoder_test.cc b/net/third_party/quic/http/decoder/payload_decoders/quic_http_unknown_payload_decoder_test.cc
deleted file mode 100644
index 3c79d91..0000000
--- a/net/third_party/quic/http/decoder/payload_decoders/quic_http_unknown_payload_decoder_test.cc
+++ /dev/null
@@ -1,110 +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 "net/third_party/quic/http/decoder/payload_decoders/quic_http_unknown_payload_decoder.h"
-
-#include <stddef.h>
-
-#include <cstdint>
-#include <type_traits>
-
-#include "base/logging.h"
-#include "net/third_party/quic/http/decoder/payload_decoders/quic_http_payload_decoder_base_test_util.h"
-#include "net/third_party/quic/http/decoder/quic_http_frame_decoder_listener.h"
-#include "net/third_party/quic/http/quic_http_constants.h"
-#include "net/third_party/quic/http/quic_http_structures.h"
-#include "net/third_party/quic/http/test_tools/quic_http_frame_parts.h"
-#include "net/third_party/quic/http/test_tools/quic_http_frame_parts_collector.h"
-#include "net/third_party/quic/http/tools/quic_http_random_decoder_test.h"
-#include "net/third_party/quic/platform/api/quic_string.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace quic {
-namespace test {
-namespace {
-QuicHttpFrameType g_unknown_frame_type;
-}  // namespace
-
-// Provides friend access to an instance of the payload decoder, and also
-// provides info to aid in testing.
-class QuicHttpUnknownQuicHttpPayloadDecoderPeer {
- public:
-  static QuicHttpFrameType FrameType() { return g_unknown_frame_type; }
-
-  // Returns the mask of flags that affect the decoding of the payload (i.e.
-  // flags that that indicate the presence of certain fields or padding).
-  static constexpr uint8_t FlagsAffectingPayloadDecoding() { return 0; }
-
-  static void Randomize(QuicHttpUnknownQuicHttpPayloadDecoder* p,
-                        QuicTestRandomBase* rng) {
-    // QuicHttpUnknownQuicHttpPayloadDecoder has no fields, so there is nothing
-    // to randomize.
-    static_assert(
-        std::is_empty<QuicHttpUnknownQuicHttpPayloadDecoder>::value,
-        "Need to randomize fields of QuicHttpUnknownQuicHttpPayloadDecoder");
-  }
-};
-
-namespace {
-
-struct Listener : public QuicHttpFramePartsCollector {
-  void OnUnknownStart(const QuicHttpFrameHeader& header) override {
-    VLOG(1) << "OnUnknownStart: " << header;
-    StartFrame(header)->OnUnknownStart(header);
-  }
-
-  void OnUnknownPayload(const char* data, size_t len) override {
-    VLOG(1) << "OnUnknownPayload: len=" << len;
-    CurrentFrame()->OnUnknownPayload(data, len);
-  }
-
-  void OnUnknownEnd() override {
-    VLOG(1) << "OnUnknownEnd";
-    EndFrame()->OnUnknownEnd();
-  }
-};
-
-constexpr bool SupportedFrameType = false;
-
-class QuicHttpUnknownQuicHttpPayloadDecoderTest
-    : public AbstractQuicHttpPayloadDecoderTest<
-          QuicHttpUnknownQuicHttpPayloadDecoder,
-          QuicHttpUnknownQuicHttpPayloadDecoderPeer,
-          Listener,
-          SupportedFrameType>,
-      public ::testing::WithParamInterface<uint32_t> {
- protected:
-  QuicHttpUnknownQuicHttpPayloadDecoderTest() : length_(GetParam()) {
-    VLOG(1) << "################  length_=" << length_ << "  ################";
-
-    // Each test case will choose a random frame type that isn't supported.
-    do {
-      g_unknown_frame_type = static_cast<QuicHttpFrameType>(Random().Rand8());
-    } while (IsSupportedQuicHttpFrameType(g_unknown_frame_type));
-  }
-
-  const uint32_t length_;
-};
-
-INSTANTIATE_TEST_CASE_P(VariousLengths,
-                        QuicHttpUnknownQuicHttpPayloadDecoderTest,
-                        ::testing::Values(0, 1, 2, 3, 255, 256));
-
-TEST_P(QuicHttpUnknownQuicHttpPayloadDecoderTest, ValidLength) {
-  QuicString unknown_payload = Random().RandString(length_);
-  QuicHttpFrameHeader frame_header(length_, g_unknown_frame_type,
-                                   Random().Rand8(), RandStreamId());
-  set_frame_header(frame_header);
-  QuicHttpFrameParts expected(frame_header, unknown_payload);
-  EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(unknown_payload, expected));
-  // TODO(jamessynge): Check here (and in other such tests) that the fast
-  // and slow decode counts are both non-zero. Perhaps also add some kind of
-  // test for the listener having been called. That could simply be a test
-  // that there is a single collected QuicHttpFrameParts instance, and that it
-  // matches expected.
-}
-
-}  // namespace
-}  // namespace test
-}  // namespace quic
diff --git a/net/third_party/quic/http/decoder/payload_decoders/quic_http_window_update_payload_decoder.cc b/net/third_party/quic/http/decoder/payload_decoders/quic_http_window_update_payload_decoder.cc
deleted file mode 100644
index 8470cb83..0000000
--- a/net/third_party/quic/http/decoder/payload_decoders/quic_http_window_update_payload_decoder.cc
+++ /dev/null
@@ -1,88 +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 "net/third_party/quic/http/decoder/payload_decoders/quic_http_window_update_payload_decoder.h"
-
-#include <cstdint>
-
-#include "base/logging.h"
-#include "net/third_party/quic/http/decoder/quic_http_decode_buffer.h"
-#include "net/third_party/quic/http/decoder/quic_http_decode_structures.h"
-#include "net/third_party/quic/http/decoder/quic_http_frame_decoder_listener.h"
-#include "net/third_party/quic/http/quic_http_constants.h"
-#include "net/third_party/quic/http/quic_http_structures.h"
-
-namespace quic {
-
-QuicHttpDecodeStatus
-QuicHttpWindowUpdateQuicHttpPayloadDecoder::StartDecodingPayload(
-    QuicHttpFrameDecoderState* state,
-    QuicHttpDecodeBuffer* db) {
-  const QuicHttpFrameHeader& frame_header = state->frame_header();
-  const uint32_t total_length = frame_header.payload_length;
-
-  DVLOG(2)
-      << "QuicHttpWindowUpdateQuicHttpPayloadDecoder::StartDecodingPayload: "
-      << frame_header;
-
-  DCHECK_EQ(QuicHttpFrameType::WINDOW_UPDATE, frame_header.type);
-  DCHECK_LE(db->Remaining(), total_length);
-
-  // WINDOW_UPDATE frames have no flags.
-  DCHECK_EQ(0, frame_header.flags);
-
-  // Special case for when the payload is the correct size and entirely in
-  // the buffer.
-  if (db->Remaining() == QuicHttpWindowUpdateFields::EncodedSize() &&
-      total_length == QuicHttpWindowUpdateFields::EncodedSize()) {
-    DoDecode(&window_update_fields_, db);
-    state->listener()->OnWindowUpdate(
-        frame_header, window_update_fields_.window_size_increment);
-    return QuicHttpDecodeStatus::kDecodeDone;
-  }
-  state->InitializeRemainders();
-  return HandleStatus(state, state->StartDecodingStructureInPayload(
-                                 &window_update_fields_, db));
-}
-
-QuicHttpDecodeStatus
-QuicHttpWindowUpdateQuicHttpPayloadDecoder::ResumeDecodingPayload(
-    QuicHttpFrameDecoderState* state,
-    QuicHttpDecodeBuffer* db) {
-  DVLOG(2) << "ResumeDecodingPayload: remaining_payload="
-           << state->remaining_payload()
-           << "; db->Remaining=" << db->Remaining();
-  DCHECK_EQ(QuicHttpFrameType::WINDOW_UPDATE, state->frame_header().type);
-  DCHECK_LE(db->Remaining(), state->frame_header().payload_length);
-  return HandleStatus(state, state->ResumeDecodingStructureInPayload(
-                                 &window_update_fields_, db));
-}
-
-QuicHttpDecodeStatus QuicHttpWindowUpdateQuicHttpPayloadDecoder::HandleStatus(
-    QuicHttpFrameDecoderState* state,
-    QuicHttpDecodeStatus status) {
-  DVLOG(2) << "HandleStatus: status=" << status
-           << "; remaining_payload=" << state->remaining_payload();
-  if (status == QuicHttpDecodeStatus::kDecodeDone) {
-    if (state->remaining_payload() == 0) {
-      state->listener()->OnWindowUpdate(
-          state->frame_header(), window_update_fields_.window_size_increment);
-      return QuicHttpDecodeStatus::kDecodeDone;
-    }
-    // Payload is too long.
-    return state->ReportFrameSizeError();
-  }
-  // Not done decoding the structure. Either we've got more payload to decode,
-  // or we've run out because the payload is too short, in which case
-  // OnFrameSizeError will have already been called.
-  DCHECK((status == QuicHttpDecodeStatus::kDecodeInProgress &&
-          state->remaining_payload() > 0) ||
-         (status == QuicHttpDecodeStatus::kDecodeError &&
-          state->remaining_payload() == 0))
-      << "\n status=" << status
-      << "; remaining_payload=" << state->remaining_payload();
-  return status;
-}
-
-}  // namespace quic
diff --git a/net/third_party/quic/http/decoder/payload_decoders/quic_http_window_update_payload_decoder.h b/net/third_party/quic/http/decoder/payload_decoders/quic_http_window_update_payload_decoder.h
deleted file mode 100644
index 03fa0fc5..0000000
--- a/net/third_party/quic/http/decoder/payload_decoders/quic_http_window_update_payload_decoder.h
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_THIRD_PARTY_QUIC_HTTP_DECODER_PAYLOAD_DECODERS_QUIC_HTTP_WINDOW_UPDATE_PAYLOAD_DECODER_H_
-#define NET_THIRD_PARTY_QUIC_HTTP_DECODER_PAYLOAD_DECODERS_QUIC_HTTP_WINDOW_UPDATE_PAYLOAD_DECODER_H_
-
-// Decodes the payload of a WINDOW_UPDATE frame.
-// See http://g3doc/gfe/quic/http/decoder/payload_decoders/README.md for info
-// about payload decoders.
-
-#include "net/third_party/quic/http/decoder/quic_http_decode_buffer.h"
-#include "net/third_party/quic/http/decoder/quic_http_decode_status.h"
-#include "net/third_party/quic/http/decoder/quic_http_frame_decoder_state.h"
-#include "net/third_party/quic/http/quic_http_structures.h"
-#include "net/third_party/quic/platform/api/quic_export.h"
-
-namespace quic {
-namespace test {
-class QuicHttpWindowUpdateQuicHttpPayloadDecoderPeer;
-}  // namespace test
-
-class QUIC_EXPORT_PRIVATE QuicHttpWindowUpdateQuicHttpPayloadDecoder {
- public:
-  // Starts decoding a WINDOW_UPDATE frame's payload, and completes it if
-  // the entire payload is in the provided decode buffer.
-  QuicHttpDecodeStatus StartDecodingPayload(QuicHttpFrameDecoderState* state,
-                                            QuicHttpDecodeBuffer* db);
-
-  // Resumes decoding a WINDOW_UPDATE frame's payload that has been split across
-  // decode buffers.
-  QuicHttpDecodeStatus ResumeDecodingPayload(QuicHttpFrameDecoderState* state,
-                                             QuicHttpDecodeBuffer* db);
-
- private:
-  friend class test::QuicHttpWindowUpdateQuicHttpPayloadDecoderPeer;
-
-  QuicHttpDecodeStatus HandleStatus(QuicHttpFrameDecoderState* state,
-                                    QuicHttpDecodeStatus status);
-
-  QuicHttpWindowUpdateFields window_update_fields_;
-};
-
-}  // namespace quic
-
-#endif  // NET_THIRD_PARTY_QUIC_HTTP_DECODER_PAYLOAD_DECODERS_QUIC_HTTP_WINDOW_UPDATE_PAYLOAD_DECODER_H_
diff --git a/net/third_party/quic/http/decoder/payload_decoders/quic_http_window_update_payload_decoder_test.cc b/net/third_party/quic/http/decoder/payload_decoders/quic_http_window_update_payload_decoder_test.cc
deleted file mode 100644
index b75fdfbe..0000000
--- a/net/third_party/quic/http/decoder/payload_decoders/quic_http_window_update_payload_decoder_test.cc
+++ /dev/null
@@ -1,104 +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 "net/third_party/quic/http/decoder/payload_decoders/quic_http_window_update_payload_decoder.h"
-
-#include <stddef.h>
-
-#include <cstdint>
-
-#include "base/logging.h"
-#include "net/third_party/quic/http/decoder/payload_decoders/quic_http_payload_decoder_base_test_util.h"
-#include "net/third_party/quic/http/decoder/quic_http_frame_decoder_listener.h"
-#include "net/third_party/quic/http/quic_http_constants.h"
-#include "net/third_party/quic/http/quic_http_structures_test_util.h"
-#include "net/third_party/quic/http/test_tools/quic_http_frame_parts.h"
-#include "net/third_party/quic/http/test_tools/quic_http_frame_parts_collector.h"
-#include "net/third_party/quic/http/tools/quic_http_frame_builder.h"
-#include "net/third_party/quic/http/tools/quic_http_random_decoder_test.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace quic {
-namespace test {
-
-class QuicHttpWindowUpdateQuicHttpPayloadDecoderPeer {
- public:
-  static constexpr QuicHttpFrameType FrameType() {
-    return QuicHttpFrameType::WINDOW_UPDATE;
-  }
-
-  // Returns the mask of flags that affect the decoding of the payload (i.e.
-  // flags that that indicate the presence of certain fields or padding).
-  static constexpr uint8_t FlagsAffectingPayloadDecoding() { return 0; }
-
-  static void Randomize(QuicHttpWindowUpdateQuicHttpPayloadDecoder* p,
-                        QuicTestRandomBase* rng) {
-    test::Randomize(&p->window_update_fields_, rng);
-    VLOG(1) << "QuicHttpWindowUpdateQuicHttpPayloadDecoderPeer::Randomize "
-            << "window_update_fields_: " << p->window_update_fields_;
-  }
-};
-
-namespace {
-
-struct Listener : public QuicHttpFramePartsCollector {
-  void OnWindowUpdate(const QuicHttpFrameHeader& header,
-                      uint32_t window_size_increment) override {
-    VLOG(1) << "OnWindowUpdate: " << header
-            << "; window_size_increment=" << window_size_increment;
-    EXPECT_EQ(QuicHttpFrameType::WINDOW_UPDATE, header.type);
-    StartAndEndFrame(header)->OnWindowUpdate(header, window_size_increment);
-  }
-
-  void OnFrameSizeError(const QuicHttpFrameHeader& header) override {
-    VLOG(1) << "OnFrameSizeError: " << header;
-    FrameError(header)->OnFrameSizeError(header);
-  }
-};
-
-class QuicHttpWindowUpdateQuicHttpPayloadDecoderTest
-    : public AbstractQuicHttpPayloadDecoderTest<
-          QuicHttpWindowUpdateQuicHttpPayloadDecoder,
-          QuicHttpWindowUpdateQuicHttpPayloadDecoderPeer,
-          Listener> {
- protected:
-  QuicHttpWindowUpdateFields RandWindowUpdateFields() {
-    QuicHttpWindowUpdateFields fields;
-    test::Randomize(&fields, RandomPtr());
-    VLOG(3) << "RandWindowUpdateFields: " << fields;
-    return fields;
-  }
-};
-
-// Confirm we get an error if the payload is not the correct size to hold
-// exactly one QuicHttpWindowUpdateFields.
-TEST_F(QuicHttpWindowUpdateQuicHttpPayloadDecoderTest, WrongSize) {
-  auto approve_size = [](size_t size) {
-    return size != QuicHttpWindowUpdateFields::EncodedSize();
-  };
-  QuicHttpFrameBuilder fb;
-  fb.Append(RandWindowUpdateFields());
-  fb.Append(RandWindowUpdateFields());
-  fb.Append(RandWindowUpdateFields());
-  EXPECT_TRUE(VerifyDetectsFrameSizeError(0, fb.buffer(), approve_size));
-}
-
-TEST_F(QuicHttpWindowUpdateQuicHttpPayloadDecoderTest, VariousPayloads) {
-  for (int n = 0; n < 100; ++n) {
-    uint32_t stream_id = n == 0 ? 0 : RandStreamId();
-    QuicHttpWindowUpdateFields fields = RandWindowUpdateFields();
-    QuicHttpFrameBuilder fb;
-    fb.Append(fields);
-    QuicHttpFrameHeader header(fb.size(), QuicHttpFrameType::WINDOW_UPDATE,
-                               RandFlags(), stream_id);
-    set_frame_header(header);
-    QuicHttpFrameParts expected(header);
-    expected.opt_window_update_increment = fields.window_size_increment;
-    EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(fb.buffer(), expected));
-  }
-}
-
-}  // namespace
-}  // namespace test
-}  // namespace quic
diff --git a/net/third_party/quic/http/decoder/quic_http_decode_buffer.cc b/net/third_party/quic/http/decoder/quic_http_decode_buffer.cc
deleted file mode 100644
index 4edb795..0000000
--- a/net/third_party/quic/http/decoder/quic_http_decode_buffer.cc
+++ /dev/null
@@ -1,60 +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 "net/third_party/quic/http/decoder/quic_http_decode_buffer.h"
-
-namespace quic {
-
-#ifndef NDEBUG
-// These are part of validating during tests that there is at most one
-// QuicHttpDecodeBufferSubset instance at a time for any DecodeBuffer instance.
-void QuicHttpDecodeBuffer::set_subset_of_base(
-    QuicHttpDecodeBuffer* base,
-    const QuicHttpDecodeBufferSubset* subset) {
-  DCHECK_EQ(this, subset);
-  base->set_subset(subset);
-}
-void QuicHttpDecodeBuffer::clear_subset_of_base(
-    QuicHttpDecodeBuffer* base,
-    const QuicHttpDecodeBufferSubset* subset) {
-  DCHECK_EQ(this, subset);
-  base->clear_subset(subset);
-}
-void QuicHttpDecodeBuffer::set_subset(
-    const QuicHttpDecodeBufferSubset* subset) {
-  DCHECK(subset != nullptr);
-  DCHECK_EQ(subset_, nullptr) << "There is already a subset";
-  subset_ = subset;
-}
-void QuicHttpDecodeBuffer::clear_subset(
-    const QuicHttpDecodeBufferSubset* subset) {
-  DCHECK(subset != nullptr);
-  DCHECK_EQ(subset_, subset);
-  subset_ = nullptr;
-}
-void QuicHttpDecodeBufferSubset::DebugSetup() {
-  start_base_offset_ = base_buffer_->Offset();
-  max_base_offset_ = start_base_offset_ + FullSize();
-  DCHECK_LE(max_base_offset_, base_buffer_->FullSize());
-
-  // Ensure that there is only one QuicHttpDecodeBufferSubset at a time for a
-  // base.
-  set_subset_of_base(base_buffer_, this);
-}
-void QuicHttpDecodeBufferSubset::DebugTearDown() {
-  // Ensure that the base hasn't been modified.
-  DCHECK_EQ(start_base_offset_, base_buffer_->Offset())
-      << "The base buffer was modified";
-
-  // Ensure that we haven't gone beyond the maximum allowed offset.
-  size_t offset = Offset();
-  DCHECK_LE(offset, FullSize());
-  DCHECK_LE(start_base_offset_ + offset, max_base_offset_);
-  DCHECK_LE(max_base_offset_, base_buffer_->FullSize());
-
-  clear_subset_of_base(base_buffer_, this);
-}
-#endif
-
-}  // namespace quic
diff --git a/net/third_party/quic/http/decoder/quic_http_decode_buffer.h b/net/third_party/quic/http/decoder/quic_http_decode_buffer.h
deleted file mode 100644
index 168dd13..0000000
--- a/net/third_party/quic/http/decoder/quic_http_decode_buffer.h
+++ /dev/null
@@ -1,202 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_THIRD_PARTY_QUIC_HTTP_DECODER_QUIC_HTTP_DECODE_BUFFER_H_
-#define NET_THIRD_PARTY_QUIC_HTTP_DECODER_QUIC_HTTP_DECODE_BUFFER_H_
-
-// QuicHttpDecodeBuffer provides primitives for decoding various integer types
-// found in HTTP/2 frames. It wraps a byte array from which we can read and
-// decode serialized HTTP/2 frames, or parts thereof. QuicHttpDecodeBuffer is
-// intended only for stack allocation, where the caller is typically going to
-// use the QuicHttpDecodeBuffer instance as part of decoding the entire buffer
-// before returning to its own caller.
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <algorithm>
-
-#include "base/logging.h"
-#include "base/macros.h"
-#include "net/third_party/quic/platform/api/quic_export.h"
-#include "net/third_party/quic/platform/api/quic_string_piece.h"
-
-namespace quic {
-class QuicHttpDecodeBufferSubset;
-
-class QUIC_EXPORT_PRIVATE QuicHttpDecodeBuffer {
- public:
-  QuicHttpDecodeBuffer(const char* buffer, size_t len)
-      : buffer_(buffer), cursor_(buffer), beyond_(buffer + len) {
-    DCHECK(buffer != nullptr);
-    DCHECK_LE(len, MaxQuicHttpDecodeBufferLength());
-  }
-  explicit QuicHttpDecodeBuffer(QuicStringPiece s)
-      : QuicHttpDecodeBuffer(s.data(), s.size()) {}
-  // Constructor for character arrays, typically in tests. For example:
-  //    const char input[] = { 0x11 };
-  //    QuicHttpDecodeBuffer b(input);
-  template <size_t N>
-  explicit QuicHttpDecodeBuffer(const char (&buf)[N])
-      : QuicHttpDecodeBuffer(buf, N) {}
-
-  bool Empty() const { return cursor_ >= beyond_; }
-  bool HasData() const { return cursor_ < beyond_; }
-  size_t Remaining() const {
-    DCHECK_LE(cursor_, beyond_);
-    return beyond_ - cursor_;
-  }
-  size_t Offset() const { return cursor_ - buffer_; }
-  size_t FullSize() const { return beyond_ - buffer_; }
-
-  // Returns the minimum of the number of bytes remaining in this
-  // QuicHttpDecodeBuffer and |length|, in support of determining how much of
-  // some structure/quic_http_payload is in this QuicHttpDecodeBuffer.
-  size_t MinLengthRemaining(size_t length) const {
-    return std::min(length, Remaining());
-  }
-
-  // For std::string decoding, returns a pointer to the next byte/char to be
-  // decoded.
-  const char* cursor() const { return cursor_; }
-  // Advances the cursor (pointer to the next byte/char to be decoded).
-  void AdvanceCursor(size_t amount) {
-    DCHECK_LE(amount, Remaining());  // Need at least that much remaining.
-    DCHECK_EQ(subset_, nullptr) << "Access via subset only when present.";
-    cursor_ += amount;
-  }
-
-  // Only call methods starting "Decode" when there is enough input remaining.
-  char DecodeChar() {
-    DCHECK_LE(1u, Remaining());  // Need at least one byte remaining.
-    DCHECK_EQ(subset_, nullptr) << "Access via subset only when present.";
-    return *cursor_++;
-  }
-
-  uint8_t DecodeUInt8() { return static_cast<uint8_t>(DecodeChar()); }
-
-  uint16_t DecodeUInt16() {
-    DCHECK_LE(2u, Remaining());
-    const uint8_t b1 = DecodeUInt8();
-    const uint8_t b2 = DecodeUInt8();
-    // Note that chars are automatically promoted to ints during arithmetic,
-    // so the b1 << 8 doesn't end up as zero before being or-ed with b2.
-    // And the left-shift operator has higher precedence than the or operator.
-    return b1 << 8 | b2;
-  }
-
-  uint32_t DecodeUInt24() {
-    DCHECK_LE(3u, Remaining());
-    const uint8_t b1 = DecodeUInt8();
-    const uint8_t b2 = DecodeUInt8();
-    const uint8_t b3 = DecodeUInt8();
-    return b1 << 16 | b2 << 8 | b3;
-  }
-
-  // For 31-bit unsigned integers, where the 32nd bit is reserved for future
-  // use (i.e. the high-bit of the first byte of the encoding); examples:
-  // the Stream Id in a frame header or the Window Size Increment in a
-  // WINDOW_UPDATE frame.
-  uint32_t DecodeUInt31() {
-    DCHECK_LE(4u, Remaining());
-    const uint8_t b1 = DecodeUInt8() & 0x7f;  // Mask out the high order bit.
-    const uint8_t b2 = DecodeUInt8();
-    const uint8_t b3 = DecodeUInt8();
-    const uint8_t b4 = DecodeUInt8();
-    return b1 << 24 | b2 << 16 | b3 << 8 | b4;
-  }
-
-  uint32_t DecodeUInt32() {
-    DCHECK_LE(4u, Remaining());
-    const uint8_t b1 = DecodeUInt8();
-    const uint8_t b2 = DecodeUInt8();
-    const uint8_t b3 = DecodeUInt8();
-    const uint8_t b4 = DecodeUInt8();
-    return b1 << 24 | b2 << 16 | b3 << 8 | b4;
-  }
-
-  // We assume the decode buffers will typically be modest in size (i.e. often a
-  // few KB, perhaps as high as 100KB). Let's make sure during testing that we
-  // don't go very high, with 32MB selected rather arbitrarily.
-  static constexpr size_t MaxQuicHttpDecodeBufferLength() { return 1 << 25; }
-
- protected:
-#ifndef NDEBUG
-  // These are part of validating during tests that there is at most one
-  // QuicHttpDecodeBufferSubset instance at a time for any DecodeBuffer
-  // instance.
-  void set_subset_of_base(QuicHttpDecodeBuffer* base,
-                          const QuicHttpDecodeBufferSubset* subset);
-  void clear_subset_of_base(QuicHttpDecodeBuffer* base,
-                            const QuicHttpDecodeBufferSubset* subset);
-#endif
-
- private:
-#ifndef NDEBUG
-  void set_subset(const QuicHttpDecodeBufferSubset* subset);
-  void clear_subset(const QuicHttpDecodeBufferSubset* subset);
-#endif
-
-  // Prevent heap allocation of QuicHttpDecodeBuffer.
-  static void* operator new(size_t s);
-  static void* operator new[](size_t s);
-  static void operator delete(void* p);
-  static void operator delete[](void* p);
-
-  const char* const buffer_;
-  const char* cursor_;
-  const char* const beyond_;
-  const QuicHttpDecodeBufferSubset* subset_ = nullptr;  // Used for DCHECKs.
-
-  DISALLOW_COPY_AND_ASSIGN(QuicHttpDecodeBuffer);
-};
-
-// QuicHttpDecodeBufferSubset is used when decoding a known sized chunk of data,
-// which starts at base->cursor(), and continues for subset_len, which may be
-// entirely in |base|, or may extend beyond it (hence the MinLengthRemaining
-// in the constructor).
-// There are two benefits to using QuicHttpDecodeBufferSubset: it ensures that
-// the cursor of |base| is advanced when the subset's destructor runs, and it
-// ensures that the consumer of the subset can't go beyond the subset which
-// it is intended to decode.
-// There must be only a single QuicHttpDecodeBufferSubset at a time for a base
-// QuicHttpDecodeBuffer, though they can be nested (i.e. a DecodeBufferSubset's
-// base may itself be a QuicHttpDecodeBufferSubset). This avoids the
-// AdvanceCursor being called erroneously.
-class QUIC_EXPORT_PRIVATE QuicHttpDecodeBufferSubset
-    : public QuicHttpDecodeBuffer {
- public:
-  QuicHttpDecodeBufferSubset(QuicHttpDecodeBuffer* base, size_t subset_len)
-      : QuicHttpDecodeBuffer(base->cursor(),
-                             base->MinLengthRemaining(subset_len)),
-        base_buffer_(base) {
-#ifndef NDEBUG
-    DebugSetup();
-#endif
-  }
-
-  ~QuicHttpDecodeBufferSubset() {
-    size_t offset = Offset();
-#ifndef NDEBUG
-    DebugTearDown();
-#endif
-    base_buffer_->AdvanceCursor(offset);
-  }
-
- private:
-  QuicHttpDecodeBuffer* const base_buffer_;
-#ifndef NDEBUG
-  size_t start_base_offset_;  // Used for DCHECKs.
-  size_t max_base_offset_;    // Used for DCHECKs.
-
-  void DebugSetup();
-  void DebugTearDown();
-#endif
-
-  DISALLOW_COPY_AND_ASSIGN(QuicHttpDecodeBufferSubset);
-};
-
-}  // namespace quic
-
-#endif  // NET_THIRD_PARTY_QUIC_HTTP_DECODER_QUIC_HTTP_DECODE_BUFFER_H_
diff --git a/net/third_party/quic/http/decoder/quic_http_decode_buffer_test.cc b/net/third_party/quic/http/decoder/quic_http_decode_buffer_test.cc
deleted file mode 100644
index 77f13faa..0000000
--- a/net/third_party/quic/http/decoder/quic_http_decode_buffer_test.cc
+++ /dev/null
@@ -1,209 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "net/third_party/quic/http/decoder/quic_http_decode_buffer.h"
-
-#include "base/logging.h"
-#include "net/third_party/quic/platform/api/quic_test_random.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace quic {
-namespace test {
-namespace {
-
-enum class TestEnumClass32 {
-  kValue1 = 1,
-  kValue99 = 99,
-  kValue1M = 1000000,
-};
-
-enum class TestEnumClass8 {
-  kValue1 = 1,
-  kValue2 = 1,
-  kValue99 = 99,
-  kValue255 = 255,
-};
-
-enum TestEnum8 {
-  kMaskLo = 0x01,
-  kMaskHi = 0x80,
-};
-
-struct TestStruct {
-  uint8_t f1;
-  uint16_t f2;
-  uint32_t f3;  // Decoded as a uint24
-  uint32_t f4;
-  uint32_t f5;  // Decoded as if uint31
-  TestEnumClass32 f6;
-  TestEnumClass8 f7;
-  TestEnum8 f8;
-};
-
-class QuicHttpDecodeBufferTest : public ::testing::Test {
- public:
-  QuicHttpDecodeBufferTest() {
-    LOG(INFO) << "Random seed (--test_random_seed): "
-              << testing::FLAGS_gtest_random_seed;
-  }
-
- protected:
-  QuicTestRandom random_;
-  uint32_t decode_offset_;
-};
-
-TEST_F(QuicHttpDecodeBufferTest, DecodesFixedInts) {
-  const char data[] = "\x01\x12\x23\x34\x45\x56\x67\x78\x89\x9a";
-  QuicHttpDecodeBuffer b1(data, strlen(data));
-  EXPECT_EQ(1, b1.DecodeUInt8());
-  EXPECT_EQ(0x1223u, b1.DecodeUInt16());
-  EXPECT_EQ(0x344556u, b1.DecodeUInt24());
-  EXPECT_EQ(0x6778899au, b1.DecodeUInt32());
-}
-
-// Make sure that QuicHttpDecodeBuffer is not copying input, just pointing into
-// provided input buffer.
-TEST_F(QuicHttpDecodeBufferTest, HasNotCopiedInput) {
-  const char data[] = "ab";
-  QuicHttpDecodeBuffer b1(data, 2);
-
-  EXPECT_EQ(2u, b1.Remaining());
-  EXPECT_EQ(0u, b1.Offset());
-  EXPECT_FALSE(b1.Empty());
-  EXPECT_EQ(data, b1.cursor());  // cursor points to input buffer
-  EXPECT_TRUE(b1.HasData());
-
-  b1.AdvanceCursor(1);
-
-  EXPECT_EQ(1u, b1.Remaining());
-  EXPECT_EQ(1u, b1.Offset());
-  EXPECT_FALSE(b1.Empty());
-  EXPECT_EQ(&data[1], b1.cursor());
-  EXPECT_TRUE(b1.HasData());
-
-  b1.AdvanceCursor(1);
-
-  EXPECT_EQ(0u, b1.Remaining());
-  EXPECT_EQ(2u, b1.Offset());
-  EXPECT_TRUE(b1.Empty());
-  EXPECT_EQ(&data[2], b1.cursor());
-  EXPECT_FALSE(b1.HasData());
-
-  QuicHttpDecodeBuffer b2(data, 0);
-
-  EXPECT_EQ(0u, b2.Remaining());
-  EXPECT_EQ(0u, b2.Offset());
-  EXPECT_TRUE(b2.Empty());
-  EXPECT_EQ(data, b2.cursor());
-  EXPECT_FALSE(b2.HasData());
-}
-
-// QuicHttpDecodeBufferSubset can't go beyond the end of the base buffer.
-TEST_F(QuicHttpDecodeBufferTest, DecodeBufferSubsetLimited) {
-  const char data[] = "abc";
-  QuicHttpDecodeBuffer base(data, 3);
-  base.AdvanceCursor(1);
-  QuicHttpDecodeBufferSubset subset(&base, 100);
-  EXPECT_EQ(2u, subset.FullSize());
-}
-
-// QuicHttpDecodeBufferSubset advances the cursor of its base upon destruction.
-TEST_F(QuicHttpDecodeBufferTest, DecodeBufferSubsetAdvancesCursor) {
-  const char data[] = "abc";
-  const size_t size = sizeof(data) - 1;
-  EXPECT_EQ(3u, size);
-  QuicHttpDecodeBuffer base(data, size);
-  {
-    // First no change to the cursor.
-    QuicHttpDecodeBufferSubset subset(&base, size + 100);
-    EXPECT_EQ(size, subset.FullSize());
-    EXPECT_EQ(base.FullSize(), subset.FullSize());
-    EXPECT_EQ(0u, subset.Offset());
-  }
-  EXPECT_EQ(0u, base.Offset());
-  EXPECT_EQ(size, base.Remaining());
-}
-
-// Make sure that QuicHttpDecodeBuffer ctor complains about bad args.
-#if GTEST_HAS_DEATH_TEST && !defined(NDEBUG)
-TEST(QuicHttpDecodeBufferDeathTest, NonNullBufferRequired) {
-  EXPECT_DEBUG_DEATH({ QuicHttpDecodeBuffer b(nullptr, 3); }, "nullptr");
-}
-
-// Make sure that QuicHttpDecodeBuffer ctor complains about bad args.
-TEST(QuicHttpDecodeBufferDeathTest, ModestBufferSizeRequired) {
-  EXPECT_DEBUG_DEATH(
-      {
-        const char data[] = "abc";
-        size_t len = 0;
-        QuicHttpDecodeBuffer b(data, ~len);
-      },
-      "Max.*Length");
-}
-
-// Make sure that QuicHttpDecodeBuffer detects advance beyond end, in debug
-// mode.
-TEST(QuicHttpDecodeBufferDeathTest, LimitedAdvance) {
-  {
-    // Advance right up to end is OK.
-    const char data[] = "abc";
-    QuicHttpDecodeBuffer b(data, 3);
-    b.AdvanceCursor(3);  // OK
-    EXPECT_TRUE(b.Empty());
-  }
-  EXPECT_DEBUG_DEATH(
-      {
-        // Going beyond is not OK.
-        const char data[] = "abc";
-        QuicHttpDecodeBuffer b(data, 3);
-        b.AdvanceCursor(4);
-      },
-      "4 vs. 3");
-}
-
-// Make sure that QuicHttpDecodeBuffer detects decode beyond end, in debug mode.
-TEST(QuicHttpDecodeBufferDeathTest, DecodeUInt8PastEnd) {
-  const char data[] = {0x12, 0x23};
-  QuicHttpDecodeBuffer b(data, sizeof data);
-  EXPECT_EQ(2u, b.FullSize());
-  EXPECT_EQ(0x1223u, b.DecodeUInt16());
-  EXPECT_DEBUG_DEATH({ b.DecodeUInt8(); }, "1 vs. 0");
-}
-
-// Make sure that QuicHttpDecodeBuffer detects decode beyond end, in debug mode.
-TEST(QuicHttpDecodeBufferDeathTest, DecodeUInt16OverEnd) {
-  const char data[] = {0x12, 0x23, 0x34};
-  QuicHttpDecodeBuffer b(data, sizeof data);
-  EXPECT_EQ(3u, b.FullSize());
-  EXPECT_EQ(0x1223u, b.DecodeUInt16());
-  EXPECT_DEBUG_DEATH({ b.DecodeUInt16(); }, "2 vs. 1");
-}
-
-// Make sure that QuicHttpDecodeBuffer doesn't agree with having two subsets.
-TEST(QuicHttpDecodeBufferSubsetDeathTest, TwoSubsets) {
-  const char data[] = "abc";
-  QuicHttpDecodeBuffer base(data, 3);
-  QuicHttpDecodeBufferSubset subset1(&base, 1);
-  EXPECT_DEBUG_DEATH({ QuicHttpDecodeBufferSubset subset2(&base, 1); },
-                     "There is already a subset");
-}
-
-// Make sure that QuicHttpDecodeBufferSubset notices when the base's cursor has
-// moved.
-TEST(QuicHttpDecodeBufferSubsetDeathTest, BaseCursorAdvanced) {
-  const char data[] = "abc";
-  QuicHttpDecodeBuffer base(data, 3);
-  base.AdvanceCursor(1);
-  EXPECT_DEBUG_DEATH(
-      {
-        QuicHttpDecodeBufferSubset subset1(&base, 2);
-        base.AdvanceCursor(1);
-      },
-      "Access via subset only when present");
-}
-#endif  // GTEST_HAS_DEATH_TEST && !defined(NDEBUG)
-
-}  // namespace
-}  // namespace test
-}  // namespace quic
diff --git a/net/third_party/quic/http/decoder/quic_http_decode_status.cc b/net/third_party/quic/http/decoder/quic_http_decode_status.cc
deleted file mode 100644
index 34d4090..0000000
--- a/net/third_party/quic/http/decoder/quic_http_decode_status.cc
+++ /dev/null
@@ -1,28 +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 "net/third_party/quic/http/decoder/quic_http_decode_status.h"
-
-#include "base/logging.h"
-#include "net/third_party/quic/platform/api/quic_bug_tracker.h"
-
-namespace quic {
-
-std::ostream& operator<<(std::ostream& out, QuicHttpDecodeStatus v) {
-  switch (v) {
-    case QuicHttpDecodeStatus::kDecodeDone:
-      return out << "DecodeDone";
-    case QuicHttpDecodeStatus::kDecodeInProgress:
-      return out << "DecodeInProgress";
-    case QuicHttpDecodeStatus::kDecodeError:
-      return out << "DecodeError";
-  }
-  // Since the value doesn't come over the wire, only a programming bug should
-  // result in reaching this point.
-  int unknown = static_cast<int>(v);
-  QUIC_BUG << "Unknown QuicHttpDecodeStatus " << unknown;
-  return out << "QuicHttpDecodeStatus(" << unknown << ")";
-}
-
-}  // namespace quic
diff --git a/net/third_party/quic/http/decoder/quic_http_decode_status.h b/net/third_party/quic/http/decoder/quic_http_decode_status.h
deleted file mode 100644
index a1091fc9..0000000
--- a/net/third_party/quic/http/decoder/quic_http_decode_status.h
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_THIRD_PARTY_QUIC_HTTP_DECODER_QUIC_HTTP_DECODE_STATUS_H_
-#define NET_THIRD_PARTY_QUIC_HTTP_DECODER_QUIC_HTTP_DECODE_STATUS_H_
-
-// Enum QuicHttpDecodeStatus is used to report the status of decoding of many
-// types of HTTP/2 and HPQUIC_HTTP_ACK objects.
-
-#include <ostream>
-
-#include "net/third_party/quic/platform/api/quic_export.h"
-
-namespace quic {
-
-enum class QuicHttpDecodeStatus {
-  // Decoding is done.
-  kDecodeDone,
-
-  // Decoder needs more input to be able to make progress.
-  kDecodeInProgress,
-
-  // Decoding failed (e.g. HPQUIC_HTTP_ACK variable length integer is too large,
-  // or
-  // an HTTP/2 frame has padding declared to be larger than the payload).
-  kDecodeError,
-};
-QUIC_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out,
-                                             QuicHttpDecodeStatus v);
-
-}  // namespace quic
-
-#endif  // NET_THIRD_PARTY_QUIC_HTTP_DECODER_QUIC_HTTP_DECODE_STATUS_H_
diff --git a/net/third_party/quic/http/decoder/quic_http_decode_structures.cc b/net/third_party/quic/http/decoder/quic_http_decode_structures.cc
deleted file mode 100644
index b870933..0000000
--- a/net/third_party/quic/http/decoder/quic_http_decode_structures.cc
+++ /dev/null
@@ -1,111 +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 "net/third_party/quic/http/decoder/quic_http_decode_structures.h"
-
-#include <cstdint>
-
-#include "base/logging.h"
-#include "net/third_party/quic/http/decoder/quic_http_decode_buffer.h"
-#include "net/third_party/quic/http/quic_http_constants.h"
-
-namespace quic {
-
-// QuicHttpFrameHeader decoding:
-
-void DoDecode(QuicHttpFrameHeader* out, QuicHttpDecodeBuffer* b) {
-  DCHECK_NE(nullptr, out);
-  DCHECK_NE(nullptr, b);
-  DCHECK_LE(QuicHttpFrameHeader::EncodedSize(), b->Remaining());
-  out->payload_length = b->DecodeUInt24();
-  out->type = static_cast<QuicHttpFrameType>(b->DecodeUInt8());
-  out->flags = static_cast<QuicHttpFrameFlag>(b->DecodeUInt8());
-  out->stream_id = b->DecodeUInt31();
-}
-
-// QuicHttpPriorityFields decoding:
-
-void DoDecode(QuicHttpPriorityFields* out, QuicHttpDecodeBuffer* b) {
-  DCHECK_NE(nullptr, out);
-  DCHECK_NE(nullptr, b);
-  DCHECK_LE(QuicHttpPriorityFields::EncodedSize(), b->Remaining());
-  uint32_t stream_id_and_flag = b->DecodeUInt32();
-  out->stream_dependency = stream_id_and_flag & QuicHttpStreamIdMask();
-  if (out->stream_dependency == stream_id_and_flag) {
-    out->is_exclusive = false;
-  } else {
-    out->is_exclusive = true;
-  }
-  // Note that chars are automatically promoted to ints during arithmetic,
-  // so 255 + 1 doesn't end up as zero.
-  out->weight = b->DecodeUInt8() + 1;
-}
-
-// QuicHttpRstStreamFields decoding:
-
-void DoDecode(QuicHttpRstStreamFields* out, QuicHttpDecodeBuffer* b) {
-  DCHECK_NE(nullptr, out);
-  DCHECK_NE(nullptr, b);
-  DCHECK_LE(QuicHttpRstStreamFields::EncodedSize(), b->Remaining());
-  out->error_code = static_cast<QuicHttpErrorCode>(b->DecodeUInt32());
-}
-
-// QuicHttpSettingFields decoding:
-
-void DoDecode(QuicHttpSettingFields* out, QuicHttpDecodeBuffer* b) {
-  DCHECK_NE(nullptr, out);
-  DCHECK_NE(nullptr, b);
-  DCHECK_LE(QuicHttpSettingFields::EncodedSize(), b->Remaining());
-  out->parameter = static_cast<QuicHttpSettingsParameter>(b->DecodeUInt16());
-  out->value = b->DecodeUInt32();
-}
-
-// QuicHttpPushPromiseFields decoding:
-
-void DoDecode(QuicHttpPushPromiseFields* out, QuicHttpDecodeBuffer* b) {
-  DCHECK_NE(nullptr, out);
-  DCHECK_NE(nullptr, b);
-  DCHECK_LE(QuicHttpPushPromiseFields::EncodedSize(), b->Remaining());
-  out->promised_stream_id = b->DecodeUInt31();
-}
-
-// QuicHttpPingFields decoding:
-
-void DoDecode(QuicHttpPingFields* out, QuicHttpDecodeBuffer* b) {
-  DCHECK_NE(nullptr, out);
-  DCHECK_NE(nullptr, b);
-  DCHECK_LE(QuicHttpPingFields::EncodedSize(), b->Remaining());
-  memcpy(out->opaque_bytes, b->cursor(), QuicHttpPingFields::EncodedSize());
-  b->AdvanceCursor(QuicHttpPingFields::EncodedSize());
-}
-
-// QuicHttpGoAwayFields decoding:
-
-void DoDecode(QuicHttpGoAwayFields* out, QuicHttpDecodeBuffer* b) {
-  DCHECK_NE(nullptr, out);
-  DCHECK_NE(nullptr, b);
-  DCHECK_LE(QuicHttpGoAwayFields::EncodedSize(), b->Remaining());
-  out->last_stream_id = b->DecodeUInt31();
-  out->error_code = static_cast<QuicHttpErrorCode>(b->DecodeUInt32());
-}
-
-// QuicHttpWindowUpdateFields decoding:
-
-void DoDecode(QuicHttpWindowUpdateFields* out, QuicHttpDecodeBuffer* b) {
-  DCHECK_NE(nullptr, out);
-  DCHECK_NE(nullptr, b);
-  DCHECK_LE(QuicHttpWindowUpdateFields::EncodedSize(), b->Remaining());
-  out->window_size_increment = b->DecodeUInt31();
-}
-
-// QuicHttpAltSvcFields decoding:
-
-void DoDecode(QuicHttpAltSvcFields* out, QuicHttpDecodeBuffer* b) {
-  DCHECK_NE(nullptr, out);
-  DCHECK_NE(nullptr, b);
-  DCHECK_LE(QuicHttpAltSvcFields::EncodedSize(), b->Remaining());
-  out->origin_length = b->DecodeUInt16();
-}
-
-}  // namespace quic
diff --git a/net/third_party/quic/http/decoder/quic_http_decode_structures.h b/net/third_party/quic/http/decoder/quic_http_decode_structures.h
deleted file mode 100644
index 6bac543e..0000000
--- a/net/third_party/quic/http/decoder/quic_http_decode_structures.h
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_THIRD_PARTY_QUIC_HTTP_DECODER_QUIC_HTTP_DECODE_STRUCTURES_H_
-#define NET_THIRD_PARTY_QUIC_HTTP_DECODER_QUIC_HTTP_DECODE_STRUCTURES_H_
-
-// Provides functions for decoding the fixed size structures in the HTTP/2 spec.
-
-#include "net/third_party/quic/http/decoder/quic_http_decode_buffer.h"
-#include "net/third_party/quic/http/quic_http_structures.h"
-#include "net/third_party/quic/platform/api/quic_export.h"
-
-namespace quic {
-
-// DoDecode(STRUCTURE* out, QuicHttpDecodeBuffer* b) decodes the structure from
-// start to end, advancing the cursor by STRUCTURE::EncodedSize(). The decode
-// buffer must be large enough (i.e. b->Remaining() >=
-// STRUCTURE::EncodedSize()).
-
-QUIC_EXPORT_PRIVATE void DoDecode(QuicHttpFrameHeader* out,
-                                  QuicHttpDecodeBuffer* b);
-QUIC_EXPORT_PRIVATE void DoDecode(QuicHttpPriorityFields* out,
-                                  QuicHttpDecodeBuffer* b);
-QUIC_EXPORT_PRIVATE void DoDecode(QuicHttpRstStreamFields* out,
-                                  QuicHttpDecodeBuffer* b);
-QUIC_EXPORT_PRIVATE void DoDecode(QuicHttpSettingFields* out,
-                                  QuicHttpDecodeBuffer* b);
-QUIC_EXPORT_PRIVATE void DoDecode(QuicHttpPushPromiseFields* out,
-                                  QuicHttpDecodeBuffer* b);
-QUIC_EXPORT_PRIVATE void DoDecode(QuicHttpPingFields* out,
-                                  QuicHttpDecodeBuffer* b);
-QUIC_EXPORT_PRIVATE void DoDecode(QuicHttpGoAwayFields* out,
-                                  QuicHttpDecodeBuffer* b);
-QUIC_EXPORT_PRIVATE void DoDecode(QuicHttpWindowUpdateFields* out,
-                                  QuicHttpDecodeBuffer* b);
-QUIC_EXPORT_PRIVATE void DoDecode(QuicHttpAltSvcFields* out,
-                                  QuicHttpDecodeBuffer* b);
-
-}  // namespace quic
-
-#endif  // NET_THIRD_PARTY_QUIC_HTTP_DECODER_QUIC_HTTP_DECODE_STRUCTURES_H_
diff --git a/net/third_party/quic/http/decoder/quic_http_frame_decoder.cc b/net/third_party/quic/http/decoder/quic_http_frame_decoder.cc
deleted file mode 100644
index 68183649..0000000
--- a/net/third_party/quic/http/decoder/quic_http_frame_decoder.cc
+++ /dev/null
@@ -1,455 +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 "net/third_party/quic/http/decoder/quic_http_frame_decoder.h"
-
-#include "net/third_party/quic/http/quic_http_constants.h"
-#include "net/third_party/quic/platform/api/quic_bug_tracker.h"
-#include "net/third_party/quic/platform/api/quic_logging.h"
-
-namespace quic {
-
-std::ostream& operator<<(std::ostream& out, QuicHttpFrameDecoder::State v) {
-  switch (v) {
-    case QuicHttpFrameDecoder::State::kStartDecodingHeader:
-      return out << "kStartDecodingHeader";
-    case QuicHttpFrameDecoder::State::kResumeDecodingHeader:
-      return out << "kResumeDecodingHeader";
-    case QuicHttpFrameDecoder::State::kResumeDecodingPayload:
-      return out << "kResumeDecodingPayload";
-    case QuicHttpFrameDecoder::State::kDiscardPayload:
-      return out << "kDiscardPayload";
-  }
-  // Since the value doesn't come over the wire, only a programming bug should
-  // result in reaching this point.
-  int unknown = static_cast<int>(v);
-  QUIC_BUG << "QuicHttpFrameDecoder::State " << unknown;
-  return out << "QuicHttpFrameDecoder::State(" << unknown << ")";
-}
-
-QuicHttpFrameDecoder::QuicHttpFrameDecoder(
-    QuicHttpFrameDecoderListener* listener)
-    : state_(State::kStartDecodingHeader),
-      maximum_payload_size_(QuicHttpSettingsInfo::DefaultMaxFrameSize()) {
-  set_listener(listener);
-}
-
-void QuicHttpFrameDecoder::set_listener(
-    QuicHttpFrameDecoderListener* listener) {
-  if (listener == nullptr) {
-    listener = &no_op_listener_;
-  }
-  frame_decoder_state_.set_listener(listener);
-}
-
-QuicHttpFrameDecoderListener* QuicHttpFrameDecoder::listener() const {
-  return frame_decoder_state_.listener();
-}
-
-QuicHttpDecodeStatus QuicHttpFrameDecoder::DecodeFrame(
-    QuicHttpDecodeBuffer* db) {
-  DVLOG(2) << "QuicHttpFrameDecoder::DecodeFrame state=" << state_;
-  switch (state_) {
-    case State::kStartDecodingHeader:
-      if (frame_decoder_state_.StartDecodingFrameHeader(db)) {
-        return StartDecodingPayload(db);
-      }
-      state_ = State::kResumeDecodingHeader;
-      return QuicHttpDecodeStatus::kDecodeInProgress;
-
-    case State::kResumeDecodingHeader:
-      if (frame_decoder_state_.ResumeDecodingFrameHeader(db)) {
-        return StartDecodingPayload(db);
-      }
-      return QuicHttpDecodeStatus::kDecodeInProgress;
-
-    case State::kResumeDecodingPayload:
-      return ResumeDecodingPayload(db);
-
-    case State::kDiscardPayload:
-      return DiscardPayload(db);
-  }
-
-  QUIC_NOTREACHED();
-  return QuicHttpDecodeStatus::kDecodeError;
-}
-
-size_t QuicHttpFrameDecoder::remaining_payload() const {
-  return frame_decoder_state_.remaining_payload();
-}
-
-uint32_t QuicHttpFrameDecoder::remaining_padding() const {
-  return frame_decoder_state_.remaining_padding();
-}
-
-QuicHttpDecodeStatus QuicHttpFrameDecoder::StartDecodingPayload(
-    QuicHttpDecodeBuffer* db) {
-  const QuicHttpFrameHeader& header = frame_header();
-
-  // TODO(jamessynge): Remove OnFrameHeader once done with supporting
-  // spdy::SpdyFramer's exact states.
-  if (!listener()->OnFrameHeader(header)) {
-    DVLOG(2) << "OnFrameHeader rejected the frame, will discard; header: "
-             << header;
-    state_ = State::kDiscardPayload;
-    frame_decoder_state_.InitializeRemainders();
-    return QuicHttpDecodeStatus::kDecodeError;
-  }
-
-  if (header.payload_length > maximum_payload_size_) {
-    DVLOG(2) << "Payload length is greater than allowed: "
-             << header.payload_length << " > " << maximum_payload_size_
-             << "\n   header: " << header;
-    state_ = State::kDiscardPayload;
-    frame_decoder_state_.InitializeRemainders();
-    listener()->OnFrameSizeError(header);
-    return QuicHttpDecodeStatus::kDecodeError;
-  }
-
-  // The decode buffer can extend across many frames. Make sure that the
-  // buffer we pass to the start method that is specific to the frame type
-  // does not exend beyond this frame.
-  QuicHttpDecodeBufferSubset subset(db, header.payload_length);
-  QuicHttpDecodeStatus status;
-  switch (header.type) {
-    case QuicHttpFrameType::DATA:
-      status = StartDecodingDataPayload(&subset);
-      break;
-
-    case QuicHttpFrameType::HEADERS:
-      status = StartDecodingHeadersPayload(&subset);
-      break;
-
-    case QuicHttpFrameType::QUIC_HTTP_PRIORITY:
-      status = StartDecodingPriorityPayload(&subset);
-      break;
-
-    case QuicHttpFrameType::RST_STREAM:
-      status = StartDecodingRstStreamPayload(&subset);
-      break;
-
-    case QuicHttpFrameType::SETTINGS:
-      status = StartDecodingSettingsPayload(&subset);
-      break;
-
-    case QuicHttpFrameType::PUSH_PROMISE:
-      status = StartDecodingPushPromisePayload(&subset);
-      break;
-
-    case QuicHttpFrameType::PING:
-      status = StartDecodingPingPayload(&subset);
-      break;
-
-    case QuicHttpFrameType::GOAWAY:
-      status = StartDecodingGoAwayPayload(&subset);
-      break;
-
-    case QuicHttpFrameType::WINDOW_UPDATE:
-      status = StartDecodingWindowUpdatePayload(&subset);
-      break;
-
-    case QuicHttpFrameType::CONTINUATION:
-      status = StartDecodingContinuationPayload(&subset);
-      break;
-
-    case QuicHttpFrameType::ALTSVC:
-      status = StartDecodingAltSvcPayload(&subset);
-      break;
-
-    default:
-      status = StartDecodingUnknownPayload(&subset);
-      break;
-  }
-
-  if (status == QuicHttpDecodeStatus::kDecodeDone) {
-    state_ = State::kStartDecodingHeader;
-    return status;
-  } else if (status == QuicHttpDecodeStatus::kDecodeInProgress) {
-    state_ = State::kResumeDecodingPayload;
-    return status;
-  } else {
-    state_ = State::kDiscardPayload;
-    return status;
-  }
-}
-
-QuicHttpDecodeStatus QuicHttpFrameDecoder::ResumeDecodingPayload(
-    QuicHttpDecodeBuffer* db) {
-  // The decode buffer can extend across many frames. Make sure that the
-  // buffer we pass to the start method that is specific to the frame type
-  // does not exend beyond this frame.
-  size_t remaining = frame_decoder_state_.remaining_total_payload();
-  DCHECK_LE(remaining, frame_header().payload_length);
-  QuicHttpDecodeBufferSubset subset(db, remaining);
-  QuicHttpDecodeStatus status;
-  switch (frame_header().type) {
-    case QuicHttpFrameType::DATA:
-      status = ResumeDecodingDataPayload(&subset);
-      break;
-
-    case QuicHttpFrameType::HEADERS:
-      status = ResumeDecodingHeadersPayload(&subset);
-      break;
-
-    case QuicHttpFrameType::QUIC_HTTP_PRIORITY:
-      status = ResumeDecodingPriorityPayload(&subset);
-      break;
-
-    case QuicHttpFrameType::RST_STREAM:
-      status = ResumeDecodingRstStreamPayload(&subset);
-      break;
-
-    case QuicHttpFrameType::SETTINGS:
-      status = ResumeDecodingSettingsPayload(&subset);
-      break;
-
-    case QuicHttpFrameType::PUSH_PROMISE:
-      status = ResumeDecodingPushPromisePayload(&subset);
-      break;
-
-    case QuicHttpFrameType::PING:
-      status = ResumeDecodingPingPayload(&subset);
-      break;
-
-    case QuicHttpFrameType::GOAWAY:
-      status = ResumeDecodingGoAwayPayload(&subset);
-      break;
-
-    case QuicHttpFrameType::WINDOW_UPDATE:
-      status = ResumeDecodingWindowUpdatePayload(&subset);
-      break;
-
-    case QuicHttpFrameType::CONTINUATION:
-      status = ResumeDecodingContinuationPayload(&subset);
-      break;
-
-    case QuicHttpFrameType::ALTSVC:
-      status = ResumeDecodingAltSvcPayload(&subset);
-      break;
-
-    default:
-      status = ResumeDecodingUnknownPayload(&subset);
-      break;
-  }
-
-  if (status == QuicHttpDecodeStatus::kDecodeDone) {
-    state_ = State::kStartDecodingHeader;
-    return status;
-  } else if (status == QuicHttpDecodeStatus::kDecodeInProgress) {
-    return status;
-  } else {
-    state_ = State::kDiscardPayload;
-    return status;
-  }
-}
-
-// Clear any of the flags in the frame header that aren't set in valid_flags.
-void QuicHttpFrameDecoder::RetainFlags(uint8_t valid_flags) {
-  frame_decoder_state_.RetainFlags(valid_flags);
-}
-
-// Clear all of the flags in the frame header; for use with frame types that
-// don't define any flags, such as WINDOW_UPDATE.
-void QuicHttpFrameDecoder::ClearFlags() {
-  frame_decoder_state_.ClearFlags();
-}
-
-QuicHttpDecodeStatus QuicHttpFrameDecoder::StartDecodingAltSvcPayload(
-    QuicHttpDecodeBuffer* db) {
-  ClearFlags();
-  return altsvc_payload_decoder_.StartDecodingPayload(&frame_decoder_state_,
-                                                      db);
-}
-QuicHttpDecodeStatus QuicHttpFrameDecoder::ResumeDecodingAltSvcPayload(
-    QuicHttpDecodeBuffer* db) {
-  // The frame is not paddable.
-  DCHECK_EQ(frame_decoder_state_.remaining_total_payload(),
-            frame_decoder_state_.remaining_payload());
-  return altsvc_payload_decoder_.ResumeDecodingPayload(&frame_decoder_state_,
-                                                       db);
-}
-
-QuicHttpDecodeStatus QuicHttpFrameDecoder::StartDecodingContinuationPayload(
-    QuicHttpDecodeBuffer* db) {
-  RetainFlags(QuicHttpFrameFlag::QUIC_HTTP_END_HEADERS);
-  return continuation_payload_decoder_.StartDecodingPayload(
-      &frame_decoder_state_, db);
-}
-QuicHttpDecodeStatus QuicHttpFrameDecoder::ResumeDecodingContinuationPayload(
-    QuicHttpDecodeBuffer* db) {
-  // The frame is not paddable.
-  DCHECK_EQ(frame_decoder_state_.remaining_total_payload(),
-            frame_decoder_state_.remaining_payload());
-  return continuation_payload_decoder_.ResumeDecodingPayload(
-      &frame_decoder_state_, db);
-}
-
-QuicHttpDecodeStatus QuicHttpFrameDecoder::StartDecodingDataPayload(
-    QuicHttpDecodeBuffer* db) {
-  RetainFlags(QuicHttpFrameFlag::QUIC_HTTP_END_STREAM |
-              QuicHttpFrameFlag::QUIC_HTTP_PADDED);
-  return data_payload_decoder_.StartDecodingPayload(&frame_decoder_state_, db);
-}
-QuicHttpDecodeStatus QuicHttpFrameDecoder::ResumeDecodingDataPayload(
-    QuicHttpDecodeBuffer* db) {
-  return data_payload_decoder_.ResumeDecodingPayload(&frame_decoder_state_, db);
-}
-
-QuicHttpDecodeStatus QuicHttpFrameDecoder::StartDecodingGoAwayPayload(
-    QuicHttpDecodeBuffer* db) {
-  ClearFlags();
-  return goaway_payload_decoder_.StartDecodingPayload(&frame_decoder_state_,
-                                                      db);
-}
-QuicHttpDecodeStatus QuicHttpFrameDecoder::ResumeDecodingGoAwayPayload(
-    QuicHttpDecodeBuffer* db) {
-  // The frame is not paddable.
-  DCHECK_EQ(frame_decoder_state_.remaining_total_payload(),
-            frame_decoder_state_.remaining_payload());
-  return goaway_payload_decoder_.ResumeDecodingPayload(&frame_decoder_state_,
-                                                       db);
-}
-
-QuicHttpDecodeStatus QuicHttpFrameDecoder::StartDecodingHeadersPayload(
-    QuicHttpDecodeBuffer* db) {
-  RetainFlags(QuicHttpFrameFlag::QUIC_HTTP_END_STREAM |
-              QuicHttpFrameFlag::QUIC_HTTP_END_HEADERS |
-              QuicHttpFrameFlag::QUIC_HTTP_PADDED |
-              QuicHttpFrameFlag::QUIC_HTTP_PRIORITY);
-  return headers_payload_decoder_.StartDecodingPayload(&frame_decoder_state_,
-                                                       db);
-}
-QuicHttpDecodeStatus QuicHttpFrameDecoder::ResumeDecodingHeadersPayload(
-    QuicHttpDecodeBuffer* db) {
-  DCHECK_LE(frame_decoder_state_.remaining_payload_and_padding(),
-            frame_header().payload_length);
-  return headers_payload_decoder_.ResumeDecodingPayload(&frame_decoder_state_,
-                                                        db);
-}
-
-QuicHttpDecodeStatus QuicHttpFrameDecoder::StartDecodingPingPayload(
-    QuicHttpDecodeBuffer* db) {
-  RetainFlags(QuicHttpFrameFlag::QUIC_HTTP_ACK);
-  return ping_payload_decoder_.StartDecodingPayload(&frame_decoder_state_, db);
-}
-QuicHttpDecodeStatus QuicHttpFrameDecoder::ResumeDecodingPingPayload(
-    QuicHttpDecodeBuffer* db) {
-  // The frame is not paddable.
-  DCHECK_EQ(frame_decoder_state_.remaining_total_payload(),
-            frame_decoder_state_.remaining_payload());
-  return ping_payload_decoder_.ResumeDecodingPayload(&frame_decoder_state_, db);
-}
-
-QuicHttpDecodeStatus QuicHttpFrameDecoder::StartDecodingPriorityPayload(
-    QuicHttpDecodeBuffer* db) {
-  ClearFlags();
-  return priority_payload_decoder_.StartDecodingPayload(&frame_decoder_state_,
-                                                        db);
-}
-QuicHttpDecodeStatus QuicHttpFrameDecoder::ResumeDecodingPriorityPayload(
-    QuicHttpDecodeBuffer* db) {
-  // The frame is not paddable.
-  DCHECK_EQ(frame_decoder_state_.remaining_total_payload(),
-            frame_decoder_state_.remaining_payload());
-  return priority_payload_decoder_.ResumeDecodingPayload(&frame_decoder_state_,
-                                                         db);
-}
-
-QuicHttpDecodeStatus QuicHttpFrameDecoder::StartDecodingPushPromisePayload(
-    QuicHttpDecodeBuffer* db) {
-  RetainFlags(QuicHttpFrameFlag::QUIC_HTTP_END_HEADERS |
-              QuicHttpFrameFlag::QUIC_HTTP_PADDED);
-  return push_promise_payload_decoder_.StartDecodingPayload(
-      &frame_decoder_state_, db);
-}
-QuicHttpDecodeStatus QuicHttpFrameDecoder::ResumeDecodingPushPromisePayload(
-    QuicHttpDecodeBuffer* db) {
-  DCHECK_LE(frame_decoder_state_.remaining_payload_and_padding(),
-            frame_header().payload_length);
-  return push_promise_payload_decoder_.ResumeDecodingPayload(
-      &frame_decoder_state_, db);
-}
-
-QuicHttpDecodeStatus QuicHttpFrameDecoder::StartDecodingRstStreamPayload(
-    QuicHttpDecodeBuffer* db) {
-  ClearFlags();
-  return rst_stream_payload_decoder_.StartDecodingPayload(&frame_decoder_state_,
-                                                          db);
-}
-QuicHttpDecodeStatus QuicHttpFrameDecoder::ResumeDecodingRstStreamPayload(
-    QuicHttpDecodeBuffer* db) {
-  // The frame is not paddable.
-  DCHECK_EQ(frame_decoder_state_.remaining_total_payload(),
-            frame_decoder_state_.remaining_payload());
-  return rst_stream_payload_decoder_.ResumeDecodingPayload(
-      &frame_decoder_state_, db);
-}
-
-QuicHttpDecodeStatus QuicHttpFrameDecoder::StartDecodingSettingsPayload(
-    QuicHttpDecodeBuffer* db) {
-  RetainFlags(QuicHttpFrameFlag::QUIC_HTTP_ACK);
-  return settings_payload_decoder_.StartDecodingPayload(&frame_decoder_state_,
-                                                        db);
-}
-QuicHttpDecodeStatus QuicHttpFrameDecoder::ResumeDecodingSettingsPayload(
-    QuicHttpDecodeBuffer* db) {
-  // The frame is not paddable.
-  DCHECK_EQ(frame_decoder_state_.remaining_total_payload(),
-            frame_decoder_state_.remaining_payload());
-  return settings_payload_decoder_.ResumeDecodingPayload(&frame_decoder_state_,
-                                                         db);
-}
-
-QuicHttpDecodeStatus QuicHttpFrameDecoder::StartDecodingUnknownPayload(
-    QuicHttpDecodeBuffer* db) {
-  // We don't known what type of frame this is, so we don't know which flags
-  // are valid, so we don't touch them.
-  return unknown_payload_decoder_.StartDecodingPayload(&frame_decoder_state_,
-                                                       db);
-}
-QuicHttpDecodeStatus QuicHttpFrameDecoder::ResumeDecodingUnknownPayload(
-    QuicHttpDecodeBuffer* db) {
-  // We don't known what type of frame this is, so we treat it as not paddable.
-  DCHECK_EQ(frame_decoder_state_.remaining_total_payload(),
-            frame_decoder_state_.remaining_payload());
-  return unknown_payload_decoder_.ResumeDecodingPayload(&frame_decoder_state_,
-                                                        db);
-}
-
-QuicHttpDecodeStatus QuicHttpFrameDecoder::StartDecodingWindowUpdatePayload(
-    QuicHttpDecodeBuffer* db) {
-  ClearFlags();
-  return window_update_payload_decoder_.StartDecodingPayload(
-      &frame_decoder_state_, db);
-}
-QuicHttpDecodeStatus QuicHttpFrameDecoder::ResumeDecodingWindowUpdatePayload(
-    QuicHttpDecodeBuffer* db) {
-  // The frame is not paddable.
-  DCHECK_EQ(frame_decoder_state_.remaining_total_payload(),
-            frame_decoder_state_.remaining_payload());
-  return window_update_payload_decoder_.ResumeDecodingPayload(
-      &frame_decoder_state_, db);
-}
-
-QuicHttpDecodeStatus QuicHttpFrameDecoder::DiscardPayload(
-    QuicHttpDecodeBuffer* db) {
-  DVLOG(2) << "remaining_payload=" << frame_decoder_state_.remaining_payload_
-           << "; remaining_padding=" << frame_decoder_state_.remaining_padding_;
-  frame_decoder_state_.remaining_payload_ +=
-      frame_decoder_state_.remaining_padding_;
-  frame_decoder_state_.remaining_padding_ = 0;
-  const size_t avail = frame_decoder_state_.AvailablePayload(db);
-  DVLOG(2) << "avail=" << avail;
-  if (avail > 0) {
-    frame_decoder_state_.ConsumePayload(avail);
-    db->AdvanceCursor(avail);
-  }
-  if (frame_decoder_state_.remaining_payload_ == 0) {
-    state_ = State::kStartDecodingHeader;
-    return QuicHttpDecodeStatus::kDecodeDone;
-  }
-  return QuicHttpDecodeStatus::kDecodeInProgress;
-}
-
-}  // namespace quic
diff --git a/net/third_party/quic/http/decoder/quic_http_frame_decoder.h b/net/third_party/quic/http/decoder/quic_http_frame_decoder.h
deleted file mode 100644
index 84d512b..0000000
--- a/net/third_party/quic/http/decoder/quic_http_frame_decoder.h
+++ /dev/null
@@ -1,211 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_THIRD_PARTY_QUIC_HTTP_DECODER_QUIC_HTTP_FRAME_DECODER_H_
-#define NET_THIRD_PARTY_QUIC_HTTP_DECODER_QUIC_HTTP_FRAME_DECODER_H_
-
-// QuicHttpFrameDecoder decodes the available input until it reaches the end of
-// the input or it reaches the end of the first frame in the input.
-// Note that QuicHttpFrameDecoder does only minimal validation; for example,
-// stream ids are not checked, nor is the sequence of frames such as
-// CONTINUATION frame placement.
-//
-// QuicHttpFrameDecoder enters state kError once it has called the listener's
-// OnFrameSizeError or OnPaddingTooLong methods, and at this time has no
-// provision for leaving that state. While the HTTP/2 spec (RFC7540) allows
-// for some such errors to be considered as just stream errors in some cases,
-// this implementation treats them all as connection errors.
-
-#include <stddef.h>
-
-#include <cstdint>
-
-#include "base/logging.h"
-#include "base/macros.h"
-#include "net/third_party/quic/http/decoder/payload_decoders/quic_http_altsvc_payload_decoder.h"
-#include "net/third_party/quic/http/decoder/payload_decoders/quic_http_continuation_payload_decoder.h"
-#include "net/third_party/quic/http/decoder/payload_decoders/quic_http_data_payload_decoder.h"
-#include "net/third_party/quic/http/decoder/payload_decoders/quic_http_goaway_payload_decoder.h"
-#include "net/third_party/quic/http/decoder/payload_decoders/quic_http_headers_payload_decoder.h"
-#include "net/third_party/quic/http/decoder/payload_decoders/quic_http_ping_payload_decoder.h"
-#include "net/third_party/quic/http/decoder/payload_decoders/quic_http_priority_payload_decoder.h"
-#include "net/third_party/quic/http/decoder/payload_decoders/quic_http_push_promise_payload_decoder.h"
-#include "net/third_party/quic/http/decoder/payload_decoders/quic_http_rst_stream_payload_decoder.h"
-#include "net/third_party/quic/http/decoder/payload_decoders/quic_http_settings_payload_decoder.h"
-#include "net/third_party/quic/http/decoder/payload_decoders/quic_http_unknown_payload_decoder.h"
-#include "net/third_party/quic/http/decoder/payload_decoders/quic_http_window_update_payload_decoder.h"
-#include "net/third_party/quic/http/decoder/quic_http_decode_buffer.h"
-#include "net/third_party/quic/http/decoder/quic_http_decode_status.h"
-#include "net/third_party/quic/http/decoder/quic_http_frame_decoder_listener.h"
-#include "net/third_party/quic/http/decoder/quic_http_frame_decoder_state.h"
-#include "net/third_party/quic/http/quic_http_structures.h"
-#include "net/third_party/quic/platform/api/quic_export.h"
-
-namespace quic {
-namespace test {
-class QuicHttpFrameDecoderPeer;
-}  // namespace test
-
-class QUIC_EXPORT_PRIVATE QuicHttpFrameDecoder {
- public:
-  explicit QuicHttpFrameDecoder(QuicHttpFrameDecoderListener* listener);
-  QuicHttpFrameDecoder() : QuicHttpFrameDecoder(nullptr) {}
-
-  // The decoder will call the listener's methods as it decodes a frame.
-  void set_listener(QuicHttpFrameDecoderListener* listener);
-  QuicHttpFrameDecoderListener* listener() const;
-
-  // The decoder will reject frame's whose payload
-  // length field exceeds the maximum payload size.
-  void set_maximum_payload_size(size_t v) { maximum_payload_size_ = v; }
-  size_t maximum_payload_size() const { return maximum_payload_size_; }
-
-  // Decodes the input up to the next frame boundary (i.e. at most one frame).
-  //
-  // Returns kDecodeDone if it decodes the final byte of a frame, OR if there
-  // is no input and it is awaiting the start of a new frame (e.g. if this
-  // is the first call to DecodeFrame, or if the previous call returned
-  // kDecodeDone).
-  //
-  // Returns kDecodeInProgress if it decodes all of the decode buffer, but has
-  // not reached the end of the frame.
-  //
-  // Returns kDecodeError if the frame's padding or length wasn't valid (i.e. if
-  // the decoder called either the listener's OnPaddingTooLong or
-  // OnFrameSizeError method).
-  QuicHttpDecodeStatus DecodeFrame(QuicHttpDecodeBuffer* db);
-
-  //////////////////////////////////////////////////////////////////////////////
-  // Methods that support QuicHttpFrameDecoderAdapter.
-
-  // Is the remainder of the frame's payload being discarded?
-  bool IsDiscardingPayload() const { return state_ == State::kDiscardPayload; }
-
-  // Returns the number of bytes of the frame's payload that remain to be
-  // decoded, excluding any trailing padding. This method must only be called
-  // after the frame header has been decoded AND DecodeFrame has returned
-  // kDecodeInProgress.
-  size_t remaining_payload() const;
-
-  // Returns the number of bytes of trailing padding after the payload that
-  // remain to be decoded. This method must only be called if the frame type
-  // allows padding, and after the frame header has been decoded AND
-  // DecodeFrame has returned. Will return 0 if the Pad Length field has not
-  // yet been decoded.
-  uint32_t remaining_padding() const;
-
- private:
-  enum class State {
-    // Ready to start decoding a new frame's header.
-    kStartDecodingHeader,
-    // Was in state kStartDecodingHeader, but unable to read the entire frame
-    // header, so needs more input to complete decoding the header.
-    kResumeDecodingHeader,
-
-    // Have decoded the frame header, and started decoding the available bytes
-    // of the frame's payload, but need more bytes to finish the job.
-    kResumeDecodingPayload,
-
-    // Decoding of the most recently started frame resulted in an error:
-    // OnPaddingTooLong or OnFrameSizeError was called to indicate that the
-    // decoder detected a problem, or OnFrameHeader returned false, indicating
-    // that the listener detected a problem. Regardless of which, the decoder
-    // will stay in state kDiscardPayload until it has been passed the rest
-    // of the bytes of the frame's payload that it hasn't yet seen, after
-    // which it will be ready to decode another frame.
-    kDiscardPayload,
-  };
-
-  friend class test::QuicHttpFrameDecoderPeer;
-  friend std::ostream& operator<<(std::ostream& out, State v);
-
-  QuicHttpDecodeStatus StartDecodingPayload(QuicHttpDecodeBuffer* db);
-  QuicHttpDecodeStatus ResumeDecodingPayload(QuicHttpDecodeBuffer* db);
-  QuicHttpDecodeStatus DiscardPayload(QuicHttpDecodeBuffer* db);
-
-  const QuicHttpFrameHeader& frame_header() const {
-    return frame_decoder_state_.frame_header();
-  }
-
-  // Clear any of the flags in the frame header that aren't set in valid_flags.
-  void RetainFlags(uint8_t valid_flags);
-
-  // Clear all of the flags in the frame header; for use with frame types that
-  // don't define any flags, such as WINDOW_UPDATE.
-  void ClearFlags();
-
-  // These methods call the StartDecodingPayload() method of the frame type's
-  // payload decoder, after first clearing invalid flags in the header. The
-  // caller must ensure that the decode buffer does not extend beyond the
-  // end of the payload (handled by QuicHttpFrameDecoder::StartDecodingPayload).
-  QuicHttpDecodeStatus StartDecodingAltSvcPayload(QuicHttpDecodeBuffer* db);
-  QuicHttpDecodeStatus StartDecodingContinuationPayload(
-      QuicHttpDecodeBuffer* db);
-  QuicHttpDecodeStatus StartDecodingDataPayload(QuicHttpDecodeBuffer* db);
-  QuicHttpDecodeStatus StartDecodingGoAwayPayload(QuicHttpDecodeBuffer* db);
-  QuicHttpDecodeStatus StartDecodingHeadersPayload(QuicHttpDecodeBuffer* db);
-  QuicHttpDecodeStatus StartDecodingPingPayload(QuicHttpDecodeBuffer* db);
-  QuicHttpDecodeStatus StartDecodingPriorityPayload(QuicHttpDecodeBuffer* db);
-  QuicHttpDecodeStatus StartDecodingPushPromisePayload(
-      QuicHttpDecodeBuffer* db);
-  QuicHttpDecodeStatus StartDecodingRstStreamPayload(QuicHttpDecodeBuffer* db);
-  QuicHttpDecodeStatus StartDecodingSettingsPayload(QuicHttpDecodeBuffer* db);
-  QuicHttpDecodeStatus StartDecodingUnknownPayload(QuicHttpDecodeBuffer* db);
-  QuicHttpDecodeStatus StartDecodingWindowUpdatePayload(
-      QuicHttpDecodeBuffer* db);
-
-  // These methods call the ResumeDecodingPayload() method of the frame type's
-  // payload decoder; they are called only if the preceding call to the
-  // corresponding Start method (above) returned kDecodeInProgress, as did any
-  // subsequent calls to the resume method.
-  // Unlike the Start methods, the decode buffer may extend beyond the
-  // end of the payload, so the method will create a QuicHttpDecodeBufferSubset
-  // before calling the ResumeDecodingPayload method of the frame type's
-  // payload decoder.
-  QuicHttpDecodeStatus ResumeDecodingAltSvcPayload(QuicHttpDecodeBuffer* db);
-  QuicHttpDecodeStatus ResumeDecodingContinuationPayload(
-      QuicHttpDecodeBuffer* db);
-  QuicHttpDecodeStatus ResumeDecodingDataPayload(QuicHttpDecodeBuffer* db);
-  QuicHttpDecodeStatus ResumeDecodingGoAwayPayload(QuicHttpDecodeBuffer* db);
-  QuicHttpDecodeStatus ResumeDecodingHeadersPayload(QuicHttpDecodeBuffer* db);
-  QuicHttpDecodeStatus ResumeDecodingPingPayload(QuicHttpDecodeBuffer* db);
-  QuicHttpDecodeStatus ResumeDecodingPriorityPayload(QuicHttpDecodeBuffer* db);
-  QuicHttpDecodeStatus ResumeDecodingPushPromisePayload(
-      QuicHttpDecodeBuffer* db);
-  QuicHttpDecodeStatus ResumeDecodingRstStreamPayload(QuicHttpDecodeBuffer* db);
-  QuicHttpDecodeStatus ResumeDecodingSettingsPayload(QuicHttpDecodeBuffer* db);
-  QuicHttpDecodeStatus ResumeDecodingUnknownPayload(QuicHttpDecodeBuffer* db);
-  QuicHttpDecodeStatus ResumeDecodingWindowUpdatePayload(
-      QuicHttpDecodeBuffer* db);
-
-  QuicHttpFrameDecoderState frame_decoder_state_;
-
-  // We only need one payload decoder at a time, so they share the same storage.
-  union {
-    QuicHttpAltSvcQuicHttpPayloadDecoder altsvc_payload_decoder_;
-    QuicHttpContinuationQuicHttpPayloadDecoder continuation_payload_decoder_;
-    QuicHttpDataQuicHttpPayloadDecoder data_payload_decoder_;
-    QuicHttpGoAwayQuicHttpPayloadDecoder goaway_payload_decoder_;
-    QuicHttpHeadersQuicHttpPayloadDecoder headers_payload_decoder_;
-    QuicHttpPingQuicHttpPayloadDecoder ping_payload_decoder_;
-    QuicHttpPriorityQuicHttpPayloadDecoder priority_payload_decoder_;
-    QuicHttpPushPromiseQuicHttpPayloadDecoder push_promise_payload_decoder_;
-    QuicHttpRstStreamQuicHttpPayloadDecoder rst_stream_payload_decoder_;
-    QuicHttpQuicHttpSettingsQuicHttpPayloadDecoder settings_payload_decoder_;
-    QuicHttpUnknownQuicHttpPayloadDecoder unknown_payload_decoder_;
-    QuicHttpWindowUpdateQuicHttpPayloadDecoder window_update_payload_decoder_;
-  };
-
-  State state_;
-  size_t maximum_payload_size_;
-
-  // Listener used whenever caller passes nullptr to set_listener.
-  QuicHttpFrameDecoderNoOpListener no_op_listener_;
-
-  DISALLOW_COPY_AND_ASSIGN(QuicHttpFrameDecoder);
-};
-
-}  // namespace quic
-
-#endif  // NET_THIRD_PARTY_QUIC_HTTP_DECODER_QUIC_HTTP_FRAME_DECODER_H_
diff --git a/net/third_party/quic/http/decoder/quic_http_frame_decoder_adapter.cc b/net/third_party/quic/http/decoder/quic_http_frame_decoder_adapter.cc
deleted file mode 100644
index 53f1b88..0000000
--- a/net/third_party/quic/http/decoder/quic_http_frame_decoder_adapter.cc
+++ /dev/null
@@ -1,987 +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 "net/third_party/quic/http/decoder/quic_http_frame_decoder_adapter.h"
-
-// Logging policy: If an error in the input is detected, VLOG(n) is used so that
-// the option exists to debug the situation. Otherwise, this code mostly uses
-// DVLOG so that the logging does not slow down production code when things are
-// working OK.
-
-#include <stddef.h>
-
-#include <cstdint>
-#include <cstring>
-#include <utility>
-
-#include "base/logging.h"
-#include "net/third_party/quic/http/decoder/quic_http_decode_buffer.h"
-#include "net/third_party/quic/http/decoder/quic_http_decode_status.h"
-#include "net/third_party/quic/http/decoder/quic_http_frame_decoder.h"
-#include "net/third_party/quic/http/decoder/quic_http_frame_decoder_listener.h"
-#include "net/third_party/quic/http/quic_http_constants.h"
-#include "net/third_party/quic/http/quic_http_structures.h"
-#include "net/third_party/quic/platform/api/quic_flags.h"
-#include "net/third_party/quic/platform/api/quic_ptr_util.h"
-#include "net/third_party/quic/platform/api/quic_string_utils.h"
-#include "net/third_party/spdy/core/hpack/hpack_decoder_adapter.h"
-#include "net/third_party/spdy/core/hpack/hpack_header_table.h"
-#include "net/third_party/spdy/core/http2_frame_decoder_adapter.h"
-#include "net/third_party/spdy/core/spdy_alt_svc_wire_format.h"
-#include "net/third_party/spdy/core/spdy_bug_tracker.h"
-#include "net/third_party/spdy/core/spdy_header_block.h"
-#include "net/third_party/spdy/core/spdy_headers_handler_interface.h"
-#include "net/third_party/spdy/core/spdy_protocol.h"
-
-#if 0
-using ::spdy::ExtensionVisitorInterface;
-using ::spdy::HpackDecoderAdapter;
-using ::spdy::HpackHeaderTable;
-using ::spdy::ParseErrorCode;
-using ::spdy::ParseFrameType;
-using ::spdy::SpdyAltSvcWireFormat;
-using ::spdy::SpdyErrorCode;
-using ::spdy::SpdyFrameType;
-using ::spdy::SpdyFramerDebugVisitorInterface;
-using ::spdy::SpdyFramerVisitorInterface;
-using ::spdy::SpdyHeadersHandlerInterface;
-using ::SpdySettingsIds;
-#endif
-using base::nullopt;
-
-namespace quic {
-
-using SpdyFramerError = http2::Http2DecoderAdapter::SpdyFramerError;
-
-namespace {
-
-const bool kHasPriorityFields = true;
-const bool kNotHasPriorityFields = false;
-
-bool IsPaddable(QuicHttpFrameType type) {
-  return type == QuicHttpFrameType::DATA ||
-         type == QuicHttpFrameType::HEADERS ||
-         type == QuicHttpFrameType::PUSH_PROMISE;
-}
-
-spdy::SpdyFrameType ToSpdyFrameType(QuicHttpFrameType type) {
-  return spdy::ParseFrameType(static_cast<uint8_t>(type));
-}
-
-uint64_t ToSpdyPingId(const QuicHttpPingFields& ping) {
-  uint64_t v;
-  std::memcpy(&v, ping.opaque_bytes, QuicHttpPingFields::EncodedSize());
-  return base::NetToHost64(v);
-}
-
-// Overwrites the fields of the header with invalid values, for the purpose
-// of identifying reading of unset fields. Only takes effect for debug builds.
-// In Address Sanatizer builds, it also marks the fields as un-readable.
-void CorruptFrameHeader(QuicHttpFrameHeader* header) {
-#ifndef NDEBUG
-  // Beyond a valid payload length, which is 2^24 - 1.
-  header->payload_length = 0x1010dead;
-  // An unsupported frame type.
-  header->type = QuicHttpFrameType(0x80);
-  DCHECK(!IsSupportedQuicHttpFrameType(header->type));
-  // Frame flag bits that aren't used by any supported frame type.
-  header->flags = QuicHttpFrameFlag(0xd2);
-  // A stream id with the reserved high-bit (R in the RFC) set.
-  // 2129510127 when the high-bit is cleared.
-  header->stream_id = 0xfeedbeef;
-#endif
-}
-
-}  // namespace
-
-const char* QuicHttpDecoderAdapter::StateToString(int state) {
-  switch (state) {
-    case SPDY_ERROR:
-      return "ERROR";
-    case SPDY_FRAME_COMPLETE:
-      return "FRAME_COMPLETE";
-    case SPDY_READY_FOR_FRAME:
-      return "READY_FOR_FRAME";
-    case SPDY_READING_COMMON_HEADER:
-      return "READING_COMMON_HEADER";
-    case SPDY_CONTROL_FRAME_PAYLOAD:
-      return "CONTROL_FRAME_PAYLOAD";
-    case SPDY_READ_DATA_FRAME_PADDING_LENGTH:
-      return "SPDY_READ_DATA_FRAME_PADDING_LENGTH";
-    case SPDY_CONSUME_PADDING:
-      return "SPDY_CONSUME_PADDING";
-    case SPDY_IGNORE_REMAINING_PAYLOAD:
-      return "IGNORE_REMAINING_PAYLOAD";
-    case SPDY_FORWARD_STREAM_FRAME:
-      return "FORWARD_STREAM_FRAME";
-    case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK:
-      return "SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK";
-    case SPDY_CONTROL_FRAME_HEADER_BLOCK:
-      return "SPDY_CONTROL_FRAME_HEADER_BLOCK";
-    case SPDY_GOAWAY_FRAME_PAYLOAD:
-      return "SPDY_GOAWAY_FRAME_PAYLOAD";
-    case SPDY_SETTINGS_FRAME_HEADER:
-      return "SPDY_SETTINGS_FRAME_HEADER";
-    case SPDY_SETTINGS_FRAME_PAYLOAD:
-      return "SPDY_SETTINGS_FRAME_PAYLOAD";
-    case SPDY_ALTSVC_FRAME_PAYLOAD:
-      return "SPDY_ALTSVC_FRAME_PAYLOAD";
-  }
-  return "UNKNOWN_STATE";
-}
-
-QuicHttpDecoderAdapter::QuicHttpDecoderAdapter() {
-  DVLOG(1) << "QuicHttpDecoderAdapter ctor";
-  ResetInternal();
-}
-
-QuicHttpDecoderAdapter::~QuicHttpDecoderAdapter() {}
-
-void QuicHttpDecoderAdapter::set_visitor(
-    spdy::SpdyFramerVisitorInterface* visitor) {
-  visitor_ = visitor;
-}
-
-void QuicHttpDecoderAdapter::set_debug_visitor(
-    spdy::SpdyFramerDebugVisitorInterface* debug_visitor) {
-  debug_visitor_ = debug_visitor;
-}
-
-void QuicHttpDecoderAdapter::set_process_single_input_frame(bool v) {
-  process_single_input_frame_ = v;
-}
-
-void QuicHttpDecoderAdapter::set_extension_visitor(
-    spdy::ExtensionVisitorInterface* visitor) {
-  extension_ = visitor;
-}
-
-// Passes the call on to the HPQUIC_HTTP_ACK decoder.
-void QuicHttpDecoderAdapter::SetDecoderHeaderTableDebugVisitor(
-    std::unique_ptr<spdy::HpackHeaderTable::DebugVisitorInterface> visitor) {
-  GetHpackDecoder()->SetHeaderTableDebugVisitor(std::move(visitor));
-}
-
-size_t QuicHttpDecoderAdapter::ProcessInput(const char* data, size_t len) {
-  size_t limit = recv_frame_size_limit_;
-  frame_decoder_->set_maximum_payload_size(limit);
-
-  size_t total_processed = 0;
-  while (len > 0 && spdy_state_ != SPDY_ERROR) {
-    // Process one at a time so that we update the adapter's internal
-    // state appropriately.
-    const size_t processed = ProcessInputFrame(data, len);
-
-    // We had some data, and weren't in an error state, so should have
-    // processed/consumed at least one byte of it, even if we then ended up
-    // in an error state.
-    DCHECK(processed > 0) << "processed=" << processed
-                          << "   spdy_state_=" << spdy_state_
-                          << "   spdy_framer_error_=" << spdy_framer_error_;
-
-    data += processed;
-    len -= processed;
-    total_processed += processed;
-    if (process_single_input_frame() || processed == 0) {
-      break;
-    }
-  }
-  return total_processed;
-}
-
-void QuicHttpDecoderAdapter::Reset() {
-  ResetInternal();
-}
-
-QuicHttpDecoderAdapter::SpdyState QuicHttpDecoderAdapter::state() const {
-  return spdy_state_;
-}
-
-SpdyFramerError QuicHttpDecoderAdapter::spdy_framer_error() const {
-  return spdy_framer_error_;
-}
-
-bool QuicHttpDecoderAdapter::probable_http_response() const {
-  return latched_probable_http_response_;
-}
-
-// ===========================================================================
-// Implementations of the methods declared by QuicHttpFrameDecoderListener.
-
-// Called once the common frame header has been decoded for any frame.
-// This function is largely based on QuicHttpDecoderAdapter::ValidateFrameHeader
-// and some parts of QuicHttpDecoderAdapter::ProcessCommonHeader.
-bool QuicHttpDecoderAdapter::OnFrameHeader(const QuicHttpFrameHeader& header) {
-  DVLOG(1) << "OnFrameHeader: " << header;
-  decoded_frame_header_ = true;
-  if (!latched_probable_http_response_) {
-    latched_probable_http_response_ = header.IsProbableHttpResponse();
-  }
-  const uint8_t raw_frame_type = static_cast<uint8_t>(header.type);
-  visitor()->OnCommonHeader(header.stream_id, header.payload_length,
-                            raw_frame_type, header.flags);
-  if (has_expected_frame_type_ && header.type != expected_frame_type_) {
-    // Report an unexpected frame error and close the connection if we
-    // expect a known frame type (probably CONTINUATION) and receive an
-    // unknown frame.
-    VLOG(1) << "The framer was expecting to receive a " << expected_frame_type_
-            << " frame, but instead received an unknown frame of type "
-            << header.type;
-    SetSpdyErrorAndNotify(SpdyFramerError::SPDY_UNEXPECTED_FRAME);
-    return false;
-  }
-  if (!IsSupportedQuicHttpFrameType(header.type)) {
-    if (extension_ != nullptr) {
-      // Unknown frames will be passed to the registered extension.
-      return true;
-    }
-    // In HTTP2 we ignore unknown frame types for extensibility, as long as
-    // the rest of the control frame header is valid.
-    // We rely on the visitor to check validity of stream_id.
-    bool valid_stream =
-        visitor()->OnUnknownFrame(header.stream_id, raw_frame_type);
-    if (!valid_stream) {
-      // Report an invalid frame error if the stream_id is not valid.
-      VLOG(1) << "Unknown control frame type " << header.type
-              << " received on invalid stream " << header.stream_id;
-      SetSpdyErrorAndNotify(SpdyFramerError::SPDY_INVALID_CONTROL_FRAME);
-      return false;
-    } else {
-      DVLOG(1) << "Ignoring unknown frame type " << header.type;
-      return true;
-    }
-  }
-
-  spdy::SpdyFrameType frame_type = ToSpdyFrameType(header.type);
-  if (!IsValidHTTP2FrameStreamId(header.stream_id, frame_type)) {
-    VLOG(1) << "The framer received an invalid streamID of " << header.stream_id
-            << " for a frame of type " << header.type;
-    SetSpdyErrorAndNotify(SpdyFramerError::SPDY_INVALID_STREAM_ID);
-    return false;
-  }
-
-  if (has_expected_frame_type_ && header.type != expected_frame_type_) {
-    VLOG(1) << "Expected frame type " << expected_frame_type_ << ", not "
-            << header.type;
-    SetSpdyErrorAndNotify(SpdyFramerError::SPDY_UNEXPECTED_FRAME);
-    return false;
-  }
-
-  if (!has_expected_frame_type_ &&
-      header.type == QuicHttpFrameType::CONTINUATION) {
-    VLOG(1) << "Got CONTINUATION frame when not expected.";
-    SetSpdyErrorAndNotify(SpdyFramerError::SPDY_UNEXPECTED_FRAME);
-    return false;
-  }
-
-  if (header.type == QuicHttpFrameType::DATA) {
-    // For some reason spdy::SpdyFramer still rejects invalid DATA frame flags.
-    uint8_t valid_flags = QuicHttpFrameFlag::QUIC_HTTP_PADDED |
-                          QuicHttpFrameFlag::QUIC_HTTP_END_STREAM;
-    if (header.HasAnyFlags(~valid_flags)) {
-      SetSpdyErrorAndNotify(SpdyFramerError::SPDY_INVALID_DATA_FRAME_FLAGS);
-      return false;
-    }
-  }
-
-  return true;
-}
-
-void QuicHttpDecoderAdapter::OnDataStart(const QuicHttpFrameHeader& header) {
-  DVLOG(1) << "OnDataStart: " << header;
-
-  if (IsOkToStartFrame(header) && HasRequiredStreamId(header)) {
-    frame_header_ = header;
-    has_frame_header_ = true;
-    visitor()->OnDataFrameHeader(header.stream_id, header.payload_length,
-                                 header.IsEndStream());
-  }
-}
-
-void QuicHttpDecoderAdapter::OnDataPayload(const char* data, size_t len) {
-  DVLOG(1) << "OnDataPayload: len=" << len;
-  DCHECK(has_frame_header_);
-  DCHECK_EQ(frame_header_.type, QuicHttpFrameType::DATA);
-  visitor()->OnStreamFrameData(frame_header().stream_id, data, len);
-}
-
-void QuicHttpDecoderAdapter::OnDataEnd() {
-  DVLOG(1) << "OnDataEnd";
-  DCHECK(has_frame_header_);
-  DCHECK_EQ(frame_header_.type, QuicHttpFrameType::DATA);
-  if (frame_header().IsEndStream()) {
-    visitor()->OnStreamEnd(frame_header().stream_id);
-  }
-  opt_pad_length_ = nullopt;
-}
-
-void QuicHttpDecoderAdapter::OnHeadersStart(const QuicHttpFrameHeader& header) {
-  DVLOG(1) << "OnHeadersStart: " << header;
-  if (IsOkToStartFrame(header) && HasRequiredStreamId(header)) {
-    frame_header_ = header;
-    has_frame_header_ = true;
-    if (header.HasPriority()) {
-      // Once we've got the priority fields, then we can report the arrival
-      // of this HEADERS frame.
-      on_headers_called_ = false;
-      return;
-    }
-    on_headers_called_ = true;
-    ReportReceiveCompressedFrame(header);
-    visitor()->OnHeaders(header.stream_id, kNotHasPriorityFields,
-                         0,      // priority
-                         0,      // parent_stream_id
-                         false,  // exclusive
-                         header.IsEndStream(), header.IsEndHeaders());
-    CommonStartHpackBlock();
-  }
-}
-
-void QuicHttpDecoderAdapter::OnHeadersPriority(
-    const QuicHttpPriorityFields& priority) {
-  DVLOG(1) << "OnHeadersPriority: " << priority;
-  DCHECK(has_frame_header_);
-  DCHECK_EQ(frame_type(), QuicHttpFrameType::HEADERS) << frame_header_;
-  DCHECK(frame_header_.HasPriority());
-  DCHECK(!on_headers_called_);
-  on_headers_called_ = true;
-  ReportReceiveCompressedFrame(frame_header_);
-  visitor()->OnHeaders(frame_header_.stream_id, kHasPriorityFields,
-                       priority.weight, priority.stream_dependency,
-                       priority.is_exclusive, frame_header_.IsEndStream(),
-                       frame_header_.IsEndHeaders());
-  CommonStartHpackBlock();
-}
-
-void QuicHttpDecoderAdapter::OnHpackFragment(const char* data, size_t len) {
-  DVLOG(1) << "OnHpackFragment: len=" << len;
-  on_hpack_fragment_called_ = true;
-  if (!GetHpackDecoder()->HandleControlFrameHeadersData(data, len)) {
-    SetSpdyErrorAndNotify(SpdyFramerError::SPDY_DECOMPRESS_FAILURE);
-    return;
-  }
-}
-
-void QuicHttpDecoderAdapter::OnHeadersEnd() {
-  DVLOG(1) << "OnHeadersEnd";
-  CommonHpackFragmentEnd();
-  opt_pad_length_ = nullopt;
-}
-
-void QuicHttpDecoderAdapter::OnPriorityFrame(
-    const QuicHttpFrameHeader& header,
-    const QuicHttpPriorityFields& priority) {
-  DVLOG(1) << "OnPriorityFrame: " << header << "; priority: " << priority;
-  if (IsOkToStartFrame(header) && HasRequiredStreamId(header)) {
-    visitor()->OnPriority(header.stream_id, priority.stream_dependency,
-                          priority.weight, priority.is_exclusive);
-  }
-}
-
-void QuicHttpDecoderAdapter::OnContinuationStart(
-    const QuicHttpFrameHeader& header) {
-  DVLOG(1) << "OnContinuationStart: " << header;
-  if (IsOkToStartFrame(header) && HasRequiredStreamId(header)) {
-    DCHECK(has_hpack_first_frame_header_);
-    if (header.stream_id != hpack_first_frame_header_.stream_id) {
-      SetSpdyErrorAndNotify(SpdyFramerError::SPDY_UNEXPECTED_FRAME);
-      return;
-    }
-    frame_header_ = header;
-    has_frame_header_ = true;
-    ReportReceiveCompressedFrame(header);
-    visitor()->OnContinuation(header.stream_id, header.IsEndHeaders());
-  }
-}
-
-void QuicHttpDecoderAdapter::OnContinuationEnd() {
-  DVLOG(1) << "OnContinuationEnd";
-  CommonHpackFragmentEnd();
-}
-
-void QuicHttpDecoderAdapter::OnPadLength(size_t trailing_length) {
-  DVLOG(1) << "OnPadLength: " << trailing_length;
-  opt_pad_length_ = trailing_length;
-  DCHECK_LT(trailing_length, 256u);
-  if (frame_header_.type == QuicHttpFrameType::DATA) {
-    visitor()->OnStreamPadLength(stream_id(), trailing_length);
-  }
-}
-
-void QuicHttpDecoderAdapter::OnPadding(const char* padding,
-                                       size_t skipped_length) {
-  DVLOG(1) << "OnPadding: " << skipped_length;
-  if (frame_header_.type == QuicHttpFrameType::DATA) {
-    visitor()->OnStreamPadding(stream_id(), skipped_length);
-  } else {
-    MaybeAnnounceEmptyFirstHpackFragment();
-  }
-}
-
-void QuicHttpDecoderAdapter::OnRstStream(const QuicHttpFrameHeader& header,
-                                         QuicHttpErrorCode http2_error_code) {
-  DVLOG(1) << "OnRstStream: " << header << "; code=" << http2_error_code;
-  if (IsOkToStartFrame(header) && HasRequiredStreamId(header)) {
-    spdy::SpdyErrorCode error_code =
-        spdy::ParseErrorCode(static_cast<uint32_t>(http2_error_code));
-    visitor()->OnRstStream(header.stream_id, error_code);
-  }
-}
-
-void QuicHttpDecoderAdapter::OnSettingsStart(
-    const QuicHttpFrameHeader& header) {
-  DVLOG(1) << "OnSettingsStart: " << header;
-  if (IsOkToStartFrame(header) && HasRequiredStreamIdZero(header)) {
-    frame_header_ = header;
-    has_frame_header_ = true;
-    visitor()->OnSettings();
-  }
-}
-
-void QuicHttpDecoderAdapter::OnSetting(
-    const QuicHttpSettingFields& setting_fields) {
-  DVLOG(1) << "OnSetting: " << setting_fields;
-  const uint16_t parameter = static_cast<uint16_t>(setting_fields.parameter);
-  spdy::SpdyKnownSettingsId setting_id;
-  if (!ParseSettingsId(parameter, &setting_id)) {
-    if (extension_ == nullptr) {
-      DVLOG(1) << "Ignoring unknown setting id: " << setting_fields;
-    } else {
-      extension_->OnSetting(parameter, setting_fields.value);
-    }
-    return;
-  }
-  // TODO(quic): Consider whether to add support for handling unknown SETTINGS
-  //     IDs, which currently cause a connection close.
-  visitor()->OnSetting(setting_id, setting_fields.value);
-}
-
-void QuicHttpDecoderAdapter::OnSettingsEnd() {
-  DVLOG(1) << "OnSettingsEnd";
-  visitor()->OnSettingsEnd();
-}
-
-void QuicHttpDecoderAdapter::OnSettingsAck(const QuicHttpFrameHeader& header) {
-  DVLOG(1) << "OnSettingsAck: " << header;
-  if (IsOkToStartFrame(header) && HasRequiredStreamIdZero(header)) {
-    visitor()->OnSettingsAck();
-  }
-}
-
-void QuicHttpDecoderAdapter::OnPushPromiseStart(
-    const QuicHttpFrameHeader& header,
-    const QuicHttpPushPromiseFields& promise,
-    size_t total_padding_length) {
-  DVLOG(1) << "OnPushPromiseStart: " << header << "; promise: " << promise
-           << "; total_padding_length: " << total_padding_length;
-  if (IsOkToStartFrame(header) && HasRequiredStreamId(header)) {
-    if (promise.promised_stream_id == 0) {
-      SetSpdyErrorAndNotify(SpdyFramerError::SPDY_INVALID_CONTROL_FRAME);
-      return;
-    }
-    frame_header_ = header;
-    has_frame_header_ = true;
-    ReportReceiveCompressedFrame(header);
-    visitor()->OnPushPromise(header.stream_id, promise.promised_stream_id,
-                             header.IsEndHeaders());
-    CommonStartHpackBlock();
-  }
-}
-
-void QuicHttpDecoderAdapter::OnPushPromiseEnd() {
-  DVLOG(1) << "OnPushPromiseEnd";
-  CommonHpackFragmentEnd();
-  opt_pad_length_ = nullopt;
-}
-
-void QuicHttpDecoderAdapter::OnPing(const QuicHttpFrameHeader& header,
-                                    const QuicHttpPingFields& ping) {
-  DVLOG(1) << "OnPing: " << header << "; ping: " << ping;
-  if (IsOkToStartFrame(header) && HasRequiredStreamIdZero(header)) {
-    visitor()->OnPing(ToSpdyPingId(ping), false);
-  }
-}
-
-void QuicHttpDecoderAdapter::OnPingAck(const QuicHttpFrameHeader& header,
-                                       const QuicHttpPingFields& ping) {
-  DVLOG(1) << "OnPingAck: " << header << "; ping: " << ping;
-  if (IsOkToStartFrame(header) && HasRequiredStreamIdZero(header)) {
-    visitor()->OnPing(ToSpdyPingId(ping), true);
-  }
-}
-
-void QuicHttpDecoderAdapter::OnGoAwayStart(const QuicHttpFrameHeader& header,
-                                           const QuicHttpGoAwayFields& goaway) {
-  DVLOG(1) << "OnGoAwayStart: " << header << "; goaway: " << goaway;
-  if (IsOkToStartFrame(header) && HasRequiredStreamIdZero(header)) {
-    frame_header_ = header;
-    has_frame_header_ = true;
-    spdy::SpdyErrorCode error_code =
-        spdy::ParseErrorCode(static_cast<uint32_t>(goaway.error_code));
-    visitor()->OnGoAway(goaway.last_stream_id, error_code);
-  }
-}
-
-void QuicHttpDecoderAdapter::OnGoAwayOpaqueData(const char* data, size_t len) {
-  DVLOG(1) << "OnGoAwayOpaqueData: len=" << len;
-  visitor()->OnGoAwayFrameData(data, len);
-}
-
-void QuicHttpDecoderAdapter::OnGoAwayEnd() {
-  DVLOG(1) << "OnGoAwayEnd";
-  visitor()->OnGoAwayFrameData(nullptr, 0);
-}
-
-void QuicHttpDecoderAdapter::OnWindowUpdate(const QuicHttpFrameHeader& header,
-                                            uint32_t increment) {
-  DVLOG(1) << "OnWindowUpdate: " << header << "; increment=" << increment;
-  if (IsOkToStartFrame(header)) {
-    visitor()->OnWindowUpdate(header.stream_id, increment);
-  }
-}
-
-// Per RFC7838, an ALTSVC frame on stream 0 with origin_length == 0, or one on
-// a stream other than stream 0 with origin_length != 0 MUST be ignored.  All
-// frames are decoded by QuicHttpDecoderAdapter, and it is left to the consumer
-// (listener) to implement this behavior.
-void QuicHttpDecoderAdapter::OnAltSvcStart(const QuicHttpFrameHeader& header,
-                                           size_t origin_length,
-                                           size_t value_length) {
-  DVLOG(1) << "OnAltSvcStart: " << header
-           << "; origin_length: " << origin_length
-           << "; value_length: " << value_length;
-  if (!IsOkToStartFrame(header)) {
-    return;
-  }
-  frame_header_ = header;
-  has_frame_header_ = true;
-  alt_svc_origin_.clear();
-  alt_svc_value_.clear();
-}
-
-void QuicHttpDecoderAdapter::OnAltSvcOriginData(const char* data, size_t len) {
-  DVLOG(1) << "OnAltSvcOriginData: len=" << len;
-  alt_svc_origin_.append(data, len);
-}
-
-// Called when decoding the Alt-Svc-Field-Value of an ALTSVC;
-// the field is uninterpreted.
-void QuicHttpDecoderAdapter::OnAltSvcValueData(const char* data, size_t len) {
-  DVLOG(1) << "OnAltSvcValueData: len=" << len;
-  alt_svc_value_.append(data, len);
-}
-
-void QuicHttpDecoderAdapter::OnAltSvcEnd() {
-  DVLOG(1) << "OnAltSvcEnd: origin.size(): " << alt_svc_origin_.size()
-           << "; value.size(): " << alt_svc_value_.size();
-  spdy::SpdyAltSvcWireFormat::AlternativeServiceVector altsvc_vector;
-  if (!spdy::SpdyAltSvcWireFormat::ParseHeaderFieldValue(alt_svc_value_,
-                                                         &altsvc_vector)) {
-    DLOG(ERROR) << "spdy::SpdyAltSvcWireFormat::ParseHeaderFieldValue failed.";
-    SetSpdyErrorAndNotify(SpdyFramerError::SPDY_INVALID_CONTROL_FRAME);
-    return;
-  }
-  visitor()->OnAltSvc(frame_header_.stream_id, alt_svc_origin_, altsvc_vector);
-  // We assume that ALTSVC frames are rare, so get rid of the storage.
-  alt_svc_origin_.clear();
-  alt_svc_origin_.shrink_to_fit();
-  alt_svc_value_.clear();
-  alt_svc_value_.shrink_to_fit();
-}
-
-// Except for BLOCKED frames, all other unknown frames are either dropped or
-// passed to a registered extension.
-void QuicHttpDecoderAdapter::OnUnknownStart(const QuicHttpFrameHeader& header) {
-  DVLOG(1) << "OnUnknownStart: " << header;
-  if (IsOkToStartFrame(header)) {
-    if (extension_ != nullptr) {
-      const uint8_t type = static_cast<uint8_t>(header.type);
-      const uint8_t flags = static_cast<uint8_t>(header.flags);
-      handling_extension_payload_ = extension_->OnFrameHeader(
-          header.stream_id, header.payload_length, type, flags);
-    }
-  }
-}
-
-void QuicHttpDecoderAdapter::OnUnknownPayload(const char* data, size_t len) {
-  if (handling_extension_payload_) {
-    extension_->OnFramePayload(data, len);
-  } else {
-    DVLOG(1) << "OnUnknownPayload: len=" << len;
-  }
-}
-
-void QuicHttpDecoderAdapter::OnUnknownEnd() {
-  DVLOG(1) << "OnUnknownEnd";
-  handling_extension_payload_ = false;
-}
-
-void QuicHttpDecoderAdapter::OnPaddingTooLong(const QuicHttpFrameHeader& header,
-                                              size_t missing_length) {
-  DVLOG(1) << "OnPaddingTooLong: " << header
-           << "; missing_length: " << missing_length;
-  if (header.type == QuicHttpFrameType::DATA) {
-    if (header.payload_length == 0) {
-      DCHECK_EQ(1u, missing_length);
-      SetSpdyErrorAndNotify(SpdyFramerError::SPDY_INVALID_DATA_FRAME_FLAGS);
-      return;
-    }
-    visitor()->OnStreamPadding(header.stream_id, 1);
-  }
-  SetSpdyErrorAndNotify(SpdyFramerError::SPDY_INVALID_PADDING);
-}
-
-void QuicHttpDecoderAdapter::OnFrameSizeError(
-    const QuicHttpFrameHeader& header) {
-  DVLOG(1) << "OnFrameSizeError: " << header;
-  size_t recv_limit = recv_frame_size_limit_;
-  if (header.payload_length > recv_limit) {
-    SetSpdyErrorAndNotify(SpdyFramerError::SPDY_OVERSIZED_PAYLOAD);
-    return;
-  }
-  if (header.type != QuicHttpFrameType::DATA &&
-      header.payload_length > recv_limit) {
-    SetSpdyErrorAndNotify(SpdyFramerError::SPDY_CONTROL_PAYLOAD_TOO_LARGE);
-    return;
-  }
-  switch (header.type) {
-    case QuicHttpFrameType::GOAWAY:
-    case QuicHttpFrameType::ALTSVC:
-      SetSpdyErrorAndNotify(SpdyFramerError::SPDY_INVALID_CONTROL_FRAME);
-      break;
-    default:
-      SetSpdyErrorAndNotify(SpdyFramerError::SPDY_INVALID_CONTROL_FRAME_SIZE);
-  }
-}
-
-// Decodes the input up to the next frame boundary (i.e. at most one frame),
-// stopping early if an error is detected.
-size_t QuicHttpDecoderAdapter::ProcessInputFrame(const char* data, size_t len) {
-  DCHECK_NE(spdy_state_, SpdyState::SPDY_ERROR);
-  QuicHttpDecodeBuffer db(data, len);
-  QuicHttpDecodeStatus status = frame_decoder_->DecodeFrame(&db);
-  if (spdy_state_ != SpdyState::SPDY_ERROR) {
-    DetermineSpdyState(status);
-  } else {
-    VLOG(1) << "ProcessInputFrame spdy_framer_error_="
-            << http2::Http2DecoderAdapter::SpdyFramerErrorToString(
-                   spdy_framer_error_);
-    if (spdy_framer_error_ == SpdyFramerError::SPDY_INVALID_PADDING &&
-        has_frame_header_ && frame_type() != QuicHttpFrameType::DATA) {
-      // spdy_framer_test checks that all of the available frame payload
-      // has been consumed, so do that.
-      size_t total = remaining_total_payload();
-      if (total <= frame_header().payload_length) {
-        size_t avail = db.MinLengthRemaining(total);
-        VLOG(1) << "Skipping past " << avail << " bytes, of " << total
-                << " total remaining in the frame's payload.";
-        db.AdvanceCursor(avail);
-      } else {
-        SPDY_BUG << "Total remaining (" << total
-                 << ") should not be greater than the payload length; "
-                 << frame_header();
-      }
-    }
-  }
-  return db.Offset();
-}
-
-// After decoding, determine the next SpdyState. Only called if the current
-// state is NOT SpdyState::SPDY_ERROR (i.e. if none of the callback methods
-// detected an error condition), because otherwise we assume that the callback
-// method has set spdy_framer_error_ appropriately.
-void QuicHttpDecoderAdapter::DetermineSpdyState(QuicHttpDecodeStatus status) {
-  DCHECK_EQ(spdy_framer_error_, SpdyFramerError::SPDY_NO_ERROR);
-  DCHECK(!HasError()) << spdy_framer_error_;
-  switch (status) {
-    case QuicHttpDecodeStatus::kDecodeDone:
-      DVLOG(1) << "ProcessInputFrame -> QuicHttpDecodeStatus::kDecodeDone";
-      ResetBetweenFrames();
-      break;
-    case QuicHttpDecodeStatus::kDecodeInProgress:
-      DVLOG(1)
-          << "ProcessInputFrame -> QuicHttpDecodeStatus::kDecodeInProgress";
-      if (decoded_frame_header_) {
-        if (IsDiscardingPayload()) {
-          set_spdy_state(SpdyState::SPDY_IGNORE_REMAINING_PAYLOAD);
-        } else if (has_frame_header_ &&
-                   frame_type() == QuicHttpFrameType::DATA) {
-          if (IsReadingPaddingLength()) {
-            set_spdy_state(SpdyState::SPDY_READ_DATA_FRAME_PADDING_LENGTH);
-          } else if (IsSkippingPadding()) {
-            set_spdy_state(SpdyState::SPDY_CONSUME_PADDING);
-          } else {
-            set_spdy_state(SpdyState::SPDY_FORWARD_STREAM_FRAME);
-          }
-        } else {
-          set_spdy_state(SpdyState::SPDY_CONTROL_FRAME_PAYLOAD);
-        }
-      } else {
-        set_spdy_state(SpdyState::SPDY_READING_COMMON_HEADER);
-      }
-      break;
-    case QuicHttpDecodeStatus::kDecodeError:
-      VLOG(1) << "ProcessInputFrame -> QuicHttpDecodeStatus::kDecodeError";
-      if (IsDiscardingPayload()) {
-        if (remaining_total_payload() == 0) {
-          // Push the QuicHttpFrameDecoder out of state kDiscardPayload now
-          // since doing so requires no input.
-          QuicHttpDecodeBuffer tmp("", 0);
-          QuicHttpDecodeStatus status = frame_decoder_->DecodeFrame(&tmp);
-          if (status != QuicHttpDecodeStatus::kDecodeDone) {
-            SPDY_BUG << "Expected to be done decoding the frame, not "
-                     << status;
-            SetSpdyErrorAndNotify(SpdyFramerError::SPDY_INTERNAL_FRAMER_ERROR);
-          } else if (spdy_framer_error_ != SpdyFramerError::SPDY_NO_ERROR) {
-            SPDY_BUG << "Expected to have no error, not "
-                     << http2::Http2DecoderAdapter::SpdyFramerErrorToString(
-                            spdy_framer_error_);
-          } else {
-            ResetBetweenFrames();
-          }
-        } else {
-          set_spdy_state(SpdyState::SPDY_IGNORE_REMAINING_PAYLOAD);
-        }
-      } else {
-        SetSpdyErrorAndNotify(SpdyFramerError::SPDY_INVALID_CONTROL_FRAME);
-      }
-      break;
-  }
-}
-
-void QuicHttpDecoderAdapter::ResetBetweenFrames() {
-  CorruptFrameHeader(&frame_header_);
-  decoded_frame_header_ = false;
-  has_frame_header_ = false;
-  set_spdy_state(SpdyState::SPDY_READY_FOR_FRAME);
-}
-
-// ResetInternal is called from the constructor, and during tests, but not
-// otherwise (i.e. not between every frame).
-void QuicHttpDecoderAdapter::ResetInternal() {
-  set_spdy_state(SpdyState::SPDY_READY_FOR_FRAME);
-  spdy_framer_error_ = SpdyFramerError::SPDY_NO_ERROR;
-
-  decoded_frame_header_ = false;
-  has_frame_header_ = false;
-  on_headers_called_ = false;
-  on_hpack_fragment_called_ = false;
-  latched_probable_http_response_ = false;
-  has_expected_frame_type_ = false;
-
-  CorruptFrameHeader(&frame_header_);
-  CorruptFrameHeader(&hpack_first_frame_header_);
-
-  frame_decoder_ = QuicMakeUnique<QuicHttpFrameDecoder>(this);
-  hpack_decoder_ = nullptr;
-}
-
-void QuicHttpDecoderAdapter::set_spdy_state(SpdyState v) {
-  DVLOG(2) << "set_spdy_state(" << StateToString(v) << ")";
-  spdy_state_ = v;
-}
-
-void QuicHttpDecoderAdapter::SetSpdyErrorAndNotify(SpdyFramerError error) {
-  if (HasError()) {
-    DCHECK_EQ(spdy_state_, SpdyState::SPDY_ERROR);
-  } else {
-    VLOG(2) << "SetSpdyErrorAndNotify("
-            << http2::Http2DecoderAdapter::SpdyFramerErrorToString(error)
-            << ")";
-    DCHECK_NE(error, SpdyFramerError::SPDY_NO_ERROR);
-    spdy_framer_error_ = error;
-    set_spdy_state(SpdyState::SPDY_ERROR);
-    frame_decoder_->set_listener(&no_op_listener_);
-    visitor()->OnError(error);
-  }
-}
-
-bool QuicHttpDecoderAdapter::HasError() const {
-  if (spdy_state_ == SpdyState::SPDY_ERROR) {
-    DCHECK_NE(spdy_framer_error(), SpdyFramerError::SPDY_NO_ERROR);
-    return true;
-  } else {
-    DCHECK_EQ(spdy_framer_error(), SpdyFramerError::SPDY_NO_ERROR);
-    return false;
-  }
-}
-
-const QuicHttpFrameHeader& QuicHttpDecoderAdapter::frame_header() const {
-  DCHECK(has_frame_header_);
-  return frame_header_;
-}
-
-uint32_t QuicHttpDecoderAdapter::stream_id() const {
-  return frame_header().stream_id;
-}
-
-QuicHttpFrameType QuicHttpDecoderAdapter::frame_type() const {
-  return frame_header().type;
-}
-
-size_t QuicHttpDecoderAdapter::remaining_total_payload() const {
-  DCHECK(has_frame_header_);
-  size_t remaining = frame_decoder_->remaining_payload();
-  if (IsPaddable(frame_type()) && frame_header_.IsPadded()) {
-    remaining += frame_decoder_->remaining_padding();
-  }
-  return remaining;
-}
-
-bool QuicHttpDecoderAdapter::IsReadingPaddingLength() {
-  bool result = frame_header_.IsPadded() && !opt_pad_length_;
-  DVLOG(2) << "QuicHttpDecoderAdapter::IsReadingPaddingLength: " << result;
-  return result;
-}
-bool QuicHttpDecoderAdapter::IsSkippingPadding() {
-  bool result = frame_header_.IsPadded() && opt_pad_length_ &&
-                frame_decoder_->remaining_payload() == 0 &&
-                frame_decoder_->remaining_padding() > 0;
-  DVLOG(2) << "QuicHttpDecoderAdapter::IsSkippingPadding: " << result;
-  return result;
-}
-bool QuicHttpDecoderAdapter::IsDiscardingPayload() {
-  bool result = decoded_frame_header_ && frame_decoder_->IsDiscardingPayload();
-  DVLOG(2) << "QuicHttpDecoderAdapter::IsDiscardingPayload: " << result;
-  return result;
-}
-// Called from OnXyz or OnXyzStart methods to decide whether it is OK to
-// handle the callback.
-bool QuicHttpDecoderAdapter::IsOkToStartFrame(
-    const QuicHttpFrameHeader& header) {
-  DVLOG(3) << "IsOkToStartFrame";
-  if (HasError()) {
-    VLOG(2) << "HasError()";
-    return false;
-  }
-  DCHECK(!has_frame_header_);
-  if (has_expected_frame_type_ && header.type != expected_frame_type_) {
-    VLOG(1) << "Expected frame type " << expected_frame_type_ << ", not "
-            << header.type;
-    SetSpdyErrorAndNotify(SpdyFramerError::SPDY_UNEXPECTED_FRAME);
-    return false;
-  }
-
-  return true;
-}
-
-bool QuicHttpDecoderAdapter::HasRequiredStreamId(uint32_t stream_id) {
-  DVLOG(3) << "HasRequiredStreamId: " << stream_id;
-  if (HasError()) {
-    VLOG(2) << "HasError()";
-    return false;
-  }
-  if (stream_id != 0) {
-    return true;
-  }
-  VLOG(1) << "Stream Id is required, but zero provided";
-  SetSpdyErrorAndNotify(SpdyFramerError::SPDY_INVALID_STREAM_ID);
-  return false;
-}
-
-bool QuicHttpDecoderAdapter::HasRequiredStreamId(
-    const QuicHttpFrameHeader& header) {
-  return HasRequiredStreamId(header.stream_id);
-}
-
-bool QuicHttpDecoderAdapter::HasRequiredStreamIdZero(uint32_t stream_id) {
-  DVLOG(3) << "HasRequiredStreamIdZero: " << stream_id;
-  if (HasError()) {
-    VLOG(2) << "HasError()";
-    return false;
-  }
-  if (stream_id == 0) {
-    return true;
-  }
-  VLOG(1) << "Stream Id was not zero, as required: " << stream_id;
-  SetSpdyErrorAndNotify(SpdyFramerError::SPDY_INVALID_STREAM_ID);
-  return false;
-}
-
-bool QuicHttpDecoderAdapter::HasRequiredStreamIdZero(
-    const QuicHttpFrameHeader& header) {
-  return HasRequiredStreamIdZero(header.stream_id);
-}
-
-void QuicHttpDecoderAdapter::ReportReceiveCompressedFrame(
-    const QuicHttpFrameHeader& header) {
-  if (debug_visitor() != nullptr) {
-    size_t total = header.payload_length + QuicHttpFrameHeader::EncodedSize();
-    debug_visitor()->OnReceiveCompressedFrame(
-        header.stream_id, ToSpdyFrameType(header.type), total);
-  }
-}
-
-spdy::HpackDecoderAdapter* QuicHttpDecoderAdapter::GetHpackDecoder() {
-  if (hpack_decoder_ == nullptr) {
-    hpack_decoder_ = spdy::SpdyMakeUnique<spdy::HpackDecoderAdapter>();
-  }
-  return hpack_decoder_.get();
-}
-
-void QuicHttpDecoderAdapter::CommonStartHpackBlock() {
-  DVLOG(1) << "CommonStartHpackBlock";
-  DCHECK(!has_hpack_first_frame_header_);
-  if (!frame_header_.IsEndHeaders()) {
-    hpack_first_frame_header_ = frame_header_;
-    has_hpack_first_frame_header_ = true;
-  } else {
-    CorruptFrameHeader(&hpack_first_frame_header_);
-  }
-  on_hpack_fragment_called_ = false;
-  spdy::SpdyHeadersHandlerInterface* handler =
-      visitor()->OnHeaderFrameStart(stream_id());
-  if (handler == nullptr) {
-    SPDY_BUG << "visitor_->OnHeaderFrameStart returned nullptr";
-    SetSpdyErrorAndNotify(SpdyFramerError::SPDY_INTERNAL_FRAMER_ERROR);
-    return;
-  }
-  GetHpackDecoder()->HandleControlFrameHeadersStart(handler);
-}
-
-// spdy::SpdyFramer calls HandleControlFrameHeadersData even if there are zero
-// fragment bytes in the first frame, so do the same.
-void QuicHttpDecoderAdapter::MaybeAnnounceEmptyFirstHpackFragment() {
-  if (!on_hpack_fragment_called_) {
-    OnHpackFragment(nullptr, 0);
-    DCHECK(on_hpack_fragment_called_);
-  }
-}
-
-void QuicHttpDecoderAdapter::CommonHpackFragmentEnd() {
-  DVLOG(1) << "CommonHpackFragmentEnd: stream_id=" << stream_id();
-  if (HasError()) {
-    VLOG(1) << "HasError(), returning";
-    return;
-  }
-  DCHECK(has_frame_header_);
-  MaybeAnnounceEmptyFirstHpackFragment();
-  if (frame_header_.IsEndHeaders()) {
-    DCHECK_EQ(has_hpack_first_frame_header_,
-              frame_type() == QuicHttpFrameType::CONTINUATION)
-        << frame_header();
-    has_expected_frame_type_ = false;
-    if (GetHpackDecoder()->HandleControlFrameHeadersComplete(nullptr)) {
-      visitor()->OnHeaderFrameEnd(stream_id());
-    } else {
-      SetSpdyErrorAndNotify(SpdyFramerError::SPDY_DECOMPRESS_FAILURE);
-      return;
-    }
-    const QuicHttpFrameHeader& first =
-        frame_type() == QuicHttpFrameType::CONTINUATION
-            ? hpack_first_frame_header_
-            : frame_header_;
-    if (first.type == QuicHttpFrameType::HEADERS && first.IsEndStream()) {
-      visitor()->OnStreamEnd(first.stream_id);
-    }
-    has_hpack_first_frame_header_ = false;
-    CorruptFrameHeader(&hpack_first_frame_header_);
-  } else {
-    DCHECK(has_hpack_first_frame_header_);
-    has_expected_frame_type_ = true;
-    expected_frame_type_ = QuicHttpFrameType::CONTINUATION;
-  }
-}
-
-}  // namespace quic
diff --git a/net/third_party/quic/http/decoder/quic_http_frame_decoder_adapter.h b/net/third_party/quic/http/decoder/quic_http_frame_decoder_adapter.h
deleted file mode 100644
index ab40c42..0000000
--- a/net/third_party/quic/http/decoder/quic_http_frame_decoder_adapter.h
+++ /dev/null
@@ -1,299 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_THIRD_PARTY_QUIC_HTTP_DECODER_QUIC_HTTP_FRAME_DECODER_ADAPTER_H_
-#define NET_THIRD_PARTY_QUIC_HTTP_DECODER_QUIC_HTTP_FRAME_DECODER_ADAPTER_H_
-
-#include <stddef.h>
-
-#include <cstdint>
-#include <memory>
-
-#include "net/third_party/quic/http/decoder/quic_http_frame_decoder.h"
-#include "net/third_party/quic/platform/api/quic_optional.h"
-#include "net/third_party/quic/platform/api/quic_string_piece.h"
-#include "net/third_party/spdy/core/hpack/hpack_decoder_adapter.h"
-#include "net/third_party/spdy/core/hpack/hpack_header_table.h"
-#include "net/third_party/spdy/core/http2_frame_decoder_adapter.h"
-#include "net/third_party/spdy/core/spdy_alt_svc_wire_format.h"
-#include "net/third_party/spdy/core/spdy_framer.h"
-#include "net/third_party/spdy/core/spdy_headers_handler_interface.h"
-#include "net/third_party/spdy/core/spdy_protocol.h"
-
-namespace spdy {
-class SpdyFramerVisitorInterface;
-
-class ExtensionVisitorInterface;
-}  // namespace spdy
-namespace quic {
-
-// Adapts spdy::SpdyFramer interface to use QuicHttpFrameDecoder.
-class SPDY_EXPORT_PRIVATE QuicHttpDecoderAdapter
-    : public QuicHttpFrameDecoderListener {
- public:
-  // HTTP2 states.
-  enum SpdyState {
-    SPDY_ERROR,
-    SPDY_READY_FOR_FRAME,  // Framer is ready for reading the next frame.
-    SPDY_FRAME_COMPLETE,  // Framer has finished reading a frame, need to reset.
-    SPDY_READING_COMMON_HEADER,
-    SPDY_CONTROL_FRAME_PAYLOAD,
-    SPDY_READ_DATA_FRAME_PADDING_LENGTH,
-    SPDY_CONSUME_PADDING,
-    SPDY_IGNORE_REMAINING_PAYLOAD,
-    SPDY_FORWARD_STREAM_FRAME,
-    SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK,
-    SPDY_CONTROL_FRAME_HEADER_BLOCK,
-    SPDY_GOAWAY_FRAME_PAYLOAD,
-    SPDY_SETTINGS_FRAME_HEADER,
-    SPDY_SETTINGS_FRAME_PAYLOAD,
-    SPDY_ALTSVC_FRAME_PAYLOAD,
-    SPDY_EXTENSION_FRAME_PAYLOAD,
-  };
-
-  // For debugging.
-  static const char* StateToString(int state);
-
-  QuicHttpDecoderAdapter();
-  ~QuicHttpDecoderAdapter() override;
-
-  // Set callbacks to be called from the framer.  A visitor must be set, or
-  // else the framer will likely crash.  It is acceptable for the visitor
-  // to do nothing.  If this is called multiple times, only the last visitor
-  // will be used.
-  void set_visitor(spdy::SpdyFramerVisitorInterface* visitor);
-  spdy::SpdyFramerVisitorInterface* visitor() const { return visitor_; }
-
-  // Set extension callbacks to be called from the framer or decoder. Optional.
-  // If called multiple times, only the last visitor will be used.
-  void set_extension_visitor(spdy::ExtensionVisitorInterface* visitor);
-
-  // Set debug callbacks to be called from the framer. The debug visitor is
-  // completely optional and need not be set in order for normal operation.
-  // If this is called multiple times, only the last visitor will be used.
-  void set_debug_visitor(spdy::SpdyFramerDebugVisitorInterface* debug_visitor);
-  spdy::SpdyFramerDebugVisitorInterface* debug_visitor() const {
-    return debug_visitor_;
-  }
-
-  // Set debug callbacks to be called from the HPQUIC_HTTP_ACK decoder.
-  void SetDecoderHeaderTableDebugVisitor(
-      std::unique_ptr<spdy::HpackHeaderTable::DebugVisitorInterface> visitor);
-
-  // Sets whether or not ProcessInput returns after finishing a frame, or
-  // continues processing additional frames. Normally ProcessInput processes
-  // all input, but this method enables the caller (and visitor) to work with
-  // a single frame at a time (or that portion of the frame which is provided
-  // as input). Reset() does not change the value of this flag.
-  void set_process_single_input_frame(bool v);
-  bool process_single_input_frame() const {
-    return process_single_input_frame_;
-  }
-
-  // Decode the |len| bytes of encoded HTTP/2 starting at |*data|. Returns
-  // the number of bytes consumed. It is safe to pass more bytes in than
-  // may be consumed. Should process (or otherwise buffer) as much as
-  // available, unless process_single_input_frame is true.
-  size_t ProcessInput(const char* data, size_t len);
-
-  // Reset the decoder (used just for tests at this time).
-  void Reset();
-
-  // Current state of the decoder.
-  SpdyState state() const;
-
-  // Current error code (NO_ERROR if state != ERROR).
-  http2::Http2DecoderAdapter::SpdyFramerError spdy_framer_error() const;
-
-  // Has any frame header looked like the start of an HTTP/1.1 (or earlier)
-  // response? Used to detect if a backend/server that we sent a request to
-  // has responded with an HTTP/1.1 (or earlier) response.
-  bool probable_http_response() const;
-
-  spdy::HpackDecoderAdapter* GetHpackDecoder();
-
-  bool HasError() const;
-
- private:
-  bool OnFrameHeader(const QuicHttpFrameHeader& header) override;
-  void OnDataStart(const QuicHttpFrameHeader& header) override;
-  void OnDataPayload(const char* data, size_t len) override;
-  void OnDataEnd() override;
-  void OnHeadersStart(const QuicHttpFrameHeader& header) override;
-  void OnHeadersPriority(const QuicHttpPriorityFields& priority) override;
-  void OnHpackFragment(const char* data, size_t len) override;
-  void OnHeadersEnd() override;
-  void OnPriorityFrame(const QuicHttpFrameHeader& header,
-                       const QuicHttpPriorityFields& priority) override;
-  void OnContinuationStart(const QuicHttpFrameHeader& header) override;
-  void OnContinuationEnd() override;
-  void OnPadLength(size_t trailing_length) override;
-  void OnPadding(const char* padding, size_t skipped_length) override;
-  void OnRstStream(const QuicHttpFrameHeader& header,
-                   QuicHttpErrorCode http2_error_code) override;
-  void OnSettingsStart(const QuicHttpFrameHeader& header) override;
-  void OnSetting(const QuicHttpSettingFields& setting_fields) override;
-  void OnSettingsEnd() override;
-  void OnSettingsAck(const QuicHttpFrameHeader& header) override;
-  void OnPushPromiseStart(const QuicHttpFrameHeader& header,
-                          const QuicHttpPushPromiseFields& promise,
-                          size_t total_padding_length) override;
-  void OnPushPromiseEnd() override;
-  void OnPing(const QuicHttpFrameHeader& header,
-              const QuicHttpPingFields& ping) override;
-  void OnPingAck(const QuicHttpFrameHeader& header,
-                 const QuicHttpPingFields& ping) override;
-  void OnGoAwayStart(const QuicHttpFrameHeader& header,
-                     const QuicHttpGoAwayFields& goaway) override;
-  void OnGoAwayOpaqueData(const char* data, size_t len) override;
-  void OnGoAwayEnd() override;
-  void OnWindowUpdate(const QuicHttpFrameHeader& header,
-                      uint32_t increment) override;
-  void OnAltSvcStart(const QuicHttpFrameHeader& header,
-                     size_t origin_length,
-                     size_t value_length) override;
-  void OnAltSvcOriginData(const char* data, size_t len) override;
-  void OnAltSvcValueData(const char* data, size_t len) override;
-  void OnAltSvcEnd() override;
-  void OnUnknownStart(const QuicHttpFrameHeader& header) override;
-  void OnUnknownPayload(const char* data, size_t len) override;
-  void OnUnknownEnd() override;
-  void OnPaddingTooLong(const QuicHttpFrameHeader& header,
-                        size_t missing_length) override;
-  void OnFrameSizeError(const QuicHttpFrameHeader& header) override;
-
-  size_t ProcessInputFrame(const char* data, size_t len);
-
-  void DetermineSpdyState(QuicHttpDecodeStatus status);
-  void ResetBetweenFrames();
-
-  // ResetInternal is called from the constructor, and during tests, but not
-  // otherwise (i.e. not between every frame).
-  void ResetInternal();
-
-  void set_spdy_state(SpdyState v);
-
-  void SetSpdyErrorAndNotify(http2::Http2DecoderAdapter::SpdyFramerError error);
-
-  const QuicHttpFrameHeader& frame_header() const;
-
-  uint32_t stream_id() const;
-  QuicHttpFrameType frame_type() const;
-
-  size_t remaining_total_payload() const;
-
-  bool IsReadingPaddingLength();
-  bool IsSkippingPadding();
-  bool IsDiscardingPayload();
-  // Called from OnXyz or OnXyzStart methods to decide whether it is OK to
-  // handle the callback.
-  bool IsOkToStartFrame(const QuicHttpFrameHeader& header);
-  bool HasRequiredStreamId(uint32_t stream_id);
-
-  bool HasRequiredStreamId(const QuicHttpFrameHeader& header);
-
-  bool HasRequiredStreamIdZero(uint32_t stream_id);
-
-  bool HasRequiredStreamIdZero(const QuicHttpFrameHeader& header);
-
-  void ReportReceiveCompressedFrame(const QuicHttpFrameHeader& header);
-
-  void CommonStartHpackBlock();
-
-  // spdy::SpdyFramer calls HandleControlFrameHeadersData even if there are zero
-  // fragment bytes in the first frame, so do the same.
-  void MaybeAnnounceEmptyFirstHpackFragment();
-  void CommonHpackFragmentEnd();
-
-  // The most recently decoded frame header; invalid after we reached the end
-  // of that frame.
-  QuicHttpFrameHeader frame_header_;
-
-  // If decoding an HPQUIC_HTTP_ACK block that is split across multiple frames,
-  // this holds the frame header of the HEADERS or PUSH_PROMISE that started the
-  // block.
-  QuicHttpFrameHeader hpack_first_frame_header_;
-
-  // Amount of trailing padding. Currently used just as an indicator of whether
-  // OnPadLength has been called.
-  QuicOptional<size_t> opt_pad_length_;
-
-  // Temporary buffers for the AltSvc fields.
-  QuicString alt_svc_origin_;
-  QuicString alt_svc_value_;
-
-  // Listener used if we transition to an error state; the listener ignores all
-  // the callbacks.
-  QuicHttpFrameDecoderNoOpListener no_op_listener_;
-
-  spdy::SpdyFramerVisitorInterface* visitor_ = nullptr;
-  spdy::SpdyFramerDebugVisitorInterface* debug_visitor_ = nullptr;
-
-  // If non-null, unknown frames and settings are passed to the extension.
-  spdy::ExtensionVisitorInterface* extension_ = nullptr;
-
-  // The HPQUIC_HTTP_ACK decoder to be used for this adapter. User is
-  // responsible for clearing if the adapter is to be used for another
-  // connection.
-  std::unique_ptr<spdy::HpackDecoderAdapter> hpack_decoder_ = nullptr;
-
-  // The HTTP/2 frame decoder. Accessed via a unique_ptr to allow replacement
-  // (e.g. in tests) when Reset() is called.
-  std::unique_ptr<QuicHttpFrameDecoder> frame_decoder_;
-
-  // Next frame type expected. Currently only used for CONTINUATION frames,
-  // but could be used for detecting whether the first frame is a SETTINGS
-  // frame.
-  // TODO(jamessyng): Provide means to indicate that decoder should require
-  // SETTINGS frame as the first frame.
-  QuicHttpFrameType expected_frame_type_;
-
-  // Attempt to duplicate the SpdyState and spdy::SpdyFramer::Error values that
-  // spdy::SpdyFramer sets. Values determined by getting tests to pass.
-  SpdyState spdy_state_;
-  http2::Http2DecoderAdapter::SpdyFramerError spdy_framer_error_;
-
-  // The limit on the size of received HTTP/2 payloads as specified in the
-  // spdy::SETTINGS_MAX_FRAME_SIZE advertised to peer.
-  size_t recv_frame_size_limit_ = spdy::kHttp2DefaultFramePayloadLimit;
-
-  // Has OnFrameHeader been called?
-  bool decoded_frame_header_ = false;
-
-  // Have we recorded an QuicHttpFrameHeader for the current frame?
-  // We only do so if the decoder will make multiple callbacks for
-  // the frame; for example, for PING frames we don't make record
-  // the frame header, but for ALTSVC we do.
-  bool has_frame_header_ = false;
-
-  // Have we recorded an QuicHttpFrameHeader for the current HPQUIC_HTTP_ACK
-  // block? True only for multi-frame HPQUIC_HTTP_ACK blocks.
-  bool has_hpack_first_frame_header_ = false;
-
-  // Has OnHeaders() already been called for current HEADERS block? Only
-  // meaningful between OnHeadersStart and OnHeadersPriority.
-  bool on_headers_called_;
-
-  // Has OnHpackFragment() already been called for current HPQUIC_HTTP_ACK
-  // block? spdy::SpdyFramer will pass an empty buffer to the HPQUIC_HTTP_ACK
-  // decoder if a HEADERS or PUSH_PROMISE has no HPQUIC_HTTP_ACK data in it
-  // (e.g. a HEADERS frame with only padding). Detect that condition and
-  // replicate the behavior using this field.
-  bool on_hpack_fragment_called_;
-
-  // Have we seen a frame header that appears to be an HTTP/1 response?
-  bool latched_probable_http_response_ = false;
-
-  // Is expected_frame_type_ set?
-  bool has_expected_frame_type_ = false;
-
-  // Is the current frame payload destined for |extension_|?
-  bool handling_extension_payload_ = false;
-
-  bool process_single_input_frame_ = false;
-};
-
-}  // namespace quic
-
-#endif  // NET_THIRD_PARTY_QUIC_HTTP_DECODER_QUIC_HTTP_FRAME_DECODER_ADAPTER_H_
diff --git a/net/third_party/quic/http/decoder/quic_http_frame_decoder_listener.cc b/net/third_party/quic/http/decoder/quic_http_frame_decoder_listener.cc
deleted file mode 100644
index 084c9b68..0000000
--- a/net/third_party/quic/http/decoder/quic_http_frame_decoder_listener.cc
+++ /dev/null
@@ -1,14 +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 "net/third_party/quic/http/decoder/quic_http_frame_decoder_listener.h"
-
-namespace quic {
-
-bool QuicHttpFrameDecoderNoOpListener::OnFrameHeader(
-    const QuicHttpFrameHeader& header) {
-  return true;
-}
-
-}  // namespace quic
diff --git a/net/third_party/quic/http/decoder/quic_http_frame_decoder_listener.h b/net/third_party/quic/http/decoder/quic_http_frame_decoder_listener.h
deleted file mode 100644
index 347e078..0000000
--- a/net/third_party/quic/http/decoder/quic_http_frame_decoder_listener.h
+++ /dev/null
@@ -1,364 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_THIRD_PARTY_QUIC_HTTP_DECODER_QUIC_HTTP_FRAME_DECODER_LISTENER_H_
-#define NET_THIRD_PARTY_QUIC_HTTP_DECODER_QUIC_HTTP_FRAME_DECODER_LISTENER_H_
-
-// QuicHttpFrameDecoderListener is the interface which the HTTP/2 decoder uses
-// to report the decoded frames to a listener.
-//
-// The general design is to assume that the listener will copy the data it needs
-// (e.g. frame headers) and will keep track of the implicit state of the
-// decoding process (i.e. the decoder maintains just the information it needs in
-// order to perform the decoding). Therefore, the parameters are just those with
-// (potentially) new data, not previously provided info about the current frame.
-//
-// The calls are described as if they are made in quick succession, i.e. one
-// after another, but of course the decoder needs input to decode, and the
-// decoder will only call the listener once the necessary input has been
-// provided. For example: OnDataStart can only be called once the 9 bytes of
-// of an HTTP/2 common frame header have been received. The decoder will call
-// the listener methods as soon as possible to avoid almost all buffering.
-//
-// The listener interface is designed so that it is possible to exactly
-// reconstruct the serialized frames, with the exception of reserved bits,
-// including in the frame header's flags and stream_id fields, which will have
-// been cleared before the methods below are called.
-
-#include <stddef.h>
-
-#include <cstdint>
-#include <type_traits>
-
-#include "net/third_party/quic/http/quic_http_constants.h"
-#include "net/third_party/quic/http/quic_http_structures.h"
-
-namespace quic {
-
-// TODO(jamessynge): Consider sorting the methods by frequency of call, if that
-// helps at all.
-class QuicHttpFrameDecoderListener {
- public:
-  QuicHttpFrameDecoderListener() {}
-  virtual ~QuicHttpFrameDecoderListener() {}
-
-  // Called once the common frame header has been decoded for any frame, and
-  // before any of the methods below, which will also be called. This method is
-  // included in this interface only for the purpose of supporting
-  // spdy::SpdyFramer semantics via an adapter. This is the only method that has
-  // a non-void return type, and this is just so that
-  // QuicHttpFrameDecoderAdapter (called from spdy::SpdyFramer) can more readily
-  // pass existing tests that expect decoding to stop if the headers alone
-  // indicate an error. Return false to stop decoding just after decoding the
-  // header, else return true to continue decoding.
-  // TODO(jamessynge): Remove OnFrameHeader once done with supporting
-  // spdy::SpdyFramer's exact states.
-  virtual bool OnFrameHeader(const QuicHttpFrameHeader& header) = 0;
-
-  //////////////////////////////////////////////////////////////////////////////
-
-  // Called once the common frame header has been decoded for a DATA frame,
-  // before examining the frame's payload, after which:
-  //   OnPadLength will be called if header.IsPadded() is true, i.e. if the
-  //     QUIC_HTTP_PADDED flag is set;
-  //   OnDataPayload will be called as the non-padding portion of the payload
-  //     is available until all of it has been provided;
-  //   OnPadding will be called if the frame is padded AND the Pad Length field
-  //     is greater than zero;
-  //   OnDataEnd will be called last. If the frame is unpadded and has no
-  //     payload, then this will be called immediately after OnDataStart.
-  virtual void OnDataStart(const QuicHttpFrameHeader& header) = 0;
-
-  // Called when the next non-padding portion of a DATA frame's payload is
-  // received.
-  // |data| The start of |len| bytes of data.
-  // |len| The length of the data buffer. Maybe zero in some cases, which does
-  //       not mean anything special.
-  virtual void OnDataPayload(const char* data, size_t len) = 0;
-
-  // Called after an entire DATA frame has been received.
-  // If header.IsEndStream() == true, this is the last data for the stream.
-  virtual void OnDataEnd() = 0;
-
-  // Called once the common frame header has been decoded for a HEADERS frame,
-  // before examining the frame's payload, after which:
-  //   OnPadLength will be called if header.IsPadded() is true, i.e. if the
-  //     QUIC_HTTP_PADDED flag is set;
-  //   OnHeadersPriority will be called if header.HasPriority() is true, i.e. if
-  //     the frame has the QUIC_HTTP_PRIORITY flag;
-  //   OnHpackFragment as the remainder of the non-padding payload is available
-  //     until all if has been provided;
-  //   OnPadding will be called if the frame is padded AND the Pad Length field
-  //     is greater than zero;
-  //   OnHeadersEnd will be called last; If the frame is unpadded and has no
-  //     payload, then this will be called immediately after OnHeadersStart;
-  //     OnHeadersEnd indicates the end of the HPQUIC_HTTP_ACK block only if the
-  //     frame header had the QUIC_HTTP_END_HEADERS flag set, else the
-  //     QUIC_HTTP_END_HEADERS should be looked for on a subsequent CONTINUATION
-  //     frame.
-  virtual void OnHeadersStart(const QuicHttpFrameHeader& header) = 0;
-
-  // Called when a HEADERS frame is received with the QUIC_HTTP_PRIORITY flag
-  // set and the priority fields have been decoded.
-  virtual void OnHeadersPriority(
-      const QuicHttpPriorityFields& priority_fields) = 0;
-
-  // Called when a fragment (i.e. some or all of an HPQUIC_HTTP_ACK Block) is
-  // received; this may be part of a HEADERS, PUSH_PROMISE or CONTINUATION
-  // frame. |data| The start of |len| bytes of data. |len| The length of the
-  // data buffer. Maybe zero in some cases, which does
-  //       not mean anything special, except that it simplified the decoder.
-  virtual void OnHpackFragment(const char* data, size_t len) = 0;
-
-  // Called after an entire HEADERS frame has been received. The frame is the
-  // end of the HEADERS if the QUIC_HTTP_END_HEADERS flag is set; else there
-  // should be CONTINUATION frames after this frame.
-  virtual void OnHeadersEnd() = 0;
-
-  // Called when an entire QUIC_HTTP_PRIORITY frame has been decoded.
-  virtual void OnPriorityFrame(
-      const QuicHttpFrameHeader& header,
-      const QuicHttpPriorityFields& priority_fields) = 0;
-
-  // Called once the common frame header has been decoded for a CONTINUATION
-  // frame, before examining the frame's payload, after which:
-  //   OnHpackFragment as the frame's payload is available until all of it
-  //     has been provided;
-  //   OnContinuationEnd will be called last; If the frame has no payload,
-  //     then this will be called immediately after OnContinuationStart;
-  //     the HPQUIC_HTTP_ACK block is at an end if and only if the frame header
-  //     passed to OnContinuationStart had the QUIC_HTTP_END_HEADERS flag set.
-  virtual void OnContinuationStart(const QuicHttpFrameHeader& header) = 0;
-
-  // Called after an entire CONTINUATION frame has been received. The frame is
-  // the end of the HEADERS if the QUIC_HTTP_END_HEADERS flag is set.
-  virtual void OnContinuationEnd() = 0;
-
-  // Called when Pad Length field has been read. Applies to DATA and HEADERS
-  // frames. For PUSH_PROMISE frames, the Pad Length + 1 is provided in the
-  // OnPushPromiseStart call as total_padding_length.
-  virtual void OnPadLength(size_t pad_length) = 0;
-
-  // Called when padding is skipped over.
-  virtual void OnPadding(const char* padding, size_t skipped_length) = 0;
-
-  // Called when an entire RST_STREAM frame has been decoded.
-  // This is the only callback for RST_STREAM frames.
-  virtual void OnRstStream(const QuicHttpFrameHeader& header,
-                           QuicHttpErrorCode error_code) = 0;
-
-  // Called once the common frame header has been decoded for a SETTINGS frame
-  // without the QUIC_HTTP_ACK flag, before examining the frame's payload, after
-  // which:
-  //   OnSetting will be called in turn for each pair of settings parameter and
-  //     value found in the payload;
-  //   OnSettingsEnd will be called last; If the frame has no payload,
-  //     then this will be called immediately after OnSettingsStart.
-  // The frame header is passed so that the caller can check the stream_id,
-  // which should be zero, but that hasn't been checked by the decoder.
-  virtual void OnSettingsStart(const QuicHttpFrameHeader& header) = 0;
-
-  // Called for each setting parameter and value within a SETTINGS frame.
-  virtual void OnSetting(const QuicHttpSettingFields& setting_fields) = 0;
-
-  // Called after parsing the complete payload of SETTINGS frame
-  // (non-QUIC_HTTP_ACK).
-  virtual void OnSettingsEnd() = 0;
-
-  // Called when an entire SETTINGS frame, with the QUIC_HTTP_ACK flag, has been
-  // decoded.
-  virtual void OnSettingsAck(const QuicHttpFrameHeader& header) = 0;
-
-  // Called just before starting to process the HPQUIC_HTTP_ACK block of a
-  // PUSH_PROMISE frame. The Pad Length field has already been decoded at this
-  // point, so OnPadLength will not be called; note that total_padding_length is
-  // Pad Length + 1. After OnPushPromiseStart:
-  //   OnHpackFragment as the remainder of the non-padding payload is available
-  //     until all if has been provided;
-  //   OnPadding will be called if the frame is padded AND the Pad Length field
-  //     is greater than zero (i.e. total_padding_length > 1);
-  //   OnPushPromiseEnd will be called last; If the frame is unpadded and has no
-  //     payload, then this will be called immediately after OnPushPromiseStart.
-  virtual void OnPushPromiseStart(const QuicHttpFrameHeader& header,
-                                  const QuicHttpPushPromiseFields& promise,
-                                  size_t total_padding_length) = 0;
-
-  // Called after all of the HPQUIC_HTTP_ACK block fragment and padding of a
-  // PUSH_PROMISE has been decoded and delivered to the listener. This call
-  // indicates the end of the HPQUIC_HTTP_ACK block if and only if the frame
-  // header had the QUIC_HTTP_END_HEADERS flag set (i.e. header.IsEndHeaders()
-  // is true); otherwise the next block must be a CONTINUATION frame with the
-  // same stream id (not the same promised stream id).
-  virtual void OnPushPromiseEnd() = 0;
-
-  // Called when an entire PING frame, without the QUIC_HTTP_ACK flag, has been
-  // decoded.
-  virtual void OnPing(const QuicHttpFrameHeader& header,
-                      const QuicHttpPingFields& ping) = 0;
-
-  // Called when an entire PING frame, with the QUIC_HTTP_ACK flag, has been
-  // decoded.
-  virtual void OnPingAck(const QuicHttpFrameHeader& header,
-                         const QuicHttpPingFields& ping) = 0;
-
-  // Called after parsing a GOAWAY frame's header and fixed size fields, after
-  // which:
-  //   OnGoAwayOpaqueData will be called as opaque data of the payload becomes
-  //     available to the decoder, until all of it has been provided to the
-  //     listener;
-  //   OnGoAwayEnd will be called last, after all the opaque data has been
-  //     provided to the listener; if there is no opaque data, then OnGoAwayEnd
-  //     will be called immediately after OnGoAwayStart.
-  virtual void OnGoAwayStart(const QuicHttpFrameHeader& header,
-                             const QuicHttpGoAwayFields& goaway) = 0;
-
-  // Called when the next portion of a GOAWAY frame's payload is received.
-  // |data| The start of |len| bytes of opaque data.
-  // |len| The length of the opaque data buffer. Maybe zero in some cases,
-  //       which does not mean anything special.
-  virtual void OnGoAwayOpaqueData(const char* data, size_t len) = 0;
-
-  // Called after finishing decoding all of a GOAWAY frame.
-  virtual void OnGoAwayEnd() = 0;
-
-  // Called when an entire WINDOW_UPDATE frame has been decoded. The
-  // window_size_increment is required to be non-zero, but that has not been
-  // checked. If header.stream_id==0, the connection's flow control window is
-  // being increased, else the specified stream's flow control is being
-  // increased.
-  virtual void OnWindowUpdate(const QuicHttpFrameHeader& header,
-                              uint32_t window_size_increment) = 0;
-
-  // Called when an ALTSVC frame header and origin length have been parsed.
-  // Either or both lengths may be zero. After OnAltSvcStart:
-  //   OnAltSvcOriginData will be called until all of the (optional) Origin
-  //     has been provided;
-  //   OnAltSvcValueData will be called until all of the Alt-Svc-Field-Value
-  //     has been provided;
-  //   OnAltSvcEnd will called last, after all of the origin and
-  //     Alt-Svc-Field-Value have been delivered to the listener.
-  virtual void OnAltSvcStart(const QuicHttpFrameHeader& header,
-                             size_t origin_length,
-                             size_t value_length) = 0;
-
-  // Called when decoding the (optional) origin of an ALTSVC;
-  // the field is uninterpreted.
-  virtual void OnAltSvcOriginData(const char* data, size_t len) = 0;
-
-  // Called when decoding the Alt-Svc-Field-Value of an ALTSVC;
-  // the field is uninterpreted.
-  virtual void OnAltSvcValueData(const char* data, size_t len) = 0;
-
-  // Called after decoding all of a ALTSVC frame and providing to the listener
-  // via the above methods.
-  virtual void OnAltSvcEnd() = 0;
-
-  // Called when the common frame header has been decoded, but the frame type
-  // is unknown, after which:
-  //   OnUnknownPayload is called as the payload of the frame is provided to the
-  //     decoder, until all of the payload has been decoded;
-  //   OnUnknownEnd will called last, after the entire frame of the unknown type
-  //     has been decoded and provided to the listener.
-  virtual void OnUnknownStart(const QuicHttpFrameHeader& header) = 0;
-
-  // Called when the payload of an unknown frame type is received.
-  // |data| A buffer containing the data received.
-  // |len| The length of the data buffer.
-  virtual void OnUnknownPayload(const char* data, size_t len) = 0;
-
-  // Called after decoding all of the payload of an unknown frame type.
-  virtual void OnUnknownEnd() = 0;
-
-  //////////////////////////////////////////////////////////////////////////////
-  // Below here are events indicating a problem has been detected during
-  // decoding (i.e. the received frames are malformed in some way).
-
-  // Padding field (uint8) has a value that is too large (i.e. the amount of
-  // padding is greater than the remainder of the payload that isn't required).
-  // From RFC Section 6.1, DATA:
-  //     If the length of the padding is the length of the frame payload or
-  //     greater, the recipient MUST treat this as a connection error
-  //     (Section 5.4.1) of type PROTOCOL_ERROR.
-  // The same is true for HEADERS and PUSH_PROMISE.
-  virtual void OnPaddingTooLong(const QuicHttpFrameHeader& header,
-                                size_t missing_length) = 0;
-
-  // Frame size error. Depending upon the effected frame, this may or may not
-  // require terminating the connection, though that is probably the best thing
-  // to do.
-  // From RFC Section 4.2, Frame Size:
-  //     An endpoint MUST send an error code of FRAME_SIZE_ERROR if a frame
-  //     exceeds the size defined in spdy::SETTINGS_MAX_FRAME_SIZE, exceeds any
-  //     limit defined for the frame type, or is too small to contain mandatory
-  //     frame data. A frame size error in a frame that could alter the state of
-  //     the the entire connection MUST be treated as a connection error
-  //     (Section 5.4.1); this includes any frame carrying a header block
-  //     (Section 4.3) (that is, HEADERS, PUSH_PROMISE, and CONTINUATION),
-  //     SETTINGS, and any frame with a stream identifier of 0.
-  virtual void OnFrameSizeError(const QuicHttpFrameHeader& header) = 0;
-};
-
-// Do nothing for each call. Useful for ignoring a frame that is invalid.
-class QuicHttpFrameDecoderNoOpListener : public QuicHttpFrameDecoderListener {
- public:
-  QuicHttpFrameDecoderNoOpListener() {}
-  ~QuicHttpFrameDecoderNoOpListener() override {}
-
-  // TODO(jamessynge): Remove OnFrameHeader once done with supporting
-  // spdy::SpdyFramer's exact states.
-  bool OnFrameHeader(const QuicHttpFrameHeader& header) override;
-
-  void OnDataStart(const QuicHttpFrameHeader& header) override {}
-  void OnDataPayload(const char* data, size_t len) override {}
-  void OnDataEnd() override {}
-  void OnHeadersStart(const QuicHttpFrameHeader& header) override {}
-  void OnHeadersPriority(const QuicHttpPriorityFields& priority) override {}
-  void OnHpackFragment(const char* data, size_t len) override {}
-  void OnHeadersEnd() override {}
-  void OnPriorityFrame(const QuicHttpFrameHeader& header,
-                       const QuicHttpPriorityFields& priority) override {}
-  void OnContinuationStart(const QuicHttpFrameHeader& header) override {}
-  void OnContinuationEnd() override {}
-  void OnPadLength(size_t trailing_length) override {}
-  void OnPadding(const char* padding, size_t skipped_length) override {}
-  void OnRstStream(const QuicHttpFrameHeader& header,
-                   QuicHttpErrorCode error_code) override {}
-  void OnSettingsStart(const QuicHttpFrameHeader& header) override {}
-  void OnSetting(const QuicHttpSettingFields& setting_fields) override {}
-  void OnSettingsEnd() override {}
-  void OnSettingsAck(const QuicHttpFrameHeader& header) override {}
-  void OnPushPromiseStart(const QuicHttpFrameHeader& header,
-                          const QuicHttpPushPromiseFields& promise,
-                          size_t total_padding_length) override {}
-  void OnPushPromiseEnd() override {}
-  void OnPing(const QuicHttpFrameHeader& header,
-              const QuicHttpPingFields& ping) override {}
-  void OnPingAck(const QuicHttpFrameHeader& header,
-                 const QuicHttpPingFields& ping) override {}
-  void OnGoAwayStart(const QuicHttpFrameHeader& header,
-                     const QuicHttpGoAwayFields& goaway) override {}
-  void OnGoAwayOpaqueData(const char* data, size_t len) override {}
-  void OnGoAwayEnd() override {}
-  void OnWindowUpdate(const QuicHttpFrameHeader& header,
-                      uint32_t increment) override {}
-  void OnAltSvcStart(const QuicHttpFrameHeader& header,
-                     size_t origin_length,
-                     size_t value_length) override {}
-  void OnAltSvcOriginData(const char* data, size_t len) override {}
-  void OnAltSvcValueData(const char* data, size_t len) override {}
-  void OnAltSvcEnd() override {}
-  void OnUnknownStart(const QuicHttpFrameHeader& header) override {}
-  void OnUnknownPayload(const char* data, size_t len) override {}
-  void OnUnknownEnd() override {}
-  void OnPaddingTooLong(const QuicHttpFrameHeader& header,
-                        size_t missing_length) override {}
-  void OnFrameSizeError(const QuicHttpFrameHeader& header) override {}
-};
-
-static_assert(!std::is_abstract<QuicHttpFrameDecoderNoOpListener>(),
-              "QuicHttpFrameDecoderNoOpListener ought to be concrete.");
-
-}  // namespace quic
-
-#endif  // NET_THIRD_PARTY_QUIC_HTTP_DECODER_QUIC_HTTP_FRAME_DECODER_LISTENER_H_
diff --git a/net/third_party/quic/http/decoder/quic_http_frame_decoder_listener_test_util.cc b/net/third_party/quic/http/decoder/quic_http_frame_decoder_listener_test_util.cc
deleted file mode 100644
index 2f66ce4..0000000
--- a/net/third_party/quic/http/decoder/quic_http_frame_decoder_listener_test_util.cc
+++ /dev/null
@@ -1,492 +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 "net/third_party/quic/http/decoder/quic_http_frame_decoder_listener_test_util.h"
-
-#include "base/logging.h"
-#include "net/third_party/quic/http/decoder/quic_http_frame_decoder_listener.h"
-#include "net/third_party/quic/http/quic_http_constants.h"
-#include "net/third_party/quic/http/quic_http_structures.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace quic {
-
-FailingQuicHttpFrameDecoderListener::FailingQuicHttpFrameDecoderListener() {}
-FailingQuicHttpFrameDecoderListener::~FailingQuicHttpFrameDecoderListener() {}
-
-bool FailingQuicHttpFrameDecoderListener::OnFrameHeader(
-    const QuicHttpFrameHeader& header) {
-  ADD_FAILURE() << "OnFrameHeader: " << header;
-  return false;
-}
-
-void FailingQuicHttpFrameDecoderListener::OnDataStart(
-    const QuicHttpFrameHeader& header) {
-  FAIL() << "OnDataStart: " << header;
-}
-
-void FailingQuicHttpFrameDecoderListener::OnDataPayload(const char* data,
-                                                        size_t len) {
-  FAIL() << "OnDataPayload: len=" << len;
-}
-
-void FailingQuicHttpFrameDecoderListener::OnDataEnd() {
-  FAIL() << "OnDataEnd";
-}
-
-void FailingQuicHttpFrameDecoderListener::OnHeadersStart(
-    const QuicHttpFrameHeader& header) {
-  FAIL() << "OnHeadersStart: " << header;
-}
-
-void FailingQuicHttpFrameDecoderListener::OnHeadersPriority(
-    const QuicHttpPriorityFields& priority) {
-  FAIL() << "OnHeadersPriority: " << priority;
-}
-
-void FailingQuicHttpFrameDecoderListener::OnHpackFragment(const char* data,
-                                                          size_t len) {
-  FAIL() << "OnHpackFragment: len=" << len;
-}
-
-void FailingQuicHttpFrameDecoderListener::OnHeadersEnd() {
-  FAIL() << "OnHeadersEnd";
-}
-
-void FailingQuicHttpFrameDecoderListener::OnPriorityFrame(
-    const QuicHttpFrameHeader& header,
-    const QuicHttpPriorityFields& priority) {
-  FAIL() << "OnPriorityFrame: " << header << "; priority: " << priority;
-}
-
-void FailingQuicHttpFrameDecoderListener::OnContinuationStart(
-    const QuicHttpFrameHeader& header) {
-  FAIL() << "OnContinuationStart: " << header;
-}
-
-void FailingQuicHttpFrameDecoderListener::OnContinuationEnd() {
-  FAIL() << "OnContinuationEnd";
-}
-
-void FailingQuicHttpFrameDecoderListener::OnPadLength(size_t trailing_length) {
-  FAIL() << "OnPadLength: trailing_length=" << trailing_length;
-}
-
-void FailingQuicHttpFrameDecoderListener::OnPadding(const char* padding,
-                                                    size_t skipped_length) {
-  FAIL() << "OnPadding: skipped_length=" << skipped_length;
-}
-
-void FailingQuicHttpFrameDecoderListener::OnRstStream(
-    const QuicHttpFrameHeader& header,
-    QuicHttpErrorCode error_code) {
-  FAIL() << "OnRstStream: " << header << "; code=" << error_code;
-}
-
-void FailingQuicHttpFrameDecoderListener::OnSettingsStart(
-    const QuicHttpFrameHeader& header) {
-  FAIL() << "OnSettingsStart: " << header;
-}
-
-void FailingQuicHttpFrameDecoderListener::OnSetting(
-    const QuicHttpSettingFields& setting_fields) {
-  FAIL() << "OnSetting: " << setting_fields;
-}
-
-void FailingQuicHttpFrameDecoderListener::OnSettingsEnd() {
-  FAIL() << "OnSettingsEnd";
-}
-
-void FailingQuicHttpFrameDecoderListener::OnSettingsAck(
-    const QuicHttpFrameHeader& header) {
-  FAIL() << "OnSettingsAck: " << header;
-}
-
-void FailingQuicHttpFrameDecoderListener::OnPushPromiseStart(
-    const QuicHttpFrameHeader& header,
-    const QuicHttpPushPromiseFields& promise,
-    size_t total_padding_length) {
-  FAIL() << "OnPushPromiseStart: " << header << "; promise: " << promise
-         << "; total_padding_length: " << total_padding_length;
-}
-
-void FailingQuicHttpFrameDecoderListener::OnPushPromiseEnd() {
-  FAIL() << "OnPushPromiseEnd";
-}
-
-void FailingQuicHttpFrameDecoderListener::OnPing(
-    const QuicHttpFrameHeader& header,
-    const QuicHttpPingFields& ping) {
-  FAIL() << "OnPing: " << header << "; ping: " << ping;
-}
-
-void FailingQuicHttpFrameDecoderListener::OnPingAck(
-    const QuicHttpFrameHeader& header,
-    const QuicHttpPingFields& ping) {
-  FAIL() << "OnPingAck: " << header << "; ping: " << ping;
-}
-
-void FailingQuicHttpFrameDecoderListener::OnGoAwayStart(
-    const QuicHttpFrameHeader& header,
-    const QuicHttpGoAwayFields& goaway) {
-  FAIL() << "OnGoAwayStart: " << header << "; goaway: " << goaway;
-}
-
-void FailingQuicHttpFrameDecoderListener::OnGoAwayOpaqueData(const char* data,
-                                                             size_t len) {
-  FAIL() << "OnGoAwayOpaqueData: len=" << len;
-}
-
-void FailingQuicHttpFrameDecoderListener::OnGoAwayEnd() {
-  FAIL() << "OnGoAwayEnd";
-}
-
-void FailingQuicHttpFrameDecoderListener::OnWindowUpdate(
-    const QuicHttpFrameHeader& header,
-    uint32_t increment) {
-  FAIL() << "OnWindowUpdate: " << header << "; increment=" << increment;
-}
-
-void FailingQuicHttpFrameDecoderListener::OnAltSvcStart(
-    const QuicHttpFrameHeader& header,
-    size_t origin_length,
-    size_t value_length) {
-  FAIL() << "OnAltSvcStart: " << header << "; origin_length: " << origin_length
-         << "; value_length: " << value_length;
-}
-
-void FailingQuicHttpFrameDecoderListener::OnAltSvcOriginData(const char* data,
-                                                             size_t len) {
-  FAIL() << "OnAltSvcOriginData: len=" << len;
-}
-
-void FailingQuicHttpFrameDecoderListener::OnAltSvcValueData(const char* data,
-                                                            size_t len) {
-  FAIL() << "OnAltSvcValueData: len=" << len;
-}
-
-void FailingQuicHttpFrameDecoderListener::OnAltSvcEnd() {
-  FAIL() << "OnAltSvcEnd";
-}
-
-void FailingQuicHttpFrameDecoderListener::OnUnknownStart(
-    const QuicHttpFrameHeader& header) {
-  FAIL() << "OnUnknownStart: " << header;
-}
-
-void FailingQuicHttpFrameDecoderListener::OnUnknownPayload(const char* data,
-                                                           size_t len) {
-  FAIL() << "OnUnknownPayload: len=" << len;
-}
-
-void FailingQuicHttpFrameDecoderListener::OnUnknownEnd() {
-  FAIL() << "OnUnknownEnd";
-}
-
-void FailingQuicHttpFrameDecoderListener::OnPaddingTooLong(
-    const QuicHttpFrameHeader& header,
-    size_t missing_length) {
-  FAIL() << "OnPaddingTooLong: " << header
-         << "; missing_length: " << missing_length;
-}
-
-void FailingQuicHttpFrameDecoderListener::OnFrameSizeError(
-    const QuicHttpFrameHeader& header) {
-  FAIL() << "OnFrameSizeError: " << header;
-}
-
-LoggingQuicHttpFrameDecoderListener::LoggingQuicHttpFrameDecoderListener()
-    : wrapped_(nullptr) {}
-LoggingQuicHttpFrameDecoderListener::LoggingQuicHttpFrameDecoderListener(
-    QuicHttpFrameDecoderListener* wrapped)
-    : wrapped_(wrapped) {}
-LoggingQuicHttpFrameDecoderListener::~LoggingQuicHttpFrameDecoderListener() {}
-
-bool LoggingQuicHttpFrameDecoderListener::OnFrameHeader(
-    const QuicHttpFrameHeader& header) {
-  VLOG(1) << "OnFrameHeader: " << header;
-  if (wrapped_ != nullptr) {
-    return wrapped_->OnFrameHeader(header);
-  }
-  return true;
-}
-
-void LoggingQuicHttpFrameDecoderListener::OnDataStart(
-    const QuicHttpFrameHeader& header) {
-  VLOG(1) << "OnDataStart: " << header;
-  if (wrapped_ != nullptr) {
-    wrapped_->OnDataStart(header);
-  }
-}
-
-void LoggingQuicHttpFrameDecoderListener::OnDataPayload(const char* data,
-                                                        size_t len) {
-  VLOG(1) << "OnDataPayload: len=" << len;
-  if (wrapped_ != nullptr) {
-    wrapped_->OnDataPayload(data, len);
-  }
-}
-
-void LoggingQuicHttpFrameDecoderListener::OnDataEnd() {
-  VLOG(1) << "OnDataEnd";
-  if (wrapped_ != nullptr) {
-    wrapped_->OnDataEnd();
-  }
-}
-
-void LoggingQuicHttpFrameDecoderListener::OnHeadersStart(
-    const QuicHttpFrameHeader& header) {
-  VLOG(1) << "OnHeadersStart: " << header;
-  if (wrapped_ != nullptr) {
-    wrapped_->OnHeadersStart(header);
-  }
-}
-
-void LoggingQuicHttpFrameDecoderListener::OnHeadersPriority(
-    const QuicHttpPriorityFields& priority) {
-  VLOG(1) << "OnHeadersPriority: " << priority;
-  if (wrapped_ != nullptr) {
-    wrapped_->OnHeadersPriority(priority);
-  }
-}
-
-void LoggingQuicHttpFrameDecoderListener::OnHpackFragment(const char* data,
-                                                          size_t len) {
-  VLOG(1) << "OnHpackFragment: len=" << len;
-  if (wrapped_ != nullptr) {
-    wrapped_->OnHpackFragment(data, len);
-  }
-}
-
-void LoggingQuicHttpFrameDecoderListener::OnHeadersEnd() {
-  VLOG(1) << "OnHeadersEnd";
-  if (wrapped_ != nullptr) {
-    wrapped_->OnHeadersEnd();
-  }
-}
-
-void LoggingQuicHttpFrameDecoderListener::OnPriorityFrame(
-    const QuicHttpFrameHeader& header,
-    const QuicHttpPriorityFields& priority) {
-  VLOG(1) << "OnPriorityFrame: " << header << "; priority: " << priority;
-  if (wrapped_ != nullptr) {
-    wrapped_->OnPriorityFrame(header, priority);
-  }
-}
-
-void LoggingQuicHttpFrameDecoderListener::OnContinuationStart(
-    const QuicHttpFrameHeader& header) {
-  VLOG(1) << "OnContinuationStart: " << header;
-  if (wrapped_ != nullptr) {
-    wrapped_->OnContinuationStart(header);
-  }
-}
-
-void LoggingQuicHttpFrameDecoderListener::OnContinuationEnd() {
-  VLOG(1) << "OnContinuationEnd";
-  if (wrapped_ != nullptr) {
-    wrapped_->OnContinuationEnd();
-  }
-}
-
-void LoggingQuicHttpFrameDecoderListener::OnPadLength(size_t trailing_length) {
-  VLOG(1) << "OnPadLength: trailing_length=" << trailing_length;
-  if (wrapped_ != nullptr) {
-    wrapped_->OnPadLength(trailing_length);
-  }
-}
-
-void LoggingQuicHttpFrameDecoderListener::OnPadding(const char* padding,
-                                                    size_t skipped_length) {
-  VLOG(1) << "OnPadding: skipped_length=" << skipped_length;
-  if (wrapped_ != nullptr) {
-    wrapped_->OnPadding(padding, skipped_length);
-  }
-}
-
-void LoggingQuicHttpFrameDecoderListener::OnRstStream(
-    const QuicHttpFrameHeader& header,
-    QuicHttpErrorCode error_code) {
-  VLOG(1) << "OnRstStream: " << header << "; code=" << error_code;
-  if (wrapped_ != nullptr) {
-    wrapped_->OnRstStream(header, error_code);
-  }
-}
-
-void LoggingQuicHttpFrameDecoderListener::OnSettingsStart(
-    const QuicHttpFrameHeader& header) {
-  VLOG(1) << "OnSettingsStart: " << header;
-  if (wrapped_ != nullptr) {
-    wrapped_->OnSettingsStart(header);
-  }
-}
-
-void LoggingQuicHttpFrameDecoderListener::OnSetting(
-    const QuicHttpSettingFields& setting_fields) {
-  VLOG(1) << "OnSetting: " << setting_fields;
-  if (wrapped_ != nullptr) {
-    wrapped_->OnSetting(setting_fields);
-  }
-}
-
-void LoggingQuicHttpFrameDecoderListener::OnSettingsEnd() {
-  VLOG(1) << "OnSettingsEnd";
-  if (wrapped_ != nullptr) {
-    wrapped_->OnSettingsEnd();
-  }
-}
-
-void LoggingQuicHttpFrameDecoderListener::OnSettingsAck(
-    const QuicHttpFrameHeader& header) {
-  VLOG(1) << "OnSettingsAck: " << header;
-  if (wrapped_ != nullptr) {
-    wrapped_->OnSettingsAck(header);
-  }
-}
-
-void LoggingQuicHttpFrameDecoderListener::OnPushPromiseStart(
-    const QuicHttpFrameHeader& header,
-    const QuicHttpPushPromiseFields& promise,
-    size_t total_padding_length) {
-  VLOG(1) << "OnPushPromiseStart: " << header << "; promise: " << promise
-          << "; total_padding_length: " << total_padding_length;
-  if (wrapped_ != nullptr) {
-    wrapped_->OnPushPromiseStart(header, promise, total_padding_length);
-  }
-}
-
-void LoggingQuicHttpFrameDecoderListener::OnPushPromiseEnd() {
-  VLOG(1) << "OnPushPromiseEnd";
-  if (wrapped_ != nullptr) {
-    wrapped_->OnPushPromiseEnd();
-  }
-}
-
-void LoggingQuicHttpFrameDecoderListener::OnPing(
-    const QuicHttpFrameHeader& header,
-    const QuicHttpPingFields& ping) {
-  VLOG(1) << "OnPing: " << header << "; ping: " << ping;
-  if (wrapped_ != nullptr) {
-    wrapped_->OnPing(header, ping);
-  }
-}
-
-void LoggingQuicHttpFrameDecoderListener::OnPingAck(
-    const QuicHttpFrameHeader& header,
-    const QuicHttpPingFields& ping) {
-  VLOG(1) << "OnPingAck: " << header << "; ping: " << ping;
-  if (wrapped_ != nullptr) {
-    wrapped_->OnPingAck(header, ping);
-  }
-}
-
-void LoggingQuicHttpFrameDecoderListener::OnGoAwayStart(
-    const QuicHttpFrameHeader& header,
-    const QuicHttpGoAwayFields& goaway) {
-  VLOG(1) << "OnGoAwayStart: " << header << "; goaway: " << goaway;
-  if (wrapped_ != nullptr) {
-    wrapped_->OnGoAwayStart(header, goaway);
-  }
-}
-
-void LoggingQuicHttpFrameDecoderListener::OnGoAwayOpaqueData(const char* data,
-                                                             size_t len) {
-  VLOG(1) << "OnGoAwayOpaqueData: len=" << len;
-  if (wrapped_ != nullptr) {
-    wrapped_->OnGoAwayOpaqueData(data, len);
-  }
-}
-
-void LoggingQuicHttpFrameDecoderListener::OnGoAwayEnd() {
-  VLOG(1) << "OnGoAwayEnd";
-  if (wrapped_ != nullptr) {
-    wrapped_->OnGoAwayEnd();
-  }
-}
-
-void LoggingQuicHttpFrameDecoderListener::OnWindowUpdate(
-    const QuicHttpFrameHeader& header,
-    uint32_t increment) {
-  VLOG(1) << "OnWindowUpdate: " << header << "; increment=" << increment;
-  if (wrapped_ != nullptr) {
-    wrapped_->OnWindowUpdate(header, increment);
-  }
-}
-
-void LoggingQuicHttpFrameDecoderListener::OnAltSvcStart(
-    const QuicHttpFrameHeader& header,
-    size_t origin_length,
-    size_t value_length) {
-  VLOG(1) << "OnAltSvcStart: " << header << "; origin_length: " << origin_length
-          << "; value_length: " << value_length;
-  if (wrapped_ != nullptr) {
-    wrapped_->OnAltSvcStart(header, origin_length, value_length);
-  }
-}
-
-void LoggingQuicHttpFrameDecoderListener::OnAltSvcOriginData(const char* data,
-                                                             size_t len) {
-  VLOG(1) << "OnAltSvcOriginData: len=" << len;
-  if (wrapped_ != nullptr) {
-    wrapped_->OnAltSvcOriginData(data, len);
-  }
-}
-
-void LoggingQuicHttpFrameDecoderListener::OnAltSvcValueData(const char* data,
-                                                            size_t len) {
-  VLOG(1) << "OnAltSvcValueData: len=" << len;
-  if (wrapped_ != nullptr) {
-    wrapped_->OnAltSvcValueData(data, len);
-  }
-}
-
-void LoggingQuicHttpFrameDecoderListener::OnAltSvcEnd() {
-  VLOG(1) << "OnAltSvcEnd";
-  if (wrapped_ != nullptr) {
-    wrapped_->OnAltSvcEnd();
-  }
-}
-
-void LoggingQuicHttpFrameDecoderListener::OnUnknownStart(
-    const QuicHttpFrameHeader& header) {
-  VLOG(1) << "OnUnknownStart: " << header;
-  if (wrapped_ != nullptr) {
-    wrapped_->OnUnknownStart(header);
-  }
-}
-
-void LoggingQuicHttpFrameDecoderListener::OnUnknownPayload(const char* data,
-                                                           size_t len) {
-  VLOG(1) << "OnUnknownPayload: len=" << len;
-  if (wrapped_ != nullptr) {
-    wrapped_->OnUnknownPayload(data, len);
-  }
-}
-
-void LoggingQuicHttpFrameDecoderListener::OnUnknownEnd() {
-  VLOG(1) << "OnUnknownEnd";
-  if (wrapped_ != nullptr) {
-    wrapped_->OnUnknownEnd();
-  }
-}
-
-void LoggingQuicHttpFrameDecoderListener::OnPaddingTooLong(
-    const QuicHttpFrameHeader& header,
-    size_t missing_length) {
-  VLOG(1) << "OnPaddingTooLong: " << header
-          << "; missing_length: " << missing_length;
-  if (wrapped_ != nullptr) {
-    wrapped_->OnPaddingTooLong(header, missing_length);
-  }
-}
-
-void LoggingQuicHttpFrameDecoderListener::OnFrameSizeError(
-    const QuicHttpFrameHeader& header) {
-  VLOG(1) << "OnFrameSizeError: " << header;
-  if (wrapped_ != nullptr) {
-    wrapped_->OnFrameSizeError(header);
-  }
-}
-
-}  // namespace quic
diff --git a/net/third_party/quic/http/decoder/quic_http_frame_decoder_listener_test_util.h b/net/third_party/quic/http/decoder/quic_http_frame_decoder_listener_test_util.h
deleted file mode 100644
index a13a4fe..0000000
--- a/net/third_party/quic/http/decoder/quic_http_frame_decoder_listener_test_util.h
+++ /dev/null
@@ -1,146 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_THIRD_PARTY_QUIC_HTTP_DECODER_QUIC_HTTP_FRAME_DECODER_LISTENER_TEST_UTIL_H_
-#define NET_THIRD_PARTY_QUIC_HTTP_DECODER_QUIC_HTTP_FRAME_DECODER_LISTENER_TEST_UTIL_H_
-
-#include <stddef.h>
-
-#include <cstdint>
-
-#include "net/third_party/quic/http/decoder/quic_http_frame_decoder_listener.h"
-#include "net/third_party/quic/http/quic_http_constants.h"
-#include "net/third_party/quic/http/quic_http_structures.h"
-
-namespace quic {
-
-// Fail if any of the methods are called. Allows a test to override only the
-// expected calls.
-class FailingQuicHttpFrameDecoderListener
-    : public QuicHttpFrameDecoderListener {
- public:
-  FailingQuicHttpFrameDecoderListener();
-  ~FailingQuicHttpFrameDecoderListener() override;
-
-  // TODO(jamessynge): Remove OnFrameHeader once done with supporting
-  // spdy::SpdyFramer's exact states.
-  bool OnFrameHeader(const QuicHttpFrameHeader& header) override;
-  void OnDataStart(const QuicHttpFrameHeader& header) override;
-  void OnDataPayload(const char* data, size_t len) override;
-  void OnDataEnd() override;
-  void OnHeadersStart(const QuicHttpFrameHeader& header) override;
-  void OnHeadersPriority(const QuicHttpPriorityFields& priority) override;
-  void OnHpackFragment(const char* data, size_t len) override;
-  void OnHeadersEnd() override;
-  void OnPriorityFrame(const QuicHttpFrameHeader& header,
-                       const QuicHttpPriorityFields& priority) override;
-  void OnContinuationStart(const QuicHttpFrameHeader& header) override;
-  void OnContinuationEnd() override;
-  void OnPadLength(size_t trailing_length) override;
-  void OnPadding(const char* padding, size_t skipped_length) override;
-  void OnRstStream(const QuicHttpFrameHeader& header,
-                   QuicHttpErrorCode error_code) override;
-  void OnSettingsStart(const QuicHttpFrameHeader& header) override;
-  void OnSetting(const QuicHttpSettingFields& setting_fields) override;
-  void OnSettingsEnd() override;
-  void OnSettingsAck(const QuicHttpFrameHeader& header) override;
-  void OnPushPromiseStart(const QuicHttpFrameHeader& header,
-                          const QuicHttpPushPromiseFields& promise,
-                          size_t total_padding_length) override;
-  void OnPushPromiseEnd() override;
-  void OnPing(const QuicHttpFrameHeader& header,
-              const QuicHttpPingFields& ping) override;
-  void OnPingAck(const QuicHttpFrameHeader& header,
-                 const QuicHttpPingFields& ping) override;
-  void OnGoAwayStart(const QuicHttpFrameHeader& header,
-                     const QuicHttpGoAwayFields& goaway) override;
-  void OnGoAwayOpaqueData(const char* data, size_t len) override;
-  void OnGoAwayEnd() override;
-  void OnWindowUpdate(const QuicHttpFrameHeader& header,
-                      uint32_t increment) override;
-  void OnAltSvcStart(const QuicHttpFrameHeader& header,
-                     size_t origin_length,
-                     size_t value_length) override;
-  void OnAltSvcOriginData(const char* data, size_t len) override;
-  void OnAltSvcValueData(const char* data, size_t len) override;
-  void OnAltSvcEnd() override;
-  void OnUnknownStart(const QuicHttpFrameHeader& header) override;
-  void OnUnknownPayload(const char* data, size_t len) override;
-  void OnUnknownEnd() override;
-  void OnPaddingTooLong(const QuicHttpFrameHeader& header,
-                        size_t missing_length) override;
-  void OnFrameSizeError(const QuicHttpFrameHeader& header) override;
-
- private:
-  void EnsureNotAbstract() { FailingQuicHttpFrameDecoderListener instance; }
-};
-
-// VLOG's all the calls it receives, and forwards those calls to an optional
-// listener.
-class LoggingQuicHttpFrameDecoderListener
-    : public QuicHttpFrameDecoderListener {
- public:
-  LoggingQuicHttpFrameDecoderListener();
-  explicit LoggingQuicHttpFrameDecoderListener(
-      QuicHttpFrameDecoderListener* wrapped);
-  ~LoggingQuicHttpFrameDecoderListener() override;
-
-  // TODO(jamessynge): Remove OnFrameHeader once done with supporting
-  // spdy::SpdyFramer's exact states.
-  bool OnFrameHeader(const QuicHttpFrameHeader& header) override;
-  void OnDataStart(const QuicHttpFrameHeader& header) override;
-  void OnDataPayload(const char* data, size_t len) override;
-  void OnDataEnd() override;
-  void OnHeadersStart(const QuicHttpFrameHeader& header) override;
-  void OnHeadersPriority(const QuicHttpPriorityFields& priority) override;
-  void OnHpackFragment(const char* data, size_t len) override;
-  void OnHeadersEnd() override;
-  void OnPriorityFrame(const QuicHttpFrameHeader& header,
-                       const QuicHttpPriorityFields& priority) override;
-  void OnContinuationStart(const QuicHttpFrameHeader& header) override;
-  void OnContinuationEnd() override;
-  void OnPadLength(size_t trailing_length) override;
-  void OnPadding(const char* padding, size_t skipped_length) override;
-  void OnRstStream(const QuicHttpFrameHeader& header,
-                   QuicHttpErrorCode error_code) override;
-  void OnSettingsStart(const QuicHttpFrameHeader& header) override;
-  void OnSetting(const QuicHttpSettingFields& setting_fields) override;
-  void OnSettingsEnd() override;
-  void OnSettingsAck(const QuicHttpFrameHeader& header) override;
-  void OnPushPromiseStart(const QuicHttpFrameHeader& header,
-                          const QuicHttpPushPromiseFields& promise,
-                          size_t total_padding_length) override;
-  void OnPushPromiseEnd() override;
-  void OnPing(const QuicHttpFrameHeader& header,
-              const QuicHttpPingFields& ping) override;
-  void OnPingAck(const QuicHttpFrameHeader& header,
-                 const QuicHttpPingFields& ping) override;
-  void OnGoAwayStart(const QuicHttpFrameHeader& header,
-                     const QuicHttpGoAwayFields& goaway) override;
-  void OnGoAwayOpaqueData(const char* data, size_t len) override;
-  void OnGoAwayEnd() override;
-  void OnWindowUpdate(const QuicHttpFrameHeader& header,
-                      uint32_t increment) override;
-  void OnAltSvcStart(const QuicHttpFrameHeader& header,
-                     size_t origin_length,
-                     size_t value_length) override;
-  void OnAltSvcOriginData(const char* data, size_t len) override;
-  void OnAltSvcValueData(const char* data, size_t len) override;
-  void OnAltSvcEnd() override;
-  void OnUnknownStart(const QuicHttpFrameHeader& header) override;
-  void OnUnknownPayload(const char* data, size_t len) override;
-  void OnUnknownEnd() override;
-  void OnPaddingTooLong(const QuicHttpFrameHeader& header,
-                        size_t missing_length) override;
-  void OnFrameSizeError(const QuicHttpFrameHeader& header) override;
-
- private:
-  void EnsureNotAbstract() { LoggingQuicHttpFrameDecoderListener instance; }
-
-  QuicHttpFrameDecoderListener* wrapped_;
-};
-
-}  // namespace quic
-
-#endif  // NET_THIRD_PARTY_QUIC_HTTP_DECODER_QUIC_HTTP_FRAME_DECODER_LISTENER_TEST_UTIL_H_
diff --git a/net/third_party/quic/http/decoder/quic_http_frame_decoder_state.cc b/net/third_party/quic/http/decoder/quic_http_frame_decoder_state.cc
deleted file mode 100644
index f47b5e7..0000000
--- a/net/third_party/quic/http/decoder/quic_http_frame_decoder_state.cc
+++ /dev/null
@@ -1,82 +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 "net/third_party/quic/http/decoder/quic_http_frame_decoder_state.h"
-
-namespace quic {
-
-QuicHttpDecodeStatus QuicHttpFrameDecoderState::ReadPadLength(
-    QuicHttpDecodeBuffer* db,
-    bool report_pad_length) {
-  DVLOG(2) << "ReadPadLength db->Remaining=" << db->Remaining()
-           << "; payload_length=" << frame_header().payload_length;
-  DCHECK(IsPaddable());
-  DCHECK(frame_header().IsPadded());
-
-  // Pad Length is always at the start of the frame, so remaining_payload_
-  // should equal payload_length at this point.
-  const uint32_t total_payload = frame_header().payload_length;
-  DCHECK_EQ(total_payload, remaining_payload_);
-  DCHECK_EQ(0u, remaining_padding_);
-
-  if (db->HasData()) {
-    const uint32_t pad_length = db->DecodeUInt8();
-    const uint32_t total_padding = pad_length + 1;
-    if (total_padding <= total_payload) {
-      remaining_padding_ = pad_length;
-      remaining_payload_ = total_payload - total_padding;
-      if (report_pad_length) {
-        listener()->OnPadLength(pad_length);
-      }
-      return QuicHttpDecodeStatus::kDecodeDone;
-    }
-    const uint32_t missing_length = total_padding - total_payload;
-    // To allow for the possibility of recovery, record the number of
-    // remaining bytes of the frame's payload (invalid though it is)
-    // in remaining_payload_.
-    remaining_payload_ = total_payload - 1;  // 1 for sizeof(Pad Length).
-    remaining_padding_ = 0;
-    listener()->OnPaddingTooLong(frame_header(), missing_length);
-    return QuicHttpDecodeStatus::kDecodeError;
-  }
-
-  if (total_payload == 0) {
-    remaining_payload_ = 0;
-    remaining_padding_ = 0;
-    listener()->OnPaddingTooLong(frame_header(), 1);
-    return QuicHttpDecodeStatus::kDecodeError;
-  }
-  // Need to wait for another buffer.
-  return QuicHttpDecodeStatus::kDecodeInProgress;
-}
-
-bool QuicHttpFrameDecoderState::SkipPadding(QuicHttpDecodeBuffer* db) {
-  DVLOG(2) << "SkipPadding remaining_padding_=" << remaining_padding_
-           << ", db->Remaining=" << db->Remaining()
-           << ", header: " << frame_header();
-  DCHECK_EQ(remaining_payload_, 0u);
-  DCHECK(IsPaddable()) << "header: " << frame_header();
-  DCHECK_GE(remaining_padding_, 0u);
-  DCHECK(remaining_padding_ == 0 || frame_header().IsPadded())
-      << "remaining_padding_=" << remaining_padding_
-      << ", header: " << frame_header();
-  const size_t avail = AvailablePadding(db);
-  if (avail > 0) {
-    listener()->OnPadding(db->cursor(), avail);
-    db->AdvanceCursor(avail);
-    remaining_padding_ -= avail;
-  }
-  return remaining_padding_ == 0;
-}
-
-QuicHttpDecodeStatus QuicHttpFrameDecoderState::ReportFrameSizeError() {
-  DVLOG(2) << "QuicHttpFrameDecoderState::ReportFrameSizeError: "
-           << " remaining_payload_=" << remaining_payload_
-           << "; remaining_padding_=" << remaining_padding_
-           << ", header: " << frame_header();
-  listener()->OnFrameSizeError(frame_header());
-  return QuicHttpDecodeStatus::kDecodeError;
-}
-
-}  // namespace quic
diff --git a/net/third_party/quic/http/decoder/quic_http_frame_decoder_state.h b/net/third_party/quic/http/decoder/quic_http_frame_decoder_state.h
deleted file mode 100644
index d93a9c38..0000000
--- a/net/third_party/quic/http/decoder/quic_http_frame_decoder_state.h
+++ /dev/null
@@ -1,259 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_THIRD_PARTY_QUIC_HTTP_DECODER_QUIC_HTTP_FRAME_DECODER_STATE_H_
-#define NET_THIRD_PARTY_QUIC_HTTP_DECODER_QUIC_HTTP_FRAME_DECODER_STATE_H_
-
-// QuicHttpFrameDecoderState provides state and behaviors in support of decoding
-// the common frame header and the payload of all frame types.
-// It is an input to all of the payload decoders.
-
-// TODO(jamessynge): Since QuicHttpFrameDecoderState has far more than state in
-// it, rename to FrameDecoderHelper, or similar.
-
-#include <stddef.h>
-
-#include <cstdint>
-
-#include "base/logging.h"
-#include "net/third_party/quic/http/decoder/quic_http_decode_buffer.h"
-#include "net/third_party/quic/http/decoder/quic_http_decode_status.h"
-#include "net/third_party/quic/http/decoder/quic_http_frame_decoder_listener.h"
-#include "net/third_party/quic/http/decoder/quic_http_structure_decoder.h"
-#include "net/third_party/quic/http/quic_http_constants.h"
-#include "net/third_party/quic/http/quic_http_structures.h"
-#include "net/third_party/quic/platform/api/quic_export.h"
-
-namespace quic {
-namespace test {
-class QuicHttpFrameDecoderStatePeer;
-}  // namespace test
-
-class QUIC_EXPORT_PRIVATE QuicHttpFrameDecoderState {
- public:
-  QuicHttpFrameDecoderState() {}
-
-  // Sets the listener which the decoders should call as they decode HTTP/2
-  // frames. The listener can be changed at any time, which allows for replacing
-  // it with a no-op listener when an error is detected, either by the payload
-  // decoder (OnPaddingTooLong or OnFrameSizeError) or by the "real" listener.
-  // That in turn allows us to define QuicHttpFrameDecoderListener such that all
-  // methods have return type void, with no direct way to indicate whether the
-  // decoder should stop, and to eliminate from the decoder all checks of the
-  // return value. Instead the listener/caller can simply replace the current
-  // listener with a no-op listener implementation.
-  // TODO(jamessynge): Make set_listener private as only QuicHttpFrameDecoder
-  // and tests need to set it, so it doesn't need to be public.
-  void set_listener(QuicHttpFrameDecoderListener* listener) {
-    listener_ = listener;
-  }
-  QuicHttpFrameDecoderListener* listener() const { return listener_; }
-
-  // The most recently decoded frame header.
-  const QuicHttpFrameHeader& frame_header() const { return frame_header_; }
-
-  // Decode a structure in the payload, adjusting remaining_payload_ to account
-  // for the consumed portion of the payload. Returns kDecodeDone when fully
-  // decoded, kDecodeError if it ran out of payload before decoding completed,
-  // and kDecodeInProgress if the decode buffer didn't have enough of the
-  // remaining payload.
-  template <class S>
-  QuicHttpDecodeStatus StartDecodingStructureInPayload(
-      S* out,
-      QuicHttpDecodeBuffer* db) {
-    DVLOG(2) << __func__ << "\n\tdb->Remaining=" << db->Remaining()
-             << "\n\tremaining_payload_=" << remaining_payload_
-             << "\n\tneed=" << S::EncodedSize();
-    QuicHttpDecodeStatus status =
-        structure_decoder_.Start(out, db, &remaining_payload_);
-    if (status != QuicHttpDecodeStatus::kDecodeError) {
-      return status;
-    }
-    DVLOG(2) << "StartDecodingStructureInPayload: detected frame size error";
-    return ReportFrameSizeError();
-  }
-
-  // Resume decoding of a structure that has been split across buffers,
-  // adjusting remaining_payload_ to account for the consumed portion of
-  // the payload. Returns values are as for StartDecodingStructureInPayload.
-  template <class S>
-  QuicHttpDecodeStatus ResumeDecodingStructureInPayload(
-      S* out,
-      QuicHttpDecodeBuffer* db) {
-    DVLOG(2) << __func__ << "\n\tdb->Remaining=" << db->Remaining()
-             << "\n\tremaining_payload_=" << remaining_payload_;
-    if (structure_decoder_.Resume(out, db, &remaining_payload_)) {
-      return QuicHttpDecodeStatus::kDecodeDone;
-    } else if (remaining_payload_ > 0) {
-      return QuicHttpDecodeStatus::kDecodeInProgress;
-    } else {
-      DVLOG(2) << "ResumeDecodingStructureInPayload: detected frame size error";
-      return ReportFrameSizeError();
-    }
-  }
-
-  // Initializes the two remaining* fields, which is needed if the frame's
-  // payload is split across buffers, or the decoder calls ReadPadLength or
-  // StartDecodingStructureInPayload, and of course the methods below which
-  // read those fields, as their names imply.
-  void InitializeRemainders() {
-    remaining_payload_ = frame_header().payload_length;
-    // Note that remaining_total_payload() relies on remaining_padding_ being
-    // zero for frames that have no padding.
-    remaining_padding_ = 0;
-  }
-
-  // Returns the number of bytes of the frame's payload that remain to be
-  // decoded, including any trailing padding. This method must only be called
-  // after the variables have been initialized, which in practice means once a
-  // payload decoder has called InitializeRemainders and/or ReadPadLength.
-  size_t remaining_total_payload() const {
-    DCHECK(IsPaddable() || remaining_padding_ == 0) << frame_header();
-    return remaining_payload_ + remaining_padding_;
-  }
-
-  // Returns the number of bytes of the frame's payload that remain to be
-  // decoded, excluding any trailing padding. This method must only be called
-  // after the variable has been initialized, which in practice means once a
-  // payload decoder has called InitializeRemainders; ReadPadLength will deduct
-  // the total number of padding bytes from remaining_payload_, including the
-  // size of the Pad Length field itself (1 byte).
-  size_t remaining_payload() const { return remaining_payload_; }
-
-  // Returns the number of bytes of the frame's payload that remain to be
-  // decoded, including any trailing padding. This method must only be called if
-  // the frame type allows padding, and after the variable has been initialized,
-  // which in practice means once a payload decoder has called
-  // InitializeRemainders and/or ReadPadLength.
-  size_t remaining_payload_and_padding() const {
-    DCHECK(IsPaddable()) << frame_header();
-    return remaining_payload_ + remaining_padding_;
-  }
-
-  // Returns the number of bytes of trailing padding after the payload that
-  // remain to be decoded. This method must only be called if the frame type
-  // allows padding, and after the variable has been initialized, which in
-  // practice means once a payload decoder has called InitializeRemainders,
-  // and isn't set to a non-zero value until ReadPadLength has been called.
-  uint32_t remaining_padding() const {
-    DCHECK(IsPaddable()) << frame_header();
-    return remaining_padding_;
-  }
-
-  // Returns the amount of trailing padding after the payload that remains to be
-  // decoded.
-  uint32_t remaining_padding_for_test() const { return remaining_padding_; }
-
-  // How many bytes of the remaining payload are in db?
-  size_t AvailablePayload(QuicHttpDecodeBuffer* db) const {
-    return db->MinLengthRemaining(remaining_payload_);
-  }
-
-  // How many bytes of the remaining payload and padding are in db?
-  // Call only for frames whose type is paddable.
-  size_t AvailablePayloadAndPadding(QuicHttpDecodeBuffer* db) const {
-    DCHECK(IsPaddable()) << frame_header();
-    return db->MinLengthRemaining(remaining_payload_ + remaining_padding_);
-  }
-
-  // How many bytes of the padding that have not yet been skipped are in db?
-  // Call only after remaining_padding_ has been set (for padded frames), or
-  // been cleared (for unpadded frames); and after all of the non-padding
-  // payload has been decoded.
-  size_t AvailablePadding(QuicHttpDecodeBuffer* db) const {
-    DCHECK(IsPaddable()) << frame_header();
-    DCHECK_EQ(remaining_payload_, 0u);
-    return db->MinLengthRemaining(remaining_padding_);
-  }
-
-  // Reduces remaining_payload_ by amount. To be called by a payload decoder
-  // after it has passed a variable length portion of the payload to the
-  // listener; remaining_payload_ will be automatically reduced when fixed
-  // size structures and padding, including the Pad Length field, are decoded.
-  void ConsumePayload(size_t amount) {
-    DCHECK_LE(amount, remaining_payload_);
-    remaining_payload_ -= amount;
-  }
-
-  // Reads the Pad Length field into remaining_padding_, and appropriately sets
-  // remaining_payload_. When present, the Pad Length field is always the first
-  // field in the payload, which this method relies on so that the caller need
-  // not set remaining_payload_ before calling this method.
-  // If report_pad_length is true, calls the listener's OnPadLength method when
-  // it decodes the Pad Length field.
-  // Returns kDecodeDone if the decode buffer was not empty (i.e. because the
-  // field is only a single byte long, it can always be decoded if the buffer is
-  // not empty).
-  // Returns kDecodeError if the buffer is empty because the frame has no
-  // payload (i.e. payload_length() == 0).
-  // Returns kDecodeInProgress if the buffer is empty but the frame has a
-  // payload.
-  QuicHttpDecodeStatus ReadPadLength(QuicHttpDecodeBuffer* db,
-                                     bool report_pad_length);
-
-  // Skip the trailing padding bytes; only call once remaining_payload_==0.
-  // Returns true when the padding has been skipped.
-  // Does NOT check that the padding is all zeroes.
-  bool SkipPadding(QuicHttpDecodeBuffer* db);
-
-  // Calls the listener's OnFrameSizeError method and returns kDecodeError.
-  QuicHttpDecodeStatus ReportFrameSizeError();
-
- private:
-  friend class QuicHttpFrameDecoder;
-  friend class test::QuicHttpFrameDecoderStatePeer;
-
-  // Starts the decoding of a common frame header. Returns true if completed the
-  // decoding, false if the decode buffer didn't have enough data in it, in
-  // which case the decode buffer will have been drained and the caller should
-  // call ResumeDecodingFrameHeader when more data is available. This is called
-  // from QuicHttpFrameDecoder, a friend class.
-  bool StartDecodingFrameHeader(QuicHttpDecodeBuffer* db) {
-    return structure_decoder_.Start(&frame_header_, db);
-  }
-
-  // Resumes decoding the common frame header after the preceding call to
-  // StartDecodingFrameHeader returned false, as did any subsequent calls to
-  // ResumeDecodingFrameHeader. This is called from QuicHttpFrameDecoder,
-  // a friend class.
-  bool ResumeDecodingFrameHeader(QuicHttpDecodeBuffer* db) {
-    return structure_decoder_.Resume(&frame_header_, db);
-  }
-
-  // Clear any of the flags in the frame header that aren't set in valid_flags.
-  void RetainFlags(uint8_t valid_flags) {
-    frame_header_.RetainFlags(valid_flags);
-  }
-
-  // Clear all of the flags in the frame header; for use with frame types that
-  // don't define any flags, such as WINDOW_UPDATE.
-  void ClearFlags() { frame_header_.flags = QuicHttpFrameFlag(); }
-
-  // Returns true if the type of frame being decoded can have padding.
-  bool IsPaddable() const {
-    return frame_header().type == QuicHttpFrameType::DATA ||
-           frame_header().type == QuicHttpFrameType::HEADERS ||
-           frame_header().type == QuicHttpFrameType::PUSH_PROMISE;
-  }
-
-  QuicHttpFrameDecoderListener* listener_ = nullptr;
-  QuicHttpFrameHeader frame_header_;
-
-  // Number of bytes remaining to be decoded, if set; does not include the
-  // trailing padding once the length of padding has been determined.
-  // See ReadPadLength.
-  uint32_t remaining_payload_;
-
-  // The amount of trailing padding after the payload that remains to be
-  // decoded. See ReadPadLength.
-  uint32_t remaining_padding_;
-
-  // Generic decoder of structures, which takes care of buffering the needed
-  // bytes if the encoded structure is split across decode buffers.
-  QuicHttpStructureDecoder structure_decoder_;
-};
-
-}  // namespace quic
-
-#endif  // NET_THIRD_PARTY_QUIC_HTTP_DECODER_QUIC_HTTP_FRAME_DECODER_STATE_H_
diff --git a/net/third_party/quic/http/decoder/quic_http_frame_decoder_state_test_util.cc b/net/third_party/quic/http/decoder/quic_http_frame_decoder_state_test_util.cc
deleted file mode 100644
index 7d6058e8..0000000
--- a/net/third_party/quic/http/decoder/quic_http_frame_decoder_state_test_util.cc
+++ /dev/null
@@ -1,25 +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 "net/third_party/quic/http/decoder/quic_http_frame_decoder_state_test_util.h"
-
-#include "base/logging.h"
-#include "net/third_party/quic/http/decoder/quic_http_structure_decoder_test_util.h"
-#include "net/third_party/quic/http/quic_http_structures.h"
-#include "net/third_party/quic/http/quic_http_structures_test_util.h"
-#include "net/third_party/quic/http/tools/quic_http_random_decoder_test.h"
-
-namespace quic {
-namespace test {
-
-// static
-void QuicHttpFrameDecoderStatePeer::set_frame_header(
-    const QuicHttpFrameHeader& header,
-    QuicHttpFrameDecoderState* p) {
-  VLOG(1) << "QuicHttpFrameDecoderStatePeer::set_frame_header " << header;
-  p->frame_header_ = header;
-}
-
-}  // namespace test
-}  // namespace quic
diff --git a/net/third_party/quic/http/decoder/quic_http_frame_decoder_state_test_util.h b/net/third_party/quic/http/decoder/quic_http_frame_decoder_state_test_util.h
deleted file mode 100644
index da16d250..0000000
--- a/net/third_party/quic/http/decoder/quic_http_frame_decoder_state_test_util.h
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_THIRD_PARTY_QUIC_HTTP_DECODER_QUIC_HTTP_FRAME_DECODER_STATE_TEST_UTIL_H_
-#define NET_THIRD_PARTY_QUIC_HTTP_DECODER_QUIC_HTTP_FRAME_DECODER_STATE_TEST_UTIL_H_
-
-#include "net/third_party/quic/http/decoder/quic_http_frame_decoder_state.h"
-#include "net/third_party/quic/http/quic_http_structures.h"
-#include "net/third_party/quic/http/tools/quic_http_random_decoder_test.h"
-
-namespace quic {
-namespace test {
-
-class QuicHttpFrameDecoderStatePeer {
- public:
-  // Inject a frame header into the QuicHttpFrameDecoderState.
-  // QuicHttpPayloadDecoderBaseTest::StartDecoding calls this just after calling
-  // Randomize (above), to simulate a full frame decoder having just finished
-  // decoding the common frame header and then calling the appropriate payload
-  // decoder based on the frame type in that frame header.
-  static void set_frame_header(const QuicHttpFrameHeader& header,
-                               QuicHttpFrameDecoderState* p);
-};
-
-}  // namespace test
-}  // namespace quic
-
-#endif  // NET_THIRD_PARTY_QUIC_HTTP_DECODER_QUIC_HTTP_FRAME_DECODER_STATE_TEST_UTIL_H_
diff --git a/net/third_party/quic/http/decoder/quic_http_frame_decoder_test.cc b/net/third_party/quic/http/decoder/quic_http_frame_decoder_test.cc
deleted file mode 100644
index e74254102..0000000
--- a/net/third_party/quic/http/decoder/quic_http_frame_decoder_test.cc
+++ /dev/null
@@ -1,939 +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 "net/third_party/quic/http/decoder/quic_http_frame_decoder.h"
-
-// Tests of QuicHttpFrameDecoder.
-
-#include <vector>
-
-#include "base/logging.h"
-#include "net/third_party/quic/http/quic_http_constants.h"
-#include "net/third_party/quic/http/test_tools/quic_http_frame_parts.h"
-#include "net/third_party/quic/http/test_tools/quic_http_frame_parts_collector_listener.h"
-#include "net/third_party/quic/http/tools/quic_http_random_decoder_test.h"
-#include "net/third_party/quic/platform/api/quic_reconstruct_object.h"
-#include "net/third_party/quic/platform/api/quic_string.h"
-#include "net/third_party/quic/platform/api/quic_string_piece.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using ::testing::AssertionResult;
-using ::testing::AssertionSuccess;
-
-namespace quic {
-namespace test {
-class QuicHttpFrameDecoderPeer {
- public:
-  static size_t remaining_total_payload(QuicHttpFrameDecoder* decoder) {
-    return decoder->frame_decoder_state_.remaining_total_payload();
-  }
-};
-
-namespace {
-
-class QuicHttpFrameDecoderTest : public QuicHttpRandomDecoderTest {
- protected:
-  void SetUp() override {
-    // On any one run of this suite, we'll always choose the same value for
-    // use_default_reconstruct_ because the random seed is the same for each
-    // test case, but across runs the random seed changes.
-    use_default_reconstruct_ = Random().OneIn(2);
-  }
-
-  QuicHttpDecodeStatus StartDecoding(QuicHttpDecodeBuffer* db) override {
-    DVLOG(2) << "StartDecoding, db->Remaining=" << db->Remaining();
-    collector_.Reset();
-    PrepareDecoder();
-
-    QuicHttpDecodeStatus status = decoder_.DecodeFrame(db);
-    if (status != QuicHttpDecodeStatus::kDecodeInProgress) {
-      // Keep track of this so that a concrete test can verify that both fast
-      // and slow decoding paths have been tested.
-      ++fast_decode_count_;
-      if (status == QuicHttpDecodeStatus::kDecodeError) {
-        ConfirmDiscardsRemainingPayload();
-      }
-    }
-    return status;
-  }
-
-  QuicHttpDecodeStatus ResumeDecoding(QuicHttpDecodeBuffer* db) override {
-    DVLOG(2) << "ResumeDecoding, db->Remaining=" << db->Remaining();
-    QuicHttpDecodeStatus status = decoder_.DecodeFrame(db);
-    if (status != QuicHttpDecodeStatus::kDecodeInProgress) {
-      // Keep track of this so that a concrete test can verify that both fast
-      // and slow decoding paths have been tested.
-      ++slow_decode_count_;
-      if (status == QuicHttpDecodeStatus::kDecodeError) {
-        ConfirmDiscardsRemainingPayload();
-      }
-    }
-    return status;
-  }
-
-  // When an error is returned, the decoder is in state kDiscardPayload, and
-  // stays there until the remaining bytes of the frame's payload have been
-  // skipped over. There are no callbacks for this situation.
-  void ConfirmDiscardsRemainingPayload() {
-    ASSERT_TRUE(decoder_.IsDiscardingPayload());
-    size_t remaining =
-        QuicHttpFrameDecoderPeer::remaining_total_payload(&decoder_);
-    // The decoder will discard the remaining bytes, but not go beyond that,
-    // which these conditions verify.
-    size_t extra = 10;
-    QuicString junk(remaining + extra, '0');
-    QuicHttpDecodeBuffer tmp(junk);
-    EXPECT_EQ(QuicHttpDecodeStatus::kDecodeDone, decoder_.DecodeFrame(&tmp));
-    EXPECT_EQ(remaining, tmp.Offset());
-    EXPECT_EQ(extra, tmp.Remaining());
-    EXPECT_FALSE(decoder_.IsDiscardingPayload());
-  }
-
-  void PrepareDecoder() {
-    // Save and restore the maximum_payload_size when reconstructing
-    // the decoder.
-    size_t maximum_payload_size = decoder_.maximum_payload_size();
-
-    // Alternate which constructor is used.
-    if (use_default_reconstruct_) {
-      QuicDefaultReconstructObject(&decoder_, RandomPtr());
-      decoder_.set_listener(&collector_);
-    } else {
-      QuicReconstructObject(&decoder_, RandomPtr(), &collector_);
-    }
-    decoder_.set_maximum_payload_size(maximum_payload_size);
-
-    use_default_reconstruct_ = !use_default_reconstruct_;
-  }
-
-  void ResetDecodeSpeedCounters() {
-    fast_decode_count_ = 0;
-    slow_decode_count_ = 0;
-  }
-
-  AssertionResult VerifyCollected(const QuicHttpFrameParts& expected) {
-    VERIFY_FALSE(collector_.IsInProgress());
-    VERIFY_EQ(1u, collector_.size());
-    VERIFY_AND_RETURN_SUCCESS(expected.VerifyEquals(*collector_.frame(0)));
-  }
-
-  AssertionResult DecodePayloadAndValidateSeveralWays(
-      QuicStringPiece payload,
-      const Validator& validator) {
-    QuicHttpDecodeBuffer db(payload);
-    bool start_decoding_requires_non_empty = false;
-    return DecodeAndValidateSeveralWays(&db, start_decoding_requires_non_empty,
-                                        validator);
-  }
-
-  // Decode one frame's payload and confirm that the listener recorded the
-  // expected QuicHttpFrameParts instance, and only one QuicHttpFrameParts
-  // instance. The payload will be decoded several times with different
-  // partitionings of the payload, and after each the validator will be called.
-  AssertionResult DecodePayloadAndValidateSeveralWays(
-      QuicStringPiece payload,
-      const QuicHttpFrameParts& expected) {
-    auto validator = [&expected, this](
-                         const QuicHttpDecodeBuffer& input,
-                         QuicHttpDecodeStatus status) -> AssertionResult {
-      VERIFY_EQ(status, QuicHttpDecodeStatus::kDecodeDone);
-      VERIFY_AND_RETURN_SUCCESS(VerifyCollected(expected));
-    };
-    ResetDecodeSpeedCounters();
-    VERIFY_SUCCESS(DecodePayloadAndValidateSeveralWays(
-        payload, ValidateDoneAndEmpty(validator)));
-    VERIFY_GT(fast_decode_count_, 0u);
-    VERIFY_GT(slow_decode_count_, 0u);
-
-    // Repeat with more input; it should stop without reading that input.
-    QuicString next_frame = Random().RandString(10);
-    QuicString input(payload);
-    input += next_frame;
-
-    ResetDecodeSpeedCounters();
-    VERIFY_SUCCESS(DecodePayloadAndValidateSeveralWays(
-        payload, ValidateDoneAndOffset(payload.size(), validator)));
-    VERIFY_GT(fast_decode_count_, 0u);
-    VERIFY_GT(slow_decode_count_, 0u);
-
-    return AssertionSuccess();
-  }
-
-  template <size_t N>
-  AssertionResult DecodePayloadAndValidateSeveralWays(
-      const char (&buf)[N],
-      const QuicHttpFrameParts& expected) {
-    return DecodePayloadAndValidateSeveralWays(QuicStringPiece(buf, N),
-                                               expected);
-  }
-
-  template <size_t N>
-  AssertionResult DecodePayloadAndValidateSeveralWays(
-      const char (&buf)[N],
-      const QuicHttpFrameHeader& header) {
-    return DecodePayloadAndValidateSeveralWays(QuicStringPiece(buf, N),
-                                               QuicHttpFrameParts(header));
-  }
-
-  template <size_t N>
-  AssertionResult DecodePayloadExpectingError(
-      const char (&buf)[N],
-      const QuicHttpFrameParts& expected) {
-    auto validator = [&expected, this](
-                         const QuicHttpDecodeBuffer& input,
-                         QuicHttpDecodeStatus status) -> AssertionResult {
-      VERIFY_EQ(status, QuicHttpDecodeStatus::kDecodeError);
-      VERIFY_AND_RETURN_SUCCESS(VerifyCollected(expected));
-    };
-    ResetDecodeSpeedCounters();
-    EXPECT_TRUE(
-        DecodePayloadAndValidateSeveralWays(ToStringPiece(buf), validator));
-    EXPECT_GT(fast_decode_count_, 0u);
-    EXPECT_GT(slow_decode_count_, 0u);
-    return AssertionSuccess();
-  }
-
-  template <size_t N>
-  AssertionResult DecodePayloadExpectingFrameSizeError(
-      const char (&buf)[N],
-      QuicHttpFrameParts expected) {
-    expected.has_frame_size_error = true;
-    VERIFY_AND_RETURN_SUCCESS(DecodePayloadExpectingError(buf, expected));
-  }
-
-  template <size_t N>
-  AssertionResult DecodePayloadExpectingFrameSizeError(
-      const char (&buf)[N],
-      const QuicHttpFrameHeader& header) {
-    return DecodePayloadExpectingFrameSizeError(buf,
-                                                QuicHttpFrameParts(header));
-  }
-
-  // Count of payloads that are fully decoded by StartDecodingPayload or for
-  // which an error was detected by StartDecodingPayload.
-  size_t fast_decode_count_ = 0;
-
-  // Count of payloads that required calling ResumeDecodingPayload in order to
-  // decode completely, or for which an error was detected by
-  // ResumeDecodingPayload.
-  size_t slow_decode_count_ = 0;
-
-  QuicHttpFramePartsCollectorListener collector_;
-  QuicHttpFrameDecoder decoder_;
-  bool use_default_reconstruct_;
-};
-
-////////////////////////////////////////////////////////////////////////////////
-// Tests that pass the minimum allowed size for the frame type, which is often
-// empty. The tests are in order by frame type value (i.e. 0 for DATA frames).
-
-TEST_F(QuicHttpFrameDecoderTest, DataEmpty) {
-  const char kFrameData[] = {
-      0x00, 0x00, 0x00,        // Payload length: 0
-      0x00,                    // DATA
-      0x00,                    // Flags: none
-      0x00, 0x00, 0x00, 0x00,  // Stream ID: 0 (invalid but unchecked here)
-  };
-  QuicHttpFrameHeader header(0, QuicHttpFrameType::DATA, 0, 0);
-  QuicHttpFrameParts expected(header, "");
-  EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
-}
-
-TEST_F(QuicHttpFrameDecoderTest, HeadersEmpty) {
-  const char kFrameData[] = {
-      0x00, 0x00, 0x00,        // Payload length: 0
-      0x01,                    // HEADERS
-      0x00,                    // Flags: none
-      0x00, 0x00, 0x00, 0x01,  // Stream ID: 0  (REQUIRES ID)
-  };
-  QuicHttpFrameHeader header(0, QuicHttpFrameType::HEADERS, 0, 1);
-  QuicHttpFrameParts expected(header, "");
-  EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
-}
-
-TEST_F(QuicHttpFrameDecoderTest, Priority) {
-  const char kFrameData[] = {
-      0x00,  0x00, 0x05,        // Length: 5
-      0x02,                     //   Type: QUIC_HTTP_PRIORITY
-      0x00,                     //  Flags: none
-      0x00,  0x00, 0x00, 0x02,  // Stream: 2
-      0x80u, 0x00, 0x00, 0x01,  // Parent: 1 (Exclusive)
-      0x10,                     // Weight: 17
-  };
-  QuicHttpFrameHeader header(5, QuicHttpFrameType::QUIC_HTTP_PRIORITY, 0, 2);
-  QuicHttpFrameParts expected(header);
-  expected.opt_priority = QuicHttpPriorityFields(1, 17, true);
-  EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
-}
-
-TEST_F(QuicHttpFrameDecoderTest, RstStream) {
-  const char kFrameData[] = {
-      0x00, 0x00, 0x04,        // Length: 4
-      0x03,                    //   Type: RST_STREAM
-      0x00,                    //  Flags: none
-      0x00, 0x00, 0x00, 0x01,  // Stream: 1
-      0x00, 0x00, 0x00, 0x01,  //  Error: PROTOCOL_ERROR
-  };
-  QuicHttpFrameHeader header(4, QuicHttpFrameType::RST_STREAM, 0, 1);
-  QuicHttpFrameParts expected(header);
-  expected.opt_rst_stream_error_code = QuicHttpErrorCode::PROTOCOL_ERROR;
-  EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
-}
-
-TEST_F(QuicHttpFrameDecoderTest, SettingsEmpty) {
-  const char kFrameData[] = {
-      0x00, 0x00, 0x00,        // Length: 0
-      0x04,                    //   Type: SETTINGS
-      0x00,                    //  Flags: none
-      0x00, 0x00, 0x00, 0x01,  // Stream: 1 (invalid but unchecked here)
-  };
-  QuicHttpFrameHeader header(0, QuicHttpFrameType::SETTINGS, 0, 1);
-  EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, header));
-}
-
-TEST_F(QuicHttpFrameDecoderTest, SettingsAck) {
-  const char kFrameData[] = {
-      0x00, 0x00, 0x00,        //   Length: 6
-      0x04,                    //     Type: SETTINGS
-      0x01,                    //    Flags: QUIC_HTTP_ACK
-      0x00, 0x00, 0x00, 0x00,  //   Stream: 0
-  };
-  QuicHttpFrameHeader header(0, QuicHttpFrameType::SETTINGS,
-                             QuicHttpFrameFlag::QUIC_HTTP_ACK, 0);
-  QuicHttpFrameParts expected(header);
-  EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
-}
-
-TEST_F(QuicHttpFrameDecoderTest, PushPromiseMinimal) {
-  const char kFrameData[] = {
-      0x00, 0x00, 0x04,        // Payload length: 4
-      0x05,                    // PUSH_PROMISE
-      0x04,                    // Flags: QUIC_HTTP_END_HEADERS
-      0x00, 0x00, 0x00, 0x02,  //   Stream: 2 (invalid but unchecked here)
-      0x00, 0x00, 0x00, 0x01,  // Promised: 1 (invalid but unchecked here)
-  };
-  QuicHttpFrameHeader header(4, QuicHttpFrameType::PUSH_PROMISE,
-                             QuicHttpFrameFlag::QUIC_HTTP_END_HEADERS, 2);
-  QuicHttpFrameParts expected(header, "");
-  expected.opt_push_promise = QuicHttpPushPromiseFields{1};
-  EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
-}
-
-TEST_F(QuicHttpFrameDecoderTest, Ping) {
-  const char kFrameData[] = {
-      0x00,  0x00, 0x08,        //   Length: 8
-      0x06,                     //     Type: PING
-      0xfeu,                    //    Flags: no valid flags
-      0x00,  0x00, 0x00, 0x00,  //   Stream: 0
-      's',   'o',  'm',  'e',   // "some"
-      'd',   'a',  't',  'a',   // "data"
-  };
-  QuicHttpFrameHeader header(8, QuicHttpFrameType::PING, 0, 0);
-  QuicHttpFrameParts expected(header);
-  expected.opt_ping =
-      QuicHttpPingFields{{'s', 'o', 'm', 'e', 'd', 'a', 't', 'a'}};
-  EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
-}
-
-TEST_F(QuicHttpFrameDecoderTest, PingAck) {
-  const char kFrameData[] = {
-      0x00,  0x00, 0x08,  //   Length: 8
-      0x06,               //     Type: PING
-      0xffu,              //    Flags: QUIC_HTTP_ACK (plus all invalid flags)
-      0x00,  0x00, 0x00, 0x00,  //   Stream: 0
-      's',   'o',  'm',  'e',   // "some"
-      'd',   'a',  't',  'a',   // "data"
-  };
-  QuicHttpFrameHeader header(8, QuicHttpFrameType::PING,
-                             QuicHttpFrameFlag::QUIC_HTTP_ACK, 0);
-  QuicHttpFrameParts expected(header);
-  expected.opt_ping =
-      QuicHttpPingFields{{'s', 'o', 'm', 'e', 'd', 'a', 't', 'a'}};
-  EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
-}
-
-TEST_F(QuicHttpFrameDecoderTest, GoAwayMinimal) {
-  const char kFrameData[] = {
-      0x00,  0x00, 0x08,         // Length: 8 (no opaque data)
-      0x07,                      //   Type: GOAWAY
-      0xffu,                     //  Flags: 0xff (no valid flags)
-      0x00,  0x00, 0x00, 0x01,   // Stream: 1 (invalid but unchecked here)
-      0x80u, 0x00, 0x00, 0xffu,  //   Last: 255 (plus R bit)
-      0x00,  0x00, 0x00, 0x09,   //  Error: COMPRESSION_ERROR
-  };
-  QuicHttpFrameHeader header(8, QuicHttpFrameType::GOAWAY, 0, 1);
-  QuicHttpFrameParts expected(header);
-  expected.opt_goaway =
-      QuicHttpGoAwayFields(255, QuicHttpErrorCode::COMPRESSION_ERROR);
-  EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
-}
-
-TEST_F(QuicHttpFrameDecoderTest, WindowUpdate) {
-  const char kFrameData[] = {
-      0x00,  0x00, 0x04,        // Length: 4
-      0x08,                     //   Type: WINDOW_UPDATE
-      0x0f,                     //  Flags: 0xff (no valid flags)
-      0x00,  0x00, 0x00, 0x01,  // Stream: 1
-      0x80u, 0x00, 0x04, 0x00,  //   Incr: 1024 (plus R bit)
-  };
-  QuicHttpFrameHeader header(4, QuicHttpFrameType::WINDOW_UPDATE, 0, 1);
-  QuicHttpFrameParts expected(header);
-  expected.opt_window_update_increment = 1024;
-  EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
-}
-
-TEST_F(QuicHttpFrameDecoderTest, ContinuationEmpty) {
-  const char kFrameData[] = {
-      0x00, 0x00, 0x00,        // Payload length: 0
-      0x09,                    // CONTINUATION
-      0x00,                    // Flags: none
-      0x00, 0x00, 0x00, 0x00,  // Stream ID: 0 (invalid but unchecked here)
-  };
-  QuicHttpFrameHeader header(0, QuicHttpFrameType::CONTINUATION, 0, 0);
-  QuicHttpFrameParts expected(header);
-  EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
-}
-
-TEST_F(QuicHttpFrameDecoderTest, AltSvcMinimal) {
-  const char kFrameData[] = {
-      0x00,  0x00, 0x02,        // Payload length: 2
-      0x0a,                     // ALTSVC
-      0xffu,                    // Flags: none (plus 0xff)
-      0x00,  0x00, 0x00, 0x00,  // Stream ID: 0 (invalid but unchecked here)
-      0x00,  0x00,              // Origin Length: 0
-  };
-  QuicHttpFrameHeader header(2, QuicHttpFrameType::ALTSVC, 0, 0);
-  QuicHttpFrameParts expected(header);
-  expected.opt_altsvc_origin_length = 0;
-  expected.opt_altsvc_value_length = 0;
-  EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
-}
-
-TEST_F(QuicHttpFrameDecoderTest, UnknownEmpty) {
-  const char kFrameData[] = {
-      0x00,  0x00, 0x00,        // Payload length: 0
-      0x20,                     // 32 (unknown)
-      0xffu,                    // Flags: all
-      0x00,  0x00, 0x00, 0x00,  // Stream ID: 0
-  };
-  QuicHttpFrameHeader header(0, static_cast<QuicHttpFrameType>(32), 0xff, 0);
-  QuicHttpFrameParts expected(header);
-  EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Tests of longer payloads, for those frame types that allow longer payloads.
-
-TEST_F(QuicHttpFrameDecoderTest, DataPayload) {
-  const char kFrameData[] = {
-      0x00,  0x00, 0x03,        // Payload length: 7
-      0x00,                     // DATA
-      0x80u,                    // Flags: 0x80
-      0x00,  0x00, 0x02, 0x02,  // Stream ID: 514
-      'a',   'b',  'c',         // Data
-  };
-  QuicHttpFrameHeader header(3, QuicHttpFrameType::DATA, 0, 514);
-  QuicHttpFrameParts expected(header, "abc");
-  EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
-}
-
-TEST_F(QuicHttpFrameDecoderTest, HeadersPayload) {
-  const char kFrameData[] = {
-      0x00, 0x00, 0x03,  // Payload length: 3
-      0x01,              // HEADERS
-      0x05,              // Flags: QUIC_HTTP_END_STREAM | QUIC_HTTP_END_HEADERS
-      0x00, 0x00, 0x00, 0x02,  // Stream ID: 0  (REQUIRES ID)
-      'a',  'b',  'c',  // HPQUIC_HTTP_ACK fragment (doesn't have to be valid)
-  };
-  QuicHttpFrameHeader header(3, QuicHttpFrameType::HEADERS,
-                             QuicHttpFrameFlag::QUIC_HTTP_END_STREAM |
-                                 QuicHttpFrameFlag::QUIC_HTTP_END_HEADERS,
-                             2);
-  QuicHttpFrameParts expected(header, "abc");
-  EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
-}
-
-TEST_F(QuicHttpFrameDecoderTest, HeadersPriority) {
-  const char kFrameData[] = {
-      0x00,  0x00, 0x05,        // Payload length: 5
-      0x01,                     // HEADERS
-      0x20,                     // Flags: QUIC_HTTP_PRIORITY
-      0x00,  0x00, 0x00, 0x02,  // Stream ID: 0  (REQUIRES ID)
-      0x00,  0x00, 0x00, 0x01,  // Parent: 1 (Not Exclusive)
-      0xffu,                    // Weight: 256
-  };
-  QuicHttpFrameHeader header(5, QuicHttpFrameType::HEADERS,
-                             QuicHttpFrameFlag::QUIC_HTTP_PRIORITY, 2);
-  QuicHttpFrameParts expected(header);
-  expected.opt_priority = QuicHttpPriorityFields(1, 256, false);
-  EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
-}
-
-TEST_F(QuicHttpFrameDecoderTest, Settings) {
-  const char kFrameData[] = {
-      0x00, 0x00, 0x0c,        // Length: 12
-      0x04,                    //   Type: SETTINGS
-      0x00,                    //  Flags: none
-      0x00, 0x00, 0x00, 0x00,  // Stream: 0
-      0x00, 0x04,              //  Param: INITIAL_WINDOW_SIZE
-      0x0a, 0x0b, 0x0c, 0x0d,  //  Value: 168496141
-      0x00, 0x02,              //  Param: ENABLE_PUSH
-      0x00, 0x00, 0x00, 0x03,  //  Value: 3 (invalid but unchecked here)
-  };
-  QuicHttpFrameHeader header(12, QuicHttpFrameType::SETTINGS, 0, 0);
-  QuicHttpFrameParts expected(header);
-  expected.settings.push_back(QuicHttpSettingFields(
-      QuicHttpSettingsParameter::INITIAL_WINDOW_SIZE, 168496141));
-  expected.settings.push_back(
-      QuicHttpSettingFields(QuicHttpSettingsParameter::ENABLE_PUSH, 3));
-  EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
-}
-
-TEST_F(QuicHttpFrameDecoderTest, PushPromisePayload) {
-  const char kFrameData[] = {
-      0x00, 0x00, 7,            // Payload length: 7
-      0x05,                     // PUSH_PROMISE
-      0x04,                     // Flags: QUIC_HTTP_END_HEADERS
-      0x00, 0x00, 0x00, 0xffu,  // Stream ID: 255
-      0x00, 0x00, 0x01, 0x00,   // Promised: 256
-      'a',  'b',  'c',  // HPQUIC_HTTP_ACK fragment (doesn't have to be valid)
-  };
-  QuicHttpFrameHeader header(7, QuicHttpFrameType::PUSH_PROMISE,
-                             QuicHttpFrameFlag::QUIC_HTTP_END_HEADERS, 255);
-  QuicHttpFrameParts expected(header, "abc");
-  expected.opt_push_promise = QuicHttpPushPromiseFields{256};
-  EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
-}
-
-TEST_F(QuicHttpFrameDecoderTest, GoAwayOpaqueData) {
-  const char kFrameData[] = {
-      0x00,  0x00, 0x0e,        // Length: 14
-      0x07,                     //   Type: GOAWAY
-      0xffu,                    //  Flags: 0xff (no valid flags)
-      0x80u, 0x00, 0x00, 0x00,  // Stream: 0 (plus R bit)
-      0x00,  0x00, 0x01, 0x00,  //   Last: 256
-      0x00,  0x00, 0x00, 0x03,  //  Error: FLOW_CONTROL_ERROR
-      'o',   'p',  'a',  'q',  'u', 'e',
-  };
-  QuicHttpFrameHeader header(14, QuicHttpFrameType::GOAWAY, 0, 0);
-  QuicHttpFrameParts expected(header, "opaque");
-  expected.opt_goaway =
-      QuicHttpGoAwayFields(256, QuicHttpErrorCode::FLOW_CONTROL_ERROR);
-  EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
-}
-
-TEST_F(QuicHttpFrameDecoderTest, ContinuationPayload) {
-  const char kFrameData[] = {
-      0x00,  0x00, 0x03,        // Payload length: 3
-      0x09,                     // CONTINUATION
-      0xffu,                    // Flags: QUIC_HTTP_END_HEADERS | 0xfb
-      0x00,  0x00, 0x00, 0x02,  // Stream ID: 2
-      'a',   'b',  'c',         // Data
-  };
-  QuicHttpFrameHeader header(3, QuicHttpFrameType::CONTINUATION,
-                             QuicHttpFrameFlag::QUIC_HTTP_END_HEADERS, 2);
-  QuicHttpFrameParts expected(header, "abc");
-  EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
-}
-
-TEST_F(QuicHttpFrameDecoderTest, AltSvcPayload) {
-  const char kFrameData[] = {
-      0x00, 0x00, 0x08,        // Payload length: 3
-      0x0a,                    // ALTSVC
-      0x00,                    // Flags: none
-      0x00, 0x00, 0x00, 0x02,  // Stream ID: 2
-      0x00, 0x03,              // Origin Length: 0
-      'a',  'b',  'c',         // Origin
-      'd',  'e',  'f',         // Value
-  };
-  QuicHttpFrameHeader header(8, QuicHttpFrameType::ALTSVC, 0, 2);
-  QuicHttpFrameParts expected(header);
-  expected.SetAltSvcExpected("abc", "def");
-  EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
-}
-
-TEST_F(QuicHttpFrameDecoderTest, UnknownPayload) {
-  const char kFrameData[] = {
-      0x00, 0x00, 0x03,        // Payload length: 3
-      0x30,                    // 48 (unknown)
-      0x00,                    // Flags: none
-      0x00, 0x00, 0x00, 0x02,  // Stream ID: 2
-      'a',  'b',  'c',         // Payload
-  };
-  QuicHttpFrameHeader header(3, static_cast<QuicHttpFrameType>(48), 0, 2);
-  QuicHttpFrameParts expected(header, "abc");
-  EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Tests of padded payloads, for those frame types that allow padding.
-
-TEST_F(QuicHttpFrameDecoderTest, DataPayloadAndPadding) {
-  const char kFrameData[] = {
-      0x00, 0x00, 0x07,        // Payload length: 7
-      0x00,                    // DATA
-      0x09,                    // Flags: QUIC_HTTP_END_STREAM | QUIC_HTTP_PADDED
-      0x00, 0x00, 0x00, 0x02,  // Stream ID: 0  (REQUIRES ID)
-      0x03,                    // Pad Len
-      'a',  'b',  'c',         // Data
-      0x00, 0x00, 0x00,        // Padding
-  };
-  QuicHttpFrameHeader header(7, QuicHttpFrameType::DATA,
-                             QuicHttpFrameFlag::QUIC_HTTP_END_STREAM |
-                                 QuicHttpFrameFlag::QUIC_HTTP_PADDED,
-                             2);
-  size_t total_pad_length = 4;  // Including the Pad Length field.
-  QuicHttpFrameParts expected(header, "abc", total_pad_length);
-  EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
-}
-
-TEST_F(QuicHttpFrameDecoderTest, HeadersPayloadAndPadding) {
-  const char kFrameData[] = {
-      0x00, 0x00, 0x07,        // Payload length: 7
-      0x01,                    // HEADERS
-      0x08,                    // Flags: QUIC_HTTP_PADDED
-      0x00, 0x00, 0x00, 0x02,  // Stream ID: 0  (REQUIRES ID)
-      0x03,                    // Pad Len
-      'a',  'b',  'c',   // HPQUIC_HTTP_ACK fragment (doesn't have to be valid)
-      0x00, 0x00, 0x00,  // Padding
-  };
-  QuicHttpFrameHeader header(7, QuicHttpFrameType::HEADERS,
-                             QuicHttpFrameFlag::QUIC_HTTP_PADDED, 2);
-  size_t total_pad_length = 4;  // Including the Pad Length field.
-  QuicHttpFrameParts expected(header, "abc", total_pad_length);
-  EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
-}
-
-TEST_F(QuicHttpFrameDecoderTest, HeadersPayloadPriorityAndPadding) {
-  const char kFrameData[] = {
-      0x00,  0x00, 0x0c,        // Payload length: 12
-      0x01,                     // HEADERS
-      0xffu,                    // Flags: all, including undefined
-      0x00,  0x00, 0x00, 0x02,  // Stream ID: 0  (REQUIRES ID)
-      0x03,                     // Pad Len
-      0x80u, 0x00, 0x00, 0x01,  // Parent: 1 (Exclusive)
-      0x10,                     // Weight: 17
-      'a',   'b',  'c',   // HPQUIC_HTTP_ACK fragment (doesn't have to be valid)
-      0x00,  0x00, 0x00,  // Padding
-  };
-  QuicHttpFrameHeader header(12, QuicHttpFrameType::HEADERS,
-                             QuicHttpFrameFlag::QUIC_HTTP_END_STREAM |
-                                 QuicHttpFrameFlag::QUIC_HTTP_END_HEADERS |
-                                 QuicHttpFrameFlag::QUIC_HTTP_PADDED |
-                                 QuicHttpFrameFlag::QUIC_HTTP_PRIORITY,
-                             2);
-  size_t total_pad_length = 4;  // Including the Pad Length field.
-  QuicHttpFrameParts expected(header, "abc", total_pad_length);
-  expected.opt_priority = QuicHttpPriorityFields(1, 17, true);
-  EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
-}
-
-TEST_F(QuicHttpFrameDecoderTest, PushPromisePayloadAndPadding) {
-  const char kFrameData[] = {
-      0x00,  0x00, 11,  // Payload length: 11
-      0x05,             // PUSH_PROMISE
-      0xffu,  // Flags: QUIC_HTTP_END_HEADERS | QUIC_HTTP_PADDED | 0xf3
-      0x00,  0x00, 0x00, 0x01,  // Stream ID: 1
-      0x03,                     // Pad Len
-      0x00,  0x00, 0x00, 0x02,  // Promised: 2
-      'a',   'b',  'c',   // HPQUIC_HTTP_ACK fragment (doesn't have to be valid)
-      0x00,  0x00, 0x00,  // Padding
-  };
-  QuicHttpFrameHeader header(11, QuicHttpFrameType::PUSH_PROMISE,
-                             QuicHttpFrameFlag::QUIC_HTTP_END_HEADERS |
-                                 QuicHttpFrameFlag::QUIC_HTTP_PADDED,
-                             1);
-  size_t total_pad_length = 4;  // Including the Pad Length field.
-  QuicHttpFrameParts expected(header, "abc", total_pad_length);
-  expected.opt_push_promise = QuicHttpPushPromiseFields{2};
-  EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(kFrameData, expected));
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Payload too short errors.
-
-TEST_F(QuicHttpFrameDecoderTest, DataMissingPadLengthField) {
-  const char kFrameData[] = {
-      0x00, 0x00, 0x00,        // Payload length: 0
-      0x00,                    // DATA
-      0x08,                    // Flags: QUIC_HTTP_PADDED
-      0x00, 0x00, 0x00, 0x01,  // Stream ID: 1
-  };
-  QuicHttpFrameHeader header(0, QuicHttpFrameType::DATA,
-                             QuicHttpFrameFlag::QUIC_HTTP_PADDED, 1);
-  QuicHttpFrameParts expected(header);
-  expected.opt_missing_length = 1;
-  EXPECT_TRUE(DecodePayloadExpectingError(kFrameData, expected));
-}
-
-TEST_F(QuicHttpFrameDecoderTest, HeaderPaddingTooLong) {
-  const char kFrameData[] = {
-      0x00,  0x00, 0x02,        // Payload length: 0
-      0x01,                     // HEADERS
-      0x08,                     // Flags: QUIC_HTTP_PADDED
-      0x00,  0x01, 0x00, 0x00,  // Stream ID: 65536
-      0xffu,                    // Pad Len: 255
-      0x00,                     // Only one byte of padding
-  };
-  QuicHttpFrameHeader header(2, QuicHttpFrameType::HEADERS,
-                             QuicHttpFrameFlag::QUIC_HTTP_PADDED, 65536);
-  QuicHttpFrameParts expected(header);
-  expected.opt_missing_length = 254;
-  EXPECT_TRUE(DecodePayloadExpectingError(kFrameData, expected));
-}
-
-TEST_F(QuicHttpFrameDecoderTest, HeaderMissingPriority) {
-  const char kFrameData[] = {
-      0x00, 0x00, 0x04,        // Payload length: 0
-      0x01,                    // HEADERS
-      0x20,                    // Flags: QUIC_HTTP_PRIORITY
-      0x00, 0x01, 0x00, 0x00,  // Stream ID: 65536
-      0x00, 0x00, 0x00, 0x00,  // Priority (truncated)
-  };
-  QuicHttpFrameHeader header(4, QuicHttpFrameType::HEADERS,
-                             QuicHttpFrameFlag::QUIC_HTTP_PRIORITY, 65536);
-  EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header));
-}
-
-TEST_F(QuicHttpFrameDecoderTest, PriorityTooShort) {
-  const char kFrameData[] = {
-      0x00,  0x00, 0x04,        // Length: 5
-      0x02,                     //   Type: QUIC_HTTP_PRIORITY
-      0x00,                     //  Flags: none
-      0x00,  0x00, 0x00, 0x02,  // Stream: 2
-      0x80u, 0x00, 0x00, 0x01,  // Parent: 1 (Exclusive)
-  };
-  QuicHttpFrameHeader header(4, QuicHttpFrameType::QUIC_HTTP_PRIORITY, 0, 2);
-  EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header));
-}
-
-TEST_F(QuicHttpFrameDecoderTest, RstStreamTooShort) {
-  const char kFrameData[] = {
-      0x00, 0x00, 0x03,        // Length: 4
-      0x03,                    //   Type: RST_STREAM
-      0x00,                    //  Flags: none
-      0x00, 0x00, 0x00, 0x01,  // Stream: 1
-      0x00, 0x00, 0x00,        //  Truncated
-  };
-  QuicHttpFrameHeader header(3, QuicHttpFrameType::RST_STREAM, 0, 1);
-  EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header));
-}
-
-// SETTINGS frames must a multiple of 6 bytes long, so an 9 byte payload is
-// invalid.
-TEST_F(QuicHttpFrameDecoderTest, SettingsWrongSize) {
-  const char kFrameData[] = {
-      0x00, 0x00, 0x09,        // Length: 2
-      0x04,                    //   Type: SETTINGS
-      0x00,                    //  Flags: none
-      0x00, 0x00, 0x00, 0x00,  // Stream: 0
-      0x00, 0x02,              //  Param: ENABLE_PUSH
-      0x00, 0x00, 0x00, 0x03,  //  Value: 1
-      0x00, 0x04,              //  Param: INITIAL_WINDOW_SIZE
-      0x00,                    //  Value: Truncated
-  };
-  QuicHttpFrameHeader header(9, QuicHttpFrameType::SETTINGS, 0, 0);
-  QuicHttpFrameParts expected(header);
-  expected.settings.push_back(
-      QuicHttpSettingFields(QuicHttpSettingsParameter::ENABLE_PUSH, 3));
-  EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, expected));
-}
-
-TEST_F(QuicHttpFrameDecoderTest, PushPromiseTooShort) {
-  const char kFrameData[] = {
-      0x00, 0x00, 3,           // Payload length: 3
-      0x05,                    // PUSH_PROMISE
-      0x00,                    // Flags: none
-      0x00, 0x00, 0x00, 0x01,  // Stream ID: 1
-      0x00, 0x00, 0x00,        // Truncated promise id
-  };
-  QuicHttpFrameHeader header(3, QuicHttpFrameType::PUSH_PROMISE, 0, 1);
-  EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header));
-}
-
-TEST_F(QuicHttpFrameDecoderTest, PushPromisePaddedTruncatedPromise) {
-  const char kFrameData[] = {
-      0x00, 0x00, 4,           // Payload length: 4
-      0x05,                    // PUSH_PROMISE
-      0x08,                    // Flags: QUIC_HTTP_PADDED
-      0x00, 0x00, 0x00, 0x01,  // Stream ID: 1
-      0x00,                    // Pad Len
-      0x00, 0x00, 0x00,        // Truncated promise id
-  };
-  QuicHttpFrameHeader header(4, QuicHttpFrameType::PUSH_PROMISE,
-                             QuicHttpFrameFlag::QUIC_HTTP_PADDED, 1);
-  EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header));
-}
-
-TEST_F(QuicHttpFrameDecoderTest, PingTooShort) {
-  const char kFrameData[] = {
-      0x00,  0x00, 0x07,        //   Length: 8
-      0x06,                     //     Type: PING
-      0xfeu,                    //    Flags: no valid flags
-      0x00,  0x00, 0x00, 0x00,  //   Stream: 0
-      's',   'o',  'm',  'e',   // "some"
-      'd',   'a',  't',         // Too little
-  };
-  QuicHttpFrameHeader header(7, QuicHttpFrameType::PING, 0, 0);
-  EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header));
-}
-
-TEST_F(QuicHttpFrameDecoderTest, GoAwayTooShort) {
-  const char kFrameData[] = {
-      0x00,  0x00, 0x00,        // Length: 0
-      0x07,                     //   Type: GOAWAY
-      0xffu,                    //  Flags: 0xff (no valid flags)
-      0x00,  0x00, 0x00, 0x00,  // Stream: 0
-  };
-  QuicHttpFrameHeader header(0, QuicHttpFrameType::GOAWAY, 0, 0);
-  EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header));
-}
-
-TEST_F(QuicHttpFrameDecoderTest, WindowUpdateTooShort) {
-  const char kFrameData[] = {
-      0x00,  0x00, 0x03,        // Length: 3
-      0x08,                     //   Type: WINDOW_UPDATE
-      0x0f,                     //  Flags: 0xff (no valid flags)
-      0x00,  0x00, 0x00, 0x01,  // Stream: 1
-      0x80u, 0x00, 0x04,        // Truncated
-  };
-  QuicHttpFrameHeader header(3, QuicHttpFrameType::WINDOW_UPDATE, 0, 1);
-  EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header));
-}
-
-TEST_F(QuicHttpFrameDecoderTest, AltSvcTruncatedOriginLength) {
-  const char kFrameData[] = {
-      0x00, 0x00, 0x01,        // Payload length: 3
-      0x0a,                    // ALTSVC
-      0x00,                    // Flags: none
-      0x00, 0x00, 0x00, 0x02,  // Stream ID: 2
-      0x00,                    // Origin Length: truncated
-  };
-  QuicHttpFrameHeader header(1, QuicHttpFrameType::ALTSVC, 0, 2);
-  EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header));
-}
-
-TEST_F(QuicHttpFrameDecoderTest, AltSvcTruncatedOrigin) {
-  const char kFrameData[] = {
-      0x00, 0x00, 0x05,        // Payload length: 3
-      0x0a,                    // ALTSVC
-      0x00,                    // Flags: none
-      0x00, 0x00, 0x00, 0x02,  // Stream ID: 2
-      0x00, 0x04,              // Origin Length: 4 (too long)
-      'a',  'b',  'c',         // Origin
-  };
-  QuicHttpFrameHeader header(5, QuicHttpFrameType::ALTSVC, 0, 2);
-  EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header));
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Payload too long errors.
-
-// The decoder calls the listener's OnFrameSizeError method if the frame's
-// payload is longer than the currently configured maximum payload size.
-TEST_F(QuicHttpFrameDecoderTest, BeyondMaximum) {
-  decoder_.set_maximum_payload_size(2);
-  const char kFrameData[] = {
-      0x00, 0x00, 0x07,        // Payload length: 7
-      0x00,                    // DATA
-      0x09,                    // Flags: QUIC_HTTP_END_STREAM | QUIC_HTTP_PADDED
-      0x00, 0x00, 0x00, 0x02,  // Stream ID: 0  (REQUIRES ID)
-      0x03,                    // Pad Len
-      'a',  'b',  'c',         // Data
-      0x00, 0x00, 0x00,        // Padding
-  };
-  QuicHttpFrameHeader header(7, QuicHttpFrameType::DATA,
-                             QuicHttpFrameFlag::QUIC_HTTP_END_STREAM |
-                                 QuicHttpFrameFlag::QUIC_HTTP_PADDED,
-                             2);
-  QuicHttpFrameParts expected(header);
-  expected.has_frame_size_error = true;
-  auto validator = [&expected, this](
-                       const QuicHttpDecodeBuffer& input,
-                       QuicHttpDecodeStatus status) -> AssertionResult {
-    VERIFY_EQ(status, QuicHttpDecodeStatus::kDecodeError);
-    // The decoder detects this error after decoding the header, and without
-    // trying to decode the payload.
-    VERIFY_EQ(input.Offset(), QuicHttpFrameHeader::EncodedSize());
-    VERIFY_AND_RETURN_SUCCESS(VerifyCollected(expected));
-  };
-  ResetDecodeSpeedCounters();
-  EXPECT_TRUE(DecodePayloadAndValidateSeveralWays(ToStringPiece(kFrameData),
-                                                  validator));
-  EXPECT_GT(fast_decode_count_, 0u);
-  EXPECT_GT(slow_decode_count_, 0u);
-}
-
-TEST_F(QuicHttpFrameDecoderTest, PriorityTooLong) {
-  const char kFrameData[] = {
-      0x00,  0x00, 0x06,        // Length: 5
-      0x02,                     //   Type: QUIC_HTTP_PRIORITY
-      0x00,                     //  Flags: none
-      0x00,  0x00, 0x00, 0x02,  // Stream: 2
-      0x80u, 0x00, 0x00, 0x01,  // Parent: 1 (Exclusive)
-      0x10,                     // Weight: 17
-      0x00,                     // Too much
-  };
-  QuicHttpFrameHeader header(6, QuicHttpFrameType::QUIC_HTTP_PRIORITY, 0, 2);
-  EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header));
-}
-
-TEST_F(QuicHttpFrameDecoderTest, RstStreamTooLong) {
-  const char kFrameData[] = {
-      0x00, 0x00, 0x05,        // Length: 4
-      0x03,                    //   Type: RST_STREAM
-      0x00,                    //  Flags: none
-      0x00, 0x00, 0x00, 0x01,  // Stream: 1
-      0x00, 0x00, 0x00, 0x01,  //  Error: PROTOCOL_ERROR
-      0x00,                    // Too much
-  };
-  QuicHttpFrameHeader header(5, QuicHttpFrameType::RST_STREAM, 0, 1);
-  EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header));
-}
-
-TEST_F(QuicHttpFrameDecoderTest, SettingsAckTooLong) {
-  const char kFrameData[] = {
-      0x00, 0x00, 0x06,        //   Length: 6
-      0x04,                    //     Type: SETTINGS
-      0x01,                    //    Flags: QUIC_HTTP_ACK
-      0x00, 0x00, 0x00, 0x00,  //   Stream: 0
-      0x00, 0x00,              //   Extra
-      0x00, 0x00, 0x00, 0x00,  //   Extra
-  };
-  QuicHttpFrameHeader header(6, QuicHttpFrameType::SETTINGS,
-                             QuicHttpFrameFlag::QUIC_HTTP_ACK, 0);
-  EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header));
-}
-
-TEST_F(QuicHttpFrameDecoderTest, PingAckTooLong) {
-  const char kFrameData[] = {
-      0x00,  0x00, 0x09,        //   Length: 8
-      0x06,                     //     Type: PING
-      0xffu,                    //    Flags: QUIC_HTTP_ACK | 0xfe
-      0x00,  0x00, 0x00, 0x00,  //   Stream: 0
-      's',   'o',  'm',  'e',   // "some"
-      'd',   'a',  't',  'a',   // "data"
-      0x00,                     // Too much
-  };
-  QuicHttpFrameHeader header(9, QuicHttpFrameType::PING,
-                             QuicHttpFrameFlag::QUIC_HTTP_ACK, 0);
-  EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header));
-}
-
-TEST_F(QuicHttpFrameDecoderTest, WindowUpdateTooLong) {
-  const char kFrameData[] = {
-      0x00,  0x00, 0x05,        // Length: 5
-      0x08,                     //   Type: WINDOW_UPDATE
-      0x0f,                     //  Flags: 0xff (no valid flags)
-      0x00,  0x00, 0x00, 0x01,  // Stream: 1
-      0x80u, 0x00, 0x04, 0x00,  //   Incr: 1024 (plus R bit)
-      0x00,                     // Too much
-  };
-  QuicHttpFrameHeader header(5, QuicHttpFrameType::WINDOW_UPDATE, 0, 1);
-  EXPECT_TRUE(DecodePayloadExpectingFrameSizeError(kFrameData, header));
-}
-
-}  // namespace
-}  // namespace test
-}  // namespace quic
diff --git a/net/third_party/quic/http/decoder/quic_http_structure_decoder.cc b/net/third_party/quic/http/decoder/quic_http_structure_decoder.cc
deleted file mode 100644
index bd9a10d..0000000
--- a/net/third_party/quic/http/decoder/quic_http_structure_decoder.cc
+++ /dev/null
@@ -1,91 +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 "net/third_party/quic/http/decoder/quic_http_structure_decoder.h"
-
-#include <algorithm>
-
-#include "net/third_party/quic/platform/api/quic_bug_tracker.h"
-
-namespace quic {
-
-// Below we have some defensive coding: if we somehow run off the end, don't
-// overwrite lots of memory. Note that most of this decoder is not defensive
-// against bugs in the decoder, only against malicious encoders, but since
-// we're copying memory into a buffer here, let's make sure we don't allow a
-// small mistake to grow larger. The decoder will get stuck if we hit the
-// QUIC_BUG conditions, but shouldn't corrupt memory.
-
-uint32_t QuicHttpStructureDecoder::IncompleteStart(QuicHttpDecodeBuffer* db,
-                                                   uint32_t target_size) {
-  if (target_size > sizeof buffer_) {
-    QUIC_BUG << "target_size too large for buffer: " << target_size;
-    return 0;
-  }
-  const uint32_t num_to_copy = db->MinLengthRemaining(target_size);
-  memcpy(buffer_, db->cursor(), num_to_copy);
-  offset_ = num_to_copy;
-  db->AdvanceCursor(num_to_copy);
-  return num_to_copy;
-}
-
-QuicHttpDecodeStatus QuicHttpStructureDecoder::IncompleteStart(
-    QuicHttpDecodeBuffer* db,
-    uint32_t* remaining_payload,
-    uint32_t target_size) {
-  DVLOG(1) << "IncompleteStart@" << this
-           << ": *remaining_payload=" << *remaining_payload
-           << "; target_size=" << target_size
-           << "; db->Remaining=" << db->Remaining();
-  *remaining_payload -=
-      IncompleteStart(db, std::min(target_size, *remaining_payload));
-  if (*remaining_payload > 0 && db->Empty()) {
-    return QuicHttpDecodeStatus::kDecodeInProgress;
-  }
-  DVLOG(1) << "IncompleteStart: kDecodeError";
-  return QuicHttpDecodeStatus::kDecodeError;
-}
-
-bool QuicHttpStructureDecoder::ResumeFillingBuffer(QuicHttpDecodeBuffer* db,
-                                                   uint32_t target_size) {
-  DVLOG(2) << "ResumeFillingBuffer@" << this << ": target_size=" << target_size
-           << "; offset_=" << offset_ << "; db->Remaining=" << db->Remaining();
-  if (target_size < offset_) {
-    QUIC_BUG << "Already filled buffer_! target_size=" << target_size
-             << "    offset_=" << offset_;
-    return false;
-  }
-  const uint32_t needed = target_size - offset_;
-  const uint32_t num_to_copy = db->MinLengthRemaining(needed);
-  DVLOG(2) << "ResumeFillingBuffer num_to_copy=" << num_to_copy;
-  memcpy(&buffer_[offset_], db->cursor(), num_to_copy);
-  db->AdvanceCursor(num_to_copy);
-  offset_ += num_to_copy;
-  return needed == num_to_copy;
-}
-
-bool QuicHttpStructureDecoder::ResumeFillingBuffer(QuicHttpDecodeBuffer* db,
-                                                   uint32_t* remaining_payload,
-                                                   uint32_t target_size) {
-  DVLOG(2) << "ResumeFillingBuffer@" << this << ": target_size=" << target_size
-           << "; offset_=" << offset_
-           << "; *remaining_payload=" << *remaining_payload
-           << "; db->Remaining=" << db->Remaining();
-  if (target_size < offset_) {
-    QUIC_BUG << "Already filled buffer_! target_size=" << target_size
-             << "    offset_=" << offset_;
-    return false;
-  }
-  const uint32_t needed = target_size - offset_;
-  const uint32_t num_to_copy =
-      db->MinLengthRemaining(std::min(needed, *remaining_payload));
-  DVLOG(2) << "ResumeFillingBuffer num_to_copy=" << num_to_copy;
-  memcpy(&buffer_[offset_], db->cursor(), num_to_copy);
-  db->AdvanceCursor(num_to_copy);
-  offset_ += num_to_copy;
-  *remaining_payload -= num_to_copy;
-  return needed == num_to_copy;
-}
-
-}  // namespace quic
diff --git a/net/third_party/quic/http/decoder/quic_http_structure_decoder.h b/net/third_party/quic/http/decoder/quic_http_structure_decoder.h
deleted file mode 100644
index 9f71beb..0000000
--- a/net/third_party/quic/http/decoder/quic_http_structure_decoder.h
+++ /dev/null
@@ -1,133 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_THIRD_PARTY_QUIC_HTTP_DECODER_QUIC_HTTP_STRUCTURE_DECODER_H_
-#define NET_THIRD_PARTY_QUIC_HTTP_DECODER_QUIC_HTTP_STRUCTURE_DECODER_H_
-
-// QuicHttpStructureDecoder is a class for decoding the fixed size structures in
-// the HTTP/2 spec, defined in gfe/quic/http/quic_http_structures.h. This class
-// is in aid of deciding whether to keep the SlowDecode methods which I
-// (jamessynge) now think may not be worth their complexity. In particular,
-// if most transport buffers are large, so it is rare that a structure is
-// split across buffer boundaries, than the cost of buffering upon
-// those rare occurrences is small, which then simplifies the callers.
-
-#include <cstdint>
-
-#include "base/logging.h"
-#include "net/third_party/quic/http/decoder/quic_http_decode_buffer.h"
-#include "net/third_party/quic/http/decoder/quic_http_decode_status.h"
-#include "net/third_party/quic/http/decoder/quic_http_decode_structures.h"
-#include "net/third_party/quic/http/quic_http_structures.h"
-#include "net/third_party/quic/platform/api/quic_export.h"
-
-namespace quic {
-namespace test {
-class QuicHttpStructureDecoderPeer;
-}  // namespace test
-
-class QUIC_EXPORT_PRIVATE QuicHttpStructureDecoder {
- public:
-  // The caller needs to keep track of whether to call Start or Resume.
-  //
-  // Start has an optimization for the case where the QuicHttpDecodeBuffer holds
-  // the entire encoded structure; in that case it decodes into *out and returns
-  // true, and does NOT touch the data members of the QuicHttpStructureDecoder
-  // instance because the caller won't be calling Resume later.
-  //
-  // However, if the QuicHttpDecodeBuffer is too small to hold the entire
-  // encoded structure, Start copies the available bytes into the
-  // QuicHttpStructureDecoder instance, and returns false to indicate that it
-  // has not been able to complete the decoding.
-  //
-  template <class S>
-  bool Start(S* out, QuicHttpDecodeBuffer* db) {
-    static_assert(S::EncodedSize() <= sizeof buffer_, "buffer_ is too small");
-    DVLOG(2) << __func__ << "@" << this << ": db->Remaining=" << db->Remaining()
-             << "; EncodedSize=" << S::EncodedSize();
-    if (db->Remaining() >= S::EncodedSize()) {
-      DoDecode(out, db);
-      return true;
-    }
-    IncompleteStart(db, S::EncodedSize());
-    return false;
-  }
-
-  template <class S>
-  bool Resume(S* out, QuicHttpDecodeBuffer* db) {
-    DVLOG(2) << __func__ << "@" << this << ": offset_=" << offset_
-             << "; db->Remaining=" << db->Remaining();
-    if (ResumeFillingBuffer(db, S::EncodedSize())) {
-      // We have the whole thing now.
-      DVLOG(2) << __func__ << "@" << this << "    offset_=" << offset_
-               << "    Ready to decode from buffer_.";
-      QuicHttpDecodeBuffer buffer_db(buffer_, S::EncodedSize());
-      DoDecode(out, &buffer_db);
-      return true;
-    }
-    DCHECK_LT(offset_, S::EncodedSize());
-    return false;
-  }
-
-  // A second pair of Start and Resume, where the caller has a variable,
-  // |remaining_payload| that is both tested for sufficiency and updated
-  // during decoding. Note that the decode buffer may extend beyond the
-  // remaining payload because the buffer may include padding.
-  template <class S>
-  QuicHttpDecodeStatus Start(S* out,
-                             QuicHttpDecodeBuffer* db,
-                             uint32_t* remaining_payload) {
-    static_assert(S::EncodedSize() <= sizeof buffer_, "buffer_ is too small");
-    DVLOG(2) << __func__ << "@" << this
-             << ": *remaining_payload=" << *remaining_payload
-             << "; db->Remaining=" << db->Remaining()
-             << "; EncodedSize=" << S::EncodedSize();
-    if (db->MinLengthRemaining(*remaining_payload) >= S::EncodedSize()) {
-      DoDecode(out, db);
-      *remaining_payload -= S::EncodedSize();
-      return QuicHttpDecodeStatus::kDecodeDone;
-    }
-    return IncompleteStart(db, remaining_payload, S::EncodedSize());
-  }
-
-  template <class S>
-  bool Resume(S* out, QuicHttpDecodeBuffer* db, uint32_t* remaining_payload) {
-    DVLOG(3) << __func__ << "@" << this << ": offset_=" << offset_
-             << "; *remaining_payload=" << *remaining_payload
-             << "; db->Remaining=" << db->Remaining()
-             << "; EncodedSize=" << S::EncodedSize();
-    if (ResumeFillingBuffer(db, remaining_payload, S::EncodedSize())) {
-      // We have the whole thing now.
-      DVLOG(2) << __func__ << "@" << this << ": offset_=" << offset_
-               << "; Ready to decode from buffer_.";
-      QuicHttpDecodeBuffer buffer_db(buffer_, S::EncodedSize());
-      DoDecode(out, &buffer_db);
-      return true;
-    }
-    DCHECK_LT(offset_, S::EncodedSize());
-    return false;
-  }
-
-  uint32_t offset() const { return offset_; }
-
- private:
-  friend class test::QuicHttpStructureDecoderPeer;
-
-  uint32_t IncompleteStart(QuicHttpDecodeBuffer* db, uint32_t target_size);
-  QuicHttpDecodeStatus IncompleteStart(QuicHttpDecodeBuffer* db,
-                                       uint32_t* remaining_payload,
-                                       uint32_t target_size);
-
-  bool ResumeFillingBuffer(QuicHttpDecodeBuffer* db, uint32_t target_size);
-  bool ResumeFillingBuffer(QuicHttpDecodeBuffer* db,
-                           uint32_t* remaining_payload,
-                           uint32_t target_size);
-
-  uint32_t offset_;
-  char buffer_[QuicHttpFrameHeader::EncodedSize()];
-};
-
-}  // namespace quic
-
-#endif  // NET_THIRD_PARTY_QUIC_HTTP_DECODER_QUIC_HTTP_STRUCTURE_DECODER_H_
diff --git a/net/third_party/quic/http/decoder/quic_http_structure_decoder_test.cc b/net/third_party/quic/http/decoder/quic_http_structure_decoder_test.cc
deleted file mode 100644
index e6a6d3c..0000000
--- a/net/third_party/quic/http/decoder/quic_http_structure_decoder_test.cc
+++ /dev/null
@@ -1,544 +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 "net/third_party/quic/http/decoder/quic_http_structure_decoder.h"
-
-// Tests decoding all of the fixed size HTTP/2 structures (i.e. those defined in
-// gfe/quic/http/quic_http_structures.h) using QuicHttpStructureDecoder, which
-// handles buffering of structures split across input buffer boundaries, and in
-// turn uses DoDecode when it has all of a structure in a contiguous buffer.
-
-// NOTE: This tests the first pair of Start and Resume, which don't take
-// a remaining_payload parameter. The other pair are well tested via the
-// payload decoder tests, though...
-// TODO(jamessynge): Create type parameterized tests for
-// QuicHttpStructureDecoder where the type is the type of structure, and with
-// testing of both pairs of Start and Resume methods; note that it appears that
-// the first pair will be used only for QuicHttpFrameHeader, and the other pair
-// only for structures in the frame payload.
-
-#include <stddef.h>
-
-#include <cstdint>
-
-#include "base/logging.h"
-#include "net/third_party/quic/http/decoder/quic_http_decode_buffer.h"
-#include "net/third_party/quic/http/decoder/quic_http_decode_status.h"
-#include "net/third_party/quic/http/quic_http_constants.h"
-#include "net/third_party/quic/http/quic_http_structures_test_util.h"
-#include "net/third_party/quic/http/tools/quic_http_random_decoder_test.h"
-#include "net/third_party/quic/platform/api/quic_reconstruct_object.h"
-#include "net/third_party/quic/platform/api/quic_string.h"
-#include "net/third_party/quic/platform/api/quic_string_piece.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using ::testing::AssertionFailure;
-using ::testing::AssertionResult;
-using ::testing::AssertionSuccess;
-
-namespace quic {
-namespace test {
-namespace {
-const bool kMayReturnZeroOnFirst = false;
-
-template <class S>
-class QuicHttpStructureDecoderTest : public QuicHttpRandomDecoderTest {
- protected:
-  typedef S Structure;
-
-  QuicHttpStructureDecoderTest() {
-    // IF the test adds more data after the encoded structure, stop as
-    // soon as the structure is decoded.
-    stop_decode_on_done_ = true;
-  }
-
-  QuicHttpDecodeStatus StartDecoding(QuicHttpDecodeBuffer* b) override {
-    // Overwrite the current contents of |structure_|, in to which we'll
-    // decode the buffer, so that we can be confident that we really decoded
-    // the structure every time.
-    QuicDefaultReconstructObject(&structure_, RandomPtr());
-    uint32_t old_remaining = b->Remaining();
-    if (structure_decoder_.Start(&structure_, b)) {
-      EXPECT_EQ(old_remaining - S::EncodedSize(), b->Remaining());
-      ++fast_decode_count_;
-      return QuicHttpDecodeStatus::kDecodeDone;
-    } else {
-      EXPECT_LT(structure_decoder_.offset(), S::EncodedSize());
-      EXPECT_EQ(0u, b->Remaining());
-      EXPECT_EQ(old_remaining - structure_decoder_.offset(), b->Remaining());
-      ++incomplete_start_count_;
-      return QuicHttpDecodeStatus::kDecodeInProgress;
-    }
-  }
-
-  QuicHttpDecodeStatus ResumeDecoding(QuicHttpDecodeBuffer* b) override {
-    uint32_t old_offset = structure_decoder_.offset();
-    EXPECT_LT(old_offset, S::EncodedSize());
-    uint32_t avail = b->Remaining();
-    if (structure_decoder_.Resume(&structure_, b)) {
-      EXPECT_LE(S::EncodedSize(), old_offset + avail);
-      EXPECT_EQ(b->Remaining(), avail - (S::EncodedSize() - old_offset));
-      ++slow_decode_count_;
-      return QuicHttpDecodeStatus::kDecodeDone;
-    } else {
-      EXPECT_LT(structure_decoder_.offset(), S::EncodedSize());
-      EXPECT_EQ(0u, b->Remaining());
-      EXPECT_GT(S::EncodedSize(), old_offset + avail);
-      ++incomplete_resume_count_;
-      return QuicHttpDecodeStatus::kDecodeInProgress;
-    }
-  }
-
-  // Fully decodes the Structure at the start of data, and confirms it matches
-  // *expected (if provided).
-  AssertionResult DecodeLeadingStructure(const S* expected,
-                                         QuicStringPiece data) {
-    VERIFY_LE(S::EncodedSize(), data.size());
-    QuicHttpDecodeBuffer original(data);
-
-    // The validator is called after each of the several times that the input
-    // QuicHttpDecodeBuffer is decoded, each with a different segmentation of
-    // the input. Validate that structure_ matches the expected value, if
-    // provided.
-    Validator validator;
-    if (expected != nullptr) {
-      validator = [expected, this](
-                      const QuicHttpDecodeBuffer& db,
-                      QuicHttpDecodeStatus status) -> AssertionResult {
-        VERIFY_EQ(*expected, structure_);
-        return AssertionSuccess();
-      };
-    }
-
-    // Before that, validate that decoding is done and that we've advanced
-    // the cursor the expected amount.
-    validator = ValidateDoneAndOffset(S::EncodedSize(), validator);
-
-    // Decode several times, with several segmentations of the input buffer.
-    fast_decode_count_ = 0;
-    slow_decode_count_ = 0;
-    incomplete_start_count_ = 0;
-    incomplete_resume_count_ = 0;
-    VERIFY_SUCCESS(DecodeAndValidateSeveralWays(
-        &original, kMayReturnZeroOnFirst, validator));
-    VERIFY_FALSE(HasFailure());
-    VERIFY_EQ(S::EncodedSize(), structure_decoder_.offset());
-    VERIFY_EQ(S::EncodedSize(), original.Offset());
-    VERIFY_LT(0u, fast_decode_count_);
-    VERIFY_LT(0u, slow_decode_count_);
-    VERIFY_LT(0u, incomplete_start_count_);
-
-    // If the structure is large enough so that SelectZeroOrOne will have
-    // caused Resume to return false, check that occurred.
-    if (S::EncodedSize() >= 2) {
-      VERIFY_LE(0u, incomplete_resume_count_);
-    } else {
-      VERIFY_EQ(0u, incomplete_resume_count_);
-    }
-    if (expected != nullptr) {
-      DVLOG(1) << "DecodeLeadingStructure expected: " << *expected;
-      DVLOG(1) << "DecodeLeadingStructure   actual: " << structure_;
-      VERIFY_EQ(*expected, structure_);
-    }
-    return AssertionSuccess();
-  }
-
-  template <size_t N>
-  AssertionResult DecodeLeadingStructure(const char (&data)[N]) {
-    VERIFY_AND_RETURN_SUCCESS(
-        DecodeLeadingStructure(nullptr, QuicStringPiece(data, N)));
-  }
-
-  template <size_t N>
-  AssertionResult DecodeLeadingStructure(const unsigned char (&data)[N]) {
-    VERIFY_AND_RETURN_SUCCESS(
-        DecodeLeadingStructure(nullptr, ToStringPiece(data)));
-  }
-
-  // Encode the structure |in_s| into bytes, then decode the bytes
-  // and validate that the decoder produced the same field values.
-  AssertionResult EncodeThenDecode(const S& in_s) {
-    QuicString bytes = SerializeStructure(in_s);
-    VERIFY_EQ(S::EncodedSize(), bytes.size());
-    VERIFY_AND_RETURN_SUCCESS(DecodeLeadingStructure(&in_s, bytes));
-  }
-
-  // Repeatedly fill a structure with random but valid contents, encode it, then
-  // decode it, and finally validate that the decoded structure matches the
-  // random input. Lather-rinse-and-repeat.
-  AssertionResult TestDecodingRandomizedStructures(size_t count) {
-    for (size_t i = 0; i < count; ++i) {
-      Structure input;
-      Randomize(&input, RandomPtr());
-      VERIFY_SUCCESS(EncodeThenDecode(input));
-    }
-    return AssertionSuccess();
-  }
-
-  AssertionResult TestDecodingRandomizedStructures() {
-    VERIFY_SUCCESS(TestDecodingRandomizedStructures(100));
-    return AssertionSuccess();
-  }
-
-  S structure_;
-  QuicHttpStructureDecoder structure_decoder_;
-  size_t fast_decode_count_ = 0;
-  size_t slow_decode_count_ = 0;
-  size_t incomplete_start_count_ = 0;
-  size_t incomplete_resume_count_ = 0;
-};
-
-class QuicHttpFrameHeaderDecoderTest
-    : public QuicHttpStructureDecoderTest<QuicHttpFrameHeader> {};
-
-TEST_F(QuicHttpFrameHeaderDecoderTest, DecodesLiteral) {
-  {
-    // Realistic input.
-    // clang-format off
-    const char kData[] = {
-        0x00, 0x00, 0x05,        // Payload length: 5
-        0x01,                    // Frame type: HEADERS
-        0x08,                    // Flags: QUIC_HTTP_PADDED
-        0x00, 0x00, 0x00, 0x01,  // Stream ID: 1
-        0x04,                    // Padding length: 4
-        0x00, 0x00, 0x00, 0x00,  // Padding bytes
-    };
-    // clang-format on
-    ASSERT_TRUE(DecodeLeadingStructure(kData));
-    EXPECT_EQ(5u, structure_.payload_length);
-    EXPECT_EQ(QuicHttpFrameType::HEADERS, structure_.type);
-    EXPECT_EQ(QuicHttpFrameFlag::QUIC_HTTP_PADDED, structure_.flags);
-    EXPECT_EQ(1u, structure_.stream_id);
-  }
-  {
-    // Unlikely input.
-    // clang-format off
-    const unsigned char kData[] = {
-        0xff, 0xff, 0xff,        // Payload length: uint24 max
-        0xff,                    // Frame type: Unknown
-        0xff,                    // Flags: Unknown/All
-        0xff, 0xff, 0xff, 0xff,  // Stream ID: uint31 max, plus R-bit
-    };
-    // clang-format on
-    ASSERT_TRUE(DecodeLeadingStructure(kData));
-    EXPECT_EQ((1 << 24) - 1u, structure_.payload_length);
-    EXPECT_EQ(static_cast<QuicHttpFrameType>(255), structure_.type);
-    EXPECT_EQ(255, structure_.flags);
-    EXPECT_EQ(0x7fffffffu, structure_.stream_id);
-  }
-}
-
-TEST_F(QuicHttpFrameHeaderDecoderTest, DecodesRandomized) {
-  TestDecodingRandomizedStructures();
-}
-
-//------------------------------------------------------------------------------
-
-class QuicHttpPriorityFieldsDecoderTest
-    : public QuicHttpStructureDecoderTest<QuicHttpPriorityFields> {};
-
-TEST_F(QuicHttpPriorityFieldsDecoderTest, DecodesLiteral) {
-  {
-    // clang-format off
-    const unsigned char kData[] = {
-        0x80, 0x00, 0x00, 0x05,  // Exclusive (yes) and Dependency (5)
-        0xff,                    // Weight: 256 (after adding 1)
-    };
-    // clang-format on
-    ASSERT_TRUE(DecodeLeadingStructure(kData));
-    EXPECT_EQ(5u, structure_.stream_dependency);
-    EXPECT_EQ(256u, structure_.weight);
-    EXPECT_EQ(true, structure_.is_exclusive);
-  }
-  {
-    // clang-format off
-    const unsigned char kData[] = {
-        0x7f, 0xff, 0xff, 0xff,  // Excl. (no) and Dependency (uint31 max)
-        0x00,                    // Weight: 1 (after adding 1)
-    };
-    // clang-format on
-    ASSERT_TRUE(DecodeLeadingStructure(kData));
-    EXPECT_EQ(QuicHttpStreamIdMask(), structure_.stream_dependency);
-    EXPECT_EQ(1u, structure_.weight);
-    EXPECT_EQ(false, structure_.is_exclusive);
-  }
-}
-
-TEST_F(QuicHttpPriorityFieldsDecoderTest, DecodesRandomized) {
-  TestDecodingRandomizedStructures();
-}
-
-//------------------------------------------------------------------------------
-
-class QuicHttpRstStreamFieldsDecoderTest
-    : public QuicHttpStructureDecoderTest<QuicHttpRstStreamFields> {};
-
-TEST_F(QuicHttpRstStreamFieldsDecoderTest, DecodesLiteral) {
-  {
-    // clang-format off
-    const char kData[] = {
-        0x00, 0x00, 0x00, 0x01,  // Error: PROTOCOL_ERROR
-    };
-    // clang-format on
-    ASSERT_TRUE(DecodeLeadingStructure(kData));
-    EXPECT_TRUE(structure_.IsSupportedErrorCode());
-    EXPECT_EQ(QuicHttpErrorCode::PROTOCOL_ERROR, structure_.error_code);
-  }
-  {
-    // clang-format off
-    const unsigned char kData[] = {
-        0xff, 0xff, 0xff, 0xff,  // Error: max uint32 (Unknown error code)
-    };
-    // clang-format on
-    ASSERT_TRUE(DecodeLeadingStructure(kData));
-    EXPECT_FALSE(structure_.IsSupportedErrorCode());
-    EXPECT_EQ(static_cast<QuicHttpErrorCode>(0xffffffff),
-              structure_.error_code);
-  }
-}
-
-TEST_F(QuicHttpRstStreamFieldsDecoderTest, DecodesRandomized) {
-  TestDecodingRandomizedStructures();
-}
-
-//------------------------------------------------------------------------------
-
-class QuicHttpSettingFieldsDecoderTest
-    : public QuicHttpStructureDecoderTest<QuicHttpSettingFields> {};
-
-TEST_F(QuicHttpSettingFieldsDecoderTest, DecodesLiteral) {
-  {
-    // clang-format off
-    const char kData[] = {
-        0x00, 0x01,              // Setting: HEADER_TABLE_SIZE
-        0x00, 0x00, 0x40, 0x00,  // Value: 16K
-    };
-    // clang-format on
-    ASSERT_TRUE(DecodeLeadingStructure(kData));
-    EXPECT_TRUE(structure_.IsSupportedParameter());
-    EXPECT_EQ(QuicHttpSettingsParameter::HEADER_TABLE_SIZE,
-              structure_.parameter);
-    EXPECT_EQ(1u << 14, structure_.value);
-  }
-  {
-    // clang-format off
-    const unsigned char kData[] = {
-        0x00, 0x00,              // Setting: Unknown (0)
-        0xff, 0xff, 0xff, 0xff,  // Value: max uint32
-    };
-    // clang-format on
-    ASSERT_TRUE(DecodeLeadingStructure(kData));
-    EXPECT_FALSE(structure_.IsSupportedParameter());
-    EXPECT_EQ(static_cast<QuicHttpSettingsParameter>(0), structure_.parameter);
-  }
-}
-
-TEST_F(QuicHttpSettingFieldsDecoderTest, DecodesRandomized) {
-  TestDecodingRandomizedStructures();
-}
-
-//------------------------------------------------------------------------------
-
-class QuicHttpPushPromiseFieldsDecoderTest
-    : public QuicHttpStructureDecoderTest<QuicHttpPushPromiseFields> {};
-
-TEST_F(QuicHttpPushPromiseFieldsDecoderTest, DecodesLiteral) {
-  {
-    // clang-format off
-    const unsigned char kData[] = {
-        0x00, 0x01, 0x8a, 0x92,  // Promised Stream ID: 101010
-    };
-    // clang-format on
-    ASSERT_TRUE(DecodeLeadingStructure(kData));
-    EXPECT_EQ(101010u, structure_.promised_stream_id);
-  }
-  {
-    // Promised stream id has R-bit (reserved for future use) set, which
-    // should be cleared by the decoder.
-    // clang-format off
-    const unsigned char kData[] = {
-        // Promised Stream ID: max uint31 and R-bit
-        0xff, 0xff, 0xff, 0xff,
-    };
-    // clang-format on
-    ASSERT_TRUE(DecodeLeadingStructure(kData));
-    EXPECT_EQ(QuicHttpStreamIdMask(), structure_.promised_stream_id);
-  }
-}
-
-TEST_F(QuicHttpPushPromiseFieldsDecoderTest, DecodesRandomized) {
-  TestDecodingRandomizedStructures();
-}
-
-//------------------------------------------------------------------------------
-
-class QuicHttpPingFieldsDecoderTest
-    : public QuicHttpStructureDecoderTest<QuicHttpPingFields> {};
-
-TEST_F(QuicHttpPingFieldsDecoderTest, DecodesLiteral) {
-  {
-    // Each byte is different, so can detect if order changed.
-    const char kData[] = {
-        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-    };
-    ASSERT_TRUE(DecodeLeadingStructure(kData));
-    EXPECT_EQ(ToStringPiece(kData), ToStringPiece(structure_.opaque_bytes));
-  }
-  {
-    // All zeros, detect problems handling NULs.
-    const char kData[] = {
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    };
-    ASSERT_TRUE(DecodeLeadingStructure(kData));
-    EXPECT_EQ(ToStringPiece(kData), ToStringPiece(structure_.opaque_bytes));
-  }
-  {
-    const unsigned char kData[] = {
-        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-    };
-    ASSERT_TRUE(DecodeLeadingStructure(kData));
-    EXPECT_EQ(ToStringPiece(kData), ToStringPiece(structure_.opaque_bytes));
-  }
-}
-
-TEST_F(QuicHttpPingFieldsDecoderTest, DecodesRandomized) {
-  TestDecodingRandomizedStructures();
-}
-
-//------------------------------------------------------------------------------
-
-class QuicHttpGoAwayFieldsDecoderTest
-    : public QuicHttpStructureDecoderTest<QuicHttpGoAwayFields> {};
-
-TEST_F(QuicHttpGoAwayFieldsDecoderTest, DecodesLiteral) {
-  {
-    // clang-format off
-    const char kData[] = {
-        0x00, 0x00, 0x00, 0x00,  // Last Stream ID: 0
-        0x00, 0x00, 0x00, 0x00,  // Error: NO_ERROR (0)
-    };
-    // clang-format on
-    ASSERT_TRUE(DecodeLeadingStructure(kData));
-    EXPECT_EQ(0u, structure_.last_stream_id);
-    EXPECT_TRUE(structure_.IsSupportedErrorCode());
-    EXPECT_EQ(QuicHttpErrorCode::HTTP2_NO_ERROR, structure_.error_code);
-  }
-  {
-    // clang-format off
-    const char kData[] = {
-        0x00, 0x00, 0x00, 0x01,  // Last Stream ID: 1
-        0x00, 0x00, 0x00, 0x0d,  // Error: HTTP_1_1_REQUIRED
-    };
-    // clang-format on
-    ASSERT_TRUE(DecodeLeadingStructure(kData));
-    EXPECT_EQ(1u, structure_.last_stream_id);
-    EXPECT_TRUE(structure_.IsSupportedErrorCode());
-    EXPECT_EQ(QuicHttpErrorCode::HTTP_1_1_REQUIRED, structure_.error_code);
-  }
-  {
-    // clang-format off
-    const unsigned char kData[] = {
-        0xff, 0xff, 0xff, 0xff,  // Last Stream ID: max uint31 and R-bit
-        0xff, 0xff, 0xff, 0xff,  // Error: max uint32 (Unknown error code)
-    };
-    // clang-format on
-    ASSERT_TRUE(DecodeLeadingStructure(kData));
-    EXPECT_EQ(QuicHttpStreamIdMask(),
-              structure_.last_stream_id);  // No high-bit.
-    EXPECT_FALSE(structure_.IsSupportedErrorCode());
-    EXPECT_EQ(static_cast<QuicHttpErrorCode>(0xffffffff),
-              structure_.error_code);
-  }
-}
-
-TEST_F(QuicHttpGoAwayFieldsDecoderTest, DecodesRandomized) {
-  TestDecodingRandomizedStructures();
-}
-
-//------------------------------------------------------------------------------
-
-class QuicHttpWindowUpdateFieldsDecoderTest
-    : public QuicHttpStructureDecoderTest<QuicHttpWindowUpdateFields> {};
-
-TEST_F(QuicHttpWindowUpdateFieldsDecoderTest, DecodesLiteral) {
-  {
-    // clang-format off
-    const char kData[] = {
-        0x00, 0x01, 0x00, 0x00,  // Window Size Increment: 2 ^ 16
-    };
-    // clang-format on
-    ASSERT_TRUE(DecodeLeadingStructure(kData));
-    EXPECT_EQ(1u << 16, structure_.window_size_increment);
-  }
-  {
-    // Increment must be non-zero, but we need to be able to decode the invalid
-    // zero to detect it.
-    // clang-format off
-    const char kData[] = {
-        0x00, 0x00, 0x00, 0x00,  // Window Size Increment: 0
-    };
-    // clang-format on
-    ASSERT_TRUE(DecodeLeadingStructure(kData));
-    EXPECT_EQ(0u, structure_.window_size_increment);
-  }
-  {
-    // Increment has R-bit (reserved for future use) set, which
-    // should be cleared by the decoder.
-    // clang-format off
-    const unsigned char kData[] = {
-      // Window Size Increment: max uint31 and R-bit
-      0xff, 0xff, 0xff, 0xff,
-    };
-    // clang-format on
-    ASSERT_TRUE(DecodeLeadingStructure(kData));
-    EXPECT_EQ(QuicHttpStreamIdMask(), structure_.window_size_increment);
-  }
-}
-
-TEST_F(QuicHttpWindowUpdateFieldsDecoderTest, DecodesRandomized) {
-  TestDecodingRandomizedStructures();
-}
-
-//------------------------------------------------------------------------------
-
-class QuicHttpAltSvcFieldsDecoderTest
-    : public QuicHttpStructureDecoderTest<QuicHttpAltSvcFields> {};
-
-TEST_F(QuicHttpAltSvcFieldsDecoderTest, DecodesLiteral) {
-  {
-    // clang-format off
-    const char kData[] = {
-        0x00, 0x00,  // Origin Length: 0
-    };
-    // clang-format on
-    ASSERT_TRUE(DecodeLeadingStructure(kData));
-    EXPECT_EQ(0u, structure_.origin_length);
-  }
-  {
-    // clang-format off
-    const char kData[] = {
-        0x00, 0x14,  // Origin Length: 20
-    };
-    // clang-format on
-    ASSERT_TRUE(DecodeLeadingStructure(kData));
-    EXPECT_EQ(20u, structure_.origin_length);
-  }
-  {
-    // clang-format off
-    const unsigned char kData[] = {
-        0xff, 0xff,  // Origin Length: uint16 max
-    };
-    // clang-format on
-    ASSERT_TRUE(DecodeLeadingStructure(kData));
-    EXPECT_EQ(65535u, structure_.origin_length);
-  }
-}
-
-TEST_F(QuicHttpAltSvcFieldsDecoderTest, DecodesRandomized) {
-  TestDecodingRandomizedStructures();
-}
-
-}  // namespace
-}  // namespace test
-}  // namespace quic
diff --git a/net/third_party/quic/http/decoder/quic_http_structure_decoder_test_util.cc b/net/third_party/quic/http/decoder/quic_http_structure_decoder_test_util.cc
deleted file mode 100644
index dcef551..0000000
--- a/net/third_party/quic/http/decoder/quic_http_structure_decoder_test_util.cc
+++ /dev/null
@@ -1,19 +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 "net/third_party/quic/http/decoder/quic_http_structure_decoder_test_util.h"
-
-namespace quic {
-namespace test {
-
-void QuicHttpStructureDecoderPeer::Randomize(QuicHttpStructureDecoder* p,
-                                             QuicTestRandomBase* rng) {
-  p->offset_ = rng->Rand32();
-  for (size_t i = 0; i < sizeof p->buffer_; ++i) {
-    p->buffer_[i] = rng->Rand8();
-  }
-}
-
-}  // namespace test
-}  // namespace quic
diff --git a/net/third_party/quic/http/decoder/quic_http_structure_decoder_test_util.h b/net/third_party/quic/http/decoder/quic_http_structure_decoder_test_util.h
deleted file mode 100644
index f9f1ab7..0000000
--- a/net/third_party/quic/http/decoder/quic_http_structure_decoder_test_util.h
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_THIRD_PARTY_QUIC_HTTP_DECODER_QUIC_HTTP_STRUCTURE_DECODER_TEST_UTIL_H_
-#define NET_THIRD_PARTY_QUIC_HTTP_DECODER_QUIC_HTTP_STRUCTURE_DECODER_TEST_UTIL_H_
-
-#include "net/third_party/quic/http/decoder/quic_http_structure_decoder.h"
-#include "net/third_party/quic/platform/api/quic_test_random.h"
-
-namespace quic {
-namespace test {
-
-class QuicHttpStructureDecoderPeer {
- public:
-  // Overwrite the QuicHttpStructureDecoder instance with random values.
-  static void Randomize(QuicHttpStructureDecoder* p, QuicTestRandomBase* rng);
-};
-
-}  // namespace test
-}  // namespace quic
-
-#endif  // NET_THIRD_PARTY_QUIC_HTTP_DECODER_QUIC_HTTP_STRUCTURE_DECODER_TEST_UTIL_H_
diff --git a/net/third_party/quic/http/quic_http_constants.cc b/net/third_party/quic/http/quic_http_constants.cc
deleted file mode 100644
index 46b7965..0000000
--- a/net/third_party/quic/http/quic_http_constants.cc
+++ /dev/null
@@ -1,156 +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 "net/third_party/quic/http/quic_http_constants.h"
-
-#include "base/logging.h"
-#include "net/third_party/quic/platform/api/quic_str_cat.h"
-#include "net/third_party/quic/platform/api/quic_string_piece.h"
-#include "net/third_party/quic/platform/api/quic_string_utils.h"
-#include "net/third_party/quic/platform/api/quic_text_utils.h"
-
-namespace quic {
-
-QuicString QuicHttpFrameTypeToString(QuicHttpFrameType v) {
-  switch (v) {
-    case QuicHttpFrameType::DATA:
-      return "DATA";
-    case QuicHttpFrameType::HEADERS:
-      return "HEADERS";
-    case QuicHttpFrameType::QUIC_HTTP_PRIORITY:
-      return "QUIC_HTTP_PRIORITY";
-    case QuicHttpFrameType::RST_STREAM:
-      return "RST_STREAM";
-    case QuicHttpFrameType::SETTINGS:
-      return "SETTINGS";
-    case QuicHttpFrameType::PUSH_PROMISE:
-      return "PUSH_PROMISE";
-    case QuicHttpFrameType::PING:
-      return "PING";
-    case QuicHttpFrameType::GOAWAY:
-      return "GOAWAY";
-    case QuicHttpFrameType::WINDOW_UPDATE:
-      return "WINDOW_UPDATE";
-    case QuicHttpFrameType::CONTINUATION:
-      return "CONTINUATION";
-    case QuicHttpFrameType::ALTSVC:
-      return "ALTSVC";
-  }
-  return QuicStrCat("UnknownFrameType(", static_cast<int>(v), ")");
-}
-
-QuicString QuicHttpFrameTypeToString(uint8_t v) {
-  return QuicHttpFrameTypeToString(static_cast<QuicHttpFrameType>(v));
-}
-
-QuicString QuicHttpFrameFlagsToString(QuicHttpFrameType type, uint8_t flags) {
-  QuicString s;
-  // Closure to append flag name |v| to the QuicString |s|,
-  // and to clear |bit| from |flags|.
-  auto append_and_clear = [&s, &flags](QuicStringPiece v, uint8_t bit) {
-    if (!s.empty()) {
-      s.push_back('|');
-    }
-    QuicStrAppend(&s, v);
-    flags ^= bit;
-  };
-  if (flags & 0x01) {
-    if (type == QuicHttpFrameType::DATA || type == QuicHttpFrameType::HEADERS) {
-      append_and_clear("QUIC_HTTP_END_STREAM",
-                       QuicHttpFrameFlag::QUIC_HTTP_END_STREAM);
-    } else if (type == QuicHttpFrameType::SETTINGS ||
-               type == QuicHttpFrameType::PING) {
-      append_and_clear("QUIC_HTTP_ACK", QuicHttpFrameFlag::QUIC_HTTP_ACK);
-    }
-  }
-  if (flags & 0x04) {
-    if (type == QuicHttpFrameType::HEADERS ||
-        type == QuicHttpFrameType::PUSH_PROMISE ||
-        type == QuicHttpFrameType::CONTINUATION) {
-      append_and_clear("QUIC_HTTP_END_HEADERS",
-                       QuicHttpFrameFlag::QUIC_HTTP_END_HEADERS);
-    }
-  }
-  if (flags & 0x08) {
-    if (type == QuicHttpFrameType::DATA || type == QuicHttpFrameType::HEADERS ||
-        type == QuicHttpFrameType::PUSH_PROMISE) {
-      append_and_clear("QUIC_HTTP_PADDED", QuicHttpFrameFlag::QUIC_HTTP_PADDED);
-    }
-  }
-  if (flags & 0x20) {
-    if (type == QuicHttpFrameType::HEADERS) {
-      append_and_clear("QUIC_HTTP_PRIORITY",
-                       QuicHttpFrameFlag::QUIC_HTTP_PRIORITY);
-    }
-  }
-  if (flags != 0) {
-    append_and_clear(QuicStringPrintf("0x%02x", flags), flags);
-  }
-  DCHECK_EQ(0, flags);
-  return s;
-}
-QuicString QuicHttpFrameFlagsToString(uint8_t type, uint8_t flags) {
-  return QuicHttpFrameFlagsToString(static_cast<QuicHttpFrameType>(type),
-                                    flags);
-}
-
-QuicString QuicHttpErrorCodeToString(uint32_t v) {
-  switch (v) {
-    case 0x0:
-      return "NO_ERROR";
-    case 0x1:
-      return "PROTOCOL_ERROR";
-    case 0x2:
-      return "INTERNAL_ERROR";
-    case 0x3:
-      return "FLOW_CONTROL_ERROR";
-    case 0x4:
-      return "SETTINGS_TIMEOUT";
-    case 0x5:
-      return "STREAM_CLOSED";
-    case 0x6:
-      return "FRAME_SIZE_ERROR";
-    case 0x7:
-      return "REFUSED_STREAM";
-    case 0x8:
-      return "CANCEL";
-    case 0x9:
-      return "COMPRESSION_ERROR";
-    case 0xa:
-      return "CONNECT_ERROR";
-    case 0xb:
-      return "ENHANCE_YOUR_CALM";
-    case 0xc:
-      return "INADEQUATE_SECURITY";
-    case 0xd:
-      return "HTTP_1_1_REQUIRED";
-  }
-  return QuicStrCat("UnknownErrorCode(0x", QuicTextUtils::Hex(v), ")");
-}
-QuicString QuicHttpErrorCodeToString(QuicHttpErrorCode v) {
-  return QuicHttpErrorCodeToString(static_cast<uint32_t>(v));
-}
-
-QuicString QuicHttpSettingsParameterToString(uint32_t v) {
-  switch (v) {
-    case 0x1:
-      return "HEADER_TABLE_SIZE";
-    case 0x2:
-      return "ENABLE_PUSH";
-    case 0x3:
-      return "MAX_CONCURRENT_STREAMS";
-    case 0x4:
-      return "INITIAL_WINDOW_SIZE";
-    case 0x5:
-      return "MAX_FRAME_SIZE";
-    case 0x6:
-      return "MAX_HEADER_LIST_SIZE";
-  }
-  return QuicStrCat("UnknownSettingsParameter(0x", QuicTextUtils::Hex(v), ")");
-}
-QuicString QuicHttpSettingsParameterToString(QuicHttpSettingsParameter v) {
-  return QuicHttpSettingsParameterToString(static_cast<uint32_t>(v));
-}
-
-}  // namespace quic
diff --git a/net/third_party/quic/http/quic_http_constants.h b/net/third_party/quic/http/quic_http_constants.h
deleted file mode 100644
index 069da04..0000000
--- a/net/third_party/quic/http/quic_http_constants.h
+++ /dev/null
@@ -1,262 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_THIRD_PARTY_QUIC_HTTP_QUIC_HTTP_CONSTANTS_H_
-#define NET_THIRD_PARTY_QUIC_HTTP_QUIC_HTTP_CONSTANTS_H_
-
-// Constants from the HTTP/2 spec, RFC 7540, and associated helper functions.
-
-#include <cstdint>
-#include <iosfwd>
-
-#include "net/third_party/quic/platform/api/quic_export.h"
-#include "net/third_party/quic/platform/api/quic_string.h"
-
-namespace quic {
-
-// TODO(jamessynge): create http2_simple_types for types similar to
-// spdy::SpdyStreamId, but not for structures like QuicHttpFrameHeader. Then
-// will be able to move these stream id functions there.
-constexpr uint32_t QuicHttpUint31Mask() {
-  return 0x7fffffff;
-}
-constexpr uint32_t QuicHttpStreamIdMask() {
-  return QuicHttpUint31Mask();
-}
-
-// The value used to identify types of frames. Upper case to match the RFC.
-// The comments indicate which flags are valid for that frame type.
-// ALTSVC is defined in http://httpwg.org/http-extensions/alt-svc.html
-// (not yet final standard as of March 2016, but close).
-enum class QuicHttpFrameType : uint8_t {
-  DATA = 0,                // QUIC_HTTP_END_STREAM | QUIC_HTTP_PADDED
-  HEADERS = 1,             // QUIC_HTTP_END_STREAM | QUIC_HTTP_END_HEADERS |
-                           // QUIC_HTTP_PADDED | QUIC_HTTP_PRIORITY
-  QUIC_HTTP_PRIORITY = 2,  //
-  RST_STREAM = 3,          //
-  SETTINGS = 4,            // QUIC_HTTP_ACK
-  PUSH_PROMISE = 5,        // QUIC_HTTP_END_HEADERS | QUIC_HTTP_PADDED
-  PING = 6,                // QUIC_HTTP_ACK
-  GOAWAY = 7,              //
-  WINDOW_UPDATE = 8,       //
-  CONTINUATION = 9,        // QUIC_HTTP_END_HEADERS
-  ALTSVC = 10,             //
-};
-
-// Is the frame type known/supported?
-inline bool IsSupportedQuicHttpFrameType(uint32_t v) {
-  return v <= static_cast<uint32_t>(QuicHttpFrameType::ALTSVC);
-}
-inline bool IsSupportedQuicHttpFrameType(QuicHttpFrameType v) {
-  return IsSupportedQuicHttpFrameType(static_cast<uint32_t>(v));
-}
-
-// The return type is 'std::string' so that they can generate a unique
-// std::string for each unsupported value. Since these are just used for
-// debugging/error messages, that isn't a cost to we need to worry about. The
-// same applies to the functions later in this file.
-QUIC_EXPORT_PRIVATE QuicString QuicHttpFrameTypeToString(QuicHttpFrameType v);
-QUIC_EXPORT_PRIVATE QuicString QuicHttpFrameTypeToString(uint8_t v);
-QUIC_EXPORT_PRIVATE inline std::ostream& operator<<(std::ostream& out,
-                                                    QuicHttpFrameType v) {
-  return out << QuicHttpFrameTypeToString(v);
-}
-
-// Flags that appear in supported frame types. These are treated as bit masks.
-// The comments indicate for which frame types the flag is valid.
-enum QuicHttpFrameFlag {
-  QUIC_HTTP_END_STREAM = 0x01,   // DATA, HEADERS
-  QUIC_HTTP_ACK = 0x01,          // SETTINGS, PING
-  QUIC_HTTP_END_HEADERS = 0x04,  // HEADERS, PUSH_PROMISE, CONTINUATION
-  QUIC_HTTP_PADDED = 0x08,       // DATA, HEADERS, PUSH_PROMISE
-  QUIC_HTTP_PRIORITY = 0x20,     // HEADERS
-};
-
-// Formats zero or more flags for the specified type of frame. Returns an
-// empty std::string if flags==0.
-QUIC_EXPORT_PRIVATE QuicString
-QuicHttpFrameFlagsToString(QuicHttpFrameType type, uint8_t flags);
-QUIC_EXPORT_PRIVATE QuicString QuicHttpFrameFlagsToString(uint8_t type,
-                                                          uint8_t flags);
-
-// Error codes for GOAWAY and RST_STREAM frames.
-enum class QuicHttpErrorCode : uint32_t {
-  // The associated condition is not a result of an error. For example, a GOAWAY
-  // might include this code to indicate graceful shutdown of a connection.
-  HTTP2_NO_ERROR = 0x0,
-
-  // The endpoint detected an unspecific protocol error. This error is for use
-  // when a more specific error code is not available.
-  PROTOCOL_ERROR = 0x1,
-
-  // The endpoint encountered an unexpected internal error.
-  INTERNAL_ERROR = 0x2,
-
-  // The endpoint detected that its peer violated the flow-control protocol.
-  FLOW_CONTROL_ERROR = 0x3,
-
-  // The endpoint sent a SETTINGS frame but did not receive a response in a
-  // timely manner. See Section 6.5.3 ("Settings Synchronization").
-  SETTINGS_TIMEOUT = 0x4,
-
-  // The endpoint received a frame after a stream was half-closed.
-  STREAM_CLOSED = 0x5,
-
-  // The endpoint received a frame with an invalid size.
-  FRAME_SIZE_ERROR = 0x6,
-
-  // The endpoint refused the stream prior to performing any application
-  // processing (see Section 8.1.4 for details).
-  REFUSED_STREAM = 0x7,
-
-  // Used by the endpoint to indicate that the stream is no longer needed.
-  CANCEL = 0x8,
-
-  // The endpoint is unable to maintain the header compression context
-  // for the connection.
-  COMPRESSION_ERROR = 0x9,
-
-  // The connection established in response to a CONNECT request (Section 8.3)
-  // was reset or abnormally closed.
-  CONNECT_ERROR = 0xa,
-
-  // The endpoint detected that its peer is exhibiting a behavior that might
-  // be generating excessive load.
-  ENHANCE_YOUR_CALM = 0xb,
-
-  // The underlying transport has properties that do not meet minimum
-  // security requirements (see Section 9.2).
-  INADEQUATE_SECURITY = 0xc,
-
-  // The endpoint requires that HTTP/1.1 be used instead of HTTP/2.
-  HTTP_1_1_REQUIRED = 0xd,
-};
-
-// Is the error code supported? (So far that means it is in RFC 7540.)
-inline bool IsSupportedQuicHttpErrorCode(uint32_t v) {
-  return v <= static_cast<uint32_t>(QuicHttpErrorCode::HTTP_1_1_REQUIRED);
-}
-inline bool IsSupportedQuicHttpErrorCode(QuicHttpErrorCode v) {
-  return IsSupportedQuicHttpErrorCode(static_cast<uint32_t>(v));
-}
-
-// Format the specified error code.
-QUIC_EXPORT_PRIVATE QuicString QuicHttpErrorCodeToString(uint32_t v);
-QUIC_EXPORT_PRIVATE QuicString QuicHttpErrorCodeToString(QuicHttpErrorCode v);
-QUIC_EXPORT_PRIVATE inline std::ostream& operator<<(std::ostream& out,
-                                                    QuicHttpErrorCode v) {
-  return out << QuicHttpErrorCodeToString(v);
-}
-
-// Supported parameters in SETTINGS frames; so far just those in RFC 7540.
-enum class QuicHttpSettingsParameter : uint16_t {
-  // Allows the sender to inform the remote endpoint of the maximum size of the
-  // header compression table used to decode header blocks, in octets. The
-  // encoder can select any size equal to or less than this value by using
-  // signaling specific to the header compression format inside a header block
-  // (see [COMPRESSION]). The initial value is 4,096 octets.
-  HEADER_TABLE_SIZE = 0x1,
-
-  // This setting can be used to disable server push (Section 8.2). An endpoint
-  // MUST NOT send a PUSH_PROMISE frame if it receives this parameter set to a
-  // value of 0. An endpoint that has both set this parameter to 0 and had it
-  // acknowledged MUST treat the receipt of a PUSH_PROMISE frame as a connection
-  // error (Section 5.4.1) of type PROTOCOL_ERROR.
-  //
-  // The initial value is 1, which indicates that server push is permitted. Any
-  // value other than 0 or 1 MUST be treated as a connection error (Section
-  // 5.4.1) of type PROTOCOL_ERROR.
-  ENABLE_PUSH = 0x2,
-
-  // Indicates the maximum number of concurrent streams that the sender will
-  // allow. This limit is directional: it applies to the number of streams that
-  // the sender permits the receiver to create. Initially, there is no limit to
-  // this value. It is recommended that this value be no smaller than 100, so as
-  // to not unnecessarily limit parallelism.
-  //
-  // A value of 0 for MAX_CONCURRENT_STREAMS SHOULD NOT be treated as
-  // special by endpoints. A zero value does prevent the creation of new
-  // streams; however, this can also happen for any limit that is exhausted with
-  // active streams. Servers SHOULD only set a zero value for short durations;
-  // if a server does not wish to accept requests, closing the connection is
-  // more appropriate.
-  MAX_CONCURRENT_STREAMS = 0x3,
-
-  // Indicates the sender's initial window size (in octets) for stream-level
-  // flow control. The initial value is 2^16-1 (65,535) octets.
-  //
-  // This setting affects the window size of all streams (see Section 6.9.2).
-  //
-  // Values above the maximum flow-control window size of 2^31-1 MUST be treated
-  // as a connection error (Section 5.4.1) of type FLOW_CONTROL_ERROR.
-  INITIAL_WINDOW_SIZE = 0x4,
-
-  // Indicates the size of the largest frame payload that the sender is willing
-  // to receive, in octets.
-  //
-  // The initial value is 2^14 (16,384) octets. The value advertised by an
-  // endpoint MUST be between this initial value and the maximum allowed frame
-  // size (2^24-1 or 16,777,215 octets), inclusive. Values outside this range
-  // MUST be treated as a connection error (Section 5.4.1) of type
-  // PROTOCOL_ERROR.
-  MAX_FRAME_SIZE = 0x5,
-
-  // This advisory setting informs a peer of the maximum size of header list
-  // that the sender is prepared to accept, in octets. The value is based on the
-  // uncompressed size of header fields, including the length of the name and
-  // value in octets plus an overhead of 32 octets for each header field.
-  //
-  // For any given request, a lower limit than what is advertised MAY be
-  // enforced. The initial value of this setting is unlimited.
-  MAX_HEADER_LIST_SIZE = 0x6,
-};
-
-// Is the settings parameter supported (so far that means it is in RFC 7540)?
-inline bool IsSupportedQuicHttpSettingsParameter(uint32_t v) {
-  return 0 < v && v <= static_cast<uint32_t>(
-                           QuicHttpSettingsParameter::MAX_HEADER_LIST_SIZE);
-}
-inline bool IsSupportedQuicHttpSettingsParameter(QuicHttpSettingsParameter v) {
-  return IsSupportedQuicHttpSettingsParameter(static_cast<uint32_t>(v));
-}
-
-// Format the specified settings parameter.
-QUIC_EXPORT_PRIVATE QuicString QuicHttpSettingsParameterToString(uint32_t v);
-QUIC_EXPORT_PRIVATE QuicString
-QuicHttpSettingsParameterToString(QuicHttpSettingsParameter v);
-inline std::ostream& operator<<(std::ostream& out,
-                                QuicHttpSettingsParameter v) {
-  return out << QuicHttpSettingsParameterToString(v);
-}
-
-// Information about the initial, minimum and maximum value of settings (not
-// applicable to all settings parameters).
-class QuicHttpSettingsInfo {
- public:
-  // Default value for HEADER_TABLE_SIZE.
-  static constexpr uint32_t DefaultHeaderTableSize() { return 4096; }
-
-  // Default value for ENABLE_PUSH.
-  static constexpr bool DefaultEnablePush() { return true; }
-
-  // Default value for INITIAL_WINDOW_SIZE.
-  static constexpr uint32_t DefaultInitialWindowSize() { return 65535; }
-
-  // Maximum value for INITIAL_WINDOW_SIZE, and for the connection flow control
-  // window, and for each stream flow control window.
-  static constexpr uint32_t MaximumWindowSize() { return QuicHttpUint31Mask(); }
-
-  // Default value for MAX_FRAME_SIZE.
-  static constexpr uint32_t DefaultMaxFrameSize() { return 16384; }
-
-  // Minimum value for MAX_FRAME_SIZE.
-  static constexpr uint32_t MinimumMaxFrameSize() { return 16384; }
-
-  // Maximum value for MAX_FRAME_SIZE.
-  static constexpr uint32_t MaximumMaxFrameSize() { return (1 << 24) - 1; }
-};
-
-}  // namespace quic
-
-#endif  // NET_THIRD_PARTY_QUIC_HTTP_QUIC_HTTP_CONSTANTS_H_
diff --git a/net/third_party/quic/http/quic_http_constants_test.cc b/net/third_party/quic/http/quic_http_constants_test.cc
deleted file mode 100644
index cb955c1..0000000
--- a/net/third_party/quic/http/quic_http_constants_test.cc
+++ /dev/null
@@ -1,304 +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 "net/third_party/quic/http/quic_http_constants.h"
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace quic {
-namespace test {
-namespace {
-
-TEST(QuicHttpConstantsTest, QuicHttpFrameType) {
-  EXPECT_EQ(QuicHttpFrameType::DATA, static_cast<QuicHttpFrameType>(0));
-  EXPECT_EQ(QuicHttpFrameType::HEADERS, static_cast<QuicHttpFrameType>(1));
-  EXPECT_EQ(QuicHttpFrameType::QUIC_HTTP_PRIORITY,
-            static_cast<QuicHttpFrameType>(2));
-  EXPECT_EQ(QuicHttpFrameType::RST_STREAM, static_cast<QuicHttpFrameType>(3));
-  EXPECT_EQ(QuicHttpFrameType::SETTINGS, static_cast<QuicHttpFrameType>(4));
-  EXPECT_EQ(QuicHttpFrameType::PUSH_PROMISE, static_cast<QuicHttpFrameType>(5));
-  EXPECT_EQ(QuicHttpFrameType::PING, static_cast<QuicHttpFrameType>(6));
-  EXPECT_EQ(QuicHttpFrameType::GOAWAY, static_cast<QuicHttpFrameType>(7));
-  EXPECT_EQ(QuicHttpFrameType::WINDOW_UPDATE,
-            static_cast<QuicHttpFrameType>(8));
-  EXPECT_EQ(QuicHttpFrameType::CONTINUATION, static_cast<QuicHttpFrameType>(9));
-  EXPECT_EQ(QuicHttpFrameType::ALTSVC, static_cast<QuicHttpFrameType>(10));
-}
-
-TEST(QuicHttpConstantsTest, QuicHttpFrameTypeToString) {
-  EXPECT_EQ("DATA", QuicHttpFrameTypeToString(QuicHttpFrameType::DATA));
-  EXPECT_EQ("HEADERS", QuicHttpFrameTypeToString(QuicHttpFrameType::HEADERS));
-  EXPECT_EQ("QUIC_HTTP_PRIORITY",
-            QuicHttpFrameTypeToString(QuicHttpFrameType::QUIC_HTTP_PRIORITY));
-  EXPECT_EQ("RST_STREAM",
-            QuicHttpFrameTypeToString(QuicHttpFrameType::RST_STREAM));
-  EXPECT_EQ("SETTINGS", QuicHttpFrameTypeToString(QuicHttpFrameType::SETTINGS));
-  EXPECT_EQ("PUSH_PROMISE",
-            QuicHttpFrameTypeToString(QuicHttpFrameType::PUSH_PROMISE));
-  EXPECT_EQ("PING", QuicHttpFrameTypeToString(QuicHttpFrameType::PING));
-  EXPECT_EQ("GOAWAY", QuicHttpFrameTypeToString(QuicHttpFrameType::GOAWAY));
-  EXPECT_EQ("WINDOW_UPDATE",
-            QuicHttpFrameTypeToString(QuicHttpFrameType::WINDOW_UPDATE));
-  EXPECT_EQ("CONTINUATION",
-            QuicHttpFrameTypeToString(QuicHttpFrameType::CONTINUATION));
-  EXPECT_EQ("ALTSVC", QuicHttpFrameTypeToString(QuicHttpFrameType::ALTSVC));
-
-  EXPECT_EQ("DATA", QuicHttpFrameTypeToString(0));
-  EXPECT_EQ("HEADERS", QuicHttpFrameTypeToString(1));
-  EXPECT_EQ("QUIC_HTTP_PRIORITY", QuicHttpFrameTypeToString(2));
-  EXPECT_EQ("RST_STREAM", QuicHttpFrameTypeToString(3));
-  EXPECT_EQ("SETTINGS", QuicHttpFrameTypeToString(4));
-  EXPECT_EQ("PUSH_PROMISE", QuicHttpFrameTypeToString(5));
-  EXPECT_EQ("PING", QuicHttpFrameTypeToString(6));
-  EXPECT_EQ("GOAWAY", QuicHttpFrameTypeToString(7));
-  EXPECT_EQ("WINDOW_UPDATE", QuicHttpFrameTypeToString(8));
-  EXPECT_EQ("CONTINUATION", QuicHttpFrameTypeToString(9));
-  EXPECT_EQ("ALTSVC", QuicHttpFrameTypeToString(10));
-
-  EXPECT_EQ("UnknownFrameType(99)", QuicHttpFrameTypeToString(99));
-}
-
-TEST(QuicHttpConstantsTest, QuicHttpFrameFlag) {
-  EXPECT_EQ(QuicHttpFrameFlag::QUIC_HTTP_END_STREAM,
-            static_cast<QuicHttpFrameFlag>(0x01));
-  EXPECT_EQ(QuicHttpFrameFlag::QUIC_HTTP_ACK,
-            static_cast<QuicHttpFrameFlag>(0x01));
-  EXPECT_EQ(QuicHttpFrameFlag::QUIC_HTTP_END_HEADERS,
-            static_cast<QuicHttpFrameFlag>(0x04));
-  EXPECT_EQ(QuicHttpFrameFlag::QUIC_HTTP_PADDED,
-            static_cast<QuicHttpFrameFlag>(0x08));
-  EXPECT_EQ(QuicHttpFrameFlag::QUIC_HTTP_PRIORITY,
-            static_cast<QuicHttpFrameFlag>(0x20));
-
-  EXPECT_EQ(QuicHttpFrameFlag::QUIC_HTTP_END_STREAM, 0x01);
-  EXPECT_EQ(QuicHttpFrameFlag::QUIC_HTTP_ACK, 0x01);
-  EXPECT_EQ(QuicHttpFrameFlag::QUIC_HTTP_END_HEADERS, 0x04);
-  EXPECT_EQ(QuicHttpFrameFlag::QUIC_HTTP_PADDED, 0x08);
-  EXPECT_EQ(QuicHttpFrameFlag::QUIC_HTTP_PRIORITY, 0x20);
-}
-
-TEST(QuicHttpConstantsTest, QuicHttpFrameFlagsToString) {
-  // Single flags...
-
-  // 0b00000001
-  EXPECT_EQ(
-      "QUIC_HTTP_END_STREAM",
-      QuicHttpFrameFlagsToString(QuicHttpFrameType::DATA,
-                                 QuicHttpFrameFlag::QUIC_HTTP_END_STREAM));
-  EXPECT_EQ("QUIC_HTTP_END_STREAM",
-            QuicHttpFrameFlagsToString(QuicHttpFrameType::HEADERS, 0x01));
-  EXPECT_EQ("QUIC_HTTP_ACK",
-            QuicHttpFrameFlagsToString(QuicHttpFrameType::SETTINGS,
-                                       QuicHttpFrameFlag::QUIC_HTTP_ACK));
-  EXPECT_EQ("QUIC_HTTP_ACK",
-            QuicHttpFrameFlagsToString(QuicHttpFrameType::PING, 0x01));
-
-  // 0b00000010
-  EXPECT_EQ("0x02", QuicHttpFrameFlagsToString(0xff, 0x02));
-
-  // 0b00000100
-  EXPECT_EQ(
-      "QUIC_HTTP_END_HEADERS",
-      QuicHttpFrameFlagsToString(QuicHttpFrameType::HEADERS,
-                                 QuicHttpFrameFlag::QUIC_HTTP_END_HEADERS));
-  EXPECT_EQ("QUIC_HTTP_END_HEADERS",
-            QuicHttpFrameFlagsToString(QuicHttpFrameType::PUSH_PROMISE, 0x04));
-  EXPECT_EQ("QUIC_HTTP_END_HEADERS", QuicHttpFrameFlagsToString(0x09, 0x04));
-  EXPECT_EQ("0x04", QuicHttpFrameFlagsToString(0xff, 0x04));
-
-  // 0b00001000
-  EXPECT_EQ("QUIC_HTTP_PADDED",
-            QuicHttpFrameFlagsToString(QuicHttpFrameType::DATA,
-                                       QuicHttpFrameFlag::QUIC_HTTP_PADDED));
-  EXPECT_EQ("QUIC_HTTP_PADDED",
-            QuicHttpFrameFlagsToString(QuicHttpFrameType::HEADERS, 0x08));
-  EXPECT_EQ("QUIC_HTTP_PADDED", QuicHttpFrameFlagsToString(0x05, 0x08));
-  EXPECT_EQ("0x08", QuicHttpFrameFlagsToString(
-                        0xff, QuicHttpFrameFlag::QUIC_HTTP_PADDED));
-
-  // 0b00010000
-  EXPECT_EQ("0x10",
-            QuicHttpFrameFlagsToString(QuicHttpFrameType::SETTINGS, 0x10));
-
-  // 0b00100000
-  EXPECT_EQ("QUIC_HTTP_PRIORITY",
-            QuicHttpFrameFlagsToString(QuicHttpFrameType::HEADERS, 0x20));
-  EXPECT_EQ("0x20",
-            QuicHttpFrameFlagsToString(QuicHttpFrameType::PUSH_PROMISE, 0x20));
-
-  // 0b01000000
-  EXPECT_EQ("0x40", QuicHttpFrameFlagsToString(0xff, 0x40));
-
-  // 0b10000000
-  EXPECT_EQ("0x80", QuicHttpFrameFlagsToString(0xff, 0x80));
-
-  // Combined flags...
-
-  EXPECT_EQ("QUIC_HTTP_END_STREAM|QUIC_HTTP_PADDED|0xf6",
-            QuicHttpFrameFlagsToString(QuicHttpFrameType::DATA, 0xff));
-  EXPECT_EQ(
-      "QUIC_HTTP_END_STREAM|QUIC_HTTP_END_HEADERS|QUIC_HTTP_PADDED|QUIC_HTTP_"
-      "PRIORITY|0xd2",
-      QuicHttpFrameFlagsToString(QuicHttpFrameType::HEADERS, 0xff));
-  EXPECT_EQ("0xff", QuicHttpFrameFlagsToString(
-                        QuicHttpFrameType::QUIC_HTTP_PRIORITY, 0xff));
-  EXPECT_EQ("0xff",
-            QuicHttpFrameFlagsToString(QuicHttpFrameType::RST_STREAM, 0xff));
-  EXPECT_EQ("QUIC_HTTP_ACK|0xfe",
-            QuicHttpFrameFlagsToString(QuicHttpFrameType::SETTINGS, 0xff));
-  EXPECT_EQ("QUIC_HTTP_END_HEADERS|QUIC_HTTP_PADDED|0xf3",
-            QuicHttpFrameFlagsToString(QuicHttpFrameType::PUSH_PROMISE, 0xff));
-  EXPECT_EQ("QUIC_HTTP_ACK|0xfe",
-            QuicHttpFrameFlagsToString(QuicHttpFrameType::PING, 0xff));
-  EXPECT_EQ("0xff",
-            QuicHttpFrameFlagsToString(QuicHttpFrameType::GOAWAY, 0xff));
-  EXPECT_EQ("0xff",
-            QuicHttpFrameFlagsToString(QuicHttpFrameType::WINDOW_UPDATE, 0xff));
-  EXPECT_EQ("QUIC_HTTP_END_HEADERS|0xfb",
-            QuicHttpFrameFlagsToString(QuicHttpFrameType::CONTINUATION, 0xff));
-  EXPECT_EQ("0xff",
-            QuicHttpFrameFlagsToString(QuicHttpFrameType::ALTSVC, 0xff));
-  EXPECT_EQ("0xff", QuicHttpFrameFlagsToString(0xff, 0xff));
-}
-
-TEST(QuicHttpConstantsTest, QuicHttpErrorCode) {
-  EXPECT_EQ(QuicHttpErrorCode::HTTP2_NO_ERROR,
-            static_cast<QuicHttpErrorCode>(0x0));
-  EXPECT_EQ(QuicHttpErrorCode::PROTOCOL_ERROR,
-            static_cast<QuicHttpErrorCode>(0x1));
-  EXPECT_EQ(QuicHttpErrorCode::INTERNAL_ERROR,
-            static_cast<QuicHttpErrorCode>(0x2));
-  EXPECT_EQ(QuicHttpErrorCode::FLOW_CONTROL_ERROR,
-            static_cast<QuicHttpErrorCode>(0x3));
-  EXPECT_EQ(QuicHttpErrorCode::SETTINGS_TIMEOUT,
-            static_cast<QuicHttpErrorCode>(0x4));
-  EXPECT_EQ(QuicHttpErrorCode::STREAM_CLOSED,
-            static_cast<QuicHttpErrorCode>(0x5));
-  EXPECT_EQ(QuicHttpErrorCode::FRAME_SIZE_ERROR,
-            static_cast<QuicHttpErrorCode>(0x6));
-  EXPECT_EQ(QuicHttpErrorCode::REFUSED_STREAM,
-            static_cast<QuicHttpErrorCode>(0x7));
-  EXPECT_EQ(QuicHttpErrorCode::CANCEL, static_cast<QuicHttpErrorCode>(0x8));
-  EXPECT_EQ(QuicHttpErrorCode::COMPRESSION_ERROR,
-            static_cast<QuicHttpErrorCode>(0x9));
-  EXPECT_EQ(QuicHttpErrorCode::CONNECT_ERROR,
-            static_cast<QuicHttpErrorCode>(0xa));
-  EXPECT_EQ(QuicHttpErrorCode::ENHANCE_YOUR_CALM,
-            static_cast<QuicHttpErrorCode>(0xb));
-  EXPECT_EQ(QuicHttpErrorCode::INADEQUATE_SECURITY,
-            static_cast<QuicHttpErrorCode>(0xc));
-  EXPECT_EQ(QuicHttpErrorCode::HTTP_1_1_REQUIRED,
-            static_cast<QuicHttpErrorCode>(0xd));
-}
-
-TEST(QuicHttpConstantsTest, QuicHttpErrorCodeToString) {
-  EXPECT_EQ("NO_ERROR",
-            QuicHttpErrorCodeToString(QuicHttpErrorCode::HTTP2_NO_ERROR));
-  EXPECT_EQ("NO_ERROR", QuicHttpErrorCodeToString(0x0));
-  EXPECT_EQ("PROTOCOL_ERROR",
-            QuicHttpErrorCodeToString(QuicHttpErrorCode::PROTOCOL_ERROR));
-  EXPECT_EQ("PROTOCOL_ERROR", QuicHttpErrorCodeToString(0x1));
-  EXPECT_EQ("INTERNAL_ERROR",
-            QuicHttpErrorCodeToString(QuicHttpErrorCode::INTERNAL_ERROR));
-  EXPECT_EQ("INTERNAL_ERROR", QuicHttpErrorCodeToString(0x2));
-  EXPECT_EQ("FLOW_CONTROL_ERROR",
-            QuicHttpErrorCodeToString(QuicHttpErrorCode::FLOW_CONTROL_ERROR));
-  EXPECT_EQ("FLOW_CONTROL_ERROR", QuicHttpErrorCodeToString(0x3));
-  EXPECT_EQ("SETTINGS_TIMEOUT",
-            QuicHttpErrorCodeToString(QuicHttpErrorCode::SETTINGS_TIMEOUT));
-  EXPECT_EQ("SETTINGS_TIMEOUT", QuicHttpErrorCodeToString(0x4));
-  EXPECT_EQ("STREAM_CLOSED",
-            QuicHttpErrorCodeToString(QuicHttpErrorCode::STREAM_CLOSED));
-  EXPECT_EQ("STREAM_CLOSED", QuicHttpErrorCodeToString(0x5));
-  EXPECT_EQ("FRAME_SIZE_ERROR",
-            QuicHttpErrorCodeToString(QuicHttpErrorCode::FRAME_SIZE_ERROR));
-  EXPECT_EQ("FRAME_SIZE_ERROR", QuicHttpErrorCodeToString(0x6));
-  EXPECT_EQ("REFUSED_STREAM",
-            QuicHttpErrorCodeToString(QuicHttpErrorCode::REFUSED_STREAM));
-  EXPECT_EQ("REFUSED_STREAM", QuicHttpErrorCodeToString(0x7));
-  EXPECT_EQ("CANCEL", QuicHttpErrorCodeToString(QuicHttpErrorCode::CANCEL));
-  EXPECT_EQ("CANCEL", QuicHttpErrorCodeToString(0x8));
-  EXPECT_EQ("COMPRESSION_ERROR",
-            QuicHttpErrorCodeToString(QuicHttpErrorCode::COMPRESSION_ERROR));
-  EXPECT_EQ("COMPRESSION_ERROR", QuicHttpErrorCodeToString(0x9));
-  EXPECT_EQ("CONNECT_ERROR",
-            QuicHttpErrorCodeToString(QuicHttpErrorCode::CONNECT_ERROR));
-  EXPECT_EQ("CONNECT_ERROR", QuicHttpErrorCodeToString(0xa));
-  EXPECT_EQ("ENHANCE_YOUR_CALM",
-            QuicHttpErrorCodeToString(QuicHttpErrorCode::ENHANCE_YOUR_CALM));
-  EXPECT_EQ("ENHANCE_YOUR_CALM", QuicHttpErrorCodeToString(0xb));
-  EXPECT_EQ("INADEQUATE_SECURITY",
-            QuicHttpErrorCodeToString(QuicHttpErrorCode::INADEQUATE_SECURITY));
-  EXPECT_EQ("INADEQUATE_SECURITY", QuicHttpErrorCodeToString(0xc));
-  EXPECT_EQ("HTTP_1_1_REQUIRED",
-            QuicHttpErrorCodeToString(QuicHttpErrorCode::HTTP_1_1_REQUIRED));
-  EXPECT_EQ("HTTP_1_1_REQUIRED", QuicHttpErrorCodeToString(0xd));
-
-  EXPECT_EQ("UnknownErrorCode(0x123)", QuicHttpErrorCodeToString(0x123));
-}
-
-TEST(QuicHttpConstantsTest, QuicHttpSettingsParameter) {
-  EXPECT_EQ(QuicHttpSettingsParameter::HEADER_TABLE_SIZE,
-            static_cast<QuicHttpSettingsParameter>(0x1));
-  EXPECT_EQ(QuicHttpSettingsParameter::ENABLE_PUSH,
-            static_cast<QuicHttpSettingsParameter>(0x2));
-  EXPECT_EQ(QuicHttpSettingsParameter::MAX_CONCURRENT_STREAMS,
-            static_cast<QuicHttpSettingsParameter>(0x3));
-  EXPECT_EQ(QuicHttpSettingsParameter::INITIAL_WINDOW_SIZE,
-            static_cast<QuicHttpSettingsParameter>(0x4));
-  EXPECT_EQ(QuicHttpSettingsParameter::MAX_FRAME_SIZE,
-            static_cast<QuicHttpSettingsParameter>(0x5));
-  EXPECT_EQ(QuicHttpSettingsParameter::MAX_HEADER_LIST_SIZE,
-            static_cast<QuicHttpSettingsParameter>(0x6));
-
-  EXPECT_TRUE(IsSupportedQuicHttpSettingsParameter(
-      QuicHttpSettingsParameter::HEADER_TABLE_SIZE));
-  EXPECT_TRUE(IsSupportedQuicHttpSettingsParameter(
-      QuicHttpSettingsParameter::ENABLE_PUSH));
-  EXPECT_TRUE(IsSupportedQuicHttpSettingsParameter(
-      QuicHttpSettingsParameter::MAX_CONCURRENT_STREAMS));
-  EXPECT_TRUE(IsSupportedQuicHttpSettingsParameter(
-      QuicHttpSettingsParameter::INITIAL_WINDOW_SIZE));
-  EXPECT_TRUE(IsSupportedQuicHttpSettingsParameter(
-      QuicHttpSettingsParameter::MAX_FRAME_SIZE));
-  EXPECT_TRUE(IsSupportedQuicHttpSettingsParameter(
-      QuicHttpSettingsParameter::MAX_HEADER_LIST_SIZE));
-
-  EXPECT_FALSE(IsSupportedQuicHttpSettingsParameter(
-      static_cast<QuicHttpSettingsParameter>(0)));
-  EXPECT_FALSE(IsSupportedQuicHttpSettingsParameter(
-      static_cast<QuicHttpSettingsParameter>(7)));
-}
-
-TEST(QuicHttpConstantsTest, QuicHttpSettingsParameterToString) {
-  EXPECT_EQ("HEADER_TABLE_SIZE",
-            QuicHttpSettingsParameterToString(
-                QuicHttpSettingsParameter::HEADER_TABLE_SIZE));
-  EXPECT_EQ("HEADER_TABLE_SIZE", QuicHttpSettingsParameterToString(0x1));
-  EXPECT_EQ("ENABLE_PUSH", QuicHttpSettingsParameterToString(
-                               QuicHttpSettingsParameter::ENABLE_PUSH));
-  EXPECT_EQ("ENABLE_PUSH", QuicHttpSettingsParameterToString(0x2));
-  EXPECT_EQ("MAX_CONCURRENT_STREAMS",
-            QuicHttpSettingsParameterToString(
-                QuicHttpSettingsParameter::MAX_CONCURRENT_STREAMS));
-  EXPECT_EQ("MAX_CONCURRENT_STREAMS", QuicHttpSettingsParameterToString(0x3));
-  EXPECT_EQ("INITIAL_WINDOW_SIZE",
-            QuicHttpSettingsParameterToString(
-                QuicHttpSettingsParameter::INITIAL_WINDOW_SIZE));
-  EXPECT_EQ("INITIAL_WINDOW_SIZE", QuicHttpSettingsParameterToString(0x4));
-  EXPECT_EQ("MAX_FRAME_SIZE", QuicHttpSettingsParameterToString(
-                                  QuicHttpSettingsParameter::MAX_FRAME_SIZE));
-  EXPECT_EQ("MAX_FRAME_SIZE", QuicHttpSettingsParameterToString(0x5));
-  EXPECT_EQ("MAX_HEADER_LIST_SIZE",
-            QuicHttpSettingsParameterToString(
-                QuicHttpSettingsParameter::MAX_HEADER_LIST_SIZE));
-  EXPECT_EQ("MAX_HEADER_LIST_SIZE", QuicHttpSettingsParameterToString(0x6));
-
-  EXPECT_EQ("UnknownSettingsParameter(0x123)",
-            QuicHttpSettingsParameterToString(0x123));
-}
-
-}  // namespace
-}  // namespace test
-}  // namespace quic
diff --git a/net/third_party/quic/http/quic_http_constants_test_util.cc b/net/third_party/quic/http/quic_http_constants_test_util.cc
deleted file mode 100644
index 8588151..0000000
--- a/net/third_party/quic/http/quic_http_constants_test_util.cc
+++ /dev/null
@@ -1,145 +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 "net/third_party/quic/http/quic_http_constants_test_util.h"
-
-namespace quic {
-namespace test {
-
-std::vector<QuicHttpFrameType> AllQuicHttpFrameTypes() {
-  // clang-format off
-  return {
-      QuicHttpFrameType::DATA,
-      QuicHttpFrameType::HEADERS,
-      QuicHttpFrameType::QUIC_HTTP_PRIORITY,
-      QuicHttpFrameType::RST_STREAM,
-      QuicHttpFrameType::SETTINGS,
-      QuicHttpFrameType::PUSH_PROMISE,
-      QuicHttpFrameType::PING,
-      QuicHttpFrameType::GOAWAY,
-      QuicHttpFrameType::WINDOW_UPDATE,
-      QuicHttpFrameType::CONTINUATION,
-      QuicHttpFrameType::ALTSVC,
-  };
-  // clang-format on
-}
-
-std::vector<QuicHttpFrameFlag> AllQuicHttpFrameFlagsForFrameType(
-    QuicHttpFrameType type) {
-  // clang-format off
-  switch (type) {
-    case QuicHttpFrameType::DATA:
-      return {
-          QuicHttpFrameFlag::QUIC_HTTP_END_STREAM,
-          QuicHttpFrameFlag::QUIC_HTTP_PADDED,
-      };
-    case QuicHttpFrameType::HEADERS:
-      return {
-          QuicHttpFrameFlag::QUIC_HTTP_END_STREAM,
-          QuicHttpFrameFlag::QUIC_HTTP_END_HEADERS,
-          QuicHttpFrameFlag::QUIC_HTTP_PADDED,
-          QuicHttpFrameFlag::QUIC_HTTP_PRIORITY,
-      };
-    case QuicHttpFrameType::SETTINGS:
-      return {
-          QuicHttpFrameFlag::QUIC_HTTP_ACK,
-      };
-    case QuicHttpFrameType::PUSH_PROMISE:
-      return {
-          QuicHttpFrameFlag::QUIC_HTTP_END_HEADERS,
-          QuicHttpFrameFlag::QUIC_HTTP_PADDED,
-      };
-    case QuicHttpFrameType::PING:
-      return {
-          QuicHttpFrameFlag::QUIC_HTTP_ACK,
-      };
-    case QuicHttpFrameType::CONTINUATION:
-      return {
-          QuicHttpFrameFlag::QUIC_HTTP_END_HEADERS,
-      };
-    default:
-      return {};
-  }
-  // clang-format on
-}
-
-std::vector<QuicHttpErrorCode> AllQuicHttpErrorCodes() {
-  // clang-format off
-  return {
-      QuicHttpErrorCode::HTTP2_NO_ERROR,
-      QuicHttpErrorCode::PROTOCOL_ERROR,
-      QuicHttpErrorCode::INTERNAL_ERROR,
-      QuicHttpErrorCode::FLOW_CONTROL_ERROR,
-      QuicHttpErrorCode::SETTINGS_TIMEOUT,
-      QuicHttpErrorCode::STREAM_CLOSED,
-      QuicHttpErrorCode::FRAME_SIZE_ERROR,
-      QuicHttpErrorCode::REFUSED_STREAM,
-      QuicHttpErrorCode::CANCEL,
-      QuicHttpErrorCode::COMPRESSION_ERROR,
-      QuicHttpErrorCode::CONNECT_ERROR,
-      QuicHttpErrorCode::ENHANCE_YOUR_CALM,
-      QuicHttpErrorCode::INADEQUATE_SECURITY,
-      QuicHttpErrorCode::HTTP_1_1_REQUIRED,
-  };
-  // clang-format on
-}
-
-std::vector<QuicHttpSettingsParameter> AllQuicHttpSettingsParameters() {
-  // clang-format off
-  return {
-      QuicHttpSettingsParameter::HEADER_TABLE_SIZE,
-      QuicHttpSettingsParameter::ENABLE_PUSH,
-      QuicHttpSettingsParameter::MAX_CONCURRENT_STREAMS,
-      QuicHttpSettingsParameter::INITIAL_WINDOW_SIZE,
-      QuicHttpSettingsParameter::MAX_FRAME_SIZE,
-      QuicHttpSettingsParameter::MAX_HEADER_LIST_SIZE,
-  };
-  // clang-format on
-}
-
-// Returns a mask of flags supported for the specified frame type. Returns
-// zero for unknown frame types.
-uint8_t KnownFlagsMaskForFrameType(QuicHttpFrameType type) {
-  switch (type) {
-    case QuicHttpFrameType::DATA:
-      return QuicHttpFrameFlag::QUIC_HTTP_END_STREAM |
-             QuicHttpFrameFlag::QUIC_HTTP_PADDED;
-    case QuicHttpFrameType::HEADERS:
-      return QuicHttpFrameFlag::QUIC_HTTP_END_STREAM |
-             QuicHttpFrameFlag::QUIC_HTTP_END_HEADERS |
-             QuicHttpFrameFlag::QUIC_HTTP_PADDED |
-             QuicHttpFrameFlag::QUIC_HTTP_PRIORITY;
-    case QuicHttpFrameType::QUIC_HTTP_PRIORITY:
-      return 0x00;
-    case QuicHttpFrameType::RST_STREAM:
-      return 0x00;
-    case QuicHttpFrameType::SETTINGS:
-      return QuicHttpFrameFlag::QUIC_HTTP_ACK;
-    case QuicHttpFrameType::PUSH_PROMISE:
-      return QuicHttpFrameFlag::QUIC_HTTP_END_HEADERS |
-             QuicHttpFrameFlag::QUIC_HTTP_PADDED;
-    case QuicHttpFrameType::PING:
-      return QuicHttpFrameFlag::QUIC_HTTP_ACK;
-    case QuicHttpFrameType::GOAWAY:
-      return 0x00;
-    case QuicHttpFrameType::WINDOW_UPDATE:
-      return 0x00;
-    case QuicHttpFrameType::CONTINUATION:
-      return QuicHttpFrameFlag::QUIC_HTTP_END_HEADERS;
-    case QuicHttpFrameType::ALTSVC:
-      return 0x00;
-    default:
-      return 0x00;
-  }
-}
-
-uint8_t InvalidFlagMaskForFrameType(QuicHttpFrameType type) {
-  if (IsSupportedQuicHttpFrameType(type)) {
-    return ~KnownFlagsMaskForFrameType(type);
-  }
-  return 0x00;
-}
-
-}  // namespace test
-}  // namespace quic
diff --git a/net/third_party/quic/http/quic_http_constants_test_util.h b/net/third_party/quic/http/quic_http_constants_test_util.h
deleted file mode 100644
index 6fa587a4..0000000
--- a/net/third_party/quic/http/quic_http_constants_test_util.h
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_THIRD_PARTY_QUIC_HTTP_QUIC_HTTP_CONSTANTS_TEST_UTIL_H_
-#define NET_THIRD_PARTY_QUIC_HTTP_QUIC_HTTP_CONSTANTS_TEST_UTIL_H_
-
-#include <cstdint>
-#include <vector>
-
-#include "net/third_party/quic/http/quic_http_constants.h"
-
-namespace quic {
-namespace test {
-
-// Returns a vector of all supported frame types.
-std::vector<QuicHttpFrameType> AllQuicHttpFrameTypes();
-
-// Returns a vector of all supported frame flags for the specified
-// frame type. Empty if the type is unknown.
-std::vector<QuicHttpFrameFlag> AllQuicHttpFrameFlagsForFrameType(
-    QuicHttpFrameType type);
-
-// Returns a vector of all supported RST_STREAM and GOAWAY error codes.
-std::vector<QuicHttpErrorCode> AllQuicHttpErrorCodes();
-
-// Returns a vector of all supported parameters in SETTINGS frames.
-std::vector<QuicHttpSettingsParameter> AllQuicHttpSettingsParameters();
-
-// Returns a mask of flags supported for the specified frame type. Returns
-// zero for unknown frame types.
-uint8_t KnownFlagsMaskForFrameType(QuicHttpFrameType type);
-
-// Returns a mask of flag bits known to be invalid for the frame type.
-// For unknown frame types, the mask is zero; i.e., we don't know that any
-// are invalid.
-uint8_t InvalidFlagMaskForFrameType(QuicHttpFrameType type);
-
-}  // namespace test
-}  // namespace quic
-
-#endif  // NET_THIRD_PARTY_QUIC_HTTP_QUIC_HTTP_CONSTANTS_TEST_UTIL_H_
diff --git a/net/third_party/quic/http/quic_http_structures.cc b/net/third_party/quic/http/quic_http_structures.cc
deleted file mode 100644
index ccd0400..0000000
--- a/net/third_party/quic/http/quic_http_structures.cc
+++ /dev/null
@@ -1,142 +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 "net/third_party/quic/http/quic_http_structures.h"
-
-#include <cstring>  // For std::memcmp
-
-#include "net/third_party/quic/platform/api/quic_str_cat.h"
-#include "net/third_party/quic/platform/api/quic_string_utils.h"
-#include "net/third_party/quic/platform/api/quic_text_utils.h"
-
-namespace quic {
-
-// QuicHttpFrameHeader:
-
-bool QuicHttpFrameHeader::IsProbableHttpResponse() const {
-  return (payload_length == 0x485454 &&      // "HTT"
-          static_cast<char>(type) == 'P' &&  // "P"
-          flags == '/');                     // "/"
-}
-
-QuicString QuicHttpFrameHeader::ToString() const {
-  return QuicStrCat("length=", payload_length,
-                    ", type=", QuicHttpFrameTypeToString(type),
-                    ", flags=", FlagsToString(), ", stream=", stream_id);
-}
-
-QuicString QuicHttpFrameHeader::FlagsToString() const {
-  return QuicHttpFrameFlagsToString(type, flags);
-}
-
-bool operator==(const QuicHttpFrameHeader& a, const QuicHttpFrameHeader& b) {
-  return a.payload_length == b.payload_length && a.stream_id == b.stream_id &&
-         a.type == b.type && a.flags == b.flags;
-}
-
-std::ostream& operator<<(std::ostream& out, const QuicHttpFrameHeader& v) {
-  return out << v.ToString();
-}
-
-// QuicHttpPriorityFields:
-
-bool operator==(const QuicHttpPriorityFields& a,
-                const QuicHttpPriorityFields& b) {
-  return a.stream_dependency == b.stream_dependency && a.weight == b.weight;
-}
-
-QuicString QuicHttpPriorityFields::ToString() const {
-  std::stringstream ss;
-  ss << "E=" << (is_exclusive ? "true" : "false")
-     << ", stream=" << stream_dependency
-     << ", weight=" << static_cast<uint32_t>(weight);
-  return ss.str();
-}
-
-std::ostream& operator<<(std::ostream& out, const QuicHttpPriorityFields& v) {
-  return out << "E=" << (v.is_exclusive ? "true" : "false")
-             << ", stream=" << v.stream_dependency
-             << ", weight=" << static_cast<uint32_t>(v.weight);
-}
-
-// QuicHttpRstStreamFields:
-
-bool operator==(const QuicHttpRstStreamFields& a,
-                const QuicHttpRstStreamFields& b) {
-  return a.error_code == b.error_code;
-}
-
-std::ostream& operator<<(std::ostream& out, const QuicHttpRstStreamFields& v) {
-  return out << "error_code=" << v.error_code;
-}
-
-// QuicHttpSettingFields:
-
-bool operator==(const QuicHttpSettingFields& a,
-                const QuicHttpSettingFields& b) {
-  return a.parameter == b.parameter && a.value == b.value;
-}
-std::ostream& operator<<(std::ostream& out, const QuicHttpSettingFields& v) {
-  return out << "parameter=" << v.parameter << ", value=" << v.value;
-}
-
-// QuicHttpPushPromiseFields:
-
-bool operator==(const QuicHttpPushPromiseFields& a,
-                const QuicHttpPushPromiseFields& b) {
-  return a.promised_stream_id == b.promised_stream_id;
-}
-
-std::ostream& operator<<(std::ostream& out,
-                         const QuicHttpPushPromiseFields& v) {
-  return out << "promised_stream_id=" << v.promised_stream_id;
-}
-
-// QuicHttpPingFields:
-
-bool operator==(const QuicHttpPingFields& a, const QuicHttpPingFields& b) {
-  static_assert((sizeof a.opaque_bytes) == QuicHttpPingFields::EncodedSize(),
-                "Why not the same size?");
-  return 0 ==
-         std::memcmp(a.opaque_bytes, b.opaque_bytes, sizeof a.opaque_bytes);
-}
-
-std::ostream& operator<<(std::ostream& out, const QuicHttpPingFields& v) {
-  return out << "opaque_bytes=0x"
-             << QuicTextUtils::HexEncode(
-                    reinterpret_cast<const char*>(v.opaque_bytes),
-                    sizeof v.opaque_bytes);
-}
-
-// QuicHttpGoAwayFields:
-
-bool operator==(const QuicHttpGoAwayFields& a, const QuicHttpGoAwayFields& b) {
-  return a.last_stream_id == b.last_stream_id && a.error_code == b.error_code;
-}
-std::ostream& operator<<(std::ostream& out, const QuicHttpGoAwayFields& v) {
-  return out << "last_stream_id=" << v.last_stream_id
-             << ", error_code=" << v.error_code;
-}
-
-// QuicHttpWindowUpdateFields:
-
-bool operator==(const QuicHttpWindowUpdateFields& a,
-                const QuicHttpWindowUpdateFields& b) {
-  return a.window_size_increment == b.window_size_increment;
-}
-std::ostream& operator<<(std::ostream& out,
-                         const QuicHttpWindowUpdateFields& v) {
-  return out << "window_size_increment=" << v.window_size_increment;
-}
-
-// QuicHttpAltSvcFields:
-
-bool operator==(const QuicHttpAltSvcFields& a, const QuicHttpAltSvcFields& b) {
-  return a.origin_length == b.origin_length;
-}
-std::ostream& operator<<(std::ostream& out, const QuicHttpAltSvcFields& v) {
-  return out << "origin_length=" << v.origin_length;
-}
-
-}  // namespace quic
diff --git a/net/third_party/quic/http/quic_http_structures.h b/net/third_party/quic/http/quic_http_structures.h
deleted file mode 100644
index c488c87..0000000
--- a/net/third_party/quic/http/quic_http_structures.h
+++ /dev/null
@@ -1,329 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_THIRD_PARTY_QUIC_HTTP_QUIC_HTTP_STRUCTURES_H_
-#define NET_THIRD_PARTY_QUIC_HTTP_QUIC_HTTP_STRUCTURES_H_
-
-// Defines structs for various fixed sized structures in HTTP/2.
-//
-// Those structs with multiple fields have constructors that take arguments in
-// the same order as their encoding (which may be different from their order
-// in the struct). For single field structs, use aggregate initialization if
-// desired, e.g.:
-//
-//   QuicHttpRstStreamFields var{QuicHttpErrorCode::ENHANCE_YOUR_CALM};
-// or:
-//   SomeFunc(QuicHttpRstStreamFields{QuicHttpErrorCode::ENHANCE_YOUR_CALM});
-//
-// Each struct includes a static method EncodedSize which returns the number
-// of bytes of the encoding.
-//
-// With the exception of QuicHttpFrameHeader, all the types are named
-// QuicHttp<X>Fields, where X is the title-case form of the frame which always
-// includes the fields; the "always" is to cover the case of the
-// QUIC_HTTP_PRIORITY frame; its fields optionally appear in the HEADERS frame,
-// but the struct is called QuicHttpPriorityFields.
-
-#include <stddef.h>
-
-#include <cstdint>
-
-#include "base/logging.h"
-#include "net/third_party/quic/http/quic_http_constants.h"
-#include "net/third_party/quic/platform/api/quic_export.h"
-#include "net/third_party/quic/platform/api/quic_string.h"
-
-namespace quic {
-
-struct QUIC_EXPORT_PRIVATE QuicHttpFrameHeader {
-  QuicHttpFrameHeader() {}
-  QuicHttpFrameHeader(uint32_t payload_length,
-                      QuicHttpFrameType type,
-                      uint8_t flags,
-                      uint32_t stream_id)
-      : payload_length(payload_length),
-        stream_id(stream_id),
-        type(type),
-        flags(static_cast<QuicHttpFrameFlag>(flags)) {
-    DCHECK_LT(payload_length, 1u << 24)
-        << "Payload Length is only a 24 bit field\n"
-        << ToString();
-  }
-
-  static constexpr size_t EncodedSize() { return 9; }
-
-  // Keep the current value of those flags that are in
-  // valid_flags, and clear all the others.
-  void RetainFlags(uint8_t valid_flags) {
-    flags = static_cast<QuicHttpFrameFlag>(flags & valid_flags);
-  }
-
-  // Returns true if any of the flags in flag_mask are set,
-  // otherwise false.
-  bool HasAnyFlags(uint8_t flag_mask) const { return 0 != (flags & flag_mask); }
-
-  // Is the QUIC_HTTP_END_STREAM flag set?
-  bool IsEndStream() const {
-    DCHECK(type == QuicHttpFrameType::DATA ||
-           type == QuicHttpFrameType::HEADERS)
-        << ToString();
-    return (flags & QuicHttpFrameFlag::QUIC_HTTP_END_STREAM) != 0;
-  }
-
-  // Is the QUIC_HTTP_ACK flag set?
-  bool IsAck() const {
-    DCHECK(type == QuicHttpFrameType::SETTINGS ||
-           type == QuicHttpFrameType::PING)
-        << ToString();
-    return (flags & QuicHttpFrameFlag::QUIC_HTTP_ACK) != 0;
-  }
-
-  // Is the QUIC_HTTP_END_HEADERS flag set?
-  bool IsEndHeaders() const {
-    DCHECK(type == QuicHttpFrameType::HEADERS ||
-           type == QuicHttpFrameType::PUSH_PROMISE ||
-           type == QuicHttpFrameType::CONTINUATION)
-        << ToString();
-    return (flags & QuicHttpFrameFlag::QUIC_HTTP_END_HEADERS) != 0;
-  }
-
-  // Is the QUIC_HTTP_PADDED flag set?
-  bool IsPadded() const {
-    DCHECK(type == QuicHttpFrameType::DATA ||
-           type == QuicHttpFrameType::HEADERS ||
-           type == QuicHttpFrameType::PUSH_PROMISE)
-        << ToString();
-    return (flags & QuicHttpFrameFlag::QUIC_HTTP_PADDED) != 0;
-  }
-
-  // Is the QUIC_HTTP_PRIORITY flag set?
-  bool HasPriority() const {
-    DCHECK_EQ(type, QuicHttpFrameType::HEADERS) << ToString();
-    return (flags & QuicHttpFrameFlag::QUIC_HTTP_PRIORITY) != 0;
-  }
-
-  // Does the encoding of this header start with "HTTP/", indicating that it
-  // might be from a non-HTTP/2 server.
-  bool IsProbableHttpResponse() const;
-
-  // Produce std::strings useful for debugging/logging messages.
-  QuicString ToString() const;
-  QuicString FlagsToString() const;
-
-  // 24 bit length of the payload after the header, including any padding.
-  // First field in encoding.
-  uint32_t payload_length;  // 24 bits
-
-  // 31 bit stream id, with high bit (32nd bit) reserved (must be zero),
-  // and is cleared during decoding.
-  // Fourth field in encoding.
-  uint32_t stream_id;
-
-  // Type of the frame.
-  // Second field in encoding.
-  QuicHttpFrameType type;
-
-  // Flag bits, with interpretations that depend upon the frame type.
-  // Flag bits not used by the frame type are cleared.
-  // Third field in encoding.
-  QuicHttpFrameFlag flags;
-};
-
-QUIC_EXPORT_PRIVATE bool operator==(const QuicHttpFrameHeader& a,
-                                    const QuicHttpFrameHeader& b);
-QUIC_EXPORT_PRIVATE inline bool operator!=(const QuicHttpFrameHeader& a,
-                                           const QuicHttpFrameHeader& b) {
-  return !(a == b);
-}
-QUIC_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out,
-                                             const QuicHttpFrameHeader& v);
-
-// QuicHttpPriorityFields:
-
-struct QUIC_EXPORT_PRIVATE QuicHttpPriorityFields {
-  QuicHttpPriorityFields() {}
-  QuicHttpPriorityFields(uint32_t stream_dependency,
-                         uint32_t weight,
-                         bool is_exclusive)
-      : stream_dependency(stream_dependency),
-        weight(weight),
-        is_exclusive(is_exclusive) {
-    // Can't have the high-bit set in the stream id because we need to use
-    // that for the EXCLUSIVE flag bit.
-    DCHECK_EQ(stream_dependency, stream_dependency & QuicHttpStreamIdMask())
-        << "Stream Dependency is only a 31-bit field.\n"
-        << ToString();
-    DCHECK_LE(1u, weight) << "Weight is too small.";
-    DCHECK_LE(weight, 256u) << "Weight is too large.";
-  }
-  static constexpr size_t EncodedSize() { return 5; }
-
-  QuicString ToString() const;
-
-  // A 31-bit stream identifier for the stream that this stream depends on.
-  uint32_t stream_dependency;
-
-  // Weight (1 to 256) is encoded as a byte in the range 0 to 255, so we
-  // add one when decoding, and store it in a field larger than a byte.
-  uint32_t weight;
-
-  // A single-bit flag indicating that the stream dependency is exclusive;
-  // extracted from high bit of stream dependency field during decoding.
-  bool is_exclusive;
-};
-
-QUIC_EXPORT_PRIVATE bool operator==(const QuicHttpPriorityFields& a,
-                                    const QuicHttpPriorityFields& b);
-QUIC_EXPORT_PRIVATE inline bool operator!=(const QuicHttpPriorityFields& a,
-                                           const QuicHttpPriorityFields& b) {
-  return !(a == b);
-}
-QUIC_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out,
-                                             const QuicHttpPriorityFields& v);
-
-// QuicHttpRstStreamFields:
-
-struct QuicHttpRstStreamFields {
-  static constexpr size_t EncodedSize() { return 4; }
-  bool IsSupportedErrorCode() const {
-    return IsSupportedQuicHttpErrorCode(error_code);
-  }
-
-  QuicHttpErrorCode error_code;
-};
-
-QUIC_EXPORT_PRIVATE bool operator==(const QuicHttpRstStreamFields& a,
-                                    const QuicHttpRstStreamFields& b);
-QUIC_EXPORT_PRIVATE inline bool operator!=(const QuicHttpRstStreamFields& a,
-                                           const QuicHttpRstStreamFields& b) {
-  return !(a == b);
-}
-QUIC_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out,
-                                             const QuicHttpRstStreamFields& v);
-
-// QuicHttpSettingFields:
-
-struct QuicHttpSettingFields {
-  QuicHttpSettingFields() {}
-  QuicHttpSettingFields(QuicHttpSettingsParameter parameter, uint32_t value)
-      : parameter(parameter), value(value) {}
-  static constexpr size_t EncodedSize() { return 6; }
-  bool IsSupportedParameter() const {
-    return IsSupportedQuicHttpSettingsParameter(parameter);
-  }
-
-  QuicHttpSettingsParameter parameter;
-  uint32_t value;
-};
-
-QUIC_EXPORT_PRIVATE bool operator==(const QuicHttpSettingFields& a,
-                                    const QuicHttpSettingFields& b);
-QUIC_EXPORT_PRIVATE inline bool operator!=(const QuicHttpSettingFields& a,
-                                           const QuicHttpSettingFields& b) {
-  return !(a == b);
-}
-QUIC_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out,
-                                             const QuicHttpSettingFields& v);
-
-// QuicHttpPushPromiseFields:
-
-struct QuicHttpPushPromiseFields {
-  static constexpr size_t EncodedSize() { return 4; }
-
-  uint32_t promised_stream_id;
-};
-
-QUIC_EXPORT_PRIVATE bool operator==(const QuicHttpPushPromiseFields& a,
-                                    const QuicHttpPushPromiseFields& b);
-QUIC_EXPORT_PRIVATE inline bool operator!=(const QuicHttpPushPromiseFields& a,
-                                           const QuicHttpPushPromiseFields& b) {
-  return !(a == b);
-}
-QUIC_EXPORT_PRIVATE std::ostream& operator<<(
-    std::ostream& out,
-    const QuicHttpPushPromiseFields& v);
-
-// QuicHttpPingFields:
-
-struct QuicHttpPingFields {
-  static constexpr size_t EncodedSize() { return 8; }
-
-  uint8_t opaque_bytes[8];
-};
-
-QUIC_EXPORT_PRIVATE bool operator==(const QuicHttpPingFields& a,
-                                    const QuicHttpPingFields& b);
-QUIC_EXPORT_PRIVATE inline bool operator!=(const QuicHttpPingFields& a,
-                                           const QuicHttpPingFields& b) {
-  return !(a == b);
-}
-QUIC_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out,
-                                             const QuicHttpPingFields& v);
-
-// QuicHttpGoAwayFields:
-
-struct QuicHttpGoAwayFields {
-  QuicHttpGoAwayFields() {}
-  QuicHttpGoAwayFields(uint32_t last_stream_id, QuicHttpErrorCode error_code)
-      : last_stream_id(last_stream_id), error_code(error_code) {}
-  static constexpr size_t EncodedSize() { return 8; }
-  bool IsSupportedErrorCode() const {
-    return IsSupportedQuicHttpErrorCode(error_code);
-  }
-
-  uint32_t last_stream_id;
-  QuicHttpErrorCode error_code;
-};
-
-QUIC_EXPORT_PRIVATE bool operator==(const QuicHttpGoAwayFields& a,
-                                    const QuicHttpGoAwayFields& b);
-QUIC_EXPORT_PRIVATE inline bool operator!=(const QuicHttpGoAwayFields& a,
-                                           const QuicHttpGoAwayFields& b) {
-  return !(a == b);
-}
-QUIC_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out,
-                                             const QuicHttpGoAwayFields& v);
-
-// QuicHttpWindowUpdateFields:
-
-struct QuicHttpWindowUpdateFields {
-  static constexpr size_t EncodedSize() { return 4; }
-
-  // 31-bit, unsigned increase in the window size (only positive values are
-  // allowed). The high-bit is reserved for the future.
-  uint32_t window_size_increment;
-};
-
-QUIC_EXPORT_PRIVATE bool operator==(const QuicHttpWindowUpdateFields& a,
-                                    const QuicHttpWindowUpdateFields& b);
-QUIC_EXPORT_PRIVATE inline bool operator!=(
-    const QuicHttpWindowUpdateFields& a,
-    const QuicHttpWindowUpdateFields& b) {
-  return !(a == b);
-}
-QUIC_EXPORT_PRIVATE std::ostream& operator<<(
-    std::ostream& out,
-    const QuicHttpWindowUpdateFields& v);
-
-// QuicHttpAltSvcFields:
-
-struct QuicHttpAltSvcFields {
-  static constexpr size_t EncodedSize() { return 2; }
-
-  // This is the one fixed size portion of the ALTSVC payload.
-  uint16_t origin_length;
-};
-
-QUIC_EXPORT_PRIVATE bool operator==(const QuicHttpAltSvcFields& a,
-                                    const QuicHttpAltSvcFields& b);
-QUIC_EXPORT_PRIVATE inline bool operator!=(const QuicHttpAltSvcFields& a,
-                                           const QuicHttpAltSvcFields& b) {
-  return !(a == b);
-}
-QUIC_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& out,
-                                             const QuicHttpAltSvcFields& v);
-
-}  // namespace quic
-
-#endif  // NET_THIRD_PARTY_QUIC_HTTP_QUIC_HTTP_STRUCTURES_H_
diff --git a/net/third_party/quic/http/quic_http_structures_test.cc b/net/third_party/quic/http/quic_http_structures_test.cc
deleted file mode 100644
index 41a5259..0000000
--- a/net/third_party/quic/http/quic_http_structures_test.cc
+++ /dev/null
@@ -1,500 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-#include "net/third_party/quic/http/quic_http_structures.h"
-
-// Tests are focused on QuicHttpFrameHeader because it has by far the most
-// methods of any of the structures.
-// Note that EXPECT.*DEATH tests are slow (a fork is probably involved).
-
-// And in case you're wondering, yes, these are ridiculously thorough tests,
-// but believe it or not, I've found stupid bugs this way.
-
-#include <memory>
-#include <ostream>  // IWYU pragma: keep  // for stringstream
-#include <type_traits>
-#include <vector>
-
-#include "net/third_party/quic/http/quic_http_structures_test_util.h"
-#include "net/third_party/quic/platform/api/quic_str_cat.h"
-#include "net/third_party/quic/platform/api/quic_string_utils.h"
-#include "net/third_party/quic/platform/api/quic_test_random.h"
-#include "net/third_party/quic/platform/api/quic_text_utils.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using ::testing::AssertionResult;
-using ::testing::Combine;
-using ::testing::Contains;
-using ::testing::HasSubstr;
-using ::testing::Not;
-using ::testing::Values;
-using ::testing::ValuesIn;
-
-namespace quic {
-namespace test {
-namespace {
-
-template <typename E>
-E IncrementEnum(E e) {
-  typedef typename std::underlying_type<E>::type I;
-  return static_cast<E>(1 + static_cast<I>(e));
-}
-
-#if GTEST_HAS_DEATH_TEST && !defined(NDEBUG)
-std::vector<QuicHttpFrameType> ValidFrameTypes() {
-  std::vector<QuicHttpFrameType> valid_types{QuicHttpFrameType::DATA};
-  while (valid_types.back() != QuicHttpFrameType::ALTSVC) {
-    valid_types.push_back(IncrementEnum(valid_types.back()));
-  }
-  return valid_types;
-}
-#endif  // GTEST_HAS_DEATH_TEST && !defined(NDEBUG)
-
-TEST(QuicHttpFrameHeaderTest, Constructor) {
-  QuicTestRandom random;
-  uint8_t frame_type = 0;
-  do {
-    // Only the payload length is DCHECK'd in the constructor, so we need to
-    // make sure it is a "uint24".
-    uint32_t payload_length = random.Rand32() & 0xffffff;
-    QuicHttpFrameType type = static_cast<QuicHttpFrameType>(frame_type);
-    uint8_t flags = random.Rand8();
-    uint32_t stream_id = random.Rand32();
-
-    QuicHttpFrameHeader v(payload_length, type, flags, stream_id);
-
-    EXPECT_EQ(payload_length, v.payload_length);
-    EXPECT_EQ(type, v.type);
-    EXPECT_EQ(flags, v.flags);
-    EXPECT_EQ(stream_id, v.stream_id);
-  } while (frame_type++ == 255);
-
-#if GTEST_HAS_DEATH_TEST && !defined(NDEBUG)
-  EXPECT_DEBUG_DEATH(
-      QuicHttpFrameHeader(0x01000000, QuicHttpFrameType::DATA, 0, 1),
-      "payload_length");
-#endif  // GTEST_HAS_DEATH_TEST && !defined(NDEBUG)
-}
-
-TEST(QuicHttpFrameHeaderTest, Eq) {
-  QuicTestRandom random;
-  uint32_t payload_length = random.Rand32() & 0xffffff;
-  QuicHttpFrameType type = static_cast<QuicHttpFrameType>(random.Rand8());
-
-  uint8_t flags = random.Rand8();
-  uint32_t stream_id = random.Rand32();
-
-  QuicHttpFrameHeader v(payload_length, type, flags, stream_id);
-
-  EXPECT_EQ(payload_length, v.payload_length);
-  EXPECT_EQ(type, v.type);
-  EXPECT_EQ(flags, v.flags);
-  EXPECT_EQ(stream_id, v.stream_id);
-
-  QuicHttpFrameHeader u(0, type, ~flags, stream_id);
-
-  EXPECT_NE(u, v);
-  EXPECT_NE(v, u);
-  EXPECT_FALSE(u == v);
-  EXPECT_FALSE(v == u);
-  EXPECT_TRUE(u != v);
-  EXPECT_TRUE(v != u);
-
-  u = v;
-
-  EXPECT_EQ(u, v);
-  EXPECT_EQ(v, u);
-  EXPECT_TRUE(u == v);
-  EXPECT_TRUE(v == u);
-  EXPECT_FALSE(u != v);
-  EXPECT_FALSE(v != u);
-}
-
-#if GTEST_HAS_DEATH_TEST && !defined(NDEBUG)
-// The tests of the valid frame types include EXPECT_DEBUG_DEATH, which is
-// quite slow, so using value parameterized tests in order to allow sharding.
-class QuicHttpFrameHeaderTypeAndFlagTest
-    : public ::testing::TestWithParam<
-          std::tuple<QuicHttpFrameType, QuicHttpFrameFlag>> {
- protected:
-  QuicHttpFrameHeaderTypeAndFlagTest()
-      : type_(std::get<0>(GetParam())), flags_(std::get<1>(GetParam())) {
-    LOG(INFO) << "Frame type: " << type_;
-    LOG(INFO) << "Frame flags: " << QuicHttpFrameFlagsToString(type_, flags_);
-  }
-
-  const QuicHttpFrameType type_;
-  const QuicHttpFrameFlag flags_;
-};
-
-class QuicHttpIsEndStreamTest : public QuicHttpFrameHeaderTypeAndFlagTest {};
-INSTANTIATE_TEST_CASE_P(IsEndStream,
-                        QuicHttpIsEndStreamTest,
-                        Combine(ValuesIn(ValidFrameTypes()),
-                                Values(~QuicHttpFrameFlag::QUIC_HTTP_END_STREAM,
-                                       0xff)));
-TEST_P(QuicHttpIsEndStreamTest, IsEndStream) {
-  const bool is_set = (flags_ & QuicHttpFrameFlag::QUIC_HTTP_END_STREAM) ==
-                      QuicHttpFrameFlag::QUIC_HTTP_END_STREAM;
-  QuicString flags_string;
-  QuicHttpFrameHeader v(0, type_, flags_, 0);
-  switch (type_) {
-    case QuicHttpFrameType::DATA:
-    case QuicHttpFrameType::HEADERS:
-      EXPECT_EQ(is_set, v.IsEndStream()) << v;
-      flags_string = v.FlagsToString();
-      if (is_set) {
-        EXPECT_THAT(QuicTextUtils::Split(flags_string, '|'),
-                    Contains("QUIC_HTTP_END_STREAM"));
-      } else {
-        EXPECT_THAT(flags_string, Not(HasSubstr("QUIC_HTTP_END_STREAM")));
-      }
-      v.RetainFlags(QuicHttpFrameFlag::QUIC_HTTP_END_STREAM);
-      EXPECT_EQ(is_set, v.IsEndStream()) << v;
-      {
-        std::stringstream s;
-        s << v;
-        EXPECT_EQ(v.ToString(), s.str());
-        if (is_set) {
-          EXPECT_THAT(s.str(), HasSubstr("flags=QUIC_HTTP_END_STREAM,"));
-        } else {
-          EXPECT_THAT(s.str(), HasSubstr("flags=,"));
-        }
-      }
-      break;
-    default:
-      EXPECT_DEBUG_DEATH(v.IsEndStream(), "DATA.*HEADERS") << v;
-  }
-}
-
-class IsQUIC_HTTP_ACKTest : public QuicHttpFrameHeaderTypeAndFlagTest {};
-INSTANTIATE_TEST_CASE_P(IsAck,
-                        IsQUIC_HTTP_ACKTest,
-                        Combine(ValuesIn(ValidFrameTypes()),
-                                Values(~QuicHttpFrameFlag::QUIC_HTTP_ACK,
-                                       0xff)));
-TEST_P(IsQUIC_HTTP_ACKTest, IsAck) {
-  const bool is_set = (flags_ & QuicHttpFrameFlag::QUIC_HTTP_ACK) ==
-                      QuicHttpFrameFlag::QUIC_HTTP_ACK;
-  QuicString flags_string;
-  QuicHttpFrameHeader v(0, type_, flags_, 0);
-  switch (type_) {
-    case QuicHttpFrameType::SETTINGS:
-    case QuicHttpFrameType::PING:
-      EXPECT_EQ(is_set, v.IsAck()) << v;
-      flags_string = v.FlagsToString();
-      if (is_set) {
-        EXPECT_THAT(QuicTextUtils::Split(flags_string, '|'),
-                    Contains("QUIC_HTTP_ACK"));
-      } else {
-        EXPECT_THAT(flags_string, Not(HasSubstr("QUIC_HTTP_ACK")));
-      }
-      v.RetainFlags(QuicHttpFrameFlag::QUIC_HTTP_ACK);
-      EXPECT_EQ(is_set, v.IsAck()) << v;
-      {
-        std::stringstream s;
-        s << v;
-        EXPECT_EQ(v.ToString(), s.str());
-        if (is_set) {
-          EXPECT_THAT(s.str(), HasSubstr("flags=QUIC_HTTP_ACK,"));
-        } else {
-          EXPECT_THAT(s.str(), HasSubstr("flags=,"));
-        }
-      }
-      break;
-    default:
-      EXPECT_DEBUG_DEATH(v.IsAck(), "SETTINGS.*PING") << v;
-  }
-}
-
-class QuicHttpIsEndHeadersTest : public QuicHttpFrameHeaderTypeAndFlagTest {};
-INSTANTIATE_TEST_CASE_P(
-    IsEndHeaders,
-    QuicHttpIsEndHeadersTest,
-    Combine(ValuesIn(ValidFrameTypes()),
-            Values(~QuicHttpFrameFlag::QUIC_HTTP_END_HEADERS, 0xff)));
-TEST_P(QuicHttpIsEndHeadersTest, IsEndHeaders) {
-  const bool is_set = (flags_ & QuicHttpFrameFlag::QUIC_HTTP_END_HEADERS) ==
-                      QuicHttpFrameFlag::QUIC_HTTP_END_HEADERS;
-  QuicString flags_string;
-  QuicHttpFrameHeader v(0, type_, flags_, 0);
-  switch (type_) {
-    case QuicHttpFrameType::HEADERS:
-    case QuicHttpFrameType::PUSH_PROMISE:
-    case QuicHttpFrameType::CONTINUATION:
-      EXPECT_EQ(is_set, v.IsEndHeaders()) << v;
-      flags_string = v.FlagsToString();
-      if (is_set) {
-        EXPECT_THAT(QuicTextUtils::Split(flags_string, '|'),
-                    Contains("QUIC_HTTP_END_HEADERS"));
-      } else {
-        EXPECT_THAT(flags_string, Not(HasSubstr("QUIC_HTTP_END_HEADERS")));
-      }
-      v.RetainFlags(QuicHttpFrameFlag::QUIC_HTTP_END_HEADERS);
-      EXPECT_EQ(is_set, v.IsEndHeaders()) << v;
-      {
-        std::stringstream s;
-        s << v;
-        EXPECT_EQ(v.ToString(), s.str());
-        if (is_set) {
-          EXPECT_THAT(s.str(), HasSubstr("flags=QUIC_HTTP_END_HEADERS,"));
-        } else {
-          EXPECT_THAT(s.str(), HasSubstr("flags=,"));
-        }
-      }
-      break;
-    default:
-      EXPECT_DEBUG_DEATH(v.IsEndHeaders(),
-                         "HEADERS.*PUSH_PROMISE.*CONTINUATION")
-          << v;
-  }
-}
-
-class QuicHttpIsPaddedTest : public QuicHttpFrameHeaderTypeAndFlagTest {};
-INSTANTIATE_TEST_CASE_P(IsPadded,
-                        QuicHttpIsPaddedTest,
-                        Combine(ValuesIn(ValidFrameTypes()),
-                                Values(~QuicHttpFrameFlag::QUIC_HTTP_PADDED,
-                                       0xff)));
-TEST_P(QuicHttpIsPaddedTest, IsPadded) {
-  const bool is_set = (flags_ & QuicHttpFrameFlag::QUIC_HTTP_PADDED) ==
-                      QuicHttpFrameFlag::QUIC_HTTP_PADDED;
-  QuicString flags_string;
-  QuicHttpFrameHeader v(0, type_, flags_, 0);
-  switch (type_) {
-    case QuicHttpFrameType::DATA:
-    case QuicHttpFrameType::HEADERS:
-    case QuicHttpFrameType::PUSH_PROMISE:
-      EXPECT_EQ(is_set, v.IsPadded()) << v;
-      flags_string = v.FlagsToString();
-      if (is_set) {
-        EXPECT_THAT(QuicTextUtils::Split(flags_string, '|'),
-                    Contains("QUIC_HTTP_PADDED"));
-      } else {
-        EXPECT_THAT(flags_string, Not(HasSubstr("QUIC_HTTP_PADDED")));
-      }
-      v.RetainFlags(QuicHttpFrameFlag::QUIC_HTTP_PADDED);
-      EXPECT_EQ(is_set, v.IsPadded()) << v;
-      {
-        std::stringstream s;
-        s << v;
-        EXPECT_EQ(v.ToString(), s.str());
-        if (is_set) {
-          EXPECT_THAT(s.str(), HasSubstr("flags=QUIC_HTTP_PADDED,"));
-        } else {
-          EXPECT_THAT(s.str(), HasSubstr("flags=,"));
-        }
-      }
-      break;
-    default:
-      EXPECT_DEBUG_DEATH(v.IsPadded(), "DATA.*HEADERS.*PUSH_PROMISE") << v;
-  }
-}
-
-class QuicHttpHasPriorityTest : public QuicHttpFrameHeaderTypeAndFlagTest {};
-INSTANTIATE_TEST_CASE_P(HasPriority,
-                        QuicHttpHasPriorityTest,
-                        Combine(ValuesIn(ValidFrameTypes()),
-                                Values(~QuicHttpFrameFlag::QUIC_HTTP_PRIORITY,
-                                       0xff)));
-TEST_P(QuicHttpHasPriorityTest, HasPriority) {
-  const bool is_set = (flags_ & QuicHttpFrameFlag::QUIC_HTTP_PRIORITY) ==
-                      QuicHttpFrameFlag::QUIC_HTTP_PRIORITY;
-  QuicString flags_string;
-  QuicHttpFrameHeader v(0, type_, flags_, 0);
-  switch (type_) {
-    case QuicHttpFrameType::HEADERS:
-      EXPECT_EQ(is_set, v.HasPriority()) << v;
-      flags_string = v.FlagsToString();
-      if (is_set) {
-        EXPECT_THAT(QuicTextUtils::Split(flags_string, '|'),
-                    Contains("QUIC_HTTP_PRIORITY"));
-      } else {
-        EXPECT_THAT(flags_string, Not(HasSubstr("QUIC_HTTP_PRIORITY")));
-      }
-      v.RetainFlags(QuicHttpFrameFlag::QUIC_HTTP_PRIORITY);
-      EXPECT_EQ(is_set, v.HasPriority()) << v;
-      {
-        std::stringstream s;
-        s << v;
-        EXPECT_EQ(v.ToString(), s.str());
-        if (is_set) {
-          EXPECT_THAT(s.str(), HasSubstr("flags=QUIC_HTTP_PRIORITY,"));
-        } else {
-          EXPECT_THAT(s.str(), HasSubstr("flags=,"));
-        }
-      }
-      break;
-    default:
-      EXPECT_DEBUG_DEATH(v.HasPriority(), "HEADERS") << v;
-  }
-}
-
-TEST(QuicHttpPriorityFieldsTest, Constructor) {
-  QuicTestRandom random;
-  uint32_t stream_dependency = random.Rand32() & QuicHttpStreamIdMask();
-  uint32_t weight = 1 + random.Rand8();
-  bool is_exclusive = random.OneIn(2);
-
-  QuicHttpPriorityFields v(stream_dependency, weight, is_exclusive);
-
-  EXPECT_EQ(stream_dependency, v.stream_dependency);
-  EXPECT_EQ(weight, v.weight);
-  EXPECT_EQ(is_exclusive, v.is_exclusive);
-
-  // The high-bit must not be set on the stream id.
-  EXPECT_DEBUG_DEATH(QuicHttpPriorityFields(stream_dependency | 0x80000000,
-                                            weight, is_exclusive),
-                     "31-bit");
-
-  // The weight must be in the range 1-256.
-  EXPECT_DEBUG_DEATH(QuicHttpPriorityFields(stream_dependency, 0, is_exclusive),
-                     "too small");
-  EXPECT_DEBUG_DEATH(
-      QuicHttpPriorityFields(stream_dependency, weight + 256, is_exclusive),
-      "too large");
-}
-#endif  // GTEST_HAS_DEATH_TEST && !defined(NDEBUG)
-
-TEST(QuicHttpRstStreamFieldsTest, IsSupported) {
-  QuicHttpRstStreamFields v{QuicHttpErrorCode::HTTP2_NO_ERROR};
-  EXPECT_TRUE(v.IsSupportedErrorCode()) << v;
-
-  QuicHttpRstStreamFields u{static_cast<QuicHttpErrorCode>(~0)};
-  EXPECT_FALSE(u.IsSupportedErrorCode()) << v;
-}
-
-TEST(QuicHttpSettingFieldsTest, Misc) {
-  QuicTestRandom random;
-  QuicHttpSettingsParameter parameter =
-      static_cast<QuicHttpSettingsParameter>(random.Rand16());
-  uint32_t value = random.Rand32();
-
-  QuicHttpSettingFields v(parameter, value);
-
-  EXPECT_EQ(v, v);
-  EXPECT_EQ(parameter, v.parameter);
-  EXPECT_EQ(value, v.value);
-
-  if (static_cast<int>(parameter) < 7) {
-    EXPECT_TRUE(v.IsSupportedParameter()) << v;
-  } else {
-    EXPECT_FALSE(v.IsSupportedParameter()) << v;
-  }
-
-  QuicHttpSettingFields u(parameter, ~value);
-  EXPECT_NE(v, u);
-  EXPECT_EQ(v.parameter, u.parameter);
-  EXPECT_NE(v.value, u.value);
-
-  QuicHttpSettingFields w(IncrementEnum(parameter), value);
-  EXPECT_NE(v, w);
-  EXPECT_NE(v.parameter, w.parameter);
-  EXPECT_EQ(v.value, w.value);
-
-  QuicHttpSettingFields x(QuicHttpSettingsParameter::MAX_FRAME_SIZE, 123);
-  std::stringstream s;
-  s << x;
-  EXPECT_EQ("parameter=MAX_FRAME_SIZE, value=123", s.str());
-}
-
-TEST(QuicHttpPushPromiseTest, Misc) {
-  QuicTestRandom random;
-  uint32_t promised_stream_id = random.Rand32() & QuicHttpStreamIdMask();
-
-  QuicHttpPushPromiseFields v{promised_stream_id};
-  EXPECT_EQ(promised_stream_id, v.promised_stream_id);
-  EXPECT_EQ(v, v);
-
-  std::stringstream s;
-  s << v;
-  EXPECT_EQ(QuicStrCat("promised_stream_id=", promised_stream_id), s.str());
-
-  // High-bit is reserved, but not used, so we can set it.
-  promised_stream_id |= 0x80000000;
-  QuicHttpPushPromiseFields w{promised_stream_id};
-  EXPECT_EQ(w, w);
-  EXPECT_NE(v, w);
-
-  v.promised_stream_id = promised_stream_id;
-  EXPECT_EQ(v, w);
-}
-
-TEST(QuicHttpPingFieldsTest, Misc) {
-  QuicHttpPingFields v{{'8', ' ', 'b', 'y', 't', 'e', 's', '\0'}};
-  std::stringstream s;
-  s << v;
-  EXPECT_EQ("opaque_bytes=0x3820627974657300", s.str());
-}
-
-// Started becoming very flaky on all platforms after around crrev.com/519987.
-TEST(QuicHttpGoAwayFieldsTest, DISABLED_Misc) {
-  QuicTestRandom random;
-  uint32_t last_stream_id = random.Rand32() & QuicHttpStreamIdMask();
-  QuicHttpErrorCode error_code =
-      static_cast<QuicHttpErrorCode>(random.Rand32());
-
-  QuicHttpGoAwayFields v(last_stream_id, error_code);
-  EXPECT_EQ(v, v);
-  EXPECT_EQ(last_stream_id, v.last_stream_id);
-  EXPECT_EQ(error_code, v.error_code);
-
-  if (static_cast<int>(error_code) < 14) {
-    EXPECT_TRUE(v.IsSupportedErrorCode()) << v;
-  } else {
-    EXPECT_FALSE(v.IsSupportedErrorCode()) << v;
-  }
-
-  QuicHttpGoAwayFields u(~last_stream_id, error_code);
-  EXPECT_NE(v, u);
-  EXPECT_NE(v.last_stream_id, u.last_stream_id);
-  EXPECT_EQ(v.error_code, u.error_code);
-}
-
-TEST(QuicHttpWindowUpdateTest, Misc) {
-  QuicTestRandom random;
-  uint32_t window_size_increment = random.Rand32() & QuicHttpUint31Mask();
-
-  QuicHttpWindowUpdateFields v{window_size_increment};
-  EXPECT_EQ(window_size_increment, v.window_size_increment);
-  EXPECT_EQ(v, v);
-
-  std::stringstream s;
-  s << v;
-  EXPECT_EQ(QuicStrCat("window_size_increment=", window_size_increment),
-            s.str());
-
-  // High-bit is reserved, but not used, so we can set it.
-  window_size_increment |= 0x80000000;
-  QuicHttpWindowUpdateFields w{window_size_increment};
-  EXPECT_EQ(w, w);
-  EXPECT_NE(v, w);
-
-  v.window_size_increment = window_size_increment;
-  EXPECT_EQ(v, w);
-}
-
-TEST(QuicHttpAltSvcTest, Misc) {
-  QuicTestRandom random;
-  uint16_t origin_length = random.Rand16();
-
-  QuicHttpAltSvcFields v{origin_length};
-  EXPECT_EQ(origin_length, v.origin_length);
-  EXPECT_EQ(v, v);
-
-  std::stringstream s;
-  s << v;
-  EXPECT_EQ(QuicStrCat("origin_length=", origin_length), s.str());
-
-  QuicHttpAltSvcFields w{++origin_length};
-  EXPECT_EQ(w, w);
-  EXPECT_NE(v, w);
-
-  v.origin_length = w.origin_length;
-  EXPECT_EQ(v, w);
-}
-
-}  // namespace
-}  // namespace test
-}  // namespace quic
diff --git a/net/third_party/quic/http/quic_http_structures_test_util.cc b/net/third_party/quic/http/quic_http_structures_test_util.cc
deleted file mode 100644
index 7bf443d0..0000000
--- a/net/third_party/quic/http/quic_http_structures_test_util.cc
+++ /dev/null
@@ -1,109 +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 "net/third_party/quic/http/quic_http_structures_test_util.h"
-
-#include <cstdint>
-
-#include "net/third_party/quic/http/quic_http_constants.h"
-#include "net/third_party/quic/http/quic_http_constants_test_util.h"
-#include "net/third_party/quic/http/quic_http_structures.h"
-#include "net/third_party/quic/platform/api/quic_test_random.h"
-
-namespace quic {
-namespace test {
-
-void Randomize(QuicHttpFrameHeader* p, QuicTestRandomBase* rng) {
-  p->payload_length = rng->Rand32() & 0xffffff;
-  p->type = static_cast<QuicHttpFrameType>(rng->Rand8());
-  p->flags = static_cast<QuicHttpFrameFlag>(rng->Rand8());
-  p->stream_id = rng->Rand32() & QuicHttpStreamIdMask();
-}
-void Randomize(QuicHttpPriorityFields* p, QuicTestRandomBase* rng) {
-  p->stream_dependency = rng->Rand32() & QuicHttpStreamIdMask();
-  p->weight = rng->Rand8() + 1;
-  p->is_exclusive = rng->OneIn(2);
-}
-void Randomize(QuicHttpRstStreamFields* p, QuicTestRandomBase* rng) {
-  p->error_code = static_cast<QuicHttpErrorCode>(rng->Rand32());
-}
-void Randomize(QuicHttpSettingFields* p, QuicTestRandomBase* rng) {
-  p->parameter = static_cast<QuicHttpSettingsParameter>(rng->Rand16());
-  p->value = rng->Rand32();
-}
-void Randomize(QuicHttpPushPromiseFields* p, QuicTestRandomBase* rng) {
-  p->promised_stream_id = rng->Rand32() & QuicHttpStreamIdMask();
-}
-void Randomize(QuicHttpPingFields* p, QuicTestRandomBase* rng) {
-  for (int ndx = 0; ndx < 8; ++ndx) {
-    p->opaque_bytes[ndx] = rng->Rand8();
-  }
-}
-void Randomize(QuicHttpGoAwayFields* p, QuicTestRandomBase* rng) {
-  p->last_stream_id = rng->Rand32() & QuicHttpStreamIdMask();
-  p->error_code = static_cast<QuicHttpErrorCode>(rng->Rand32());
-}
-void Randomize(QuicHttpWindowUpdateFields* p, QuicTestRandomBase* rng) {
-  p->window_size_increment = rng->Rand32() & 0x7fffffff;
-}
-void Randomize(QuicHttpAltSvcFields* p, QuicTestRandomBase* rng) {
-  p->origin_length = rng->Rand16();
-}
-
-void ScrubFlagsOfHeader(QuicHttpFrameHeader* header) {
-  uint8_t invalid_mask = InvalidFlagMaskForFrameType(header->type);
-  uint8_t keep_mask = ~invalid_mask;
-  header->RetainFlags(keep_mask);
-}
-
-bool FrameIsPadded(const QuicHttpFrameHeader& header) {
-  switch (header.type) {
-    case QuicHttpFrameType::DATA:
-    case QuicHttpFrameType::HEADERS:
-    case QuicHttpFrameType::PUSH_PROMISE:
-      return header.IsPadded();
-    default:
-      return false;
-  }
-}
-
-bool FrameHasPriority(const QuicHttpFrameHeader& header) {
-  switch (header.type) {
-    case QuicHttpFrameType::HEADERS:
-      return header.HasPriority();
-    case QuicHttpFrameType::QUIC_HTTP_PRIORITY:
-      return true;
-    default:
-      return false;
-  }
-}
-
-bool FrameCanHavePayload(const QuicHttpFrameHeader& header) {
-  switch (header.type) {
-    case QuicHttpFrameType::DATA:
-    case QuicHttpFrameType::HEADERS:
-    case QuicHttpFrameType::PUSH_PROMISE:
-    case QuicHttpFrameType::CONTINUATION:
-    case QuicHttpFrameType::PING:
-    case QuicHttpFrameType::GOAWAY:
-    case QuicHttpFrameType::ALTSVC:
-      return true;
-    default:
-      return false;
-  }
-}
-
-bool FrameCanHaveHpackPayload(const QuicHttpFrameHeader& header) {
-  switch (header.type) {
-    case QuicHttpFrameType::HEADERS:
-    case QuicHttpFrameType::PUSH_PROMISE:
-    case QuicHttpFrameType::CONTINUATION:
-      return true;
-    default:
-      return false;
-  }
-}
-
-}  // namespace test
-}  // namespace quic
diff --git a/net/third_party/quic/http/quic_http_structures_test_util.h b/net/third_party/quic/http/quic_http_structures_test_util.h
deleted file mode 100644
index 7ad1bdd..0000000
--- a/net/third_party/quic/http/quic_http_structures_test_util.h
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_THIRD_PARTY_QUIC_HTTP_QUIC_HTTP_STRUCTURES_TEST_UTIL_H_
-#define NET_THIRD_PARTY_QUIC_HTTP_QUIC_HTTP_STRUCTURES_TEST_UTIL_H_
-
-#include "net/third_party/quic/http/quic_http_structures.h"
-#include "net/third_party/quic/http/tools/quic_http_frame_builder.h"
-#include "net/third_party/quic/platform/api/quic_string.h"
-#include "net/third_party/quic/platform/api/quic_test_random.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace quic {
-namespace test {
-
-template <class S>
-QuicString SerializeStructure(const S& s) {
-  QuicHttpFrameBuilder fb;
-  fb.Append(s);
-  EXPECT_EQ(S::EncodedSize(), fb.size());
-  return fb.buffer();
-}
-
-// Randomize the members of out, in a manner that yields encodeable contents
-// (e.g. a "uint24" field has only the low 24 bits set).
-void Randomize(QuicHttpFrameHeader* p, QuicTestRandomBase* rng);
-void Randomize(QuicHttpPriorityFields* p, QuicTestRandomBase* rng);
-void Randomize(QuicHttpRstStreamFields* p, QuicTestRandomBase* rng);
-void Randomize(QuicHttpSettingFields* p, QuicTestRandomBase* rng);
-void Randomize(QuicHttpPushPromiseFields* p, QuicTestRandomBase* rng);
-void Randomize(QuicHttpPingFields* p, QuicTestRandomBase* rng);
-void Randomize(QuicHttpGoAwayFields* p, QuicTestRandomBase* rng);
-void Randomize(QuicHttpWindowUpdateFields* p, QuicTestRandomBase* rng);
-void Randomize(QuicHttpAltSvcFields* p, QuicTestRandomBase* rng);
-
-// Clear bits of header->flags that are known to be invalid for the
-// type. For unknown frame types, no change is made.
-void ScrubFlagsOfHeader(QuicHttpFrameHeader* header);
-
-// Is the frame with this header padded? Only true for known/supported frame
-// types.
-bool FrameIsPadded(const QuicHttpFrameHeader& header);
-
-// Does the frame with this header have QuicHttpPriorityFields?
-bool FrameHasPriority(const QuicHttpFrameHeader& header);
-
-// Does the frame with this header have a variable length payload (including
-// empty) payload (e.g. DATA or HEADERS)? Really a test of the frame type.
-bool FrameCanHavePayload(const QuicHttpFrameHeader& header);
-
-// Does the frame with this header have a variable length HPQUIC_HTTP_ACK
-// payload (including empty) payload (e.g. HEADERS)? Really a test of the frame
-// type.
-bool FrameCanHaveHpackPayload(const QuicHttpFrameHeader& header);
-
-}  // namespace test
-}  // namespace quic
-
-#endif  // NET_THIRD_PARTY_QUIC_HTTP_QUIC_HTTP_STRUCTURES_TEST_UTIL_H_
diff --git a/net/third_party/quic/http/test_tools/quic_http_frame_parts.cc b/net/third_party/quic/http/test_tools/quic_http_frame_parts.cc
deleted file mode 100644
index 267015c..0000000
--- a/net/third_party/quic/http/test_tools/quic_http_frame_parts.cc
+++ /dev/null
@@ -1,544 +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 "net/third_party/quic/http/test_tools/quic_http_frame_parts.h"
-
-#include <type_traits>
-
-#include "net/base/escape.h"
-#include "net/third_party/http2/tools/failure.h"
-#include "net/third_party/quic/http/quic_http_structures_test_util.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using ::testing::AssertionFailure;
-using ::testing::AssertionResult;
-using ::testing::AssertionSuccess;
-using ::testing::ContainerEq;
-
-namespace quic {
-namespace test {
-namespace {
-
-static_assert(
-    std::is_base_of<QuicHttpFrameDecoderListener, QuicHttpFrameParts>::value &&
-        !std::is_abstract<QuicHttpFrameParts>::value,
-    "QuicHttpFrameParts needs to implement all of the methods of "
-    "QuicHttpFrameDecoderListener");
-
-// Compare two optional variables of the same type.
-// TODO(jamessynge): Maybe create a ::testing::Matcher for this.
-template <class T>
-AssertionResult VerifyOptionalEq(const T& opt_a, const T& opt_b) {
-  if (opt_a) {
-    if (opt_b) {
-      VERIFY_EQ(opt_a.value(), opt_b.value());
-    } else {
-      return AssertionFailure()
-             << "opt_b is not set; opt_a.value()=" << opt_a.value();
-    }
-  } else if (opt_b) {
-    return AssertionFailure()
-           << "opt_a is not set; opt_b.value()=" << opt_b.value();
-  }
-  return AssertionSuccess();
-}
-
-}  // namespace
-
-QuicHttpFrameParts::QuicHttpFrameParts(const QuicHttpFrameHeader& header)
-    : frame_header(header) {
-  VLOG(1) << "QuicHttpFrameParts, header: " << frame_header;
-}
-
-QuicHttpFrameParts::QuicHttpFrameParts(const QuicHttpFrameHeader& header,
-                                       QuicStringPiece payload)
-    : QuicHttpFrameParts(header) {
-  VLOG(1) << "QuicHttpFrameParts with payload.size() = " << payload.size();
-  this->payload.append(payload.data(), payload.size());
-  opt_payload_length = payload.size();
-}
-QuicHttpFrameParts::QuicHttpFrameParts(const QuicHttpFrameHeader& header,
-                                       QuicStringPiece payload,
-                                       size_t total_pad_length)
-    : QuicHttpFrameParts(header, payload) {
-  VLOG(1) << "QuicHttpFrameParts with total_pad_length=" << total_pad_length;
-  SetTotalPadLength(total_pad_length);
-}
-
-QuicHttpFrameParts::QuicHttpFrameParts(const QuicHttpFrameParts& header) =
-    default;
-
-QuicHttpFrameParts::~QuicHttpFrameParts() {}
-
-AssertionResult QuicHttpFrameParts::VerifyEquals(
-    const QuicHttpFrameParts& that) const {
-#define COMMON_MESSAGE "\n  this: " << *this << "\n  that: " << that
-
-  VERIFY_EQ(frame_header, that.frame_header) << COMMON_MESSAGE;
-  VERIFY_EQ(payload, that.payload) << COMMON_MESSAGE;
-  VERIFY_EQ(padding, that.padding) << COMMON_MESSAGE;
-  VERIFY_EQ(altsvc_origin, that.altsvc_origin) << COMMON_MESSAGE;
-  VERIFY_EQ(altsvc_value, that.altsvc_value) << COMMON_MESSAGE;
-  VERIFY_THAT(settings, ContainerEq(that.settings)) << COMMON_MESSAGE;
-
-#define VERIFY_OPTIONAL_FIELD(field_name) \
-  VERIFY_SUCCESS(VerifyOptionalEq(field_name, that.field_name))
-
-  VERIFY_OPTIONAL_FIELD(opt_altsvc_origin_length) << COMMON_MESSAGE;
-  VERIFY_OPTIONAL_FIELD(opt_altsvc_value_length) << COMMON_MESSAGE;
-  VERIFY_OPTIONAL_FIELD(opt_goaway) << COMMON_MESSAGE;
-  VERIFY_OPTIONAL_FIELD(opt_missing_length) << COMMON_MESSAGE;
-  VERIFY_OPTIONAL_FIELD(opt_pad_length) << COMMON_MESSAGE;
-  VERIFY_OPTIONAL_FIELD(opt_ping) << COMMON_MESSAGE;
-  VERIFY_OPTIONAL_FIELD(opt_priority) << COMMON_MESSAGE;
-  VERIFY_OPTIONAL_FIELD(opt_push_promise) << COMMON_MESSAGE;
-  VERIFY_OPTIONAL_FIELD(opt_rst_stream_error_code) << COMMON_MESSAGE;
-  VERIFY_OPTIONAL_FIELD(opt_window_update_increment) << COMMON_MESSAGE;
-
-#undef VERIFY_OPTIONAL_FIELD
-
-  return AssertionSuccess();
-}
-
-void QuicHttpFrameParts::SetTotalPadLength(size_t total_pad_length) {
-  opt_pad_length.reset();
-  padding.clear();
-  if (total_pad_length > 0) {
-    ASSERT_LE(total_pad_length, 256u);
-    ASSERT_TRUE(frame_header.IsPadded());
-    opt_pad_length = total_pad_length - 1;
-    char zero = 0;
-    padding.append(opt_pad_length.value(), zero);
-  }
-
-  if (opt_pad_length) {
-    VLOG(1) << "SetTotalPadLength: pad_length=" << opt_pad_length.value();
-  } else {
-    VLOG(1) << "SetTotalPadLength: has no pad length";
-  }
-}
-
-void QuicHttpFrameParts::SetAltSvcExpected(QuicStringPiece origin,
-                                           QuicStringPiece value) {
-  altsvc_origin.append(origin.data(), origin.size());
-  altsvc_value.append(value.data(), value.size());
-  opt_altsvc_origin_length = origin.size();
-  opt_altsvc_value_length = value.size();
-}
-
-bool QuicHttpFrameParts::OnFrameHeader(const QuicHttpFrameHeader& header) {
-  ADD_FAILURE() << "OnFrameHeader: " << *this;
-  return true;
-}
-
-void QuicHttpFrameParts::OnDataStart(const QuicHttpFrameHeader& header) {
-  VLOG(1) << "OnDataStart: " << header;
-  ASSERT_TRUE(StartFrameOfType(header, QuicHttpFrameType::DATA)) << *this;
-  opt_payload_length = header.payload_length;
-}
-
-void QuicHttpFrameParts::OnDataPayload(const char* data, size_t len) {
-  VLOG(1) << "OnDataPayload: len=" << len << "; frame_header: " << frame_header;
-  ASSERT_TRUE(InFrameOfType(QuicHttpFrameType::DATA)) << *this;
-  ASSERT_TRUE(
-      AppendString(QuicStringPiece(data, len), &payload, &opt_payload_length));
-}
-
-void QuicHttpFrameParts::OnDataEnd() {
-  VLOG(1) << "OnDataEnd; frame_header: " << frame_header;
-  ASSERT_TRUE(EndFrameOfType(QuicHttpFrameType::DATA)) << *this;
-}
-
-void QuicHttpFrameParts::OnHeadersStart(const QuicHttpFrameHeader& header) {
-  VLOG(1) << "OnHeadersStart: " << header;
-  ASSERT_TRUE(StartFrameOfType(header, QuicHttpFrameType::HEADERS)) << *this;
-  opt_payload_length = header.payload_length;
-}
-
-void QuicHttpFrameParts::OnHeadersPriority(
-    const QuicHttpPriorityFields& priority) {
-  VLOG(1) << "OnHeadersPriority: priority: " << priority
-          << "; frame_header: " << frame_header;
-  ASSERT_TRUE(InFrameOfType(QuicHttpFrameType::HEADERS)) << *this;
-  ASSERT_FALSE(opt_priority);
-  opt_priority = priority;
-  ASSERT_TRUE(opt_payload_length);
-  opt_payload_length =
-      opt_payload_length.value() - QuicHttpPriorityFields::EncodedSize();
-}
-
-void QuicHttpFrameParts::OnHpackFragment(const char* data, size_t len) {
-  VLOG(1) << "OnHpackFragment: len=" << len
-          << "; frame_header: " << frame_header;
-  ASSERT_TRUE(got_start_callback);
-  ASSERT_FALSE(got_end_callback);
-  ASSERT_TRUE(FrameCanHaveHpackPayload(frame_header)) << *this;
-  ASSERT_TRUE(
-      AppendString(QuicStringPiece(data, len), &payload, &opt_payload_length));
-}
-
-void QuicHttpFrameParts::OnHeadersEnd() {
-  VLOG(1) << "OnHeadersEnd; frame_header: " << frame_header;
-  ASSERT_TRUE(EndFrameOfType(QuicHttpFrameType::HEADERS)) << *this;
-}
-
-void QuicHttpFrameParts::OnPriorityFrame(
-    const QuicHttpFrameHeader& header,
-    const QuicHttpPriorityFields& priority) {
-  VLOG(1) << "OnPriorityFrame: " << header << "; priority: " << priority;
-  ASSERT_TRUE(StartFrameOfType(header, QuicHttpFrameType::QUIC_HTTP_PRIORITY))
-      << *this;
-  ASSERT_FALSE(opt_priority);
-  opt_priority = priority;
-  ASSERT_TRUE(EndFrameOfType(QuicHttpFrameType::QUIC_HTTP_PRIORITY)) << *this;
-}
-
-void QuicHttpFrameParts::OnContinuationStart(
-    const QuicHttpFrameHeader& header) {
-  VLOG(1) << "OnContinuationStart: " << header;
-  ASSERT_TRUE(StartFrameOfType(header, QuicHttpFrameType::CONTINUATION))
-      << *this;
-  opt_payload_length = header.payload_length;
-}
-
-void QuicHttpFrameParts::OnContinuationEnd() {
-  VLOG(1) << "OnContinuationEnd; frame_header: " << frame_header;
-  ASSERT_TRUE(EndFrameOfType(QuicHttpFrameType::CONTINUATION)) << *this;
-}
-
-void QuicHttpFrameParts::OnPadLength(size_t trailing_length) {
-  VLOG(1) << "OnPadLength: trailing_length=" << trailing_length;
-  ASSERT_TRUE(InPaddedFrame()) << *this;
-  ASSERT_FALSE(opt_pad_length);
-  ASSERT_TRUE(opt_payload_length);
-  size_t total_padding_length = trailing_length + 1;
-  ASSERT_GE(opt_payload_length.value(), total_padding_length);
-  opt_payload_length = opt_payload_length.value() - total_padding_length;
-  opt_pad_length = trailing_length;
-}
-
-void QuicHttpFrameParts::OnPadding(const char* pad, size_t skipped_length) {
-  VLOG(1) << "OnPadding: skipped_length=" << skipped_length;
-  ASSERT_TRUE(InPaddedFrame()) << *this;
-  ASSERT_TRUE(opt_pad_length);
-  ASSERT_TRUE(AppendString(QuicStringPiece(pad, skipped_length), &padding,
-                           &opt_pad_length));
-}
-
-void QuicHttpFrameParts::OnRstStream(const QuicHttpFrameHeader& header,
-                                     QuicHttpErrorCode error_code) {
-  VLOG(1) << "OnRstStream: " << header << "; code=" << error_code;
-  ASSERT_TRUE(StartFrameOfType(header, QuicHttpFrameType::RST_STREAM)) << *this;
-  ASSERT_FALSE(opt_rst_stream_error_code);
-  opt_rst_stream_error_code = error_code;
-  ASSERT_TRUE(EndFrameOfType(QuicHttpFrameType::RST_STREAM)) << *this;
-}
-
-void QuicHttpFrameParts::OnSettingsStart(const QuicHttpFrameHeader& header) {
-  VLOG(1) << "OnSettingsStart: " << header;
-  ASSERT_TRUE(StartFrameOfType(header, QuicHttpFrameType::SETTINGS)) << *this;
-  ASSERT_EQ(0u, settings.size());
-  ASSERT_FALSE(header.IsAck()) << header;
-}
-
-void QuicHttpFrameParts::OnSetting(
-    const QuicHttpSettingFields& setting_fields) {
-  VLOG(1) << "OnSetting: " << setting_fields;
-  ASSERT_TRUE(InFrameOfType(QuicHttpFrameType::SETTINGS)) << *this;
-  settings.push_back(setting_fields);
-}
-
-void QuicHttpFrameParts::OnSettingsEnd() {
-  VLOG(1) << "OnSettingsEnd; frame_header: " << frame_header;
-  ASSERT_TRUE(EndFrameOfType(QuicHttpFrameType::SETTINGS)) << *this;
-}
-
-void QuicHttpFrameParts::OnSettingsAck(const QuicHttpFrameHeader& header) {
-  VLOG(1) << "OnSettingsAck: " << header;
-  ASSERT_TRUE(StartFrameOfType(header, QuicHttpFrameType::SETTINGS)) << *this;
-  ASSERT_EQ(0u, settings.size());
-  ASSERT_TRUE(header.IsAck());
-  ASSERT_TRUE(EndFrameOfType(QuicHttpFrameType::SETTINGS)) << *this;
-}
-
-void QuicHttpFrameParts::OnPushPromiseStart(
-    const QuicHttpFrameHeader& header,
-    const QuicHttpPushPromiseFields& promise,
-    size_t total_padding_length) {
-  VLOG(1) << "OnPushPromiseStart header: " << header << "; promise: " << promise
-          << "; total_padding_length: " << total_padding_length;
-  ASSERT_TRUE(StartFrameOfType(header, QuicHttpFrameType::PUSH_PROMISE))
-      << *this;
-  ASSERT_GE(header.payload_length, QuicHttpPushPromiseFields::EncodedSize());
-  opt_payload_length =
-      header.payload_length - QuicHttpPushPromiseFields::EncodedSize();
-  ASSERT_FALSE(opt_push_promise);
-  opt_push_promise = promise;
-  if (total_padding_length > 0) {
-    ASSERT_GE(opt_payload_length.value(), total_padding_length);
-    OnPadLength(total_padding_length - 1);
-  } else {
-    ASSERT_FALSE(header.IsPadded());
-  }
-}
-
-void QuicHttpFrameParts::OnPushPromiseEnd() {
-  VLOG(1) << "OnPushPromiseEnd; frame_header: " << frame_header;
-  ASSERT_TRUE(EndFrameOfType(QuicHttpFrameType::PUSH_PROMISE)) << *this;
-}
-
-void QuicHttpFrameParts::OnPing(const QuicHttpFrameHeader& header,
-                                const QuicHttpPingFields& ping) {
-  VLOG(1) << "OnPing header: " << header << "   ping: " << ping;
-  ASSERT_TRUE(StartFrameOfType(header, QuicHttpFrameType::PING)) << *this;
-  ASSERT_FALSE(header.IsAck());
-  ASSERT_FALSE(opt_ping);
-  opt_ping = ping;
-  ASSERT_TRUE(EndFrameOfType(QuicHttpFrameType::PING)) << *this;
-}
-
-void QuicHttpFrameParts::OnPingAck(const QuicHttpFrameHeader& header,
-                                   const QuicHttpPingFields& ping) {
-  VLOG(1) << "OnPingAck header: " << header << "   ping: " << ping;
-  ASSERT_TRUE(StartFrameOfType(header, QuicHttpFrameType::PING)) << *this;
-  ASSERT_TRUE(header.IsAck());
-  ASSERT_FALSE(opt_ping);
-  opt_ping = ping;
-  ASSERT_TRUE(EndFrameOfType(QuicHttpFrameType::PING)) << *this;
-}
-
-void QuicHttpFrameParts::OnGoAwayStart(const QuicHttpFrameHeader& header,
-                                       const QuicHttpGoAwayFields& goaway) {
-  VLOG(1) << "OnGoAwayStart: " << goaway;
-  ASSERT_TRUE(StartFrameOfType(header, QuicHttpFrameType::GOAWAY)) << *this;
-  ASSERT_FALSE(opt_goaway);
-  opt_goaway = goaway;
-  opt_payload_length =
-      header.payload_length - QuicHttpGoAwayFields::EncodedSize();
-}
-
-void QuicHttpFrameParts::OnGoAwayOpaqueData(const char* data, size_t len) {
-  VLOG(1) << "OnGoAwayOpaqueData: len=" << len;
-  ASSERT_TRUE(InFrameOfType(QuicHttpFrameType::GOAWAY)) << *this;
-  ASSERT_TRUE(
-      AppendString(QuicStringPiece(data, len), &payload, &opt_payload_length));
-}
-
-void QuicHttpFrameParts::OnGoAwayEnd() {
-  VLOG(1) << "OnGoAwayEnd; frame_header: " << frame_header;
-  ASSERT_TRUE(EndFrameOfType(QuicHttpFrameType::GOAWAY)) << *this;
-}
-
-void QuicHttpFrameParts::OnWindowUpdate(const QuicHttpFrameHeader& header,
-                                        uint32_t increment) {
-  VLOG(1) << "OnWindowUpdate header: " << header
-          << "     increment=" << increment;
-  ASSERT_TRUE(StartFrameOfType(header, QuicHttpFrameType::WINDOW_UPDATE))
-      << *this;
-  ASSERT_FALSE(opt_window_update_increment);
-  opt_window_update_increment = increment;
-  ASSERT_TRUE(EndFrameOfType(QuicHttpFrameType::WINDOW_UPDATE)) << *this;
-}
-
-void QuicHttpFrameParts::OnAltSvcStart(const QuicHttpFrameHeader& header,
-                                       size_t origin_length,
-                                       size_t value_length) {
-  VLOG(1) << "OnAltSvcStart: " << header
-          << "    origin_length: " << origin_length
-          << "    value_length: " << value_length;
-  ASSERT_TRUE(StartFrameOfType(header, QuicHttpFrameType::ALTSVC)) << *this;
-  ASSERT_FALSE(opt_altsvc_origin_length);
-  opt_altsvc_origin_length = origin_length;
-  ASSERT_FALSE(opt_altsvc_value_length);
-  opt_altsvc_value_length = value_length;
-}
-
-void QuicHttpFrameParts::OnAltSvcOriginData(const char* data, size_t len) {
-  VLOG(1) << "OnAltSvcOriginData: len=" << len;
-  ASSERT_TRUE(InFrameOfType(QuicHttpFrameType::ALTSVC)) << *this;
-  ASSERT_TRUE(AppendString(QuicStringPiece(data, len), &altsvc_origin,
-                           &opt_altsvc_origin_length));
-}
-
-void QuicHttpFrameParts::OnAltSvcValueData(const char* data, size_t len) {
-  VLOG(1) << "OnAltSvcValueData: len=" << len;
-  ASSERT_TRUE(InFrameOfType(QuicHttpFrameType::ALTSVC)) << *this;
-  ASSERT_TRUE(AppendString(QuicStringPiece(data, len), &altsvc_value,
-                           &opt_altsvc_value_length));
-}
-
-void QuicHttpFrameParts::OnAltSvcEnd() {
-  VLOG(1) << "OnAltSvcEnd; frame_header: " << frame_header;
-  ASSERT_TRUE(EndFrameOfType(QuicHttpFrameType::ALTSVC)) << *this;
-}
-
-void QuicHttpFrameParts::OnUnknownStart(const QuicHttpFrameHeader& header) {
-  VLOG(1) << "OnUnknownStart: " << header;
-  ASSERT_FALSE(IsSupportedQuicHttpFrameType(header.type)) << header;
-  ASSERT_FALSE(got_start_callback);
-  ASSERT_EQ(frame_header, header);
-  got_start_callback = true;
-  opt_payload_length = header.payload_length;
-}
-
-void QuicHttpFrameParts::OnUnknownPayload(const char* data, size_t len) {
-  VLOG(1) << "OnUnknownPayload: len=" << len;
-  ASSERT_FALSE(IsSupportedQuicHttpFrameType(frame_header.type)) << *this;
-  ASSERT_TRUE(got_start_callback);
-  ASSERT_FALSE(got_end_callback);
-  ASSERT_TRUE(
-      AppendString(QuicStringPiece(data, len), &payload, &opt_payload_length));
-}
-
-void QuicHttpFrameParts::OnUnknownEnd() {
-  VLOG(1) << "OnUnknownEnd; frame_header: " << frame_header;
-  ASSERT_FALSE(IsSupportedQuicHttpFrameType(frame_header.type)) << *this;
-  ASSERT_TRUE(got_start_callback);
-  ASSERT_FALSE(got_end_callback);
-  got_end_callback = true;
-}
-
-void QuicHttpFrameParts::OnPaddingTooLong(const QuicHttpFrameHeader& header,
-                                          size_t missing_length) {
-  VLOG(1) << "OnPaddingTooLong: " << header
-          << "; missing_length: " << missing_length;
-  ASSERT_EQ(frame_header, header);
-  ASSERT_FALSE(got_end_callback);
-  ASSERT_TRUE(FrameIsPadded(header));
-  ASSERT_FALSE(opt_pad_length);
-  ASSERT_FALSE(opt_missing_length);
-  opt_missing_length = missing_length;
-  got_start_callback = true;
-  got_end_callback = true;
-}
-
-void QuicHttpFrameParts::OnFrameSizeError(const QuicHttpFrameHeader& header) {
-  VLOG(1) << "OnFrameSizeError: " << header;
-  ASSERT_EQ(frame_header, header);
-  ASSERT_FALSE(got_end_callback);
-  ASSERT_FALSE(has_frame_size_error);
-  has_frame_size_error = true;
-  got_end_callback = true;
-}
-
-void QuicHttpFrameParts::OutputTo(std::ostream& out) const {
-  out << "QuicHttpFrameParts{\n  frame_header: " << frame_header << "\n";
-  if (!payload.empty()) {
-    out << "  payload=\"" << net::EscapeQueryParamValue(payload, false)
-        << "\"\n";
-  }
-  if (!padding.empty()) {
-    out << "  padding=\"" << net::EscapeQueryParamValue(padding, false)
-        << "\"\n";
-  }
-  if (!altsvc_origin.empty()) {
-    out << "  altsvc_origin=\""
-        << net::EscapeQueryParamValue(altsvc_origin, false) << "\"\n";
-  }
-  if (!altsvc_value.empty()) {
-    out << "  altsvc_value=\""
-        << net::EscapeQueryParamValue(altsvc_value, false) << "\"\n";
-  }
-  if (opt_priority) {
-    out << "  priority=" << opt_priority.value() << "\n";
-  }
-  if (opt_rst_stream_error_code) {
-    out << "  rst_stream=" << opt_rst_stream_error_code.value() << "\n";
-  }
-  if (opt_push_promise) {
-    out << "  push_promise=" << opt_push_promise.value() << "\n";
-  }
-  if (opt_ping) {
-    out << "  ping=" << opt_ping.value() << "\n";
-  }
-  if (opt_goaway) {
-    out << "  goaway=" << opt_goaway.value() << "\n";
-  }
-  if (opt_window_update_increment) {
-    out << "  window_update=" << opt_window_update_increment.value() << "\n";
-  }
-  if (opt_payload_length) {
-    out << "  payload_length=" << opt_payload_length.value() << "\n";
-  }
-  if (opt_pad_length) {
-    out << "  pad_length=" << opt_pad_length.value() << "\n";
-  }
-  if (opt_missing_length) {
-    out << "  missing_length=" << opt_missing_length.value() << "\n";
-  }
-  if (opt_altsvc_origin_length) {
-    out << "  origin_length=" << opt_altsvc_origin_length.value() << "\n";
-  }
-  if (opt_altsvc_value_length) {
-    out << "  value_length=" << opt_altsvc_value_length.value() << "\n";
-  }
-  if (has_frame_size_error) {
-    out << "  has_frame_size_error\n";
-  }
-  if (got_start_callback) {
-    out << "  got_start_callback\n";
-  }
-  if (got_end_callback) {
-    out << "  got_end_callback\n";
-  }
-  for (size_t ndx = 0; ndx < settings.size(); ++ndx) {
-    out << "  setting[" << ndx << "]=" << settings[ndx];
-  }
-  out << "}";
-}
-
-AssertionResult QuicHttpFrameParts::StartFrameOfType(
-    const QuicHttpFrameHeader& header,
-    QuicHttpFrameType expected_frame_type) {
-  VERIFY_EQ(header.type, expected_frame_type);
-  VERIFY_FALSE(got_start_callback);
-  VERIFY_FALSE(got_end_callback);
-  VERIFY_EQ(frame_header, header);
-  got_start_callback = true;
-  return AssertionSuccess();
-}
-
-AssertionResult QuicHttpFrameParts::InFrameOfType(
-    QuicHttpFrameType expected_frame_type) {
-  VERIFY_TRUE(got_start_callback);
-  VERIFY_FALSE(got_end_callback);
-  VERIFY_EQ(frame_header.type, expected_frame_type);
-  return AssertionSuccess();
-}
-
-AssertionResult QuicHttpFrameParts::EndFrameOfType(
-    QuicHttpFrameType expected_frame_type) {
-  VERIFY_SUCCESS(InFrameOfType(expected_frame_type));
-  got_end_callback = true;
-  return AssertionSuccess();
-}
-
-AssertionResult QuicHttpFrameParts::InPaddedFrame() {
-  VERIFY_TRUE(got_start_callback);
-  VERIFY_FALSE(got_end_callback);
-  VERIFY_TRUE(FrameIsPadded(frame_header));
-  return AssertionSuccess();
-}
-
-AssertionResult QuicHttpFrameParts::AppendString(
-    QuicStringPiece source,
-    QuicString* target,
-    QuicOptional<size_t>* opt_length) {
-  target->append(source.data(), source.size());
-  if (opt_length != nullptr) {
-    VERIFY_TRUE(*opt_length) << "Length is not set yet\n" << *this;
-    VERIFY_LE(target->size(), opt_length->value())
-        << "String too large; source.size() = " << source.size() << "\n"
-        << *this;
-  }
-  return ::testing::AssertionSuccess();
-}
-
-std::ostream& operator<<(std::ostream& out, const QuicHttpFrameParts& v) {
-  v.OutputTo(out);
-  return out;
-}
-
-}  // namespace test
-}  // namespace quic
diff --git a/net/third_party/quic/http/test_tools/quic_http_frame_parts.h b/net/third_party/quic/http/test_tools/quic_http_frame_parts.h
deleted file mode 100644
index 4cd2ff5..0000000
--- a/net/third_party/quic/http/test_tools/quic_http_frame_parts.h
+++ /dev/null
@@ -1,183 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_THIRD_PARTY_QUIC_HTTP_TEST_TOOLS_QUIC_HTTP_FRAME_PARTS_H_
-#define NET_THIRD_PARTY_QUIC_HTTP_TEST_TOOLS_QUIC_HTTP_FRAME_PARTS_H_
-
-// QuicHttpFrameParts implements QuicHttpFrameDecoderListener, recording the
-// callbacks during the decoding of a single frame. It is also used for
-// comparing the info that a test expects to be recorded during the decoding of
-// a frame with the actual recorded value (i.e. by providing a comparator).
-
-// TODO(jamessynge): Convert QuicHttpFrameParts to a class, hide the members,
-// add getters/setters.
-
-#include <stddef.h>
-
-#include <cstdint>
-#include <vector>
-
-#include "base/logging.h"
-#include "net/third_party/quic/http/decoder/quic_http_frame_decoder_listener.h"
-#include "net/third_party/quic/http/quic_http_constants.h"
-#include "net/third_party/quic/http/quic_http_structures.h"
-#include "net/third_party/quic/platform/api/quic_optional.h"
-#include "net/third_party/quic/platform/api/quic_string.h"
-#include "net/third_party/quic/platform/api/quic_string_piece.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace quic {
-namespace test {
-
-// Forward declarations.
-struct QuicHttpFrameParts;
-std::ostream& operator<<(std::ostream& out, const QuicHttpFrameParts& v);
-
-struct QuicHttpFrameParts : public QuicHttpFrameDecoderListener {
-  // The first callback for every type of frame includes the frame header; this
-  // is the only constructor used during decoding of a frame.
-  explicit QuicHttpFrameParts(const QuicHttpFrameHeader& header);
-
-  // For use in tests where the expected frame has a variable size payload.
-  QuicHttpFrameParts(const QuicHttpFrameHeader& header,
-                     QuicStringPiece payload);
-
-  // For use in tests where the expected frame has a variable size payload
-  // and may be padded.
-  QuicHttpFrameParts(const QuicHttpFrameHeader& header,
-                     QuicStringPiece payload,
-                     size_t total_pad_length);
-
-  // Copy constructor.
-  QuicHttpFrameParts(const QuicHttpFrameParts& header);
-
-  ~QuicHttpFrameParts() override;
-
-  // Returns AssertionSuccess() if they're equal, else AssertionFailure()
-  // with info about the difference.
-  ::testing::AssertionResult VerifyEquals(const QuicHttpFrameParts& that) const;
-
-  // Format this QuicHttpFrameParts object.
-  void OutputTo(std::ostream& out) const;
-
-  // Set the total padding length (0 to 256).
-  void SetTotalPadLength(size_t total_pad_length);
-
-  // Set the origin and value expected in an ALTSVC frame.
-  void SetAltSvcExpected(QuicStringPiece origin, QuicStringPiece value);
-
-  // QuicHttpFrameDecoderListener methods:
-  bool OnFrameHeader(const QuicHttpFrameHeader& header) override;
-  void OnDataStart(const QuicHttpFrameHeader& header) override;
-  void OnDataPayload(const char* data, size_t len) override;
-  void OnDataEnd() override;
-  void OnHeadersStart(const QuicHttpFrameHeader& header) override;
-  void OnHeadersPriority(const QuicHttpPriorityFields& priority) override;
-  void OnHpackFragment(const char* data, size_t len) override;
-  void OnHeadersEnd() override;
-  void OnPriorityFrame(const QuicHttpFrameHeader& header,
-                       const QuicHttpPriorityFields& priority) override;
-  void OnContinuationStart(const QuicHttpFrameHeader& header) override;
-  void OnContinuationEnd() override;
-  void OnPadLength(size_t trailing_length) override;
-  void OnPadding(const char* pad, size_t skipped_length) override;
-  void OnRstStream(const QuicHttpFrameHeader& header,
-                   QuicHttpErrorCode error_code) override;
-  void OnSettingsStart(const QuicHttpFrameHeader& header) override;
-  void OnSetting(const QuicHttpSettingFields& setting_fields) override;
-  void OnSettingsEnd() override;
-  void OnSettingsAck(const QuicHttpFrameHeader& header) override;
-  void OnPushPromiseStart(const QuicHttpFrameHeader& header,
-                          const QuicHttpPushPromiseFields& promise,
-                          size_t total_padding_length) override;
-  void OnPushPromiseEnd() override;
-  void OnPing(const QuicHttpFrameHeader& header,
-              const QuicHttpPingFields& ping) override;
-  void OnPingAck(const QuicHttpFrameHeader& header,
-                 const QuicHttpPingFields& ping) override;
-  void OnGoAwayStart(const QuicHttpFrameHeader& header,
-                     const QuicHttpGoAwayFields& goaway) override;
-  void OnGoAwayOpaqueData(const char* data, size_t len) override;
-  void OnGoAwayEnd() override;
-  void OnWindowUpdate(const QuicHttpFrameHeader& header,
-                      uint32_t increment) override;
-  void OnAltSvcStart(const QuicHttpFrameHeader& header,
-                     size_t origin_length,
-                     size_t value_length) override;
-  void OnAltSvcOriginData(const char* data, size_t len) override;
-  void OnAltSvcValueData(const char* data, size_t len) override;
-  void OnAltSvcEnd() override;
-  void OnUnknownStart(const QuicHttpFrameHeader& header) override;
-  void OnUnknownPayload(const char* data, size_t len) override;
-  void OnUnknownEnd() override;
-  void OnPaddingTooLong(const QuicHttpFrameHeader& header,
-                        size_t missing_length) override;
-  void OnFrameSizeError(const QuicHttpFrameHeader& header) override;
-
-  // The fields are public for access by tests.
-
-  const QuicHttpFrameHeader frame_header;
-
-  QuicString payload;
-  QuicString padding;
-  QuicString altsvc_origin;
-  QuicString altsvc_value;
-
-  QuicOptional<QuicHttpPriorityFields> opt_priority;
-  QuicOptional<QuicHttpErrorCode> opt_rst_stream_error_code;
-  QuicOptional<QuicHttpPushPromiseFields> opt_push_promise;
-  QuicOptional<QuicHttpPingFields> opt_ping;
-  QuicOptional<QuicHttpGoAwayFields> opt_goaway;
-
-  QuicOptional<size_t> opt_pad_length;
-  QuicOptional<size_t> opt_payload_length;
-  QuicOptional<size_t> opt_missing_length;
-  QuicOptional<size_t> opt_altsvc_origin_length;
-  QuicOptional<size_t> opt_altsvc_value_length;
-
-  QuicOptional<size_t> opt_window_update_increment;
-
-  bool has_frame_size_error = false;
-
-  std::vector<QuicHttpSettingFields> settings;
-
-  // These booleans are not checked by CompareCollectedFrames.
-  bool got_start_callback = false;
-  bool got_end_callback = false;
-
- private:
-  // ASSERT during an On* method that we're handling a frame of type
-  // expected_frame_type, and have not already received other On* methods
-  // (i.e. got_start_callback is false).
-  ::testing::AssertionResult StartFrameOfType(
-      const QuicHttpFrameHeader& header,
-      QuicHttpFrameType expected_frame_type);
-
-  // ASSERT that StartFrameOfType has already been called with
-  // expected_frame_type (i.e. got_start_callback has been called), and that
-  // EndFrameOfType has not yet been called (i.e. got_end_callback is false).
-  ::testing::AssertionResult InFrameOfType(
-      QuicHttpFrameType expected_frame_type);
-
-  // ASSERT that we're InFrameOfType, and then sets got_end_callback=true.
-  ::testing::AssertionResult EndFrameOfType(
-      QuicHttpFrameType expected_frame_type);
-
-  // ASSERT that we're in the middle of processing a frame that is padded.
-  ::testing::AssertionResult InPaddedFrame();
-
-  // Append source to target. If opt_length is not nullptr, then verifies that
-  // the optional has a value (i.e. that the necessary On*Start method has been
-  // called), and that target is not longer than opt_length->value().
-  ::testing::AssertionResult AppendString(QuicStringPiece source,
-                                          QuicString* target,
-                                          QuicOptional<size_t>* opt_length);
-};
-
-std::ostream& operator<<(std::ostream& out, const QuicHttpFrameParts& v);
-
-}  // namespace test
-}  // namespace quic
-
-#endif  // NET_THIRD_PARTY_QUIC_HTTP_TEST_TOOLS_QUIC_HTTP_FRAME_PARTS_H_
diff --git a/net/third_party/quic/http/test_tools/quic_http_frame_parts_collector.cc b/net/third_party/quic/http/test_tools/quic_http_frame_parts_collector.cc
deleted file mode 100644
index 8b7ce0d..0000000
--- a/net/third_party/quic/http/test_tools/quic_http_frame_parts_collector.cc
+++ /dev/null
@@ -1,115 +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 "net/third_party/quic/http/test_tools/quic_http_frame_parts_collector.h"
-
-#include <utility>
-
-#include "base/logging.h"
-#include "net/third_party/quic/http/quic_http_structures_test_util.h"
-#include "net/third_party/quic/platform/api/quic_ptr_util.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace quic {
-namespace test {
-
-QuicHttpFramePartsCollector::QuicHttpFramePartsCollector() {}
-QuicHttpFramePartsCollector::~QuicHttpFramePartsCollector() {}
-
-void QuicHttpFramePartsCollector::Reset() {
-  current_frame_.reset();
-  collected_frames_.clear();
-  expected_header_set_ = false;
-}
-
-const QuicHttpFrameParts* QuicHttpFramePartsCollector::frame(size_t n) const {
-  if (n < size()) {
-    return collected_frames_.at(n).get();
-  }
-  CHECK(n == size());
-  return current_frame();
-}
-
-void QuicHttpFramePartsCollector::ExpectFrameHeader(
-    const QuicHttpFrameHeader& header) {
-  EXPECT_FALSE(IsInProgress());
-  EXPECT_FALSE(expected_header_set_)
-      << "expected_header_: " << expected_header_;
-  expected_header_ = header;
-  expected_header_set_ = true;
-  // OnFrameHeader is called before the flags are scrubbed, but the other
-  // methods are called after, so scrub the invalid flags from expected_header_.
-  ScrubFlagsOfHeader(&expected_header_);
-}
-
-void QuicHttpFramePartsCollector::TestExpectedHeader(
-    const QuicHttpFrameHeader& header) {
-  if (expected_header_set_) {
-    EXPECT_EQ(header, expected_header_);
-    expected_header_set_ = false;
-  }
-}
-
-QuicHttpFrameDecoderListener* QuicHttpFramePartsCollector::StartFrame(
-    const QuicHttpFrameHeader& header) {
-  TestExpectedHeader(header);
-  EXPECT_FALSE(IsInProgress());
-  if (current_frame_ == nullptr) {
-    current_frame_ = QuicMakeUnique<QuicHttpFrameParts>(header);
-  }
-  return current_frame();
-}
-
-QuicHttpFrameDecoderListener* QuicHttpFramePartsCollector::StartAndEndFrame(
-    const QuicHttpFrameHeader& header) {
-  TestExpectedHeader(header);
-  EXPECT_FALSE(IsInProgress());
-  if (current_frame_ == nullptr) {
-    current_frame_ = QuicMakeUnique<QuicHttpFrameParts>(header);
-  }
-  QuicHttpFrameDecoderListener* result = current_frame();
-  collected_frames_.push_back(std::move(current_frame_));
-  return result;
-}
-
-QuicHttpFrameDecoderListener* QuicHttpFramePartsCollector::CurrentFrame() {
-  EXPECT_TRUE(IsInProgress());
-  if (current_frame_ == nullptr) {
-    return &failing_listener_;
-  }
-  return current_frame();
-}
-
-QuicHttpFrameDecoderListener* QuicHttpFramePartsCollector::EndFrame() {
-  EXPECT_TRUE(IsInProgress());
-  if (current_frame_ == nullptr) {
-    return &failing_listener_;
-  }
-  QuicHttpFrameDecoderListener* result = current_frame();
-  collected_frames_.push_back(std::move(current_frame_));
-  return result;
-}
-
-QuicHttpFrameDecoderListener* QuicHttpFramePartsCollector::FrameError(
-    const QuicHttpFrameHeader& header) {
-  TestExpectedHeader(header);
-  if (current_frame_ == nullptr) {
-    // The decoder may detect an error before making any calls to the listener
-    // regarding the frame, in which case current_frame_==nullptr and we need
-    // to create a QuicHttpFrameParts instance.
-    current_frame_ = QuicMakeUnique<QuicHttpFrameParts>(header);
-  } else {
-    // Similarly, the decoder may have made calls to the listener regarding the
-    // frame before detecting the error; for example, the DATA payload decoder
-    // calls OnDataStart before it can detect padding errors, hence before it
-    // can call OnPaddingTooLong.
-    EXPECT_EQ(header, current_frame_->frame_header);
-  }
-  QuicHttpFrameDecoderListener* result = current_frame();
-  collected_frames_.push_back(std::move(current_frame_));
-  return result;
-}
-
-}  // namespace test
-}  // namespace quic
diff --git a/net/third_party/quic/http/test_tools/quic_http_frame_parts_collector.h b/net/third_party/quic/http/test_tools/quic_http_frame_parts_collector.h
deleted file mode 100644
index 959af2f..0000000
--- a/net/third_party/quic/http/test_tools/quic_http_frame_parts_collector.h
+++ /dev/null
@@ -1,114 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_THIRD_PARTY_QUIC_HTTP_TEST_TOOLS_QUIC_HTTP_FRAME_PARTS_COLLECTOR_H_
-#define NET_THIRD_PARTY_QUIC_HTTP_TEST_TOOLS_QUIC_HTTP_FRAME_PARTS_COLLECTOR_H_
-
-// QuicHttpFramePartsCollector is a base class for QuicHttpFrameDecoderListener
-// implementations that create one QuicHttpFrameParts instance for each decoded
-// frame.
-
-#include <stddef.h>
-#include <memory>
-#include <vector>
-
-#include "net/third_party/quic/http/decoder/quic_http_frame_decoder_listener.h"
-#include "net/third_party/quic/http/decoder/quic_http_frame_decoder_listener_test_util.h"
-#include "net/third_party/quic/http/quic_http_structures.h"
-#include "net/third_party/quic/http/test_tools/quic_http_frame_parts.h"
-
-namespace quic {
-namespace test {
-
-class QuicHttpFramePartsCollector : public FailingQuicHttpFrameDecoderListener {
- public:
-  QuicHttpFramePartsCollector();
-  ~QuicHttpFramePartsCollector() override;
-
-  // Toss out the collected data.
-  void Reset();
-
-  // Returns true if has started recording the info for a frame and has not yet
-  // finished doing so.
-  bool IsInProgress() const { return current_frame_ != nullptr; }
-
-  // Returns the QuicHttpFrameParts instance into which we're currently
-  // recording callback info if IsInProgress, else nullptr.
-  const QuicHttpFrameParts* current_frame() const {
-    return current_frame_.get();
-  }
-
-  // Returns the number of completely collected QuicHttpFrameParts instances.
-  size_t size() const { return collected_frames_.size(); }
-
-  // Returns the n'th frame, where 0 is the oldest of the collected frames,
-  // and n==size() is the frame currently being collected, if there is one.
-  // Returns nullptr if the requested index is not valid.
-  const QuicHttpFrameParts* frame(size_t n) const;
-
- protected:
-  // In support of OnFrameHeader, set the header that we expect to be used in
-  // the next call.
-  // TODO(jamessynge): Remove ExpectFrameHeader et al. once done with supporting
-  // spdy::SpdyFramer's exact states.
-  void ExpectFrameHeader(const QuicHttpFrameHeader& header);
-
-  // For use in implementing On*Start methods of QuicHttpFrameDecoderListener,
-  // returns a QuicHttpFrameParts instance, which will be newly created if
-  // IsInProgress==false (which the caller should ensure), else will be the
-  // current_frame(); never returns nullptr.
-  // If called when IsInProgress==true, a test failure will be recorded.
-  QuicHttpFrameDecoderListener* StartFrame(const QuicHttpFrameHeader& header);
-
-  // For use in implementing On* callbacks, such as OnPingAck, that are the only
-  // call expected for the frame being decoded; not for On*Start methods.
-  // Returns a QuicHttpFrameParts instance, which will be newly created if
-  // IsInProgress==false (which the caller should ensure), else will be the
-  // current_frame(); never returns nullptr.
-  // If called when IsInProgress==true, a test failure will be recorded.
-  QuicHttpFrameDecoderListener* StartAndEndFrame(
-      const QuicHttpFrameHeader& header);
-
-  // If IsInProgress==true, returns the QuicHttpFrameParts into which the
-  // current frame is being recorded; else records a test failure and returns
-  // failing_listener_, which will record a test failure when any of its
-  // On* methods is called.
-  QuicHttpFrameDecoderListener* CurrentFrame();
-
-  // For use in implementing On*End methods, pushes the current frame onto
-  // the vector of completed frames, and returns a pointer to it for recording
-  // the info in the final call. If IsInProgress==false, records a test failure
-  // and returns failing_listener_, which will record a test failure when any
-  // of its On* methods is called.
-  QuicHttpFrameDecoderListener* EndFrame();
-
-  // For use in implementing OnPaddingTooLong and OnFrameSizeError, is
-  // equivalent to EndFrame() if IsInProgress==true, else equivalent to
-  // StartAndEndFrame().
-  QuicHttpFrameDecoderListener* FrameError(const QuicHttpFrameHeader& header);
-
- private:
-  // Returns the mutable QuicHttpFrameParts instance into which we're currently
-  // recording callback info if IsInProgress, else nullptr.
-  QuicHttpFrameParts* current_frame() { return current_frame_.get(); }
-
-  // If expected header is set, verify that it matches the header param.
-  // TODO(jamessynge): Remove TestExpectedHeader et al. once done
-  // with supporting spdy::SpdyFramer's exact states.
-  void TestExpectedHeader(const QuicHttpFrameHeader& header);
-
-  std::unique_ptr<QuicHttpFrameParts> current_frame_;
-  std::vector<std::unique_ptr<QuicHttpFrameParts>> collected_frames_;
-  FailingQuicHttpFrameDecoderListener failing_listener_;
-
-  // TODO(jamessynge): Remove expected_header_ et al. once done with supporting
-  // spdy::SpdyFramer's exact states.
-  QuicHttpFrameHeader expected_header_;
-  bool expected_header_set_ = false;
-};
-
-}  // namespace test
-}  // namespace quic
-
-#endif  // NET_THIRD_PARTY_QUIC_HTTP_TEST_TOOLS_QUIC_HTTP_FRAME_PARTS_COLLECTOR_H_
diff --git a/net/third_party/quic/http/test_tools/quic_http_frame_parts_collector_listener.cc b/net/third_party/quic/http/test_tools/quic_http_frame_parts_collector_listener.cc
deleted file mode 100644
index d3c4e8d..0000000
--- a/net/third_party/quic/http/test_tools/quic_http_frame_parts_collector_listener.cc
+++ /dev/null
@@ -1,236 +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 "net/third_party/quic/http/test_tools/quic_http_frame_parts_collector_listener.h"
-
-#include "base/logging.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace quic {
-namespace test {
-
-bool QuicHttpFramePartsCollectorListener::OnFrameHeader(
-    const QuicHttpFrameHeader& header) {
-  VLOG(1) << "OnFrameHeader: " << header;
-  ExpectFrameHeader(header);
-  return true;
-}
-
-void QuicHttpFramePartsCollectorListener::OnDataStart(
-    const QuicHttpFrameHeader& header) {
-  VLOG(1) << "OnDataStart: " << header;
-  StartFrame(header)->OnDataStart(header);
-}
-
-void QuicHttpFramePartsCollectorListener::OnDataPayload(const char* data,
-                                                        size_t len) {
-  VLOG(1) << "OnDataPayload: len=" << len;
-  CurrentFrame()->OnDataPayload(data, len);
-}
-
-void QuicHttpFramePartsCollectorListener::OnDataEnd() {
-  VLOG(1) << "OnDataEnd";
-  EndFrame()->OnDataEnd();
-}
-
-void QuicHttpFramePartsCollectorListener::OnHeadersStart(
-    const QuicHttpFrameHeader& header) {
-  VLOG(1) << "OnHeadersStart: " << header;
-  StartFrame(header)->OnHeadersStart(header);
-}
-
-void QuicHttpFramePartsCollectorListener::OnHeadersPriority(
-    const QuicHttpPriorityFields& priority) {
-  VLOG(1) << "OnHeadersPriority: " << priority;
-  CurrentFrame()->OnHeadersPriority(priority);
-}
-
-void QuicHttpFramePartsCollectorListener::OnHpackFragment(const char* data,
-                                                          size_t len) {
-  VLOG(1) << "OnHpackFragment: len=" << len;
-  CurrentFrame()->OnHpackFragment(data, len);
-}
-
-void QuicHttpFramePartsCollectorListener::OnHeadersEnd() {
-  VLOG(1) << "OnHeadersEnd";
-  EndFrame()->OnHeadersEnd();
-}
-
-void QuicHttpFramePartsCollectorListener::OnPriorityFrame(
-    const QuicHttpFrameHeader& header,
-    const QuicHttpPriorityFields& priority_fields) {
-  VLOG(1) << "OnPriority: " << header << "; " << priority_fields;
-  StartAndEndFrame(header)->OnPriorityFrame(header, priority_fields);
-}
-
-void QuicHttpFramePartsCollectorListener::OnContinuationStart(
-    const QuicHttpFrameHeader& header) {
-  VLOG(1) << "OnContinuationStart: " << header;
-  StartFrame(header)->OnContinuationStart(header);
-}
-
-void QuicHttpFramePartsCollectorListener::OnContinuationEnd() {
-  VLOG(1) << "OnContinuationEnd";
-  EndFrame()->OnContinuationEnd();
-}
-
-void QuicHttpFramePartsCollectorListener::OnPadLength(size_t pad_length) {
-  VLOG(1) << "OnPadLength: " << pad_length;
-  CurrentFrame()->OnPadLength(pad_length);
-}
-
-void QuicHttpFramePartsCollectorListener::OnPadding(const char* padding,
-                                                    size_t skipped_length) {
-  VLOG(1) << "OnPadding: " << skipped_length;
-  CurrentFrame()->OnPadding(padding, skipped_length);
-}
-
-void QuicHttpFramePartsCollectorListener::OnRstStream(
-    const QuicHttpFrameHeader& header,
-    QuicHttpErrorCode error_code) {
-  VLOG(1) << "OnRstStream: " << header << "; error_code=" << error_code;
-  StartAndEndFrame(header)->OnRstStream(header, error_code);
-}
-
-void QuicHttpFramePartsCollectorListener::OnSettingsStart(
-    const QuicHttpFrameHeader& header) {
-  VLOG(1) << "OnSettingsStart: " << header;
-  EXPECT_EQ(QuicHttpFrameType::SETTINGS, header.type) << header;
-  EXPECT_EQ(QuicHttpFrameFlag(), header.flags) << header;
-  StartFrame(header)->OnSettingsStart(header);
-}
-
-void QuicHttpFramePartsCollectorListener::OnSetting(
-    const QuicHttpSettingFields& setting_fields) {
-  VLOG(1) << "QuicHttpSettingFields: setting_fields=" << setting_fields;
-  CurrentFrame()->OnSetting(setting_fields);
-}
-
-void QuicHttpFramePartsCollectorListener::OnSettingsEnd() {
-  VLOG(1) << "OnSettingsEnd";
-  EndFrame()->OnSettingsEnd();
-}
-
-void QuicHttpFramePartsCollectorListener::OnSettingsAck(
-    const QuicHttpFrameHeader& header) {
-  VLOG(1) << "OnSettingsAck: " << header;
-  StartAndEndFrame(header)->OnSettingsAck(header);
-}
-
-void QuicHttpFramePartsCollectorListener::OnPushPromiseStart(
-    const QuicHttpFrameHeader& header,
-    const QuicHttpPushPromiseFields& promise,
-    size_t total_padding_length) {
-  VLOG(1) << "OnPushPromiseStart header: " << header << "  promise: " << promise
-          << "  total_padding_length: " << total_padding_length;
-  EXPECT_EQ(QuicHttpFrameType::PUSH_PROMISE, header.type);
-  StartFrame(header)->OnPushPromiseStart(header, promise, total_padding_length);
-}
-
-void QuicHttpFramePartsCollectorListener::OnPushPromiseEnd() {
-  VLOG(1) << "OnPushPromiseEnd";
-  EndFrame()->OnPushPromiseEnd();
-}
-
-void QuicHttpFramePartsCollectorListener::OnPing(
-    const QuicHttpFrameHeader& header,
-    const QuicHttpPingFields& ping) {
-  VLOG(1) << "OnPing: " << header << "; " << ping;
-  StartAndEndFrame(header)->OnPing(header, ping);
-}
-
-void QuicHttpFramePartsCollectorListener::OnPingAck(
-    const QuicHttpFrameHeader& header,
-    const QuicHttpPingFields& ping) {
-  VLOG(1) << "OnPingAck: " << header << "; " << ping;
-  StartAndEndFrame(header)->OnPingAck(header, ping);
-}
-
-void QuicHttpFramePartsCollectorListener::OnGoAwayStart(
-    const QuicHttpFrameHeader& header,
-    const QuicHttpGoAwayFields& goaway) {
-  VLOG(1) << "OnGoAwayStart header: " << header << "; goaway: " << goaway;
-  StartFrame(header)->OnGoAwayStart(header, goaway);
-}
-
-void QuicHttpFramePartsCollectorListener::OnGoAwayOpaqueData(const char* data,
-                                                             size_t len) {
-  VLOG(1) << "OnGoAwayOpaqueData: len=" << len;
-  CurrentFrame()->OnGoAwayOpaqueData(data, len);
-}
-
-void QuicHttpFramePartsCollectorListener::OnGoAwayEnd() {
-  VLOG(1) << "OnGoAwayEnd";
-  EndFrame()->OnGoAwayEnd();
-}
-
-void QuicHttpFramePartsCollectorListener::OnWindowUpdate(
-    const QuicHttpFrameHeader& header,
-    uint32_t window_size_increment) {
-  VLOG(1) << "OnWindowUpdate: " << header
-          << "; window_size_increment=" << window_size_increment;
-  EXPECT_EQ(QuicHttpFrameType::WINDOW_UPDATE, header.type);
-  StartAndEndFrame(header)->OnWindowUpdate(header, window_size_increment);
-}
-
-void QuicHttpFramePartsCollectorListener::OnAltSvcStart(
-    const QuicHttpFrameHeader& header,
-    size_t origin_length,
-    size_t value_length) {
-  VLOG(1) << "OnAltSvcStart header: " << header
-          << "; origin_length=" << origin_length
-          << "; value_length=" << value_length;
-  StartFrame(header)->OnAltSvcStart(header, origin_length, value_length);
-}
-
-void QuicHttpFramePartsCollectorListener::OnAltSvcOriginData(const char* data,
-                                                             size_t len) {
-  VLOG(1) << "OnAltSvcOriginData: len=" << len;
-  CurrentFrame()->OnAltSvcOriginData(data, len);
-}
-
-void QuicHttpFramePartsCollectorListener::OnAltSvcValueData(const char* data,
-                                                            size_t len) {
-  VLOG(1) << "OnAltSvcValueData: len=" << len;
-  CurrentFrame()->OnAltSvcValueData(data, len);
-}
-
-void QuicHttpFramePartsCollectorListener::OnAltSvcEnd() {
-  VLOG(1) << "OnAltSvcEnd";
-  EndFrame()->OnAltSvcEnd();
-}
-
-void QuicHttpFramePartsCollectorListener::OnUnknownStart(
-    const QuicHttpFrameHeader& header) {
-  VLOG(1) << "OnUnknownStart: " << header;
-  StartFrame(header)->OnUnknownStart(header);
-}
-
-void QuicHttpFramePartsCollectorListener::OnUnknownPayload(const char* data,
-                                                           size_t len) {
-  VLOG(1) << "OnUnknownPayload: len=" << len;
-  CurrentFrame()->OnUnknownPayload(data, len);
-}
-
-void QuicHttpFramePartsCollectorListener::OnUnknownEnd() {
-  VLOG(1) << "OnUnknownEnd";
-  EndFrame()->OnUnknownEnd();
-}
-
-void QuicHttpFramePartsCollectorListener::OnPaddingTooLong(
-    const QuicHttpFrameHeader& header,
-    size_t missing_length) {
-  VLOG(1) << "OnPaddingTooLong: " << header
-          << "    missing_length: " << missing_length;
-  EndFrame()->OnPaddingTooLong(header, missing_length);
-}
-
-void QuicHttpFramePartsCollectorListener::OnFrameSizeError(
-    const QuicHttpFrameHeader& header) {
-  VLOG(1) << "OnFrameSizeError: " << header;
-  FrameError(header)->OnFrameSizeError(header);
-}
-
-}  // namespace test
-}  // namespace quic
diff --git a/net/third_party/quic/http/test_tools/quic_http_frame_parts_collector_listener.h b/net/third_party/quic/http/test_tools/quic_http_frame_parts_collector_listener.h
deleted file mode 100644
index 2ca7363..0000000
--- a/net/third_party/quic/http/test_tools/quic_http_frame_parts_collector_listener.h
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_THIRD_PARTY_QUIC_HTTP_TEST_TOOLS_QUIC_HTTP_FRAME_PARTS_COLLECTOR_LISTENER_H_
-#define NET_THIRD_PARTY_QUIC_HTTP_TEST_TOOLS_QUIC_HTTP_FRAME_PARTS_COLLECTOR_LISTENER_H_
-
-// QuicHttpFramePartsCollectorListener extends QuicHttpFramePartsCollector with
-// an implementation of every method of QuicHttpFrameDecoderListener; it is
-// essentially the union of all the Listener classes in the tests of the
-// payload decoders (i.e. in ./payload_decoders/*_test.cc files), with the
-// addition of the OnFrameHeader method.
-// QuicHttpFramePartsCollectorListener supports tests of QuicHttpFrameDecoder.
-
-#include <stddef.h>
-
-#include <cstdint>
-
-#include "net/third_party/quic/http/quic_http_constants.h"
-#include "net/third_party/quic/http/quic_http_structures.h"
-#include "net/third_party/quic/http/test_tools/quic_http_frame_parts_collector.h"
-
-namespace quic {
-namespace test {
-
-class QuicHttpFramePartsCollectorListener : public QuicHttpFramePartsCollector {
- public:
-  QuicHttpFramePartsCollectorListener() {}
-  ~QuicHttpFramePartsCollectorListener() override {}
-
-  // TODO(jamessynge): Remove OnFrameHeader once done with supporting
-  // spdy::SpdyFramer's exact states.
-  bool OnFrameHeader(const QuicHttpFrameHeader& header) override;
-  void OnDataStart(const QuicHttpFrameHeader& header) override;
-  void OnDataPayload(const char* data, size_t len) override;
-  void OnDataEnd() override;
-  void OnHeadersStart(const QuicHttpFrameHeader& header) override;
-  void OnHeadersPriority(const QuicHttpPriorityFields& priority) override;
-  void OnHpackFragment(const char* data, size_t len) override;
-  void OnHeadersEnd() override;
-  void OnPriorityFrame(const QuicHttpFrameHeader& header,
-                       const QuicHttpPriorityFields& priority_fields) override;
-  void OnContinuationStart(const QuicHttpFrameHeader& header) override;
-  void OnContinuationEnd() override;
-  void OnPadLength(size_t pad_length) override;
-  void OnPadding(const char* padding, size_t skipped_length) override;
-  void OnRstStream(const QuicHttpFrameHeader& header,
-                   QuicHttpErrorCode error_code) override;
-  void OnSettingsStart(const QuicHttpFrameHeader& header) override;
-  void OnSetting(const QuicHttpSettingFields& setting_fields) override;
-  void OnSettingsEnd() override;
-  void OnSettingsAck(const QuicHttpFrameHeader& header) override;
-  void OnPushPromiseStart(const QuicHttpFrameHeader& header,
-                          const QuicHttpPushPromiseFields& promise,
-                          size_t total_padding_length) override;
-  void OnPushPromiseEnd() override;
-  void OnPing(const QuicHttpFrameHeader& header,
-              const QuicHttpPingFields& ping) override;
-  void OnPingAck(const QuicHttpFrameHeader& header,
-                 const QuicHttpPingFields& ping) override;
-  void OnGoAwayStart(const QuicHttpFrameHeader& header,
-                     const QuicHttpGoAwayFields& goaway) override;
-  void OnGoAwayOpaqueData(const char* data, size_t len) override;
-  void OnGoAwayEnd() override;
-  void OnWindowUpdate(const QuicHttpFrameHeader& header,
-                      uint32_t window_size_increment) override;
-  void OnAltSvcStart(const QuicHttpFrameHeader& header,
-                     size_t origin_length,
-                     size_t value_length) override;
-  void OnAltSvcOriginData(const char* data, size_t len) override;
-  void OnAltSvcValueData(const char* data, size_t len) override;
-  void OnAltSvcEnd() override;
-  void OnUnknownStart(const QuicHttpFrameHeader& header) override;
-  void OnUnknownPayload(const char* data, size_t len) override;
-  void OnUnknownEnd() override;
-  void OnPaddingTooLong(const QuicHttpFrameHeader& header,
-                        size_t missing_length) override;
-  void OnFrameSizeError(const QuicHttpFrameHeader& header) override;
-};
-
-}  // namespace test
-}  // namespace quic
-
-#endif  // NET_THIRD_PARTY_QUIC_HTTP_TEST_TOOLS_QUIC_HTTP_FRAME_PARTS_COLLECTOR_LISTENER_H_
diff --git a/net/third_party/quic/http/tools/quic_http_frame_builder.cc b/net/third_party/quic/http/tools/quic_http_frame_builder.cc
deleted file mode 100644
index ac9f6d59..0000000
--- a/net/third_party/quic/http/tools/quic_http_frame_builder.cc
+++ /dev/null
@@ -1,181 +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 "net/third_party/quic/http/tools/quic_http_frame_builder.h"
-
-#ifdef WIN32
-#include <winsock2.h>  // for htonl() functions
-#else
-#include <arpa/inet.h>   // IWYU pragma: keep  // because of Chrome
-#include <netinet/in.h>  // for htonl, htons
-#endif
-
-#include "net/third_party/quic/platform/api/quic_string_utils.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace quic {
-namespace test {
-
-QuicHttpFrameBuilder::QuicHttpFrameBuilder(QuicHttpFrameType type,
-                                           uint8_t flags,
-                                           uint32_t stream_id) {
-  AppendUInt24(0);  // Frame payload length, unknown so far.
-  Append(type);
-  AppendUInt8(flags);
-  AppendUInt31(stream_id);
-}
-
-QuicHttpFrameBuilder::QuicHttpFrameBuilder(const QuicHttpFrameHeader& v) {
-  Append(v);
-}
-
-void QuicHttpFrameBuilder::Append(QuicStringPiece s) {
-  QuicStrAppend(&buffer_, s);
-}
-
-void QuicHttpFrameBuilder::AppendBytes(const void* data, uint32_t num_bytes) {
-  Append(QuicStringPiece(static_cast<const char*>(data), num_bytes));
-}
-
-void QuicHttpFrameBuilder::AppendZeroes(size_t num_zero_bytes) {
-  char zero = 0;
-  buffer_.append(num_zero_bytes, zero);
-}
-
-void QuicHttpFrameBuilder::AppendUInt8(uint8_t value) {
-  AppendBytes(&value, 1);
-}
-
-void QuicHttpFrameBuilder::AppendUInt16(uint16_t value) {
-  value = htons(value);
-  AppendBytes(&value, 2);
-}
-
-void QuicHttpFrameBuilder::AppendUInt24(uint32_t value) {
-  // Doesn't make sense to try to append a larger value, as that doesn't
-  // simulate something an encoder could do (i.e. the other 8 bits simply aren't
-  // there to be occupied).
-  EXPECT_EQ(value, value & 0xffffff);
-  value = htonl(value);
-  AppendBytes(reinterpret_cast<char*>(&value) + 1, 3);
-}
-
-void QuicHttpFrameBuilder::AppendUInt31(uint32_t value) {
-  // If you want to test the high-bit being set, call AppendUInt32 instead.
-  uint32_t tmp = value & QuicHttpStreamIdMask();
-  EXPECT_EQ(value, value & QuicHttpStreamIdMask())
-      << "High-bit of uint32_t should be clear.";
-  value = htonl(tmp);
-  AppendBytes(&value, 4);
-}
-
-void QuicHttpFrameBuilder::AppendUInt32(uint32_t value) {
-  value = htonl(value);
-  AppendBytes(&value, sizeof(value));
-}
-
-void QuicHttpFrameBuilder::Append(QuicHttpErrorCode error_code) {
-  AppendUInt32(static_cast<uint32_t>(error_code));
-}
-
-void QuicHttpFrameBuilder::Append(QuicHttpFrameType type) {
-  AppendUInt8(static_cast<uint8_t>(type));
-}
-
-void QuicHttpFrameBuilder::Append(QuicHttpSettingsParameter parameter) {
-  AppendUInt16(static_cast<uint16_t>(parameter));
-}
-
-void QuicHttpFrameBuilder::Append(const QuicHttpFrameHeader& v) {
-  AppendUInt24(v.payload_length);
-  Append(v.type);
-  AppendUInt8(v.flags);
-  AppendUInt31(v.stream_id);
-}
-
-void QuicHttpFrameBuilder::Append(const QuicHttpPriorityFields& v) {
-  // The EXCLUSIVE flag is the high-bit of the 32-bit stream dependency field.
-  uint32_t tmp = v.stream_dependency & QuicHttpStreamIdMask();
-  EXPECT_EQ(tmp, v.stream_dependency);
-  if (v.is_exclusive) {
-    tmp |= 0x80000000;
-  }
-  AppendUInt32(tmp);
-
-  // The QUIC_HTTP_PRIORITY frame's weight field is logically in the range [1,
-  // 256], but is encoded as a byte in the range [0, 255].
-  ASSERT_LE(1u, v.weight);
-  ASSERT_LE(v.weight, 256u);
-  AppendUInt8(v.weight - 1);
-}
-
-void QuicHttpFrameBuilder::Append(const QuicHttpRstStreamFields& v) {
-  Append(v.error_code);
-}
-
-void QuicHttpFrameBuilder::Append(const QuicHttpSettingFields& v) {
-  Append(v.parameter);
-  AppendUInt32(v.value);
-}
-
-void QuicHttpFrameBuilder::Append(const QuicHttpPushPromiseFields& v) {
-  AppendUInt31(v.promised_stream_id);
-}
-
-void QuicHttpFrameBuilder::Append(const QuicHttpPingFields& v) {
-  AppendBytes(v.opaque_bytes, sizeof QuicHttpPingFields::opaque_bytes);
-}
-
-void QuicHttpFrameBuilder::Append(const QuicHttpGoAwayFields& v) {
-  AppendUInt31(v.last_stream_id);
-  Append(v.error_code);
-}
-
-void QuicHttpFrameBuilder::Append(const QuicHttpWindowUpdateFields& v) {
-  EXPECT_NE(0u, v.window_size_increment) << "Increment must be non-zero.";
-  AppendUInt31(v.window_size_increment);
-}
-
-void QuicHttpFrameBuilder::Append(const QuicHttpAltSvcFields& v) {
-  AppendUInt16(v.origin_length);
-}
-
-// Methods for changing existing buffer contents.
-
-void QuicHttpFrameBuilder::WriteAt(QuicStringPiece s, size_t offset) {
-  ASSERT_LE(offset, buffer_.size());
-  size_t len = offset + s.size();
-  if (len > buffer_.size()) {
-    buffer_.resize(len);
-  }
-  for (size_t ndx = 0; ndx < s.size(); ++ndx) {
-    buffer_[offset + ndx] = s[ndx];
-  }
-}
-
-void QuicHttpFrameBuilder::WriteBytesAt(const void* data,
-                                        uint32_t num_bytes,
-                                        size_t offset) {
-  WriteAt(QuicStringPiece(static_cast<const char*>(data), num_bytes), offset);
-}
-
-void QuicHttpFrameBuilder::WriteUInt24At(uint32_t value, size_t offset) {
-  ASSERT_LT(value, 1u << 24);
-  value = htonl(value);
-  WriteBytesAt(reinterpret_cast<char*>(&value) + 1, sizeof(value) - 1, offset);
-}
-
-void QuicHttpFrameBuilder::SetPayloadLength(uint32_t payload_length) {
-  WriteUInt24At(payload_length, 0);
-}
-
-size_t QuicHttpFrameBuilder::SetPayloadLength() {
-  EXPECT_GE(size(), QuicHttpFrameHeader::EncodedSize());
-  uint32_t payload_length = size() - QuicHttpFrameHeader::EncodedSize();
-  SetPayloadLength(payload_length);
-  return payload_length;
-}
-
-}  // namespace test
-}  // namespace quic
diff --git a/net/third_party/quic/http/tools/quic_http_frame_builder.h b/net/third_party/quic/http/tools/quic_http_frame_builder.h
deleted file mode 100644
index 7d20030..0000000
--- a/net/third_party/quic/http/tools/quic_http_frame_builder.h
+++ /dev/null
@@ -1,103 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_THIRD_PARTY_QUIC_HTTP_TOOLS_QUIC_HTTP_FRAME_BUILDER_H_
-#define NET_THIRD_PARTY_QUIC_HTTP_TOOLS_QUIC_HTTP_FRAME_BUILDER_H_
-
-// QuicHttpFrameBuilder builds wire-format HTTP/2 frames (or fragments thereof)
-// from components.
-//
-// For now, this is only intended for use in tests, and thus has EXPECT* in the
-// code. If desired to use it in an encoder, it will need optimization work,
-// especially w.r.t memory mgmt, and the EXPECT* will need to be removed or
-// replaced with DCHECKs.
-
-#include <stddef.h>  // for size_t
-
-#include <cstdint>
-
-#include "net/third_party/quic/http/quic_http_constants.h"
-#include "net/third_party/quic/http/quic_http_structures.h"
-#include "net/third_party/quic/platform/api/quic_string.h"
-#include "net/third_party/quic/platform/api/quic_string_piece.h"
-
-namespace quic {
-namespace test {
-
-class QuicHttpFrameBuilder {
- public:
-  QuicHttpFrameBuilder(QuicHttpFrameType type,
-                       uint8_t flags,
-                       uint32_t stream_id);
-  explicit QuicHttpFrameBuilder(const QuicHttpFrameHeader& v);
-  QuicHttpFrameBuilder() {}
-  ~QuicHttpFrameBuilder() {}
-
-  size_t size() const { return buffer_.size(); }
-  const QuicString& buffer() const { return buffer_; }
-
-  //----------------------------------------------------------------------------
-  // Methods for appending to the end of the buffer.
-
-  // Append a sequence of bytes from various sources.
-  void Append(QuicStringPiece s);
-  void AppendBytes(const void* data, uint32_t num_bytes);
-
-  // Append an array of type T[N] to the std::string. Intended for tests with
-  // arrays initialized from literals, such as:
-  //    const char kData[] = {0x12, 0x23, ...};
-  //    builder.AppendBytes(kData);
-  template <typename T, size_t N>
-  void AppendBytes(T (&buf)[N]) {
-    AppendBytes(buf, N * sizeof(buf[0]));
-  }
-
-  // Support for appending padding. Does not read or write the Pad Length field.
-  void AppendZeroes(size_t num_zero_bytes);
-
-  // Append various sizes of unsigned integers.
-  void AppendUInt8(uint8_t value);
-  void AppendUInt16(uint16_t value);
-  void AppendUInt24(uint32_t value);
-  void AppendUInt31(uint32_t value);
-  void AppendUInt32(uint32_t value);
-
-  // Append various enums.
-  void Append(QuicHttpErrorCode error_code);
-  void Append(QuicHttpFrameType type);
-  void Append(QuicHttpSettingsParameter parameter);
-
-  // Append various structures.
-  void Append(const QuicHttpFrameHeader& v);
-  void Append(const QuicHttpPriorityFields& v);
-  void Append(const QuicHttpRstStreamFields& v);
-  void Append(const QuicHttpSettingFields& v);
-  void Append(const QuicHttpPushPromiseFields& v);
-  void Append(const QuicHttpPingFields& v);
-  void Append(const QuicHttpGoAwayFields& v);
-  void Append(const QuicHttpWindowUpdateFields& v);
-  void Append(const QuicHttpAltSvcFields& v);
-
-  // Methods for changing existing buffer contents (mostly focused on updating
-  // the payload length).
-
-  void WriteAt(QuicStringPiece s, size_t offset);
-  void WriteBytesAt(const void* data, uint32_t num_bytes, size_t offset);
-  void WriteUInt24At(uint32_t value, size_t offset);
-
-  // Set the payload length to the specified size.
-  void SetPayloadLength(uint32_t payload_length);
-
-  // Sets the payload length to the size of the buffer minus the size of
-  // the frame header.
-  size_t SetPayloadLength();
-
- private:
-  QuicString buffer_;
-};
-
-}  // namespace test
-}  // namespace quic
-
-#endif  // NET_THIRD_PARTY_QUIC_HTTP_TOOLS_QUIC_HTTP_FRAME_BUILDER_H_
diff --git a/net/third_party/quic/http/tools/quic_http_random_decoder_test.cc b/net/third_party/quic/http/tools/quic_http_random_decoder_test.cc
deleted file mode 100644
index fa0c9e2..0000000
--- a/net/third_party/quic/http/tools/quic_http_random_decoder_test.cc
+++ /dev/null
@@ -1,172 +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 "net/third_party/quic/http/tools/quic_http_random_decoder_test.h"
-
-#include <stddef.h>
-#include <algorithm>
-#include <memory>
-
-#include "base/logging.h"
-#include "base/strings/string_number_conversions.h"
-#include "net/third_party/http2/tools/failure.h"
-#include "net/third_party/quic/http/decoder/quic_http_decode_buffer.h"
-#include "net/third_party/quic/http/decoder/quic_http_decode_status.h"
-#include "net/third_party/quic/http/quic_http_constants.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-// It's rather time consuming to decode large buffers one at a time,
-// especially with the log level cranked up. So, by default we don't do
-// that unless explicitly requested.
-
-using ::testing::AssertionFailure;
-using ::testing::AssertionResult;
-using ::testing::AssertionSuccess;
-
-namespace quic {
-namespace test {
-
-QuicHttpRandomDecoderTest::QuicHttpRandomDecoderTest() {}
-
-bool QuicHttpRandomDecoderTest::StopDecodeOnDone() {
-  return stop_decode_on_done_;
-}
-
-QuicHttpDecodeStatus QuicHttpRandomDecoderTest::DecodeSegments(
-    QuicHttpDecodeBuffer* original,
-    const SelectSize& select_size) {
-  QuicHttpDecodeStatus status = QuicHttpDecodeStatus::kDecodeInProgress;
-  bool first = true;
-  VLOG(2) << "DecodeSegments: input size=" << original->Remaining();
-  while (first || original->HasData()) {
-    size_t remaining = original->Remaining();
-    size_t size =
-        std::min(remaining, select_size(first, original->Offset(), remaining));
-    QuicHttpDecodeBuffer db(original->cursor(), size);
-    VLOG(2) << "Decoding " << size << " bytes of " << remaining << " remaining";
-    if (first) {
-      first = false;
-      status = StartDecoding(&db);
-    } else {
-      status = ResumeDecoding(&db);
-    }
-    // A decoder MUST consume some input (if any is available), else we could
-    // get stuck in infinite loops.
-    if (db.Offset() == 0 && db.HasData() &&
-        status != QuicHttpDecodeStatus::kDecodeError) {
-      ADD_FAILURE() << "Decoder didn't make any progress; db.FullSize="
-                    << db.FullSize()
-                    << "   original.Offset=" << original->Offset();
-      return QuicHttpDecodeStatus::kDecodeError;
-    }
-    original->AdvanceCursor(db.Offset());
-    switch (status) {
-      case QuicHttpDecodeStatus::kDecodeDone:
-        if (original->Empty() || StopDecodeOnDone()) {
-          return QuicHttpDecodeStatus::kDecodeDone;
-        }
-        continue;
-      case QuicHttpDecodeStatus::kDecodeInProgress:
-        continue;
-      case QuicHttpDecodeStatus::kDecodeError:
-        return QuicHttpDecodeStatus::kDecodeError;
-    }
-  }
-  return status;
-}
-
-// Decode |original| multiple times, with different segmentations, validating
-// after each decode, returning on the first failure.
-AssertionResult QuicHttpRandomDecoderTest::DecodeAndValidateSeveralWays(
-    QuicHttpDecodeBuffer* original,
-    bool return_non_zero_on_first,
-    const Validator& validator) {
-  const uint32_t original_remaining = original->Remaining();
-  VLOG(1) << "DecodeAndValidateSeveralWays - Start, remaining = "
-          << original_remaining;
-  uint32_t first_consumed;
-  {
-    // Fast decode (no stopping unless decoder does so).
-    QuicHttpDecodeBuffer input(original->cursor(), original_remaining);
-    VLOG(2) << "DecodeSegmentsAndValidate with SelectRemaining";
-    VERIFY_SUCCESS(
-        DecodeSegmentsAndValidate(&input, SelectRemaining(), validator))
-        << "\nFailed with SelectRemaining; input.Offset=" << input.Offset()
-        << "; input.Remaining=" << input.Remaining();
-    first_consumed = input.Offset();
-  }
-  if (original_remaining <= 30) {
-    // Decode again, one byte at a time.
-    QuicHttpDecodeBuffer input(original->cursor(), original_remaining);
-    VLOG(2) << "DecodeSegmentsAndValidate with SelectOne";
-    VERIFY_SUCCESS(DecodeSegmentsAndValidate(&input, SelectOne(), validator))
-        << "\nFailed with SelectOne; input.Offset=" << input.Offset()
-        << "; input.Remaining=" << input.Remaining();
-    VERIFY_EQ(first_consumed, input.Offset()) << "\nFailed with SelectOne";
-  }
-  if (original_remaining <= 20) {
-    // Decode again, one or zero bytes at a time.
-    QuicHttpDecodeBuffer input(original->cursor(), original_remaining);
-    VLOG(2) << "DecodeSegmentsAndValidate with SelectZeroAndOne";
-    VERIFY_SUCCESS(DecodeSegmentsAndValidate(
-        &input, SelectZeroAndOne(return_non_zero_on_first), validator))
-        << "\nFailed with SelectZeroAndOne";
-    VERIFY_EQ(first_consumed, input.Offset())
-        << "\nFailed with SelectZeroAndOne; input.Offset=" << input.Offset()
-        << "; input.Remaining=" << input.Remaining();
-  }
-  {
-    // Decode again, with randomly selected segment sizes.
-    QuicHttpDecodeBuffer input(original->cursor(), original_remaining);
-    VLOG(2) << "DecodeSegmentsAndValidate with SelectRandom";
-    VERIFY_SUCCESS(DecodeSegmentsAndValidate(
-        &input, SelectRandom(return_non_zero_on_first), validator))
-        << "\nFailed with SelectRandom; input.Offset=" << input.Offset()
-        << "; input.Remaining=" << input.Remaining();
-    VERIFY_EQ(first_consumed, input.Offset()) << "\nFailed with SelectRandom";
-  }
-  VERIFY_EQ(original_remaining, original->Remaining());
-  original->AdvanceCursor(first_consumed);
-  VLOG(1) << "DecodeAndValidateSeveralWays - SUCCESS";
-  return ::testing::AssertionSuccess();
-}
-
-// static
-QuicHttpRandomDecoderTest::SelectSize
-QuicHttpRandomDecoderTest::SelectZeroAndOne(bool return_non_zero_on_first) {
-  std::shared_ptr<bool> zero_next(new bool);
-  *zero_next = !return_non_zero_on_first;
-  return [zero_next](bool first, size_t offset, size_t remaining) -> size_t {
-    if (*zero_next) {
-      *zero_next = false;
-      return 0;
-    } else {
-      *zero_next = true;
-      return 1;
-    }
-  };
-}
-
-QuicHttpRandomDecoderTest::SelectSize QuicHttpRandomDecoderTest::SelectRandom(
-    bool return_non_zero_on_first) {
-  return [this, return_non_zero_on_first](bool first, size_t offset,
-                                          size_t remaining) -> size_t {
-    uint32_t r = random_.Rand32();
-    if (first && return_non_zero_on_first) {
-      CHECK_LT(0U, remaining);
-      if (remaining == 1) {
-        return 1;
-      }
-      return 1 + (r % remaining);  // size in range [1, remaining).
-    }
-    return r % (remaining + 1);  // size in range [0, remaining].
-  };
-}
-
-uint32_t QuicHttpRandomDecoderTest::RandStreamId() {
-  return random_.Rand32() & QuicHttpStreamIdMask();
-}
-
-}  // namespace test
-}  // namespace quic
diff --git a/net/third_party/quic/http/tools/quic_http_random_decoder_test.h b/net/third_party/quic/http/tools/quic_http_random_decoder_test.h
deleted file mode 100644
index 9da8e80..0000000
--- a/net/third_party/quic/http/tools/quic_http_random_decoder_test.h
+++ /dev/null
@@ -1,279 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_THIRD_PARTY_QUIC_HTTP_TOOLS_QUIC_HTTP_RANDOM_DECODER_TEST_H_
-#define NET_THIRD_PARTY_QUIC_HTTP_TOOLS_QUIC_HTTP_RANDOM_DECODER_TEST_H_
-
-// QuicHttpRandomDecoderTest is a base class for tests of decoding various kinds
-// of HTTP/2 and HPQUIC_HTTP_ACK encodings.
-// Exports QuicTestRandomBase's include file so that all the sub-classes don't
-// have to do so (i.e. promising that method Random() will continue to return
-// QuicTestRandomBase well into the future).
-
-// TODO(jamessynge): Move more methods into .cc file.
-
-#include <stddef.h>
-
-#include <cstdint>
-#include <functional>
-#include <type_traits>
-
-#include "base/logging.h"
-#include "net/third_party/http2/tools/failure.h"
-#include "net/third_party/quic/http/decoder/quic_http_decode_buffer.h"
-#include "net/third_party/quic/http/decoder/quic_http_decode_status.h"
-#include "net/third_party/quic/platform/api/quic_string.h"
-#include "net/third_party/quic/platform/api/quic_string_piece.h"
-#include "net/third_party/quic/platform/api/quic_test.h"
-#include "net/third_party/quic/platform/api/quic_test_random.h"  // IWYU pragma: export
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace quic {
-namespace test {
-
-// Some helpers.
-
-template <typename T, size_t N>
-QuicStringPiece ToStringPiece(T (&data)[N]) {
-  return QuicStringPiece(reinterpret_cast<const char*>(data), N * sizeof(T));
-}
-
-// Overwrite the enum with some random value, probably not a valid value for
-// the enum type, but which fits into its storage.
-template <typename T,
-          typename E = typename std::enable_if<std::is_enum<T>::value>::type>
-void CorruptEnum(T* out, QuicTestRandomBase* rng) {
-  // Per cppreference.com, if the destination type of a static_cast is
-  // smaller than the source type (i.e. type of r and uint32 below), the
-  // resulting value is the smallest unsigned value equal to the source value
-  // modulo 2^n, where n is the number of bits used to represent the
-  // destination type unsigned U.
-  typedef typename std::underlying_type<T>::type underlying_type_T;
-  typedef typename std::make_unsigned<underlying_type_T>::type
-      unsigned_underlying_type_T;
-  auto r = static_cast<unsigned_underlying_type_T>(rng->Rand32());
-  *out = static_cast<T>(r);
-}
-
-// Base class for tests of the ability to decode a sequence of bytes with
-// various boundaries between the QuicHttpDecodeBuffers provided to the decoder.
-class QuicHttpRandomDecoderTest : public QuicTest {
- public:
-  // SelectSize returns the size of the next QuicHttpDecodeBuffer to be passed
-  // to the decoder. Note that QuicHttpRandomDecoderTest allows that size to be
-  // zero, though some decoders can't deal with that on the first byte, hence
-  // the |first| parameter.
-  typedef std::function<size_t(bool first, size_t offset, size_t remaining)>
-      SelectSize;
-
-  // Validator returns an AssertionResult so test can do:
-  // EXPECT_THAT(DecodeAndValidate(..., validator));
-  typedef ::testing::AssertionResult AssertionResult;
-  typedef std::function<AssertionResult(const QuicHttpDecodeBuffer& input,
-                                        QuicHttpDecodeStatus status)>
-      Validator;
-  typedef std::function<AssertionResult()> NoArgValidator;
-
-  QuicHttpRandomDecoderTest();
-
- protected:
-  // Enables sub-class using BoostLoggingIfDefault to restore the verbosity
-  // without waiting for gUnit to restore flags at the end of a test case.
-  class RestoreVerbosity {
-   public:
-    explicit RestoreVerbosity(int old_verbosity);
-    ~RestoreVerbosity();
-
-   private:
-    const int old_verbosity_;
-  };
-
-  // In support of better coverage of VLOG and DVLOG lines, increase the log
-  // level if not overridden already. Because there are so many D?VLOG(2)
-  // statements triggered by the randomized decoding, it is recommended to only
-  // call this method when decoding a small payload.
-  // Returns the previous value of FLAGS_v.
-  int BoostLoggingIfDefault(int target_level);
-
-  // TODO(jamessynge): Modify StartDecoding, etc. to (somehow) return
-  // AssertionResult so that the VERIFY_* methods exported from
-  // gunit_helpers.h can be widely used.
-
-  // Start decoding; call allows sub-class to Reset the decoder, or deal with
-  // the first byte if that is done in a unique fashion.  Might be called with
-  // a zero byte buffer.
-  virtual QuicHttpDecodeStatus StartDecoding(QuicHttpDecodeBuffer* db) = 0;
-
-  // Resume decoding of the input after a prior call to StartDecoding, and
-  // possibly many calls to ResumeDecoding.
-  virtual QuicHttpDecodeStatus ResumeDecoding(QuicHttpDecodeBuffer* db) = 0;
-
-  // Return true if a decode status of kDecodeDone indicates that
-  // decoding should stop.
-  virtual bool StopDecodeOnDone();
-
-  // Decode buffer |original| until we run out of input, or kDecodeDone is
-  // returned by the decoder AND StopDecodeOnDone() returns true. Segments
-  // (i.e. cuts up) the original QuicHttpDecodeBuffer into (potentially) smaller
-  // buffers by calling |select_size| to decide how large each buffer should be.
-  // We do this to test the ability to deal with arbitrary boundaries, as might
-  // happen in transport.
-  // Returns the final QuicHttpDecodeStatus.
-  QuicHttpDecodeStatus DecodeSegments(QuicHttpDecodeBuffer* original,
-                                      const SelectSize& select_size);
-
-  // Decode buffer |original| until we run out of input, or kDecodeDone is
-  // returned by the decoder AND StopDecodeOnDone() returns true. Segments
-  // (i.e. cuts up) the original QuicHttpDecodeBuffer into (potentially) smaller
-  // buffers by calling |select_size| to decide how large each buffer should be.
-  // We do this to test the ability to deal with arbitrary boundaries, as might
-  // happen in transport.
-  // Invokes |validator| with the final decode status and the original decode
-  // buffer, with the cursor advanced as far as has been consumed by the decoder
-  // and returns validator's result.
-  ::testing::AssertionResult DecodeSegmentsAndValidate(
-      QuicHttpDecodeBuffer* original,
-      const SelectSize& select_size,
-      const Validator& validator) {
-    QuicHttpDecodeStatus status = DecodeSegments(original, select_size);
-    VERIFY_AND_RETURN_SUCCESS(validator(*original, status));
-  }
-
-  // Returns a SelectSize function for fast decoding, i.e. passing all that
-  // is available to the decoder.
-  static SelectSize SelectRemaining() {
-    return [](bool first, size_t offset, size_t remaining) -> size_t {
-      return remaining;
-    };
-  }
-
-  // Returns a SelectSize function for decoding a single byte at a time.
-  static SelectSize SelectOne() {
-    return
-        [](bool first, size_t offset, size_t remaining) -> size_t { return 1; };
-  }
-
-  // Returns a SelectSize function for decoding a single byte at a time, where
-  // zero byte buffers are also allowed. Alternates between zero and one,
-  // starting with zero if allowed, else with one.
-  static SelectSize SelectZeroAndOne(bool return_non_zero_on_first);
-
-  // Returns a SelectSize function for decoding random sized segments.
-  SelectSize SelectRandom(bool return_non_zero_on_first);
-
-  // Decode |original| multiple times, with different segmentations of the
-  // decode buffer, validating after each decode, and confirming that they
-  // each decode the same amount. Returns on the first failure, else returns
-  // success.
-  AssertionResult DecodeAndValidateSeveralWays(QuicHttpDecodeBuffer* original,
-                                               bool return_non_zero_on_first,
-                                               const Validator& validator);
-
-  static Validator ToValidator(std::nullptr_t) {
-    return [](const QuicHttpDecodeBuffer& input, QuicHttpDecodeStatus status) {
-      return ::testing::AssertionSuccess();
-    };
-  }
-
-  static Validator ToValidator(const Validator& validator) {
-    if (validator == nullptr) {
-      return ToValidator(nullptr);
-    }
-    return validator;
-  }
-
-  static Validator ToValidator(const NoArgValidator& validator) {
-    if (validator == nullptr) {
-      return ToValidator(nullptr);
-    }
-    return [validator](const QuicHttpDecodeBuffer& input,
-                       QuicHttpDecodeStatus status) { return validator(); };
-  }
-
-  // Wraps a validator (which may be empty) with another validator
-  // that first checks that the QuicHttpDecodeStatus is kDecodeDone and
-  // that the QuicHttpDecodeBuffer is empty.
-  // TODO(jamessynge): Replace this overload with the next, as using this method
-  // usually means that the wrapped function doesn't need to be passed the
-  // QuicHttpDecodeBuffer nor the QuicHttpDecodeStatus.
-  static Validator ValidateDoneAndEmpty(const Validator& wrapped) {
-    return [wrapped](const QuicHttpDecodeBuffer& input,
-                     QuicHttpDecodeStatus status) -> AssertionResult {
-      VERIFY_EQ(status, QuicHttpDecodeStatus::kDecodeDone);
-      VERIFY_EQ(0u, input.Remaining()) << "\nOffset=" << input.Offset();
-      if (wrapped) {
-        return wrapped(input, status);
-      }
-      return ::testing::AssertionSuccess();
-    };
-  }
-  static Validator ValidateDoneAndEmpty(const NoArgValidator& wrapped) {
-    return [wrapped](const QuicHttpDecodeBuffer& input,
-                     QuicHttpDecodeStatus status) -> AssertionResult {
-      VERIFY_EQ(status, QuicHttpDecodeStatus::kDecodeDone);
-      VERIFY_EQ(0u, input.Remaining()) << "\nOffset=" << input.Offset();
-      if (wrapped) {
-        return wrapped();
-      }
-      return ::testing::AssertionSuccess();
-    };
-  }
-  static Validator ValidateDoneAndEmpty() {
-    NoArgValidator validator;
-    return ValidateDoneAndEmpty(validator);
-  }
-
-  // Wraps a validator (which may be empty) with another validator
-  // that first checks that the QuicHttpDecodeStatus is kDecodeDone and
-  // that the QuicHttpDecodeBuffer has the expected offset.
-  // TODO(jamessynge): Replace this overload with the next, as using this method
-  // usually means that the wrapped function doesn't need to be passed the
-  // QuicHttpDecodeBuffer nor the QuicHttpDecodeStatus.
-  static Validator ValidateDoneAndOffset(uint32_t offset,
-                                         const Validator& wrapped) {
-    return [wrapped, offset](const QuicHttpDecodeBuffer& input,
-                             QuicHttpDecodeStatus status) -> AssertionResult {
-      VERIFY_EQ(status, QuicHttpDecodeStatus::kDecodeDone);
-      VERIFY_EQ(offset, input.Offset()) << "\nRemaining=" << input.Remaining();
-      if (wrapped) {
-        return wrapped(input, status);
-      }
-      return ::testing::AssertionSuccess();
-    };
-  }
-  static Validator ValidateDoneAndOffset(uint32_t offset,
-                                         const NoArgValidator& wrapped) {
-    return [wrapped, offset](const QuicHttpDecodeBuffer& input,
-                             QuicHttpDecodeStatus status) -> AssertionResult {
-      VERIFY_EQ(status, QuicHttpDecodeStatus::kDecodeDone);
-      VERIFY_EQ(offset, input.Offset()) << "\nRemaining=" << input.Remaining();
-      if (wrapped) {
-        return wrapped();
-      }
-      return ::testing::AssertionSuccess();
-    };
-  }
-  static Validator ValidateDoneAndOffset(uint32_t offset) {
-    NoArgValidator validator;
-    return ValidateDoneAndOffset(offset, validator);
-  }
-
-  // Expose random_ as QuicTestRandomBase so callers don't have to care about
-  // which sub-class of QuicTestRandomBase is used, nor can they rely on the
-  // specific sub-class that QuicHttpRandomDecoderTest uses.
-  QuicTestRandomBase& Random() { return random_; }
-  QuicTestRandomBase* RandomPtr() { return &random_; }
-
-  uint32_t RandStreamId();
-
-  bool stop_decode_on_done_ = true;
-
- private:
-  QuicTestRandom random_;
-};
-
-}  // namespace test
-}  // namespace quic
-
-#endif  // NET_THIRD_PARTY_QUIC_HTTP_TOOLS_QUIC_HTTP_RANDOM_DECODER_TEST_H_
diff --git a/net/third_party/quic/http/tools/quic_http_random_util.cc b/net/third_party/quic/http/tools/quic_http_random_util.cc
deleted file mode 100644
index 1254d6f..0000000
--- a/net/third_party/quic/http/tools/quic_http_random_util.cc
+++ /dev/null
@@ -1,82 +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 "net/third_party/quic/http/tools/quic_http_random_util.h"
-
-#include <cmath>
-
-#include "base/rand_util.h"
-#include "net/third_party/quic/platform/api/quic_string_piece.h"
-#include "net/third_party/quic/platform/api/quic_test_random.h"
-
-namespace quic {
-namespace test {
-namespace {
-
-const char kWebsafe64[] =
-    "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_";
-
-// Generate two independent standard normal random variables using the polar
-// method.
-void GenerateRandomSizeSkewedLowHelper(size_t max, size_t* x, size_t* y) {
-  double a, b, s;
-  do {
-    // Draw uniformly on [-1, 1).
-    a = 2 * base::RandDouble() - 1.0;
-    b = 2 * base::RandDouble() - 1.0;
-    s = a * a + b * b;
-  } while (s >= 1.0);
-  double t = std::sqrt(-2.0 * std::log(s) / s);
-  *x = static_cast<size_t>(a * t * max);
-  *y = static_cast<size_t>(b * t * max);
-}
-
-}  // anonymous namespace
-
-QuicString RandomString(QuicTestRandomBase* rng,
-                        int len,
-                        QuicStringPiece alphabet) {
-  QuicString random_string;
-  random_string.reserve(len);
-  for (int i = 0; i < len; ++i)
-    random_string.push_back(alphabet[rng->Uniform(alphabet.size())]);
-  return random_string;
-}
-
-size_t GenerateUniformInRange(size_t lo, size_t hi, QuicTestRandomBase* rng) {
-  if (lo + 1 >= hi) {
-    return lo;
-  }
-  return lo + rng->Rand64() % (hi - lo);
-}
-
-QuicString GenerateWebSafeString(size_t len, QuicTestRandomBase* rng) {
-  return RandomString(rng, len, kWebsafe64);
-}
-
-QuicString GenerateWebSafeString(size_t lo,
-                                 size_t hi,
-                                 QuicTestRandomBase* rng) {
-  return GenerateWebSafeString(GenerateUniformInRange(lo, hi, rng), rng);
-}
-
-size_t GenerateRandomSizeSkewedLow(size_t max, QuicTestRandomBase* rng) {
-  if (max == 0) {
-    return 0;
-  }
-  // Generate a random number with a Gaussian distribution, centered on zero;
-  // take the absolute, and then keep in range 0 to max.
-  for (int i = 0; i < 5; i++) {
-    size_t x, y;
-    GenerateRandomSizeSkewedLowHelper(max, &x, &y);
-    if (x <= max)
-      return x;
-    if (y <= max)
-      return y;
-  }
-  return rng->Uniform(max + 1);
-}
-
-}  // namespace test
-}  // namespace quic
diff --git a/net/third_party/quic/http/tools/quic_http_random_util.h b/net/third_party/quic/http/tools/quic_http_random_util.h
deleted file mode 100644
index 3db6a5c4..0000000
--- a/net/third_party/quic/http/tools/quic_http_random_util.h
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_THIRD_PARTY_QUIC_HTTP_TOOLS_QUIC_HTTP_RANDOM_UTIL_H_
-#define NET_THIRD_PARTY_QUIC_HTTP_TOOLS_QUIC_HTTP_RANDOM_UTIL_H_
-
-#include <stddef.h>
-
-#include "net/third_party/quic/platform/api/quic_string.h"
-#include "net/third_party/quic/platform/api/quic_test_random.h"
-
-namespace quic {
-namespace test {
-
-// Returns a random integer in the range [lo, hi).
-size_t GenerateUniformInRange(size_t lo, size_t hi, QuicTestRandomBase* rng);
-
-// Generate a string with the web-safe string character set of specified len.
-QuicString GenerateWebSafeString(size_t len, QuicTestRandomBase* rng);
-
-// Generate a string with the web-safe string character set of length
-// [lo, hi).
-QuicString GenerateWebSafeString(size_t lo, size_t hi, QuicTestRandomBase* rng);
-
-// Returns a random integer in the range [0, max], with a bias towards producing
-// lower numbers.
-size_t GenerateRandomSizeSkewedLow(size_t max, QuicTestRandomBase* rng);
-
-}  // namespace test
-}  // namespace quic
-
-#endif  // NET_THIRD_PARTY_QUIC_HTTP_TOOLS_QUIC_HTTP_RANDOM_UTIL_H_
diff --git a/net/third_party/quic/quartc/quartc_factory.cc b/net/third_party/quic/quartc/quartc_factory.cc
index da9e056..a1cf7f5 100644
--- a/net/third_party/quic/quartc/quartc_factory.cc
+++ b/net/third_party/quic/quartc/quartc_factory.cc
@@ -186,6 +186,21 @@
     }
   }
   QuicConfig quic_config;
+
+  // Use the limits for the session & stream flow control. The default 16KB
+  // limit leads to significantly undersending (not reaching BWE on the outgoing
+  // bitrate) due to blocked frames, and it leads to high latency (and one-way
+  // delay). Setting it to its limits is not going to cause issues (our streams
+  // are small generally, and if we were to buffer 24MB it wouldn't be the end
+  // of the world). We can consider setting different limits in future (e.g. 1MB
+  // stream, 1.5MB session). It's worth noting that on 1mbps bitrate, limit of
+  // 24MB can capture approx 4 minutes of the call, and the default increase in
+  // size of the window (half of the window size) is approximately 2 minutes of
+  // the call.
+  quic_config.SetInitialSessionFlowControlWindowToSend(
+      kSessionReceiveWindowLimit);
+  quic_config.SetInitialStreamFlowControlWindowToSend(
+      kStreamReceiveWindowLimit);
   quic_config.SetConnectionOptionsToSend(copt);
   quic_config.SetClientConnectionOptions(copt);
   if (quartc_session_config.max_time_before_crypto_handshake_secs > 0) {
@@ -203,6 +218,10 @@
         quartc_session_config.idle_network_timeout,
         quartc_session_config.idle_network_timeout);
   }
+
+  // The ICE transport provides a unique 5-tuple for each connection. Save
+  // overhead by omitting the connection id.
+  quic_config.SetBytesForConnectionIdToSend(0);
   return QuicMakeUnique<QuartcSession>(
       std::move(quic_connection), quic_config,
       quartc_session_config.unique_remote_server_id, perspective,
diff --git a/net/third_party/quic/quartc/quartc_session.cc b/net/third_party/quic/quartc/quartc_session.cc
index 39a177d..d9b6897 100644
--- a/net/third_party/quic/quartc/quartc_session.cc
+++ b/net/third_party/quic/quartc/quartc_session.cc
@@ -176,10 +176,10 @@
     : QuicSession(connection.get(), nullptr /*visitor*/, config),
       unique_remote_server_id_(unique_remote_server_id),
       perspective_(perspective),
+      packet_writer_(std::move(packet_writer)),
       connection_(std::move(connection)),
       helper_(helper),
-      clock_(clock),
-      packet_writer_(std::move(packet_writer)) {
+      clock_(clock) {
   packet_writer_->set_connection(connection_.get());
 
   // Initialization with default crypto configuration.
diff --git a/net/third_party/quic/quartc/quartc_session.h b/net/third_party/quic/quartc/quartc_session.h
index e3bcd3f..ac1eb24 100644
--- a/net/third_party/quic/quartc/quartc_session.h
+++ b/net/third_party/quic/quartc/quartc_session.h
@@ -166,7 +166,11 @@
   std::unique_ptr<QuicCryptoStream> crypto_stream_;
   const std::string unique_remote_server_id_;
   Perspective perspective_;
-  // Take the ownership of the QuicConnection.  Note:  if |connection_| changes,
+
+  // Packet writer used by |connection_|.
+  std::unique_ptr<QuartcPacketWriter> packet_writer_;
+
+  // Take ownership of the QuicConnection.  Note: if |connection_| changes,
   // the new value of |connection_| must be given to |packet_writer_| before any
   // packets are written.  Otherwise, |packet_writer_| will crash.
   std::unique_ptr<QuicConnection> connection_;
@@ -174,9 +178,6 @@
   QuicConnectionHelperInterface* helper_;
   // For recording packet receipt time
   QuicClock* clock_;
-  // Packet writer used by |connection_|.
-  std::unique_ptr<QuartcPacketWriter> packet_writer_;
-
   // Not owned by QuartcSession.
   QuartcSessionInterface::Delegate* session_delegate_ = nullptr;
   // Used by QUIC crypto server stream to track most recently compressed certs.
diff --git a/net/third_party/quic/quartc/quartc_session_test.cc b/net/third_party/quic/quartc/quartc_session_test.cc
index 934c8e20..836efd9f 100644
--- a/net/third_party/quic/quartc/quartc_session_test.cc
+++ b/net/third_party/quic/quartc/quartc_session_test.cc
@@ -424,7 +424,6 @@
   ~QuartcSessionTest() override {}
 
   void Init() {
-    SetQuicReloadableFlag(quic_respect_ietf_header, true);
     // Quic crashes if packets are sent at time 0, and the clock defaults to 0.
     clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(1000));
     client_channel_ =
diff --git a/net/third_party/quic/test_tools/mock_crypto_client_stream.cc b/net/third_party/quic/test_tools/mock_crypto_client_stream.cc
index 6d6bdfe..ba277e50 100644
--- a/net/third_party/quic/test_tools/mock_crypto_client_stream.cc
+++ b/net/third_party/quic/test_tools/mock_crypto_client_stream.cc
@@ -199,8 +199,6 @@
   config.SetIdleNetworkTimeout(
       QuicTime::Delta::FromSeconds(2 * kMaximumIdleTimeoutSecs),
       QuicTime::Delta::FromSeconds(kMaximumIdleTimeoutSecs));
-  config.SetMaxStreamsPerConnection(kDefaultMaxStreamsPerConnection / 2,
-                                    kDefaultMaxStreamsPerConnection / 2);
   config.SetBytesForConnectionIdToSend(PACKET_8BYTE_CONNECTION_ID);
   config.SetMaxIncomingDynamicStreamsToSend(kDefaultMaxStreamsPerConnection /
                                             2);
diff --git a/net/third_party/quic/test_tools/mock_crypto_client_stream.h b/net/third_party/quic/test_tools/mock_crypto_client_stream.h
index 1bf24465..26da81c4 100644
--- a/net/third_party/quic/test_tools/mock_crypto_client_stream.h
+++ b/net/third_party/quic/test_tools/mock_crypto_client_stream.h
@@ -78,7 +78,6 @@
 
  private:
   void SetConfigNegotiated();
-
   bool encryption_established_;
   bool handshake_confirmed_;
   QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters>
diff --git a/net/third_party/quic/test_tools/mock_quic_time_wait_list_manager.cc b/net/third_party/quic/test_tools/mock_quic_time_wait_list_manager.cc
index abba287..22157e2 100644
--- a/net/third_party/quic/test_tools/mock_quic_time_wait_list_manager.cc
+++ b/net/third_party/quic/test_tools/mock_quic_time_wait_list_manager.cc
@@ -18,9 +18,9 @@
     : QuicTimeWaitListManager(writer, visitor, helper, alarm_factory) {
   // Though AddConnectionIdToTimeWait is mocked, we want to retain its
   // functionality.
-  EXPECT_CALL(*this, AddConnectionIdToTimeWait(_, _, _, _, _))
+  EXPECT_CALL(*this, AddConnectionIdToTimeWait(_, _, _, _))
       .Times(testing::AnyNumber());
-  ON_CALL(*this, AddConnectionIdToTimeWait(_, _, _, _, _))
+  ON_CALL(*this, AddConnectionIdToTimeWait(_, _, _, _))
       .WillByDefault(
           Invoke(this, &MockTimeWaitListManager::
                            QuicTimeWaitListManager_AddConnectionIdToTimeWait));
diff --git a/net/third_party/quic/test_tools/mock_quic_time_wait_list_manager.h b/net/third_party/quic/test_tools/mock_quic_time_wait_list_manager.h
index 8a875732..13600e0 100644
--- a/net/third_party/quic/test_tools/mock_quic_time_wait_list_manager.h
+++ b/net/third_party/quic/test_tools/mock_quic_time_wait_list_manager.h
@@ -19,9 +19,8 @@
                           QuicAlarmFactory* alarm_factory);
   ~MockTimeWaitListManager() override;
 
-  MOCK_METHOD5(AddConnectionIdToTimeWait,
+  MOCK_METHOD4(AddConnectionIdToTimeWait,
                void(QuicConnectionId connection_id,
-                    ParsedQuicVersion version,
                     bool ietf_quic,
                     QuicTimeWaitListManager::TimeWaitAction action,
                     std::vector<std::unique_ptr<QuicEncryptedPacket>>*
@@ -29,12 +28,11 @@
 
   void QuicTimeWaitListManager_AddConnectionIdToTimeWait(
       QuicConnectionId connection_id,
-      ParsedQuicVersion version,
       bool ietf_quic,
       QuicTimeWaitListManager::TimeWaitAction action,
       std::vector<std::unique_ptr<QuicEncryptedPacket>>* termination_packets) {
     QuicTimeWaitListManager::AddConnectionIdToTimeWait(
-        connection_id, version, ietf_quic, action, termination_packets);
+        connection_id, ietf_quic, action, termination_packets);
   }
 
   MOCK_METHOD3(ProcessPacket,
diff --git a/net/third_party/quic/test_tools/quic_time_wait_list_manager_peer.cc b/net/third_party/quic/test_tools/quic_time_wait_list_manager_peer.cc
index 679dc6a..974d88e 100644
--- a/net/third_party/quic/test_tools/quic_time_wait_list_manager_peer.cc
+++ b/net/third_party/quic/test_tools/quic_time_wait_list_manager_peer.cc
@@ -18,14 +18,6 @@
   return manager->time_wait_period_;
 }
 
-QuicTransportVersion
-QuicTimeWaitListManagerPeer::GetQuicVersionFromConnectionId(
-    QuicTimeWaitListManager* manager,
-    QuicConnectionId connection_id) {
-  return manager->GetQuicVersionFromConnectionId(connection_id)
-      .transport_version;
-}
-
 QuicAlarm* QuicTimeWaitListManagerPeer::expiration_alarm(
     QuicTimeWaitListManager* manager) {
   return manager->connection_id_clean_up_alarm_.get();
diff --git a/net/third_party/quic/test_tools/quic_time_wait_list_manager_peer.h b/net/third_party/quic/test_tools/quic_time_wait_list_manager_peer.h
index 27bd8bef..b719ba79 100644
--- a/net/third_party/quic/test_tools/quic_time_wait_list_manager_peer.h
+++ b/net/third_party/quic/test_tools/quic_time_wait_list_manager_peer.h
@@ -17,10 +17,6 @@
 
   static QuicTime::Delta time_wait_period(QuicTimeWaitListManager* manager);
 
-  static QuicTransportVersion GetQuicVersionFromConnectionId(
-      QuicTimeWaitListManager* manager,
-      QuicConnectionId connection_id);
-
   static QuicAlarm* expiration_alarm(QuicTimeWaitListManager* manager);
 
   static void set_clock(QuicTimeWaitListManager* manager,
diff --git a/net/third_party/quic/test_tools/run_all_unittests.cc b/net/third_party/quic/test_tools/run_all_unittests.cc
deleted file mode 100644
index 6d42d33..0000000
--- a/net/third_party/quic/test_tools/run_all_unittests.cc
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/test/test_suite.h"
-
-int main(int argc, char** argv) {
-  base::TestSuite test_suite(argc, argv);
-
-  return test_suite.Run();
-}
diff --git a/net/third_party/quic/tools/quic_simple_server_session_test.cc b/net/third_party/quic/tools/quic_simple_server_session_test.cc
index 71b342c..2c8718e 100644
--- a/net/third_party/quic/tools/quic_simple_server_session_test.cc
+++ b/net/third_party/quic/tools/quic_simple_server_session_test.cc
@@ -191,7 +191,6 @@
                        TlsServerHandshaker::CreateSslCtx()),
         compressed_certs_cache_(
             QuicCompressedCertsCache::kQuicCompressedCertsCacheSize) {
-    config_.SetMaxStreamsPerConnection(kMaxStreamsForTest, kMaxStreamsForTest);
     config_.SetMaxIncomingDynamicStreamsToSend(kMaxStreamsForTest);
     QuicConfigPeer::SetReceivedMaxIncomingDynamicStreams(&config_,
                                                          kMaxStreamsForTest);
@@ -464,8 +463,6 @@
   const size_t kStreamFlowControlWindowSize = 32 * 1024;  // 32KB.
 
   QuicSimpleServerSessionServerPushTest() : QuicSimpleServerSessionTest() {
-    config_.SetMaxStreamsPerConnection(kMaxStreamsForTest, kMaxStreamsForTest);
-
     // Reset stream level flow control window to be 32KB.
     QuicConfigPeer::SetReceivedInitialStreamFlowControlWindow(
         &config_, kStreamFlowControlWindowSize);
@@ -515,8 +512,6 @@
     // than stream flow control window so stream won't send the full body.
     size_t body_size = 2 * kStreamFlowControlWindowSize;  // 64KB.
 
-    config_.SetMaxStreamsPerConnection(kMaxStreamsForTest, kMaxStreamsForTest);
-
     QuicString request_url = "mail.google.com/";
     spdy::SpdyHeaderBlock request_headers;
     QuicString resource_host = "www.google.com";
diff --git a/net/websockets/websocket_stream_test.cc b/net/websockets/websocket_stream_test.cc
index b6c8fbf..78e6aa2 100644
--- a/net/websockets/websocket_stream_test.cc
+++ b/net/websockets/websocket_stream_test.cc
@@ -73,11 +73,10 @@
   return std::make_unique<SequencedSocketData>();
 }
 
-class MockWeakTimer : public base::MockTimer,
+class MockWeakTimer : public base::MockOneShotTimer,
                       public base::SupportsWeakPtr<MockWeakTimer> {
  public:
-  MockWeakTimer(bool retain_user_task, bool is_repeating)
-      : MockTimer(retain_user_task, is_repeating) {}
+  MockWeakTimer() {}
 };
 
 const char kOrigin[] = "http://www.example.org";
@@ -1230,7 +1229,7 @@
 TEST_P(WebSocketStreamCreateTest, HandshakeTimeout) {
   std::unique_ptr<SequencedSocketData> socket_data(BuildNullSocketData());
   socket_data->set_connect_data(MockConnect(SYNCHRONOUS, ERR_IO_PENDING));
-  auto timer = std::make_unique<MockWeakTimer>(false, false);
+  auto timer = std::make_unique<MockWeakTimer>();
   base::WeakPtr<MockWeakTimer> weak_timer = timer->AsWeakPtr();
   SetTimer(std::move(timer));
   CreateAndConnectRawExpectations("ws://www.example.org/", NoSubProtocols(),
@@ -1250,7 +1249,7 @@
 
 // When the connection establishes the timer should be stopped.
 TEST_P(WebSocketStreamCreateTest, HandshakeTimerOnSuccess) {
-  auto timer = std::make_unique<MockWeakTimer>(false, false);
+  auto timer = std::make_unique<MockWeakTimer>();
   base::WeakPtr<MockWeakTimer> weak_timer = timer->AsWeakPtr();
 
   SetTimer(std::move(timer));
@@ -1271,7 +1270,7 @@
   std::unique_ptr<SequencedSocketData> socket_data(BuildNullSocketData());
   socket_data->set_connect_data(
       MockConnect(SYNCHRONOUS, ERR_CONNECTION_REFUSED));
-  auto timer = std::make_unique<MockWeakTimer>(false, false);
+  auto timer = std::make_unique<MockWeakTimer>();
   base::WeakPtr<MockWeakTimer> weak_timer = timer->AsWeakPtr();
   SetTimer(std::move(timer));
   CreateAndConnectRawExpectations("ws://www.example.org/", NoSubProtocols(),
diff --git a/services/network/test/test_url_loader_factory.cc b/services/network/test/test_url_loader_factory.cc
index 679c0bf..aaa3c99 100644
--- a/services/network/test/test_url_loader_factory.cc
+++ b/services/network/test/test_url_loader_factory.cc
@@ -14,6 +14,21 @@
 
 namespace network {
 
+namespace {
+
+ResourceResponseHead CreateResourceResponseHead(
+    net::HttpStatusCode http_status) {
+  ResourceResponseHead head;
+  std::string headers(base::StringPrintf(
+      "HTTP/1.1 %d %s\nContent-type: text/html\n\n",
+      static_cast<int>(http_status), net::GetHttpReasonPhrase(http_status)));
+  head.headers = new net::HttpResponseHeaders(
+      net::HttpUtil::AssembleRawHeaders(headers.c_str(), headers.size()));
+  return head;
+}
+
+}  // namespace
+
 TestURLLoaderFactory::PendingRequest::PendingRequest() = default;
 TestURLLoaderFactory::PendingRequest::~PendingRequest() = default;
 
@@ -55,12 +70,7 @@
 void TestURLLoaderFactory::AddResponse(const std::string& url,
                                        const std::string& content,
                                        net::HttpStatusCode http_status) {
-  ResourceResponseHead head;
-  std::string headers(base::StringPrintf(
-      "HTTP/1.1 %d %s\nContent-type: text/html\n\n",
-      static_cast<int>(http_status), GetHttpReasonPhrase(http_status)));
-  head.headers = new net::HttpResponseHeaders(
-      net::HttpUtil::AssembleRawHeaders(headers.c_str(), headers.size()));
+  ResourceResponseHead head = CreateResourceResponseHead(http_status);
   head.mime_type = "text/html";
   URLLoaderCompletionStatus status;
   status.decoded_body_length = content.size();
@@ -131,20 +141,44 @@
   if (it == responses_.end())
     return false;
 
-  for (const auto& redirect : it->second.redirects)
+  SimulateResponseImpl(client, it->second.redirects, it->second.head,
+                       it->second.content, it->second.status);
+  return true;
+}
+
+// static
+void TestURLLoaderFactory::SimulateResponse(
+    TestURLLoaderFactory::PendingRequest request,
+    std::string content,
+    int net_error) {
+  network::URLLoaderCompletionStatus status(net::OK);
+  ResourceResponseHead head = CreateResourceResponseHead(net::HTTP_OK);
+  status.decoded_body_length = content.size();
+  SimulateResponseImpl(request.client.get(), TestURLLoaderFactory::Redirects(),
+                       head, content, status);
+  base::RunLoop().RunUntilIdle();
+}
+
+// static
+void TestURLLoaderFactory::SimulateResponseImpl(
+    mojom::URLLoaderClient* client,
+    TestURLLoaderFactory::Redirects redirects,
+    ResourceResponseHead head,
+    std::string content,
+    URLLoaderCompletionStatus status) {
+  for (const auto& redirect : redirects)
     client->OnReceiveRedirect(redirect.first, redirect.second);
 
-  if (it->second.status.error_code == net::OK) {
-    client->OnReceiveResponse(it->second.head);
-    mojo::DataPipe data_pipe(it->second.content.size());
-    uint32_t bytes_written = it->second.content.size();
+  if (status.error_code == net::OK) {
+    client->OnReceiveResponse(head);
+    mojo::DataPipe data_pipe(content.size());
+    uint32_t bytes_written = content.size();
     CHECK_EQ(MOJO_RESULT_OK, data_pipe.producer_handle->WriteData(
-                                 it->second.content.data(), &bytes_written,
+                                 content.data(), &bytes_written,
                                  MOJO_WRITE_DATA_FLAG_ALL_OR_NONE));
     client->OnStartLoadingResponseBody(std::move(data_pipe.consumer_handle));
   }
-  client->OnComplete(it->second.status);
-  return true;
+  client->OnComplete(status);
 }
 
 }  // namespace network
diff --git a/services/network/test/test_url_loader_factory.h b/services/network/test/test_url_loader_factory.h
index f36a6ce..5aca2f6 100644
--- a/services/network/test/test_url_loader_factory.h
+++ b/services/network/test/test_url_loader_factory.h
@@ -77,6 +77,12 @@
   // servicing requests themselves, whenever possible.
   std::vector<PendingRequest>* pending_requests() { return &pending_requests_; }
 
+  // Sends a response for |request| that can be retrieved from
+  // pending_requests(). Prefer using AddResponse.
+  static void SimulateResponse(PendingRequest request,
+                               std::string content,
+                               int net_error = net::OK);
+
   // mojom::URLLoaderFactory implementation.
   void CreateLoaderAndStart(mojom::URLLoaderRequest request,
                             int32_t routing_id,
@@ -92,6 +98,12 @@
   bool CreateLoaderAndStartInternal(const GURL& url,
                                     mojom::URLLoaderClient* client);
 
+  static void SimulateResponseImpl(mojom::URLLoaderClient* client,
+                                   Redirects redirects,
+                                   ResourceResponseHead head,
+                                   std::string content,
+                                   URLLoaderCompletionStatus status);
+
   struct Response {
     Response();
     ~Response();
diff --git a/services/ui/ws/window_tree_client_unittest.cc b/services/ui/ws/window_tree_client_unittest.cc
index 4736073..db45aa65 100644
--- a/services/ui/ws/window_tree_client_unittest.cc
+++ b/services/ui/ws/window_tree_client_unittest.cc
@@ -1937,7 +1937,7 @@
 
 // Tests that when opacity is set on a window, that the calling client is not
 // notified, however children are. Also that setting the same opacity is
-// rejected and no on eis notifiyed.
+// rejected and no one is notified.
 TEST_F(WindowTreeClientTest, SetOpacityNotifications) {
   Id window_1_1 = wt_client1()->NewWindow(1);
   ASSERT_TRUE(window_1_1);
diff --git a/services/ui/ws2/ids.h b/services/ui/ws2/ids.h
index be27b9f..1fc394b 100644
--- a/services/ui/ws2/ids.h
+++ b/services/ui/ws2/ids.h
@@ -15,12 +15,22 @@
 
 // A client id used to indicate no client. That is, no WindowTree ever gets this
 // id.
-const ClientSpecificId kInvalidClientId = 0;
+constexpr ClientSpecificId kInvalidClientId = 0;
 
-const Id kInvalidTransportId = 0;
+constexpr Id kInvalidTransportId = 0;
 
 // A client id used to indicate WindowServer.
-const ClientSpecificId kWindowServerClientId = 1;
+constexpr ClientSpecificId kWindowServerClientId = 1;
+
+// The initial id assigned to window service clients, incremented thereafter.
+constexpr ClientSpecificId kInitialClientId = 2;
+
+// The initial id assigned to window service clients in a decrementing mode.
+// Used when Chrome hosts Ash in the browser process; in that configuration,
+// Content connects directly to Viz and assigns incrementing FrameSinkIds to
+// renderers, so the window service uses decrementing ids to avoid conflicts.
+constexpr ClientSpecificId kInitialClientIdDecrement =
+    std::numeric_limits<ClientSpecificId>::max();
 
 // Used for ids assigned by the client.
 using ClientWindowId = viz::FrameSinkId;
diff --git a/services/ui/ws2/test_change_tracker.cc b/services/ui/ws2/test_change_tracker.cc
index 9d3998a..d0d316be 100644
--- a/services/ui/ws2/test_change_tracker.cc
+++ b/services/ui/ws2/test_change_tracker.cc
@@ -19,7 +19,8 @@
 
 std::string WindowIdToString(Id id) {
   return (id == 0) ? "null"
-                   : base::StringPrintf("%d,%d", ClientIdFromTransportId(id),
+                   : base::StringPrintf("%" PRIu32 ",%" PRIu32,
+                                        ClientIdFromTransportId(id),
                                         ClientWindowIdFromTransportId(id));
 }
 
@@ -175,6 +176,11 @@
                                 WindowIdToString(change.window_id).c_str());
     case CHANGE_TYPE_DRAG_DROP_DONE:
       return "DragDropDone";
+    case CHANGE_TYPE_ON_PERFORM_DRAG_DROP_COMPLETED:
+      return base::StringPrintf(
+          "OnPerformDragDropCompleted id=%d success=%s action=%d",
+          change.change_id, change.bool_value ? "true" : "false",
+          change.drag_drop_action);
   }
   return std::string();
 }
@@ -558,6 +564,17 @@
   AddChange(change);
 }
 
+void TestChangeTracker::OnPerformDragDropCompleted(uint32_t change_id,
+                                                   bool success,
+                                                   uint32_t action_taken) {
+  Change change;
+  change.type = CHANGE_TYPE_ON_PERFORM_DRAG_DROP_COMPLETED;
+  change.change_id = change_id;
+  change.bool_value = success;
+  change.drag_drop_action = action_taken;
+  AddChange(change);
+}
+
 void TestChangeTracker::RequestClose(Id window_id) {
   Change change;
   change.type = CHANGE_TYPE_REQUEST_CLOSE;
diff --git a/services/ui/ws2/test_change_tracker.h b/services/ui/ws2/test_change_tracker.h
index 8cf1ca76..4410d81 100644
--- a/services/ui/ws2/test_change_tracker.h
+++ b/services/ui/ws2/test_change_tracker.h
@@ -54,6 +54,7 @@
   CHANGE_TYPE_DRAG_LEAVE,
   CHANGE_TYPE_COMPLETE_DROP,
   CHANGE_TYPE_DRAG_DROP_DONE,
+  CHANGE_TYPE_ON_PERFORM_DRAG_DROP_COMPLETED,
 };
 
 // TODO(sky): consider nuking and converting directly to WindowData.
@@ -111,6 +112,7 @@
   gfx::Point location1;
   gfx::PointF location2;
   base::flat_map<std::string, std::vector<uint8_t>> drag_data;
+  uint32_t drag_drop_action;
 };
 
 // The ChangeToDescription related functions convert a Change into a string.
@@ -226,6 +228,9 @@
   void OnDragLeave(Id widnow_id);
   void OnCompleteDrop(Id window_id);
   void OnDragDropDone();
+  void OnPerformDragDropCompleted(uint32_t change_id,
+                                  bool success,
+                                  uint32_t action_taken);
   void RequestClose(Id window_id);
 
  private:
diff --git a/services/ui/ws2/test_window_service_delegate.cc b/services/ui/ws2/test_window_service_delegate.cc
index 9a78f16..5bd4224 100644
--- a/services/ui/ws2/test_window_service_delegate.cc
+++ b/services/ui/ws2/test_window_service_delegate.cc
@@ -21,6 +21,11 @@
   return std::move(move_loop_callback_);
 }
 
+WindowServiceDelegate::DragDropCompletedCallback
+TestWindowServiceDelegate::TakeDragLoopCallback() {
+  return std::move(drag_loop_callback_);
+}
+
 std::unique_ptr<aura::Window> TestWindowServiceDelegate::NewTopLevel(
     aura::PropertyConverter* property_converter,
     const base::flat_map<std::string, std::vector<uint8_t>>& properties) {
@@ -52,5 +57,19 @@
   cancel_window_move_loop_called_ = true;
 }
 
+void TestWindowServiceDelegate::RunDragLoop(
+    aura::Window* window,
+    const ui::OSExchangeData& data,
+    const gfx::Point& screen_location,
+    uint32_t drag_operation,
+    ui::DragDropTypes::DragEventSource source,
+    DragDropCompletedCallback callback) {
+  drag_loop_callback_ = std::move(callback);
+}
+
+void TestWindowServiceDelegate::CancelDragLoop(aura::Window* window) {
+  cancel_drag_loop_called_ = true;
+}
+
 }  // namespace ws2
 }  // namespace ui
diff --git a/services/ui/ws2/test_window_service_delegate.h b/services/ui/ws2/test_window_service_delegate.h
index 2a4e1d1..0c28c04 100644
--- a/services/ui/ws2/test_window_service_delegate.h
+++ b/services/ui/ws2/test_window_service_delegate.h
@@ -43,6 +43,10 @@
 
   DoneCallback TakeMoveLoopCallback();
 
+  bool cancel_drag_loop_called() const { return cancel_drag_loop_called_; }
+
+  DragDropCompletedCallback TakeDragLoopCallback();
+
   // WindowServiceDelegate:
   std::unique_ptr<aura::Window> NewTopLevel(
       aura::PropertyConverter* property_converter,
@@ -54,6 +58,13 @@
                          const gfx::Point& cursor,
                          DoneCallback callback) override;
   void CancelWindowMoveLoop() override;
+  void RunDragLoop(aura::Window* window,
+                   const ui::OSExchangeData& data,
+                   const gfx::Point& screen_location,
+                   uint32_t drag_operation,
+                   ui::DragDropTypes::DragEventSource source,
+                   DragDropCompletedCallback callback) override;
+  void CancelDragLoop(aura::Window* window) override;
 
  private:
   aura::Window* top_level_parent_;
@@ -62,10 +73,14 @@
   // Callback supplied to RunWindowMoveLoop() is set here.
   DoneCallback move_loop_callback_;
 
+  // Callback supplied to RunDragLoop() is set here.
+  DragDropCompletedCallback drag_loop_callback_;
+
   // Events passed to OnUnhandledKeyEvent() are added here.
   std::vector<KeyEvent> unhandled_key_events_;
 
   bool cancel_window_move_loop_called_ = false;
+  bool cancel_drag_loop_called_ = false;
 
   DISALLOW_COPY_AND_ASSIGN(TestWindowServiceDelegate);
 };
diff --git a/services/ui/ws2/test_window_tree_client.cc b/services/ui/ws2/test_window_tree_client.cc
index 3f72fa20..1c9f063 100644
--- a/services/ui/ws2/test_window_tree_client.cc
+++ b/services/ui/ws2/test_window_tree_client.cc
@@ -278,7 +278,9 @@
 
 void TestWindowTreeClient::OnPerformDragDropCompleted(uint32_t change_id,
                                                       bool success,
-                                                      uint32_t action_taken) {}
+                                                      uint32_t action_taken) {
+  tracker_.OnPerformDragDropCompleted(change_id, success, action_taken);
+}
 
 void TestWindowTreeClient::OnDragDropDone() {
   tracker_.OnDragDropDone();
diff --git a/services/ui/ws2/window_service.cc b/services/ui/ws2/window_service.cc
index caa0f7e..6c14cc1 100644
--- a/services/ui/ws2/window_service.cc
+++ b/services/ui/ws2/window_service.cc
@@ -21,11 +21,15 @@
 WindowService::WindowService(
     WindowServiceDelegate* delegate,
     std::unique_ptr<GpuInterfaceProvider> gpu_interface_provider,
-    aura::client::FocusClient* focus_client)
+    aura::client::FocusClient* focus_client,
+    bool decrement_client_ids)
     : delegate_(delegate),
       gpu_interface_provider_(std::move(gpu_interface_provider)),
       screen_provider_(std::make_unique<ScreenProvider>()),
       focus_client_(focus_client),
+      next_client_id_(decrement_client_ids ? kInitialClientIdDecrement
+                                           : kInitialClientId),
+      decrement_client_ids_(decrement_client_ids),
       ime_registrar_(&ime_driver_) {
   DCHECK(focus_client);  // A |focus_client| must be provided.
   // MouseLocationManager is necessary for providing the shared memory with the
@@ -57,8 +61,10 @@
 
 std::unique_ptr<WindowTree> WindowService::CreateWindowTree(
     mojom::WindowTreeClient* window_tree_client) {
-  const ClientSpecificId client_id = next_client_id_++;
-  CHECK_NE(0u, next_client_id_);
+  const ClientSpecificId client_id =
+      decrement_client_ids_ ? next_client_id_-- : next_client_id_++;
+  CHECK_NE(kInvalidClientId, next_client_id_);
+  CHECK_NE(kWindowServerClientId, next_client_id_);
   auto window_tree =
       std::make_unique<WindowTree>(this, client_id, window_tree_client);
   window_trees_.insert(window_tree.get());
diff --git a/services/ui/ws2/window_service.h b/services/ui/ws2/window_service.h
index ad4ca14a..95303361 100644
--- a/services/ui/ws2/window_service.h
+++ b/services/ui/ws2/window_service.h
@@ -59,7 +59,8 @@
  public:
   WindowService(WindowServiceDelegate* delegate,
                 std::unique_ptr<GpuInterfaceProvider> gpu_support,
-                aura::client::FocusClient* focus_client);
+                aura::client::FocusClient* focus_client,
+                bool decrement_client_ids = false);
   ~WindowService() override;
 
   // Gets the ServerWindow for |window|, creating if necessary.
@@ -133,7 +134,10 @@
   std::unique_ptr<ClipboardHost> clipboard_host_;
 
   // Id for the next WindowTree.
-  ClientSpecificId next_client_id_ = kWindowServerClientId + 1;
+  ClientSpecificId next_client_id_;
+
+  // If true, client ids are decremented, not incremented; the default is false.
+  const bool decrement_client_ids_;
 
   // Id used for the next window created locally that is exposed to clients.
   ClientSpecificId next_window_id_ = 1;
diff --git a/services/ui/ws2/window_service_delegate.cc b/services/ui/ws2/window_service_delegate.cc
index dc1d947..d4a32aa5 100644
--- a/services/ui/ws2/window_service_delegate.cc
+++ b/services/ui/ws2/window_service_delegate.cc
@@ -19,5 +19,15 @@
   std::move(callback).Run(false);
 }
 
+void WindowServiceDelegate::RunDragLoop(
+    aura::Window* window,
+    const ui::OSExchangeData& data,
+    const gfx::Point& screen_location,
+    uint32_t drag_operation,
+    ui::DragDropTypes::DragEventSource source,
+    DragDropCompletedCallback callback) {
+  std::move(callback).Run(ui::DragDropTypes::DRAG_NONE);
+}
+
 }  // namespace ws2
 }  // namespace ui
diff --git a/services/ui/ws2/window_service_delegate.h b/services/ui/ws2/window_service_delegate.h
index cbf5329..67c2f9cb 100644
--- a/services/ui/ws2/window_service_delegate.h
+++ b/services/ui/ws2/window_service_delegate.h
@@ -16,6 +16,7 @@
 #include "base/containers/flat_map.h"
 #include "services/ui/public/interfaces/window_tree_constants.mojom.h"
 #include "ui/base/cursor/cursor.h"
+#include "ui/base/dragdrop/drag_drop_types.h"
 
 namespace aura {
 class PropertyConverter;
@@ -29,6 +30,7 @@
 namespace ui {
 
 class KeyEvent;
+class OSExchangeData;
 
 namespace ws2 {
 
@@ -68,6 +70,23 @@
   // RunWindowMoveLoop().
   virtual void CancelWindowMoveLoop() {}
 
+  // Called to run a drag loop for |window|. When done, |callback| should be
+  // invoked with the |drag_result|. |drag_result| == DRAG_NONE means drag
+  // failed or is canceled. Otherwise, it the final drag operation applied at
+  // the end. If a drag is not allowed, the delegate should run |callback|
+  // immediately. Note this call blocks until the drag operation is finished or
+  // canceled.
+  using DragDropCompletedCallback = base::OnceCallback<void(int drag_result)>;
+  virtual void RunDragLoop(aura::Window* window,
+                           const ui::OSExchangeData& data,
+                           const gfx::Point& screen_location,
+                           uint32_t drag_operation,
+                           ui::DragDropTypes::DragEventSource source,
+                           DragDropCompletedCallback callback);
+
+  // Called to cancel an in-progress drag loop that was started by RunDragLoop.
+  virtual void CancelDragLoop(aura::Window* window) {}
+
  protected:
   virtual ~WindowServiceDelegate() = default;
 };
diff --git a/services/ui/ws2/window_service_unittest.cc b/services/ui/ws2/window_service_unittest.cc
index 412a6a0..742dfb5 100644
--- a/services/ui/ws2/window_service_unittest.cc
+++ b/services/ui/ws2/window_service_unittest.cc
@@ -13,6 +13,8 @@
 #include "services/ui/public/interfaces/window_tree.mojom.h"
 #include "services/ui/ws2/gpu_interface_provider.h"
 #include "services/ui/ws2/window_service_test_setup.h"
+#include "services/ui/ws2/window_tree.h"
+#include "services/ui/ws2/window_tree_test_helper.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace ui {
@@ -53,5 +55,46 @@
   // ensure a DCHECK isn't hit in ~WindowTree.
 }
 
+// Test client ids assigned to window trees that connect to the window service.
+TEST(WindowServiceTest, ClientIds) {
+  // Use |test_setup| to configure aura and other state.
+  WindowServiceTestSetup test_setup;
+
+  // Create another WindowService.
+  TestWindowServiceDelegate test_window_service_delegate;
+  WindowService window_service(&test_window_service_delegate, nullptr,
+                               test_setup.focus_controller());
+
+  // The first window tree should have the initial client id.
+  auto tree = window_service.CreateWindowTree(nullptr);
+  EXPECT_EQ(kInitialClientId, WindowTreeTestHelper(tree.get()).client_id());
+
+  // The second window tree should have an incremented client id.
+  tree = window_service.CreateWindowTree(nullptr);
+  EXPECT_EQ(kInitialClientId + 1, WindowTreeTestHelper(tree.get()).client_id());
+}
+
+// Test client ids assigned to window trees in the decrementing mode.
+TEST(WindowServiceTest, ClientIdsDecrement) {
+  // Use |test_setup| to configure aura and other state.
+  WindowServiceTestSetup test_setup;
+
+  // Create another WindowService that decrements window ids.
+  const bool decrement = true;
+  TestWindowServiceDelegate test_window_service_delegate;
+  WindowService window_service(&test_window_service_delegate, nullptr,
+                               test_setup.focus_controller(), decrement);
+
+  // The first window tree should have the initial decrementing client id.
+  auto tree = window_service.CreateWindowTree(nullptr);
+  EXPECT_EQ(kInitialClientIdDecrement,
+            WindowTreeTestHelper(tree.get()).client_id());
+
+  // The second window tree should have a decremented client id.
+  tree = window_service.CreateWindowTree(nullptr);
+  EXPECT_EQ(kInitialClientIdDecrement - 1,
+            WindowTreeTestHelper(tree.get()).client_id());
+}
+
 }  // namespace ws2
 }  // namespace ui
diff --git a/services/ui/ws2/window_tree.cc b/services/ui/ws2/window_tree.cc
index cb8bd48..ec8d343e3 100644
--- a/services/ui/ws2/window_tree.cc
+++ b/services/ui/ws2/window_tree.cc
@@ -8,6 +8,7 @@
 
 #include "base/auto_reset.h"
 #include "base/bind.h"
+#include "base/threading/thread_task_runner_handle.h"
 #include "base/unguessable_token.h"
 #include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
 #include "components/viz/common/surfaces/surface_info.h"
@@ -25,16 +26,20 @@
 #include "services/ui/ws2/window_service_delegate.h"
 #include "ui/aura/client/transient_window_client.h"
 #include "ui/aura/env.h"
+#include "ui/aura/mus/os_exchange_data_provider_mus.h"
 #include "ui/aura/mus/property_converter.h"
 #include "ui/aura/mus/property_utils.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_observer.h"
 #include "ui/aura/window_tree_host.h"
 #include "ui/base/cursor/cursor.h"
+#include "ui/base/dragdrop/drag_drop_types.h"
+#include "ui/base/dragdrop/os_exchange_data.h"
 #include "ui/compositor/layer.h"
 #include "ui/compositor/layer_type.h"
 #include "ui/display/display.h"
 #include "ui/display/screen.h"
+#include "ui/gfx/image/image_skia.h"
 #include "ui/wm/core/capture_controller.h"
 
 namespace ui {
@@ -319,6 +324,53 @@
   window_tree_client_->OnChangeCompleted(change_id, result);
 }
 
+void WindowTree::DoPerformDragDrop(
+    uint32_t change_id,
+    Id source_window_id,
+    const gfx::Point& screen_location,
+    const base::flat_map<std::string, std::vector<uint8_t>>& drag_data,
+    const gfx::ImageSkia& drag_image,
+    const gfx::Vector2d& drag_image_offset,
+    uint32_t drag_operation,
+    ::ui::mojom::PointerKind source) {
+  if (pending_drag_source_window_id_ != source_window_id) {
+    // Pending drag is canceled before DoPerformDragDrop runs.
+    window_tree_client_->OnPerformDragDropCompleted(change_id, false,
+                                                    mojom::kDropEffectNone);
+    return;
+  }
+
+  aura::Window* source_window = GetWindowByTransportId(source_window_id);
+  if (!source_window) {
+    DVLOG(1) << "PerformDragDrop failed (no window)";
+    OnPerformDragDropDone(change_id, mojom::kDropEffectNone);
+    return;
+  }
+  if (!IsClientCreatedWindow(source_window)) {
+    DVLOG(1) << "PerformDragDrop failed (access denied)";
+    OnPerformDragDropDone(change_id, mojom::kDropEffectNone);
+    return;
+  }
+
+  ui::OSExchangeData data(std::make_unique<aura::OSExchangeDataProviderMus>(
+      mojo::FlatMapToMap(drag_data)));
+  data.provider().SetDragImage(drag_image, drag_image_offset);
+
+  window_service_->delegate()->RunDragLoop(
+      source_window, data, screen_location, drag_operation,
+      source == ::ui::mojom::PointerKind::MOUSE
+          ? ui::DragDropTypes::DRAG_EVENT_SOURCE_MOUSE
+          : ui::DragDropTypes::DRAG_EVENT_SOURCE_TOUCH,
+      base::BindOnce(&WindowTree::OnPerformDragDropDone,
+                     weak_factory_.GetWeakPtr(), change_id));
+}
+
+void WindowTree::OnPerformDragDropDone(uint32_t change_id, int drag_result) {
+  pending_drag_source_window_id_ = kInvalidTransportId;
+  window_tree_client_->OnPerformDragDropCompleted(
+      change_id, drag_result != ui::DragDropTypes::DRAG_NONE, drag_result);
+}
+
 aura::Window* WindowTree::AddClientCreatedWindow(
     const ClientWindowId& id,
     bool is_top_level,
@@ -763,11 +815,9 @@
   if (flags & mojom::kEmbedFlagEmbedderControlsVisibility)
     embedding->embedded_tree()->can_change_root_window_visibility_ = false;
   ServerWindow* server_window = ServerWindow::GetMayBeNull(window);
-  const ClientWindowId client_window_id = server_window->frame_sink_id();
   server_window->SetEmbedding(std::move(embedding));
   window_tree_client_->OnFrameSinkIdAllocated(
-      ClientWindowIdToTransportId(client_window_id),
-      server_window->frame_sink_id());
+      ClientWindowIdToTransportId(window_id), server_window->frame_sink_id());
   return true;
 }
 
@@ -1522,11 +1572,40 @@
     const gfx::Vector2d& drag_image_offset,
     uint32_t drag_operation,
     ::ui::mojom::PointerKind source) {
-  NOTIMPLEMENTED_LOG_ONCE();
+  if (pending_drag_source_window_id_ != kInvalidTransportId) {
+    DVLOG(1) << "PerformDragDrop failed (only one drag allowed)";
+    window_tree_client_->OnPerformDragDropCompleted(change_id, false,
+                                                    mojom::kDropEffectNone);
+    return;
+  }
+
+  pending_drag_source_window_id_ = source_window_id;
+
+  // Runs the drag loop as a posted task to unwind mojo call stack.
+  base::ThreadTaskRunnerHandle::Get()->PostTask(
+      FROM_HERE,
+      base::BindOnce(&WindowTree::DoPerformDragDrop, weak_factory_.GetWeakPtr(),
+                     change_id, source_window_id, screen_location, drag_data,
+                     drag_image, drag_image_offset, drag_operation, source));
 }
 
 void WindowTree::CancelDragDrop(Id window_id) {
-  NOTIMPLEMENTED_LOG_ONCE();
+  if (pending_drag_source_window_id_ == kInvalidTransportId) {
+    DVLOG(1) << "CancelDragDrop called and a drag is not underway";
+    return;
+  }
+
+  if (pending_drag_source_window_id_ != window_id) {
+    DVLOG(1) << "CancelDragDrop called with wrong window";
+    return;
+  }
+
+  // Clear |pending_drag_source_window_id_| to cancel posted drag loop task.
+  pending_drag_source_window_id_ = kInvalidTransportId;
+
+  // Cancel the current drag loop if it is running.
+  window_service_->delegate()->CancelDragLoop(
+      GetWindowByTransportId(window_id));
 }
 
 }  // namespace ws2
diff --git a/services/ui/ws2/window_tree.h b/services/ui/ws2/window_tree.h
index 42051ca6..fe59249 100644
--- a/services/ui/ws2/window_tree.h
+++ b/services/ui/ws2/window_tree.h
@@ -162,6 +162,23 @@
   // the move loop (true for success).
   void OnPerformWindowMoveDone(uint32_t change_id, bool result);
 
+  // Scheduled from PerformDragDrop to run drag loop with mojo stack unwinded.
+  void DoPerformDragDrop(
+      uint32_t change_id,
+      Id source_window_id,
+      const gfx::Point& screen_location,
+      const base::flat_map<std::string, std::vector<uint8_t>>& drag_data,
+      const gfx::ImageSkia& drag_image,
+      const gfx::Vector2d& drag_image_offset,
+      uint32_t drag_operation,
+      ::ui::mojom::PointerKind source);
+
+  // Callback from WindowServiceDelegate::RunDragLoop(). |change_id| is
+  // the id at the time the drag loop was initiated. |result| is the result of
+  // the drag (the final drag operation performed, or DRAG_NONE when the drag
+  // fails or gets canceled).
+  void OnPerformDragDropDone(uint32_t change_id, int drag_result);
+
   // Called for windows created by the client (including top-levels).
   aura::Window* AddClientCreatedWindow(
       const ClientWindowId& id,
@@ -449,6 +466,9 @@
   // Set while a window move loop is in progress.
   aura::Window* window_moving_ = nullptr;
 
+  // Set while a drag loop is in progress.
+  Id pending_drag_source_window_id_ = kInvalidTransportId;
+
   base::WeakPtrFactory<WindowTree> weak_factory_{this};
 
   DISALLOW_COPY_AND_ASSIGN(WindowTree);
diff --git a/services/ui/ws2/window_tree_client_unittest.cc b/services/ui/ws2/window_tree_client_unittest.cc
index 9ba3254..9de9e94 100644
--- a/services/ui/ws2/window_tree_client_unittest.cc
+++ b/services/ui/ws2/window_tree_client_unittest.cc
@@ -587,14 +587,14 @@
 
   Id root_window_id() const { return root_window_id_; }
 
-  int client_id_1() const { return client_id_1_; }
-  int client_id_2() const { return client_id_2_; }
-  int client_id_3() const { return client_id_3_; }
+  ClientSpecificId client_id_1() const { return client_id_1_; }
+  ClientSpecificId client_id_2() const { return client_id_2_; }
+  ClientSpecificId client_id_3() const { return client_id_3_; }
 
   void EstablishSecondClientWithRoot(Id root_id) {
     ASSERT_TRUE(wt_client2_.get() == nullptr);
     wt_client2_ = EstablishClientViaEmbed(wt1(), root_id);
-    ASSERT_GT(client_id_2_, 0);
+    ASSERT_GT(client_id_2_, 0u);
     ASSERT_TRUE(wt_client2_.get() != nullptr);
   }
 
@@ -716,9 +716,9 @@
 
  private:
   std::unique_ptr<WindowTreeClientFactory> client_factory_;
-  int client_id_1_ = kWindowServerClientId + 1;
-  int client_id_2_ = client_id_1_ + 1;
-  int client_id_3_ = client_id_2_ + 1;
+  const ClientSpecificId client_id_1_ = kWindowServerClientId + 1;
+  const ClientSpecificId client_id_2_ = client_id_1_ + 1;
+  const ClientSpecificId client_id_3_ = client_id_2_ + 1;
   Id root_window_id_;
   service_manager::BinderRegistry registry_;
 
@@ -1795,7 +1795,7 @@
 
 // Tests that when opacity is set on a window, that the calling client is not
 // notified, however children are. Also that setting the same opacity is
-// rejected and no on eis notifiyed.
+// rejected and no one is notified.
 TEST_F(WindowTreeClientTest2, DISABLED_SetOpacityNotifications) {
   Id window_1_1 = wt_client1()->NewWindow(1);
   ASSERT_TRUE(window_1_1);
diff --git a/services/ui/ws2/window_tree_test_helper.cc b/services/ui/ws2/window_tree_test_helper.cc
index a48a4f8..7ee157da 100644
--- a/services/ui/ws2/window_tree_test_helper.cc
+++ b/services/ui/ws2/window_tree_test_helper.cc
@@ -5,7 +5,6 @@
 #include "services/ui/ws2/window_tree_test_helper.h"
 
 #include "services/ui/ws2/server_window.h"
-#include "services/ui/ws2/window_tree.h"
 #include "services/ui/ws2/window_tree_binding.h"
 
 namespace ui {
diff --git a/services/ui/ws2/window_tree_test_helper.h b/services/ui/ws2/window_tree_test_helper.h
index d59ba88..ebc9602 100644
--- a/services/ui/ws2/window_tree_test_helper.h
+++ b/services/ui/ws2/window_tree_test_helper.h
@@ -14,6 +14,7 @@
 #include "services/ui/public/interfaces/window_tree.mojom.h"
 #include "services/ui/public/interfaces/window_tree_constants.mojom.h"
 #include "services/ui/ws2/ids.h"
+#include "services/ui/ws2/window_tree.h"
 #include "ui/gfx/geometry/rect.h"
 
 namespace aura {
@@ -35,7 +36,6 @@
 namespace ws2 {
 
 class Embedding;
-class WindowTree;
 
 // Used for accessing private members of WindowTree in tests.
 class WindowTreeTestHelper {
@@ -45,6 +45,8 @@
 
   mojom::WindowTree* window_tree();
 
+  ClientSpecificId client_id() const { return window_tree_->client_id_; }
+
   mojom::WindowDataPtr WindowToWindowData(aura::Window* window);
 
   aura::Window* NewWindow(
diff --git a/services/ui/ws2/window_tree_unittest.cc b/services/ui/ws2/window_tree_unittest.cc
index 9b95cd6b..cd5e394 100644
--- a/services/ui/ws2/window_tree_unittest.cc
+++ b/services/ui/ws2/window_tree_unittest.cc
@@ -1005,6 +1005,11 @@
   // OnFrameSinkIdAllocated() should called on the parent tree.
   ASSERT_EQ(1u, setup.changes()->size());
   EXPECT_EQ(CHANGE_TYPE_FRAME_SINK_ID_ALLOCATED, (*setup.changes())[0].type);
+  const Id embed_window_transport_id =
+      setup.window_tree_test_helper()->TransportIdForWindow(embed_window);
+  EXPECT_EQ(embed_window_transport_id, (*setup.changes())[0].window_id);
+  EXPECT_EQ(ServerWindow::GetMayBeNull(embed_window)->frame_sink_id(),
+            (*setup.changes())[0].frame_sink_id);
 }
 
 // Base class for ScheduleEmbed() related tests. This creates a Window and
@@ -1470,6 +1475,173 @@
             SingleChangeToDescription(*setup.changes()));
 }
 
+TEST(WindowTreeTest2, PerformDragDrop) {
+  WindowServiceTestSetup setup;
+  aura::Window* top_level =
+      setup.window_tree_test_helper()->NewTopLevelWindow();
+  ASSERT_TRUE(top_level);
+  top_level->Show();
+  const Id top_level_id =
+      setup.window_tree_test_helper()->TransportIdForWindow(top_level);
+  setup.changes()->clear();
+  setup.window_tree_test_helper()->window_tree()->PerformDragDrop(
+      12, top_level_id, gfx::Point(),
+      base::flat_map<std::string, std::vector<uint8_t>>(), gfx::ImageSkia(),
+      gfx::Vector2d(), 0, ::ui::mojom::PointerKind::MOUSE);
+
+  // Let the posted drag loop task run.
+  base::RunLoop().RunUntilIdle();
+
+  // WindowServiceDelegate should be asked to run the drag loop.
+  WindowServiceDelegate::DragDropCompletedCallback drag_loop_callback =
+      setup.delegate()->TakeDragLoopCallback();
+  ASSERT_TRUE(drag_loop_callback);
+
+  // As the drag is in progress, changes should be empty.
+  EXPECT_TRUE(setup.changes()->empty());
+
+  // Respond with a drop operation, client should be notified with success.
+  std::move(drag_loop_callback).Run(ui::DragDropTypes::DRAG_MOVE);
+  EXPECT_EQ("OnPerformDragDropCompleted id=12 success=true action=1",
+            SingleChangeToDescription(*setup.changes()));
+
+  // Starts another drag and but the drag is canceled this time.
+  setup.changes()->clear();
+  setup.window_tree_test_helper()->window_tree()->PerformDragDrop(
+      13, top_level_id, gfx::Point(),
+      base::flat_map<std::string, std::vector<uint8_t>>(), gfx::ImageSkia(),
+      gfx::Vector2d(), 0, ::ui::mojom::PointerKind::MOUSE);
+  base::RunLoop().RunUntilIdle();
+  drag_loop_callback = setup.delegate()->TakeDragLoopCallback();
+  ASSERT_TRUE(drag_loop_callback);
+
+  std::move(drag_loop_callback).Run(ui::DragDropTypes::DRAG_NONE);
+  EXPECT_EQ("OnPerformDragDropCompleted id=13 success=false action=0",
+            SingleChangeToDescription(*setup.changes()));
+}
+
+TEST(WindowTreeTest2, PerformDragDropBeforePreviousOneFinish) {
+  WindowServiceTestSetup setup;
+  aura::Window* top_level =
+      setup.window_tree_test_helper()->NewTopLevelWindow();
+  ASSERT_TRUE(top_level);
+  top_level->Show();
+  const Id top_level_id =
+      setup.window_tree_test_helper()->TransportIdForWindow(top_level);
+  setup.changes()->clear();
+  setup.window_tree_test_helper()->window_tree()->PerformDragDrop(
+      12, top_level_id, gfx::Point(),
+      base::flat_map<std::string, std::vector<uint8_t>>(), gfx::ImageSkia(),
+      gfx::Vector2d(), 0, ::ui::mojom::PointerKind::MOUSE);
+
+  // PerformDragDrop before the drag loop task runs should fail.
+  setup.window_tree_test_helper()->window_tree()->PerformDragDrop(
+      13, top_level_id, gfx::Point(),
+      base::flat_map<std::string, std::vector<uint8_t>>(), gfx::ImageSkia(),
+      gfx::Vector2d(), 0, ::ui::mojom::PointerKind::MOUSE);
+  EXPECT_EQ("OnPerformDragDropCompleted id=13 success=false action=0",
+            SingleChangeToDescription(*setup.changes()));
+
+  // Let the posted drag loop task run.
+  base::RunLoop().RunUntilIdle();
+
+  // WindowServiceDelegate should be asked to run the drag loop.
+  WindowServiceDelegate::DragDropCompletedCallback drag_loop_callback =
+      setup.delegate()->TakeDragLoopCallback();
+  ASSERT_TRUE(drag_loop_callback);
+
+  // PerformDragDrop after the drop loop task runs should fail too because
+  // the drag is not finished.
+  setup.changes()->clear();
+  setup.window_tree_test_helper()->window_tree()->PerformDragDrop(
+      14, top_level_id, gfx::Point(),
+      base::flat_map<std::string, std::vector<uint8_t>>(), gfx::ImageSkia(),
+      gfx::Vector2d(), 0, ::ui::mojom::PointerKind::MOUSE);
+  EXPECT_EQ("OnPerformDragDropCompleted id=14 success=false action=0",
+            SingleChangeToDescription(*setup.changes()));
+
+  // Finish the drop operation, client should be notified with success.
+  setup.changes()->clear();
+  std::move(drag_loop_callback).Run(ui::DragDropTypes::DRAG_MOVE);
+  EXPECT_EQ("OnPerformDragDropCompleted id=12 success=true action=1",
+            SingleChangeToDescription(*setup.changes()));
+}
+
+TEST(WindowTreeTest2, CancelDragDrop) {
+  WindowServiceTestSetup setup;
+  aura::Window* top_level =
+      setup.window_tree_test_helper()->NewTopLevelWindow();
+  ASSERT_TRUE(top_level);
+  top_level->Show();
+  const Id top_level_id =
+      setup.window_tree_test_helper()->TransportIdForWindow(top_level);
+  setup.changes()->clear();
+  setup.window_tree_test_helper()->window_tree()->PerformDragDrop(
+      12, top_level_id, gfx::Point(),
+      base::flat_map<std::string, std::vector<uint8_t>>(), gfx::ImageSkia(),
+      gfx::Vector2d(), 0, ::ui::mojom::PointerKind::MOUSE);
+
+  // Let the posted drag loop task run.
+  base::RunLoop().RunUntilIdle();
+
+  // WindowServiceDelegate should be asked to run the drag loop.
+  WindowServiceDelegate::DragDropCompletedCallback drag_loop_callback =
+      setup.delegate()->TakeDragLoopCallback();
+  ASSERT_TRUE(drag_loop_callback);
+
+  // Cancelling with an invalid id should do nothing.
+  EXPECT_FALSE(setup.delegate()->cancel_drag_loop_called());
+  setup.window_tree_test_helper()->window_tree()->CancelDragDrop(
+      kInvalidTransportId);
+  EXPECT_TRUE(setup.changes()->empty());
+  EXPECT_FALSE(setup.delegate()->cancel_drag_loop_called());
+
+  // Cancel with the real id should notify the delegate.
+  EXPECT_FALSE(setup.delegate()->cancel_drag_loop_called());
+  setup.window_tree_test_helper()->window_tree()->CancelDragDrop(top_level_id);
+  EXPECT_TRUE(setup.delegate()->cancel_drag_loop_called());
+
+  // No changes yet because the |drag_loop_callback| has not run.
+  EXPECT_TRUE(setup.changes()->empty());
+
+  // Run the closure to simulate drag cancel.
+  std::move(drag_loop_callback).Run(ui::DragDropTypes::DRAG_NONE);
+  EXPECT_EQ("OnPerformDragDropCompleted id=12 success=false action=0",
+            SingleChangeToDescription(*setup.changes()));
+}
+
+TEST(WindowTreeTest2, CancelDragDropBeforeDragLoopRun) {
+  WindowServiceTestSetup setup;
+  aura::Window* top_level =
+      setup.window_tree_test_helper()->NewTopLevelWindow();
+  ASSERT_TRUE(top_level);
+  top_level->Show();
+  const Id top_level_id =
+      setup.window_tree_test_helper()->TransportIdForWindow(top_level);
+  setup.changes()->clear();
+  setup.window_tree_test_helper()->window_tree()->PerformDragDrop(
+      12, top_level_id, gfx::Point(),
+      base::flat_map<std::string, std::vector<uint8_t>>(), gfx::ImageSkia(),
+      gfx::Vector2d(), 0, ::ui::mojom::PointerKind::MOUSE);
+
+  // Cancel the drag before the drag loop task runs.
+  EXPECT_FALSE(setup.delegate()->cancel_drag_loop_called());
+  setup.window_tree_test_helper()->window_tree()->CancelDragDrop(top_level_id);
+  EXPECT_TRUE(setup.delegate()->cancel_drag_loop_called());
+
+  // Let the posted drag loop task run.
+  base::RunLoop().RunUntilIdle();
+
+  // WindowServiceDelegate should not be notified.
+  WindowServiceDelegate::DragDropCompletedCallback drag_loop_callback =
+      setup.delegate()->TakeDragLoopCallback();
+  EXPECT_FALSE(drag_loop_callback);
+
+  // The request should fail.
+  EXPECT_EQ("OnPerformDragDropCompleted id=12 success=false action=0",
+            SingleChangeToDescription(*setup.changes()));
+}
+
 }  // namespace
 }  // namespace ws2
 }  // namespace ui
diff --git a/styleguide/c++/blink-c++.md b/styleguide/c++/blink-c++.md
index 25653fe0..4d7f765 100644
--- a/styleguide/c++/blink-c++.md
+++ b/styleguide/c++/blink-c++.md
@@ -47,13 +47,10 @@
 }
 ```
 
-## Prefer WTF types over STL types
+## Prefer WTF types over STL and base types
 
-Outside of `//third_party/blink/common`, Blink should use WTF types. STL string
-and container types should only be used at the boundary to interoperate with
-'//base', `//third_party/blink/common`, and other Chromium-side code.
-Similarly, Blink should prefer `KURL` over `GURL` and `SecurityOrigin` over
-`url::Origin`.
+See [Blink readme](../../third_party/blink/renderer/README.md#Type-dependencies)
+for more details on Blink directories and their type usage.
 
 **Good:**
 ```c++
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index e1836e4..ff8aac4 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -423,17 +423,6 @@
       },
       {
         "args": [
-          "--enable-surface-synchronization"
-        ],
-        "name": "surface_sync_content_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 2
-        },
-        "test": "content_browsertests"
-      },
-      {
-        "args": [
           "--enable-features=VizDisplayCompositor",
           "--test-launcher-filter-file=../../testing/buildbot/filters/viz.content_browsertests.filter"
         ],
@@ -547,16 +536,6 @@
         "test": "interactive_ui_tests"
       },
       {
-        "args": [
-          "--enable-features=VizDisplayCompositor"
-        ],
-        "name": "viz_interactive_ui_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "interactive_ui_tests"
-      },
-      {
         "swarming": {
           "can_use_on_swarming_builders": true
         },
@@ -1285,17 +1264,6 @@
     "gtest_tests": [
       {
         "args": [
-          "--enable-surface-synchronization"
-        ],
-        "name": "surface_sync_browser_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 10
-        },
-        "test": "browser_tests"
-      },
-      {
-        "args": [
           "--enable-features=VizDisplayCompositor",
           "--test-launcher-filter-file=../../testing/buildbot/filters/viz.browser_tests.filter"
         ],
@@ -1308,17 +1276,6 @@
       },
       {
         "args": [
-          "--enable-surface-synchronization"
-        ],
-        "name": "surface_sync_content_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 2
-        },
-        "test": "content_browsertests"
-      },
-      {
-        "args": [
           "--enable-features=VizDisplayCompositor",
           "--test-launcher-filter-file=../../testing/buildbot/filters/viz.content_browsertests.filter"
         ],
@@ -1760,17 +1717,6 @@
       },
       {
         "args": [
-          "--enable-surface-synchronization"
-        ],
-        "name": "surface_sync_browser_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 10
-        },
-        "test": "browser_tests"
-      },
-      {
-        "args": [
           "--enable-features=VizDisplayCompositor",
           "--test-launcher-filter-file=../../testing/buildbot/filters/viz.browser_tests.filter"
         ],
@@ -1789,17 +1735,6 @@
       },
       {
         "args": [
-          "--enable-surface-synchronization"
-        ],
-        "name": "surface_sync_content_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 2
-        },
-        "test": "content_browsertests"
-      },
-      {
-        "args": [
           "--enable-features=VizDisplayCompositor",
           "--test-launcher-filter-file=../../testing/buildbot/filters/viz.content_browsertests.filter"
         ],
@@ -1950,17 +1885,6 @@
       },
       {
         "args": [
-          "--enable-surface-synchronization"
-        ],
-        "name": "surface_sync_browser_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 10
-        },
-        "test": "browser_tests"
-      },
-      {
-        "args": [
           "--enable-features=VizDisplayCompositor",
           "--test-launcher-filter-file=../../testing/buildbot/filters/viz.browser_tests.filter"
         ],
@@ -1995,17 +1919,6 @@
       },
       {
         "args": [
-          "--enable-surface-synchronization"
-        ],
-        "name": "surface_sync_content_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 2
-        },
-        "test": "content_browsertests"
-      },
-      {
-        "args": [
           "--enable-features=VizDisplayCompositor",
           "--test-launcher-filter-file=../../testing/buildbot/filters/viz.content_browsertests.filter"
         ],
@@ -3531,17 +3444,6 @@
       },
       {
         "args": [
-          "--enable-surface-synchronization"
-        ],
-        "name": "surface_sync_content_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 2
-        },
-        "test": "content_browsertests"
-      },
-      {
-        "args": [
           "--enable-features=VizDisplayCompositor",
           "--test-launcher-filter-file=../../testing/buildbot/filters/viz.content_browsertests.filter"
         ],
@@ -3655,16 +3557,6 @@
         "test": "interactive_ui_tests"
       },
       {
-        "args": [
-          "--enable-features=VizDisplayCompositor"
-        ],
-        "name": "viz_interactive_ui_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "interactive_ui_tests"
-      },
-      {
         "swarming": {
           "can_use_on_swarming_builders": true
         },
@@ -7214,18 +7106,6 @@
       },
       {
         "args": [
-          "--enable-surface-synchronization",
-          "--enable-features=ViewsBrowserWindows"
-        ],
-        "name": "surface_sync_content_browsertests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "shards": 2
-        },
-        "test": "content_browsertests"
-      },
-      {
-        "args": [
           "--enable-features=VizDisplayCompositor,ViewsBrowserWindows",
           "--test-launcher-filter-file=../../testing/buildbot/filters/viz.content_browsertests.filter"
         ],
@@ -7385,16 +7265,6 @@
       },
       {
         "args": [
-          "--enable-features=VizDisplayCompositor,ViewsBrowserWindows"
-        ],
-        "name": "viz_interactive_ui_tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true
-        },
-        "test": "interactive_ui_tests"
-      },
-      {
-        "args": [
           "--enable-features=ViewsBrowserWindows"
         ],
         "swarming": {
diff --git a/testing/buildbot/chromium.gpu.fyi.json b/testing/buildbot/chromium.gpu.fyi.json
index 0f67c6139..d2da6e7 100644
--- a/testing/buildbot/chromium.gpu.fyi.json
+++ b/testing/buildbot/chromium.gpu.fyi.json
@@ -96,6 +96,101 @@
       }
     ]
   },
+  "Android FYI 32 Vk Release (Pixel 2)": {
+    "gtest_tests": [
+      {
+        "args": [
+          "--gs-results-bucket=chromium-result-details",
+          "--recover-devices"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "device_os": "P",
+              "device_type": "walleye",
+              "os": "Android",
+              "pool": "Chrome-GPU"
+            }
+          ],
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ]
+        },
+        "test": "angle_end2end_tests"
+      },
+      {
+        "args": [
+          "--gs-results-bucket=chromium-result-details",
+          "--recover-devices"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "device_os": "P",
+              "device_type": "walleye",
+              "os": "Android",
+              "pool": "Chrome-GPU"
+            }
+          ],
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ]
+        },
+        "test": "angle_unittests"
+      }
+    ],
+    "isolated_scripts": [
+      {
+        "args": [
+          "-v",
+          "--one-frame-only"
+        ],
+        "isolate_name": "angle_perftests",
+        "name": "angle_perftests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_os": "P",
+              "device_type": "walleye",
+              "os": "Android",
+              "pool": "Chrome-GPU"
+            }
+          ]
+        }
+      }
+    ]
+  },
   "Android FYI 32 dEQP Vk Release (Nexus 5X)": {
     "gtest_tests": [
       {
@@ -140,6 +235,50 @@
       }
     ]
   },
+  "Android FYI 32 dEQP Vk Release (Pixel 2)": {
+    "gtest_tests": [
+      {
+        "args": [
+          "--deqp-egl-display-type=angle-vulkan",
+          "--enable-xml-result-parsing",
+          "--shard-timeout=500",
+          "--gs-results-bucket=chromium-result-details",
+          "--recover-devices"
+        ],
+        "name": "angle_deqp_gles2_vulkan_tests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "device_os": "P",
+              "device_type": "walleye",
+              "os": "Android",
+              "pool": "Chrome-GPU"
+            }
+          ],
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ],
+          "shards": 4
+        },
+        "test": "angle_deqp_gles2_tests"
+      }
+    ]
+  },
   "Android FYI 64 Vk Release (Nexus 5X)": {
     "gtest_tests": [
       {
@@ -235,6 +374,101 @@
       }
     ]
   },
+  "Android FYI 64 Vk Release (Pixel 2)": {
+    "gtest_tests": [
+      {
+        "args": [
+          "--gs-results-bucket=chromium-result-details",
+          "--recover-devices"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "device_os": "P",
+              "device_type": "walleye",
+              "os": "Android",
+              "pool": "Chrome-GPU"
+            }
+          ],
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ]
+        },
+        "test": "angle_end2end_tests"
+      },
+      {
+        "args": [
+          "--gs-results-bucket=chromium-result-details",
+          "--recover-devices"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "device_os": "P",
+              "device_type": "walleye",
+              "os": "Android",
+              "pool": "Chrome-GPU"
+            }
+          ],
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ]
+        },
+        "test": "angle_unittests"
+      }
+    ],
+    "isolated_scripts": [
+      {
+        "args": [
+          "-v",
+          "--one-frame-only"
+        ],
+        "isolate_name": "angle_perftests",
+        "name": "angle_perftests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_os": "P",
+              "device_type": "walleye",
+              "os": "Android",
+              "pool": "Chrome-GPU"
+            }
+          ]
+        }
+      }
+    ]
+  },
   "Android FYI 64 dEQP Vk Release (Nexus 5X)": {
     "gtest_tests": [
       {
@@ -279,6 +513,50 @@
       }
     ]
   },
+  "Android FYI 64 dEQP Vk Release (Pixel 2)": {
+    "gtest_tests": [
+      {
+        "args": [
+          "--deqp-egl-display-type=angle-vulkan",
+          "--enable-xml-result-parsing",
+          "--shard-timeout=500",
+          "--gs-results-bucket=chromium-result-details",
+          "--recover-devices"
+        ],
+        "name": "angle_deqp_gles2_vulkan_tests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "device_os": "P",
+              "device_type": "walleye",
+              "os": "Android",
+              "pool": "Chrome-GPU"
+            }
+          ],
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ],
+          "shards": 4
+        },
+        "test": "angle_deqp_gles2_tests"
+      }
+    ]
+  },
   "Android FYI Release (NVIDIA Shield TV)": {
     "gtest_tests": [
       {
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl
index 424e775..7dfdb7d 100644
--- a/testing/buildbot/test_suites.pyl
+++ b/testing/buildbot/test_suites.pyl
@@ -2187,24 +2187,6 @@
   },
 
   'viz_fyi_gtests': {
-    'surface_sync_browser_tests': {
-      'args': [
-        '--enable-surface-synchronization',
-      ],
-      'swarming': {
-        'shards': 10,
-      },
-      'test': 'browser_tests',
-    },
-    'surface_sync_content_browsertests': {
-      'args': [
-        '--enable-surface-synchronization',
-      ],
-      'swarming': {
-        'shards': 2,
-      },
-      'test': 'content_browsertests',
-    },
     'viz_browser_tests': {
       'args': [
         '--enable-features=VizDisplayCompositor',
@@ -2481,16 +2463,6 @@
     'telemetry_perf_unittests_isolated_scripts',
   ],
 
-  'chromium_mac_fyi_gtests': [
-    'chromium_gtests',
-    'chromium_gtests_for_devices_with_graphical_output',
-    'mac_specific_chromium_gtests',
-    'non_android_chromium_gtests',
-    'non_android_and_cast_and_chromeos_chromium_gtests',
-    'non_linux_chromium_gtests',
-    'viz_fyi_gtests',
-  ],
-
   'chromium_mac_gtests': [
     'chromium_gtests',
     'chromium_gtests_for_devices_with_graphical_output',
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl
index 784be8e..4a35de7 100644
--- a/testing/buildbot/waterfalls.pyl
+++ b/testing/buildbot/waterfalls.pyl
@@ -1044,6 +1044,24 @@
           'isolated_scripts': 'gpu_fyi_and_optional_isolated_scripts',
         },
       },
+      'Android FYI 32 Vk Release (Pixel 2)': {
+        'os_type': 'android',
+        'skip_merge_script': True,
+        'swarming': {
+          'dimension_sets': [
+            {
+              'device_type': 'walleye',
+              'device_os': 'P',
+              'os': 'Android',
+              'pool': 'Chrome-GPU',
+            },
+          ],
+        },
+        'test_suites': {
+          'gtest_tests': 'gpu_angle_gtests',
+          'isolated_scripts': 'gpu_fyi_and_optional_isolated_scripts',
+        },
+      },
       'Android FYI 32 dEQP Vk Release (Nexus 5X)': {
         'os_type': 'android',
         'skip_merge_script': True,
@@ -1061,6 +1079,23 @@
           'gtest_tests': 'gpu_angle_deqp_gles2_vulkan_tests',
         },
       },
+      'Android FYI 32 dEQP Vk Release (Pixel 2)': {
+        'os_type': 'android',
+        'skip_merge_script': True,
+        'swarming': {
+          'dimension_sets': [
+            {
+              'device_type': 'walleye',
+              'device_os': 'P',
+              'os': 'Android',
+              'pool': 'Chrome-GPU',
+            },
+          ],
+        },
+        'test_suites': {
+          'gtest_tests': 'gpu_angle_deqp_gles2_vulkan_tests',
+        },
+      },
       'Android FYI 64 Vk Release (Nexus 5X)': {
         'os_type': 'android',
         'skip_merge_script': True,
@@ -1079,6 +1114,24 @@
           'isolated_scripts': 'gpu_fyi_and_optional_isolated_scripts',
         },
       },
+      'Android FYI 64 Vk Release (Pixel 2)': {
+        'os_type': 'android',
+        'skip_merge_script': True,
+        'swarming': {
+          'dimension_sets': [
+            {
+              'device_type': 'walleye',
+              'device_os': 'P',
+              'os': 'Android',
+              'pool': 'Chrome-GPU',
+            },
+          ],
+        },
+        'test_suites': {
+          'gtest_tests': 'gpu_angle_gtests',
+          'isolated_scripts': 'gpu_fyi_and_optional_isolated_scripts',
+        },
+      },
       'Android FYI 64 dEQP Vk Release (Nexus 5X)': {
         'os_type': 'android',
         'skip_merge_script': True,
@@ -1096,6 +1149,23 @@
           'gtest_tests': 'gpu_angle_deqp_gles2_vulkan_tests',
         },
       },
+      'Android FYI 64 dEQP Vk Release (Pixel 2)': {
+        'os_type': 'android',
+        'skip_merge_script': True,
+        'swarming': {
+          'dimension_sets': [
+            {
+              'device_type': 'walleye',
+              'device_os': 'P',
+              'os': 'Android',
+              'pool': 'Chrome-GPU',
+            },
+          ],
+        },
+        'test_suites': {
+          'gtest_tests': 'gpu_angle_deqp_gles2_vulkan_tests',
+        },
+      },
       'Android FYI Release (NVIDIA Shield TV)': {
         'browser_config': 'android-chromium',
         'os_type': 'android',
@@ -2042,7 +2112,7 @@
       },
       'Chromium Mac 10.13': {
         'test_suites': {
-          'gtest_tests': 'chromium_mac_fyi_gtests',
+          'gtest_tests': 'chromium_mac_gtests',
           'isolated_scripts': 'chromium_rel_isolated_scripts',
         },
       },
@@ -2369,7 +2439,7 @@
       },
       'mac-views-rel': {
         'test_suites': {
-          'gtest_tests': 'chromium_mac_fyi_gtests',
+          'gtest_tests': 'chromium_mac_gtests',
         },
         'args': [
           '--enable-features=ViewsBrowserWindows',
@@ -2441,7 +2511,7 @@
       },
       'Out of Process Profiling Mac': {
         'test_suites': {
-          'gtest_tests': 'chromium_mac_fyi_gtests',
+          'gtest_tests': 'chromium_mac_gtests',
           'isolated_scripts': 'chromium_rel_isolated_scripts',
         },
       },
diff --git a/testing/scripts/run_isolated_script_test.py b/testing/scripts/run_isolated_script_test.py
index 1733bfc..480c401 100755
--- a/testing/scripts/run_isolated_script_test.py
+++ b/testing/scripts/run_isolated_script_test.py
@@ -46,6 +46,12 @@
 import xvfb
 
 
+# Known typ test runners this script wraps. They need a different argument name
+# when selecting which tests to run.
+# TODO(dpranke): Detect if the wrapped test suite uses typ better.
+KNOWN_TYP_TEST_RUNNERS = ['run_blinkpy_tests.py', 'metrics_python_tests.py']
+
+
 def main():
   parser = argparse.ArgumentParser()
   parser.add_argument('--isolated-script-test-output', type=str,
@@ -73,10 +79,13 @@
       temp_filter_file = tempfile.NamedTemporaryFile(mode='w', delete=False)
       temp_filter_file.write('\n'.join(filter_list))
       temp_filter_file.close()
+
       arg_name = 'test-list'
       for arg in rest_args:
-        if 'run_blinkpy_tests.py' in arg:
-          arg_name = 'file-list'
+        for runner in KNOWN_TYP_TEST_RUNNERS:
+          if runner in arg:
+            arg_name = 'file-list'
+
       cmd += ['--%s=' % arg_name + temp_filter_file.name]
     if args.xvfb:
       return xvfb.run_executable(cmd, env)
diff --git a/testing/scripts/run_telemetry_as_googletest.py b/testing/scripts/run_telemetry_as_googletest.py
index d561357..1bd713434 100755
--- a/testing/scripts/run_telemetry_as_googletest.py
+++ b/testing/scripts/run_telemetry_as_googletest.py
@@ -66,7 +66,8 @@
     # This harness takes the test names to run as the first arguments.
     # The first argument of rest_args is the script to run, so insert
     # the test names after that.
-    rest_args = [rest_args[0]] + filter_list + rest_args[1:]
+    rest_args = ([rest_args[0]] + filter_list + '--exact-test-filter' +
+                 rest_args[1:])
 
   # Compatibility with gtest-based sharding.
   total_shards = None
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index f3e3151..c68e0b7 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -3755,18 +3755,24 @@
             ],
             "experiments": [
                 {
-                    "name": "Enabled",
+                    "name": "Enabled_NoScrollToLoad",
                     "enable_features": [
                         "SimplifiedNTP"
+                    ],
+                    "disable_features": [
+                        "ContentSuggestionsScrollToLoad"
                     ]
                 },
                 {
-                    "name": "Enabled_Ablation",
+                    "name": "Enabled_Ablation_NoScrollToLoad",
                     "params": {
                         "simplified_ntp_ablation": "true"
                     },
                     "enable_features": [
                         "SimplifiedNTP"
+                    ],
+                    "disable_features": [
+                        "ContentSuggestionsScrollToLoad"
                     ]
                 }
             ]
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/site-per-process b/third_party/WebKit/LayoutTests/FlagExpectations/site-per-process
index de2ed218..561a240 100644
--- a/third_party/WebKit/LayoutTests/FlagExpectations/site-per-process
+++ b/third_party/WebKit/LayoutTests/FlagExpectations/site-per-process
@@ -210,6 +210,45 @@
 crbug.com/834185 http/tests/fetch/workers/thorough/redirect-password-base-https-other-https.html [ Pass Timeout ]
 crbug.com/834185 http/tests/fetch/workers/thorough/scheme-blob-base-https-other-https.html [ Pass Timeout ]
 crbug.com/834185 http/tests/fetch/workers/thorough/scheme-data-base-https-other-https.html [ Pass Timeout ]
+crbug.com/854630 virtual/outofblink-cors/http/tests/fetch/serviceworker/thorough/access-control-base-https-other-https.html [ Pass Timeout ]
+crbug.com/854630 virtual/outofblink-cors/http/tests/fetch/serviceworker/thorough/auth-base-https-other-https.html [ Pass Timeout ]
+crbug.com/854630 virtual/outofblink-cors/http/tests/fetch/serviceworker/thorough/auth-nocors-base-https-other-https.html [ Pass Timeout ]
+crbug.com/854630 virtual/outofblink-cors/http/tests/fetch/serviceworker/thorough/cookie-base-https-other-https.html [ Pass Timeout ]
+crbug.com/854630 virtual/outofblink-cors/http/tests/fetch/serviceworker/thorough/cookie-nocors-base-https-other-https.html [ Pass Timeout ]
+crbug.com/854630 virtual/outofblink-cors/http/tests/fetch/serviceworker/thorough/cors-base-https-other-https.html [ Pass Timeout ]
+crbug.com/854630 virtual/outofblink-cors/http/tests/fetch/serviceworker/thorough/cors-preflight-base-https-other-https.html [ Pass Timeout ]
+crbug.com/854630 virtual/outofblink-cors/http/tests/fetch/serviceworker/thorough/cors-preflight2-base-https-other-https.html [ Pass Timeout ]
+crbug.com/854630 virtual/outofblink-cors/http/tests/fetch/serviceworker/thorough/nocors-base-https-other-https.html [ Pass Timeout ]
+crbug.com/854630 virtual/outofblink-cors/http/tests/fetch/serviceworker/thorough/redirect-nocors-base-https-other-https.html [ Pass Timeout ]
+crbug.com/854630 virtual/outofblink-cors/http/tests/fetch/serviceworker/thorough/redirect-password-base-https-other-https.html [ Pass Timeout ]
+crbug.com/854630 virtual/outofblink-cors/http/tests/fetch/serviceworker/thorough/scheme-blob-base-https-other-https.html [ Pass Timeout ]
+crbug.com/854630 virtual/outofblink-cors/http/tests/fetch/serviceworker/thorough/scheme-data-base-https-other-https.html [ Pass Timeout ]
+crbug.com/854630 virtual/outofblink-cors/http/tests/fetch/window/thorough/access-control-base-https-other-https.html [ Pass Timeout ]
+crbug.com/854630 virtual/outofblink-cors/http/tests/fetch/window/thorough/auth-base-https-other-https.html [ Pass Timeout ]
+crbug.com/854630 virtual/outofblink-cors/http/tests/fetch/window/thorough/auth-nocors-base-https-other-https.html [ Pass Timeout ]
+crbug.com/854630 virtual/outofblink-cors/http/tests/fetch/window/thorough/cookie-base-https-other-https.html [ Pass Timeout ]
+crbug.com/854630 virtual/outofblink-cors/http/tests/fetch/window/thorough/cookie-nocors-base-https-other-https.html [ Pass Timeout ]
+crbug.com/854630 virtual/outofblink-cors/http/tests/fetch/window/thorough/cors-base-https-other-https.html [ Pass Timeout ]
+crbug.com/854630 virtual/outofblink-cors/http/tests/fetch/window/thorough/cors-preflight-base-https-other-https.html [ Pass Timeout ]
+crbug.com/854630 virtual/outofblink-cors/http/tests/fetch/window/thorough/cors-preflight2-base-https-other-https.html [ Pass Timeout ]
+crbug.com/854630 virtual/outofblink-cors/http/tests/fetch/window/thorough/nocors-base-https-other-https.html [ Pass Timeout ]
+crbug.com/854630 virtual/outofblink-cors/http/tests/fetch/window/thorough/redirect-nocors-base-https-other-https.html [ Pass Timeout ]
+crbug.com/854630 virtual/outofblink-cors/http/tests/fetch/window/thorough/redirect-password-base-https-other-https.html [ Pass Timeout ]
+crbug.com/854630 virtual/outofblink-cors/http/tests/fetch/window/thorough/scheme-blob-base-https-other-https.html [ Pass Timeout ]
+crbug.com/854630 virtual/outofblink-cors/http/tests/fetch/window/thorough/scheme-data-base-https-other-https.html [ Pass Timeout ]
+crbug.com/854630 virtual/outofblink-cors/http/tests/fetch/workers/thorough/access-control-base-https-other-https.html [ Pass Timeout ]
+crbug.com/854630 virtual/outofblink-cors/http/tests/fetch/workers/thorough/auth-base-https-other-https.html [ Pass Timeout ]
+crbug.com/854630 virtual/outofblink-cors/http/tests/fetch/workers/thorough/auth-nocors-base-https-other-https.html [ Pass Timeout ]
+crbug.com/854630 virtual/outofblink-cors/http/tests/fetch/workers/thorough/cookie-base-https-other-https.html [ Pass Timeout ]
+crbug.com/854630 virtual/outofblink-cors/http/tests/fetch/workers/thorough/cookie-nocors-base-https-other-https.html [ Pass Timeout ]
+crbug.com/854630 virtual/outofblink-cors/http/tests/fetch/workers/thorough/cors-base-https-other-https.html [ Pass Timeout ]
+crbug.com/854630 virtual/outofblink-cors/http/tests/fetch/workers/thorough/cors-preflight-base-https-other-https.html [ Pass Timeout ]
+crbug.com/854630 virtual/outofblink-cors/http/tests/fetch/workers/thorough/cors-preflight2-base-https-other-https.html [ Pass Timeout ]
+crbug.com/854630 virtual/outofblink-cors/http/tests/fetch/workers/thorough/nocors-base-https-other-https.html [ Pass Timeout ]
+crbug.com/854630 virtual/outofblink-cors/http/tests/fetch/workers/thorough/redirect-nocors-base-https-other-https.html [ Pass Timeout ]
+crbug.com/854630 virtual/outofblink-cors/http/tests/fetch/workers/thorough/redirect-password-base-https-other-https.html [ Pass Timeout ]
+crbug.com/854630 virtual/outofblink-cors/http/tests/fetch/workers/thorough/scheme-blob-base-https-other-https.html [ Pass Timeout ]
+crbug.com/854630 virtual/outofblink-cors/http/tests/fetch/workers/thorough/scheme-data-base-https-other-https.html [ Pass Timeout ]
 
 # These tests have issues with —site-per-process. https://crbug.com/794631
 crbug.com/794631 http/tests/media/autoplay/document-user-activation-cross-origin-feature-policy-delegation.html [ Failure Pass Timeout ]
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations
index f09cd520..d46a084 100644
--- a/third_party/WebKit/LayoutTests/TestExpectations
+++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -1747,19 +1747,6 @@
 crbug.com/736308 virtual/outofblink-cors/external/wpt/service-workers/service-worker/sandboxed-iframe-fetch-event.https.html [ Timeout ]
 crbug.com/626703 virtual/outofblink-cors/external/wpt/service-workers/service-worker/update-bytecheck.https.html [ Timeout ]
 crbug.com/736308 virtual/outofblink-cors/external/wpt/service-workers/service-worker/worker-in-sandboxed-iframe-by-csp-fetch-event.https.html [ Timeout ]
-crbug.com/854630 virtual/outofblink-cors/http/tests/fetch/serviceworker/thorough/access-control-base-https-other-https.html [ Pass Timeout ]
-crbug.com/854630 virtual/outofblink-cors/http/tests/fetch/serviceworker/thorough/auth-base-https-other-https.html [ Pass Timeout ]
-crbug.com/854630 virtual/outofblink-cors/http/tests/fetch/serviceworker/thorough/auth-nocors-base-https-other-https.html [ Pass Timeout ]
-crbug.com/854630 virtual/outofblink-cors/http/tests/fetch/serviceworker/thorough/cookie-base-https-other-https.html [ Pass Timeout ]
-crbug.com/854630 virtual/outofblink-cors/http/tests/fetch/serviceworker/thorough/cookie-nocors-base-https-other-https.html [ Pass Timeout ]
-crbug.com/854630 virtual/outofblink-cors/http/tests/fetch/serviceworker/thorough/cors-base-https-other-https.html [ Pass Timeout ]
-crbug.com/854630 virtual/outofblink-cors/http/tests/fetch/serviceworker/thorough/cors-preflight-base-https-other-https.html [ Pass Timeout ]
-crbug.com/854630 virtual/outofblink-cors/http/tests/fetch/serviceworker/thorough/cors-preflight2-base-https-other-https.html [ Pass Timeout ]
-crbug.com/854630 virtual/outofblink-cors/http/tests/fetch/serviceworker/thorough/nocors-base-https-other-https.html [ Pass Timeout ]
-crbug.com/854630 virtual/outofblink-cors/http/tests/fetch/serviceworker/thorough/redirect-nocors-base-https-other-https.html [ Pass Timeout ]
-crbug.com/854630 virtual/outofblink-cors/http/tests/fetch/serviceworker/thorough/redirect-password-base-https-other-https.html [ Pass Timeout ]
-crbug.com/854630 virtual/outofblink-cors/http/tests/fetch/serviceworker/thorough/scheme-blob-base-https-other-https.html [ Pass Timeout ]
-crbug.com/854630 virtual/outofblink-cors/http/tests/fetch/serviceworker/thorough/scheme-data-base-https-other-https.html [ Pass Timeout ]
 crbug.com/736308 virtual/outofblink-cors/http/tests/xmlhttprequest/cross-origin-unsupported-url.html [ Timeout ]
 crbug.com/736308 virtual/outofblink-cors/http/tests/xmlhttprequest/simple-cross-origin-denied-events-post.html [ Timeout ]
 crbug.com/736308 virtual/outofblink-cors/http/tests/xmlhttprequest/workers/cross-origin-unsupported-url.html [ Timeout ]
@@ -2828,6 +2815,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/svg/painting/reftests/paint-context-001.svg [ Failure ]
+crbug.com/626703 external/wpt/svg/painting/reftests/paint-context-002.svg [ Failure ]
 crbug.com/626703 external/wpt/html/browsers/browsing-the-web/unloading-documents/unload/pagehide-manual.html [ Skip ]
 crbug.com/626703 external/wpt/css/css-scoping/shadow-directionality-002.tentative.html [ Failure ]
 crbug.com/626703 external/wpt/css/css-scoping/shadow-directionality-001.tentative.html [ Failure ]
@@ -4734,3 +4723,12 @@
 crbug.com/854053 [ Mac10.13 Debug ] virtual/threaded/fast/animationworklet/animation-worklet-scroll-timeline.html [ Pass Crash ]
 
 crbug.com/854538 [ Win7 ] http/tests/security/contentSecurityPolicy/1.1/form-action-src-default-ignored-with-redirect.html [ Skip ]
+
+# Sheriff 2018-06-21
+crbug.com/854910 [ Mac ] fast/scroll-behavior/smooth-scroll/track-scroll.html [ Failure Pass ]
+crbug.com/854910 [ Mac ] virtual/scroll_customization/fast/scroll-behavior/smooth-scroll/track-scroll.html [ Failure Pass ]
+crbug.com/855222 [ Mac ] external/wpt/orientation-sensor/AbsoluteOrientationSensor-iframe-access.https.html [ Failure Pass ]
+crbug.com/855222 [ Mac ] external/wpt/orientation-sensor/RelativeOrientationSensor-iframe-access.https.html [ Failure Pass ]
+
+# Sheriff 2018-06-22
+crbug.com/855055 [ Mac ] virtual/threaded/animations/interpolation/svg-stroke-dasharray-interpolation.html [ Pass Timeout ]
diff --git a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
index f7030ed..8f17b3fa 100644
--- a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
+++ b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
@@ -95385,6 +95385,30 @@
      {}
     ]
    ],
+   "svg/painting/reftests/paint-context-001.svg": [
+    [
+     "/svg/painting/reftests/paint-context-001.svg",
+     [
+      [
+       "/svg/painting/reftests/paint-context-001-ref.svg",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
+   "svg/painting/reftests/paint-context-002.svg": [
+    [
+     "/svg/painting/reftests/paint-context-002.svg",
+     [
+      [
+       "/svg/painting/reftests/paint-context-002-ref.svg",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
    "svg/path/bearing/absolute.svg": [
     [
      "/svg/path/bearing/absolute.svg",
@@ -157634,6 +157658,11 @@
      {}
     ]
    ],
+   "interfaces/orientation-event.idl": [
+    [
+     {}
+    ]
+   ],
    "interfaces/orientation-sensor.idl": [
     [
      {}
@@ -167674,6 +167703,16 @@
      {}
     ]
    ],
+   "svg/painting/reftests/paint-context-001-ref.svg": [
+    [
+     {}
+    ]
+   ],
+   "svg/painting/reftests/paint-context-002-ref.svg": [
+    [
+     {}
+    ]
+   ],
    "svg/path/bearing/absolute-ref.svg": [
     [
      {}
@@ -235217,9 +235256,9 @@
      {}
     ]
    ],
-   "orientation-event/idlharness.html": [
+   "orientation-event/idlharness.window.js": [
     [
-     "/orientation-event/idlharness.html",
+     "/orientation-event/idlharness.window.html",
      {}
     ]
    ],
@@ -269533,7 +269572,7 @@
    "testharness"
   ],
   "IndexedDB/idbdatabase-createObjectStore-exception-order.htm": [
-   "24d86e0a278a52c759f1a220041838bedd59959e",
+   "91fbbe23f8cdfc231aa01b8ad276ebb88d377c51",
    "testharness"
   ],
   "IndexedDB/idbdatabase-deleteObjectStore-exception-order.htm": [
@@ -374168,6 +374207,10 @@
    "7cbe73f7f563ee45772bb466ce63e16a549548d3",
    "support"
   ],
+  "interfaces/orientation-event.idl": [
+   "0188bd03cdd323e354e8e7c3d279c6983f701378",
+   "support"
+  ],
   "interfaces/orientation-sensor.idl": [
    "1f0698a8611726b1ba724a5d7a0961e836c7b07e",
    "support"
@@ -375569,7 +375612,7 @@
    "testharness"
   ],
   "mediacapture-streams/MediaStreamTrack-getSettings.https.html": [
-   "e73c53bfd0c77c91f2f736cb5bb723856c2d1501",
+   "64136d9276455bd7ff619db1f3914b83b7076da0",
    "testharness"
   ],
   "mediacapture-streams/MediaStreamTrack-id.https.html": [
@@ -383956,8 +383999,8 @@
    "097967a0076ecae8de3bd38ebbba4fbde8403da3",
    "support"
   ],
-  "orientation-event/idlharness.html": [
-   "0e9e6441b4ccbf7618b21fdb5a02f9fa8fab87dd",
+  "orientation-event/idlharness.window.js": [
+   "824ae0a40b84ce1746f813cd16be75e550f2bd6c",
    "testharness"
   ],
   "orientation-event/screen-upmost-manual.html": [
@@ -400524,6 +400567,22 @@
    "fb8aec792684b97151d2964b85d1e70829e141ad",
    "support"
   ],
+  "svg/painting/reftests/paint-context-001-ref.svg": [
+   "d7e12d36f0b3168c677edf95ce401b3e1e5eccbe",
+   "support"
+  ],
+  "svg/painting/reftests/paint-context-001.svg": [
+   "d39d2988c685db29c1487e800f12e9ebea02ceac",
+   "reftest"
+  ],
+  "svg/painting/reftests/paint-context-002-ref.svg": [
+   "d625175aeaa329436b79b1a3c5d349b7fc4c18b7",
+   "support"
+  ],
+  "svg/painting/reftests/paint-context-002.svg": [
+   "510bd6b75e4e3688fd604fa7145c27587e63d6ff",
+   "reftest"
+  ],
   "svg/path/bearing/absolute-ref.svg": [
    "6ad5320a05fcc31fd2af98d2bbd0bd6fbc558daa",
    "support"
diff --git a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbdatabase-createObjectStore-exception-order.htm b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbdatabase-createObjectStore-exception-order.htm
index 50b3adb..8705501 100644
--- a/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbdatabase-createObjectStore-exception-order.htm
+++ b/third_party/WebKit/LayoutTests/external/wpt/IndexedDB/idbdatabase-createObjectStore-exception-order.htm
@@ -8,9 +8,13 @@
 <script>
 
 indexeddb_test(
-  (t, db, txn) => {
+  (t, db, txn, rq) => {
     db.createObjectStore('s');
 
+    // Acknowledge the error, to prevent window.error from firing in
+    // browsers that implement that.
+    rq.onerror = e => { e.preventDefault(); };
+
     txn.onabort = () => {
       setTimeout(t.step_func(() => {
         assert_throws(
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-template-element/template-element/template-as-a-descendant-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-template-element/template-element/template-as-a-descendant-expected.txt
deleted file mode 100644
index 271fc41..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-template-element/template-element/template-as-a-descendant-expected.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-This is a testharness.js-based test.
-PASS Template element as a descendant of the BODY element. Template element is created by innerHTML
-PASS Template element as a descendant of the HEAD element. Template element is created by innerHTML
-FAIL Template element as a descendant of the FRAMESET element. Template element is created by innerHTML assert_equals: Template element should not be allowed as a descendant of the FRAMESET element expected null but got Element node <template>some text</template>
-PASS Template element as an indirect descendant of the BODY element. Template element is created by innerHTML
-PASS Template element as an indirect descendant of the HEAD element. Template element is created by innerHTML
-FAIL Template element as an indirect descendant of the FRAMESET element. Template element is created by innerHTML assert_equals: Template element should not be allowed as indirect descendant of the FRAMESET element expected null but got Element node <template>some text</template>
-PASS Template element as a descendant of the BODY element. Template element is appended by appendChild()
-PASS Template element as a descendant of the HEAD element. Template element is appended by appendChild()
-PASS Template element as a descendant of the FRAMESET element. Template element is  appended by appendChild()
-PASS Template element as an indirect descendant of the BODY element. Template element is appended by appendChild()
-PASS Template element as an indirect descendant of the HEAD element. Template element is appended by appendChild()
-PASS Template element as an indirect descendant of the FRAMESET element. Template element is  appended by appendChild()
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-template-element/template-element/template-descendant-frameset-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-template-element/template-element/template-descendant-frameset-expected.txt
deleted file mode 100644
index 27b9487..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/html/semantics/scripting-1/the-template-element/template-element/template-descendant-frameset-expected.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-This is a testharness.js-based test.
-FAIL Template element as a descendant of the frameset element. Test loading from a file assert_equals: Template element should not be a descendant of the frameset element expected null but got Element node <template>
-        <div>Hello, template</div>
-    </templ...
-FAIL Template element as a descendant of the frameset element. Test template element is assigned to frameset's innerHTML) assert_equals: Template element should not be a descendant of the frameset element expected null but got Element node <template>some text</template>
-FAIL Template element as a descendant of the frameset element. Test template element appended to frameset by appendChild() assert_equals: Template element should be a descendant of the frameset element expected 1 but got 2
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/html5lib_template_run_type=uri-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/html5lib_template_run_type=uri-expected.txt
deleted file mode 100644
index cbb6f28..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/html5lib_template_run_type=uri-expected.txt
+++ /dev/null
@@ -1,111 +0,0 @@
-This is a testharness.js-based test.
-Found 107 tests; 103 PASS, 4 FAIL, 0 TIMEOUT, 0 NOTRUN.
-PASS html5lib_template.html 010950d55f4eccf16e9c4af1d263bb747294c646
-PASS html5lib_template.html a838bd54410cef059a42eea9606356488e16535b
-PASS html5lib_template.html 27fb9111f6675a7e033b867480c0afddcda161a6
-PASS html5lib_template.html aee883a65775489399a003b2371d58248a6aff6f
-PASS html5lib_template.html 89b17b54ab343191bf74ef5434f4d2cfac40ea97
-PASS html5lib_template.html c4433556c7414cfd71f27b420f1ffc4348774f5e
-PASS html5lib_template.html 3dcce7d97108b3e9ea7fa96f240ac62bf280e74b
-PASS html5lib_template.html a1f587f7ea85ccfe294bd45bfb501e850cb979e0
-PASS html5lib_template.html cd26a7832f13bdc135697321ca6c2fecdca6ef5d
-PASS html5lib_template.html e30571d90b0e56864499961eb7be955994cf72e2
-PASS html5lib_template.html 01cbe9f6a25f286b08d8dc4f7b65421e8eb3500c
-PASS html5lib_template.html 96cbbcdffe02c86a8b929604c2fd5f3571a18dbe
-PASS html5lib_template.html d51676f55550e960dd0f5fa7fd0bdfa20bdde046
-PASS html5lib_template.html f9dfd9acfd494489c899604649a01d864741f50f
-PASS html5lib_template.html ea00361c265d3ffb47ce636d919c94ca10d58911
-PASS html5lib_template.html d8ebfcf7694c9d04457e796ac73049210313602e
-PASS html5lib_template.html b4d5e6fe9b92e2c8f54199d7cab3da383c42add0
-PASS html5lib_template.html 07724ef8f7a4fa61c77ffcd5180d3101c4781502
-PASS html5lib_template.html e90f8aae8fc690540b42b3ffa3e741e7c1dfbf43
-PASS html5lib_template.html 687bdf4adda88a316ec69fe20e84720acc5d1fe6
-PASS html5lib_template.html 5b232642f472c2b4c0c7511fed464eebe686b427
-PASS html5lib_template.html dc1ac1830a881d1532a1e6fd6d0cfa56d6571da2
-PASS html5lib_template.html c58747a85e8b4f44d7ae63c04cdad783a903c25e
-PASS html5lib_template.html ca59bfdaec7451f704973176fab46e582bd691b2
-PASS html5lib_template.html cf807d6391a58c172b6c15c3b01d2a99ec0e6cf8
-PASS html5lib_template.html 350b7ac850e46de79615308fc923649264406104
-PASS html5lib_template.html a31ff44edf7f377543dabdda8141cda9bb6de134
-PASS html5lib_template.html 533c5c1b5f0d0cbb1ede2cc5ae927095c5b21f0b
-PASS html5lib_template.html 61f79e083005007853c4f8e431559ac8d3845cfd
-PASS html5lib_template.html e802e85f36792b176b73c102c0e8761d9478621d
-PASS html5lib_template.html 51d0797ff7653cd7be34458d689146e08a666c7f
-PASS html5lib_template.html d60e4079a18bd6266740cc61d1ca736e9d5098ce
-PASS html5lib_template.html 308709292677b4d74c108a811ad7b7acd0bdfc9c
-PASS html5lib_template.html 8965cdf9c4e9936262e25c90c7a7f8673840a445
-PASS html5lib_template.html 7dccda789764beb489e09be10188af9347335d05
-PASS html5lib_template.html e15be51c77e1a6de35568a099ed339440ce9426d
-PASS html5lib_template.html 503d3782e45940c19f096f360a092282b46ab1ea
-PASS html5lib_template.html b4ab56fd9e9cebf479d14adfa523c06d16483a5e
-PASS html5lib_template.html cd8bc9521f9683086a9e8529dd97314a6869daeb
-FAIL html5lib_template.html f915e7b3407c24b28c3aad318e5693cc774020f4 assert_equals: expected "#document\n| <html>\n|   <head>\n|   <frameset>\n|     <frame>" but got "#document\n| <html>\n|   <head>\n|   <frameset>\n|     <template>\n|       content\n|         <frame>"
-FAIL html5lib_template.html 3c5eb261787b3d15aff86fa61de773fd7e439b0e assert_equals: expected "#document\n| <html>\n|   <head>\n|     <template>\n|       content\n|   <body>" but got "#document\n| <html>\n|   <head>\n|     <template>\n|       content\n|         <frame>\n|         <frame>\n|   <body>"
-PASS html5lib_template.html 2b57775750c198d4b98b23aed74ff80a866a01f5
-PASS html5lib_template.html dc3d016610f3ab532525a6c2871f03d6b62b0168
-PASS html5lib_template.html 6a184d71d00580a26a8b6bd97aafe5503339f3f6
-PASS html5lib_template.html ce570a6c4bcee8b72a03e25508c6dd72e3cc6c35
-PASS html5lib_template.html e0c3d922f7b1f1654f02f716c3d9b31198ce3385
-PASS html5lib_template.html 87e67242bf6debcf3b7dca852d10aa0f7b625b28
-PASS html5lib_template.html 35ac4d4c972a01d368ed0cacb41370efef0a644d
-PASS html5lib_template.html 5226c39dfc2d624ad4191b4eacb7e40c7ae528eb
-PASS html5lib_template.html aa90cd4db6b12e0a47341914a90cc536eec32d64
-PASS html5lib_template.html 48af1faf5fcf48a0854af5a5c33656d9ccf6736b
-PASS html5lib_template.html ed3a029ba5e7f59969d65a4fc490a8f13b098cb9
-PASS html5lib_template.html 6c8880d54475ad9574e203dcf2e55820b123cc64
-PASS html5lib_template.html 275060925a844cb51b29bae660301de9780d68c8
-PASS html5lib_template.html 9f82f6ec4c0a48c1d4dfbe6803b94abd553aea88
-PASS html5lib_template.html f094bf7e94a88b86c80a0643e70c8e5ff3354698
-PASS html5lib_template.html 35a07ec3b4bf26ea407dc1ddf52f14195a714059
-PASS html5lib_template.html 24faa53b271f994a4ff31d5796c8ff47d6f2c3e6
-PASS html5lib_template.html 0f1c491b58c2dd3c402a62e37f833bc1f1db8d21
-PASS html5lib_template.html 868d918a7b5d8b5c065c15229492bc2022bfbcba
-PASS html5lib_template.html 0538efa44e857596c556033a3821d424378aea3f
-PASS html5lib_template.html e7d7bf3973c70d3cf9b0adad2ebed9f25be48d66
-PASS html5lib_template.html c69d0ac542d477b7312bb24981127b8aa8fdb1df
-PASS html5lib_template.html b496a8c13a7bd75b778bb0de489726aee952ae0c
-PASS html5lib_template.html 5d6ee61de40274c9626ca78ee208d51276d5662d
-PASS html5lib_template.html 9bd9687a65f258adc24450fc5cbd781fff6c038a
-FAIL html5lib_template.html db1baeb846d718c773324746524fbd68f2e9436e assert_equals: expected "#document\n| <html>\n|   a=\"b\"\n|   <head>\n|     <template>\n|       content\n|   <body>" but got "#document\n| <html>\n|   a=\"b\"\n|   <head>\n|     <template>\n|       content\n|         <frame>\n|         <frame>\n|   <body>"
-PASS html5lib_template.html 4b0ce46c611dbcc016db272ef007f302bee0c897
-PASS html5lib_template.html 1a735e1c7f28f8701f3c7fd5e9404b8911916086
-PASS html5lib_template.html 0686eedec06b2db1dc283fac92c1ef1a33114c71
-PASS html5lib_template.html d4dfb87ce626f12923056a6cd77448eaf4660ac2
-PASS html5lib_template.html 1f295920f2937b2c8023b3761c43a0d4d9e5353c
-PASS html5lib_template.html 3b91fa08fad923d387d924cff37fbf6b4c3a5712
-PASS html5lib_template.html 45a1c1ad5d99ad67c573096a79253996a664e01b
-PASS html5lib_template.html 0fe3a66773c6048c8f6f2c92f2611f65be972ec1
-PASS html5lib_template.html be40897ca411e1507197c31ab2a9f9752a05f769
-PASS html5lib_template.html dcfb1048ed5c40e406b4fbf0cde24c826713907f
-PASS html5lib_template.html 78263aeea68ac97903598682013bae9c0c21d547
-PASS html5lib_template.html 5aa177ef1a35bf4502dcb867d8e666288982ba99
-PASS html5lib_template.html 5d303375907dc4d4380b477e0317c17b660613e9
-PASS html5lib_template.html d822f726927c34b92fe102b13e63920850878f6a
-PASS html5lib_template.html 07acdcaeb4fa639296d46673cf28823ddf2a6ca7
-PASS html5lib_template.html 58bd846ce1be0caf7560fba2ef19e2c2070ab123
-PASS html5lib_template.html 8eeee377e5ab324731cc592f1fa8abe1045ad610
-PASS html5lib_template.html b30690019090149132fc228a7261c5cf2fd149fc
-PASS html5lib_template.html 67a209d928804f90fdb66d070201b23f3d0c8a42
-PASS html5lib_template.html 12104886b8f87daa937eac30b5ff0e1e074eaa6f
-PASS html5lib_template.html 483cc9957a7225fe435112642be59abb4c459a1e
-PASS html5lib_template.html 72d8ac431a154c40ab75d53a258d9d80d47689eb
-PASS html5lib_template.html 1125967cbbcd404f4cb14d48270b8ec778970d77
-PASS html5lib_template.html 32c963e164b9ec82c60e490bb141c1ccc70b992f
-PASS html5lib_template.html 574a95fc9c9f2de3aeaa0c9ee1e6967fc3d4770d
-FAIL html5lib_template.html 332863a7f9e61bff32bd3427ede7a088b790d453 assert_equals: expected "#document\n| <html>\n|   <head>\n|     <template>\n|       content\n|         <template>\n|           content\n|   <body>" but got "#document\n| <html>\n|   <head>\n|     <template>\n|       content\n|         <template>\n|           content\n|             <frame>\n|   <body>"
-PASS html5lib_template.html 2121db07146781773df9e53b94fa921a805175ce
-PASS html5lib_template.html 8675de267cd7e34f2febdee3feb665614d1562fe
-PASS html5lib_template.html c5d26ad923a2b1e988ddd378ca4fb26eb48353e1
-PASS html5lib_template.html eec1542e2fa0e9eafb7f8d4a51eae56b5a31b3c8
-PASS html5lib_template.html b79387a54c3b136db0f28ed96555ff683b3947fe
-PASS html5lib_template.html c477a29a4deb32d072a415fa809a84a4f2beee0c
-PASS html5lib_template.html 26e4480c08e1f5f7b6ac8b8c1832ab0312e3b7c5
-PASS html5lib_template.html 24b3b50fdd0bf8d5cf2ebaa6bf502d7bcfde1da4
-PASS html5lib_template.html d3704c68528357189eb5826ab66eea071d6137a5
-PASS html5lib_template.html d958f7d44faf772d1fb60f1a8f186f837ca735d9
-PASS html5lib_template.html 3fc4d97fa68fc2658356bdbd4e051c867de8de53
-PASS html5lib_template.html 94820107bbf3fab3f82de1f717e8413aead7d3a6
-PASS html5lib_template.html 657c00ebdda37ae060cc69633ed98482ccc29e18
-PASS html5lib_template.html 649fc955a4b60ab2a5b881d94c9493eb4a545002
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/html5lib_template_run_type=write-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/html5lib_template_run_type=write-expected.txt
deleted file mode 100644
index cbb6f28..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/html5lib_template_run_type=write-expected.txt
+++ /dev/null
@@ -1,111 +0,0 @@
-This is a testharness.js-based test.
-Found 107 tests; 103 PASS, 4 FAIL, 0 TIMEOUT, 0 NOTRUN.
-PASS html5lib_template.html 010950d55f4eccf16e9c4af1d263bb747294c646
-PASS html5lib_template.html a838bd54410cef059a42eea9606356488e16535b
-PASS html5lib_template.html 27fb9111f6675a7e033b867480c0afddcda161a6
-PASS html5lib_template.html aee883a65775489399a003b2371d58248a6aff6f
-PASS html5lib_template.html 89b17b54ab343191bf74ef5434f4d2cfac40ea97
-PASS html5lib_template.html c4433556c7414cfd71f27b420f1ffc4348774f5e
-PASS html5lib_template.html 3dcce7d97108b3e9ea7fa96f240ac62bf280e74b
-PASS html5lib_template.html a1f587f7ea85ccfe294bd45bfb501e850cb979e0
-PASS html5lib_template.html cd26a7832f13bdc135697321ca6c2fecdca6ef5d
-PASS html5lib_template.html e30571d90b0e56864499961eb7be955994cf72e2
-PASS html5lib_template.html 01cbe9f6a25f286b08d8dc4f7b65421e8eb3500c
-PASS html5lib_template.html 96cbbcdffe02c86a8b929604c2fd5f3571a18dbe
-PASS html5lib_template.html d51676f55550e960dd0f5fa7fd0bdfa20bdde046
-PASS html5lib_template.html f9dfd9acfd494489c899604649a01d864741f50f
-PASS html5lib_template.html ea00361c265d3ffb47ce636d919c94ca10d58911
-PASS html5lib_template.html d8ebfcf7694c9d04457e796ac73049210313602e
-PASS html5lib_template.html b4d5e6fe9b92e2c8f54199d7cab3da383c42add0
-PASS html5lib_template.html 07724ef8f7a4fa61c77ffcd5180d3101c4781502
-PASS html5lib_template.html e90f8aae8fc690540b42b3ffa3e741e7c1dfbf43
-PASS html5lib_template.html 687bdf4adda88a316ec69fe20e84720acc5d1fe6
-PASS html5lib_template.html 5b232642f472c2b4c0c7511fed464eebe686b427
-PASS html5lib_template.html dc1ac1830a881d1532a1e6fd6d0cfa56d6571da2
-PASS html5lib_template.html c58747a85e8b4f44d7ae63c04cdad783a903c25e
-PASS html5lib_template.html ca59bfdaec7451f704973176fab46e582bd691b2
-PASS html5lib_template.html cf807d6391a58c172b6c15c3b01d2a99ec0e6cf8
-PASS html5lib_template.html 350b7ac850e46de79615308fc923649264406104
-PASS html5lib_template.html a31ff44edf7f377543dabdda8141cda9bb6de134
-PASS html5lib_template.html 533c5c1b5f0d0cbb1ede2cc5ae927095c5b21f0b
-PASS html5lib_template.html 61f79e083005007853c4f8e431559ac8d3845cfd
-PASS html5lib_template.html e802e85f36792b176b73c102c0e8761d9478621d
-PASS html5lib_template.html 51d0797ff7653cd7be34458d689146e08a666c7f
-PASS html5lib_template.html d60e4079a18bd6266740cc61d1ca736e9d5098ce
-PASS html5lib_template.html 308709292677b4d74c108a811ad7b7acd0bdfc9c
-PASS html5lib_template.html 8965cdf9c4e9936262e25c90c7a7f8673840a445
-PASS html5lib_template.html 7dccda789764beb489e09be10188af9347335d05
-PASS html5lib_template.html e15be51c77e1a6de35568a099ed339440ce9426d
-PASS html5lib_template.html 503d3782e45940c19f096f360a092282b46ab1ea
-PASS html5lib_template.html b4ab56fd9e9cebf479d14adfa523c06d16483a5e
-PASS html5lib_template.html cd8bc9521f9683086a9e8529dd97314a6869daeb
-FAIL html5lib_template.html f915e7b3407c24b28c3aad318e5693cc774020f4 assert_equals: expected "#document\n| <html>\n|   <head>\n|   <frameset>\n|     <frame>" but got "#document\n| <html>\n|   <head>\n|   <frameset>\n|     <template>\n|       content\n|         <frame>"
-FAIL html5lib_template.html 3c5eb261787b3d15aff86fa61de773fd7e439b0e assert_equals: expected "#document\n| <html>\n|   <head>\n|     <template>\n|       content\n|   <body>" but got "#document\n| <html>\n|   <head>\n|     <template>\n|       content\n|         <frame>\n|         <frame>\n|   <body>"
-PASS html5lib_template.html 2b57775750c198d4b98b23aed74ff80a866a01f5
-PASS html5lib_template.html dc3d016610f3ab532525a6c2871f03d6b62b0168
-PASS html5lib_template.html 6a184d71d00580a26a8b6bd97aafe5503339f3f6
-PASS html5lib_template.html ce570a6c4bcee8b72a03e25508c6dd72e3cc6c35
-PASS html5lib_template.html e0c3d922f7b1f1654f02f716c3d9b31198ce3385
-PASS html5lib_template.html 87e67242bf6debcf3b7dca852d10aa0f7b625b28
-PASS html5lib_template.html 35ac4d4c972a01d368ed0cacb41370efef0a644d
-PASS html5lib_template.html 5226c39dfc2d624ad4191b4eacb7e40c7ae528eb
-PASS html5lib_template.html aa90cd4db6b12e0a47341914a90cc536eec32d64
-PASS html5lib_template.html 48af1faf5fcf48a0854af5a5c33656d9ccf6736b
-PASS html5lib_template.html ed3a029ba5e7f59969d65a4fc490a8f13b098cb9
-PASS html5lib_template.html 6c8880d54475ad9574e203dcf2e55820b123cc64
-PASS html5lib_template.html 275060925a844cb51b29bae660301de9780d68c8
-PASS html5lib_template.html 9f82f6ec4c0a48c1d4dfbe6803b94abd553aea88
-PASS html5lib_template.html f094bf7e94a88b86c80a0643e70c8e5ff3354698
-PASS html5lib_template.html 35a07ec3b4bf26ea407dc1ddf52f14195a714059
-PASS html5lib_template.html 24faa53b271f994a4ff31d5796c8ff47d6f2c3e6
-PASS html5lib_template.html 0f1c491b58c2dd3c402a62e37f833bc1f1db8d21
-PASS html5lib_template.html 868d918a7b5d8b5c065c15229492bc2022bfbcba
-PASS html5lib_template.html 0538efa44e857596c556033a3821d424378aea3f
-PASS html5lib_template.html e7d7bf3973c70d3cf9b0adad2ebed9f25be48d66
-PASS html5lib_template.html c69d0ac542d477b7312bb24981127b8aa8fdb1df
-PASS html5lib_template.html b496a8c13a7bd75b778bb0de489726aee952ae0c
-PASS html5lib_template.html 5d6ee61de40274c9626ca78ee208d51276d5662d
-PASS html5lib_template.html 9bd9687a65f258adc24450fc5cbd781fff6c038a
-FAIL html5lib_template.html db1baeb846d718c773324746524fbd68f2e9436e assert_equals: expected "#document\n| <html>\n|   a=\"b\"\n|   <head>\n|     <template>\n|       content\n|   <body>" but got "#document\n| <html>\n|   a=\"b\"\n|   <head>\n|     <template>\n|       content\n|         <frame>\n|         <frame>\n|   <body>"
-PASS html5lib_template.html 4b0ce46c611dbcc016db272ef007f302bee0c897
-PASS html5lib_template.html 1a735e1c7f28f8701f3c7fd5e9404b8911916086
-PASS html5lib_template.html 0686eedec06b2db1dc283fac92c1ef1a33114c71
-PASS html5lib_template.html d4dfb87ce626f12923056a6cd77448eaf4660ac2
-PASS html5lib_template.html 1f295920f2937b2c8023b3761c43a0d4d9e5353c
-PASS html5lib_template.html 3b91fa08fad923d387d924cff37fbf6b4c3a5712
-PASS html5lib_template.html 45a1c1ad5d99ad67c573096a79253996a664e01b
-PASS html5lib_template.html 0fe3a66773c6048c8f6f2c92f2611f65be972ec1
-PASS html5lib_template.html be40897ca411e1507197c31ab2a9f9752a05f769
-PASS html5lib_template.html dcfb1048ed5c40e406b4fbf0cde24c826713907f
-PASS html5lib_template.html 78263aeea68ac97903598682013bae9c0c21d547
-PASS html5lib_template.html 5aa177ef1a35bf4502dcb867d8e666288982ba99
-PASS html5lib_template.html 5d303375907dc4d4380b477e0317c17b660613e9
-PASS html5lib_template.html d822f726927c34b92fe102b13e63920850878f6a
-PASS html5lib_template.html 07acdcaeb4fa639296d46673cf28823ddf2a6ca7
-PASS html5lib_template.html 58bd846ce1be0caf7560fba2ef19e2c2070ab123
-PASS html5lib_template.html 8eeee377e5ab324731cc592f1fa8abe1045ad610
-PASS html5lib_template.html b30690019090149132fc228a7261c5cf2fd149fc
-PASS html5lib_template.html 67a209d928804f90fdb66d070201b23f3d0c8a42
-PASS html5lib_template.html 12104886b8f87daa937eac30b5ff0e1e074eaa6f
-PASS html5lib_template.html 483cc9957a7225fe435112642be59abb4c459a1e
-PASS html5lib_template.html 72d8ac431a154c40ab75d53a258d9d80d47689eb
-PASS html5lib_template.html 1125967cbbcd404f4cb14d48270b8ec778970d77
-PASS html5lib_template.html 32c963e164b9ec82c60e490bb141c1ccc70b992f
-PASS html5lib_template.html 574a95fc9c9f2de3aeaa0c9ee1e6967fc3d4770d
-FAIL html5lib_template.html 332863a7f9e61bff32bd3427ede7a088b790d453 assert_equals: expected "#document\n| <html>\n|   <head>\n|     <template>\n|       content\n|         <template>\n|           content\n|   <body>" but got "#document\n| <html>\n|   <head>\n|     <template>\n|       content\n|         <template>\n|           content\n|             <frame>\n|   <body>"
-PASS html5lib_template.html 2121db07146781773df9e53b94fa921a805175ce
-PASS html5lib_template.html 8675de267cd7e34f2febdee3feb665614d1562fe
-PASS html5lib_template.html c5d26ad923a2b1e988ddd378ca4fb26eb48353e1
-PASS html5lib_template.html eec1542e2fa0e9eafb7f8d4a51eae56b5a31b3c8
-PASS html5lib_template.html b79387a54c3b136db0f28ed96555ff683b3947fe
-PASS html5lib_template.html c477a29a4deb32d072a415fa809a84a4f2beee0c
-PASS html5lib_template.html 26e4480c08e1f5f7b6ac8b8c1832ab0312e3b7c5
-PASS html5lib_template.html 24b3b50fdd0bf8d5cf2ebaa6bf502d7bcfde1da4
-PASS html5lib_template.html d3704c68528357189eb5826ab66eea071d6137a5
-PASS html5lib_template.html d958f7d44faf772d1fb60f1a8f186f837ca735d9
-PASS html5lib_template.html 3fc4d97fa68fc2658356bdbd4e051c867de8de53
-PASS html5lib_template.html 94820107bbf3fab3f82de1f717e8413aead7d3a6
-PASS html5lib_template.html 657c00ebdda37ae060cc69633ed98482ccc29e18
-PASS html5lib_template.html 649fc955a4b60ab2a5b881d94c9493eb4a545002
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/html5lib_template_run_type=write_single-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/html5lib_template_run_type=write_single-expected.txt
deleted file mode 100644
index cbb6f28..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/html5lib_template_run_type=write_single-expected.txt
+++ /dev/null
@@ -1,111 +0,0 @@
-This is a testharness.js-based test.
-Found 107 tests; 103 PASS, 4 FAIL, 0 TIMEOUT, 0 NOTRUN.
-PASS html5lib_template.html 010950d55f4eccf16e9c4af1d263bb747294c646
-PASS html5lib_template.html a838bd54410cef059a42eea9606356488e16535b
-PASS html5lib_template.html 27fb9111f6675a7e033b867480c0afddcda161a6
-PASS html5lib_template.html aee883a65775489399a003b2371d58248a6aff6f
-PASS html5lib_template.html 89b17b54ab343191bf74ef5434f4d2cfac40ea97
-PASS html5lib_template.html c4433556c7414cfd71f27b420f1ffc4348774f5e
-PASS html5lib_template.html 3dcce7d97108b3e9ea7fa96f240ac62bf280e74b
-PASS html5lib_template.html a1f587f7ea85ccfe294bd45bfb501e850cb979e0
-PASS html5lib_template.html cd26a7832f13bdc135697321ca6c2fecdca6ef5d
-PASS html5lib_template.html e30571d90b0e56864499961eb7be955994cf72e2
-PASS html5lib_template.html 01cbe9f6a25f286b08d8dc4f7b65421e8eb3500c
-PASS html5lib_template.html 96cbbcdffe02c86a8b929604c2fd5f3571a18dbe
-PASS html5lib_template.html d51676f55550e960dd0f5fa7fd0bdfa20bdde046
-PASS html5lib_template.html f9dfd9acfd494489c899604649a01d864741f50f
-PASS html5lib_template.html ea00361c265d3ffb47ce636d919c94ca10d58911
-PASS html5lib_template.html d8ebfcf7694c9d04457e796ac73049210313602e
-PASS html5lib_template.html b4d5e6fe9b92e2c8f54199d7cab3da383c42add0
-PASS html5lib_template.html 07724ef8f7a4fa61c77ffcd5180d3101c4781502
-PASS html5lib_template.html e90f8aae8fc690540b42b3ffa3e741e7c1dfbf43
-PASS html5lib_template.html 687bdf4adda88a316ec69fe20e84720acc5d1fe6
-PASS html5lib_template.html 5b232642f472c2b4c0c7511fed464eebe686b427
-PASS html5lib_template.html dc1ac1830a881d1532a1e6fd6d0cfa56d6571da2
-PASS html5lib_template.html c58747a85e8b4f44d7ae63c04cdad783a903c25e
-PASS html5lib_template.html ca59bfdaec7451f704973176fab46e582bd691b2
-PASS html5lib_template.html cf807d6391a58c172b6c15c3b01d2a99ec0e6cf8
-PASS html5lib_template.html 350b7ac850e46de79615308fc923649264406104
-PASS html5lib_template.html a31ff44edf7f377543dabdda8141cda9bb6de134
-PASS html5lib_template.html 533c5c1b5f0d0cbb1ede2cc5ae927095c5b21f0b
-PASS html5lib_template.html 61f79e083005007853c4f8e431559ac8d3845cfd
-PASS html5lib_template.html e802e85f36792b176b73c102c0e8761d9478621d
-PASS html5lib_template.html 51d0797ff7653cd7be34458d689146e08a666c7f
-PASS html5lib_template.html d60e4079a18bd6266740cc61d1ca736e9d5098ce
-PASS html5lib_template.html 308709292677b4d74c108a811ad7b7acd0bdfc9c
-PASS html5lib_template.html 8965cdf9c4e9936262e25c90c7a7f8673840a445
-PASS html5lib_template.html 7dccda789764beb489e09be10188af9347335d05
-PASS html5lib_template.html e15be51c77e1a6de35568a099ed339440ce9426d
-PASS html5lib_template.html 503d3782e45940c19f096f360a092282b46ab1ea
-PASS html5lib_template.html b4ab56fd9e9cebf479d14adfa523c06d16483a5e
-PASS html5lib_template.html cd8bc9521f9683086a9e8529dd97314a6869daeb
-FAIL html5lib_template.html f915e7b3407c24b28c3aad318e5693cc774020f4 assert_equals: expected "#document\n| <html>\n|   <head>\n|   <frameset>\n|     <frame>" but got "#document\n| <html>\n|   <head>\n|   <frameset>\n|     <template>\n|       content\n|         <frame>"
-FAIL html5lib_template.html 3c5eb261787b3d15aff86fa61de773fd7e439b0e assert_equals: expected "#document\n| <html>\n|   <head>\n|     <template>\n|       content\n|   <body>" but got "#document\n| <html>\n|   <head>\n|     <template>\n|       content\n|         <frame>\n|         <frame>\n|   <body>"
-PASS html5lib_template.html 2b57775750c198d4b98b23aed74ff80a866a01f5
-PASS html5lib_template.html dc3d016610f3ab532525a6c2871f03d6b62b0168
-PASS html5lib_template.html 6a184d71d00580a26a8b6bd97aafe5503339f3f6
-PASS html5lib_template.html ce570a6c4bcee8b72a03e25508c6dd72e3cc6c35
-PASS html5lib_template.html e0c3d922f7b1f1654f02f716c3d9b31198ce3385
-PASS html5lib_template.html 87e67242bf6debcf3b7dca852d10aa0f7b625b28
-PASS html5lib_template.html 35ac4d4c972a01d368ed0cacb41370efef0a644d
-PASS html5lib_template.html 5226c39dfc2d624ad4191b4eacb7e40c7ae528eb
-PASS html5lib_template.html aa90cd4db6b12e0a47341914a90cc536eec32d64
-PASS html5lib_template.html 48af1faf5fcf48a0854af5a5c33656d9ccf6736b
-PASS html5lib_template.html ed3a029ba5e7f59969d65a4fc490a8f13b098cb9
-PASS html5lib_template.html 6c8880d54475ad9574e203dcf2e55820b123cc64
-PASS html5lib_template.html 275060925a844cb51b29bae660301de9780d68c8
-PASS html5lib_template.html 9f82f6ec4c0a48c1d4dfbe6803b94abd553aea88
-PASS html5lib_template.html f094bf7e94a88b86c80a0643e70c8e5ff3354698
-PASS html5lib_template.html 35a07ec3b4bf26ea407dc1ddf52f14195a714059
-PASS html5lib_template.html 24faa53b271f994a4ff31d5796c8ff47d6f2c3e6
-PASS html5lib_template.html 0f1c491b58c2dd3c402a62e37f833bc1f1db8d21
-PASS html5lib_template.html 868d918a7b5d8b5c065c15229492bc2022bfbcba
-PASS html5lib_template.html 0538efa44e857596c556033a3821d424378aea3f
-PASS html5lib_template.html e7d7bf3973c70d3cf9b0adad2ebed9f25be48d66
-PASS html5lib_template.html c69d0ac542d477b7312bb24981127b8aa8fdb1df
-PASS html5lib_template.html b496a8c13a7bd75b778bb0de489726aee952ae0c
-PASS html5lib_template.html 5d6ee61de40274c9626ca78ee208d51276d5662d
-PASS html5lib_template.html 9bd9687a65f258adc24450fc5cbd781fff6c038a
-FAIL html5lib_template.html db1baeb846d718c773324746524fbd68f2e9436e assert_equals: expected "#document\n| <html>\n|   a=\"b\"\n|   <head>\n|     <template>\n|       content\n|   <body>" but got "#document\n| <html>\n|   a=\"b\"\n|   <head>\n|     <template>\n|       content\n|         <frame>\n|         <frame>\n|   <body>"
-PASS html5lib_template.html 4b0ce46c611dbcc016db272ef007f302bee0c897
-PASS html5lib_template.html 1a735e1c7f28f8701f3c7fd5e9404b8911916086
-PASS html5lib_template.html 0686eedec06b2db1dc283fac92c1ef1a33114c71
-PASS html5lib_template.html d4dfb87ce626f12923056a6cd77448eaf4660ac2
-PASS html5lib_template.html 1f295920f2937b2c8023b3761c43a0d4d9e5353c
-PASS html5lib_template.html 3b91fa08fad923d387d924cff37fbf6b4c3a5712
-PASS html5lib_template.html 45a1c1ad5d99ad67c573096a79253996a664e01b
-PASS html5lib_template.html 0fe3a66773c6048c8f6f2c92f2611f65be972ec1
-PASS html5lib_template.html be40897ca411e1507197c31ab2a9f9752a05f769
-PASS html5lib_template.html dcfb1048ed5c40e406b4fbf0cde24c826713907f
-PASS html5lib_template.html 78263aeea68ac97903598682013bae9c0c21d547
-PASS html5lib_template.html 5aa177ef1a35bf4502dcb867d8e666288982ba99
-PASS html5lib_template.html 5d303375907dc4d4380b477e0317c17b660613e9
-PASS html5lib_template.html d822f726927c34b92fe102b13e63920850878f6a
-PASS html5lib_template.html 07acdcaeb4fa639296d46673cf28823ddf2a6ca7
-PASS html5lib_template.html 58bd846ce1be0caf7560fba2ef19e2c2070ab123
-PASS html5lib_template.html 8eeee377e5ab324731cc592f1fa8abe1045ad610
-PASS html5lib_template.html b30690019090149132fc228a7261c5cf2fd149fc
-PASS html5lib_template.html 67a209d928804f90fdb66d070201b23f3d0c8a42
-PASS html5lib_template.html 12104886b8f87daa937eac30b5ff0e1e074eaa6f
-PASS html5lib_template.html 483cc9957a7225fe435112642be59abb4c459a1e
-PASS html5lib_template.html 72d8ac431a154c40ab75d53a258d9d80d47689eb
-PASS html5lib_template.html 1125967cbbcd404f4cb14d48270b8ec778970d77
-PASS html5lib_template.html 32c963e164b9ec82c60e490bb141c1ccc70b992f
-PASS html5lib_template.html 574a95fc9c9f2de3aeaa0c9ee1e6967fc3d4770d
-FAIL html5lib_template.html 332863a7f9e61bff32bd3427ede7a088b790d453 assert_equals: expected "#document\n| <html>\n|   <head>\n|     <template>\n|       content\n|         <template>\n|           content\n|   <body>" but got "#document\n| <html>\n|   <head>\n|     <template>\n|       content\n|         <template>\n|           content\n|             <frame>\n|   <body>"
-PASS html5lib_template.html 2121db07146781773df9e53b94fa921a805175ce
-PASS html5lib_template.html 8675de267cd7e34f2febdee3feb665614d1562fe
-PASS html5lib_template.html c5d26ad923a2b1e988ddd378ca4fb26eb48353e1
-PASS html5lib_template.html eec1542e2fa0e9eafb7f8d4a51eae56b5a31b3c8
-PASS html5lib_template.html b79387a54c3b136db0f28ed96555ff683b3947fe
-PASS html5lib_template.html c477a29a4deb32d072a415fa809a84a4f2beee0c
-PASS html5lib_template.html 26e4480c08e1f5f7b6ac8b8c1832ab0312e3b7c5
-PASS html5lib_template.html 24b3b50fdd0bf8d5cf2ebaa6bf502d7bcfde1da4
-PASS html5lib_template.html d3704c68528357189eb5826ab66eea071d6137a5
-PASS html5lib_template.html d958f7d44faf772d1fb60f1a8f186f837ca735d9
-PASS html5lib_template.html 3fc4d97fa68fc2658356bdbd4e051c867de8de53
-PASS html5lib_template.html 94820107bbf3fab3f82de1f717e8413aead7d3a6
-PASS html5lib_template.html 657c00ebdda37ae060cc69633ed98482ccc29e18
-PASS html5lib_template.html 649fc955a4b60ab2a5b881d94c9493eb4a545002
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/template/additions-to-the-in-frameset-insertion-mode/end-tag-frameset-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/template/additions-to-the-in-frameset-insertion-mode/end-tag-frameset-expected.txt
deleted file mode 100644
index 5b5821c..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/html/syntax/parsing/template/additions-to-the-in-frameset-insertion-mode/end-tag-frameset-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-FAIL <template> tag should be ignored in "in frameset" insertion mode assert_equals: Wrong number of frameset children elements expected 0 but got 1
-Harness: the test ran to completion.
-
diff --git a/third_party/WebKit/LayoutTests/external/wpt/interfaces/orientation-event.idl b/third_party/WebKit/LayoutTests/external/wpt/interfaces/orientation-event.idl
new file mode 100644
index 0000000..aa74fa32
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/interfaces/orientation-event.idl
@@ -0,0 +1,68 @@
+// GENERATED CONTENT - DO NOT EDIT
+// Content of this file was automatically extracted from the
+// "DeviceOrientation Event Specification" spec.
+// See: https://w3c.github.io/deviceorientation/spec-source-orientation.html
+
+partial interface Window {
+      attribute EventHandler ondeviceorientation;
+    };
+
+    [Constructor(DOMString type, optional DeviceOrientationEventInit eventInitDict), Exposed=Window]
+    interface DeviceOrientationEvent : Event {
+      readonly attribute double? alpha;
+      readonly attribute double? beta;
+      readonly attribute double? gamma;
+      readonly attribute boolean absolute;
+    };
+
+    dictionary DeviceOrientationEventInit : EventInit {
+      double? alpha = null;
+      double? beta = null;
+      double? gamma = null;
+      boolean absolute = false;
+    };
+
+    partial interface Window {
+      attribute EventHandler ondevicemotion;
+    };
+
+    [NoInterfaceObject]
+    interface DeviceAcceleration {
+      readonly attribute double? x;
+      readonly attribute double? y;
+      readonly attribute double? z;
+    };
+
+    [NoInterfaceObject]
+    interface DeviceRotationRate {
+      readonly attribute double? alpha;
+      readonly attribute double? beta;
+      readonly attribute double? gamma;
+    };
+
+    [Constructor(DOMString type, optional DeviceMotionEventInit eventInitDict), Exposed=Window]
+    interface DeviceMotionEvent : Event {
+      readonly attribute DeviceAcceleration? acceleration;
+      readonly attribute DeviceAcceleration? accelerationIncludingGravity;
+      readonly attribute DeviceRotationRate? rotationRate;
+      readonly attribute double interval;
+    };
+
+    dictionary DeviceAccelerationInit {
+      double? x = null;
+      double? y = null;
+      double? z = null;
+    };
+
+    dictionary DeviceRotationRateInit {
+      double? alpha = null;
+      double? beta = null;
+      double? gamma = null;
+    };
+
+    dictionary DeviceMotionEventInit : EventInit {
+      DeviceAccelerationInit? acceleration;
+      DeviceAccelerationInit? accelerationIncludingGravity;
+      DeviceRotationRateInit? rotationRate;
+      double interval = 0;
+    };
diff --git a/third_party/WebKit/LayoutTests/external/wpt/orientation-event/idlharness.html b/third_party/WebKit/LayoutTests/external/wpt/orientation-event/idlharness.html
deleted file mode 100644
index dabb45c..0000000
--- a/third_party/WebKit/LayoutTests/external/wpt/orientation-event/idlharness.html
+++ /dev/null
@@ -1,101 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8" />
-<title>DeviceOrientation Event IDL tests</title>
-<link rel="author" title="Intel" href="http://www.intel.com">
-<link rel="help" href="http://dev.w3.org/geo/api/spec-source-orientation.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_idl">
-interface Event {
-};
-
-interface EventHandler {
-};
-
-dictionary EventInit {
-};
-
-interface Window {
-};
-</script>
-
-<script type="text/plain" id="idl">
-partial interface Window {
-  attribute EventHandler ondeviceorientation;
-  attribute EventHandler ondevicemotion;
-};
-
-[Constructor(DOMString type, optional DeviceOrientationEventInit eventInitDict)]
-interface DeviceOrientationEvent : Event {
-  readonly attribute double? alpha;
-  readonly attribute double? beta;
-  readonly attribute double? gamma;
-  readonly attribute boolean absolute;
-};
-
-dictionary DeviceOrientationEventInit : EventInit {
-  double? alpha = null;
-  double? beta = null;
-  double? gamma = null;
-  boolean absolute = false;
-};
-
-[NoInterfaceObject]
-interface DeviceAcceleration {
-  readonly attribute double? x;
-  readonly attribute double? y;
-  readonly attribute double? z;
-};
-
-[NoInterfaceObject]
-interface DeviceRotationRate {
-  readonly attribute double? alpha;
-  readonly attribute double? beta;
-  readonly attribute double? gamma;
-};
-
-[Constructor(DOMString type, optional DeviceMotionEventInit eventInitDict)]
-interface DeviceMotionEvent : Event {
-  readonly attribute DeviceAcceleration? acceleration;
-  readonly attribute DeviceAcceleration? accelerationIncludingGravity;
-  readonly attribute DeviceRotationRate? rotationRate;
-  readonly attribute double interval;
-};
-
-dictionary DeviceAccelerationInit {
-  double? x = null;
-  double? y = null;
-  double? z = null;
-};
-
-dictionary DeviceRotationRateInit {
-  double? alpha = null;
-  double? beta  = null;
-  double? gamma = null;
-};
-
-dictionary DeviceMotionEventInit : EventInit {
-  DeviceAcceleration? acceleration;
-  DeviceAcceleration? accelerationIncludingGravity;
-  DeviceRotationRate? rotationRate;
-  double interval = 0;
-};
-</script>
-
-<script>
-"use strict";
-var idl_array = new IdlArray();
-
-idl_array.add_untested_idls(document.getElementById("untested_idl").textContent);
-idl_array.add_idls(document.getElementById("idl").textContent);
-
-idl_array.add_objects({
-  DeviceOrientationEvent: ['new DeviceOrientationEvent("foo")'],
-  DeviceMotionEvent: ['new DeviceMotionEvent("foo")'],
-});
-
-idl_array.test();
-</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/orientation-event/idlharness.window.js b/third_party/WebKit/LayoutTests/external/wpt/orientation-event/idlharness.window.js
new file mode 100644
index 0000000..ed8309d
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/orientation-event/idlharness.window.js
@@ -0,0 +1,23 @@
+// META: script=/resources/WebIDLParser.js
+// META: script=/resources/idlharness.js
+
+// https://w3c.github.io/deviceorientation/spec-source-orientation.html
+
+'use strict';
+
+promise_test(async () => {
+  const idl = await fetch('/interfaces/orientation-event.idl').then(r => r.text());
+  const dom = await fetch('/interfaces/dom.idl').then(r => r.text());
+  const html = await fetch('/interfaces/html.idl').then(r => r.text());
+
+  var idl_array = new IdlArray();
+  idl_array.add_idls(idl);
+  idl_array.add_dependency_idls(html);
+  idl_array.add_dependency_idls(dom);
+  idl_array.add_objects({
+    Window: ['window'],
+    DeviceOrientationEvent: ['new DeviceOrientationEvent("foo")'],
+    DeviceMotionEvent: ['new DeviceMotionEvent("foo")'],
+  });
+  idl_array.test();
+}, 'orientation-event interfaces');
diff --git a/third_party/WebKit/LayoutTests/external/wpt/svg/painting/reftests/paint-context-001-ref.svg b/third_party/WebKit/LayoutTests/external/wpt/svg/painting/reftests/paint-context-001-ref.svg
new file mode 100644
index 0000000..99bd8c4
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/svg/painting/reftests/paint-context-001-ref.svg
@@ -0,0 +1,44 @@
+<svg id="svg-root"
+  width="100%" height="100%" viewBox="0 0 480 360"
+  xmlns="http://www.w3.org/2000/svg"
+  xmlns:xlink="http://www.w3.org/1999/xlink"
+  xmlns:html="http://www.w3.org/1999/xhtml">
+  <g id="testmeta">
+    <title>Paint: 'paint-order'</title>
+    <html:link rel="author"
+          title="Tavmjong Bah"
+          href="http://tavmjong.free.fr"/>
+  </g>
+
+  <style id="test-font" type="text/css">
+    /* Standard Font (if needed). */
+    @font-face {
+      font-family: FreeSans;
+      src: url("../fonts/FreeSans.woff") format("woff");
+    }
+    text {
+      font-family: FreeSans, sans-serif;
+      text-anchor: middle;
+      fill: black;
+    }
+    #title {
+      font-size: 24px;
+    }
+    .label {
+      font-size: 18px;
+    }
+  </style>
+
+  <defs>
+    <rect id="rectangle" width="2" height="2" style="fill:lime;stroke:blue" />
+    <marker id="marker" style="overflow:visible" markerWidth="2" markerHeight="2" orient="auto" viewBox="0 0 2 2" refX="1" refY="1">
+      <use xlink:href="#rectangle"/>
+    </marker>
+    <path id="path" d="m -25,-25 0,50 50,0 0,-50 z"/>
+  </defs>
+
+  <g id="test-reference" font-size="16" style="fill:blue;stroke:lime;stroke-width:15px;marker:url(#marker)">
+    <path d="m 120,220 c 120,120 120,-120 240,0"/>
+  </g>
+
+</svg>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/svg/painting/reftests/paint-context-001.svg b/third_party/WebKit/LayoutTests/external/wpt/svg/painting/reftests/paint-context-001.svg
new file mode 100644
index 0000000..fd58d9b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/svg/painting/reftests/paint-context-001.svg
@@ -0,0 +1,47 @@
+<svg id="svg-root"
+  width="100%" height="100%" viewBox="0 0 480 360"
+  xmlns="http://www.w3.org/2000/svg"
+  xmlns:xlink="http://www.w3.org/1999/xlink"
+  xmlns:html="http://www.w3.org/1999/xhtml">
+  <g id="testmeta">
+    <title>Paint: 'context-fill' and 'context-stroke'</title>
+    <html:link rel="author"
+          title="Tavmjong Bah"
+          href="http://tavmjong.free.fr"/>
+    <html:link rel="help"
+          href="https://www.w3.org/TR/SVG2/painting.html#SpecifyingPaint"/>
+    <html:link rel="match"  href="paint-context-001-ref.svg" />
+  </g>
+
+  <style id="test-font" type="text/css">
+    /* Standard Font (if needed). */
+    @font-face {
+      font-family: FreeSans;
+      src: url("../fonts/FreeSans.woff") format("woff");
+    }
+    text {
+      font-family: FreeSans, sans-serif;
+      text-anchor: middle;
+      fill: black;
+    }
+    #title {
+      font-size: 24px;
+    }
+    .label {
+      font-size: 18px;
+    }
+  </style>
+
+  <defs>
+    <rect id="rectangle" width="2" height="2" style="fill:context-stroke;stroke:context-fill" />
+    <marker id="marker" style="overflow:visible" markerWidth="2" markerHeight="2" orient="auto" viewBox="0 0 2 2" refX="1" refY="1">
+      <use xlink:href="#rectangle"/>
+    </marker>
+    <path id="path" d="m -25,-25 0,50 50,0 0,-50 z"/>
+  </defs>
+
+  <g id="test-body-content" font-size="16" style="fill:blue;stroke:lime;stroke-width:15px;marker:url(#marker)">
+    <path d="m 120,220 c 120,120 120,-120 240,0"/>
+  </g>
+
+</svg>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/svg/painting/reftests/paint-context-002-ref.svg b/third_party/WebKit/LayoutTests/external/wpt/svg/painting/reftests/paint-context-002-ref.svg
new file mode 100644
index 0000000..446e8e3
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/svg/painting/reftests/paint-context-002-ref.svg
@@ -0,0 +1,41 @@
+<svg id="svg-root"
+  width="100%" height="100%" viewBox="0 0 480 360"
+  xmlns="http://www.w3.org/2000/svg"
+  xmlns:xlink="http://www.w3.org/1999/xlink"
+  xmlns:html="http://www.w3.org/1999/xhtml">
+  <g id="testmeta">
+    <title>Paint: 'paint-order'</title>
+    <html:link rel="author"
+          title="Tavmjong Bah"
+          href="http://tavmjong.free.fr"/>
+  </g>
+
+  <style id="test-font" type="text/css">
+    /* Standard Font (if needed). */
+    @font-face {
+      font-family: FreeSans;
+      src: url("../fonts/FreeSans.woff") format("woff");
+    }
+    text {
+      font-family: FreeSans, sans-serif;
+      text-anchor: middle;
+      fill: black;
+    }
+    #title {
+      font-size: 24px;
+    }
+    .label {
+      font-size: 18px;
+    }
+  </style>
+
+  <defs>
+    <rect id="rectangle" width="120" height="120" />
+  </defs>
+
+  <g id="test-reference" font-size="16" style="fill:lime;stroke:blue;stroke-width:15px">
+    <use xlink:href="#rectangle" transform="translate(60,120)"/>
+    <use xlink:href="#rectangle" transform="translate(300,120)" style="fill:lightblue;stroke:green"/>
+  </g>
+
+</svg>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/svg/painting/reftests/paint-context-002.svg b/third_party/WebKit/LayoutTests/external/wpt/svg/painting/reftests/paint-context-002.svg
new file mode 100644
index 0000000..8a8a378
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/external/wpt/svg/painting/reftests/paint-context-002.svg
@@ -0,0 +1,44 @@
+<svg id="svg-root"
+  width="100%" height="100%" viewBox="0 0 480 360"
+  xmlns="http://www.w3.org/2000/svg"
+  xmlns:xlink="http://www.w3.org/1999/xlink"
+  xmlns:html="http://www.w3.org/1999/xhtml">
+  <g id="testmeta">
+    <title>Paint: 'context-fill' and 'context-stroke'</title>
+    <html:link rel="author"
+          title="Tavmjong Bah"
+          href="http://tavmjong.free.fr"/>
+    <html:link rel="help"
+          href="https://www.w3.org/TR/SVG2/painting.html#SpecifyingPaint"/>
+    <html:link rel="match"  href="paint-context-002-ref.svg" />
+  </g>
+
+  <style id="test-font" type="text/css">
+    /* Standard Font (if needed). */
+    @font-face {
+      font-family: FreeSans;
+      src: url("../fonts/FreeSans.woff") format("woff");
+    }
+    text {
+      font-family: FreeSans, sans-serif;
+      text-anchor: middle;
+      fill: black;
+    }
+    #title {
+      font-size: 24px;
+    }
+    .label {
+      font-size: 18px;
+    }
+  </style>
+
+  <defs>
+    <rect id="rectangle" width="120" height="120" style="fill:context-stroke;stroke:context-fill" />
+  </defs>
+
+  <g id="test-body-content" font-size="16" style="fill:blue;stroke:lime;stroke-width:15px">
+    <use xlink:href="#rectangle" transform="translate(60,120)"/>
+    <use xlink:href="#rectangle" transform="translate(300,120)" style="fill:green;stroke:lightblue"/>
+  </g>
+
+</svg>
diff --git a/third_party/WebKit/LayoutTests/fast/dom/custom/svg-use-shadow-tree-expected.txt b/third_party/WebKit/LayoutTests/fast/dom/custom/svg-use-shadow-tree-expected.txt
index 43f63b1..e5467a2e 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/custom/svg-use-shadow-tree-expected.txt
+++ b/third_party/WebKit/LayoutTests/fast/dom/custom/svg-use-shadow-tree-expected.txt
@@ -1,9 +1,4 @@
-CONSOLE ERROR: line 2748: Uncaught Error: assert_false: Should not call createdCallback in UA ShadowRoot. expected false got true
-CONSOLE ERROR: line 2748: Uncaught Error: assert_false: Should not call attachedCallback in UA ShadowRoot. expected false got true
-CONSOLE ERROR: line 2748: Uncaught Error: assert_false: Should not call createdCallback in UA ShadowRoot. expected false got true
-CONSOLE ERROR: line 2748: Uncaught Error: assert_false: Should not call attachedCallback in UA ShadowRoot. expected false got true
 This is a testharness.js-based test.
-Harness Error. harness_status.status = 1 , harness_status.message = Uncaught Error: assert_false: Should not call attachedCallback in UA ShadowRoot. expected false got true
-PASS SVG <use> shadow trees should not be exposed through custom elements.
+FAIL SVG <use> shadow trees should not be exposed through custom elements. assert_false: Should not call createdCallback in UA ShadowRoot. expected false got true
 Harness: the test ran to completion.
 
diff --git a/third_party/WebKit/LayoutTests/fast/dom/custom/svg-use-shadow-tree.html b/third_party/WebKit/LayoutTests/fast/dom/custom/svg-use-shadow-tree.html
index 9222cbd..8ebf7f12 100644
--- a/third_party/WebKit/LayoutTests/fast/dom/custom/svg-use-shadow-tree.html
+++ b/third_party/WebKit/LayoutTests/fast/dom/custom/svg-use-shadow-tree.html
@@ -23,6 +23,8 @@
 <script>
 "use strict";
 
+var t = async_test("SVG <use> shadow trees should not be exposed through custom elements.");
+
 var instances = [];
 
 function createPrototype(superClass) {
@@ -34,40 +36,48 @@
             return scope;
         }
         createdCallback() {
-            this.instanceId = instances.length;
-            instances[this.instanceId] = this;
-            assert_false(this.ownerScope instanceof ShadowRoot,
-                "Should not call createdCallback in UA ShadowRoot.");
+            t.step(() => {
+                this.instanceId = instances.length;
+                instances[this.instanceId] = this;
+                assert_false(this.ownerScope instanceof ShadowRoot,
+                    "Should not call createdCallback in UA ShadowRoot.");
+            });
         }
         attachedCallback() {
-            assert_false(this.ownerScope instanceof ShadowRoot,
-                "Should not call attachedCallback in UA ShadowRoot.");
-            assert_equals(instances[this.instanceId], this);
+            t.step(() => {
+                assert_false(this.ownerScope instanceof ShadowRoot,
+                    "Should not call attachedCallback in UA ShadowRoot.");
+                assert_equals(instances[this.instanceId], this);
+            });
         }
         detachedCallback() {
-            assert_false(this.ownerScope instanceof ShadowRoot,
-                "Should not call detachedCallback in UA ShadowRoot.");
-            assert_equals(instances[this.instanceId], this);
+            t.step(() => {
+                assert_false(this.ownerScope instanceof ShadowRoot,
+                    "Should not call detachedCallback in UA ShadowRoot.");
+                assert_equals(instances[this.instanceId], this);
+            });
         }
         attributeChangedCallback() {
-            assert_unreached("attributeChangedCallback should never be called.");
+            t.step(() => {
+                assert_unreached("attributeChangedCallback should never be called.");
+            });
         }
     };
     return ElementType.prototype;
 }
 
-// <rect is=x-rect>
-var XRectElement = document.registerElement('x-rect', {
-    extends: 'rect',
-    prototype: createPrototype(SVGRectElement),
-});
+t.step(function () {
+    // <rect is=x-rect>
+    var XRectElement = document.registerElement('x-rect', {
+        extends: 'rect',
+        prototype: createPrototype(SVGRectElement),
+    });
 
-// <x-test>
-var XTestElement = document.registerElement('x-test', {
-    prototype: createPrototype(HTMLElement),
-});
+    // <x-test>
+    var XTestElement = document.registerElement('x-test', {
+        prototype: createPrototype(HTMLElement),
+    });
 
-test(function () {
     var template = document.getElementById("template");
     var svg = document.importNode(template.content, true).firstElementChild;
     var usedGroup = svg.getElementById("used-group");
@@ -97,5 +107,9 @@
         assert_true(instances[i].ownerScope instanceof Document,
             "No instances should be inside a ShadowRoot.");
     }
-}, "SVG <use> shadow trees should not be exposed through custom elements.");
+
+    // Any callbacks will have been scheduled and run in microtasks,
+    // so end test after that.
+    t.step_timeout(t.step_func_done());
+});
 </script>
diff --git a/third_party/WebKit/LayoutTests/fast/events/mouse-wheel-main-frame-scroll-expected.txt b/third_party/WebKit/LayoutTests/fast/events/mouse-wheel-main-frame-scroll-expected.txt
new file mode 100644
index 0000000..43e5eeed
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/events/mouse-wheel-main-frame-scroll-expected.txt
@@ -0,0 +1,4 @@
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/third_party/WebKit/LayoutTests/fast/events/mouse-wheel-main-frame-scroll.html b/third_party/WebKit/LayoutTests/fast/events/mouse-wheel-main-frame-scroll.html
index 34f60069..e146e97 100644
--- a/third_party/WebKit/LayoutTests/fast/events/mouse-wheel-main-frame-scroll.html
+++ b/third_party/WebKit/LayoutTests/fast/events/mouse-wheel-main-frame-scroll.html
@@ -1,20 +1,27 @@
 <!DOCTYPE HTML>
 <html style="height:100%; overflow:scroll;">
 <head>
-<script src="../../resources/testharness.js"></script>
-<script src="../../resources/testharnessreport.js"></script>
-<script src="../../resources/gesture-util.js"></script>
-</head>
+<script src="../../resources/js-test.js"></script>
 <script>
-promise_test (async () => {
-	await mouseMoveTo(50, 50);
-	await smoothScroll(100, 50, 50, GestureSourceType.MOUSE_INPUT, 'down', SPEED_INSTANT);
-	await waitFor( () => {
-		return window.scrollY == 100;
-	});
-},"Mouse wheel scrolls properly on main frame.");
+jsTestIsAsync = true;
+
+function finishTest() {
+  if (window.scrollY == 100 && window.scrollX == 0)
+    finishJSTest();
+  else
+    requestAnimationFrame(finishTest);
+}
+
+function test() {
+    if (window.eventSender) {
+        eventSender.mouseMoveTo(50, 50);
+        eventSender.continuousMouseScrollBy(0, -100);
+        finishTest();
+    }
+}
 </script>
-<body>
+</head>
+<body onload="test()">
 <div style="height:1000px;">
 </div>
 </body>
diff --git a/third_party/WebKit/LayoutTests/fast/events/touch/touch-latched-scroll-node-removed.html b/third_party/WebKit/LayoutTests/fast/events/touch/touch-latched-scroll-node-removed.html
deleted file mode 100644
index 44c9754c..0000000
--- a/third_party/WebKit/LayoutTests/fast/events/touch/touch-latched-scroll-node-removed.html
+++ /dev/null
@@ -1,72 +0,0 @@
-<!DOCTYPE HTML>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/gesture-util.js"></script>
-<style>
-
-  ::-webkit-scrollbar {
-    display: none;
-  }
-  body {
-    margin: 0px;
-    height: 1000px;
-    width: 1000px;
-  }
-  #parentDiv {
-    background-color: #FF7F7F;
-    height: 600px;
-    width: 600px;
-    overflow: scroll;
-  }
-  #content1 {
-    height: 700px;
-    width: 700px;
-  }
-  #childDiv {
-    background-color: #84BE6A;
-    height: 500px;
-    width: 500px;
-    overflow: scroll;
-  }
-  #content2 {
-    height: 600px;
-    width: 600px;
-  }
-</style>
-
-<div id="parentDiv">
-  <div id="content1">
-    <div id="childDiv">
-      <div id="content2">
-      </div>
-    </div>
-  </div>
-</div>
-
-<script>
-var parentDiv = document.getElementById('parentDiv');
-var childDiv = document.getElementById('childDiv');
-var rect = childDiv.getBoundingClientRect();
-
-function setUpForTest() {
-  if (window.internals)
-    internals.settings.setScrollAnimatorEnabled(false);
-  parentDiv.scrollTo(0, 0);
-  childDiv.scrollTo(0, 0);
-}
-
-childDiv.addEventListener('scroll', () => {
-  if(childDiv.scrollTop > 0)
-    childDiv.remove();
-});
-
-promise_test( async () => {
-  setUpForTest();
-  // Start scrolling on the child div and remove the div in the middle of
-  // scrolling, then check that parentDiv starts scrolling.
-  var x = (rect.left + rect.right) / 2;
-  var y = (rect.top + rect.bottom) / 2;
-  await smoothScroll(70, x, y, GestureSourceType.TOUCH_INPUT, 'down');
-  await waitFor( () => {return parentDiv.scrollTop > 0});
-}, "New node must start wheel scrolling when the latched node is removed.");
-</script>
diff --git a/third_party/WebKit/LayoutTests/fast/events/wheel/latched-scroll-node-removed.html b/third_party/WebKit/LayoutTests/fast/events/wheel/latched-scroll-node-removed.html
new file mode 100644
index 0000000..77fecacc
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/events/wheel/latched-scroll-node-removed.html
@@ -0,0 +1,94 @@
+<!DOCTYPE HTML>
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
+<style>
+
+  ::-webkit-scrollbar {
+    display: none;
+  }
+  body {
+    margin: 0px;
+    height: 1000px;
+    width: 1000px;
+  }
+  #parentDiv {
+    background-color: #FF7F7F;
+    height: 600px;
+    width: 600px;
+    overflow: scroll;
+  }
+  #content1 {
+    height: 700px;
+    width: 700px;
+  }
+  #childDiv {
+    background-color: #84BE6A;
+    height: 500px;
+    width: 500px;
+    overflow: scroll;
+  }
+  #content2 {
+    height: 600px;
+    width: 600px;
+  }
+</style>
+
+<div id="parentDiv">
+  <div id="content1">
+    <div id="childDiv">
+      <div id="content2">
+      </div>
+    </div>
+  </div>
+</div>
+
+<script>
+var parentDiv = document.getElementById('parentDiv');
+var childDiv = document.getElementById('childDiv');
+var rect = childDiv.getBoundingClientRect();
+var source = "touchpad";
+
+function setUpForTest() {
+  if (window.internals)
+    internals.settings.setScrollAnimatorEnabled(false);
+  if (!document.getElementById('childDiv'))
+     document.getElementById('content1').appendChild(childDiv);
+  parentDiv.scrollTo(0, 0);
+  childDiv.scrollTo(0, 0);
+}
+
+function sendScrollEventsAndCheck() {
+  // Start scrolling on the child div.
+  eventSender.gestureScrollBegin(source,
+                                 (rect.left + rect.right) / 2,
+                                 (rect.top + rect.bottom) / 2);
+  eventSender.gestureScrollUpdate(source, 0, -70);
+
+  // Check that childDiv fully consumes scroll delta, then remove the div.
+  assert_equals(parentDiv.scrollTop, 0,
+        "The parent div should not scroll.");
+  assert_equals(childDiv.scrollTop, 70,
+        "The child div should fully comsume scroll delta.");
+  childDiv.remove();
+
+  // Send the next GSU event and check that parentDiv scrolls.
+  eventSender.gestureScrollUpdate(source, 0, -30);
+  assert_greater_than(parentDiv.scrollTop, 0,
+        "The parent div should start scrolling.");
+
+  // Finish scrolling.
+  eventSender.gestureScrollEnd(source,
+                               (rect.left + rect.right) / 2,
+                               (rect.top + rect.bottom) / 2);
+}
+
+test(() => {
+  setUpForTest();
+  sendScrollEventsAndCheck();
+}, "New node must start wheel scrolling when the latched node is removed.");
+test(() => {
+  source = "touchscreen";
+  setUpForTest();
+  sendScrollEventsAndCheck();
+}, "New node must start touch scrolling when the latched node is removed.");
+</script>
diff --git a/third_party/WebKit/LayoutTests/fast/events/wheel/wheel-in-scrollbar-expected.txt b/third_party/WebKit/LayoutTests/fast/events/wheel/wheel-in-scrollbar-expected.txt
new file mode 100644
index 0000000..97ee933
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/events/wheel/wheel-in-scrollbar-expected.txt
@@ -0,0 +1,11 @@
+Test that wheel scrolling over the page scrollbar scrolls the page. We also placed an overflow div below the scrollbar to make sure we target the page and not the div in that case.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS window.scrollY is 30
+PASS overflowDiv.scrollTop is 0
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/third_party/WebKit/LayoutTests/fast/events/wheel/wheel-in-scrollbar.html b/third_party/WebKit/LayoutTests/fast/events/wheel/wheel-in-scrollbar.html
index f15210d2..9689f4e 100644
--- a/third_party/WebKit/LayoutTests/fast/events/wheel/wheel-in-scrollbar.html
+++ b/third_party/WebKit/LayoutTests/fast/events/wheel/wheel-in-scrollbar.html
@@ -1,31 +1,38 @@
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/gesture-util.js"></script>
-<body style="margin:0">
-  <div id="overflowDiv" style="width:1000px; height:500px; overflow:scroll">
-    <div style="height: 1000px"></div>
-  </div>
-  <div style="height: 1000px"></div>
-</body>
+<script src="../../../resources/js-test.js"></script>
 <script>
-  internals.settings.setScrollAnimatorEnabled(false);
-  var overflowDiv = document.getElementById('overflowDiv');
+    window.jsTestIsAsync = true;
 
-  promise_test (async () => {
-    overflowDiv.addEventListener("scroll", () => {
-      Promise.reject('overflowDiv should not scroll.');
-    });
+    description("Test that wheel scrolling over the page scrollbar scrolls " +
+                "the page. We also placed an overflow div below the " +
+                "scrollbar to make sure we target the page and not the div " +
+                "in that case.");
 
-    // Move the mouse over the vertical scrollbar.
-    await mouseMoveTo(790, 300);
+    var overflowDiv;
 
-    // Scroll down precisely by 30 px.
-    await smoothScroll(30, 790, 300, GestureSourceType.MOUSE_INPUT, 'down', SPEED_INSTANT);
+    window.onload = function() {
+        if (!window.testRunner || !window.eventSender)
+            return;
 
-    await waitFor( () => {return window.scrollY == 30});
-  }, "Test that wheel scrolling over the page scrollbar scrolls " +
-      "the page. We also placed an overflow div below the " +
-      "scrollbar to make sure we target the page and not the div " +
-      "in that case.");
+        internals.settings.setScrollAnimatorEnabled(false);
+
+        overflowDiv = document.getElementById('overflowDiv');
+
+        // Move the mouse over the vertical scrollbar.
+        eventSender.mouseMoveTo(790, 300);
+
+        // Scroll down precisely by 30 px.
+        eventSender.continuousMouseScrollBy(0, -30, false, true);
+
+        shouldBe('window.scrollY', '30');
+        shouldBe('overflowDiv.scrollTop', '0');
+        finishJSTest();
+    }
 </script>
+
+<body style="margin:0">
+    <div id="overflowDiv" style="width:1000px; height:500px; overflow:scroll">
+      <div style="height: 1000px"></div>
+    </div>
+    <div style="height: 1000px"></div>
+</body>
diff --git a/third_party/WebKit/LayoutTests/fast/events/wheel/wheel-latched-scroll-node-removed.html b/third_party/WebKit/LayoutTests/fast/events/wheel/wheel-latched-scroll-node-removed.html
deleted file mode 100644
index 02e93810..0000000
--- a/third_party/WebKit/LayoutTests/fast/events/wheel/wheel-latched-scroll-node-removed.html
+++ /dev/null
@@ -1,72 +0,0 @@
-<!DOCTYPE HTML>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/gesture-util.js"></script>
-<style>
-
-  ::-webkit-scrollbar {
-    display: none;
-  }
-  body {
-    margin: 0px;
-    height: 1000px;
-    width: 1000px;
-  }
-  #parentDiv {
-    background-color: #FF7F7F;
-    height: 600px;
-    width: 600px;
-    overflow: scroll;
-  }
-  #content1 {
-    height: 700px;
-    width: 700px;
-  }
-  #childDiv {
-    background-color: #84BE6A;
-    height: 500px;
-    width: 500px;
-    overflow: scroll;
-  }
-  #content2 {
-    height: 600px;
-    width: 600px;
-  }
-</style>
-
-<div id="parentDiv">
-  <div id="content1">
-    <div id="childDiv">
-      <div id="content2">
-      </div>
-    </div>
-  </div>
-</div>
-
-<script>
-var parentDiv = document.getElementById('parentDiv');
-var childDiv = document.getElementById('childDiv');
-var rect = childDiv.getBoundingClientRect();
-
-function setUpForTest() {
-  if (window.internals)
-    internals.settings.setScrollAnimatorEnabled(false);
-  parentDiv.scrollTo(0, 0);
-  childDiv.scrollTo(0, 0);
-}
-
-childDiv.addEventListener('scroll', () => {
-  if(childDiv.scrollTop > 0)
-    childDiv.remove();
-});
-
-promise_test( async () => {
-  setUpForTest();
-  // Start scrolling on the child div and remove the div in the middle of
-  // scrolling, then check that parentDiv starts scrolling.
-  var x = (rect.left + rect.right) / 2;
-  var y = (rect.top + rect.bottom) / 2;
-  await smoothScroll(70, x, y, GestureSourceType.MOUSE_INPUT, 'down');
-  await waitFor( () => {return parentDiv.scrollTop > 0});
-}, "New node must start wheel scrolling when the latched node is removed.");
-</script>
diff --git a/third_party/WebKit/LayoutTests/fast/events/wheel/wheelevent-basic-expected.txt b/third_party/WebKit/LayoutTests/fast/events/wheel/wheelevent-basic-expected.txt
new file mode 100644
index 0000000..d189f863
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/events/wheel/wheelevent-basic-expected.txt
@@ -0,0 +1,30 @@
+TOP TOP TOP TOP TOP TOP TOP TOP TOP TOP TOP TOP TOP TOP
+Scroll mouse wheel over here
+Scroll mouse wheel over here
+Scroll mouse wheel over here
+Scroll mouse wheel over here
+Scroll mouse wheel over here
+Scroll mouse wheel over here
+END END END END END END END END END END END END END END
+Tests the basic functionality of the standard wheel event
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS WheelEvent.__proto__ is MouseEvent
+PASS WheelEvent.prototype.__proto__ is MouseEvent.prototype
+PASS WheelEvent.DOM_DELTA_PIXEL is 0x00
+PASS WheelEvent.DOM_DELTA_LINE is 0x01
+PASS WheelEvent.DOM_DELTA_PAGE is 0x02
+PASS window.onwheel is null
+PASS document.onwheel is null
+PASS testDiv.onwheel is null
+PASS testEvent.__proto__ is WheelEvent.prototype
+PASS testEvent.__proto__.__proto__ is MouseEvent.prototype
+PASS testEvent.deltaZ is 0
+PASS testEvent.deltaMode is WheelEvent.DOM_DELTA_PIXEL
+PASS deltaX > 0 && deltaY > 0 && deltaX == testDiv.scrollLeft && deltaY == testDiv.scrollTop became true
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/third_party/WebKit/LayoutTests/fast/events/wheel/wheelevent-basic.html b/third_party/WebKit/LayoutTests/fast/events/wheel/wheelevent-basic.html
index aac7303..e4fbfce9 100644
--- a/third_party/WebKit/LayoutTests/fast/events/wheel/wheelevent-basic.html
+++ b/third_party/WebKit/LayoutTests/fast/events/wheel/wheelevent-basic.html
@@ -2,63 +2,71 @@
 <html>
 <head>
 <link rel="help" href="http://www.w3.org/TR/DOM-Level-3-Events/#events-WheelEvent">
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/gesture-util.js"></script>
-</head>
-<body>
-<span id="parent">
-  <div id="target" style="border:solid 1px green; width:220px; height:70px; overflow:scroll; white-space:nowrap;">
-    TOP TOP TOP TOP TOP TOP TOP TOP TOP TOP TOP TOP TOP TOP<br/>
-    Scroll mouse wheel over here<br/>
-    Scroll mouse wheel over here<br/>
-    Scroll mouse wheel over here<br/>
-    Scroll mouse wheel over here<br/>
-    Scroll mouse wheel over here<br/>
-    Scroll mouse wheel over here<br/>
-    END END END END END END END END END END END END END END<br/>
-  </div>
-</span>
-<div id="console"></div>
-</body>
+<script src="../../../resources/js-test.js"></script>
 <script>
+window.jsTestIsAsync = true;
+
 var deltaX = 0;
 var deltaY = 0;
 
-promise_test(async () => {
-  // Basic checks.
-  assert_equals(WheelEvent.__proto__, MouseEvent);
-  assert_equals(WheelEvent.prototype.__proto__, MouseEvent.prototype);
-  assert_equals(WheelEvent.DOM_DELTA_PIXEL, 0x00);
-  assert_equals(WheelEvent.DOM_DELTA_LINE, 0x01);
-  assert_equals(WheelEvent.DOM_DELTA_PAGE, 0x02);
+var testDiv;
+function runTest() {
+    // Basic checks.
+    shouldBe('WheelEvent.__proto__', 'MouseEvent');
+    shouldBe('WheelEvent.prototype.__proto__', 'MouseEvent.prototype');
+    shouldBe('WheelEvent.DOM_DELTA_PIXEL', '0x00');
+    shouldBe('WheelEvent.DOM_DELTA_LINE', '0x01');
+    shouldBe('WheelEvent.DOM_DELTA_PAGE', '0x02');
 
-  var testDiv = document.getElementById('target');
-  assert_equals(window.onwheel, null);
-  assert_equals(document.onwheel, null);
-  assert_equals(testDiv.onwheel, null);
-  testDiv.addEventListener('wheel', wheelHandler);
-  var x = testDiv.offsetLeft + 5;
-  var y = testDiv.offsetTop + 5;
-  await mouseMoveTo(x, y);
-  await smoothScroll(40, x, y, GestureSourceType.MOUSE_INPUT, 'downright', SPEED_INSTANT);
-  await waitFor( () => {
-    return deltaX > 0 && deltaY > 0 && deltaX == testDiv.scrollLeft &&
-        deltaY == testDiv.scrollTop;
-  });
-}, "Tests the basic functionality of the standard wheel event");
+    testDiv = document.getElementById('target');
+    shouldBeNull('window.onwheel');
+    shouldBeNull('document.onwheel');
+    shouldBeNull('testDiv.onwheel');
+    testDiv.addEventListener('wheel', wheelHandler);
+    if (window.eventSender) {
+        eventSender.mouseMoveTo(testDiv.offsetLeft + 5, testDiv.offsetTop + 5);
+        eventSender.mouseScrollBy(-1, -2, false, false, 0, true, 'phaseBegan');
+        var positive = "deltaX > 0 && deltaY > 0";
+        var correct = "deltaX == testDiv.scrollLeft && deltaY == testDiv.scrollTop";
+        shouldBecomeEqual(positive + " && " + correct , "true", finishJSTest);
+    } else {
+        debug("FAIL: This test requires window.eventSender.");
+    }
+}
 
 var testEvent;
 function wheelHandler(e) {
-  testEvent = e;
-  assert_equals(testEvent.__proto__, WheelEvent.prototype);
-  assert_equals(testEvent.__proto__.__proto__, MouseEvent.prototype);
-  if (e.deltaX)
-    deltaX = e.deltaX;
-  if (e.deltaY)
-    deltaY = e.deltaY;
-  assert_equals(testEvent.deltaZ, 0);
-  assert_equals(testEvent.deltaMode, WheelEvent.DOM_DELTA_PIXEL);
+    testEvent = e;
+    shouldBe("testEvent.__proto__", "WheelEvent.prototype");
+    shouldBe("testEvent.__proto__.__proto__", "MouseEvent.prototype");
+    if (e.deltaX)
+      deltaX = e.deltaX;
+    if (e.deltaY)
+      deltaY = e.deltaY;
+    shouldBe("testEvent.deltaZ", "0");
+    shouldBe("testEvent.deltaMode", "WheelEvent.DOM_DELTA_PIXEL")
 }
+
 </script>
+</head>
+<body>
+<span id="parent">
+    <div id="target" style="border:solid 1px green; width:220px; height:70px; overflow:scroll; white-space:nowrap;">
+        TOP TOP TOP TOP TOP TOP TOP TOP TOP TOP TOP TOP TOP TOP<br/>
+        Scroll mouse wheel over here<br/>
+        Scroll mouse wheel over here<br/>
+        Scroll mouse wheel over here<br/>
+        Scroll mouse wheel over here<br/>
+        Scroll mouse wheel over here<br/>
+        Scroll mouse wheel over here<br/>
+        END END END END END END END END END END END END END END<br/>
+    </div>
+</span>
+<div id="console"></div>
+<script>
+description("Tests the basic functionality of the standard wheel event");
+
+runTest();
+</script>
+</body>
 </html>
diff --git a/third_party/WebKit/LayoutTests/fast/events/wheel/wheelevent-in-horizontal-scrollbar-in-rtl-expected.txt b/third_party/WebKit/LayoutTests/fast/events/wheel/wheelevent-in-horizontal-scrollbar-in-rtl-expected.txt
new file mode 100644
index 0000000..2e56675
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/events/wheel/wheelevent-in-horizontal-scrollbar-in-rtl-expected.txt
@@ -0,0 +1,9 @@
+Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
+PASS window.scrollX == -90 && window.scrollY == 100 became true
+PASS window.scrollX == -120 && window.scrollY == 100 became true
+PASS window.scrollX == -120 && window.scrollY == 110 became true
+PASS window.scrollX == -120 && window.scrollY == 80 became true
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/third_party/WebKit/LayoutTests/fast/events/wheel/wheelevent-in-horizontal-scrollbar-in-rtl.html b/third_party/WebKit/LayoutTests/fast/events/wheel/wheelevent-in-horizontal-scrollbar-in-rtl.html
index 9ca8c10..9d4b09e 100644
--- a/third_party/WebKit/LayoutTests/fast/events/wheel/wheelevent-in-horizontal-scrollbar-in-rtl.html
+++ b/third_party/WebKit/LayoutTests/fast/events/wheel/wheelevent-in-horizontal-scrollbar-in-rtl.html
@@ -1,43 +1,40 @@
 <html dir=rtl>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/gesture-util.js"></script>
+
+<script src="../../../resources/js-test.js"></script>
 <script>
-  var testScrolls = [
-    {distance: 10, expectedX: -90, expectedY: 100, direction: 'right'},
-    {distance: 30, expectedX: -120, expectedY: 100, direction: 'left'},
-    {distance: 10, expectedX: -120, expectedY: 110, direction: 'down'},
-    {distance: 30, expectedX: -120, expectedY: 80, direction: 'up'},
-  ];
-  var currentTest = -1;
+    var testScrolls = [
+        {x: -10, y: 0, expectedX: -90, expectedY: 100},
+        {x: 30, y: 0, expectedX: -120, expectedY: 100},
+        {x: 0, y: -10, expectedX: -120, expectedY: 110},
+        {x: 0, y: 30, expectedX: -120, expectedY: 80},
+    ];
+    var currentTest = -1;
+    window.jsTestIsAsync = true;
 
-  function startNextTestCase() {
-    currentTest++;
-    if (currentTest >= testScrolls.length)
-      return;
+    function startNextTestCase() {
+        currentTest++;
+        if (currentTest >= testScrolls.length) {
+            finishJSTest();
+            return;
+        }
+        var testCase = testScrolls[currentTest];
+        eventSender.mouseMoveTo(100, 100);
+        eventSender.continuousMouseScrollBy(testCase.x, testCase.y);
+        shouldBecomeEqual("window.scrollX == " + testCase.expectedX + " && " +
+            "window.scrollY == " + testCase.expectedY, "true", startNextTestCase);
+    }
 
-    var testCase = testScrolls[currentTest];
-    promise_test(async () => {
-      await mouseMoveTo(100, 100);
-      await smoothScroll(testCase.distance, 100, 100,
-          GestureSourceType.MOUSE_INPUT, testCase.direction, SPEED_INSTANT);
-      await waitFor( () => {
-        return window.scrollX == testCase.expectedX &&
-            window.scrollY == testCase.expectedY;
-      });
-      startNextTestCase();
-    }, 'scroll ' + testCase.direction);
-  }
-
-  window.onload = function() {
-    window.addEventListener("mousewheel", function (e){}, false);
-    window.scrollTo(-100, 100);
-    startNextTestCase();
-  }
+    window.onload = function() {
+        if (!window.testRunner)
+            return;
+        window.addEventListener("mousewheel", function (e){}, false);
+        window.scrollTo(-100, 100);
+        startNextTestCase();
+    }
 </script>
 
 <body style="margin:0">
-  <div id="div" style="whitespace:nowrap; width: 4000px; height: 1000px; border: 1px solid red;">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."</div>
-  <div id="console"></div>
+    <div id="div" style="whitespace:nowrap; width: 4000px; height: 1000px; border: 1px solid red;">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."</div>
+    <div id="console"></div>
 </body>
 </html>
diff --git a/third_party/WebKit/LayoutTests/fast/events/wheel/wheelevent-in-text-node-expected.txt b/third_party/WebKit/LayoutTests/fast/events/wheel/wheelevent-in-text-node-expected.txt
new file mode 100644
index 0000000..3dfc6fd2
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/events/wheel/wheelevent-in-text-node-expected.txt
@@ -0,0 +1,6 @@
+'Real' MouseWheel events should not be dispatched on the text node, but instead on its parent.
+PASS theEvent.target.nodeName is "DIV"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+This is a div containing text. Wheel events originating on the text node should target the div.
diff --git a/third_party/WebKit/LayoutTests/fast/events/wheel/wheelevent-in-text-node.html b/third_party/WebKit/LayoutTests/fast/events/wheel/wheelevent-in-text-node.html
index 4094deb0..a54f5f9 100644
--- a/third_party/WebKit/LayoutTests/fast/events/wheel/wheelevent-in-text-node.html
+++ b/third_party/WebKit/LayoutTests/fast/events/wheel/wheelevent-in-text-node.html
@@ -1,32 +1,36 @@
 <!DOCTYPE html>
 <html>
 <head>
-  <script src="../../../resources/testharness.js"></script>
-  <script src="../../../resources/testharnessreport.js"></script>
-  <script src="../../../resources/gesture-util.js"></script>
+    <script src="../../../resources/js-test.js"></script>
+    <script>
+        window.jsTestIsAsync = true;
+
+        function test() {
+            var div = document.querySelector('div');
+            if (window.eventSender) {
+                eventSender.mouseMoveTo(div.offsetLeft + 5, div.offsetTop + 5);
+                eventSender.mouseScrollBy(0, 120, false, true, 0, true, "phaseBegan");
+            } else {
+                debug("FAIL: This test requires window.eventSender.");
+                finishJSTest();
+            }
+        }
+
+        function wheelHandler(e) {
+            window.theEvent = e;
+
+            debug("'Real' MouseWheel events should not be dispatched on the text node, but instead on its parent.");
+            shouldBeEqualToString('theEvent.target.nodeName', 'DIV');
+            finishJSTest();
+        }
+
+        window.onload = function () {
+            var div = document.querySelector('div');
+            div.addEventListener('mousewheel', wheelHandler);
+            test();
+        };
+    </script>
 </head>
-<script>
-  setup({ explicit_done: true });
-  function test() {
-    var div = document.querySelector('div');
-    var x = div.offsetLeft + 5;
-    var y = div.offsetTop + 5;
-    mouseMoveTo(x, y)
-    .then(smoothScroll(120, x, y, GestureSourceType.MOUSE_INPUT, 'down'));
-  }
-
-  function wheelHandler(e) {
-    window.theEvent = e;
-    assert_equals(theEvent.target.nodeName, 'DIV');
-    done();
-  }
-
-  window.onload = function () {
-    var div = document.querySelector('div');
-    div.addEventListener('mousewheel', wheelHandler);
-    test();
-  };
-</script>
 <body>
     <div>This is a div containing text. Wheel events originating on the text
     node should target the div.</div>
diff --git a/third_party/WebKit/LayoutTests/fast/events/wheel/wheelevent-in-vertical-scrollbar-in-rtl-expected.txt b/third_party/WebKit/LayoutTests/fast/events/wheel/wheelevent-in-vertical-scrollbar-in-rtl-expected.txt
new file mode 100644
index 0000000..1c7c5523
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/events/wheel/wheelevent-in-vertical-scrollbar-in-rtl-expected.txt
@@ -0,0 +1,9 @@
+Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
+PASS window.scrollX == 110 && window.scrollY == -100 became true
+PASS window.scrollX == 80 && window.scrollY == -100 became true
+PASS window.scrollX == 80 && window.scrollY == -90 became true
+PASS window.scrollX == 80 && window.scrollY == -120 became true
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/third_party/WebKit/LayoutTests/fast/events/wheel/wheelevent-in-vertical-scrollbar-in-rtl.html b/third_party/WebKit/LayoutTests/fast/events/wheel/wheelevent-in-vertical-scrollbar-in-rtl.html
index 6b322eb..8d1eb8f 100644
--- a/third_party/WebKit/LayoutTests/fast/events/wheel/wheelevent-in-vertical-scrollbar-in-rtl.html
+++ b/third_party/WebKit/LayoutTests/fast/events/wheel/wheelevent-in-vertical-scrollbar-in-rtl.html
@@ -1,43 +1,41 @@
 <html dir=rtl style="-webkit-writing-mode:vertical-lr">
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/gesture-util.js"></script>
+
+<script src="../../../resources/js-test.js"></script>
 <script>
-  var testScrolls = [
-    {distance: 10, expectedX: 110, expectedY: -100, direction: 'right'},
-    {distance: 30, expectedX: 80, expectedY: -100, direction: 'left'},
-    {distance: 10, expectedX: 80, expectedY: -90, direction: 'down'},
-    {distance: 30, expectedX: 80, expectedY: -120, direction: 'up'},
-  ];
-  var currentTest = -1;
+    var testScrolls = [
+        {x: -10, y: 0, expectedX: 110, expectedY: -100},
+        {x: 30, y: 0, expectedX: 80, expectedY: -100},
+        {x: 0, y: -10, expectedX: 80, expectedY: -90},
+        {x: 0, y: 30, expectedX: 80, expectedY: -120},
+    ];
+    var currentTest = -1;
+    window.jsTestIsAsync = true;
 
-  function startNextTestCase() {
-    currentTest++;
-    if (currentTest >= testScrolls.length)
-      return;
+    function startNextTestCase() {
+        currentTest++;
+        if (currentTest >= testScrolls.length) {
+            finishJSTest();
+            return;
+        }
+        var testCase = testScrolls[currentTest];
+        eventSender.mouseMoveTo(100, 100);
+        eventSender.continuousMouseScrollBy(testCase.x, testCase.y);
+        shouldBecomeEqual("window.scrollX == " + testCase.expectedX + " && " +
+            "window.scrollY == " + testCase.expectedY, "true", startNextTestCase);
+    }
 
-    var testCase = testScrolls[currentTest];
-    promise_test(async () => {
-      await mouseMoveTo(100, 100);
-      await smoothScroll(testCase.distance, 100, 100,
-          GestureSourceType.MOUSE_INPUT, testCase.direction, SPEED_INSTANT);
-      await waitFor( () => {
-        return window.scrollX == testCase.expectedX &&
-            window.scrollY == testCase.expectedY;
-      });
+    window.onload = function() {
+        if (!window.testRunner)
+            return;
+        window.addEventListener("mousewheel", function (e){}, false);
+        window.scrollTo(100, -100);
         startNextTestCase();
-      }, 'scroll ' + testCase.direction);
-  }
-
-  window.onload = function() {
-    window.addEventListener("mousewheel", function (e){}, false);
-    window.scrollTo(100, -100);
-    startNextTestCase();
-  }
+    }
 </script>
 
 <body style="margin:0">
-  <div id="div" style="whitespace:nowrap; width: 4000px; height: 1000px; border: 1px solid red;">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."</div>
-  <div id="console"></div>
+
+    <div id="div" style="whitespace:nowrap; width: 4000px; height: 1000px; border: 1px solid red;">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."</div>
+    <div id="console"></div>
 </body>
 </html>
diff --git a/third_party/WebKit/LayoutTests/html5lib/resources/template.dat b/third_party/WebKit/LayoutTests/html5lib/resources/template.dat
index 8ffa2a18..ff822b06 100644
--- a/third_party/WebKit/LayoutTests/html5lib/resources/template.dat
+++ b/third_party/WebKit/LayoutTests/html5lib/resources/template.dat
@@ -477,9 +477,7 @@
 | <html>
 |   <head>
 |   <frameset>
-|     <template>
-|       content
-|         <frame>
+|     <frame>
 
 #data
 <template><frame></frame></frameset><frame></frame></template>
@@ -489,8 +487,6 @@
 |   <head>
 |     <template>
 |       content
-|         <frame>
-|         <frame>
 |   <body>
 
 #data
@@ -823,8 +819,6 @@
 |   <head>
 |     <template>
 |       content
-|         <frame>
-|         <frame>
 |   <body>
 
 #data
@@ -1160,7 +1154,6 @@
 |       content
 |         <template>
 |           content
-|             <frame>
 |   <body>
 
 #data
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/profiler/heap-snapshot-summary-show-ranges-expected.txt b/third_party/WebKit/LayoutTests/http/tests/devtools/profiler/heap-snapshot-summary-show-ranges-expected.txt
index 8088d0d5..7fde097 100644
--- a/third_party/WebKit/LayoutTests/http/tests/devtools/profiler/heap-snapshot-summary-show-ranges-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/devtools/profiler/heap-snapshot-summary-show-ranges-expected.txt
@@ -8,235 +8,235 @@
 
 Step 3
 Retrieved ranges: [{"from":0,"to":10}]
-[0] A  773492  492  
-[1] A  213482  482  
-[2] A  613482  482  
-[3] A  853472  472  
-[4] A  1813462  462  
-[5] A  413452  452  
-[6] A  1413452  452  
-[7] A  1853442  442  
-[8] A  573432  432  
-[9] A  533412  412  
+[0] A 77  3492  492  
+[1] A 21  3482  482  
+[2] A 61  3482  482  
+[3] A 85  3472  472  
+[4] A 181  3462  462  
+[5] A 41  3452  452  
+[6] A 141  3452  452  
+[7] A 185  3442  442  
+[8] A 57  3432  432  
+[9] A 53  3412  412  
 [10] Show 10 beforeShow all 40Show 10 after
 
 Step 4
 Retrieved ranges: [{"from":0,"to":10},{"from":30,"to":40}]
-[0] A  773492  492  
-[1] A  213482  482  
-[2] A  613482  482  
-[3] A  853472  472  
-[4] A  1813462  462  
-[5] A  413452  452  
-[6] A  1413452  452  
-[7] A  1853442  442  
-[8] A  573432  432  
-[9] A  533412  412  
+[0] A 77  3492  492  
+[1] A 21  3482  482  
+[2] A 61  3482  482  
+[3] A 85  3472  472  
+[4] A 181  3462  462  
+[5] A 41  3452  452  
+[6] A 141  3452  452  
+[7] A 185  3442  442  
+[8] A 57  3432  432  
+[9] A 53  3412  412  
 [10] Show 10 beforeShow all 20Show 10 after
-[11] A  1333241  241  
-[12] A  173231  231  
-[13] A  1453231  231  
-[14] A  1773211  211  
-[15] A  1973211  211  
-[16] A  1893181  181  
-[17] A  253161  161  
-[18] A  1093151  151  
-[19] A  2013151  151  
-[20] A  1933131  131  
+[11] A 133  3241  241  
+[12] A 17  3231  231  
+[13] A 145  3231  231  
+[14] A 177  3211  211  
+[15] A 197  3211  211  
+[16] A 189  3181  181  
+[17] A 25  3161  161  
+[18] A 109  3151  151  
+[19] A 201  3151  151  
+[20] A 193  3131  131  
 [21] Show 10 beforeShow all 10Show 10 after
 
 Step 5
 Retrieved ranges: [{"from":0,"to":10},{"from":20,"to":25},{"from":30,"to":40}]
-[0] A  773492  492  
-[1] A  213482  482  
-[2] A  613482  482  
-[3] A  853472  472  
-[4] A  1813462  462  
-[5] A  413452  452  
-[6] A  1413452  452  
-[7] A  1853442  442  
-[8] A  573432  432  
-[9] A  533412  412  
+[0] A 77  3492  492  
+[1] A 21  3482  482  
+[2] A 61  3482  482  
+[3] A 85  3472  472  
+[4] A 181  3462  462  
+[5] A 41  3452  452  
+[6] A 141  3452  452  
+[7] A 185  3442  442  
+[8] A 57  3432  432  
+[9] A 53  3412  412  
 [10] Show 10 beforeShow all 10Show 10 after
-[11] A  1293342  342  
-[12] A  813312  312  
-[13] A  1573302  302  
-[14] A  1373291  291  
-[15] A  1693291  291  
+[11] A 129  3342  342  
+[12] A 81  3312  312  
+[13] A 157  3302  302  
+[14] A 137  3291  291  
+[15] A 169  3291  291  
 [16] Show 10 beforeShow all 5Show 10 after
-[17] A  1333241  241  
-[18] A  173231  231  
-[19] A  1453231  231  
-[20] A  1773211  211  
-[21] A  1973211  211  
-[22] A  1893181  181  
-[23] A  253161  161  
-[24] A  1093151  151  
-[25] A  2013151  151  
-[26] A  1933131  131  
+[17] A 133  3241  241  
+[18] A 17  3231  231  
+[19] A 145  3231  231  
+[20] A 177  3211  211  
+[21] A 197  3211  211  
+[22] A 189  3181  181  
+[23] A 25  3161  161  
+[24] A 109  3151  151  
+[25] A 201  3151  151  
+[26] A 193  3131  131  
 [27] Show 10 beforeShow all 10Show 10 after
 
 Step 6
 Retrieved ranges: [{"from":0,"to":10},{"from":20,"to":25},{"from":28,"to":40}]
-[0] A  773492  492  
-[1] A  213482  482  
-[2] A  613482  482  
-[3] A  853472  472  
-[4] A  1813462  462  
-[5] A  413452  452  
-[6] A  1413452  452  
-[7] A  1853442  442  
-[8] A  573432  432  
-[9] A  533412  412  
+[0] A 77  3492  492  
+[1] A 21  3482  482  
+[2] A 61  3482  482  
+[3] A 85  3472  472  
+[4] A 181  3462  462  
+[5] A 41  3452  452  
+[6] A 141  3452  452  
+[7] A 185  3442  442  
+[8] A 57  3432  432  
+[9] A 53  3412  412  
 [10] Show 10 beforeShow all 10Show 10 after
-[11] A  1293342  342  
-[12] A  813312  312  
-[13] A  1573302  302  
-[14] A  1373291  291  
-[15] A  1693291  291  
+[11] A 129  3342  342  
+[12] A 81  3312  312  
+[13] A 157  3302  302  
+[14] A 137  3291  291  
+[15] A 169  3291  291  
 [16] Show 10 beforeShow all 3Show 10 after
-[17] A  453251  251  
-[18] A  333241  241  
-[19] A  1333241  241  
-[20] A  173231  231  
-[21] A  1453231  231  
-[22] A  1773211  211  
-[23] A  1973211  211  
-[24] A  1893181  181  
-[25] A  253161  161  
-[26] A  1093151  151  
-[27] A  2013151  151  
-[28] A  1933131  131  
+[17] A 45  3251  251  
+[18] A 33  3241  241  
+[19] A 133  3241  241  
+[20] A 17  3231  231  
+[21] A 145  3231  231  
+[22] A 177  3211  211  
+[23] A 197  3211  211  
+[24] A 189  3181  181  
+[25] A 25  3161  161  
+[26] A 109  3151  151  
+[27] A 201  3151  151  
+[28] A 193  3131  131  
 [29] Show 10 beforeShow all 10Show 10 after
 
 Step 7
 Retrieved ranges: [{"from":0,"to":10},{"from":18,"to":26},{"from":28,"to":40}]
-[0] A  773492  492  
-[1] A  213482  482  
-[2] A  613482  482  
-[3] A  853472  472  
-[4] A  1813462  462  
-[5] A  413452  452  
-[6] A  1413452  452  
-[7] A  1853442  442  
-[8] A  573432  432  
-[9] A  533412  412  
+[0] A 77  3492  492  
+[1] A 21  3482  482  
+[2] A 61  3482  482  
+[3] A 85  3472  472  
+[4] A 181  3462  462  
+[5] A 41  3452  452  
+[6] A 141  3452  452  
+[7] A 185  3442  442  
+[8] A 57  3432  432  
+[9] A 53  3412  412  
 [10] Show 10 beforeShow all 8Show 10 after
-[11] A  1253352  352  
-[12] A  1173342  342  
-[13] A  1293342  342  
-[14] A  813312  312  
-[15] A  1573302  302  
-[16] A  1373291  291  
-[17] A  1693291  291  
-[18] A  2053281  281  
+[11] A 125  3352  352  
+[12] A 117  3342  342  
+[13] A 129  3342  342  
+[14] A 81  3312  312  
+[15] A 157  3302  302  
+[16] A 137  3291  291  
+[17] A 169  3291  291  
+[18] A 205  3281  281  
 [19] Show 10 beforeShow all 2Show 10 after
-[20] A  453251  251  
-[21] A  333241  241  
-[22] A  1333241  241  
-[23] A  173231  231  
-[24] A  1453231  231  
-[25] A  1773211  211  
-[26] A  1973211  211  
-[27] A  1893181  181  
-[28] A  253161  161  
-[29] A  1093151  151  
-[30] A  2013151  151  
-[31] A  1933131  131  
+[20] A 45  3251  251  
+[21] A 33  3241  241  
+[22] A 133  3241  241  
+[23] A 17  3231  231  
+[24] A 145  3231  231  
+[25] A 177  3211  211  
+[26] A 197  3211  211  
+[27] A 189  3181  181  
+[28] A 25  3161  161  
+[29] A 109  3151  151  
+[30] A 201  3151  151  
+[31] A 193  3131  131  
 [32] Show 10 beforeShow all 10Show 10 after
 
 Step 8
 Retrieved ranges: [{"from":0,"to":10},{"from":15,"to":45}]
-[0] A  773492  492  
-[1] A  213482  482  
-[2] A  613482  482  
-[3] A  853472  472  
-[4] A  1813462  462  
-[5] A  413452  452  
-[6] A  1413452  452  
-[7] A  1853442  442  
-[8] A  573432  432  
-[9] A  533412  412  
+[0] A 77  3492  492  
+[1] A 21  3482  482  
+[2] A 61  3482  482  
+[3] A 85  3472  472  
+[4] A 181  3462  462  
+[5] A 41  3452  452  
+[6] A 141  3452  452  
+[7] A 185  3442  442  
+[8] A 57  3432  432  
+[9] A 53  3412  412  
 [10] Show 10 beforeShow all 5Show 10 after
-[11] A  653382  382  
-[12] A  1133382  382  
-[13] A  1533362  362  
-[14] A  1253352  352  
-[15] A  1173342  342  
-[16] A  1293342  342  
-[17] A  813312  312  
-[18] A  1573302  302  
-[19] A  1373291  291  
-[20] A  1693291  291  
-[21] A  2053281  281  
-[22] A  373271  271  
-[23] A  493261  261  
-[24] A  453251  251  
-[25] A  333241  241  
-[26] A  1333241  241  
-[27] A  173231  231  
-[28] A  1453231  231  
-[29] A  1773211  211  
-[30] A  1973211  211  
-[31] A  1893181  181  
-[32] A  253161  161  
-[33] A  1093151  151  
-[34] A  2013151  151  
-[35] A  1933131  131  
-[36] A  1493121  121  
-[37] A  693111  111  
-[38] A  29390  90  
-[39] A  121380  80  
-[40] A  165380  80  
+[11] A 65  3382  382  
+[12] A 113  3382  382  
+[13] A 153  3362  362  
+[14] A 125  3352  352  
+[15] A 117  3342  342  
+[16] A 129  3342  342  
+[17] A 81  3312  312  
+[18] A 157  3302  302  
+[19] A 137  3291  291  
+[20] A 169  3291  291  
+[21] A 205  3281  281  
+[22] A 37  3271  271  
+[23] A 49  3261  261  
+[24] A 45  3251  251  
+[25] A 33  3241  241  
+[26] A 133  3241  241  
+[27] A 17  3231  231  
+[28] A 145  3231  231  
+[29] A 177  3211  211  
+[30] A 197  3211  211  
+[31] A 189  3181  181  
+[32] A 25  3161  161  
+[33] A 109  3151  151  
+[34] A 201  3151  151  
+[35] A 193  3131  131  
+[36] A 149  3121  121  
+[37] A 69  3111  111  
+[38] A 29  390  90  
+[39] A 121  380  80  
+[40] A 165  380  80  
 [41] Show 10 beforeShow all 5Show 10 after
 
 Step 9
 Retrieved ranges: [{"from":0,"to":45}]
-[0] A  773492  492  
-[1] A  213482  482  
-[2] A  613482  482  
-[3] A  853472  472  
-[4] A  1813462  462  
-[5] A  413452  452  
-[6] A  1413452  452  
-[7] A  1853442  442  
-[8] A  573432  432  
-[9] A  533412  412  
-[10] A  893402  402  
-[11] A  973402  402  
-[12] A  733392  392  
-[13] A  1013392  392  
-[14] A  133382  382  
-[15] A  653382  382  
-[16] A  1133382  382  
-[17] A  1533362  362  
-[18] A  1253352  352  
-[19] A  1173342  342  
-[20] A  1293342  342  
-[21] A  813312  312  
-[22] A  1573302  302  
-[23] A  1373291  291  
-[24] A  1693291  291  
-[25] A  2053281  281  
-[26] A  373271  271  
-[27] A  493261  261  
-[28] A  453251  251  
-[29] A  333241  241  
-[30] A  1333241  241  
-[31] A  173231  231  
-[32] A  1453231  231  
-[33] A  1773211  211  
-[34] A  1973211  211  
-[35] A  1893181  181  
-[36] A  253161  161  
-[37] A  1093151  151  
-[38] A  2013151  151  
-[39] A  1933131  131  
-[40] A  1493121  121  
-[41] A  693111  111  
-[42] A  29390  90  
-[43] A  121380  80  
-[44] A  165380  80  
+[0] A 77  3492  492  
+[1] A 21  3482  482  
+[2] A 61  3482  482  
+[3] A 85  3472  472  
+[4] A 181  3462  462  
+[5] A 41  3452  452  
+[6] A 141  3452  452  
+[7] A 185  3442  442  
+[8] A 57  3432  432  
+[9] A 53  3412  412  
+[10] A 89  3402  402  
+[11] A 97  3402  402  
+[12] A 73  3392  392  
+[13] A 101  3392  392  
+[14] A 13  3382  382  
+[15] A 65  3382  382  
+[16] A 113  3382  382  
+[17] A 153  3362  362  
+[18] A 125  3352  352  
+[19] A 117  3342  342  
+[20] A 129  3342  342  
+[21] A 81  3312  312  
+[22] A 157  3302  302  
+[23] A 137  3291  291  
+[24] A 169  3291  291  
+[25] A 205  3281  281  
+[26] A 37  3271  271  
+[27] A 49  3261  261  
+[28] A 45  3251  251  
+[29] A 33  3241  241  
+[30] A 133  3241  241  
+[31] A 17  3231  231  
+[32] A 145  3231  231  
+[33] A 177  3211  211  
+[34] A 197  3211  211  
+[35] A 189  3181  181  
+[36] A 25  3161  161  
+[37] A 109  3151  151  
+[38] A 201  3151  151  
+[39] A 193  3131  131  
+[40] A 149  3121  121  
+[41] A 69  3111  111  
+[42] A 29  390  90  
+[43] A 121  380  80  
+[44] A 165  380  80  
 [45] Show 10 beforeShow all 5Show 10 after
 
 Profiler was disabled.
diff --git a/third_party/WebKit/LayoutTests/http/tests/webaudio/autoplay-crossorigin-expected.txt b/third_party/WebKit/LayoutTests/http/tests/webaudio/autoplay-crossorigin-expected.txt
index 2ae8c34c..c7b5fd3d 100644
--- a/third_party/WebKit/LayoutTests/http/tests/webaudio/autoplay-crossorigin-expected.txt
+++ b/third_party/WebKit/LayoutTests/http/tests/webaudio/autoplay-crossorigin-expected.txt
@@ -1,9 +1,10 @@
-CONSOLE WARNING: line 13: The AudioContext was not allowed to start. It must be resumed (or created) from a user gesture event handler.
-CONSOLE WARNING: line 23: The AudioContext was not allowed to start. It must be resumed (or created) from a user gesture event handler.
-CONSOLE WARNING: line 36: The AudioContext was not allowed to start. It must be resumed (or created) from a user gesture event handler.
-CONSOLE ERROR: line 2684: Uncaught Error: assert_equals: stateAfterClick expected "running" but got "suspended"
+CONSOLE WARNING: line 13: The AudioContext was not allowed to start. It must be resumed (or created) from a user gesture event handler. https://goo.gl/7K7WLu
+CONSOLE WARNING: line 13: The Web Audio autoplay policy will be re-enabled in Chrome 70 (October 2018). Please check that your website is compatible with it. https://goo.gl/7K7WLu
+CONSOLE WARNING: line 23: The AudioContext was not allowed to start. It must be resumed (or created) from a user gesture event handler. https://goo.gl/7K7WLu
+CONSOLE WARNING: line 32: The AudioContext was not allowed to start. It must be resumed (or created) from a user gesture event handler. https://goo.gl/7K7WLu
+CONSOLE WARNING: line 36: The AudioContext was not allowed to start. It must be resumed (or created) from a user gesture event handler. https://goo.gl/7K7WLu
+CONSOLE WARNING: line 36: The Web Audio autoplay policy will be re-enabled in Chrome 70 (October 2018). Please check that your website is compatible with it. https://goo.gl/7K7WLu
 This is a testharness.js-based test.
-Harness Error. harness_status.status = 1 , harness_status.message = Uncaught Error: assert_equals: stateAfterClick expected "running" but got "suspended"
-PASS Verify that autoplaying Web Audio from a cross origin iframe is blocked by mediaPlaybackRequiresUserGesture
+FAIL Verify that autoplaying Web Audio from a cross origin iframe is blocked by mediaPlaybackRequiresUserGesture assert_equals: stateAfterClick expected "running" but got "suspended"
 Harness: the test ran to completion.
 
diff --git a/third_party/WebKit/LayoutTests/http/tests/webaudio/autoplay-crossorigin.html b/third_party/WebKit/LayoutTests/http/tests/webaudio/autoplay-crossorigin.html
index e7259ddf..4bd49080 100644
--- a/third_party/WebKit/LayoutTests/http/tests/webaudio/autoplay-crossorigin.html
+++ b/third_party/WebKit/LayoutTests/http/tests/webaudio/autoplay-crossorigin.html
@@ -5,7 +5,7 @@
 <body></body>
 <script>
 async_test(t => {
-  window.addEventListener('message', e => {
+  window.addEventListener('message', t.step_func(e => {
     switch (e.data.msg) {
       case 'clickme':
         if (!('eventSender' in window))
@@ -37,7 +37,7 @@
       default:
         assert_unreached();
     }
-  });
+  }));
 
   var f = document.createElement('iframe');
   f.src = 'http://localhost:8000/webaudio/resources/autoplay-crossorigin-iframe.html';
diff --git a/third_party/WebKit/LayoutTests/images/feature-policy-max-downscaling-image-forced-layout-expected.html b/third_party/WebKit/LayoutTests/images/feature-policy-max-downscaling-image-forced-layout-expected.html
new file mode 100644
index 0000000..7bfaefa84
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/images/feature-policy-max-downscaling-image-forced-layout-expected.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<style>img { filter: invert(1); }</style>
+<img src="resources/green-256x256.jpg" width="100" height="100">
+<img src="resources/green-256x256.jpg" style="width: 100px; height: 100px">
diff --git a/third_party/WebKit/LayoutTests/images/feature-policy-max-downscaling-image-forced-layout.html b/third_party/WebKit/LayoutTests/images/feature-policy-max-downscaling-image-forced-layout.html
new file mode 100644
index 0000000..d17c89fd
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/images/feature-policy-max-downscaling-image-forced-layout.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<iframe src="resources/frame-with-max-downscaling-image-test-images-forced-layout.html"
+        allow="max-downscaling-image 'none'" frameborder="0">
+</iframe>
diff --git a/third_party/WebKit/LayoutTests/images/resources/frame-with-max-downscaling-image-test-images-forced-layout.html b/third_party/WebKit/LayoutTests/images/resources/frame-with-max-downscaling-image-test-images-forced-layout.html
new file mode 100644
index 0000000..b30800b
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/images/resources/frame-with-max-downscaling-image-test-images-forced-layout.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<style>body { margin: 0; }</style>
+<img src="green-256x256.jpg" width="100" height="100">
+<img src="green-256x256.jpg" style="width: 100px; height: 100px">
+<script>
+document.body.offsetTop;
+</script>
diff --git a/third_party/WebKit/LayoutTests/printing/thead-tfoot-repeat-scrolled-expected.html b/third_party/WebKit/LayoutTests/printing/thead-tfoot-repeat-scrolled-expected.html
new file mode 100644
index 0000000..97626639
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/printing/thead-tfoot-repeat-scrolled-expected.html
@@ -0,0 +1,123 @@
+<!DOCTYPE html>
+<style>
+body {
+  font-size: 30px;
+  line-height: 50px;
+}
+</style>
+<script>
+onload = function() {
+  if (window.testRunner)
+    testRunner.setPrinting();
+};
+</script>
+<table>
+  <thead>
+    <tr>
+      <th>Header</th>
+    </tr>
+  </thead>
+  <tbody>
+    <tr>
+      <td>1</td>
+    </tr>
+    <tr>
+      <td>2</td>
+    </tr>
+    <tr>
+      <td>3</td>
+    </tr>
+    <tr>
+      <td>4</td>
+    </tr>
+    <tr>
+      <td>5</td>
+    </tr>
+    <tr>
+      <td>6</td>
+    </tr>
+    <tr>
+      <td>7</td>
+    </tr>
+    <tr>
+      <td>8</td>
+    </tr>
+    <tr>
+      <td>9</td>
+    </tr>
+    <tr>
+      <td>10</td>
+    </tr>
+    <tr>
+      <td>11</td>
+    </tr>
+    <tr>
+      <td>12</td>
+    </tr>
+    <tr>
+      <td>13</td>
+    </tr>
+    <tr>
+      <td>14</td>
+    </tr>
+    <tr>
+      <td>15</td>
+    </tr>
+    <tr>
+      <td>16</td>
+    </tr>
+    <tr>
+      <td>17</td>
+    </tr>
+    <tr>
+      <td>18</td>
+    </tr>
+    <tr>
+      <td>19</td>
+    </tr>
+    <tr>
+      <td>20</td>
+    </tr>
+    <tr>
+      <td>21</td>
+    </tr>
+    <tr>
+      <td>22</td>
+    </tr>
+    <tr>
+      <td>23</td>
+    </tr>
+    <tr>
+      <td>24</td>
+    </tr>
+    <tr>
+      <td>25</td>
+    </tr>
+    <tr>
+      <td>26</td>
+    </tr>
+    <tr>
+      <td>27</td>
+    </tr>
+    <tr>
+      <td>28</td>
+    </tr>
+    <tr>
+      <td>29</td>
+    </tr>
+    <tr>
+      <td>30</td>
+    </tr>
+    <tr>
+      <td>31</td>
+    </tr>
+    <tr>
+      <td>32</td>
+    </tr>
+  </tbody>
+  <tfoot>
+    <tr>
+      <th>Footer</th>
+    </tr>
+  </tfoot>
+</table>
diff --git a/third_party/WebKit/LayoutTests/printing/thead-tfoot-repeat-scrolled.html b/third_party/WebKit/LayoutTests/printing/thead-tfoot-repeat-scrolled.html
new file mode 100644
index 0000000..c719eb31
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/printing/thead-tfoot-repeat-scrolled.html
@@ -0,0 +1,124 @@
+<!DOCTYPE html>
+<style>
+body {
+  font-size: 30px;
+  line-height: 50px;
+}
+</style>
+<script>
+onload = function() {
+  window.scrollBy(0, 400);
+  if (window.testRunner)
+    testRunner.setPrinting();
+};
+</script>
+<table>
+  <thead>
+    <tr>
+      <th>Header</th>
+    </tr>
+  </thead>
+  <tbody>
+    <tr>
+      <td>1</td>
+    </tr>
+    <tr>
+      <td>2</td>
+    </tr>
+    <tr>
+      <td>3</td>
+    </tr>
+    <tr>
+      <td>4</td>
+    </tr>
+    <tr>
+      <td>5</td>
+    </tr>
+    <tr>
+      <td>6</td>
+    </tr>
+    <tr>
+      <td>7</td>
+    </tr>
+    <tr>
+      <td>8</td>
+    </tr>
+    <tr>
+      <td>9</td>
+    </tr>
+    <tr>
+      <td>10</td>
+    </tr>
+    <tr>
+      <td>11</td>
+    </tr>
+    <tr>
+      <td>12</td>
+    </tr>
+    <tr>
+      <td>13</td>
+    </tr>
+    <tr>
+      <td>14</td>
+    </tr>
+    <tr>
+      <td>15</td>
+    </tr>
+    <tr>
+      <td>16</td>
+    </tr>
+    <tr>
+      <td>17</td>
+    </tr>
+    <tr>
+      <td>18</td>
+    </tr>
+    <tr>
+      <td>19</td>
+    </tr>
+    <tr>
+      <td>20</td>
+    </tr>
+    <tr>
+      <td>21</td>
+    </tr>
+    <tr>
+      <td>22</td>
+    </tr>
+    <tr>
+      <td>23</td>
+    </tr>
+    <tr>
+      <td>24</td>
+    </tr>
+    <tr>
+      <td>25</td>
+    </tr>
+    <tr>
+      <td>26</td>
+    </tr>
+    <tr>
+      <td>27</td>
+    </tr>
+    <tr>
+      <td>28</td>
+    </tr>
+    <tr>
+      <td>29</td>
+    </tr>
+    <tr>
+      <td>30</td>
+    </tr>
+    <tr>
+      <td>31</td>
+    </tr>
+    <tr>
+      <td>32</td>
+    </tr>
+  </tbody>
+  <tfoot>
+    <tr>
+      <th>Footer</th>
+    </tr>
+  </tfoot>
+</table>
diff --git a/third_party/blink/public/mojom/page/display_cutout.mojom b/third_party/blink/public/mojom/page/display_cutout.mojom
index b93ad623..80c04255 100644
--- a/third_party/blink/public/mojom/page/display_cutout.mojom
+++ b/third_party/blink/public/mojom/page/display_cutout.mojom
@@ -4,6 +4,8 @@
 
 module blink.mojom;
 
+import "ui/gfx/geometry/mojo/geometry.mojom";
+
 enum ViewportFit {
   // No effect - the whole web page is viewable (default).
   kAuto,
@@ -22,3 +24,20 @@
   // Notify the browser that the ViewportFit for the renderer has changed.
   ViewportFitChanged(blink.mojom.ViewportFit value);
 };
+
+// Contains the four safe areas for the display cutout. These are insets from
+// each edge of the display measured in pixels.
+// TODO(beccahughes): Replace with gfx::Insets
+struct DisplayCutoutSafeArea {
+  int32 top;
+  int32 left;
+  int32 bottom;
+  int32 right;
+};
+
+// Used for browser -> renderer calls about display cutout. This is associated
+// with a frame.
+interface DisplayCutoutClient {
+  // Notify the renderer that the safe areas have changed.
+  SetSafeArea(DisplayCutoutSafeArea safe_area);
+};
diff --git a/third_party/blink/public/platform/modules/background_fetch/background_fetch.mojom b/third_party/blink/public/platform/modules/background_fetch/background_fetch.mojom
index 1d815ba..af3a523 100644
--- a/third_party/blink/public/platform/modules/background_fetch/background_fetch.mojom
+++ b/third_party/blink/public/platform/modules/background_fetch/background_fetch.mojom
@@ -6,6 +6,7 @@
 
 import "skia/public/interfaces/bitmap.mojom";
 import "third_party/blink/public/platform/modules/fetch/fetch_api_request.mojom";
+import "third_party/blink/public/mojom/manifest/manifest.mojom";
 import "ui/gfx/geometry/mojo/geometry.mojom";
 
 enum BackgroundFetchError {
@@ -17,20 +18,11 @@
   SERVICE_WORKER_UNAVAILABLE
 };
 
-// Represents the definition of an icon developers can optionally provide with a
-// Background Fetch fetch. Analogous to the following structure in the spec:
-// https://wicg.github.io/background-fetch/#background-fetch-manager
-struct IconDefinition {
-  string src;
-  string sizes;
-  string type;
-};
-
 // Represents the optional options a developer can provide when starting a new
 // Background Fetch fetch. Analogous to the following structure in the spec:
 // https://wicg.github.io/background-fetch/#background-fetch-manager
 struct BackgroundFetchOptions {
-  array<IconDefinition> icons;
+  array<ManifestImageResource> icons;
   uint64 download_total;
   string title;
 };
diff --git a/third_party/blink/renderer/README.md b/third_party/blink/renderer/README.md
index 07318e79..5f1eb64 100644
--- a/third_party/blink/renderer/README.md
+++ b/third_party/blink/renderer/README.md
@@ -127,16 +127,33 @@
 
 ### Type dependencies
 
-`core/`, `modules/`, `bindings/`, `platform/` and `controller/` can use `std::` types and
-types defined in Chromium. The philosophy is that we should
-share as much code between Chromium and Blink as possible.
+Member variables of the following types are strongly discouraged in Blink:
+  - STL strings and containers. Use `WTF::String` and WTF containers instead.
+  - `GURL` and `url::Origin`. Use `KURL` and `SecurityOrigin` respectively.
+  - Any `//base` type which has a matching type in `platform/wtf`. The number of
+  duplicated types between WTF and base is continuously shrinking,
+  but always look at WTF first.
 
-However, there are a couple of types that really need to be optimized
-for Blink's workload (e.g., `Vector`, `HashTable`, `Bind`, `AtomicString`).
-These types are defined in `platform/wtf`. If there is an equivalent in
-`platform/wtf`, Blink must use the type in `platform/wtf` instead of the type
-defined in Chromium. For example, Blink should not use `std::vector`
-(except places where a conversion between `std::vector` and `WTF::Vector` is needed).
+The types above could only be used at the boundary to interoperate
+with `//base`, `//services`, `//third_party/blink/common` and other
+Chromium-side or third-party code. It is also allowed to use local variables
+of these types when convenient, as long as the result is not stored
+in a member variable.
+For example, calling an utility function on an `std::string` which came
+from `//net` and then converting to `WTF::String` to store in a field
+is allowed.
+
+We try to share as much code between Chromium and Blink as possible,
+so the number of these types should go down. However, some types
+really need to be optimized for Blink's workload (e.g., `Vector`,
+`HashTable`, `AtomicString`).
+
+Exceptions to this rule:
+  - Code in `//third_party/blink/common` and `//third_party/blink/public/common`
+  also runs in the browser process, and should use STL and base instead of WTF.
+  - Selected types in `public/platform` and `public/web`,
+  whole purpose of which is conversion between WTF and STL,
+  for example `WebString` or `WebVector`.
 
 To prevent use of random types, we control allowed types by whitelisting
 them in DEPS and a [presubmit script](../tools/audit_non_blink_usage.py).
diff --git a/third_party/blink/renderer/controller/blink_initializer.cc b/third_party/blink/renderer/controller/blink_initializer.cc
index ba13e03f..b0c7cee 100644
--- a/third_party/blink/renderer/controller/blink_initializer.cc
+++ b/third_party/blink/renderer/controller/blink_initializer.cc
@@ -44,6 +44,7 @@
 #include "third_party/blink/renderer/controller/bloated_renderer_detector.h"
 #include "third_party/blink/renderer/controller/dev_tools_frontend_impl.h"
 #include "third_party/blink/renderer/core/animation/animation_clock.h"
+#include "third_party/blink/renderer/core/frame/display_cutout_client_impl.h"
 #include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/platform/bindings/microtask.h"
 #include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h"
@@ -158,6 +159,11 @@
 }
 
 void BlinkInitializer::InitLocalFrame(LocalFrame& frame) const {
+  if (frame.IsMainFrame() &&
+      RuntimeEnabledFeatures::DisplayCutoutAPIEnabled()) {
+    frame.GetInterfaceRegistry()->AddAssociatedInterface(WTF::BindRepeating(
+        &DisplayCutoutClientImpl::BindMojoRequest, WrapWeakPersistent(&frame)));
+  }
   frame.GetInterfaceRegistry()->AddAssociatedInterface(WTF::BindRepeating(
       &DevToolsFrontendImpl::BindMojoRequest, WrapWeakPersistent(&frame)));
   frame.GetInterfaceRegistry()->AddInterface(WTF::BindRepeating(
diff --git a/third_party/blink/renderer/core/css/parser/css_tokenizer_test.cc b/third_party/blink/renderer/core/css/parser/css_tokenizer_test.cc
index 3cd7217..01e31733 100644
--- a/third_party/blink/renderer/core/css/parser/css_tokenizer_test.cc
+++ b/third_party/blink/renderer/core/css/parser/css_tokenizer_test.cc
@@ -233,8 +233,8 @@
   TEST_TOKENS("\\\f", Delim('\\'), Whitespace());
   TEST_TOKENS("\\\r\n", Delim('\\'), Whitespace());
   String replacement = FromUChar32(0xFFFD);
-  TEST_TOKENS(String("null\\\0", 6), Ident("null" + replacement));
-  TEST_TOKENS(String("null\\\0\0", 7),
+  TEST_TOKENS(String("null\\\0", 6u), Ident("null" + replacement));
+  TEST_TOKENS(String("null\\\0\0", 7u),
               Ident("null" + replacement + replacement));
   TEST_TOKENS("null\\0", Ident("null" + replacement));
   TEST_TOKENS("null\\0000", Ident("null" + replacement));
@@ -267,9 +267,9 @@
               Ident(FromUChar32(0xA0)));  // non-breaking space
   TEST_TOKENS(FromUChar32(0x1234), Ident(FromUChar32(0x1234)));
   TEST_TOKENS(FromUChar32(0x12345), Ident(FromUChar32(0x12345)));
-  TEST_TOKENS(String("\0", 1), Ident(FromUChar32(0xFFFD)));
-  TEST_TOKENS(String("ab\0c", 4), Ident("ab" + FromUChar32(0xFFFD) + "c"));
-  TEST_TOKENS(String("ab\0c", 4), Ident("ab" + FromUChar32(0xFFFD) + "c"));
+  TEST_TOKENS(String("\0", 1u), Ident(FromUChar32(0xFFFD)));
+  TEST_TOKENS(String("ab\0c", 4u), Ident("ab" + FromUChar32(0xFFFD) + "c"));
+  TEST_TOKENS(String("ab\0c", 4u), Ident("ab" + FromUChar32(0xFFFD) + "c"));
 }
 
 TEST(CSSTokenizerTest, FunctionToken) {
@@ -344,10 +344,10 @@
   TEST_TOKENS("'bad\rstring", BadString(), Whitespace(), Ident("string"));
   TEST_TOKENS("'bad\r\nstring", BadString(), Whitespace(), Ident("string"));
   TEST_TOKENS("'bad\fstring", BadString(), Whitespace(), Ident("string"));
-  TEST_TOKENS(String("'\0'", 3), GetString(FromUChar32(0xFFFD)));
-  TEST_TOKENS(String("'hel\0lo'", 8),
+  TEST_TOKENS(String("'\0'", 3u), GetString(FromUChar32(0xFFFD)));
+  TEST_TOKENS(String("'hel\0lo'", 8u),
               GetString("hel" + FromUChar32(0xFFFD) + "lo"));
-  TEST_TOKENS(String("'h\\65l\0lo'", 10),
+  TEST_TOKENS(String("'h\\65l\0lo'", 10u),
               GetString("hel" + FromUChar32(0xFFFD) + "lo"));
 }
 
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc
index 4d62c72..7c51b59 100644
--- a/third_party/blink/renderer/core/dom/document.cc
+++ b/third_party/blink/renderer/core/dom/document.cc
@@ -5502,7 +5502,7 @@
     AtomicString& local_name) {
   bool name_start = true;
   bool saw_colon = false;
-  int colon_pos = 0;
+  unsigned colon_pos = 0;
 
   for (unsigned i = 0; i < length;) {
     UChar32 c;
diff --git a/third_party/blink/renderer/core/editing/serializers/markup_formatter.cc b/third_party/blink/renderer/core/editing/serializers/markup_formatter.cc
index b57be31..536ffd2 100644
--- a/third_party/blink/renderer/core/editing/serializers/markup_formatter.cc
+++ b/third_party/blink/renderer/core/editing/serializers/markup_formatter.cc
@@ -390,7 +390,7 @@
           // This behavior is in process of being standardized. See
           // crbug.com/248044 and
           // https://www.w3.org/Bugs/Public/show_bug.cgi?id=24208
-          String prefix_prefix("ns", 2);
+          String prefix_prefix("ns", 2u);
           for (unsigned i = attribute.NamespaceURI().Impl()->ExistingHash();;
                ++i) {
             AtomicString new_prefix(String(prefix_prefix + String::Number(i)));
diff --git a/third_party/blink/renderer/core/frame/BUILD.gn b/third_party/blink/renderer/core/frame/BUILD.gn
index 2ff5126..fe7ea6b 100644
--- a/third_party/blink/renderer/core/frame/BUILD.gn
+++ b/third_party/blink/renderer/core/frame/BUILD.gn
@@ -32,6 +32,8 @@
     "deprecation_report_body.h",
     "device_single_window_event_controller.cc",
     "device_single_window_event_controller.h",
+    "display_cutout_client_impl.cc",
+    "display_cutout_client_impl.h",
     "dom_timer.cc",
     "dom_timer.h",
     "dom_timer_coordinator.cc",
diff --git a/third_party/blink/renderer/core/frame/display_cutout_client_impl.cc b/third_party/blink/renderer/core/frame/display_cutout_client_impl.cc
new file mode 100644
index 0000000..055f69c
--- /dev/null
+++ b/third_party/blink/renderer/core/frame/display_cutout_client_impl.cc
@@ -0,0 +1,53 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/frame/display_cutout_client_impl.h"
+
+#include "third_party/blink/renderer/core/css/document_style_environment_variables.h"
+#include "third_party/blink/renderer/core/css/style_engine.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
+
+namespace blink {
+
+namespace {
+
+const char kSafeAreaInsetTopName[] = "safe-area-inset-top";
+const char kSafeAreaInsetLeftName[] = "safe-area-inset-left";
+const char kSafeAreaInsetBottomName[] = "safe-area-inset-bottom";
+const char kSafeAreaInsetRightName[] = "safe-area-inset-right";
+
+String GetPx(int value) {
+  return String::Format("%dpx", value);
+}
+
+}  // namespace
+
+DisplayCutoutClientImpl::DisplayCutoutClientImpl(
+    LocalFrame* frame,
+    mojom::blink::DisplayCutoutClientAssociatedRequest request)
+    : frame_(frame), binding_(this, std::move(request)) {}
+
+void DisplayCutoutClientImpl::BindMojoRequest(
+    LocalFrame* frame,
+    mojom::blink::DisplayCutoutClientAssociatedRequest request) {
+  if (!frame)
+    return;
+  new DisplayCutoutClientImpl(frame, std::move(request));
+}
+
+void DisplayCutoutClientImpl::SetSafeArea(
+    mojom::blink::DisplayCutoutSafeAreaPtr safe_area) {
+  DocumentStyleEnvironmentVariables& vars =
+      frame_->GetDocument()->GetStyleEngine().EnsureEnvironmentVariables();
+  vars.SetVariable(kSafeAreaInsetTopName, GetPx(safe_area->top));
+  vars.SetVariable(kSafeAreaInsetLeftName, GetPx(safe_area->left));
+  vars.SetVariable(kSafeAreaInsetBottomName, GetPx(safe_area->bottom));
+  vars.SetVariable(kSafeAreaInsetRightName, GetPx(safe_area->right));
+}
+
+void DisplayCutoutClientImpl::Trace(Visitor* visitor) {
+  visitor->Trace(frame_);
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/core/frame/display_cutout_client_impl.h b/third_party/blink/renderer/core/frame/display_cutout_client_impl.h
new file mode 100644
index 0000000..56aade2
--- /dev/null
+++ b/third_party/blink/renderer/core/frame/display_cutout_client_impl.h
@@ -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.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_DISPLAY_CUTOUT_CLIENT_IMPL_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_DISPLAY_CUTOUT_CLIENT_IMPL_H_
+
+#include "mojo/public/cpp/bindings/associated_binding.h"
+#include "third_party/blink/public/mojom/page/display_cutout.mojom-blink.h"
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/platform/heap/heap.h"
+#include "third_party/blink/renderer/platform/heap/member.h"
+
+namespace blink {
+
+class LocalFrame;
+
+// Mojo interface to set CSS environment variables for display cutout.
+class CORE_EXPORT DisplayCutoutClientImpl final
+    : public GarbageCollectedFinalized<DisplayCutoutClientImpl>,
+      public mojom::blink::DisplayCutoutClient {
+ public:
+  static void BindMojoRequest(
+      LocalFrame*,
+      mojom::blink::DisplayCutoutClientAssociatedRequest);
+
+  // Notify the renderer that the safe areas have changed.
+  void SetSafeArea(mojom::blink::DisplayCutoutSafeAreaPtr safe_area) override;
+
+  void Trace(Visitor*);
+
+ private:
+  DisplayCutoutClientImpl(LocalFrame*,
+                          mojom::blink::DisplayCutoutClientAssociatedRequest);
+
+  Member<LocalFrame> frame_;
+
+  mojo::AssociatedBinding<mojom::blink::DisplayCutoutClient> binding_;
+
+  DISALLOW_COPY_AND_ASSIGN(DisplayCutoutClientImpl);
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_DISPLAY_CUTOUT_CLIENT_IMPL_H_
diff --git a/third_party/blink/renderer/core/frame/local_frame.cc b/third_party/blink/renderer/core/frame/local_frame.cc
index ccc77a6..cc8f0ba22 100644
--- a/third_party/blink/renderer/core/frame/local_frame.cc
+++ b/third_party/blink/renderer/core/frame/local_frame.cc
@@ -82,15 +82,12 @@
 #include "third_party/blink/renderer/core/page/scrolling/scrolling_coordinator.h"
 #include "third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.h"
 #include "third_party/blink/renderer/core/paint/object_painter.h"
-#include "third_party/blink/renderer/core/paint/transform_recorder.h"
 #include "third_party/blink/renderer/core/probe/core_probes.h"
 #include "third_party/blink/renderer/core/svg/svg_document_extensions.h"
 #include "third_party/blink/renderer/platform/bindings/script_forbidden_scope.h"
 #include "third_party/blink/renderer/platform/graphics/graphics_layer.h"
-#include "third_party/blink/renderer/platform/graphics/paint/clip_recorder.h"
 #include "third_party/blink/renderer/platform/graphics/paint/paint_canvas.h"
 #include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h"
-#include "third_party/blink/renderer/platform/graphics/paint/transform_display_item.h"
 #include "third_party/blink/renderer/platform/histogram.h"
 #include "third_party/blink/renderer/platform/instrumentation/resource_coordinator/blink_resource_coordinator_base.h"
 #include "third_party/blink/renderer/platform/instrumentation/resource_coordinator/frame_resource_coordinator.h"
diff --git a/third_party/blink/renderer/core/frame/local_frame_view.cc b/third_party/blink/renderer/core/frame/local_frame_view.cc
index 84168035..e6775c3 100644
--- a/third_party/blink/renderer/core/frame/local_frame_view.cc
+++ b/third_party/blink/renderer/core/frame/local_frame_view.cc
@@ -2443,7 +2443,8 @@
 }
 
 CompositorElementId LocalFrameView::GetCompositorElementId() const {
-  return PaintInvalidationCapableScrollableArea::GetCompositorElementId();
+  return CompositorElementIdFromUniqueObjectId(
+      GetLayoutView()->UniqueId(), CompositorElementIdNamespace::kScroll);
 }
 
 bool LocalFrameView::ScrollAnimatorEnabled() const {
diff --git a/third_party/blink/renderer/core/frame/local_frame_view.h b/third_party/blink/renderer/core/frame/local_frame_view.h
index aa812e3..4313fbf3 100644
--- a/third_party/blink/renderer/core/frame/local_frame_view.h
+++ b/third_party/blink/renderer/core/frame/local_frame_view.h
@@ -41,8 +41,8 @@
 #include "third_party/blink/renderer/core/page/scrolling/scrolling_coordinator.h"
 #include "third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.h"
 #include "third_party/blink/renderer/core/paint/layout_object_counter.h"
-#include "third_party/blink/renderer/core/paint/paint_invalidation_capable_scrollable_area.h"
 #include "third_party/blink/renderer/platform/graphics/graphics_layer_client.h"
+#include "third_party/blink/renderer/platform/scroll/scrollable_area.h"
 
 namespace base {
 class SingleThreadTaskRunner;
@@ -71,7 +71,6 @@
 class LayoutEmbeddedObject;
 class LayoutObject;
 class LayoutSVGRoot;
-class LayoutScrollbarPart;
 class LayoutView;
 class PaintArtifactCompositor;
 class PaintController;
@@ -94,7 +93,7 @@
 class CORE_EXPORT LocalFrameView final
     : public GarbageCollectedFinalized<LocalFrameView>,
       public FrameView,
-      public PaintInvalidationCapableScrollableArea {
+      public ScrollableArea {
   USING_GARBAGE_COLLECTED_MIXIN(LocalFrameView);
 
   friend class PaintControllerPaintTestBase;
@@ -499,8 +498,6 @@
   void RemoveScrollbar(Scrollbar*);
   void AddScrollbar(Scrollbar*);
 
-  LayoutScrollbarPart* ScrollCorner() const override { return nullptr; }
-
   // Functions for setting and retrieving the scrolling mode in each axis
   // (horizontal/vertical). The mode has values of AlwaysOff, AlwaysOn, and
   // Auto. AlwaysOff means never show a scrollbar, AlwaysOn means always show a
@@ -918,8 +915,7 @@
 
   void NotifyResizeObservers();
 
-  // PaintInvalidationCapableScrollableArea
-  LayoutScrollbarPart* Resizer() const override { return nullptr; }
+  void ScrollControlWasSetNeedsPaintInvalidation() override {}
 
   bool CheckLayoutInvalidationIsAllowed() const;
 
diff --git a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
index 36da9403..ae0cb09 100644
--- a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
+++ b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
@@ -214,7 +214,6 @@
 #include "third_party/blink/renderer/core/page/page.h"
 #include "third_party/blink/renderer/core/page/print_context.h"
 #include "third_party/blink/renderer/core/paint/paint_layer.h"
-#include "third_party/blink/renderer/core/paint/transform_recorder.h"
 #include "third_party/blink/renderer/core/timing/dom_window_performance.h"
 #include "third_party/blink/renderer/core/timing/window_performance.h"
 #include "third_party/blink/renderer/platform/bindings/dom_wrapper_world.h"
@@ -226,7 +225,6 @@
 #include "third_party/blink/renderer/platform/graphics/color.h"
 #include "third_party/blink/renderer/platform/graphics/graphics_context.h"
 #include "third_party/blink/renderer/platform/graphics/graphics_layer_client.h"
-#include "third_party/blink/renderer/platform/graphics/paint/clip_recorder.h"
 #include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
 #include "third_party/blink/renderer/platform/graphics/paint/paint_record_builder.h"
 #include "third_party/blink/renderer/platform/graphics/paint/scoped_paint_chunk_properties.h"
@@ -388,25 +386,17 @@
 
     auto* frame_view = GetFrame()->View();
     DCHECK(frame_view);
-    PropertyTreeState property_tree_state = PropertyTreeState::Root();
-    if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
-      property_tree_state = frame_view->GetLayoutView()
-                                ->FirstFragment()
-                                .LocalBorderBoxProperties();
-    }
+    PropertyTreeState property_tree_state =
+        frame_view->GetLayoutView()->FirstFragment().LocalBorderBoxProperties();
 
     PaintRecordBuilder builder(&context.Canvas()->getMetaData(), &context);
 
     frame_view->PaintContents(builder.Context(), kGlobalPaintNormalPhase,
                               page_rect);
     {
-      base::Optional<ScopedPaintChunkProperties> scoped_paint_chunk_properties;
-      if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
-        scoped_paint_chunk_properties.emplace(
-            builder.Context().GetPaintController(), property_tree_state,
-            builder, DisplayItem::kPrintedContentDestinationLocations);
-      }
-
+      ScopedPaintChunkProperties scoped_paint_chunk_properties(
+          builder.Context().GetPaintController(), property_tree_state, builder,
+          DisplayItem::kPrintedContentDestinationLocations);
       DrawingRecorder line_boundary_recorder(
           builder.Context(), builder,
           DisplayItem::kPrintedContentDestinationLocations);
@@ -414,7 +404,6 @@
     }
 
     context.DrawRecord(builder.EndRecording(property_tree_state));
-
     context.Restore();
 
     return scale;
diff --git a/third_party/blink/renderer/core/html/anchor_element_metrics.cc b/third_party/blink/renderer/core/html/anchor_element_metrics.cc
index 46125fd..a0e4ee10 100644
--- a/third_party/blink/renderer/core/html/anchor_element_metrics.cc
+++ b/third_party/blink/renderer/core/html/anchor_element_metrics.cc
@@ -63,7 +63,9 @@
   target_location = local_frame_view->ConvertToRootFrame(target_location);
 
   // Calculate features of the anchor element.
-  float ratio_area = FloatSize(target_rect.Size()).Area() / visible_size.Area();
+  // Limit the element size to the viewport size.
+  float ratio_area = std::min(
+      1.0f, FloatSize(target_rect.Size()).Area() / visible_size.Area());
   float ratio_distance_root_top =
       float(target_location.Y() +
             AccumulatedScrollOffset(anchor_element).Height()) /
@@ -82,11 +84,11 @@
 
   UMA_HISTOGRAM_COUNTS_10000(
       "AnchorElementMetrics.Clicked.RatioDistanceRootTop",
-      int(ratio_distance_root_top * 100));
+      int(std::min(ratio_distance_root_top, 100.0f) * 100));
 
-  UMA_HISTOGRAM_PERCENTAGE(
+  UMA_HISTOGRAM_COUNTS_10000(
       "AnchorElementMetrics.Clicked.RatioDistanceVisibleTop",
-      int(ratio_distance_visible_top * 100));
+      int(std::min(ratio_distance_visible_top, 100.0f) * 100));
 
   UMA_HISTOGRAM_BOOLEAN("AnchorElementMetrics.Clicked.IsInIFrame",
                         is_in_iframe);
diff --git a/third_party/blink/renderer/core/html/parser/html_tree_builder.cc b/third_party/blink/renderer/core/html/parser/html_tree_builder.cc
index 30454d0..bbfd0b70 100644
--- a/third_party/blink/renderer/core/html/parser/html_tree_builder.cc
+++ b/third_party/blink/renderer/core/html/parser/html_tree_builder.cc
@@ -552,7 +552,8 @@
       token->GetName() == bgsoundTag || token->GetName() == commandTag ||
       token->GetName() == linkTag || token->GetName() == metaTag ||
       token->GetName() == noframesTag || token->GetName() == scriptTag ||
-      token->GetName() == styleTag || token->GetName() == titleTag) {
+      token->GetName() == styleTag || token->GetName() == titleTag ||
+      token->GetName() == templateTag) {
     bool did_process = ProcessStartTagForInHead(token);
     DCHECK(did_process);
     return;
@@ -847,10 +848,6 @@
     ParseError(token);
     return;
   }
-  if (token->GetName() == templateTag) {
-    ProcessTemplateStartTag(token);
-    return;
-  }
   tree_.ReconstructTheActiveFormattingElements();
   tree_.InsertHTMLElement(token);
 }
@@ -1237,10 +1234,6 @@
         ProcessStartTagForInHead(token);
         return;
       }
-      if (token->GetName() == templateTag) {
-        ProcessTemplateStartTag(token);
-        return;
-      }
       ParseError(token);
       break;
     case kAfterFramesetMode:
@@ -1346,9 +1339,7 @@
       }
 
       InsertionMode insertion_mode = kTemplateContentsMode;
-      if (token->GetName() == frameTag)
-        insertion_mode = kInFramesetMode;
-      else if (token->GetName() == colTag)
+      if (token->GetName() == colTag)
         insertion_mode = kInColumnGroupMode;
       else if (IsCaptionColOrColgroupTag(token->GetName()) ||
                IsTableBodyContextTag(token->GetName()))
@@ -2068,10 +2059,6 @@
           SetInsertionMode(kAfterFramesetMode);
         return;
       }
-      if (token->GetName() == templateTag) {
-        ProcessTemplateEndTag(token);
-        return;
-      }
       break;
     case kAfterFramesetMode:
       DCHECK_EQ(GetInsertionMode(), kAfterFramesetMode);
diff --git a/third_party/blink/renderer/core/html/track/vtt/buffered_line_reader_test.cc b/third_party/blink/renderer/core/html/track/vtt/buffered_line_reader_test.cc
index bc9d59d1..46198a6 100644
--- a/third_party/blink/renderer/core/html/track/vtt/buffered_line_reader_test.cc
+++ b/third_party/blink/renderer/core/html/track/vtt/buffered_line_reader_test.cc
@@ -154,7 +154,7 @@
 String LineBreakString(NewlineType type) {
   static const char kBreakStrings[] = "\r\n";
   return String(type == kLf ? kBreakStrings + 1 : kBreakStrings,
-                type == kCrLf ? 2 : 1);
+                type == kCrLf ? 2u : 1u);
 }
 
 String MakeTestData(const char** lines, const NewlineType* breaks, int count) {
@@ -248,7 +248,7 @@
 
 TEST(BufferedLineReaderTest, NormalizedNUL) {
   BufferedLineReader reader;
-  reader.Append(String("X\0Y\n", 4));
+  reader.Append(String("X\0Y\n", 4u));
   String line;
   ASSERT_TRUE(reader.GetLine(line));
   ASSERT_EQ(line[1], kReplacementCharacter);
diff --git a/third_party/blink/renderer/core/layout/layout_image.cc b/third_party/blink/renderer/core/layout/layout_image.cc
index dd861b7..91b8db1 100644
--- a/third_party/blink/renderer/core/layout/layout_image.cc
+++ b/third_party/blink/renderer/core/layout/layout_image.cc
@@ -257,8 +257,13 @@
   // Check for optimized image policies.
   if (View() && View()->GetFrameView()) {
     bool old_flag = ShouldInvertColor();
-    is_legacy_format_or_compressed_image_ = CheckForOptimizedImagePolicy(
-        View()->GetFrameView()->GetFrame(), this, new_image);
+    const LocalFrame& frame = View()->GetFrameView()->GetFrame();
+    is_legacy_format_or_compressed_image_ =
+        CheckForOptimizedImagePolicy(frame, this, new_image);
+    if (auto* image_element = ToHTMLImageElementOrNull(GetNode())) {
+      is_downscaled_image_ =
+          CheckForMaxDownscalingImagePolicy(frame, image_element, this);
+    }
     if (old_flag != ShouldInvertColor())
       UpdateShouldInvertColor();
   }
diff --git a/third_party/blink/renderer/core/layout/layout_object.h b/third_party/blink/renderer/core/layout/layout_object.h
index ed41ad49..63bf9bf4 100644
--- a/third_party/blink/renderer/core/layout/layout_object.h
+++ b/third_party/blink/renderer/core/layout/layout_object.h
@@ -1930,7 +1930,6 @@
    protected:
     friend class LayoutBoxModelObject;
     friend class LayoutScrollbar;
-    friend class PaintInvalidationCapableScrollableArea;
     friend class PaintInvalidator;
     friend class PaintPropertyTreeBuilder;
     friend class PrePaintTreeWalk;
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_resource_pattern.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_resource_pattern.cc
index af180fc..6d409f6c 100644
--- a/third_party/blink/renderer/core/layout/svg/layout_svg_resource_pattern.cc
+++ b/third_party/blink/renderer/core/layout/svg/layout_svg_resource_pattern.cc
@@ -28,7 +28,6 @@
 #include "third_party/blink/renderer/core/layout/svg/svg_resources.h"
 #include "third_party/blink/renderer/core/layout/svg/svg_resources_cache.h"
 #include "third_party/blink/renderer/core/paint/svg_paint_context.h"
-#include "third_party/blink/renderer/core/paint/transform_recorder.h"
 #include "third_party/blink/renderer/core/svg/svg_fit_to_view_box.h"
 #include "third_party/blink/renderer/core/svg/svg_pattern_element.h"
 #include "third_party/blink/renderer/platform/graphics/graphics_context.h"
diff --git a/third_party/blink/renderer/core/page/page_widget_delegate.cc b/third_party/blink/renderer/core/page/page_widget_delegate.cc
index f28ba97..710b525 100644
--- a/third_party/blink/renderer/core/page/page_widget_delegate.cc
+++ b/third_party/blink/renderer/core/page/page_widget_delegate.cc
@@ -42,9 +42,7 @@
 #include "third_party/blink/renderer/core/page/autoscroll_controller.h"
 #include "third_party/blink/renderer/core/page/page.h"
 #include "third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.h"
-#include "third_party/blink/renderer/core/paint/transform_recorder.h"
 #include "third_party/blink/renderer/platform/graphics/graphics_context.h"
-#include "third_party/blink/renderer/platform/graphics/paint/clip_recorder.h"
 #include "third_party/blink/renderer/platform/graphics/paint/cull_rect.h"
 #include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
 #include "third_party/blink/renderer/platform/graphics/paint/paint_record_builder.h"
diff --git a/third_party/blink/renderer/core/page/scrolling/root_scroller_test.cc b/third_party/blink/renderer/core/page/scrolling/root_scroller_test.cc
index 5b78760..edda98a 100644
--- a/third_party/blink/renderer/core/page/scrolling/root_scroller_test.cc
+++ b/third_party/blink/renderer/core/page/scrolling/root_scroller_test.cc
@@ -562,9 +562,7 @@
     SetAndSelectRootScroller(*MainFrame()->GetDocument(), iframe);
 
     ScrollableArea* container_scroller =
-        static_cast<PaintInvalidationCapableScrollableArea*>(
-            ToLayoutBox(container->GetLayoutObject())->GetScrollableArea());
-
+        ToLayoutBox(container->GetLayoutObject())->GetScrollableArea();
     EXPECT_EQ(main_controller.RootScrollerLayer(),
               container_scroller->LayerForScrolling());
     EXPECT_FALSE(main_controller.IsViewportScrollCallback(
@@ -958,9 +956,7 @@
   SetAndSelectRootScroller(*MainFrame()->GetDocument(), container);
 
   ScrollableArea* container_scroller =
-      static_cast<PaintInvalidationCapableScrollableArea*>(
-          ToLayoutBox(container->GetLayoutObject())->GetScrollableArea());
-
+      ToLayoutBox(container->GetLayoutObject())->GetScrollableArea();
   EXPECT_FALSE(container_scroller->HorizontalScrollbar());
   EXPECT_FALSE(container_scroller->VerticalScrollbar());
   EXPECT_GT(container_scroller->MaximumScrollOffset().Width(), 0);
@@ -1026,8 +1022,7 @@
   SetAndSelectRootScroller(*MainFrame()->GetDocument(), container);
 
   ScrollableArea* container_scroller =
-      static_cast<PaintInvalidationCapableScrollableArea*>(
-          ToLayoutBox(container->GetLayoutObject())->GetScrollableArea());
+      ToLayoutBox(container->GetLayoutObject())->GetScrollableArea();
 
   // Hide the top controls and scroll down maximally. We should account for the
   // change in maximum scroll offset due to the top controls hiding. That is,
@@ -1067,8 +1062,8 @@
         MainFrame()->GetDocument()->getElementById("container");
     SetAndSelectRootScroller(*MainFrame()->GetDocument(), container);
 
-    container_scroller = static_cast<PaintInvalidationCapableScrollableArea*>(
-        ToLayoutBox(container->GetLayoutObject())->GetScrollableArea());
+    container_scroller =
+        ToLayoutBox(container->GetLayoutObject())->GetScrollableArea();
   }
 
   Element* target = MainFrame()->GetDocument()->getElementById("target");
diff --git a/third_party/blink/renderer/core/page/scrolling/root_scroller_util.cc b/third_party/blink/renderer/core/page/scrolling/root_scroller_util.cc
index 5af24eb..87b8a07 100644
--- a/third_party/blink/renderer/core/page/scrolling/root_scroller_util.cc
+++ b/third_party/blink/renderer/core/page/scrolling/root_scroller_util.cc
@@ -42,8 +42,8 @@
   if (!element->GetLayoutObject() || !element->GetLayoutObject()->IsBox())
     return nullptr;
 
-  return static_cast<PaintInvalidationCapableScrollableArea*>(
-      ToLayoutBoxModelObject(element->GetLayoutObject())->GetScrollableArea());
+  return ToLayoutBoxModelObject(element->GetLayoutObject())
+      ->GetScrollableArea();
 }
 
 PaintLayer* PaintLayerForRootScroller(const Node* node) {
diff --git a/third_party/blink/renderer/core/paint/BUILD.gn b/third_party/blink/renderer/core/paint/BUILD.gn
index b1eff1f..0927a4d5 100644
--- a/third_party/blink/renderer/core/paint/BUILD.gn
+++ b/third_party/blink/renderer/core/paint/BUILD.gn
@@ -91,13 +91,9 @@
     "file_upload_control_painter.h",
     "filter_effect_builder.cc",
     "filter_effect_builder.h",
-    "filter_painter.cc",
-    "filter_painter.h",
     "find_properties_needing_update.h",
     "first_meaningful_paint_detector.cc",
     "first_meaningful_paint_detector.h",
-    "float_clip_recorder.cc",
-    "float_clip_recorder.h",
     "fragment_data.cc",
     "fragment_data.h",
     "frame_paint_timing.h",
@@ -160,8 +156,6 @@
     "object_painter_base.h",
     "paint_event.h",
     "paint_info.h",
-    "paint_invalidation_capable_scrollable_area.cc",
-    "paint_invalidation_capable_scrollable_area.h",
     "paint_invalidator.cc",
     "paint_invalidator.h",
     "paint_layer.cc",
@@ -197,12 +191,8 @@
     "root_inline_box_painter.h",
     "rounded_inner_rect_clipper.cc",
     "rounded_inner_rect_clipper.h",
-    "scroll_recorder.cc",
-    "scroll_recorder.h",
     "scrollable_area_painter.cc",
     "scrollable_area_painter.h",
-    "scrollbar_manager.cc",
-    "scrollbar_manager.h",
     "scrollbar_painter.cc",
     "scrollbar_painter.h",
     "selection_painting_utils.cc",
@@ -254,10 +244,6 @@
     "theme_painter_default.h",
     "theme_painter_mac.h",
     "theme_painter_mac.mm",
-    "transform_3d_recorder.cc",
-    "transform_3d_recorder.h",
-    "transform_recorder.cc",
-    "transform_recorder.h",
     "video_painter.cc",
     "video_painter.h",
     "view_painter.cc",
diff --git a/third_party/blink/renderer/core/paint/block_painter.cc b/third_party/blink/renderer/core/paint/block_painter.cc
index 71bc036e..c80ca6d3 100644
--- a/third_party/blink/renderer/core/paint/block_painter.cc
+++ b/third_party/blink/renderer/core/paint/block_painter.cc
@@ -19,10 +19,8 @@
 #include "third_party/blink/renderer/core/paint/object_painter.h"
 #include "third_party/blink/renderer/core/paint/paint_info.h"
 #include "third_party/blink/renderer/core/paint/paint_layer.h"
-#include "third_party/blink/renderer/core/paint/scroll_recorder.h"
 #include "third_party/blink/renderer/core/paint/scrollable_area_painter.h"
 #include "third_party/blink/renderer/platform/graphics/graphics_layer.h"
-#include "third_party/blink/renderer/platform/graphics/paint/clip_recorder.h"
 #include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
 #include "third_party/blink/renderer/platform/graphics/paint/scroll_hit_test_display_item.h"
 
@@ -87,14 +85,6 @@
   if (layout_block_.HasOverflowClip() &&
       layout_block_.Style()->Visibility() == EVisibility::kVisible &&
       ShouldPaintSelfBlockBackground(paint_info.phase)) {
-    base::Optional<ClipRecorder> clip_recorder;
-    if (!layout_block_.Layer()->IsSelfPaintingLayer()) {
-      LayoutRect clip_rect = layout_block_.BorderBoxRect();
-      clip_rect.MoveBy(paint_offset);
-      clip_recorder.emplace(paint_info.context, layout_block_,
-                            DisplayItem::kClipScrollbarsToBoxBounds,
-                            PixelSnappedIntRect(clip_rect));
-    }
     ScrollableAreaPainter(*layout_block_.Layer()->GetScrollableArea())
         .PaintOverflowControls(paint_info, RoundedIntPoint(paint_offset),
                                false /* painting_overlay_controls */);
@@ -268,38 +258,24 @@
 
   if (paint_phase != PaintPhase::kSelfOutlineOnly) {
     base::Optional<ScopedPaintChunkProperties> scoped_scroll_property;
-    base::Optional<ScrollRecorder> scroll_recorder;
     base::Optional<PaintInfo> scrolled_paint_info;
-    if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
-      if (const auto* fragment = paint_info.FragmentToPaint(layout_block_)) {
-        const auto* object_properties = fragment->PaintProperties();
-        auto* scroll_translation = object_properties
-                                       ? object_properties->ScrollTranslation()
-                                       : nullptr;
-        if (scroll_translation) {
-          scoped_scroll_property.emplace(
-              paint_info.context.GetPaintController(), scroll_translation,
-              layout_block_, DisplayItem::PaintPhaseToScrollType(paint_phase));
-          scrolled_paint_info.emplace(paint_info);
-          if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
-            scrolled_paint_info->UpdateCullRectForScrollingContents(
-                EnclosingIntRect(layout_block_.OverflowClipRect(paint_offset)),
-                scroll_translation->Matrix().ToAffineTransform());
-          } else {
-            scrolled_paint_info->UpdateCullRect(
-                scroll_translation->Matrix().ToAffineTransform());
-          }
-        }
-      }
-    } else if (layout_block_.HasOverflowClip()) {
-      IntSize scroll_offset = layout_block_.ScrolledContentOffset();
-      if (layout_block_.Layer()->ScrollsOverflow() || !scroll_offset.IsZero()) {
-        scroll_recorder.emplace(paint_info.context, layout_block_, paint_phase,
-                                scroll_offset);
+    if (const auto* fragment = paint_info.FragmentToPaint(layout_block_)) {
+      const auto* object_properties = fragment->PaintProperties();
+      auto* scroll_translation =
+          object_properties ? object_properties->ScrollTranslation() : nullptr;
+      if (scroll_translation) {
+        scoped_scroll_property.emplace(
+            paint_info.context.GetPaintController(), scroll_translation,
+            layout_block_, DisplayItem::PaintPhaseToScrollType(paint_phase));
         scrolled_paint_info.emplace(paint_info);
-        AffineTransform transform;
-        transform.Translate(-scroll_offset.Width(), -scroll_offset.Height());
-        scrolled_paint_info->UpdateCullRect(transform);
+        if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) {
+          scrolled_paint_info->UpdateCullRectForScrollingContents(
+              EnclosingIntRect(layout_block_.OverflowClipRect(paint_offset)),
+              scroll_translation->Matrix().ToAffineTransform());
+        } else {
+          scrolled_paint_info->UpdateCullRect(
+              scroll_translation->Matrix().ToAffineTransform());
+        }
       }
     }
 
diff --git a/third_party/blink/renderer/core/paint/box_clipper.cc b/third_party/blink/renderer/core/paint/box_clipper.cc
index 5edcc4e..1affee0d 100644
--- a/third_party/blink/renderer/core/paint/box_clipper.cc
+++ b/third_party/blink/renderer/core/paint/box_clipper.cc
@@ -10,25 +10,11 @@
 #include "third_party/blink/renderer/core/paint/paint_info.h"
 #include "third_party/blink/renderer/core/paint/paint_layer.h"
 #include "third_party/blink/renderer/platform/graphics/graphics_layer.h"
-#include "third_party/blink/renderer/platform/graphics/paint/clip_display_item.h"
 #include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h"
 #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
 
 namespace blink {
 
-// Clips for boxes are applied by the box's PaintLayerClipper, if the box has
-// a self-painting PaintLayer. Otherwise the box clips itself.
-// Note that this method is very similar to
-// PaintLayerClipper::shouldClipOverflow for that reason.
-//
-// An exception is control clip, which is currently never applied by
-// PaintLayerClipper.
-static bool BoxNeedsClip(const LayoutBox& box) {
-  if (box.HasLayer() && box.Layer()->IsSelfPaintingLayer())
-    return false;
-  return box.ShouldClipOverflow();
-}
-
 DISABLE_CFI_PERF
 BoxClipper::BoxClipper(const LayoutBox& box,
                        const PaintInfo& paint_info,
@@ -43,60 +29,8 @@
   if (paint_info_.phase == PaintPhase::kMask)
     return;
 
-  if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
-    InitializeScopedClipProperty(paint_info.FragmentToPaint(box_), box,
-                                 paint_info);
-    return;
-  }
-
-  if (!BoxNeedsClip(box_))
-    return;
-
-  LayoutRect clip_rect = box_.OverflowClipRect(accumulated_offset);
-  FloatRoundedRect clip_rounded_rect(0, 0, 0, 0);
-  bool has_border_radius = box_.Style()->HasBorderRadius();
-  if (has_border_radius) {
-    clip_rounded_rect = box_.Style()->GetRoundedInnerBorderFor(
-        LayoutRect(accumulated_offset, box_.Size()));
-  }
-
-  // Selection may extend beyond visual overflow, so this optimization is
-  // invalid if selection is present.
-  if (contents_clip_behavior == kSkipContentsClipIfPossible &&
-      box.GetSelectionState() == SelectionState::kNone) {
-    LayoutRect contents_visual_overflow = box_.ContentsVisualOverflowRect();
-    if (contents_visual_overflow.IsEmpty())
-      return;
-
-    LayoutRect conservative_clip_rect = clip_rect;
-    if (has_border_radius)
-      conservative_clip_rect.Intersect(
-          LayoutRect(clip_rounded_rect.RadiusCenterRect()));
-    conservative_clip_rect.MoveBy(-accumulated_offset);
-    if (box_.HasLayer())
-      conservative_clip_rect.Move(box_.ScrolledContentOffset());
-    if (conservative_clip_rect.Contains(contents_visual_overflow))
-      return;
-  }
-
-  if (!paint_info_.context.GetPaintController()
-           .DisplayItemConstructionIsDisabled()) {
-    clip_type_ = paint_info_.DisplayItemTypeForClipping();
-    Vector<FloatRoundedRect> rounded_rects;
-    if (has_border_radius)
-      rounded_rects.push_back(clip_rounded_rect);
-    paint_info_.context.GetPaintController().CreateAndAppend<ClipDisplayItem>(
-        box_, clip_type_, PixelSnappedIntRect(clip_rect), rounded_rects);
-  }
-}
-
-BoxClipper::~BoxClipper() {
-  if (clip_type_ == DisplayItem::kUninitializedType)
-    return;
-
-  DCHECK(BoxNeedsClip(box_));
-  paint_info_.context.GetPaintController().EndItem<EndClipDisplayItem>(
-      box_, DisplayItem::ClipTypeToEndClipType(clip_type_));
+  InitializeScopedClipProperty(paint_info.FragmentToPaint(box_), box,
+                               paint_info);
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/paint/box_clipper.h b/third_party/blink/renderer/core/paint/box_clipper.h
index b9c967d..eb8be29 100644
--- a/third_party/blink/renderer/core/paint/box_clipper.h
+++ b/third_party/blink/renderer/core/paint/box_clipper.h
@@ -13,6 +13,9 @@
 
 class LayoutBox;
 
+// TODO(wangxianzhu): Combine this tiny module with box_clipper_base.h, and
+// cleanup unused flags and parameters.
+
 enum ContentsClipBehavior { kForceContentsClip, kSkipContentsClipIfPossible };
 
 class BoxClipper : public BoxClipperBase {
@@ -23,7 +26,6 @@
              const PaintInfo&,
              const LayoutPoint& accumulated_offset,
              ContentsClipBehavior);
-  ~BoxClipper();
 
  private:
   const LayoutBox& box_;
diff --git a/third_party/blink/renderer/core/paint/box_clipper_base.cc b/third_party/blink/renderer/core/paint/box_clipper_base.cc
index 5b3acb3..1bb5f6d 100644
--- a/third_party/blink/renderer/core/paint/box_clipper_base.cc
+++ b/third_party/blink/renderer/core/paint/box_clipper_base.cc
@@ -8,7 +8,6 @@
 #include "third_party/blink/renderer/core/paint/paint_info.h"
 #include "third_party/blink/renderer/core/paint/paint_layer.h"
 #include "third_party/blink/renderer/platform/graphics/graphics_layer.h"
-#include "third_party/blink/renderer/platform/graphics/paint/clip_display_item.h"
 #include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h"
 #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
 
diff --git a/third_party/blink/renderer/core/paint/box_painter.cc b/third_party/blink/renderer/core/paint/box_painter.cc
index f7782f3..791f29078 100644
--- a/third_party/blink/renderer/core/paint/box_painter.cc
+++ b/third_party/blink/renderer/core/paint/box_painter.cc
@@ -20,7 +20,6 @@
 #include "third_party/blink/renderer/core/paint/nine_piece_image_painter.h"
 #include "third_party/blink/renderer/core/paint/object_painter.h"
 #include "third_party/blink/renderer/core/paint/paint_info.h"
-#include "third_party/blink/renderer/core/paint/scroll_recorder.h"
 #include "third_party/blink/renderer/core/paint/svg_foreign_object_painter.h"
 #include "third_party/blink/renderer/core/paint/theme_painter.h"
 #include "third_party/blink/renderer/platform/geometry/layout_point.h"
@@ -57,7 +56,6 @@
 void BoxPainter::PaintBoxDecorationBackground(const PaintInfo& paint_info,
                                               const LayoutPoint& paint_offset) {
   LayoutRect paint_rect;
-  base::Optional<ScrollRecorder> scroll_recorder;
   base::Optional<ScopedPaintChunkProperties> scoped_scroll_property;
   if (BoxModelObjectPainter::
           IsPaintingBackgroundOfPaintContainerIntoScrollingContentsLayer(
@@ -67,8 +65,6 @@
     // overflow rect.
     paint_rect = layout_box_.PhysicalLayoutOverflowRect();
 
-    scroll_recorder.emplace(paint_info.context, layout_box_, paint_info.phase,
-                            layout_box_.ScrolledContentOffset());
     if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
       if (const auto* fragment = paint_info.FragmentToPaint(layout_box_)) {
         scoped_scroll_property.emplace(
diff --git a/third_party/blink/renderer/core/paint/clip_path_clipper.cc b/third_party/blink/renderer/core/paint/clip_path_clipper.cc
index 21b120ddc..65e8bfc4 100644
--- a/third_party/blink/renderer/core/paint/clip_path_clipper.cc
+++ b/third_party/blink/renderer/core/paint/clip_path_clipper.cc
@@ -145,35 +145,6 @@
       layout_object_(layout_object),
       paint_offset_(paint_offset) {
   DCHECK(layout_object.StyleRef().ClipPath());
-
-  // Technically we should apply the mask clip and mask isolation property
-  // nodes to match clip_recorder_ and mask_isolation_recorder_ below,
-  // but we can safely omit those, because they will be applied in bundle
-  // when the contents are painted.
-  if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
-    return;
-
-  base::Optional<FloatRect> bounding_box =
-      LocalClipPathBoundingBox(layout_object);
-  if (!bounding_box)
-    return;
-
-  FloatRect adjusted_bounding_box = *bounding_box;
-  adjusted_bounding_box.MoveBy(FloatPoint(paint_offset));
-  clip_recorder_.emplace(context, layout_object,
-                         DisplayItem::kFloatClipClipPathBounds,
-                         adjusted_bounding_box);
-
-  bool is_valid = false;
-  if (base::Optional<Path> as_path =
-          PathBasedClip(layout_object, layout_object.IsSVGChild(),
-                        LocalReferenceBox(layout_object), is_valid)) {
-    as_path->Translate(FloatSize(paint_offset.X(), paint_offset.Y()));
-    clip_path_recorder_.emplace(context, layout_object, *as_path);
-  } else if (is_valid) {
-    mask_isolation_recorder_.emplace(context, layout_object,
-                                     SkBlendMode::kSrcOver, 1.f);
-  }
 }
 
 static AffineTransform MaskToContentTransform(
@@ -195,24 +166,17 @@
 }
 
 ClipPathClipper::~ClipPathClipper() {
-  base::Optional<ScopedPaintChunkProperties> scoped_properties;
-  if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
-    const auto* properties = layout_object_.FirstFragment().PaintProperties();
-    if (!properties || !properties->ClipPath())
-      return;
-    scoped_properties.emplace(
-        context_.GetPaintController(),
-        layout_object_.FirstFragment().ClipPathProperties(), layout_object_,
-        DisplayItem::kSVGClip);
-  } else if (!mask_isolation_recorder_) {
+  const auto* properties = layout_object_.FirstFragment().PaintProperties();
+  if (!properties || !properties->ClipPath())
     return;
-  }
+  ScopedPaintChunkProperties scoped_properties(
+      context_.GetPaintController(),
+      layout_object_.FirstFragment().ClipPathProperties(), layout_object_,
+      DisplayItem::kSVGClip);
 
   bool is_svg_child = layout_object_.IsSVGChild();
   FloatRect reference_box = LocalReferenceBox(layout_object_);
 
-  CompositingRecorder mask_recorder(context_, layout_object_,
-                                    SkBlendMode::kDstIn, 1.f);
   if (DrawingRecorder::UseCachedDrawingIfPossible(context_, layout_object_,
                                                   DisplayItem::kSVGClip))
     return;
diff --git a/third_party/blink/renderer/core/paint/clip_path_clipper.h b/third_party/blink/renderer/core/paint/clip_path_clipper.h
index debbc7e1..9bea09e 100644
--- a/third_party/blink/renderer/core/paint/clip_path_clipper.h
+++ b/third_party/blink/renderer/core/paint/clip_path_clipper.h
@@ -7,10 +7,9 @@
 
 #include "base/optional.h"
 #include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/paint/float_clip_recorder.h"
 #include "third_party/blink/renderer/platform/geometry/float_rect.h"
-#include "third_party/blink/renderer/platform/graphics/paint/clip_path_recorder.h"
-#include "third_party/blink/renderer/platform/graphics/paint/compositing_recorder.h"
+#include "third_party/blink/renderer/platform/geometry/layout_point.h"
+#include "third_party/blink/renderer/platform/graphics/path.h"
 
 namespace blink {
 
@@ -26,8 +25,6 @@
                   const LayoutPoint& paint_offset);
   ~ClipPathClipper();
 
-  bool IsIsolationInstalled() const { return !!mask_isolation_recorder_; }
-
   // Returns the reference box used by CSS clip-path. For HTML objects,
   // this is the border box of the element. For SVG objects this is the
   // object bounding box.
@@ -56,10 +53,6 @@
   GraphicsContext& context_;
   const LayoutObject& layout_object_;
   LayoutPoint paint_offset_;
-
-  base::Optional<FloatClipRecorder> clip_recorder_;
-  base::Optional<ClipPathRecorder> clip_path_recorder_;
-  base::Optional<CompositingRecorder> mask_isolation_recorder_;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc b/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc
index 5b78051a..da89d14 100644
--- a/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc
+++ b/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc
@@ -65,18 +65,14 @@
 #include "third_party/blink/renderer/core/paint/paint_layer_painter.h"
 #include "third_party/blink/renderer/core/paint/paint_layer_stacking_node_iterator.h"
 #include "third_party/blink/renderer/core/paint/scrollable_area_painter.h"
-#include "third_party/blink/renderer/core/paint/transform_recorder.h"
 #include "third_party/blink/renderer/core/probe/core_probes.h"
 #include "third_party/blink/renderer/platform/fonts/font_cache.h"
 #include "third_party/blink/renderer/platform/graphics/bitmap_image.h"
 #include "third_party/blink/renderer/platform/graphics/compositor_filter_operations.h"
 #include "third_party/blink/renderer/platform/graphics/graphics_context.h"
-#include "third_party/blink/renderer/platform/graphics/paint/clip_display_item.h"
-#include "third_party/blink/renderer/platform/graphics/paint/clip_recorder.h"
 #include "third_party/blink/renderer/platform/graphics/paint/cull_rect.h"
 #include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
 #include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h"
-#include "third_party/blink/renderer/platform/graphics/paint/transform_display_item.h"
 #include "third_party/blink/renderer/platform/length_functions.h"
 #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
 #include "third_party/blink/renderer/platform/transforms/transform_state.h"
@@ -3127,10 +3123,6 @@
   FontCachePurgePreventer font_cache_purge_preventer;
 
   IntSize offset = paint_info.offset_from_layout_object;
-  AffineTransform translation;
-  translation.Translate(-offset.Width(), -offset.Height());
-  TransformRecorder transform_recorder(context, graphics_layer, translation);
-
   // The dirtyRect is in the coords of the painting root.
   IntRect dirty_rect(clip);
   dirty_rect.Move(offset);
@@ -3182,22 +3174,6 @@
     PaintLayerPaintingInfo painting_info(
         paint_info.paint_layer, LayoutRect(dirty_rect), kGlobalPaintNormalPhase,
         paint_info.paint_layer->SubpixelAccumulation());
-
-    // PaintLayer::paintLayer assumes that the caller clips to the passed rect.
-    // Squashed layers need to do this clipping in software, since there is no
-    // graphics layer to clip them precisely. Furthermore, in some cases we
-    // squash layers that need clipping in software from clipping ancestors (see
-    // CompositedLayerMapping::localClipRectForSquashedLayer()).
-    // FIXME: Is it correct to clip to dirtyRect in slimming paint mode?
-    ClipRect clip_rect = paint_info.local_clip_rect_for_squashed_layer;
-    clip_rect.Intersect(LayoutRect(dirty_rect));
-
-    LayerClipRecorder layer_clip_recorder(
-        context, *paint_info.paint_layer,
-        DisplayItem::kClipLayerOverflowControls, clip_rect,
-        paint_info.local_clip_rect_root, paint_info.offset_from_clip_rect_root,
-        paint_layer_flags, graphics_layer,
-        LayerClipRecorder::kDoNotIncludeSelfForBorderRadius);
     PaintLayerPainter(*paint_info.paint_layer)
         .Paint(context, painting_info, paint_layer_flags);
   }
@@ -3514,19 +3490,10 @@
     const GraphicsLayer* graphics_layer,
     GraphicsContext& context,
     const IntRect& interest_rect) const {
-  // Note the composited scrollable area painted here is never associated with a
-  // frame. For painting frame ScrollableAreas, see
-  // PaintLayerCompositor::paintContents.
-
-  // Map context and cull_rect which are in the local space of the scrollbar
-  // to the space of the containing scrollable area in which Scrollbar::Paint()
-  // will paint the scrollbar.
-  auto offset = graphics_layer->OffsetFromLayoutObject();
-  CullRect cull_rect(CullRect(interest_rect), offset);
-  TransformRecorder transform_recorder(
-      context, *graphics_layer,
-      AffineTransform::Translation(-offset.Width(), -offset.Height()));
-
+  // cull_rect is in the space of the containing scrollable area in which
+  // Scrollbar::Paint() will paint the scrollbar.
+  CullRect cull_rect(CullRect(interest_rect),
+                     graphics_layer->OffsetFromLayoutObject());
   PaintLayerScrollableArea* scrollable_area = owning_layer_.GetScrollableArea();
   if (graphics_layer == LayerForHorizontalScrollbar()) {
     if (const Scrollbar* scrollbar = scrollable_area->HorizontalScrollbar())
diff --git a/third_party/blink/renderer/core/paint/embedded_content_painter.cc b/third_party/blink/renderer/core/paint/embedded_content_painter.cc
index 95500c3f..54b09d4 100644
--- a/third_party/blink/renderer/core/paint/embedded_content_painter.cc
+++ b/third_party/blink/renderer/core/paint/embedded_content_painter.cc
@@ -16,7 +16,6 @@
 #include "third_party/blink/renderer/core/paint/rounded_inner_rect_clipper.h"
 #include "third_party/blink/renderer/core/paint/scrollable_area_painter.h"
 #include "third_party/blink/renderer/core/paint/selection_painting_utils.h"
-#include "third_party/blink/renderer/core/paint/transform_recorder.h"
 #include "third_party/blink/renderer/platform/graphics/paint/display_item_cache_skipper.h"
 #include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
 
@@ -159,10 +158,6 @@
   // the frame rect neutralized.
   IntSize view_paint_offset =
       paint_location - embedded_content_view->FrameRect().Location();
-  TransformRecorder transform(
-      local_paint_info.context, layout_embedded_content_,
-      AffineTransform::Translation(view_paint_offset.Width(),
-                                   view_paint_offset.Height()));
   CullRect adjusted_cull_rect(local_paint_info.GetCullRect(),
                               -view_paint_offset);
   embedded_content_view->Paint(
diff --git a/third_party/blink/renderer/core/paint/file_upload_control_painter.cc b/third_party/blink/renderer/core/paint/file_upload_control_painter.cc
index 68b5b460..8f20777 100644
--- a/third_party/blink/renderer/core/paint/file_upload_control_painter.cc
+++ b/third_party/blink/renderer/core/paint/file_upload_control_painter.cc
@@ -10,36 +10,16 @@
 #include "third_party/blink/renderer/core/layout/text_run_constructor.h"
 #include "third_party/blink/renderer/core/paint/paint_info.h"
 #include "third_party/blink/renderer/platform/fonts/text_run_paint_info.h"
-#include "third_party/blink/renderer/platform/graphics/paint/clip_recorder.h"
 #include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
 
 namespace blink {
 
-const int kButtonShadowHeight = 2;
-
 void FileUploadControlPainter::PaintObject(const PaintInfo& paint_info,
                                            const LayoutPoint& paint_offset) {
   if (layout_file_upload_control_.Style()->Visibility() !=
       EVisibility::kVisible)
     return;
 
-  // Push a clip.
-  base::Optional<ClipRecorder> clip_recorder;
-  if (paint_info.phase == PaintPhase::kForeground ||
-      paint_info.phase == PaintPhase::kDescendantBlockBackgroundsOnly) {
-    IntRect clip_rect = EnclosingIntRect(LayoutRect(
-        LayoutPoint(paint_offset.X() + layout_file_upload_control_.BorderLeft(),
-                    paint_offset.Y() + layout_file_upload_control_.BorderTop()),
-        layout_file_upload_control_.Size() +
-            LayoutSize(LayoutUnit(),
-                       -layout_file_upload_control_.BorderWidth() +
-                           kButtonShadowHeight)));
-    if (clip_rect.IsEmpty())
-      return;
-    clip_recorder.emplace(paint_info.context, layout_file_upload_control_,
-                          DisplayItem::kClipFileUploadControlRect, clip_rect);
-  }
-
   if (paint_info.phase == PaintPhase::kForeground &&
       !DrawingRecorder::UseCachedDrawingIfPossible(
           paint_info.context, layout_file_upload_control_, paint_info.phase)) {
diff --git a/third_party/blink/renderer/core/paint/filter_painter.cc b/third_party/blink/renderer/core/paint/filter_painter.cc
deleted file mode 100644
index 6613a0aa..0000000
--- a/third_party/blink/renderer/core/paint/filter_painter.cc
+++ /dev/null
@@ -1,95 +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 "third_party/blink/renderer/core/paint/filter_painter.h"
-
-#include <memory>
-#include <utility>
-
-#include "third_party/blink/renderer/core/paint/filter_effect_builder.h"
-#include "third_party/blink/renderer/core/paint/layer_clip_recorder.h"
-#include "third_party/blink/renderer/core/paint/paint_layer.h"
-#include "third_party/blink/renderer/platform/graphics/compositor_filter_operations.h"
-#include "third_party/blink/renderer/platform/graphics/filters/filter_effect.h"
-#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
-#include "third_party/blink/renderer/platform/graphics/graphics_layer.h"
-#include "third_party/blink/renderer/platform/graphics/paint/filter_display_item.h"
-#include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h"
-#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
-
-namespace blink {
-
-sk_sp<PaintFilter> FilterPainter::GetImageFilter(PaintLayer& layer) {
-  if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
-    return nullptr;
-
-  if (!layer.PaintsWithFilters())
-    return nullptr;
-
-  FilterEffect* last_effect = layer.LastFilterEffect();
-  if (!last_effect)
-    return nullptr;
-
-  return PaintFilterBuilder::Build(last_effect, kInterpolationSpaceSRGB);
-}
-
-FilterPainter::FilterPainter(PaintLayer& layer,
-                             GraphicsContext& context,
-                             const LayoutPoint& offset_from_root,
-                             const ClipRect& clip_rect,
-                             PaintLayerPaintingInfo& painting_info,
-                             PaintLayerFlags paint_flags)
-    : filter_in_progress_(false),
-      context_(context),
-      layout_object_(layer.GetLayoutObject()) {
-  sk_sp<PaintFilter> image_filter = GetImageFilter(layer);
-  if (!image_filter)
-    return;
-
-  if (clip_rect.Rect() != painting_info.paint_dirty_rect ||
-      clip_rect.HasRadius()) {
-    // Apply clips outside the filter. See discussion about these clips
-    // in PaintLayerPainter regarding "clipping in the presence of filters".
-    clip_recorder_ = std::make_unique<LayerClipRecorder>(
-        context, layer, DisplayItem::kClipLayerFilter, clip_rect,
-        painting_info.root_layer, LayoutPoint(), paint_flags,
-        layer.GetLayoutObject());
-  }
-
-  if (!context.GetPaintController().DisplayItemConstructionIsDisabled()) {
-    CompositorFilterOperations compositor_filter_operations;
-    layer.UpdateCompositorFilterOperationsForFilter(
-        compositor_filter_operations);
-    // FIXME: It's possible to have empty CompositorFilterOperations here even
-    // though the PaintFilter produced above is non-null, since the
-    // layer's FilterEffectBuilder can have a stale representation of
-    // the layer's filter. See crbug.com/502026.
-    if (compositor_filter_operations.IsEmpty())
-      return;
-    LayoutRect visual_bounds(
-        layer.PhysicalBoundingBoxIncludingStackingChildren(offset_from_root));
-    if (layer.EnclosingPaginationLayer()) {
-      // Filters are set up before pagination, so we need to make the bounding
-      // box visual on our own.
-      visual_bounds.MoveBy(-offset_from_root);
-      layer.ConvertFromFlowThreadToVisualBoundingBoxInAncestor(
-          painting_info.root_layer, visual_bounds);
-    }
-    FloatPoint origin(offset_from_root);
-    context.GetPaintController().CreateAndAppend<BeginFilterDisplayItem>(
-        layout_object_, std::move(image_filter), FloatRect(visual_bounds),
-        origin, std::move(compositor_filter_operations));
-  }
-
-  filter_in_progress_ = true;
-}
-
-FilterPainter::~FilterPainter() {
-  if (!filter_in_progress_)
-    return;
-
-  context_.GetPaintController().EndItem<EndFilterDisplayItem>(layout_object_);
-}
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/core/paint/filter_painter.h b/third_party/blink/renderer/core/paint/filter_painter.h
deleted file mode 100644
index 97c4ea3..0000000
--- a/third_party/blink/renderer/core/paint/filter_painter.h
+++ /dev/null
@@ -1,45 +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 THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_FILTER_PAINTER_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_FILTER_PAINTER_H_
-
-#include <memory>
-#include "third_party/blink/renderer/core/paint/paint_layer_painting_info.h"
-#include "third_party/blink/renderer/platform/graphics/filters/paint_filter_builder.h"
-#include "third_party/blink/renderer/platform/wtf/allocator.h"
-
-namespace blink {
-
-class ClipRect;
-class GraphicsContext;
-class PaintLayer;
-class LayerClipRecorder;
-class LayoutObject;
-
-class FilterPainter {
- public:
-  FilterPainter(PaintLayer&,
-                GraphicsContext&,
-                const LayoutPoint& offset_from_root,
-                const ClipRect&,
-                PaintLayerPaintingInfo&,
-                PaintLayerFlags paint_flags);
-  ~FilterPainter();
-
-  // Returns whether it's ok to clip this PaintLayer's painted outputs
-  // the dirty rect. Some filters require input from outside this rect, in
-  // which case this method would return true.
-  static sk_sp<PaintFilter> GetImageFilter(PaintLayer&);
-
- private:
-  bool filter_in_progress_;
-  GraphicsContext& context_;
-  std::unique_ptr<LayerClipRecorder> clip_recorder_;
-  LayoutObject& layout_object_;
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_FILTER_PAINTER_H_
diff --git a/third_party/blink/renderer/core/paint/float_clip_recorder.cc b/third_party/blink/renderer/core/paint/float_clip_recorder.cc
deleted file mode 100644
index 4d79a428..0000000
--- a/third_party/blink/renderer/core/paint/float_clip_recorder.cc
+++ /dev/null
@@ -1,42 +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 "third_party/blink/renderer/core/paint/float_clip_recorder.h"
-
-#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
-#include "third_party/blink/renderer/platform/graphics/paint/float_clip_display_item.h"
-#include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h"
-
-namespace blink {
-
-FloatClipRecorder::FloatClipRecorder(GraphicsContext& context,
-                                     const DisplayItemClient& client,
-                                     PaintPhase paint_phase,
-                                     const FloatRect& clip_rect)
-    : FloatClipRecorder(context,
-                        client,
-                        DisplayItem::PaintPhaseToFloatClipType(paint_phase),
-                        clip_rect) {}
-
-FloatClipRecorder::FloatClipRecorder(GraphicsContext& context,
-                                     const DisplayItemClient& client,
-                                     DisplayItem::Type clip_type,
-                                     const FloatRect& clip_rect)
-    : context_(context), client_(client), clip_type_(clip_type) {
-  if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
-    return;
-  context_.GetPaintController().CreateAndAppend<FloatClipDisplayItem>(
-      client_, clip_type_, clip_rect);
-}
-
-FloatClipRecorder::~FloatClipRecorder() {
-  if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
-    return;
-  DisplayItem::Type end_type =
-      DisplayItem::FloatClipTypeToEndFloatClipType(clip_type_);
-  context_.GetPaintController().EndItem<EndFloatClipDisplayItem>(client_,
-                                                                 end_type);
-}
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/core/paint/float_clip_recorder.h b/third_party/blink/renderer/core/paint/float_clip_recorder.h
deleted file mode 100644
index 0700c56..0000000
--- a/third_party/blink/renderer/core/paint/float_clip_recorder.h
+++ /dev/null
@@ -1,40 +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 THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_FLOAT_CLIP_RECORDER_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_FLOAT_CLIP_RECORDER_H_
-
-#include "base/macros.h"
-#include "third_party/blink/renderer/core/paint/paint_phase.h"
-#include "third_party/blink/renderer/platform/geometry/float_rect.h"
-#include "third_party/blink/renderer/platform/graphics/paint/display_item.h"
-#include "third_party/blink/renderer/platform/wtf/allocator.h"
-
-namespace blink {
-
-class FloatClipRecorder {
-  USING_FAST_MALLOC(FloatClipRecorder);
-
- public:
-  FloatClipRecorder(GraphicsContext&,
-                    const DisplayItemClient&,
-                    PaintPhase,
-                    const FloatRect&);
-  FloatClipRecorder(GraphicsContext&,
-                    const DisplayItemClient&,
-                    DisplayItem::Type,
-                    const FloatRect&);
-
-  ~FloatClipRecorder();
-
- private:
-  GraphicsContext& context_;
-  const DisplayItemClient& client_;
-  DisplayItem::Type clip_type_;
-  DISALLOW_COPY_AND_ASSIGN(FloatClipRecorder);
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_FLOAT_CLIP_RECORDER_H_
diff --git a/third_party/blink/renderer/core/paint/frame_painter.cc b/third_party/blink/renderer/core/paint/frame_painter.cc
index 4c84356..3c172037 100644
--- a/third_party/blink/renderer/core/paint/frame_painter.cc
+++ b/third_party/blink/renderer/core/paint/frame_painter.cc
@@ -11,12 +11,12 @@
 #include "third_party/blink/renderer/core/paint/frame_paint_timing.h"
 #include "third_party/blink/renderer/core/paint/paint_layer.h"
 #include "third_party/blink/renderer/core/paint/paint_layer_painter.h"
-#include "third_party/blink/renderer/core/paint/transform_recorder.h"
+#include "third_party/blink/renderer/core/paint/scrollbar_painter.h"
 #include "third_party/blink/renderer/core/probe/core_probes.h"
 #include "third_party/blink/renderer/platform/graphics/graphics_context.h"
 #include "third_party/blink/renderer/platform/graphics/graphics_layer.h"
-#include "third_party/blink/renderer/platform/graphics/paint/clip_recorder.h"
 #include "third_party/blink/renderer/platform/graphics/paint/cull_rect.h"
+#include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
 #include "third_party/blink/renderer/platform/loader/fetch/memory_cache.h"
 
 namespace blink {
@@ -44,15 +44,6 @@
   if (document_dirty_rect.IsEmpty())
     return;
 
-  TransformRecorder transform_recorder(
-      context, *GetFrameView().GetLayoutView(),
-      AffineTransform::Translation(
-          frame_view_location.X() - GetFrameView().ScrollX(),
-          frame_view_location.Y() - GetFrameView().ScrollY()));
-
-  ClipRecorder clip_recorder(context, *GetFrameView().GetLayoutView(),
-                             DisplayItem::kClipFrameToVisibleContentRect,
-                             GetFrameView().VisibleContentRect());
   PaintContents(context, global_paint_flags, document_dirty_rect);
 }
 
diff --git a/third_party/blink/renderer/core/paint/layer_clip_recorder.cc b/third_party/blink/renderer/core/paint/layer_clip_recorder.cc
index b407638..9d8f50a 100644
--- a/third_party/blink/renderer/core/paint/layer_clip_recorder.cc
+++ b/third_party/blink/renderer/core/paint/layer_clip_recorder.cc
@@ -5,49 +5,11 @@
 #include "third_party/blink/renderer/core/paint/layer_clip_recorder.h"
 
 #include "third_party/blink/renderer/core/layout/layout_view.h"
-#include "third_party/blink/renderer/core/paint/clip_rect.h"
 #include "third_party/blink/renderer/core/paint/paint_layer.h"
 #include "third_party/blink/renderer/platform/geometry/int_rect.h"
-#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
-#include "third_party/blink/renderer/platform/graphics/graphics_layer.h"
-#include "third_party/blink/renderer/platform/graphics/paint/clip_recorder.h"
-#include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h"
 
 namespace blink {
 
-LayerClipRecorder::LayerClipRecorder(GraphicsContext& graphics_context,
-                                     const PaintLayer& paint_layer,
-                                     DisplayItem::Type clip_type,
-                                     const ClipRect& clip_rect,
-                                     const PaintLayer* clip_root,
-                                     const LayoutPoint& fragment_offset,
-                                     PaintLayerFlags paint_flags,
-                                     const DisplayItemClient& client,
-                                     BorderRadiusClippingRule rule)
-    : graphics_context_(graphics_context),
-      client_(client),
-      clip_type_(clip_type) {
-  if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
-    return;
-  IntRect snapped_clip_rect = PixelSnappedIntRect(clip_rect.Rect());
-#if DCHECK_IS_ON
-  // In SPv175+ mode, clip rects are pre-snapped.
-  if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
-    DCHECK(FloatRect(snapped_clip_rect) == clip_rect.Rect());
-#endif
-  bool painting_masks =
-      (paint_flags & kPaintLayerPaintingChildClippingMaskPhase ||
-       paint_flags & kPaintLayerPaintingAncestorClippingMaskPhase);
-  Vector<FloatRoundedRect> rounded_rects;
-  if (clip_root && (clip_rect.HasRadius() || painting_masks)) {
-    CollectRoundedRectClips(paint_layer, clip_root, fragment_offset,
-                            painting_masks, rule, rounded_rects);
-  }
-
-  graphics_context_.GetPaintController().CreateAndAppend<ClipDisplayItem>(
-      client_, clip_type_, snapped_clip_rect, rounded_rects);
-}
-
 static bool InContainingBlockChain(const PaintLayer* start_layer,
                                    const PaintLayer* end_layer) {
   if (start_layer == end_layer)
@@ -119,11 +81,4 @@
   }
 }
 
-LayerClipRecorder::~LayerClipRecorder() {
-  if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
-    return;
-  graphics_context_.GetPaintController().EndItem<EndClipDisplayItem>(
-      client_, DisplayItem::ClipTypeToEndClipType(clip_type_));
-}
-
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/paint/layer_clip_recorder.h b/third_party/blink/renderer/core/paint/layer_clip_recorder.h
index 5da20f4..86990f7 100644
--- a/third_party/blink/renderer/core/paint/layer_clip_recorder.h
+++ b/third_party/blink/renderer/core/paint/layer_clip_recorder.h
@@ -6,53 +6,24 @@
 #define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_LAYER_CLIP_RECORDER_H_
 
 #include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/paint/paint_layer_painting_info.h"
-#include "third_party/blink/renderer/core/paint/paint_phase.h"
-#include "third_party/blink/renderer/platform/graphics/paint/clip_display_item.h"
-#include "third_party/blink/renderer/platform/graphics/paint/display_item.h"
 #include "third_party/blink/renderer/platform/wtf/vector.h"
 
 namespace blink {
 
-class ClipRect;
-class GraphicsContext;
+class FloatRoundedRect;
+class LayoutPoint;
+class PaintLayer;
+
+// TODO(wangxianzhu): Either rename the class, or merge the code into the only
+// caller of LayerClipRecorder::CollectRoundedRectClips().
 
 class CORE_EXPORT LayerClipRecorder {
-  USING_FAST_MALLOC(LayerClipRecorder);
-
  public:
   enum BorderRadiusClippingRule {
     kIncludeSelfForBorderRadius,
     kDoNotIncludeSelfForBorderRadius
   };
 
-  // Set rounded clip rectangles defined by border radii all the way from the
-  // PaintLayerPaintingInfo "root" layer down to the specified layer (or the
-  // parent of said layer, in case BorderRadiusClippingRule says to skip self).
-  // fragmentOffset is used for multicol, to specify the translation required to
-  // get from flow thread coordinates to visual coordinates for a certain
-  // column.
-  // FIXME: The BorderRadiusClippingRule parameter is really useless now. If we
-  // want to skip self,
-  // why not just supply the parent layer as the first parameter instead?
-  // FIXME: The ClipRect passed is in visual coordinates (not flow thread
-  // coordinates), but at the same time we pass a fragmentOffset, so that we can
-  // translate from flow thread coordinates to visual coordinates. This may look
-  // rather confusing/redundant, but it is needed for rounded border clipping.
-  // Would be nice to clean up this.
-  explicit LayerClipRecorder(
-      GraphicsContext&,
-      const PaintLayer&,
-      DisplayItem::Type,
-      const ClipRect&,
-      const PaintLayer* clip_root,
-      const LayoutPoint& fragment_offset,
-      PaintLayerFlags,
-      const DisplayItemClient&,
-      BorderRadiusClippingRule = kIncludeSelfForBorderRadius);
-
-  ~LayerClipRecorder();
-
   // Build a vector of the border radius clips that should be applied to
   // the given PaintLayer, walking up the paint layer tree to the clip_root.
   // The fragment_offset is an offset to apply to the clip to position it
@@ -70,11 +41,6 @@
       bool cross_composited_scrollers,
       BorderRadiusClippingRule,
       Vector<FloatRoundedRect>& rounded_rect_clips);
-
- private:
-  GraphicsContext& graphics_context_;
-  const DisplayItemClient& client_;
-  DisplayItem::Type clip_type_;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc b/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc
index ad1e701..0818a677 100644
--- a/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc
+++ b/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc
@@ -28,11 +28,9 @@
 #include "third_party/blink/renderer/core/paint/paint_info.h"
 #include "third_party/blink/renderer/core/paint/paint_layer.h"
 #include "third_party/blink/renderer/core/paint/paint_phase.h"
-#include "third_party/blink/renderer/core/paint/scroll_recorder.h"
 #include "third_party/blink/renderer/core/paint/scrollable_area_painter.h"
 #include "third_party/blink/renderer/platform/geometry/layout_rect_outsets.h"
 #include "third_party/blink/renderer/platform/graphics/graphics_context_state_saver.h"
-#include "third_party/blink/renderer/platform/graphics/paint/clip_recorder.h"
 #include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
 #include "third_party/blink/renderer/platform/scroll/scroll_types.h"
 
@@ -733,17 +731,7 @@
   if (box_fragment_.HasOverflowClip() &&
       box_fragment_.Style().Visibility() == EVisibility::kVisible &&
       ShouldPaintSelfBlockBackground(paint_info.phase)) {
-    const NGPhysicalBoxFragment& fragment = PhysicalFragment();
-    base::Optional<ClipRecorder> clip_recorder;
-    if (!fragment.Layer()->IsSelfPaintingLayer()) {
-      LayoutRect clip_rect =
-          LayoutRect(LayoutPoint(), fragment.Size().ToLayoutSize());
-      clip_rect.MoveBy(paint_offset);
-      clip_recorder.emplace(paint_info.context, box_fragment_,
-                            DisplayItem::kClipScrollbarsToBoxBounds,
-                            PixelSnappedIntRect(clip_rect));
-    }
-    ScrollableAreaPainter(*fragment.Layer()->GetScrollableArea())
+    ScrollableAreaPainter(*PhysicalFragment().Layer()->GetScrollableArea())
         .PaintOverflowControls(paint_info, RoundedIntPoint(paint_offset),
                                false /* painting_overlay_controls */);
   }
diff --git a/third_party/blink/renderer/core/paint/paint_invalidation_capable_scrollable_area.cc b/third_party/blink/renderer/core/paint/paint_invalidation_capable_scrollable_area.cc
deleted file mode 100644
index 70af5d0..0000000
--- a/third_party/blink/renderer/core/paint/paint_invalidation_capable_scrollable_area.cc
+++ /dev/null
@@ -1,287 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/paint/paint_invalidation_capable_scrollable_area.h"
-
-#include "third_party/blink/renderer/core/frame/settings.h"
-#include "third_party/blink/renderer/core/frame/use_counter.h"
-#include "third_party/blink/renderer/core/html/html_frame_owner_element.h"
-#include "third_party/blink/renderer/core/layout/layout_box.h"
-#include "third_party/blink/renderer/core/layout/layout_scrollbar.h"
-#include "third_party/blink/renderer/core/layout/layout_scrollbar_part.h"
-#include "third_party/blink/renderer/core/paint/find_paint_offset_and_visual_rect_needing_update.h"
-#include "third_party/blink/renderer/core/paint/object_paint_invalidator.h"
-#include "third_party/blink/renderer/core/paint/paint_invalidator.h"
-#include "third_party/blink/renderer/core/paint/paint_layer.h"
-#include "third_party/blink/renderer/platform/graphics/graphics_layer.h"
-
-namespace blink {
-
-void PaintInvalidationCapableScrollableArea::WillRemoveScrollbar(
-    Scrollbar& scrollbar,
-    ScrollbarOrientation orientation) {
-  if (!scrollbar.IsCustomScrollbar() &&
-      !(orientation == kHorizontalScrollbar ? LayerForHorizontalScrollbar()
-                                            : LayerForVerticalScrollbar())) {
-    ObjectPaintInvalidator(*GetLayoutBox())
-        .SlowSetPaintingLayerNeedsRepaintAndInvalidateDisplayItemClient(
-            scrollbar, PaintInvalidationReason::kScrollControl);
-  }
-
-  ScrollableArea::WillRemoveScrollbar(scrollbar, orientation);
-}
-
-static LayoutRect ScrollControlVisualRect(
-    const IntRect& scroll_control_rect,
-    const LayoutBox& box,
-    const PaintInvalidatorContext& context,
-    const LayoutRect& previous_visual_rect) {
-  LayoutRect visual_rect(scroll_control_rect);
-#if DCHECK_IS_ON()
-  FindVisualRectNeedingUpdateScope finder(box, context, previous_visual_rect,
-                                          visual_rect);
-#endif
-  if (!context.NeedsVisualRectUpdate(box))
-    return previous_visual_rect;
-
-  // No need to apply any paint offset. Scroll controls paint in a different
-  // transform space than their contained box (the scrollbarPaintOffset
-  // transform node).
-  if (!visual_rect.IsEmpty() &&
-      !RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
-    // PaintInvalidatorContext::mapLocalRectToPaintInvalidationBacking() treats
-    // the rect as in flipped block direction, but scrollbar controls don't
-    // flip for block direction, so flip here to undo the flip in the function.
-    box.FlipForWritingMode(visual_rect);
-    context.MapLocalRectToVisualRect(box, visual_rect);
-  }
-  return visual_rect;
-}
-
-// Returns true if the scroll control is invalidated.
-static bool InvalidatePaintOfScrollControlIfNeeded(
-    const LayoutRect& new_visual_rect,
-    const LayoutRect& previous_visual_rect,
-    bool needs_paint_invalidation,
-    LayoutBox& box,
-    const LayoutBoxModelObject& paint_invalidation_container) {
-  bool should_invalidate_new_rect = needs_paint_invalidation;
-  if (new_visual_rect != previous_visual_rect) {
-    if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
-      ObjectPaintInvalidator(box).InvalidatePaintUsingContainer(
-          paint_invalidation_container, previous_visual_rect,
-          PaintInvalidationReason::kScrollControl);
-    }
-    should_invalidate_new_rect = true;
-  } else if (previous_visual_rect.IsEmpty()) {
-    DCHECK(new_visual_rect.IsEmpty());
-    // Do not issue an empty invalidation.
-    should_invalidate_new_rect = false;
-  }
-
-  if (should_invalidate_new_rect) {
-    if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
-      ObjectPaintInvalidator(box).InvalidatePaintUsingContainer(
-          paint_invalidation_container, new_visual_rect,
-          PaintInvalidationReason::kScrollControl);
-    }
-    return true;
-  }
-  return false;
-}
-
-static LayoutRect InvalidatePaintOfScrollbarIfNeeded(
-    Scrollbar* scrollbar,
-    GraphicsLayer* graphics_layer,
-    bool& previously_was_overlay,
-    const LayoutRect& previous_visual_rect,
-    bool needs_paint_invalidation_arg,
-    LayoutBox& box,
-    const PaintInvalidatorContext& context) {
-  bool is_overlay = scrollbar && scrollbar->IsOverlayScrollbar();
-
-  LayoutRect new_visual_rect;
-  // Calculate visual rect of the scrollbar, except overlay composited
-  // scrollbars because we invalidate the graphics layer only.
-  if (scrollbar && !(graphics_layer && is_overlay)) {
-    new_visual_rect = ScrollControlVisualRect(scrollbar->FrameRect(), box,
-                                              context, previous_visual_rect);
-  }
-
-  bool needs_paint_invalidation = needs_paint_invalidation_arg;
-  if (needs_paint_invalidation && graphics_layer) {
-    // If the scrollbar needs paint invalidation but didn't change location/size
-    // or the scrollbar is an overlay scrollbar (visual rect is empty),
-    // invalidating the graphics layer is enough (which has been done in
-    // ScrollableArea::setScrollbarNeedsPaintInvalidation()).
-    // Otherwise invalidatePaintOfScrollControlIfNeeded() below will invalidate
-    // the old and new location of the scrollbar on the box's paint invalidation
-    // container to ensure newly expanded/shrunk areas of the box to be
-    // invalidated.
-    needs_paint_invalidation = false;
-    DCHECK(!graphics_layer->DrawsContent() ||
-           graphics_layer->GetPaintController().GetPaintArtifact().IsEmpty());
-  }
-
-  // Invalidate the box's display item client if the box's padding box size is
-  // affected by change of the non-overlay scrollbar width. We detect change of
-  // visual rect size instead of change of scrollbar width change, which may
-  // have some false-positives (e.g. the scrollbar changed length but not width)
-  // but won't invalidate more than expected because in the false-positive case
-  // the box must have changed size and have been invalidated.
-  const LayoutBoxModelObject& paint_invalidation_container =
-      *context.paint_invalidation_container;
-  LayoutSize new_scrollbar_used_space_in_box;
-  if (!is_overlay)
-    new_scrollbar_used_space_in_box = new_visual_rect.Size();
-  LayoutSize previous_scrollbar_used_space_in_box;
-  if (!previously_was_overlay)
-    previous_scrollbar_used_space_in_box = previous_visual_rect.Size();
-
-  // The IsEmpty() check avoids invalidaiton in cases when the visual rect
-  // changes from (0,0 0x0) to (0,0 0x100).
-  if (!(new_scrollbar_used_space_in_box.IsEmpty() &&
-        previous_scrollbar_used_space_in_box.IsEmpty()) &&
-      new_scrollbar_used_space_in_box != previous_scrollbar_used_space_in_box) {
-    context.painting_layer->SetNeedsRepaint();
-    ObjectPaintInvalidator(box).InvalidateDisplayItemClient(
-        box, PaintInvalidationReason::kGeometry);
-  }
-
-  bool invalidated = InvalidatePaintOfScrollControlIfNeeded(
-      new_visual_rect, previous_visual_rect, needs_paint_invalidation, box,
-      paint_invalidation_container);
-
-  previously_was_overlay = is_overlay;
-
-  if (!invalidated || !scrollbar || graphics_layer)
-    return new_visual_rect;
-
-  context.painting_layer->SetNeedsRepaint();
-  ObjectPaintInvalidator(box).InvalidateDisplayItemClient(
-      *scrollbar, PaintInvalidationReason::kScrollControl);
-  if (scrollbar->IsCustomScrollbar()) {
-    ToLayoutScrollbar(scrollbar)
-        ->InvalidateDisplayItemClientsOfScrollbarParts();
-  }
-
-  return new_visual_rect;
-}
-
-void PaintInvalidationCapableScrollableArea::
-    InvalidatePaintOfScrollControlsIfNeeded(
-        const PaintInvalidatorContext& context) {
-  LayoutBox& box = *GetLayoutBox();
-  SetHorizontalScrollbarVisualRect(InvalidatePaintOfScrollbarIfNeeded(
-      HorizontalScrollbar(), LayerForHorizontalScrollbar(),
-      horizontal_scrollbar_previously_was_overlay_,
-      horizontal_scrollbar_visual_rect_,
-      HorizontalScrollbarNeedsPaintInvalidation(), box, context));
-  SetVerticalScrollbarVisualRect(InvalidatePaintOfScrollbarIfNeeded(
-      VerticalScrollbar(), LayerForVerticalScrollbar(),
-      vertical_scrollbar_previously_was_overlay_,
-      vertical_scrollbar_visual_rect_,
-      VerticalScrollbarNeedsPaintInvalidation(), box, context));
-
-  LayoutRect scroll_corner_and_resizer_visual_rect =
-      ScrollControlVisualRect(ScrollCornerAndResizerRect(), box, context,
-                              scroll_corner_and_resizer_visual_rect_);
-  const LayoutBoxModelObject& paint_invalidation_container =
-      *context.paint_invalidation_container;
-  if (InvalidatePaintOfScrollControlIfNeeded(
-          scroll_corner_and_resizer_visual_rect,
-          scroll_corner_and_resizer_visual_rect_,
-          ScrollCornerNeedsPaintInvalidation(), box,
-          paint_invalidation_container)) {
-    SetScrollCornerAndResizerVisualRect(scroll_corner_and_resizer_visual_rect);
-    if (LayoutScrollbarPart* scroll_corner = ScrollCorner()) {
-      ObjectPaintInvalidator(*scroll_corner)
-          .InvalidateDisplayItemClientsIncludingNonCompositingDescendants(
-              PaintInvalidationReason::kScrollControl);
-    }
-    if (LayoutScrollbarPart* resizer = Resizer()) {
-      ObjectPaintInvalidator(*resizer)
-          .InvalidateDisplayItemClientsIncludingNonCompositingDescendants(
-              PaintInvalidationReason::kScrollControl);
-    }
-  }
-
-  ClearNeedsPaintInvalidationForScrollControls();
-}
-
-void PaintInvalidationCapableScrollableArea::ClearPreviousVisualRects() {
-  SetHorizontalScrollbarVisualRect(LayoutRect());
-  SetVerticalScrollbarVisualRect(LayoutRect());
-  SetScrollCornerAndResizerVisualRect(LayoutRect());
-}
-
-void PaintInvalidationCapableScrollableArea::SetHorizontalScrollbarVisualRect(
-    const LayoutRect& rect) {
-  horizontal_scrollbar_visual_rect_ = rect;
-  if (Scrollbar* scrollbar = HorizontalScrollbar())
-    scrollbar->SetVisualRect(rect);
-}
-
-void PaintInvalidationCapableScrollableArea::SetVerticalScrollbarVisualRect(
-    const LayoutRect& rect) {
-  vertical_scrollbar_visual_rect_ = rect;
-  if (Scrollbar* scrollbar = VerticalScrollbar())
-    scrollbar->SetVisualRect(rect);
-}
-
-void PaintInvalidationCapableScrollableArea::
-    SetScrollCornerAndResizerVisualRect(const LayoutRect& rect) {
-  scroll_corner_and_resizer_visual_rect_ = rect;
-  if (LayoutScrollbarPart* scroll_corner = ScrollCorner())
-    scroll_corner->GetMutableForPainting().FirstFragment().SetVisualRect(rect);
-  if (LayoutScrollbarPart* resizer = Resizer())
-    resizer->GetMutableForPainting().FirstFragment().SetVisualRect(rect);
-}
-
-void PaintInvalidationCapableScrollableArea::
-    ScrollControlWasSetNeedsPaintInvalidation() {
-  GetLayoutBox()->SetMayNeedPaintInvalidation();
-}
-
-void PaintInvalidationCapableScrollableArea::DidScrollWithScrollbar(
-    ScrollbarPart part,
-    ScrollbarOrientation orientation) {
-  WebFeature scrollbar_use_uma;
-  switch (part) {
-    case kBackButtonStartPart:
-    case kForwardButtonStartPart:
-    case kBackButtonEndPart:
-    case kForwardButtonEndPart:
-      scrollbar_use_uma =
-          (orientation == kVerticalScrollbar
-               ? WebFeature::kScrollbarUseVerticalScrollbarButton
-               : WebFeature::kScrollbarUseHorizontalScrollbarButton);
-      break;
-    case kThumbPart:
-      scrollbar_use_uma =
-          (orientation == kVerticalScrollbar
-               ? WebFeature::kScrollbarUseVerticalScrollbarThumb
-               : WebFeature::kScrollbarUseHorizontalScrollbarThumb);
-      break;
-    case kBackTrackPart:
-    case kForwardTrackPart:
-      scrollbar_use_uma =
-          (orientation == kVerticalScrollbar
-               ? WebFeature::kScrollbarUseVerticalScrollbarTrack
-               : WebFeature::kScrollbarUseHorizontalScrollbarTrack);
-      break;
-    default:
-      return;
-  }
-
-  UseCounter::Count(GetLayoutBox()->GetDocument(), scrollbar_use_uma);
-}
-
-CompositorElementId
-PaintInvalidationCapableScrollableArea::GetCompositorElementId() const {
-  return CompositorElementIdFromUniqueObjectId(
-      GetLayoutBox()->UniqueId(), CompositorElementIdNamespace::kScroll);
-}
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/core/paint/paint_invalidation_capable_scrollable_area.h b/third_party/blink/renderer/core/paint/paint_invalidation_capable_scrollable_area.h
deleted file mode 100644
index 19eaa0c44..0000000
--- a/third_party/blink/renderer/core/paint/paint_invalidation_capable_scrollable_area.h
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_PAINT_INVALIDATION_CAPABLE_SCROLLABLE_AREA_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_PAINT_INVALIDATION_CAPABLE_SCROLLABLE_AREA_H_
-
-#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/platform/geometry/layout_rect.h"
-#include "third_party/blink/renderer/platform/scroll/scrollable_area.h"
-
-namespace blink {
-
-class LayoutScrollbarPart;
-struct PaintInvalidatorContext;
-
-// Base class of LocalFrameView and PaintLayerScrollableArea to share paint
-// invalidation code.
-// TODO(wangxianzhu): Combine this into PaintLayerScrollableArea when
-// root-layer-scrolls launches.
-class CORE_EXPORT PaintInvalidationCapableScrollableArea
-    : public ScrollableArea {
- public:
-  PaintInvalidationCapableScrollableArea()
-      : horizontal_scrollbar_previously_was_overlay_(false),
-        vertical_scrollbar_previously_was_overlay_(false) {}
-
-  void WillRemoveScrollbar(Scrollbar&, ScrollbarOrientation) override;
-
-  void InvalidatePaintOfScrollControlsIfNeeded(const PaintInvalidatorContext&);
-
-  // Should be called when the previous visual rects are no longer valid.
-  void ClearPreviousVisualRects();
-
-  virtual IntRect ScrollCornerAndResizerRect() const {
-    return ScrollCornerRect();
-  }
-
-  void DidScrollWithScrollbar(ScrollbarPart, ScrollbarOrientation) override;
-  CompositorElementId GetCompositorElementId() const override;
-
- private:
-  virtual LayoutScrollbarPart* ScrollCorner() const = 0;
-  virtual LayoutScrollbarPart* Resizer() const = 0;
-
-  void ScrollControlWasSetNeedsPaintInvalidation() override;
-
-  void SetHorizontalScrollbarVisualRect(const LayoutRect&);
-  void SetVerticalScrollbarVisualRect(const LayoutRect&);
-  void SetScrollCornerAndResizerVisualRect(const LayoutRect&);
-
-  bool horizontal_scrollbar_previously_was_overlay_;
-  bool vertical_scrollbar_previously_was_overlay_;
-  LayoutRect horizontal_scrollbar_visual_rect_;
-  LayoutRect vertical_scrollbar_visual_rect_;
-  LayoutRect scroll_corner_and_resizer_visual_rect_;
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_PAINT_INVALIDATION_CAPABLE_SCROLLABLE_AREA_H_
diff --git a/third_party/blink/renderer/core/paint/paint_layer_painter.cc b/third_party/blink/renderer/core/paint/paint_layer_painter.cc
index 91a5a13..6712980 100644
--- a/third_party/blink/renderer/core/paint/paint_layer_painter.cc
+++ b/third_party/blink/renderer/core/paint/paint_layer_painter.cc
@@ -9,24 +9,19 @@
 #include "third_party/blink/renderer/core/layout/layout_view.h"
 #include "third_party/blink/renderer/core/paint/clip_path_clipper.h"
 #include "third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h"
-#include "third_party/blink/renderer/core/paint/filter_painter.h"
 #include "third_party/blink/renderer/core/paint/layer_clip_recorder.h"
 #include "third_party/blink/renderer/core/paint/object_paint_properties.h"
 #include "third_party/blink/renderer/core/paint/paint_info.h"
 #include "third_party/blink/renderer/core/paint/paint_layer.h"
-#include "third_party/blink/renderer/core/paint/scroll_recorder.h"
 #include "third_party/blink/renderer/core/paint/scrollable_area_painter.h"
-#include "third_party/blink/renderer/core/paint/transform_3d_recorder.h"
 #include "third_party/blink/renderer/platform/geometry/float_point_3d.h"
 #include "third_party/blink/renderer/platform/graphics/graphics_layer.h"
-#include "third_party/blink/renderer/platform/graphics/paint/compositing_recorder.h"
 #include "third_party/blink/renderer/platform/graphics/paint/display_item_cache_skipper.h"
 #include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
 #include "third_party/blink/renderer/platform/graphics/paint/geometry_mapper.h"
 #include "third_party/blink/renderer/platform/graphics/paint/scoped_display_item_fragment.h"
 #include "third_party/blink/renderer/platform/graphics/paint/scoped_paint_chunk_properties.h"
 #include "third_party/blink/renderer/platform/graphics/paint/subsequence_recorder.h"
-#include "third_party/blink/renderer/platform/graphics/paint/transform_3d_display_item.h"
 #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
 
 namespace blink {
@@ -450,35 +445,9 @@
                               visual_offset_from_root);
   }
 
-  base::Optional<CompositingRecorder> compositing_recorder;
-  // FIXME: this should be unified further into
-  // PaintLayer::paintsWithTransparency().
-  bool compositing_already_applied =
-      painting_info.root_layer == &paint_layer_ &&
-      is_painting_overflow_contents;
-  bool should_composite_for_blend_mode =
-      paint_layer_.StackingNode()->IsStackingContext() &&
-      paint_layer_.HasNonIsolatedDescendantWithBlendMode();
-  if (!compositing_already_applied &&
-      (should_composite_for_blend_mode ||
-       paint_layer_.PaintsWithTransparency(
-           painting_info.GetGlobalPaintFlags()))) {
-    FloatRect compositing_bounds = EnclosingIntRect(paint_layer_.PaintingExtent(
-        painting_info.root_layer, painting_info.sub_pixel_accumulation,
-        painting_info.GetGlobalPaintFlags()));
-    compositing_recorder.emplace(
-        context, paint_layer_.GetLayoutObject(),
-        WebCoreCompositeToSkiaComposite(
-            kCompositeSourceOver,
-            paint_layer_.GetLayoutObject().Style()->GetBlendMode()),
-        paint_layer_.GetLayoutObject().Opacity(), &compositing_bounds);
-  }
-
   PaintLayerPaintingInfo local_painting_info(painting_info);
   local_painting_info.sub_pixel_accumulation = subpixel_accumulation;
 
-  sk_sp<PaintFilter> image_filter = FilterPainter::GetImageFilter(paint_layer_);
-
   bool should_paint_content =
       paint_layer_.HasVisibleContent() &&
       // Content under a LayoutSVGHiddenContainer is auxiliary resources for
@@ -538,31 +507,6 @@
           &offset_from_root, local_painting_info.sub_pixel_accumulation);
       RepeatFixedPositionObjectInPages(single_fragment[0], painting_info,
                                        layer_fragments);
-    } else if (image_filter && !paint_layer_.EnclosingPaginationLayer()) {
-      // Clipping in the presence of filters needs to happen in two phases.
-      // It proceeds like this:
-      // 1. Apply overflow clip to normal-flow contents.
-      // 2. Paint layer contents into the filter.
-      // 3. Apply all inherited clips (including dirty rect) plus CSS clip
-      //    of the current layer to the filter output.
-      //
-      // It is critical to avoid clipping to the dirty rect or any clips
-      // above the filter before applying the filter, because content which
-      // appears to be clipped may affect visual output if the filter moves
-      // pixels.
-      //
-      // #1 is applied in the lines below.  #3 is applied in FilterPainter,
-      // and computed just before construction of the FilterPainter.
-      LayoutRect foreground_clip(LayoutRect::InfiniteIntRect());
-      if (paint_layer_.GetLayoutObject().IsBox()) {
-        const LayoutBox& box = ToLayoutBox(paint_layer_.GetLayoutObject());
-        if (box.ShouldClipOverflow())
-          foreground_clip = box.OverflowClipRect(offset_from_root);
-      }
-      PaintLayerFragment& fragment = layer_fragments.emplace_back();
-      fragment.SetRects(
-          LayoutRect(offset_from_root, LayoutSize(paint_layer_.Size())),
-          LayoutRect(LayoutRect::InfiniteIntRect()), foreground_clip);
     } else {
       paint_layer_for_fragments->CollectFragments(
           layer_fragments, local_painting_info.root_layer,
@@ -604,24 +548,6 @@
     size_t display_item_list_size_before_painting =
         context.GetPaintController().NewDisplayItemList().size();
 
-    base::Optional<FilterPainter> filter_painter;
-    if (image_filter) {
-      DCHECK(!RuntimeEnabledFeatures::SlimmingPaintV175Enabled());
-      // Compute clips outside the filter (#3, see above for discussion).
-      PaintLayerFragments filter_fragments;
-      paint_layer_.AppendSingleFragmentIgnoringPagination(
-          filter_fragments, local_painting_info.root_layer,
-          &local_painting_info.paint_dirty_rect,
-          kIgnorePlatformOverlayScrollbarSize, respect_overflow_clip,
-          &offset_from_root, local_painting_info.sub_pixel_accumulation);
-
-      filter_painter.emplace(paint_layer_, context, offset_from_root,
-                             filter_fragments.IsEmpty()
-                                 ? ClipRect()
-                                 : filter_fragments[0].background_rect,
-                             local_painting_info, paint_flags);
-    }
-
     bool is_painting_root_layer = (&paint_layer_) == painting_info.root_layer;
     bool should_paint_background =
         should_paint_content && !selection_only &&
@@ -774,33 +700,6 @@
   return result;
 }
 
-bool PaintLayerPainter::NeedsToClip(
-    const PaintLayerPaintingInfo& local_painting_info,
-    const ClipRect& clip_rect,
-    const PaintLayerFlags& paint_flags,
-    const LayoutBoxModelObject& layout_object) {
-  // Other clipping will be applied by property nodes directly for SPv175+.
-  if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
-    return false;
-
-  // Always clip if painting an ancestor clipping mask layer.
-  if (paint_flags & kPaintLayerPaintingAncestorClippingMaskPhase)
-    return true;
-
-  // Embedded objects have a clip rect when border radius is present
-  // because we need it for the border radius mask with composited
-  // chidren. However, we do not want to apply the clip when painting
-  // the embedded content itself. Doing so would clip out the
-  // border because LayoutEmbeddedObject does not obey the painting phases
-  // of a normal box object.
-  if (layout_object.IsLayoutEmbeddedContent() &&
-      layout_object.GetCompositingState() == kPaintsIntoOwnBacking)
-    return paint_flags & kPaintLayerPaintingChildClippingMaskPhase;
-
-  return clip_rect.Rect() != local_painting_info.paint_dirty_rect ||
-         clip_rect.HasRadius();
-}
-
 bool PaintLayerPainter::AtLeastOneFragmentIntersectsDamageRect(
     PaintLayerFragments& fragments,
     const PaintLayerPaintingInfo& local_painting_info,
@@ -940,18 +839,6 @@
 
   ForAllFragments(
       context, layer_fragments, [&](const PaintLayerFragment& fragment) {
-        base::Optional<LayerClipRecorder> clip_recorder;
-        if (parent_layer &&
-            !RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
-          if (NeedsToClip(painting_info, fragment.background_rect, paint_flags,
-                          paint_layer_.GetLayoutObject())) {
-            clip_recorder.emplace(
-                context, *parent_layer, DisplayItem::kClipLayerParent,
-                fragment.background_rect, painting_info.root_layer,
-                fragment.pagination_offset, paint_flags,
-                paint_layer_.GetLayoutObject());
-          }
-        }
         if (paint_layer_.PaintsWithTransform(
                 painting_info.GetGlobalPaintFlags())) {
           if (PaintFragmentByApplyingTransform(context, painting_info,
@@ -991,14 +878,6 @@
     new_sub_pixel_accumulation += delta - rounded_delta;
   // Otherwise discard the sub-pixel remainder because paint offset can't be
   // transformed by a non-translation transform.
-
-  // TODO(jbroman): Put the real transform origin here, instead of using a
-  // matrix with the origin baked in.
-  FloatPoint3D transform_origin;
-  Transform3DRecorder transform3d_recorder(
-      context, paint_layer_.GetLayoutObject(),
-      DisplayItem::kTransform3DElementTransform, transform, transform_origin);
-
   return PaintSingleFragment(context, painting_info, paint_flags, fragment,
                              new_sub_pixel_accumulation);
 }
@@ -1112,26 +991,6 @@
         // We need to apply the same clips and transforms that
         // paintFragmentWithPhase would have.
         LayoutRect cull_rect = fragment.background_rect.Rect();
-
-        base::Optional<LayerClipRecorder> clip_recorder;
-        if (NeedsToClip(painting_info, fragment.background_rect, paint_flags,
-                        paint_layer_.GetLayoutObject())) {
-          clip_recorder.emplace(
-              context, paint_layer_, DisplayItem::kClipLayerOverflowControls,
-              fragment.background_rect, painting_info.root_layer,
-              fragment.pagination_offset, paint_flags,
-              paint_layer_.GetLayoutObject());
-        }
-
-        base::Optional<ScrollRecorder> scroll_recorder;
-        if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled() &&
-            !painting_info.scroll_offset_accumulation.IsZero()) {
-          cull_rect.Move(painting_info.scroll_offset_accumulation);
-          scroll_recorder.emplace(context, paint_layer_.GetLayoutObject(),
-                                  DisplayItem::kScrollOverflowControls,
-                                  painting_info.scroll_offset_accumulation);
-        }
-
         PaintInfo paint_info(
             context, PixelSnappedIntRect(cull_rect),
             PaintPhase::kSelfBlockBackgroundOnly,
@@ -1155,8 +1014,7 @@
     GraphicsContext& context,
     const ClipRect& clip_rect,
     const PaintLayerPaintingInfo& painting_info,
-    PaintLayerFlags paint_flags,
-    ClipState clip_state) {
+    PaintLayerFlags paint_flags) {
   DCHECK(paint_layer_.IsSelfPaintingLayer());
 
   base::Optional<ScopedPaintChunkProperties> fragment_paint_chunk_properties;
@@ -1180,81 +1038,17 @@
         DisplayItem::PaintPhaseToDrawingType(phase));
   }
 
-  DisplayItemClient* client = &paint_layer_.GetLayoutObject();
-  base::Optional<LayerClipRecorder> clip_recorder;
-  if (clip_state != kHasClipped &&
-      NeedsToClip(painting_info, clip_rect, paint_flags,
-                  paint_layer_.GetLayoutObject())) {
-    DisplayItem::Type clip_type =
-        DisplayItem::PaintPhaseToClipLayerFragmentType(phase);
-    LayerClipRecorder::BorderRadiusClippingRule clipping_rule;
-    switch (phase) {
-      case PaintPhase::kSelfBlockBackgroundOnly:  // Background painting will
-                                                  // handle clipping to self.
-      case PaintPhase::kSelfOutlineOnly:
-      case PaintPhase::kMask:  // Mask painting will handle clipping to self.
-        clipping_rule = LayerClipRecorder::kDoNotIncludeSelfForBorderRadius;
-        break;
-      case PaintPhase::kClippingMask:
-        if (paint_flags & kPaintLayerPaintingAncestorClippingMaskPhase) {
-          // The ancestor is the thing that needs to clip, so do not include
-          // this layer's clips.
-          clipping_rule = LayerClipRecorder::kDoNotIncludeSelfForBorderRadius;
-          // The ancestor clipping mask may have a larger visual rect than
-          // paint_layer_, since it includes ancestor clips.
-          client = paint_layer_.GetCompositedLayerMapping()
-                       ->AncestorClippingMaskLayer();
-          break;
-        }
-        FALLTHROUGH;
-      default:
-        clipping_rule = LayerClipRecorder::kIncludeSelfForBorderRadius;
-        break;
-    }
-    clip_recorder.emplace(context, paint_layer_, clip_type, clip_rect,
-                          painting_info.root_layer, fragment.pagination_offset,
-                          paint_flags, *client, clipping_rule);
-  }
-
-  // If we are painting a mask for any reason and we have already processed the
-  // clips, there is no need to go through the remaining painting pipeline.
-  // We know that the mask just needs the area bounded by the clip rects to be
-  // filled with black.
-  if (clip_recorder && phase == PaintPhase::kClippingMask) {
-    DCHECK(!RuntimeEnabledFeatures::SlimmingPaintV175Enabled());
-    FillMaskingFragment(context, clip_rect, *client);
-    return;
-  }
-
   LayoutRect new_cull_rect(clip_rect.Rect());
-  base::Optional<ScrollRecorder> scroll_recorder;
   LayoutPoint paint_offset = -paint_layer_.LayoutBoxLocation();
-  if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
-    paint_offset += fragment.fragment_data->PaintOffset();
-    // For SPv175+, we paint in the containing transform node's space. Now
-    // |new_cull_rect| is in the pixel-snapped border box space of
-    // |painting_info.root_layer|. Adjust it to the correct space.
-    // |paint_offset| is already in the correct space.
-    new_cull_rect.MoveBy(
-        RoundedIntPoint(painting_info.root_layer->GetLayoutObject()
-                            .FirstFragment()
-                            .PaintOffset()));
-  } else {
-    paint_offset += ToSize(fragment.layer_bounds.Location());
-    if (!painting_info.scroll_offset_accumulation.IsZero()) {
-      // As a descendant of the root layer, m_paintLayer's painting is not
-      // controlled by the ScrollRecorders created by BlockPainter of the
-      // ancestor layers up to the root layer, so we need to issue
-      // ScrollRecorder for this layer seperately, with the scroll offset
-      // accumulated from the root layer to the parent of this layer, to get the
-      // same result as ScrollRecorder in BlockPainter.
-      paint_offset += painting_info.scroll_offset_accumulation;
-
-      new_cull_rect.Move(painting_info.scroll_offset_accumulation);
-      scroll_recorder.emplace(context, paint_layer_.GetLayoutObject(), phase,
-                              painting_info.scroll_offset_accumulation);
-    }
-  }
+  paint_offset += fragment.fragment_data->PaintOffset();
+  // We paint in the containing transform node's space. Now |new_cull_rect| is
+  // in the pixel-snapped border box space of |painting_info.root_layer|.
+  // Adjust it to the correct space. |paint_offset| is already in the correct
+  // space.
+  new_cull_rect.MoveBy(
+      RoundedIntPoint(painting_info.root_layer->GetLayoutObject()
+                          .FirstFragment()
+                          .PaintOffset()));
   PaintInfo paint_info(context, PixelSnappedIntRect(new_cull_rect), phase,
                        painting_info.GetGlobalPaintFlags(), paint_flags,
                        &painting_info.root_layer->GetLayoutObject(),
@@ -1279,8 +1073,7 @@
       context, layer_fragments, [&](const PaintLayerFragment& fragment) {
         PaintFragmentWithPhase(PaintPhase::kSelfBlockBackgroundOnly, fragment,
                                context, fragment.background_rect,
-                               local_painting_info, paint_flags,
-                               kHasNotClipped);
+                               local_painting_info, paint_flags);
       });
 }
 
@@ -1291,26 +1084,10 @@
     bool selection_only,
     bool force_paint_chunks,
     PaintLayerFlags paint_flags) {
-  // Optimize clipping for the single fragment case.
-  bool should_clip = layer_fragments.size() == 1 &&
-                     !layer_fragments[0].foreground_rect.IsEmpty();
-  ClipState clip_state = kHasNotClipped;
-  base::Optional<LayerClipRecorder> clip_recorder;
-  if (should_clip &&
-      NeedsToClip(local_painting_info, layer_fragments[0].foreground_rect,
-                  paint_flags, paint_layer_.GetLayoutObject())) {
-    clip_recorder.emplace(
-        context, paint_layer_, DisplayItem::kClipLayerForeground,
-        layer_fragments[0].foreground_rect, local_painting_info.root_layer,
-        layer_fragments[0].pagination_offset, paint_flags,
-        paint_layer_.GetLayoutObject());
-    clip_state = kHasClipped;
-  }
-
   if (selection_only) {
-    PaintForegroundForFragmentsWithPhase(
-        PaintPhase::kSelection, layer_fragments, context, local_painting_info,
-        paint_flags, clip_state);
+    PaintForegroundForFragmentsWithPhase(PaintPhase::kSelection,
+                                         layer_fragments, context,
+                                         local_painting_info, paint_flags);
   } else {
     if (RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled() ||
         paint_layer_.NeedsPaintPhaseDescendantBlockBackgrounds()) {
@@ -1322,7 +1099,7 @@
           context.GetPaintController().NewDisplayItemList().size();
       PaintForegroundForFragmentsWithPhase(
           PaintPhase::kDescendantBlockBackgroundsOnly, layer_fragments, context,
-          local_painting_info, paint_flags, clip_state);
+          local_painting_info, paint_flags);
       // Don't set the empty flag if we are not painting the whole background.
       if (!(paint_flags & kPaintLayerPaintingSkipRootBackground)) {
         bool phase_is_empty =
@@ -1345,7 +1122,7 @@
           context.GetPaintController().NewDisplayItemList().size();
       PaintForegroundForFragmentsWithPhase(PaintPhase::kFloat, layer_fragments,
                                            context, local_painting_info,
-                                           paint_flags, clip_state);
+                                           paint_flags);
       bool phase_is_empty =
           context.GetPaintController().NewDisplayItemList().size() ==
           size_before;
@@ -1358,17 +1135,17 @@
           paint_layer_, DisplayItem::kLayerChunkForeground);
     }
 
-    PaintForegroundForFragmentsWithPhase(
-        PaintPhase::kForeground, layer_fragments, context, local_painting_info,
-        paint_flags, clip_state);
+    PaintForegroundForFragmentsWithPhase(PaintPhase::kForeground,
+                                         layer_fragments, context,
+                                         local_painting_info, paint_flags);
 
     if (RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled() ||
         paint_layer_.NeedsPaintPhaseDescendantOutlines()) {
       size_t size_before =
           context.GetPaintController().NewDisplayItemList().size();
-      PaintForegroundForFragmentsWithPhase(
-          PaintPhase::kDescendantOutlinesOnly, layer_fragments, context,
-          local_painting_info, paint_flags, clip_state);
+      PaintForegroundForFragmentsWithPhase(PaintPhase::kDescendantOutlinesOnly,
+                                           layer_fragments, context,
+                                           local_painting_info, paint_flags);
       bool phase_is_empty =
           context.GetPaintController().NewDisplayItemList().size() ==
           size_before;
@@ -1384,14 +1161,13 @@
     const PaintLayerFragments& layer_fragments,
     GraphicsContext& context,
     const PaintLayerPaintingInfo& local_painting_info,
-    PaintLayerFlags paint_flags,
-    ClipState clip_state) {
+    PaintLayerFlags paint_flags) {
   ForAllFragments(
       context, layer_fragments, [&](const PaintLayerFragment& fragment) {
         if (!fragment.foreground_rect.IsEmpty()) {
           PaintFragmentWithPhase(phase, fragment, context,
                                  fragment.foreground_rect, local_painting_info,
-                                 paint_flags, clip_state);
+                                 paint_flags);
         }
       });
 }
@@ -1406,8 +1182,7 @@
         if (!fragment.background_rect.IsEmpty()) {
           PaintFragmentWithPhase(PaintPhase::kSelfOutlineOnly, fragment,
                                  context, fragment.background_rect,
-                                 local_painting_info, paint_flags,
-                                 kHasNotClipped);
+                                 local_painting_info, paint_flags);
         }
       });
 }
@@ -1417,12 +1192,12 @@
     GraphicsContext& context,
     const PaintLayerPaintingInfo& local_painting_info,
     PaintLayerFlags paint_flags) {
-  ForAllFragments(
-      context, layer_fragments, [&](const PaintLayerFragment& fragment) {
-        PaintFragmentWithPhase(PaintPhase::kMask, fragment, context,
-                               fragment.background_rect, local_painting_info,
-                               paint_flags, kHasNotClipped);
-      });
+  ForAllFragments(context, layer_fragments,
+                  [&](const PaintLayerFragment& fragment) {
+                    PaintFragmentWithPhase(PaintPhase::kMask, fragment, context,
+                                           fragment.background_rect,
+                                           local_painting_info, paint_flags);
+                  });
 }
 
 void PaintLayerPainter::PaintAncestorClippingMask(
@@ -1430,26 +1205,19 @@
     GraphicsContext& context,
     const PaintLayerPaintingInfo& local_painting_info,
     PaintLayerFlags paint_flags) {
-  if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
-    const DisplayItemClient& client =
-        *paint_layer_.GetCompositedLayerMapping()->AncestorClippingMaskLayer();
-    const auto& layer_fragment = paint_layer_.GetLayoutObject().FirstFragment();
-    auto state = layer_fragment.PreEffectProperties();
-    // This is a hack to incorporate mask-based clip-path.
-    // See CompositingLayerPropertyUpdater.cpp about AncestorClippingMaskLayer.
-    state.SetEffect(layer_fragment.PreFilter());
-    ScopedPaintChunkProperties properties(
-        context.GetPaintController(), state, client,
-        DisplayItem::PaintPhaseToDrawingType(PaintPhase::kClippingMask));
-    ClipRect mask_rect = fragment.background_rect;
-    mask_rect.MoveBy(layer_fragment.PaintOffset());
-    FillMaskingFragment(context, mask_rect, client);
-    return;
-  }
-
-  PaintFragmentWithPhase(PaintPhase::kClippingMask, fragment, context,
-                         fragment.background_rect, local_painting_info,
-                         paint_flags, kHasNotClipped);
+  const DisplayItemClient& client =
+      *paint_layer_.GetCompositedLayerMapping()->AncestorClippingMaskLayer();
+  const auto& layer_fragment = paint_layer_.GetLayoutObject().FirstFragment();
+  auto state = layer_fragment.PreEffectProperties();
+  // This is a hack to incorporate mask-based clip-path.
+  // See CompositingLayerPropertyUpdater.cpp about AncestorClippingMaskLayer.
+  state.SetEffect(layer_fragment.PreFilter());
+  ScopedPaintChunkProperties properties(
+      context.GetPaintController(), state, client,
+      DisplayItem::PaintPhaseToDrawingType(PaintPhase::kClippingMask));
+  ClipRect mask_rect = fragment.background_rect;
+  mask_rect.MoveBy(layer_fragment.PaintOffset());
+  FillMaskingFragment(context, mask_rect, client);
 }
 
 void PaintLayerPainter::PaintChildClippingMaskForFragments(
@@ -1457,35 +1225,25 @@
     GraphicsContext& context,
     const PaintLayerPaintingInfo& local_painting_info,
     PaintLayerFlags paint_flags) {
-  if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
-    const DisplayItemClient& client =
-        *paint_layer_.GetCompositedLayerMapping()->ChildClippingMaskLayer();
-    ForAllFragments(
-        context, layer_fragments, [&](const PaintLayerFragment& fragment) {
-          // Use the LocalBorderboxProperties as a starting point to ensure that
-          // we don't include the scroll offset when painting the mask layer.
-          auto state = fragment.fragment_data->LocalBorderBoxProperties();
-          // This is a hack to incorporate mask-based clip-path.
-          // See CompositingLayerPropertyUpdater.cpp about
-          // ChildClippingMaskLayer.
-          state.SetEffect(fragment.fragment_data->PreFilter());
-          // Update the clip to be the ContentsProperties clip, since it
-          // includes the InnerBorderRadiusClip.
-          state.SetClip(fragment.fragment_data->ContentsProperties().Clip());
-          ScopedPaintChunkProperties fragment_paint_chunk_properties(
-              context.GetPaintController(), state, client,
-              DisplayItem::PaintPhaseToDrawingType(PaintPhase::kClippingMask));
-          ClipRect mask_rect = fragment.background_rect;
-          FillMaskingFragment(context, mask_rect, client);
-        });
-    return;
-  }
-
+  const DisplayItemClient& client =
+      *paint_layer_.GetCompositedLayerMapping()->ChildClippingMaskLayer();
   ForAllFragments(
       context, layer_fragments, [&](const PaintLayerFragment& fragment) {
-        PaintFragmentWithPhase(PaintPhase::kClippingMask, fragment, context,
-                               fragment.foreground_rect, local_painting_info,
-                               paint_flags, kHasNotClipped);
+        // Use the LocalBorderboxProperties as a starting point to ensure that
+        // we don't include the scroll offset when painting the mask layer.
+        auto state = fragment.fragment_data->LocalBorderBoxProperties();
+        // This is a hack to incorporate mask-based clip-path.
+        // See CompositingLayerPropertyUpdater.cpp about
+        // ChildClippingMaskLayer.
+        state.SetEffect(fragment.fragment_data->PreFilter());
+        // Update the clip to be the ContentsProperties clip, since it
+        // includes the InnerBorderRadiusClip.
+        state.SetClip(fragment.fragment_data->ContentsProperties().Clip());
+        ScopedPaintChunkProperties fragment_paint_chunk_properties(
+            context.GetPaintController(), state, client,
+            DisplayItem::PaintPhaseToDrawingType(PaintPhase::kClippingMask));
+        ClipRect mask_rect = fragment.background_rect;
+        FillMaskingFragment(context, mask_rect, client);
       });
 }
 
diff --git a/third_party/blink/renderer/core/paint/paint_layer_painter.h b/third_party/blink/renderer/core/paint/paint_layer_painter.h
index fe3cd61..c12cf14 100644
--- a/third_party/blink/renderer/core/paint/paint_layer_painter.h
+++ b/third_party/blink/renderer/core/paint/paint_layer_painter.h
@@ -18,7 +18,6 @@
 class DisplayItemClient;
 class PaintLayer;
 class GraphicsContext;
-class LayoutBoxModelObject;
 class LayoutPoint;
 
 // This class is responsible for painting self-painting PaintLayer.
@@ -63,8 +62,6 @@
  private:
   friend class PaintLayerPainterTest;
 
-  enum ClipState { kHasNotClipped, kHasClipped };
-
   bool ShouldAdjustPaintingRoot(const PaintLayerPaintingInfo& painting_info,
                                 PaintLayerFlags paint_flags);
 
@@ -110,8 +107,7 @@
                               GraphicsContext&,
                               const ClipRect&,
                               const PaintLayerPaintingInfo&,
-                              PaintLayerFlags,
-                              ClipState);
+                              PaintLayerFlags);
   void PaintBackgroundForFragments(
       const PaintLayerFragments&,
       GraphicsContext&,
@@ -127,8 +123,7 @@
                                             const PaintLayerFragments&,
                                             GraphicsContext&,
                                             const PaintLayerPaintingInfo&,
-                                            PaintLayerFlags,
-                                            ClipState);
+                                            PaintLayerFlags);
   void PaintSelfOutlineForFragments(const PaintLayerFragments&,
                                     GraphicsContext&,
                                     const PaintLayerPaintingInfo&,
@@ -156,11 +151,6 @@
 
   void PaintEmptyContentForFilters(GraphicsContext&);
 
-  static bool NeedsToClip(const PaintLayerPaintingInfo& local_painting_info,
-                          const ClipRect&,
-                          const PaintLayerFlags&,
-                          const LayoutBoxModelObject&);
-
   void AdjustForPaintProperties(PaintLayerPaintingInfo&, PaintLayerFlags&);
 
   PaintLayer& paint_layer_;
diff --git a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc
index 0a75d2e6..1484abd 100644
--- a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc
+++ b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc
@@ -85,6 +85,8 @@
 #include "third_party/blink/renderer/core/page/scrolling/top_document_root_scroller_controller.h"
 #include "third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h"
 #include "third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.h"
+#include "third_party/blink/renderer/core/paint/find_paint_offset_and_visual_rect_needing_update.h"
+#include "third_party/blink/renderer/core/paint/paint_invalidator.h"
 #include "third_party/blink/renderer/core/paint/paint_layer_fragment.h"
 #include "third_party/blink/renderer/platform/graphics/graphics_layer.h"
 #include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
@@ -139,7 +141,9 @@
       scroll_corner_(nullptr),
       resizer_(nullptr),
       scroll_anchor_(this),
-      non_composited_main_thread_scrolling_reasons_(0) {
+      non_composited_main_thread_scrolling_reasons_(0),
+      horizontal_scrollbar_previously_was_overlay_(false),
+      vertical_scrollbar_previously_was_overlay_(false) {
   Node* node = GetLayoutBox()->GetNode();
   if (node && node->IsElementNode()) {
     // We save and restore only the scrollOffset as the other scroll values are
@@ -2334,20 +2338,6 @@
     tickmarks = ToLayoutView(GetLayoutBox())->GetTickmarks();
 }
 
-PaintLayerScrollableArea*
-PaintLayerScrollableArea::ScrollbarManager::ScrollableArea() {
-  return ToPaintLayerScrollableArea(scrollable_area_.Get());
-}
-
-void PaintLayerScrollableArea::ScrollbarManager::DestroyDetachedScrollbars() {
-  DCHECK(!h_bar_is_attached_ || h_bar_);
-  DCHECK(!v_bar_is_attached_ || v_bar_);
-  if (h_bar_ && !h_bar_is_attached_)
-    DestroyScrollbar(kHorizontalScrollbar);
-  if (v_bar_ && !v_bar_is_attached_)
-    DestroyScrollbar(kVerticalScrollbar);
-}
-
 void PaintLayerScrollableArea::ScrollbarManager::SetHasHorizontalScrollbar(
     bool has_scrollbar) {
   if (has_scrollbar) {
@@ -2444,6 +2434,28 @@
   scrollbar = nullptr;
 }
 
+void PaintLayerScrollableArea::ScrollbarManager::DestroyDetachedScrollbars() {
+  DCHECK(!h_bar_is_attached_ || h_bar_);
+  DCHECK(!v_bar_is_attached_ || v_bar_);
+  if (h_bar_ && !h_bar_is_attached_)
+    DestroyScrollbar(kHorizontalScrollbar);
+  if (v_bar_ && !v_bar_is_attached_)
+    DestroyScrollbar(kVerticalScrollbar);
+}
+
+void PaintLayerScrollableArea::ScrollbarManager::Dispose() {
+  h_bar_is_attached_ = v_bar_is_attached_ = 0;
+  DestroyScrollbar(kHorizontalScrollbar);
+  DestroyScrollbar(kVerticalScrollbar);
+}
+
+void PaintLayerScrollableArea::ScrollbarManager::Trace(
+    blink::Visitor* visitor) {
+  visitor->Trace(scrollable_area_);
+  visitor->Trace(h_bar_);
+  visitor->Trace(v_bar_);
+}
+
 uint64_t PaintLayerScrollableArea::Id() const {
   return DOMNodeIds::IdForNode(GetLayoutBox()->GetNode());
 }
@@ -2568,4 +2580,267 @@
   return page->GetScrollbarTheme();
 }
 
+void PaintLayerScrollableArea::WillRemoveScrollbar(
+    Scrollbar& scrollbar,
+    ScrollbarOrientation orientation) {
+  if (!scrollbar.IsCustomScrollbar() &&
+      !(orientation == kHorizontalScrollbar ? LayerForHorizontalScrollbar()
+                                            : LayerForVerticalScrollbar())) {
+    ObjectPaintInvalidator(*GetLayoutBox())
+        .SlowSetPaintingLayerNeedsRepaintAndInvalidateDisplayItemClient(
+            scrollbar, PaintInvalidationReason::kScrollControl);
+  }
+
+  ScrollableArea::WillRemoveScrollbar(scrollbar, orientation);
+}
+
+static LayoutRect ScrollControlVisualRect(
+    const IntRect& scroll_control_rect,
+    const LayoutBox& box,
+    const PaintInvalidatorContext& context,
+    const LayoutRect& previous_visual_rect) {
+  LayoutRect visual_rect(scroll_control_rect);
+#if DCHECK_IS_ON()
+  FindVisualRectNeedingUpdateScope finder(box, context, previous_visual_rect,
+                                          visual_rect);
+#endif
+  if (!context.NeedsVisualRectUpdate(box))
+    return previous_visual_rect;
+
+  // No need to apply any paint offset. Scroll controls paint in a different
+  // transform space than their contained box (the scrollbarPaintOffset
+  // transform node).
+  if (!visual_rect.IsEmpty() &&
+      !RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
+    // PaintInvalidatorContext::mapLocalRectToPaintInvalidationBacking() treats
+    // the rect as in flipped block direction, but scrollbar controls don't
+    // flip for block direction, so flip here to undo the flip in the function.
+    box.FlipForWritingMode(visual_rect);
+    context.MapLocalRectToVisualRect(box, visual_rect);
+  }
+  return visual_rect;
+}
+
+// Returns true if the scroll control is invalidated.
+static bool InvalidatePaintOfScrollControlIfNeeded(
+    const LayoutRect& new_visual_rect,
+    const LayoutRect& previous_visual_rect,
+    bool needs_paint_invalidation,
+    LayoutBox& box,
+    const LayoutBoxModelObject& paint_invalidation_container) {
+  bool should_invalidate_new_rect = needs_paint_invalidation;
+  if (new_visual_rect != previous_visual_rect) {
+    if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
+      ObjectPaintInvalidator(box).InvalidatePaintUsingContainer(
+          paint_invalidation_container, previous_visual_rect,
+          PaintInvalidationReason::kScrollControl);
+    }
+    should_invalidate_new_rect = true;
+  } else if (previous_visual_rect.IsEmpty()) {
+    DCHECK(new_visual_rect.IsEmpty());
+    // Do not issue an empty invalidation.
+    should_invalidate_new_rect = false;
+  }
+
+  if (should_invalidate_new_rect) {
+    if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
+      ObjectPaintInvalidator(box).InvalidatePaintUsingContainer(
+          paint_invalidation_container, new_visual_rect,
+          PaintInvalidationReason::kScrollControl);
+    }
+    return true;
+  }
+  return false;
+}
+
+static LayoutRect InvalidatePaintOfScrollbarIfNeeded(
+    Scrollbar* scrollbar,
+    GraphicsLayer* graphics_layer,
+    bool& previously_was_overlay,
+    const LayoutRect& previous_visual_rect,
+    bool needs_paint_invalidation_arg,
+    LayoutBox& box,
+    const PaintInvalidatorContext& context) {
+  bool is_overlay = scrollbar && scrollbar->IsOverlayScrollbar();
+
+  LayoutRect new_visual_rect;
+  // Calculate visual rect of the scrollbar, except overlay composited
+  // scrollbars because we invalidate the graphics layer only.
+  if (scrollbar && !(graphics_layer && is_overlay)) {
+    new_visual_rect = ScrollControlVisualRect(scrollbar->FrameRect(), box,
+                                              context, previous_visual_rect);
+  }
+
+  bool needs_paint_invalidation = needs_paint_invalidation_arg;
+  if (needs_paint_invalidation && graphics_layer) {
+    // If the scrollbar needs paint invalidation but didn't change location/size
+    // or the scrollbar is an overlay scrollbar (visual rect is empty),
+    // invalidating the graphics layer is enough (which has been done in
+    // ScrollableArea::setScrollbarNeedsPaintInvalidation()).
+    // Otherwise invalidatePaintOfScrollControlIfNeeded() below will invalidate
+    // the old and new location of the scrollbar on the box's paint invalidation
+    // container to ensure newly expanded/shrunk areas of the box to be
+    // invalidated.
+    needs_paint_invalidation = false;
+    DCHECK(!graphics_layer->DrawsContent() ||
+           graphics_layer->GetPaintController().GetPaintArtifact().IsEmpty());
+  }
+
+  // Invalidate the box's display item client if the box's padding box size is
+  // affected by change of the non-overlay scrollbar width. We detect change of
+  // visual rect size instead of change of scrollbar width change, which may
+  // have some false-positives (e.g. the scrollbar changed length but not width)
+  // but won't invalidate more than expected because in the false-positive case
+  // the box must have changed size and have been invalidated.
+  const LayoutBoxModelObject& paint_invalidation_container =
+      *context.paint_invalidation_container;
+  LayoutSize new_scrollbar_used_space_in_box;
+  if (!is_overlay)
+    new_scrollbar_used_space_in_box = new_visual_rect.Size();
+  LayoutSize previous_scrollbar_used_space_in_box;
+  if (!previously_was_overlay)
+    previous_scrollbar_used_space_in_box = previous_visual_rect.Size();
+
+  // The IsEmpty() check avoids invalidaiton in cases when the visual rect
+  // changes from (0,0 0x0) to (0,0 0x100).
+  if (!(new_scrollbar_used_space_in_box.IsEmpty() &&
+        previous_scrollbar_used_space_in_box.IsEmpty()) &&
+      new_scrollbar_used_space_in_box != previous_scrollbar_used_space_in_box) {
+    context.painting_layer->SetNeedsRepaint();
+    ObjectPaintInvalidator(box).InvalidateDisplayItemClient(
+        box, PaintInvalidationReason::kGeometry);
+  }
+
+  bool invalidated = InvalidatePaintOfScrollControlIfNeeded(
+      new_visual_rect, previous_visual_rect, needs_paint_invalidation, box,
+      paint_invalidation_container);
+
+  previously_was_overlay = is_overlay;
+
+  if (!invalidated || !scrollbar || graphics_layer)
+    return new_visual_rect;
+
+  context.painting_layer->SetNeedsRepaint();
+  ObjectPaintInvalidator(box).InvalidateDisplayItemClient(
+      *scrollbar, PaintInvalidationReason::kScrollControl);
+  if (scrollbar->IsCustomScrollbar()) {
+    ToLayoutScrollbar(scrollbar)
+        ->InvalidateDisplayItemClientsOfScrollbarParts();
+  }
+
+  return new_visual_rect;
+}
+
+void PaintLayerScrollableArea::InvalidatePaintOfScrollControlsIfNeeded(
+    const PaintInvalidatorContext& context) {
+  LayoutBox& box = *GetLayoutBox();
+  SetHorizontalScrollbarVisualRect(InvalidatePaintOfScrollbarIfNeeded(
+      HorizontalScrollbar(), LayerForHorizontalScrollbar(),
+      horizontal_scrollbar_previously_was_overlay_,
+      horizontal_scrollbar_visual_rect_,
+      HorizontalScrollbarNeedsPaintInvalidation(), box, context));
+  SetVerticalScrollbarVisualRect(InvalidatePaintOfScrollbarIfNeeded(
+      VerticalScrollbar(), LayerForVerticalScrollbar(),
+      vertical_scrollbar_previously_was_overlay_,
+      vertical_scrollbar_visual_rect_,
+      VerticalScrollbarNeedsPaintInvalidation(), box, context));
+
+  LayoutRect scroll_corner_and_resizer_visual_rect =
+      ScrollControlVisualRect(ScrollCornerAndResizerRect(), box, context,
+                              scroll_corner_and_resizer_visual_rect_);
+  const LayoutBoxModelObject& paint_invalidation_container =
+      *context.paint_invalidation_container;
+  if (InvalidatePaintOfScrollControlIfNeeded(
+          scroll_corner_and_resizer_visual_rect,
+          scroll_corner_and_resizer_visual_rect_,
+          ScrollCornerNeedsPaintInvalidation(), box,
+          paint_invalidation_container)) {
+    SetScrollCornerAndResizerVisualRect(scroll_corner_and_resizer_visual_rect);
+    if (LayoutScrollbarPart* scroll_corner = ScrollCorner()) {
+      ObjectPaintInvalidator(*scroll_corner)
+          .InvalidateDisplayItemClientsIncludingNonCompositingDescendants(
+              PaintInvalidationReason::kScrollControl);
+    }
+    if (LayoutScrollbarPart* resizer = Resizer()) {
+      ObjectPaintInvalidator(*resizer)
+          .InvalidateDisplayItemClientsIncludingNonCompositingDescendants(
+              PaintInvalidationReason::kScrollControl);
+    }
+  }
+
+  ClearNeedsPaintInvalidationForScrollControls();
+}
+
+void PaintLayerScrollableArea::ClearPreviousVisualRects() {
+  SetHorizontalScrollbarVisualRect(LayoutRect());
+  SetVerticalScrollbarVisualRect(LayoutRect());
+  SetScrollCornerAndResizerVisualRect(LayoutRect());
+}
+
+void PaintLayerScrollableArea::SetHorizontalScrollbarVisualRect(
+    const LayoutRect& rect) {
+  horizontal_scrollbar_visual_rect_ = rect;
+  if (Scrollbar* scrollbar = HorizontalScrollbar())
+    scrollbar->SetVisualRect(rect);
+}
+
+void PaintLayerScrollableArea::SetVerticalScrollbarVisualRect(
+    const LayoutRect& rect) {
+  vertical_scrollbar_visual_rect_ = rect;
+  if (Scrollbar* scrollbar = VerticalScrollbar())
+    scrollbar->SetVisualRect(rect);
+}
+
+void PaintLayerScrollableArea::SetScrollCornerAndResizerVisualRect(
+    const LayoutRect& rect) {
+  scroll_corner_and_resizer_visual_rect_ = rect;
+  if (LayoutScrollbarPart* scroll_corner = ScrollCorner())
+    scroll_corner->GetMutableForPainting().FirstFragment().SetVisualRect(rect);
+  if (LayoutScrollbarPart* resizer = Resizer())
+    resizer->GetMutableForPainting().FirstFragment().SetVisualRect(rect);
+}
+
+void PaintLayerScrollableArea::ScrollControlWasSetNeedsPaintInvalidation() {
+  GetLayoutBox()->SetMayNeedPaintInvalidation();
+}
+
+void PaintLayerScrollableArea::DidScrollWithScrollbar(
+    ScrollbarPart part,
+    ScrollbarOrientation orientation) {
+  WebFeature scrollbar_use_uma;
+  switch (part) {
+    case kBackButtonStartPart:
+    case kForwardButtonStartPart:
+    case kBackButtonEndPart:
+    case kForwardButtonEndPart:
+      scrollbar_use_uma =
+          (orientation == kVerticalScrollbar
+               ? WebFeature::kScrollbarUseVerticalScrollbarButton
+               : WebFeature::kScrollbarUseHorizontalScrollbarButton);
+      break;
+    case kThumbPart:
+      scrollbar_use_uma =
+          (orientation == kVerticalScrollbar
+               ? WebFeature::kScrollbarUseVerticalScrollbarThumb
+               : WebFeature::kScrollbarUseHorizontalScrollbarThumb);
+      break;
+    case kBackTrackPart:
+    case kForwardTrackPart:
+      scrollbar_use_uma =
+          (orientation == kVerticalScrollbar
+               ? WebFeature::kScrollbarUseVerticalScrollbarTrack
+               : WebFeature::kScrollbarUseHorizontalScrollbarTrack);
+      break;
+    default:
+      return;
+  }
+
+  UseCounter::Count(GetLayoutBox()->GetDocument(), scrollbar_use_uma);
+}
+
+CompositorElementId PaintLayerScrollableArea::GetCompositorElementId() const {
+  return CompositorElementIdFromUniqueObjectId(
+      GetLayoutBox()->UniqueId(), CompositorElementIdNamespace::kScroll);
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h
index ec713777..bd287d0 100644
--- a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h
+++ b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h
@@ -49,11 +49,10 @@
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/layout/scroll_anchor.h"
 #include "third_party/blink/renderer/core/page/scrolling/sticky_position_scrolling_constraints.h"
-#include "third_party/blink/renderer/core/paint/paint_invalidation_capable_scrollable_area.h"
 #include "third_party/blink/renderer/core/paint/paint_layer_fragment.h"
-#include "third_party/blink/renderer/core/paint/scrollbar_manager.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/scroll/scroll_types.h"
+#include "third_party/blink/renderer/platform/scroll/scrollable_area.h"
 
 namespace blink {
 
@@ -63,6 +62,7 @@
 class HitTestResult;
 class LayoutBox;
 class LayoutScrollbarPart;
+struct PaintInvalidatorContext;
 class PaintLayer;
 class ScrollingCoordinator;
 class StickyPositionScrollingConstraints;
@@ -115,12 +115,12 @@
 // PaintLayerPaintingOverlayScrollbars.
 class CORE_EXPORT PaintLayerScrollableArea final
     : public GarbageCollectedFinalized<PaintLayerScrollableArea>,
-      public PaintInvalidationCapableScrollableArea {
+      public ScrollableArea {
   USING_GARBAGE_COLLECTED_MIXIN(PaintLayerScrollableArea);
   friend class Internals;
 
  private:
-  class ScrollbarManager : public blink::ScrollbarManager {
+  class ScrollbarManager {
     DISALLOW_NEW();
 
     // Helper class to manage the life cycle of Scrollbar objects.  Some layout
@@ -136,19 +136,43 @@
     // previously "deleted" scrollbar will be restored, rather than constructing
     // a new one.
    public:
-    ScrollbarManager(PaintLayerScrollableArea& scroller)
-        : blink::ScrollbarManager(scroller) {}
+    ScrollbarManager(PaintLayerScrollableArea& scrollable_area)
+        : scrollable_area_(scrollable_area),
+          h_bar_is_attached_(0),
+          v_bar_is_attached_(0) {}
 
-    void SetHasHorizontalScrollbar(bool has_scrollbar) override;
-    void SetHasVerticalScrollbar(bool has_scrollbar) override;
+    PaintLayerScrollableArea* ScrollableArea() const {
+      return scrollable_area_.Get();
+    }
+    Scrollbar* HorizontalScrollbar() const {
+      return h_bar_is_attached_ ? h_bar_.Get() : nullptr;
+    }
+    Scrollbar* VerticalScrollbar() const {
+      return v_bar_is_attached_ ? v_bar_.Get() : nullptr;
+    }
+    bool HasHorizontalScrollbar() const { return HorizontalScrollbar(); }
+    bool HasVerticalScrollbar() const { return VerticalScrollbar(); }
 
+    void SetHasHorizontalScrollbar(bool has_scrollbar);
+    void SetHasVerticalScrollbar(bool has_scrollbar);
+
+    Scrollbar* CreateScrollbar(ScrollbarOrientation);
     void DestroyDetachedScrollbars();
-    Scrollbar* CreateScrollbar(ScrollbarOrientation) override;
+    void Dispose();
 
-   protected:
-    void DestroyScrollbar(ScrollbarOrientation) override;
+    void Trace(blink::Visitor*);
 
-    PaintLayerScrollableArea* ScrollableArea();
+   private:
+    void DestroyScrollbar(ScrollbarOrientation);
+
+    Member<PaintLayerScrollableArea> scrollable_area_;
+
+    // The scrollbars associated with scrollable_area_. Both can nullptr.
+    Member<Scrollbar> h_bar_;
+    Member<Scrollbar> v_bar_;
+
+    unsigned h_bar_is_attached_ : 1;
+    unsigned v_bar_is_attached_ : 1;
   };
 
  public:
@@ -350,7 +374,7 @@
     return HasScrollbar() || ScrollCorner() || Resizer();
   }
 
-  LayoutScrollbarPart* ScrollCorner() const override { return scroll_corner_; }
+  LayoutScrollbarPart* ScrollCorner() const { return scroll_corner_; }
 
   void Resize(const IntPoint& pos, const LayoutSize& old_offset);
   IntSize OffsetFromResizeCorner(const IntPoint& absolute_point) const;
@@ -400,7 +424,7 @@
   bool ScrollsOverflow() const { return scrolls_overflow_; }
 
   // Rectangle encompassing the scroll corner and resizer rect.
-  IntRect ScrollCornerAndResizerRect() const final;
+  IntRect ScrollCornerAndResizerRect() const;
 
   void UpdateNeedsCompositedScrolling(bool layer_has_been_composited = false);
   bool NeedsCompositedScrolling() const { return needs_composited_scrolling_; }
@@ -418,7 +442,7 @@
 
   PaintLayer* Layer() const override;
 
-  LayoutScrollbarPart* Resizer() const override { return resizer_; }
+  LayoutScrollbarPart* Resizer() const { return resizer_; }
 
   const IntPoint& CachedOverlayScrollbarOffset() {
     return cached_overlay_scrollbar_offset_;
@@ -498,6 +522,16 @@
 
   ScrollbarTheme& GetPageScrollbarTheme() const override;
 
+  void WillRemoveScrollbar(Scrollbar&, ScrollbarOrientation) override;
+
+  void InvalidatePaintOfScrollControlsIfNeeded(const PaintInvalidatorContext&);
+
+  // Should be called when the previous visual rects are no longer valid.
+  void ClearPreviousVisualRects();
+
+  void DidScrollWithScrollbar(ScrollbarPart, ScrollbarOrientation) override;
+  CompositorElementId GetCompositorElementId() const override;
+
   void Trace(blink::Visitor*) override;
 
  private:
@@ -570,6 +604,12 @@
 
   IntRect CornerRect(const IntRect& bounds) const;
 
+  void ScrollControlWasSetNeedsPaintInvalidation() override;
+
+  void SetHorizontalScrollbarVisualRect(const LayoutRect&);
+  void SetVerticalScrollbarVisualRect(const LayoutRect&);
+  void SetScrollCornerAndResizerVisualRect(const LayoutRect&);
+
   // PaintLayer is destructed before PaintLayerScrollable area, during this
   // time before PaintLayerScrollableArea has been collected layer_ will
   // be set to nullptr by the Dispose method.
@@ -628,6 +668,12 @@
 
   // MainThreadScrollingReason due to the properties of the LayoutObject
   uint32_t non_composited_main_thread_scrolling_reasons_;
+
+  bool horizontal_scrollbar_previously_was_overlay_;
+  bool vertical_scrollbar_previously_was_overlay_;
+  LayoutRect horizontal_scrollbar_visual_rect_;
+  LayoutRect vertical_scrollbar_visual_rect_;
+  LayoutRect scroll_corner_and_resizer_visual_rect_;
 };
 
 DEFINE_TYPE_CASTS(PaintLayerScrollableArea,
diff --git a/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc b/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
index c46afc4..852fd19 100644
--- a/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
+++ b/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
@@ -2281,6 +2281,9 @@
   LayoutView* view = object_.View();
   context_.repeating_table_section_bounding_box =
       BoundingBoxInPaginationContainer(object_, *view->Layer());
+  // Convert the bounding box into the scrolling contents space.
+  context_.repeating_table_section_bounding_box.Move(LayoutUnit(),
+                                                     view->ScrollTop());
 
   auto page_height = view->PageLogicalHeight();
   const auto& bounding_box = context_.repeating_table_section_bounding_box;
diff --git a/third_party/blink/renderer/core/paint/rounded_inner_rect_clipper.cc b/third_party/blink/renderer/core/paint/rounded_inner_rect_clipper.cc
index 9ea7567..af3dfd0 100644
--- a/third_party/blink/renderer/core/paint/rounded_inner_rect_clipper.cc
+++ b/third_party/blink/renderer/core/paint/rounded_inner_rect_clipper.cc
@@ -5,7 +5,6 @@
 #include "third_party/blink/renderer/core/paint/rounded_inner_rect_clipper.h"
 
 #include "third_party/blink/renderer/core/paint/paint_info.h"
-#include "third_party/blink/renderer/platform/graphics/paint/clip_display_item.h"
 #include "third_party/blink/renderer/platform/graphics/paint/display_item_client.h"
 #include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h"
 
@@ -19,12 +18,8 @@
     RoundedInnerRectClipperBehavior behavior)
     : display_item_(display_item),
       paint_info_(paint_info),
-      use_paint_controller_(behavior == kApplyToDisplayList),
-      clip_type_(use_paint_controller_
-                     ? paint_info_.DisplayItemTypeForClipping()
-                     : DisplayItem::kClipBoxPaintPhaseFirst) {
-  if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled() &&
-      use_paint_controller_)
+      use_paint_controller_(behavior == kApplyToDisplayList) {
+  if (use_paint_controller_)
     return;
 
   Vector<FloatRoundedRect> rounded_rect_clips;
@@ -72,29 +67,16 @@
     }
   }
 
-  if (use_paint_controller_) {
-    paint_info_.context.GetPaintController().CreateAndAppend<ClipDisplayItem>(
-        display_item, clip_type_, LayoutRect::InfiniteIntRect(),
-        rounded_rect_clips);
-  } else {
-    paint_info.context.Save();
-    for (const auto& rrect : rounded_rect_clips)
-      paint_info.context.ClipRoundedRect(rrect);
-  }
+  paint_info.context.Save();
+  for (const auto& rrect : rounded_rect_clips)
+    paint_info.context.ClipRoundedRect(rrect);
 }
 
 RoundedInnerRectClipper::~RoundedInnerRectClipper() {
-  if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled() &&
-      use_paint_controller_)
+  if (use_paint_controller_)
     return;
 
-  DisplayItem::Type end_type = DisplayItem::ClipTypeToEndClipType(clip_type_);
-  if (use_paint_controller_) {
-    paint_info_.context.GetPaintController().EndItem<EndClipDisplayItem>(
-        display_item_, end_type);
-  } else {
-    paint_info_.context.Restore();
-  }
+  paint_info_.context.Restore();
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/paint/rounded_inner_rect_clipper.h b/third_party/blink/renderer/core/paint/rounded_inner_rect_clipper.h
index 25fd36b..9394457c 100644
--- a/third_party/blink/renderer/core/paint/rounded_inner_rect_clipper.h
+++ b/third_party/blink/renderer/core/paint/rounded_inner_rect_clipper.h
@@ -5,7 +5,6 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_ROUNDED_INNER_RECT_CLIPPER_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_ROUNDED_INNER_RECT_CLIPPER_H_
 
-#include "third_party/blink/renderer/platform/graphics/paint/display_item.h"
 #include "third_party/blink/renderer/platform/wtf/allocator.h"
 
 namespace blink {
@@ -32,7 +31,6 @@
   const DisplayItemClient& display_item_;
   const PaintInfo& paint_info_;
   bool use_paint_controller_;
-  DisplayItem::Type clip_type_;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/paint/scroll_recorder.cc b/third_party/blink/renderer/core/paint/scroll_recorder.cc
deleted file mode 100644
index b0890f1..0000000
--- a/third_party/blink/renderer/core/paint/scroll_recorder.cc
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/paint/scroll_recorder.h"
-
-#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
-#include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h"
-#include "third_party/blink/renderer/platform/graphics/paint/scroll_display_item.h"
-
-namespace blink {
-
-ScrollRecorder::ScrollRecorder(GraphicsContext& context,
-                               const DisplayItemClient& client,
-                               DisplayItem::Type type,
-                               const IntSize& current_offset)
-    : client_(client), begin_item_type_(type), context_(context) {
-  if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
-    return;
-  context_.GetPaintController().CreateAndAppend<BeginScrollDisplayItem>(
-      client_, begin_item_type_, current_offset);
-}
-
-ScrollRecorder::ScrollRecorder(GraphicsContext& context,
-                               const DisplayItemClient& client,
-                               PaintPhase phase,
-                               const IntSize& current_offset)
-    : ScrollRecorder(context,
-                     client,
-                     DisplayItem::PaintPhaseToScrollType(phase),
-                     current_offset) {}
-
-ScrollRecorder::~ScrollRecorder() {
-  if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
-    return;
-  context_.GetPaintController().EndItem<EndScrollDisplayItem>(
-      client_, DisplayItem::ScrollTypeToEndScrollType(begin_item_type_));
-}
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/core/paint/scroll_recorder.h b/third_party/blink/renderer/core/paint/scroll_recorder.h
deleted file mode 100644
index 8127339..0000000
--- a/third_party/blink/renderer/core/paint/scroll_recorder.h
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_SCROLL_RECORDER_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_SCROLL_RECORDER_H_
-
-#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/paint/paint_phase.h"
-#include "third_party/blink/renderer/platform/geometry/int_size.h"
-#include "third_party/blink/renderer/platform/graphics/paint/display_item.h"
-#include "third_party/blink/renderer/platform/wtf/allocator.h"
-
-namespace blink {
-
-class GraphicsContext;
-
-// Emits display items which represent a region which is scrollable, so that it
-// can be translated by the scroll offset.
-class CORE_EXPORT ScrollRecorder {
-  USING_FAST_MALLOC(ScrollRecorder);
-
- public:
-  ScrollRecorder(GraphicsContext&,
-                 const DisplayItemClient&,
-                 DisplayItem::Type,
-                 const IntSize& current_offset);
-  ScrollRecorder(GraphicsContext&,
-                 const DisplayItemClient&,
-                 PaintPhase,
-                 const IntSize& current_offset);
-  ~ScrollRecorder();
-
- private:
-  const DisplayItemClient& client_;
-  DisplayItem::Type begin_item_type_;
-  GraphicsContext& context_;
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_SCROLL_RECORDER_H_
diff --git a/third_party/blink/renderer/core/paint/scrollable_area_painter.cc b/third_party/blink/renderer/core/paint/scrollable_area_painter.cc
index d7071a6c..7fa6eb6e 100644
--- a/third_party/blink/renderer/core/paint/scrollable_area_painter.cc
+++ b/third_party/blink/renderer/core/paint/scrollable_area_painter.cc
@@ -11,11 +11,9 @@
 #include "third_party/blink/renderer/core/paint/paint_layer.h"
 #include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
 #include "third_party/blink/renderer/core/paint/scrollbar_painter.h"
-#include "third_party/blink/renderer/core/paint/transform_recorder.h"
 #include "third_party/blink/renderer/platform/graphics/graphics_context.h"
 #include "third_party/blink/renderer/platform/graphics/graphics_context_state_saver.h"
 #include "third_party/blink/renderer/platform/graphics/graphics_layer.h"
-#include "third_party/blink/renderer/platform/graphics/paint/clip_recorder.h"
 #include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
 #include "third_party/blink/renderer/platform/graphics/paint/scoped_paint_chunk_properties.h"
 #include "third_party/blink/renderer/platform/platform_chrome_client.h"
@@ -173,46 +171,31 @@
     return;
 
   GraphicsContext& context = paint_info.context;
+  const auto& box = *GetScrollableArea().GetLayoutBox();
+  const auto* fragment = paint_info.FragmentToPaint(box);
+  if (!fragment)
+    return;
 
-  base::Optional<ClipRecorder> clip_recorder;
   base::Optional<ScopedPaintChunkProperties> scoped_paint_chunk_properties;
-  if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
-    const auto& box = *GetScrollableArea().GetLayoutBox();
-    if (const auto* fragment = paint_info.FragmentToPaint(box)) {
-      const auto* properties = fragment->PaintProperties();
-      // TODO(crbug.com/849278): Remove either the DCHECK or the if condition
-      // when we figure out in what cases that the box doesn't have properties.
-      DCHECK(properties);
-      if (properties) {
-        if (const auto* clip = properties->OverflowControlsClip()) {
-          scoped_paint_chunk_properties.emplace(
-              context.GetPaintController(), clip, box,
-              DisplayItem::kClipLayerOverflowControls);
-        }
-      }
+  const auto* properties = fragment->PaintProperties();
+  // TODO(crbug.com/849278): Remove either the DCHECK or the if condition
+  // when we figure out in what cases that the box doesn't have properties.
+  DCHECK(properties);
+  if (properties) {
+    if (const auto* clip = properties->OverflowControlsClip()) {
+      scoped_paint_chunk_properties.emplace(
+          context.GetPaintController(), clip, box,
+          DisplayItem::kClipLayerOverflowControls);
     }
-  } else {
-    IntRect clip_rect(adjusted_paint_offset,
-                      GetScrollableArea().Layer()->PixelSnappedSize());
-    clip_recorder.emplace(context, *GetScrollableArea().GetLayoutBox(),
-                          DisplayItem::kClipLayerOverflowControls, clip_rect);
   }
 
   if (GetScrollableArea().HorizontalScrollbar() &&
       !GetScrollableArea().LayerForHorizontalScrollbar()) {
-    TransformRecorder translate_recorder(
-        context, *GetScrollableArea().HorizontalScrollbar(),
-        AffineTransform::Translation(adjusted_paint_offset.X(),
-                                     adjusted_paint_offset.Y()));
     GetScrollableArea().HorizontalScrollbar()->Paint(context,
                                                      adjusted_cull_rect);
   }
   if (GetScrollableArea().VerticalScrollbar() &&
       !GetScrollableArea().LayerForVerticalScrollbar()) {
-    TransformRecorder translate_recorder(
-        context, *GetScrollableArea().VerticalScrollbar(),
-        AffineTransform::Translation(adjusted_paint_offset.X(),
-                                     adjusted_paint_offset.Y()));
     GetScrollableArea().VerticalScrollbar()->Paint(context, adjusted_cull_rect);
   }
   if (!GetScrollableArea().LayerForScrollCorner()) {
diff --git a/third_party/blink/renderer/core/paint/scrollbar_manager.cc b/third_party/blink/renderer/core/paint/scrollbar_manager.cc
deleted file mode 100644
index 0dc78ec..0000000
--- a/third_party/blink/renderer/core/paint/scrollbar_manager.cc
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/core/paint/scrollbar_manager.h"
-
-namespace blink {
-
-ScrollbarManager::ScrollbarManager(ScrollableArea& scrollable_area)
-    : scrollable_area_(&scrollable_area),
-      h_bar_is_attached_(0),
-      v_bar_is_attached_(0) {}
-
-void ScrollbarManager::Trace(blink::Visitor* visitor) {
-  visitor->Trace(scrollable_area_);
-  visitor->Trace(h_bar_);
-  visitor->Trace(v_bar_);
-}
-
-void ScrollbarManager::Dispose() {
-  h_bar_is_attached_ = v_bar_is_attached_ = 0;
-  DestroyScrollbar(kHorizontalScrollbar);
-  DestroyScrollbar(kVerticalScrollbar);
-}
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/core/paint/scrollbar_manager.h b/third_party/blink/renderer/core/paint/scrollbar_manager.h
deleted file mode 100644
index fdf90a6..0000000
--- a/third_party/blink/renderer/core/paint/scrollbar_manager.h
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_SCROLLBAR_MANAGER_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_SCROLLBAR_MANAGER_H_
-
-#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/platform/scroll/scrollable_area.h"
-
-namespace blink {
-
-class CORE_EXPORT ScrollbarManager {
-  DISALLOW_NEW();
-
-  // Helper class to manage the life cycle of Scrollbar objects.
- public:
-  ScrollbarManager(ScrollableArea&);
-
-  void Dispose();
-
-  Scrollbar* HorizontalScrollbar() const {
-    return h_bar_is_attached_ ? h_bar_.Get() : nullptr;
-  }
-  Scrollbar* VerticalScrollbar() const {
-    return v_bar_is_attached_ ? v_bar_.Get() : nullptr;
-  }
-  bool HasHorizontalScrollbar() const { return HorizontalScrollbar(); }
-  bool HasVerticalScrollbar() const { return VerticalScrollbar(); }
-
-  // These functions are used to create/destroy scrollbars.
-  virtual void SetHasHorizontalScrollbar(bool has_scrollbar) = 0;
-  virtual void SetHasVerticalScrollbar(bool has_scrollbar) = 0;
-
-  virtual void Trace(blink::Visitor*);
-
- protected:
-  // TODO(ymalik): This can be made non-virtual since there's a lot of
-  // common code in subclasses.
-  virtual Scrollbar* CreateScrollbar(ScrollbarOrientation) = 0;
-  virtual void DestroyScrollbar(ScrollbarOrientation) = 0;
-
- protected:
-  Member<ScrollableArea> scrollable_area_;
-
-  // The scrollbars associated with m_scrollableArea. Both can nullptr.
-  Member<Scrollbar> h_bar_;
-  Member<Scrollbar> v_bar_;
-
-  unsigned h_bar_is_attached_ : 1;
-  unsigned v_bar_is_attached_ : 1;
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_SCROLLBAR_MANAGER_H_
diff --git a/third_party/blink/renderer/core/paint/svg_container_painter.cc b/third_party/blink/renderer/core/paint/svg_container_painter.cc
index ede56819..171b686fb 100644
--- a/third_party/blink/renderer/core/paint/svg_container_painter.cc
+++ b/third_party/blink/renderer/core/paint/svg_container_painter.cc
@@ -10,7 +10,6 @@
 #include "third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object.h"
 #include "third_party/blink/renderer/core/layout/svg/layout_svg_viewport_container.h"
 #include "third_party/blink/renderer/core/layout/svg/svg_layout_support.h"
-#include "third_party/blink/renderer/core/paint/float_clip_recorder.h"
 #include "third_party/blink/renderer/core/paint/object_painter.h"
 #include "third_party/blink/renderer/core/paint/paint_info.h"
 #include "third_party/blink/renderer/core/paint/svg_foreign_object_painter.h"
@@ -47,11 +46,9 @@
       paint_info_before_filtering, layout_svg_container_,
       layout_svg_container_.LocalToSVGParentTransform());
   {
-    base::Optional<FloatClipRecorder> clip_recorder;
     base::Optional<ScopedPaintChunkProperties> scoped_paint_chunk_properties;
     if (layout_svg_container_.IsSVGViewportContainer() &&
         SVGLayoutSupport::IsOverflowHidden(layout_svg_container_)) {
-      if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
         const auto* fragment =
             paint_info.FragmentToPaint(layout_svg_container_);
         if (!fragment)
@@ -66,14 +63,6 @@
               properties->OverflowClip(), layout_svg_container_,
               paint_info.DisplayItemTypeForClipping());
         }
-      } else {
-        FloatRect viewport =
-            layout_svg_container_.LocalToSVGParentTransform().Inverse().MapRect(
-                ToLayoutSVGViewportContainer(layout_svg_container_).Viewport());
-        clip_recorder.emplace(paint_info_before_filtering.context,
-                              layout_svg_container_,
-                              paint_info_before_filtering.phase, viewport);
-      }
     }
 
     SVGPaintContext paint_context(layout_svg_container_,
@@ -85,8 +74,7 @@
     if (continue_rendering) {
       for (LayoutObject* child = layout_svg_container_.FirstChild(); child;
            child = child->NextSibling()) {
-        if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled() &&
-            child->IsSVGForeignObject()) {
+        if (child->IsSVGForeignObject()) {
           SVGForeignObjectPainter(ToLayoutSVGForeignObject(*child))
               .PaintLayer(paint_context.GetPaintInfo());
         } else {
diff --git a/third_party/blink/renderer/core/paint/svg_foreign_object_painter.cc b/third_party/blink/renderer/core/paint/svg_foreign_object_painter.cc
index d2734756..51a271a 100644
--- a/third_party/blink/renderer/core/paint/svg_foreign_object_painter.cc
+++ b/third_party/blink/renderer/core/paint/svg_foreign_object_painter.cc
@@ -8,7 +8,6 @@
 #include "third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object.h"
 #include "third_party/blink/renderer/core/layout/svg/svg_layout_support.h"
 #include "third_party/blink/renderer/core/paint/block_painter.h"
-#include "third_party/blink/renderer/core/paint/float_clip_recorder.h"
 #include "third_party/blink/renderer/core/paint/object_painter.h"
 #include "third_party/blink/renderer/core/paint/paint_info.h"
 #include "third_party/blink/renderer/core/paint/paint_layer.h"
@@ -17,27 +16,7 @@
 
 namespace blink {
 
-namespace {
-
-class BlockPainterDelegate : public LayoutBlock {
- public:
-  BlockPainterDelegate(const LayoutSVGForeignObject& layout_svg_foreign_object)
-      : LayoutBlock(nullptr),
-        layout_svg_foreign_object_(layout_svg_foreign_object) {}
-
- private:
-  void Paint(const PaintInfo& paint_info,
-             const LayoutPoint& paint_offset) const final {
-    BlockPainter(layout_svg_foreign_object_).Paint(paint_info, paint_offset);
-  }
-  const LayoutSVGForeignObject& layout_svg_foreign_object_;
-};
-
-}  // namespace
-
 void SVGForeignObjectPainter::PaintLayer(const PaintInfo& paint_info) {
-  if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
-    return;
   if (paint_info.phase != PaintPhase::kForeground &&
       paint_info.phase != PaintPhase::kSelection)
     return;
@@ -64,54 +43,14 @@
 }
 
 void SVGForeignObjectPainter::Paint(const PaintInfo& paint_info) {
-  if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
-    if (paint_info.phase != PaintPhase::kForeground &&
-        paint_info.phase != PaintPhase::kSelection)
-      return;
-  }
-
   PaintInfo paint_info_before_filtering(paint_info);
-  base::Optional<SVGTransformContext> transform_context;
-
-  if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
-    paint_info_before_filtering.UpdateCullRect(
-        layout_svg_foreign_object_.LocalSVGTransform());
-    transform_context.emplace(paint_info_before_filtering,
-                              layout_svg_foreign_object_,
-                              layout_svg_foreign_object_.LocalSVGTransform());
-
-    // In theory we should just let BlockPainter::paint() handle the clip, but
-    // for now we don't allow normal overflow clip for LayoutSVGBlock, so we
-    // have to apply clip manually. See LayoutSVGBlock::allowsOverflowClip() for
-    // details.
-    base::Optional<FloatClipRecorder> clip_recorder;
-    base::Optional<ScopedPaintChunkProperties> scoped_paint_chunk_properties;
-    if (SVGLayoutSupport::IsOverflowHidden(layout_svg_foreign_object_)) {
-      clip_recorder.emplace(paint_info_before_filtering.context,
-                            layout_svg_foreign_object_,
-                            paint_info_before_filtering.phase,
-                            FloatRect(layout_svg_foreign_object_.FrameRect()));
-    }
-  }
-
   SVGPaintContext paint_context(layout_svg_foreign_object_,
                                 paint_info_before_filtering);
   if (paint_context.GetPaintInfo().phase == PaintPhase::kForeground &&
       !paint_context.ApplyClipMaskAndFilterIfNecessary())
     return;
 
-  if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
-    BlockPainter(layout_svg_foreign_object_).Paint(paint_info, LayoutPoint());
-  } else {
-    // Paint all phases of FO elements atomically as though the FO element
-    // established its own stacking context.  The delegate forwards calls to
-    // paint() in LayoutObject::paintAllPhasesAtomically() to
-    // BlockPainter::paint(), instead of m_layoutSVGForeignObject.paint() (which
-    // would call this method again).
-    BlockPainterDelegate delegate(layout_svg_foreign_object_);
-    ObjectPainter(delegate).PaintAllPhasesAtomically(
-        paint_context.GetPaintInfo(), LayoutPoint());
-  }
+  BlockPainter(layout_svg_foreign_object_).Paint(paint_info, LayoutPoint());
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/paint/svg_mask_painter.cc b/third_party/blink/renderer/core/paint/svg_mask_painter.cc
index 0d369f8..9e2863a 100644
--- a/third_party/blink/renderer/core/paint/svg_mask_painter.cc
+++ b/third_party/blink/renderer/core/paint/svg_mask_painter.cc
@@ -7,8 +7,6 @@
 #include "third_party/blink/renderer/core/layout/svg/layout_svg_resource_masker.h"
 #include "third_party/blink/renderer/core/paint/object_paint_properties.h"
 #include "third_party/blink/renderer/core/paint/paint_info.h"
-#include "third_party/blink/renderer/platform/graphics/paint/compositing_display_item.h"
-#include "third_party/blink/renderer/platform/graphics/paint/compositing_recorder.h"
 #include "third_party/blink/renderer/platform/graphics/paint/drawing_display_item.h"
 #include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
 #include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h"
@@ -27,10 +25,6 @@
   if (visual_rect.IsEmpty() || !mask_.GetElement()->HasChildren())
     return false;
 
-  if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
-    context.GetPaintController().CreateAndAppend<BeginCompositingDisplayItem>(
-        object, SkBlendMode::kSrcOver, 1, &visual_rect);
-  }
   return true;
 }
 
@@ -39,47 +33,26 @@
   DCHECK(mask_.Style());
   SECURITY_DCHECK(!mask_.NeedsLayout());
 
-  FloatRect visual_rect = object.VisualRectInLocalSVGCoordinates();
-  {
-    ColorFilter mask_layer_filter =
-        mask_.Style()->SvgStyle().MaskType() == MT_LUMINANCE
-            ? kColorFilterLuminanceToAlpha
-            : kColorFilterNone;
-    CompositingRecorder mask_compositing(context, object, SkBlendMode::kDstIn,
-                                         1, &visual_rect, mask_layer_filter);
-    base::Optional<ScopedPaintChunkProperties> scoped_paint_chunk_properties;
-    if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
-      const auto* properties = object.FirstFragment().PaintProperties();
-      // TODO(crbug.com/814815): This condition should be a DCHECK, but for now
-      // we may paint the object for filters during PrePaint before the
-      // properties are ready.
-      if (properties && properties->Mask()) {
-        scoped_paint_chunk_properties.emplace(context.GetPaintController(),
-                                              properties->Mask(), object,
-                                              DisplayItem::kSVGMask);
-      }
-    }
-
-    DrawMaskForLayoutObject(context, object, object.ObjectBoundingBox());
+  base::Optional<ScopedPaintChunkProperties> scoped_paint_chunk_properties;
+  const auto* properties = object.FirstFragment().PaintProperties();
+  // TODO(crbug.com/814815): This condition should be a DCHECK, but for now
+  // we may paint the object for filters during PrePaint before the
+  // properties are ready.
+  if (properties && properties->Mask()) {
+    scoped_paint_chunk_properties.emplace(context.GetPaintController(),
+                                          properties->Mask(), object,
+                                          DisplayItem::kSVGMask);
   }
 
-  if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
-    context.GetPaintController().EndItem<EndCompositingDisplayItem>(object);
-}
-
-void SVGMaskPainter::DrawMaskForLayoutObject(
-    GraphicsContext& context,
-    const LayoutObject& layout_object,
-    const FloatRect& target_bounding_box) {
   AffineTransform content_transformation;
   sk_sp<const PaintRecord> record = mask_.CreatePaintRecord(
-      content_transformation, target_bounding_box, context);
+      content_transformation, object.ObjectBoundingBox(), context);
 
-  if (DrawingRecorder::UseCachedDrawingIfPossible(context, layout_object,
+  if (DrawingRecorder::UseCachedDrawingIfPossible(context, object,
                                                   DisplayItem::kSVGMask))
     return;
 
-  DrawingRecorder recorder(context, layout_object, DisplayItem::kSVGMask);
+  DrawingRecorder recorder(context, object, DisplayItem::kSVGMask);
   context.Save();
   context.ConcatCTM(content_transformation);
   context.DrawRecord(std::move(record));
diff --git a/third_party/blink/renderer/core/paint/svg_paint_context.cc b/third_party/blink/renderer/core/paint/svg_paint_context.cc
index e2645a5..c742efb 100644
--- a/third_party/blink/renderer/core/paint/svg_paint_context.cc
+++ b/third_party/blink/renderer/core/paint/svg_paint_context.cc
@@ -78,17 +78,11 @@
   }
 
   bool is_svg_root = object_.IsSVGRoot();
-
-  // Layer takes care of root opacity and blend mode.
   if (is_svg_root) {
-    DCHECK(!(object_.IsTransparent() || object_.StyleRef().HasBlendMode()) ||
-           object_.HasLayer());
-  } else {
-    ApplyCompositingIfNecessary();
-  }
-
-  if (is_svg_root) {
-    DCHECK(!object_.StyleRef().ClipPath() || object_.HasLayer());
+    // Layer takes care of root opacity and blend mode.
+    DCHECK(object_.HasLayer() ||
+           !(object_.IsTransparent() || object_.StyleRef().HasBlendMode() ||
+             object_.StyleRef().ClipPath()));
   } else {
     ApplyClipIfNecessary();
   }
@@ -100,24 +94,16 @@
     return false;
 
   if (is_svg_root) {
-    DCHECK(!object_.StyleRef().HasFilter() || object_.HasLayer());
+    // Layer takes care of root filter.
+    DCHECK(object_.HasLayer() || !object_.StyleRef().HasFilter());
   } else if (!ApplyFilterIfNecessary(resources)) {
     return false;
   }
 
-  if (!IsIsolationInstalled() &&
-      SVGLayoutSupport::IsIsolationRequired(&object_)) {
-    compositing_recorder_ = std::make_unique<CompositingRecorder>(
-        GetPaintInfo().context, object_, SkBlendMode::kSrcOver, 1);
-  }
-
   return true;
 }
 
 void SVGPaintContext::ApplyPaintPropertyState() {
-  if (!RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
-    return;
-
   // SVGRoot works like normal CSS replaced element and its effects are
   // applied as stacking context effect by PaintLayerPainter.
   if (object_.IsSVGRoot())
@@ -144,24 +130,6 @@
       DisplayItem::PaintPhaseToSVGEffectType(GetPaintInfo().phase));
 }
 
-void SVGPaintContext::ApplyCompositingIfNecessary() {
-  DCHECK(!GetPaintInfo().IsRenderingClipPathAsMaskImage());
-
-  const ComputedStyle& style = object_.StyleRef();
-  float opacity = style.Opacity();
-  BlendMode blend_mode = style.HasBlendMode() && object_.IsBlendingAllowed()
-                             ? style.GetBlendMode()
-                             : BlendMode::kNormal;
-  if (opacity < 1 || blend_mode != BlendMode::kNormal) {
-    const FloatRect compositing_bounds =
-        object_.VisualRectInLocalSVGCoordinates();
-    compositing_recorder_ = std::make_unique<CompositingRecorder>(
-        GetPaintInfo().context, object_,
-        WebCoreCompositeToSkiaComposite(kCompositeSourceOver, blend_mode),
-        opacity, &compositing_bounds);
-  }
-}
-
 void SVGPaintContext::ApplyClipIfNecessary() {
   if (object_.StyleRef().ClipPath())
     clip_path_clipper_.emplace(GetPaintInfo().context, object_, LayoutPoint());
@@ -213,21 +181,6 @@
   return true;
 }
 
-bool SVGPaintContext::IsIsolationInstalled() const {
-  // In SPv175+ isolation is modeled by effect nodes, and will be applied by
-  // PaintArtifactCompositor or PaintChunksToCcLayer depends on compositing
-  // state.
-  if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
-    return true;
-  if (compositing_recorder_)
-    return true;
-  if (masker_ || filter_)
-    return true;
-  if (clip_path_clipper_ && clip_path_clipper_->IsIsolationInstalled())
-    return true;
-  return false;
-}
-
 void SVGPaintContext::PaintResourceSubtree(GraphicsContext& context,
                                            const LayoutObject* item) {
   DCHECK(item);
diff --git a/third_party/blink/renderer/core/paint/svg_paint_context.h b/third_party/blink/renderer/core/paint/svg_paint_context.h
index 8a60c27..2616396 100644
--- a/third_party/blink/renderer/core/paint/svg_paint_context.h
+++ b/third_party/blink/renderer/core/paint/svg_paint_context.h
@@ -31,8 +31,6 @@
 #include "third_party/blink/renderer/core/paint/object_paint_properties.h"
 #include "third_party/blink/renderer/core/paint/paint_info.h"
 #include "third_party/blink/renderer/core/paint/svg_filter_painter.h"
-#include "third_party/blink/renderer/core/paint/transform_recorder.h"
-#include "third_party/blink/renderer/platform/graphics/paint/compositing_recorder.h"
 #include "third_party/blink/renderer/platform/graphics/paint/scoped_paint_chunk_properties.h"
 #include "third_party/blink/renderer/platform/transforms/affine_transform.h"
 
@@ -43,43 +41,38 @@
 class LayoutSVGResourceMasker;
 class SVGResources;
 
-// This class hooks up the correct paint property transform node when spv2 is
-// enabled, and otherwise works like a TransformRecorder which emits Transform
-// display items for spv1.
-class SVGTransformContext : public TransformRecorder {
+// Hooks up the correct paint property transform node.
+class SVGTransformContext {
   STACK_ALLOCATED();
 
  public:
   SVGTransformContext(const PaintInfo& paint_info,
                       const LayoutObject& object,
-                      const AffineTransform& transform)
-      : TransformRecorder(paint_info.context, object, transform) {
-    if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
-      const auto* fragment = paint_info.FragmentToPaint(object);
-      if (!fragment)
-        return;
-      const auto* properties = fragment->PaintProperties();
-      if (!properties)
-        return;
+                      const AffineTransform& transform) {
+    const auto* fragment = paint_info.FragmentToPaint(object);
+    if (!fragment)
+      return;
+    const auto* properties = fragment->PaintProperties();
+    if (!properties)
+      return;
 
-      const TransformPaintPropertyNode* transform_node;
-      if (object.IsSVGRoot()) {
-        // If a transform exists, we can rely on a layer existing to apply it.
-        DCHECK(!properties || !properties->Transform() || object.HasLayer());
-        transform_node = properties->SvgLocalToBorderBoxTransform();
-      } else {
-        DCHECK(object.IsSVG());
-        // Should only be used by LayoutSVGRoot.
-        DCHECK(!properties->SvgLocalToBorderBoxTransform());
-        transform_node = properties->Transform();
-      }
+    const TransformPaintPropertyNode* transform_node;
+    if (object.IsSVGRoot()) {
+      // If a transform exists, we can rely on a layer existing to apply it.
+      DCHECK(!properties || !properties->Transform() || object.HasLayer());
+      transform_node = properties->SvgLocalToBorderBoxTransform();
+    } else {
+      DCHECK(object.IsSVG());
+      // Should only be used by LayoutSVGRoot.
+      DCHECK(!properties->SvgLocalToBorderBoxTransform());
+      transform_node = properties->Transform();
+    }
 
-      if (transform_node) {
-        DCHECK(transform_node->Matrix() == transform.ToTransformationMatrix());
-        transform_property_scope_.emplace(
-            paint_info.context.GetPaintController(), transform_node, object,
-            DisplayItem::PaintPhaseToSVGTransformType(paint_info.phase));
-      }
+    if (transform_node) {
+      DCHECK(transform_node->Matrix() == transform.ToTransformationMatrix());
+      transform_property_scope_.emplace(
+          paint_info.context.GetPaintController(), transform_node, object,
+          DisplayItem::PaintPhaseToSVGTransformType(paint_info.phase));
     }
   }
 
@@ -120,7 +113,6 @@
       const AffineTransform* additional_paint_server_transform = nullptr);
 
  private:
-  void ApplyCompositingIfNecessary();
   void ApplyPaintPropertyState();
   void ApplyClipIfNecessary();
 
@@ -132,14 +124,11 @@
   // applied.
   bool ApplyFilterIfNecessary(SVGResources*);
 
-  bool IsIsolationInstalled() const;
-
   const LayoutObject& object_;
   PaintInfo paint_info_;
   std::unique_ptr<PaintInfo> filter_paint_info_;
   LayoutSVGResourceFilter* filter_;
   LayoutSVGResourceMasker* masker_;
-  std::unique_ptr<CompositingRecorder> compositing_recorder_;
   base::Optional<ClipPathClipper> clip_path_clipper_;
   std::unique_ptr<SVGFilterRecordingContext> filter_recording_context_;
   base::Optional<ScopedPaintChunkProperties> scoped_paint_chunk_properties_;
diff --git a/third_party/blink/renderer/core/paint/transform_3d_recorder.cc b/third_party/blink/renderer/core/paint/transform_3d_recorder.cc
deleted file mode 100644
index 0807fc6..0000000
--- a/third_party/blink/renderer/core/paint/transform_3d_recorder.cc
+++ /dev/null
@@ -1,41 +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 "third_party/blink/renderer/core/paint/transform_3d_recorder.h"
-
-#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
-#include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h"
-#include "third_party/blink/renderer/platform/graphics/paint/transform_3d_display_item.h"
-
-namespace blink {
-
-Transform3DRecorder::Transform3DRecorder(GraphicsContext& context,
-                                         const DisplayItemClient& client,
-                                         DisplayItem::Type type,
-                                         const TransformationMatrix& transform,
-                                         const FloatPoint3D& transform_origin)
-    : context_(context), client_(client), type_(type) {
-  if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
-    return;
-  DCHECK(DisplayItem::IsTransform3DType(type));
-  skip_recording_for_identity_transform_ = transform.IsIdentity();
-
-  if (skip_recording_for_identity_transform_)
-    return;
-
-  context_.GetPaintController().CreateAndAppend<BeginTransform3DDisplayItem>(
-      client_, type_, transform, transform_origin);
-}
-
-Transform3DRecorder::~Transform3DRecorder() {
-  if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
-    return;
-  if (skip_recording_for_identity_transform_)
-    return;
-
-  context_.GetPaintController().EndItem<EndTransform3DDisplayItem>(
-      client_, DisplayItem::Transform3DTypeToEndTransform3DType(type_));
-}
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/core/paint/transform_3d_recorder.h b/third_party/blink/renderer/core/paint/transform_3d_recorder.h
deleted file mode 100644
index ecf11f2..0000000
--- a/third_party/blink/renderer/core/paint/transform_3d_recorder.h
+++ /dev/null
@@ -1,37 +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 THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_TRANSFORM_3D_RECORDER_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_TRANSFORM_3D_RECORDER_H_
-
-#include "third_party/blink/renderer/platform/graphics/paint/display_item.h"
-#include "third_party/blink/renderer/platform/wtf/allocator.h"
-
-namespace blink {
-
-class FloatPoint3D;
-class GraphicsContext;
-class TransformationMatrix;
-
-class Transform3DRecorder {
-  STACK_ALLOCATED();
-
- public:
-  Transform3DRecorder(GraphicsContext&,
-                      const DisplayItemClient&,
-                      DisplayItem::Type,
-                      const TransformationMatrix&,
-                      const FloatPoint3D& transform_origin);
-  ~Transform3DRecorder();
-
- private:
-  GraphicsContext& context_;
-  const DisplayItemClient& client_;
-  DisplayItem::Type type_;
-  bool skip_recording_for_identity_transform_;
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_TRANSFORM_3D_RECORDER_H_
diff --git a/third_party/blink/renderer/core/paint/transform_recorder.cc b/third_party/blink/renderer/core/paint/transform_recorder.cc
deleted file mode 100644
index c265273..0000000
--- a/third_party/blink/renderer/core/paint/transform_recorder.cc
+++ /dev/null
@@ -1,37 +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 "third_party/blink/renderer/core/paint/transform_recorder.h"
-
-#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
-#include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h"
-#include "third_party/blink/renderer/platform/graphics/paint/transform_display_item.h"
-
-namespace blink {
-
-TransformRecorder::TransformRecorder(GraphicsContext& context,
-                                     const DisplayItemClient& client,
-                                     const AffineTransform& transform)
-    : context_(context), client_(client) {
-  if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
-    return;
-  skip_recording_for_identity_transform_ = transform.IsIdentity();
-
-  if (skip_recording_for_identity_transform_)
-    return;
-
-  context_.GetPaintController().CreateAndAppend<BeginTransformDisplayItem>(
-      client_, transform);
-}
-
-TransformRecorder::~TransformRecorder() {
-  if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
-    return;
-  if (skip_recording_for_identity_transform_)
-    return;
-
-  context_.GetPaintController().EndItem<EndTransformDisplayItem>(client_);
-}
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/core/paint/transform_recorder.h b/third_party/blink/renderer/core/paint/transform_recorder.h
deleted file mode 100644
index 28955f75..0000000
--- a/third_party/blink/renderer/core/paint/transform_recorder.h
+++ /dev/null
@@ -1,34 +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 THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_TRANSFORM_RECORDER_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_TRANSFORM_RECORDER_H_
-
-#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/platform/graphics/paint/display_item.h"
-#include "third_party/blink/renderer/platform/wtf/allocator.h"
-
-namespace blink {
-
-class GraphicsContext;
-class AffineTransform;
-
-class CORE_EXPORT TransformRecorder {
-  STACK_ALLOCATED();
-
- public:
-  TransformRecorder(GraphicsContext&,
-                    const DisplayItemClient&,
-                    const AffineTransform&);
-  ~TransformRecorder();
-
- private:
-  GraphicsContext& context_;
-  const DisplayItemClient& client_;
-  bool skip_recording_for_identity_transform_;
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_TRANSFORM_RECORDER_H_
diff --git a/third_party/blink/renderer/core/paint/view_painter.cc b/third_party/blink/renderer/core/paint/view_painter.cc
index 6a2380a..50638b0 100644
--- a/third_party/blink/renderer/core/paint/view_painter.cc
+++ b/third_party/blink/renderer/core/paint/view_painter.cc
@@ -15,7 +15,6 @@
 #include "third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h"
 #include "third_party/blink/renderer/core/paint/paint_info.h"
 #include "third_party/blink/renderer/core/paint/paint_layer.h"
-#include "third_party/blink/renderer/core/paint/scroll_recorder.h"
 #include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
 #include "third_party/blink/renderer/platform/graphics/paint/scoped_paint_chunk_properties.h"
 #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
@@ -67,24 +66,16 @@
   const DisplayItemClient* display_item_client = &layout_view_;
 
   base::Optional<ScopedPaintChunkProperties> scoped_scroll_property;
-  base::Optional<ScrollRecorder> scroll_recorder;
   if (BoxModelObjectPainter::
           IsPaintingBackgroundOfPaintContainerIntoScrollingContentsLayer(
               &layout_view_, paint_info)) {
     // Layout overflow, combined with the visible content size.
     background_rect.Unite(layout_view_.DocumentRect());
     display_item_client = layout_view_.Layer()->GraphicsLayerBacking();
-    if (!layout_view_.ScrolledContentOffset().IsZero()) {
-      scroll_recorder.emplace(paint_info.context, layout_view_,
-                              paint_info.phase,
-                              layout_view_.ScrolledContentOffset());
-    }
-    if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled()) {
-      scoped_scroll_property.emplace(
-          paint_info.context.GetPaintController(),
-          layout_view_.FirstFragment().ContentsProperties(),
-          *display_item_client, DisplayItem::kDocumentBackground);
-    }
+    scoped_scroll_property.emplace(
+        paint_info.context.GetPaintController(),
+        layout_view_.FirstFragment().ContentsProperties(), *display_item_client,
+        DisplayItem::kDocumentBackground);
   }
 
   if (DrawingRecorder::UseCachedDrawingIfPossible(
diff --git a/third_party/blink/renderer/core/svg/graphics/filters/svg_fe_image.cc b/third_party/blink/renderer/core/svg/graphics/filters/svg_fe_image.cc
index 9acbfde..c33f9a8d 100644
--- a/third_party/blink/renderer/core/svg/graphics/filters/svg_fe_image.cc
+++ b/third_party/blink/renderer/core/svg/graphics/filters/svg_fe_image.cc
@@ -25,7 +25,6 @@
 
 #include "third_party/blink/renderer/core/layout/layout_object.h"
 #include "third_party/blink/renderer/core/paint/svg_paint_context.h"
-#include "third_party/blink/renderer/core/paint/transform_recorder.h"
 #include "third_party/blink/renderer/core/svg/svg_element.h"
 #include "third_party/blink/renderer/core/svg/svg_length_context.h"
 #include "third_party/blink/renderer/core/svg/svg_uri_reference.h"
diff --git a/third_party/blink/renderer/core/svg/graphics/svg_image.cc b/third_party/blink/renderer/core/svg/graphics/svg_image.cc
index 3acfc2ed..ed611aa 100644
--- a/third_party/blink/renderer/core/svg/graphics/svg_image.cc
+++ b/third_party/blink/renderer/core/svg/graphics/svg_image.cc
@@ -42,9 +42,7 @@
 #include "third_party/blink/renderer/core/layout/layout_view.h"
 #include "third_party/blink/renderer/core/layout/svg/layout_svg_root.h"
 #include "third_party/blink/renderer/core/loader/frame_load_request.h"
-#include "third_party/blink/renderer/core/paint/float_clip_recorder.h"
 #include "third_party/blink/renderer/core/paint/paint_layer.h"
-#include "third_party/blink/renderer/core/paint/transform_recorder.h"
 #include "third_party/blink/renderer/core/style/computed_style.h"
 #include "third_party/blink/renderer/core/svg/animation/smil_time_container.h"
 #include "third_party/blink/renderer/core/svg/graphics/svg_image_chrome_client.h"
@@ -58,7 +56,6 @@
 #include "third_party/blink/renderer/platform/graphics/color.h"
 #include "third_party/blink/renderer/platform/graphics/graphics_context.h"
 #include "third_party/blink/renderer/platform/graphics/image_observer.h"
-#include "third_party/blink/renderer/platform/graphics/paint/clip_recorder.h"
 #include "third_party/blink/renderer/platform/graphics/paint/cull_rect.h"
 #include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
 #include "third_party/blink/renderer/platform/graphics/paint/paint_record.h"
diff --git a/third_party/blink/renderer/devtools/front_end/profiler/HeapSnapshotDataGrids.js b/third_party/blink/renderer/devtools/front_end/profiler/HeapSnapshotDataGrids.js
index f87c6fe..553fb61 100644
--- a/third_party/blink/renderer/devtools/front_end/profiler/HeapSnapshotDataGrids.js
+++ b/third_party/blink/renderer/devtools/front_end/profiler/HeapSnapshotDataGrids.js
@@ -40,6 +40,15 @@
     // TODO(allada) This entire class needs to be converted to use the templates in DataGridNode.
     super(columns);
     this._dataDisplayDelegate = dataDisplayDelegate;
+    const tooltips = [
+      ['distance', ls`Distance from window object`], ['shallowSize', ls`Size of the object itself in bytes`],
+      ['retainedSize', ls`Size of the object plus the graph it retains in bytes`]
+    ];
+    for (const info of tooltips) {
+      const headerCell = this.headerTableHeader(info[0]);
+      if (headerCell)
+        headerCell.setAttribute('title', info[1]);
+    }
 
     /**
      * @type {number}
@@ -555,20 +564,18 @@
    * @param {!Array.<!DataGrid.DataGrid.ColumnDescriptor>=} columns
    */
   constructor(dataDisplayDelegate, columns) {
-    columns =
-        columns || (/** @type {!Array<!DataGrid.DataGrid.ColumnDescriptor>} */ ([
-          {id: 'object', title: Common.UIString('Object'), disclosure: true, sortable: true},
-          {id: 'distance', title: Common.UIString('Distance'), width: '70px', sortable: true, fixedWidth: true},
-          {id: 'shallowSize', title: Common.UIString('Shallow Size'), width: '110px', sortable: true, fixedWidth: true},
-          {
-            id: 'retainedSize',
-            title: Common.UIString('Retained Size'),
-            width: '110px',
-            sortable: true,
-            fixedWidth: true,
-            sort: DataGrid.DataGrid.Order.Descending
-          }
-        ]));
+    columns = columns || (/** @type {!Array<!DataGrid.DataGrid.ColumnDescriptor>} */ ([
+                {id: 'object', title: ls`Object`, disclosure: true, sortable: true},
+                {id: 'distance', title: ls`Distance`, width: '70px', sortable: true, fixedWidth: true},
+                {id: 'shallowSize', title: ls`Shallow Size`, width: '110px', sortable: true, fixedWidth: true}, {
+                  id: 'retainedSize',
+                  title: ls`Retained Size`,
+                  width: '110px',
+                  sortable: true,
+                  fixedWidth: true,
+                  sort: DataGrid.DataGrid.Order.Descending
+                }
+              ]));
     super(dataDisplayDelegate, columns);
   }
 
@@ -607,16 +614,16 @@
    */
   constructor(dataDisplayDelegate) {
     const columns = /** @type {!Array<!DataGrid.DataGrid.ColumnDescriptor>} */ ([
-      {id: 'object', title: Common.UIString('Object'), disclosure: true, sortable: true}, {
+      {id: 'object', title: ls`Object`, disclosure: true, sortable: true}, {
         id: 'distance',
-        title: Common.UIString('Distance'),
+        title: ls`Distance`,
         width: '70px',
         sortable: true,
         fixedWidth: true,
         sort: DataGrid.DataGrid.Order.Ascending
       },
-      {id: 'shallowSize', title: Common.UIString('Shallow Size'), width: '110px', sortable: true, fixedWidth: true},
-      {id: 'retainedSize', title: Common.UIString('Retained Size'), width: '110px', sortable: true, fixedWidth: true}
+      {id: 'shallowSize', title: ls`Shallow Size`, width: '110px', sortable: true, fixedWidth: true},
+      {id: 'retainedSize', title: ls`Retained Size`, width: '110px', sortable: true, fixedWidth: true}
     ]);
     super(dataDisplayDelegate, columns);
   }
@@ -668,12 +675,11 @@
    */
   constructor(dataDisplayDelegate) {
     const columns = /** @type {!Array<!DataGrid.DataGrid.ColumnDescriptor>} */ ([
-      {id: 'object', title: Common.UIString('Constructor'), disclosure: true, sortable: true},
-      {id: 'distance', title: Common.UIString('Distance'), width: '70px', sortable: true, fixedWidth: true},
-      {id: 'count', title: Common.UIString('Objects Count'), width: '100px', sortable: true, fixedWidth: true},
-      {id: 'shallowSize', title: Common.UIString('Shallow Size'), width: '110px', sortable: true, fixedWidth: true}, {
+      {id: 'object', title: ls`Constructor`, disclosure: true, sortable: true},
+      {id: 'distance', title: ls`Distance`, width: '70px', sortable: true, fixedWidth: true},
+      {id: 'shallowSize', title: ls`Shallow Size`, width: '110px', sortable: true, fixedWidth: true}, {
         id: 'retainedSize',
-        title: Common.UIString('Retained Size'),
+        title: ls`Retained Size`,
         width: '110px',
         sort: DataGrid.DataGrid.Order.Descending,
         sortable: true,
@@ -682,15 +688,18 @@
     ]);
     super(dataDisplayDelegate, columns);
     this._profileIndex = -1;
-
     this._objectIdToSelect = null;
   }
 
+  /**
+   * @param {string} sortColumn
+   * @param {boolean} sortAscending
+   * @return {!Array}
+   */
   _sortFields(sortColumn, sortAscending) {
     return {
-      object: ['_name', sortAscending, '_count', false],
-      distance: ['_distance', sortAscending, '_retainedSize', true],
-      count: ['_count', sortAscending, '_name', true],
+      object: ['_name', sortAscending, '_retainedSize', false],
+      distance: ['_distance', sortAscending, '_retainedSize', false],
       shallowSize: ['_shallowSize', sortAscending, '_name', true],
       retainedSize: ['_retainedSize', sortAscending, '_name', true]
     }[sortColumn];
@@ -795,7 +804,6 @@
     this._filterInProgress = nodeFilter;
 
     const aggregates = await this.snapshot.aggregatesWithFilter(nodeFilter);
-
     this._aggregatesReceived(nodeFilter, aggregates);
   }
 
@@ -821,19 +829,19 @@
    */
   constructor(dataDisplayDelegate) {
     const columns = /** @type {!Array<!DataGrid.DataGrid.ColumnDescriptor>} */ ([
-      {id: 'object', title: Common.UIString('Constructor'), disclosure: true, sortable: true},
-      {id: 'addedCount', title: Common.UIString('# New'), width: '75px', sortable: true, fixedWidth: true},
-      {id: 'removedCount', title: Common.UIString('# Deleted'), width: '75px', sortable: true, fixedWidth: true},
-      {id: 'countDelta', title: Common.UIString('# Delta'), width: '65px', sortable: true, fixedWidth: true}, {
+      {id: 'object', title: ls`Constructor`, disclosure: true, sortable: true},
+      {id: 'addedCount', title: ls`# New`, width: '75px', sortable: true, fixedWidth: true},
+      {id: 'removedCount', title: ls`# Deleted`, width: '75px', sortable: true, fixedWidth: true},
+      {id: 'countDelta', title: ls`# Delta`, width: '65px', sortable: true, fixedWidth: true}, {
         id: 'addedSize',
-        title: Common.UIString('Alloc. Size'),
+        title: ls`Alloc. Size`,
         width: '75px',
         sortable: true,
         fixedWidth: true,
         sort: DataGrid.DataGrid.Order.Descending
       },
-      {id: 'removedSize', title: Common.UIString('Freed Size'), width: '75px', sortable: true, fixedWidth: true},
-      {id: 'sizeDelta', title: Common.UIString('Size Delta'), width: '75px', sortable: true, fixedWidth: true}
+      {id: 'removedSize', title: ls`Freed Size`, width: '75px', sortable: true, fixedWidth: true},
+      {id: 'sizeDelta', title: ls`Size Delta`, width: '75px', sortable: true, fixedWidth: true}
     ]);
     super(dataDisplayDelegate, columns);
   }
@@ -901,18 +909,18 @@
    */
   constructor(heapProfilerModel, dataDisplayDelegate) {
     const columns = /** @type {!Array<!DataGrid.DataGrid.ColumnDescriptor>} */ ([
-      {id: 'liveCount', title: Common.UIString('Live Count'), width: '75px', sortable: true, fixedWidth: true},
-      {id: 'count', title: Common.UIString('Count'), width: '65px', sortable: true, fixedWidth: true},
-      {id: 'liveSize', title: Common.UIString('Live Size'), width: '75px', sortable: true, fixedWidth: true},
+      {id: 'liveCount', title: ls`Live Count`, width: '75px', sortable: true, fixedWidth: true},
+      {id: 'count', title: ls`Count`, width: '65px', sortable: true, fixedWidth: true},
+      {id: 'liveSize', title: ls`Live Size`, width: '75px', sortable: true, fixedWidth: true},
       {
         id: 'size',
-        title: Common.UIString('Size'),
+        title: ls`Size`,
         width: '75px',
         sortable: true,
         fixedWidth: true,
         sort: DataGrid.DataGrid.Order.Descending
       },
-      {id: 'name', title: Common.UIString('Function'), disclosure: true, sortable: true},
+      {id: 'name', title: ls`Function`, disclosure: true, sortable: true},
     ]);
     super(dataDisplayDelegate, columns);
     this._heapProfilerModel = heapProfilerModel;
diff --git a/third_party/blink/renderer/devtools/front_end/profiler/HeapSnapshotGridNodes.js b/third_party/blink/renderer/devtools/front_end/profiler/HeapSnapshotGridNodes.js
index 6e454a5..666a3af 100644
--- a/third_party/blink/renderer/devtools/front_end/profiler/HeapSnapshotGridNodes.js
+++ b/third_party/blink/renderer/devtools/front_end/profiler/HeapSnapshotGridNodes.js
@@ -192,19 +192,12 @@
    * @return {!Element}
    */
   _createValueCell(columnId) {
-    const cell = createElement('td');
-    cell.className = 'numeric-column';
+    const cell = UI.html`<td class="numeric-column" />`;
     if (this.dataGrid.snapshot.totalSize !== 0) {
-      const div = createElement('div');
-      const valueSpan = createElement('span');
-      valueSpan.textContent = this.data[columnId];
-      div.appendChild(valueSpan);
+      const div = UI.html`<div><span>${this.data[columnId]}</span></div>`;
       const percentColumn = columnId + '-percent';
       if (percentColumn in this.data) {
-        const percentSpan = createElement('span');
-        percentSpan.className = 'percent-column';
-        percentSpan.textContent = this.data[percentColumn];
-        div.appendChild(percentSpan);
+        div.appendChild(UI.html`<span class="percent-column">${this.data[percentColumn]}</span>`);
         div.classList.add('profile-multiple-values');
       }
       cell.appendChild(div);
@@ -525,15 +518,15 @@
     switch (this._type) {
       case 'concatenated string':
       case 'string':
-        value = '"' + value + '"';
+        value = `"${value}"`;
         valueStyle = 'string';
         break;
       case 'regexp':
-        value = '/' + value + '/';
+        value = `/${value}/`;
         valueStyle = 'string';
         break;
       case 'closure':
-        value = value + '()';
+        value = `${value}()`;
         valueStyle = 'function';
         break;
       case 'bigint':
@@ -546,45 +539,43 @@
         valueStyle = 'null';
         break;
       case 'array':
-        value = (value || '') + '[]';
+        value = (value || ls`(internal array)`) + '[]';
         break;
     }
-    if (this._reachableFromWindow && !this.detachedDOMTreeNode)
-      valueStyle += ' highlight';
-    if (value === 'Object')
-      value = '';
-    if (this.detachedDOMTreeNode)
-      valueStyle += ' detached-dom-tree-node';
     return this._createObjectCellWithValue(valueStyle, value);
   }
 
+  /**
+   * @param {string} valueStyle
+   * @param {string} value
+   * @return {!Element}
+   */
   _createObjectCellWithValue(valueStyle, value) {
-    const cell = createElement('td');
-    cell.className = 'object-column';
-    const div = createElement('div');
-    div.className = 'source-code event-properties';
-    div.style.overflow = 'visible';
-
+    const fragment = UI.Fragment.build`
+        <td class="object-column disclosure">
+          <div class="source-code event-properties" style="overflow: visible" $="container">
+            <span class="value object-value-${valueStyle}">${value}</span>
+            <span class="object-value-id">@${this.snapshotNodeId}</span>
+          </div>
+        </td>`;
+    const div = fragment.$('container');
     this._prefixObjectCell(div);
-
-    const valueSpan = createElement('span');
-    valueSpan.className = 'value object-value-' + valueStyle;
-    valueSpan.textContent = value;
-    div.appendChild(valueSpan);
-
-    const idSpan = createElement('span');
-    idSpan.className = 'object-value-id';
-    idSpan.textContent = ' @' + this.snapshotNodeId;
-    div.appendChild(idSpan);
-
-    cell.appendChild(div);
-    cell.classList.add('disclosure');
+    if (this._reachableFromWindow) {
+      div.appendChild(UI.html
+                      `<span class="heap-object-tag" title="${ls`User object reachable from window`}">🗖</span>`);
+    }
+    if (this.detachedDOMTreeNode)
+      div.appendChild(UI.html`<span class="heap-object-tag" title="${ls`Detached from DOM tree`}">✀</span>`);
+    const cell = fragment.element();
     if (this.depth)
       cell.style.setProperty('padding-left', (this.depth * this.dataGrid.indentWidth) + 'px');
     cell.heapSnapshotNode = this;
     return cell;
   }
 
+  /**
+   * @param {!Element} div
+   */
   _prefixObjectCell(div) {
   }
 
@@ -602,7 +593,7 @@
      * @param {?SDK.RemoteObject} object
      */
     function onResult(object) {
-      fulfill(object || runtimeModel.createRemoteObjectFromPrimitiveValue(Common.UIString('Preview is not available')));
+      fulfill(object || runtimeModel.createRemoteObjectFromPrimitiveValue(ls`Preview is not available`));
     }
 
     const runtimeModel = heapProfilerModel.runtimeModel();
@@ -739,6 +730,7 @@
 
   /**
    * @override
+   * @param {!Element} div
    */
   _prefixObjectCell(div) {
     let name = this._referenceName || '(empty)';
@@ -753,29 +745,20 @@
         nameClass = 'object-value-null';
         break;
       case 'element':
-        name = '[' + name + ']';
+        name = `[${name}]`;
         break;
     }
-
     if (this._cycledWithAncestorGridNode)
-      div.className += ' cycled-ancessor-node';
-
-    const nameSpan = createElement('span');
-    nameSpan.className = nameClass;
-    nameSpan.textContent = name;
-    div.appendChild(nameSpan);
-
-    const separatorSpan = createElement('span');
-    separatorSpan.className = 'grayed';
-    separatorSpan.textContent = this._edgeNodeSeparator();
-    div.appendChild(separatorSpan);
+      div.classList.add('cycled-ancessor-node');
+    div.prepend(UI.html`<span class="${nameClass}">${name}</span>
+                        <span class="grayed">${this._edgeNodeSeparator()}</span>`);
   }
 
   /**
    * @return {string}
    */
   _edgeNodeSeparator() {
-    return ' :: ';
+    return '::';
   }
 };
 
@@ -815,7 +798,7 @@
    * @return {string}
    */
   _edgeNodeSeparator() {
-    return ' in ';
+    return ls`in`;
   }
 
   /**
@@ -960,17 +943,14 @@
     this._retainedSize = aggregate.maxRet;
 
     const snapshot = dataGrid.snapshot;
-    const countPercent = this._count / snapshot.nodeCount * 100.0;
     const retainedSizePercent = this._retainedSize / snapshot.totalSize * 100.0;
     const shallowSizePercent = this._shallowSize / snapshot.totalSize * 100.0;
-
     this.data = {
       'object': className,
       'count': Number.withThousandsSeparator(this._count),
       'distance': this._toUIDistance(this._distance),
       'shallowSize': Number.withThousandsSeparator(this._shallowSize),
       'retainedSize': Number.withThousandsSeparator(this._retainedSize),
-      'count-percent': this._toPercentString(countPercent),
       'shallowSize-percent': this._toPercentString(shallowSizePercent),
       'retainedSize-percent': this._toPercentString(retainedSizePercent)
     };
@@ -1018,7 +998,9 @@
    * @return {!Element}
    */
   createCell(columnId) {
-    const cell = columnId !== 'object' ? this._createValueCell(columnId) : super.createCell(columnId);
+    const cell = columnId === 'object' ? super.createCell(columnId) : this._createValueCell(columnId);
+    if (columnId === 'object' && this._count > 1)
+      cell.appendChild(UI.html`<span class="objects-count">×${this._count}</span>`);
     if (this._searchMatched)
       cell.classList.add('highlight');
     return cell;
@@ -1041,7 +1023,6 @@
     const sortFields = {
       object: ['name', sortAscending, 'id', true],
       distance: ['distance', sortAscending, 'retainedSize', false],
-      count: ['name', true, 'id', true],
       shallowSize: ['selfSize', sortAscending, 'id', true],
       retainedSize: ['retainedSize', sortAscending, 'id', true]
     }[sortColumnId];
diff --git a/third_party/blink/renderer/devtools/front_end/profiler/heapProfiler.css b/third_party/blink/renderer/devtools/front_end/profiler/heapProfiler.css
index b60620d..a68c341 100644
--- a/third_party/blink/renderer/devtools/front_end/profiler/heapProfiler.css
+++ b/third_party/blink/renderer/devtools/front_end/profiler/heapProfiler.css
@@ -52,14 +52,16 @@
     position: static;
 }
 
-.detached-dom-tree-node {
-    background-color: #FF9999;
-}
-
 .heap-snapshot-view .object-value-string {
     white-space: nowrap;
 }
 
+.heap-snapshot-view td.object-column .objects-count {
+    margin-left: 10px;
+    font-size: 11px;
+    color: grey;
+}
+
 .heap-snapshot-view tr:not(.selected) .object-value-id {
     color: grey;
 }
@@ -99,7 +101,15 @@
 }
 
 .heap-snapshot-view tr:not(.selected) td.object-column span.highlight {
-    background-color: rgb(255, 255, 200);
+    background-color: inherit;
+}
+
+.heap-snapshot-view td.object-column span {
+    margin-right: 6px;
+}
+
+.heap-snapshot-view tr:not(.selected) td.object-column span.heap-object-tag {
+    color: #888;
 }
 
 .heap-snapshot-view td.object-column span.grayed {
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object.cc b/third_party/blink/renderer/modules/accessibility/ax_object.cc
index 76ad8cc..e815f6e 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_object.cc
+++ b/third_party/blink/renderer/modules/accessibility/ax_object.cc
@@ -417,7 +417,7 @@
     role_map->Set(String(kRoles[i].aria_role), kRoles[i].webcore_role);
 
   // Grids "ignore" their non-row children during computation of children.
-  role_map->Set("rowgroup", kIgnoredRole);
+  role_map->Set(String("rowgroup"), kIgnoredRole);
 
   return role_map;
 }
diff --git a/third_party/blink/renderer/modules/background_fetch/background_fetch_bridge.cc b/third_party/blink/renderer/modules/background_fetch/background_fetch_bridge.cc
index 3020036..32fa520 100644
--- a/third_party/blink/renderer/modules/background_fetch/background_fetch_bridge.cc
+++ b/third_party/blink/renderer/modules/background_fetch/background_fetch_bridge.cc
@@ -11,7 +11,7 @@
 #include "third_party/blink/renderer/modules/background_fetch/background_fetch_options.h"
 #include "third_party/blink/renderer/modules/background_fetch/background_fetch_registration.h"
 #include "third_party/blink/renderer/modules/background_fetch/background_fetch_type_converters.h"
-#include "third_party/blink/renderer/modules/background_fetch/icon_definition.h"
+#include "third_party/blink/renderer/modules/manifest/image_resource.h"
 
 namespace blink {
 
diff --git a/third_party/blink/renderer/modules/background_fetch/background_fetch_icon_loader.cc b/third_party/blink/renderer/modules/background_fetch/background_fetch_icon_loader.cc
index ff6b1b8..19398ea7 100644
--- a/third_party/blink/renderer/modules/background_fetch/background_fetch_icon_loader.cc
+++ b/third_party/blink/renderer/modules/background_fetch/background_fetch_icon_loader.cc
@@ -10,7 +10,7 @@
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
 #include "third_party/blink/renderer/core/loader/threadable_loader.h"
 #include "third_party/blink/renderer/modules/background_fetch/background_fetch_bridge.h"
-#include "third_party/blink/renderer/modules/background_fetch/icon_definition.h"
+#include "third_party/blink/renderer/modules/manifest/image_resource.h"
 #include "third_party/blink/renderer/platform/graphics/color_behavior.h"
 #include "third_party/blink/renderer/platform/heap/heap_allocator.h"
 #include "third_party/blink/renderer/platform/image-decoders/image_decoder.h"
@@ -40,7 +40,7 @@
 
 void BackgroundFetchIconLoader::Start(BackgroundFetchBridge* bridge,
                                       ExecutionContext* execution_context,
-                                      HeapVector<IconDefinition> icons,
+                                      HeapVector<ManifestImageResource> icons,
                                       IconCallback icon_callback) {
   DCHECK(!stopped_);
   DCHECK_GE(icons.size(), 1u);
@@ -139,7 +139,7 @@
 //
 // Note: If this is an ico file containing multiple sizes, return the best
 // score.
-double BackgroundFetchIconLoader::GetIconScore(IconDefinition icon,
+double BackgroundFetchIconLoader::GetIconScore(ManifestImageResource icon,
                                                const int ideal_size) {
   // Extract sizes from the icon definition, expressed as "<width>x<height>
   // <width>x<height> ...."
diff --git a/third_party/blink/renderer/modules/background_fetch/background_fetch_icon_loader.h b/third_party/blink/renderer/modules/background_fetch/background_fetch_icon_loader.h
index 1f4a3f7..4bba472 100644
--- a/third_party/blink/renderer/modules/background_fetch/background_fetch_icon_loader.h
+++ b/third_party/blink/renderer/modules/background_fetch/background_fetch_icon_loader.h
@@ -10,6 +10,7 @@
 #include "third_party/blink/renderer/core/loader/threadable_loader.h"
 #include "third_party/blink/renderer/core/loader/threadable_loader_client.h"
 #include "third_party/blink/renderer/modules/background_fetch/background_fetch_type_converters.h"
+#include "third_party/blink/renderer/modules/manifest/image_resource.h"
 #include "third_party/blink/renderer/modules/modules_export.h"
 #include "third_party/blink/renderer/platform/shared_buffer.h"
 #include "third_party/skia/include/core/SkBitmap.h"
@@ -17,7 +18,6 @@
 namespace blink {
 
 class BackgroundFetchBridge;
-class IconDefinition;
 struct WebSize;
 
 class MODULES_EXPORT BackgroundFetchIconLoader final
@@ -39,7 +39,7 @@
   // data, and passes the bitmap to the given callback.
   void Start(BackgroundFetchBridge* bridge,
              ExecutionContext* execution_context,
-             HeapVector<IconDefinition>,
+             HeapVector<ManifestImageResource>,
              IconCallback callback);
 
   // Cancels the pending load, if there is one. The |icon_callback_| will not
@@ -75,12 +75,12 @@
 
   // Get a score for the given icon, based on ideal_size. The icon with the
   // highest score is chosen.
-  double GetIconScore(IconDefinition icon, const int ideal_size);
+  double GetIconScore(ManifestImageResource icon, const int ideal_size);
 
   bool stopped_ = false;
   scoped_refptr<SharedBuffer> data_;
   IconCallback icon_callback_;
-  HeapVector<IconDefinition> icons_;
+  HeapVector<ManifestImageResource> icons_;
   Member<ThreadableLoader> threadable_loader_;
 };
 
diff --git a/third_party/blink/renderer/modules/background_fetch/background_fetch_icon_loader_test.cc b/third_party/blink/renderer/modules/background_fetch/background_fetch_icon_loader_test.cc
index c15f676a..df73355f 100644
--- a/third_party/blink/renderer/modules/background_fetch/background_fetch_icon_loader_test.cc
+++ b/third_party/blink/renderer/modules/background_fetch/background_fetch_icon_loader_test.cc
@@ -2,14 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LiICENSE file.
 
+#include "third_party/blink/renderer/modules/background_fetch/background_fetch_icon_loader.h"
+
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/platform/web_size.h"
 #include "third_party/blink/public/platform/web_url.h"
 #include "third_party/blink/public/platform/web_url_loader_mock_factory.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
 #include "third_party/blink/renderer/core/testing/page_test_base.h"
-#include "third_party/blink/renderer/modules/background_fetch/background_fetch_icon_loader.h"
-#include "third_party/blink/renderer/modules/background_fetch/icon_definition.h"
+#include "third_party/blink/renderer/modules/manifest/image_resource.h"
 #include "third_party/blink/renderer/platform/heap/persistent.h"
 #include "third_party/blink/renderer/platform/testing/testing_platform_support.h"
 #include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
@@ -63,27 +64,28 @@
       loaded_ = BackgroundFetchLoadState::kLoadFailed;
   }
 
-  IconDefinition CreateTestIcon(const String& url_str, const String& size) {
+  ManifestImageResource CreateTestIcon(const String& url_str,
+                                       const String& size) {
     KURL url = RegisterMockedURL(url_str);
-    IconDefinition icon;
+    ManifestImageResource icon;
     icon.setSrc(url.GetString());
     icon.setType("image/png");
     icon.setSizes(size);
     return icon;
   }
 
-  int PickRightIcon(HeapVector<IconDefinition> icons,
+  int PickRightIcon(HeapVector<ManifestImageResource> icons,
                     const WebSize& ideal_display_size) {
     loader_->icons_ = std::move(icons);
     return loader_->PickBestIconForDisplay(GetContext(), ideal_display_size);
   }
 
   void LoadIcon(const KURL& url) {
-    IconDefinition icon;
+    ManifestImageResource icon;
     icon.setSrc(url.GetString());
     icon.setType("image/png");
     icon.setSizes("500x500");
-    HeapVector<IconDefinition> icons(1, icon);
+    HeapVector<ManifestImageResource> icons(1, icon);
     loader_->icons_ = std::move(icons);
     loader_->DidGetIconDisplaySizeIfSoLoadIcon(
         GetContext(),
@@ -109,14 +111,14 @@
 }
 
 TEST_F(BackgroundFetchIconLoaderTest, PickRightIconTest) {
-  IconDefinition icon0 =
+  ManifestImageResource icon0 =
       CreateTestIcon(kBackgroundFetchImageLoaderIcon500x500, "500x500");
-  IconDefinition icon1 =
+  ManifestImageResource icon1 =
       CreateTestIcon(kBackgroundFetchImageLoaderIcon48x48, "48x48");
-  IconDefinition icon2 =
+  ManifestImageResource icon2 =
       CreateTestIcon(kBackgroundFetchImageLoaderIcon3000x2000, "3000x2000");
 
-  HeapVector<IconDefinition> icons;
+  HeapVector<ManifestImageResource> icons;
   icons.push_back(icon0);
   icons.push_back(icon1);
   icons.push_back(icon2);
@@ -126,13 +128,14 @@
 }
 
 TEST_F(BackgroundFetchIconLoaderTest, PickRightIconGivenAnyTest) {
-  IconDefinition icon0 =
+  ManifestImageResource icon0 =
       CreateTestIcon(kBackgroundFetchImageLoaderIcon500x500, "500x500");
-  IconDefinition icon1 =
+  ManifestImageResource icon1 =
       CreateTestIcon(kBackgroundFetchImageLoaderIcon48x48, "48x48");
-  IconDefinition icon2 = CreateTestIcon(kBackgroundFetchImageLoaderIcon, "any");
+  ManifestImageResource icon2 =
+      CreateTestIcon(kBackgroundFetchImageLoaderIcon, "any");
 
-  HeapVector<IconDefinition> icons;
+  HeapVector<ManifestImageResource> icons;
   icons.push_back(icon0);
   icons.push_back(icon1);
   icons.push_back(icon2);
@@ -144,13 +147,13 @@
 TEST_F(BackgroundFetchIconLoaderTest, PickRightIconWithTieBreakTest) {
   // Test that if two icons get the same score, the one declared last gets
   // picked.
-  IconDefinition icon0 =
+  ManifestImageResource icon0 =
       CreateTestIcon(kBackgroundFetchImageLoaderIcon500x500, "500x500");
-  IconDefinition icon1 =
+  ManifestImageResource icon1 =
       CreateTestIcon(kBackgroundFetchImageLoaderIcon48x48, "48x48");
-  IconDefinition icon2 =
+  ManifestImageResource icon2 =
       CreateTestIcon(kBackgroundFetchImageLoaderIcon3000x2000, "48x48");
-  HeapVector<IconDefinition> icons;
+  HeapVector<ManifestImageResource> icons;
   icons.push_back(icon0);
   icons.push_back(icon1);
   icons.push_back(icon2);
diff --git a/third_party/blink/renderer/modules/background_fetch/background_fetch_options.idl b/third_party/blink/renderer/modules/background_fetch/background_fetch_options.idl
index 408371e..c80d491 100644
--- a/third_party/blink/renderer/modules/background_fetch/background_fetch_options.idl
+++ b/third_party/blink/renderer/modules/background_fetch/background_fetch_options.idl
@@ -5,7 +5,7 @@
 // https://wicg.github.io/background-fetch/#background-fetch-manager
 
 dictionary BackgroundFetchOptions {
-    sequence<IconDefinition> icons = [];
+    sequence<ImageResource> icons = [];
     DOMString title = "";
     [ImplementedAs=downloadTotal] unsigned long long totalDownloadSize = 0;
     unsigned long long downloadTotal = 0;
diff --git a/third_party/blink/renderer/modules/background_fetch/background_fetch_registration.cc b/third_party/blink/renderer/modules/background_fetch/background_fetch_registration.cc
index aab5aa8a..bf448e1 100644
--- a/third_party/blink/renderer/modules/background_fetch/background_fetch_registration.cc
+++ b/third_party/blink/renderer/modules/background_fetch/background_fetch_registration.cc
@@ -7,8 +7,8 @@
 #include "third_party/blink/renderer/core/dom/dom_exception.h"
 #include "third_party/blink/renderer/core/dom/events/event.h"
 #include "third_party/blink/renderer/modules/background_fetch/background_fetch_bridge.h"
-#include "third_party/blink/renderer/modules/background_fetch/icon_definition.h"
 #include "third_party/blink/renderer/modules/event_target_modules_names.h"
+#include "third_party/blink/renderer/modules/manifest/image_resource.h"
 #include "third_party/blink/renderer/modules/serviceworkers/service_worker_registration.h"
 #include "third_party/blink/renderer/platform/bindings/script_state.h"
 
diff --git a/third_party/blink/renderer/modules/background_fetch/background_fetch_type_converters.cc b/third_party/blink/renderer/modules/background_fetch/background_fetch_type_converters.cc
index 0409251..413559e 100644
--- a/third_party/blink/renderer/modules/background_fetch/background_fetch_type_converters.cc
+++ b/third_party/blink/renderer/modules/background_fetch/background_fetch_type_converters.cc
@@ -6,6 +6,7 @@
 
 #include <utility>
 #include "third_party/blink/renderer/modules/background_fetch/background_fetch_registration.h"
+#include "third_party/blink/renderer/modules/manifest/image_resource_type_converters.h"
 #include "third_party/blink/renderer/platform/heap/heap_allocator.h"
 
 namespace mojo {
@@ -31,11 +32,11 @@
   blink::mojom::blink::BackgroundFetchOptionsPtr mojoOptions =
       blink::mojom::blink::BackgroundFetchOptions::New();
 
-  WTF::Vector<blink::mojom::blink::IconDefinitionPtr> mojoIcons;
+  WTF::Vector<blink::mojom::blink::ManifestImageResourcePtr> mojoIcons;
   mojoIcons.ReserveInitialCapacity(options.icons().size());
 
   for (const auto& icon : options.icons())
-    mojoIcons.push_back(blink::mojom::blink::IconDefinition::From(icon));
+    mojoIcons.push_back(blink::mojom::blink::ManifestImageResource::From(icon));
 
   mojoOptions->icons = std::move(mojoIcons);
   mojoOptions->download_total = options.downloadTotal();
@@ -44,27 +45,4 @@
   return mojoOptions;
 }
 
-blink::IconDefinition
-TypeConverter<blink::IconDefinition, blink::mojom::blink::IconDefinitionPtr>::
-    Convert(const blink::mojom::blink::IconDefinitionPtr& mojoDefinition) {
-  blink::IconDefinition definition;
-  definition.setSrc(mojoDefinition->src);
-  definition.setSizes(mojoDefinition->sizes);
-  definition.setType(mojoDefinition->type);
-
-  return definition;
-}
-
-blink::mojom::blink::IconDefinitionPtr TypeConverter<
-    blink::mojom::blink::IconDefinitionPtr,
-    blink::IconDefinition>::Convert(const blink::IconDefinition& definition) {
-  blink::mojom::blink::IconDefinitionPtr mojoDefinition =
-      blink::mojom::blink::IconDefinition::New();
-  mojoDefinition->src = definition.src();
-  mojoDefinition->sizes = definition.sizes();
-  mojoDefinition->type = definition.type();
-
-  return mojoDefinition;
-}
-
 }  // namespace mojo
diff --git a/third_party/blink/renderer/modules/background_fetch/background_fetch_type_converters.h b/third_party/blink/renderer/modules/background_fetch/background_fetch_type_converters.h
index 3e55cb3b1..7e8d66ee 100644
--- a/third_party/blink/renderer/modules/background_fetch/background_fetch_type_converters.h
+++ b/third_party/blink/renderer/modules/background_fetch/background_fetch_type_converters.h
@@ -7,7 +7,6 @@
 
 #include "third_party/blink/public/platform/modules/background_fetch/background_fetch.mojom-blink.h"
 #include "third_party/blink/renderer/modules/background_fetch/background_fetch_options.h"
-#include "third_party/blink/renderer/modules/background_fetch/icon_definition.h"
 
 namespace blink {
 class BackgroundFetchRegistration;
@@ -29,20 +28,6 @@
       const blink::BackgroundFetchOptions&);
 };
 
-template <>
-struct TypeConverter<blink::IconDefinition,
-                     blink::mojom::blink::IconDefinitionPtr> {
-  static blink::IconDefinition Convert(
-      const blink::mojom::blink::IconDefinitionPtr&);
-};
-
-template <>
-struct TypeConverter<blink::mojom::blink::IconDefinitionPtr,
-                     blink::IconDefinition> {
-  static blink::mojom::blink::IconDefinitionPtr Convert(
-      const blink::IconDefinition&);
-};
-
 }  // namespace mojo
 
 #endif  // THIRD_PARTY_BLINK_RENDERER_MODULES_BACKGROUND_FETCH_BACKGROUND_FETCH_TYPE_CONVERTERS_H_
diff --git a/third_party/blink/renderer/modules/background_fetch/icon_definition.idl b/third_party/blink/renderer/modules/background_fetch/icon_definition.idl
deleted file mode 100644
index 8fc31b5..0000000
--- a/third_party/blink/renderer/modules/background_fetch/icon_definition.idl
+++ /dev/null
@@ -1,11 +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.
-
-// https://wicg.github.io/background-fetch/#background-fetch-manager
-
-dictionary IconDefinition {
-  DOMString src;
-  DOMString sizes;
-  DOMString type;
-};
diff --git a/third_party/blink/renderer/modules/crypto/normalize_algorithm.cc b/third_party/blink/renderer/modules/crypto/normalize_algorithm.cc
index 649ea37..013cfad 100644
--- a/third_party/blink/renderer/modules/crypto/normalize_algorithm.cc
+++ b/third_party/blink/renderer/modules/crypto/normalize_algorithm.cc
@@ -135,7 +135,8 @@
   for (const AlgorithmNameMapping* it = begin; it != end; ++it) {
     if (it->algorithm_name_length != strlen(it->algorithm_name))
       return false;
-    String str(it->algorithm_name, it->algorithm_name_length);
+    String str(it->algorithm_name,
+               static_cast<unsigned>(it->algorithm_name_length));
     if (!str.ContainsOnlyASCII())
       return false;
     if (str.UpperASCII() != str)
diff --git a/third_party/blink/renderer/modules/modules_idl_files.gni b/third_party/blink/renderer/modules/modules_idl_files.gni
index a382ddc..55a4949 100644
--- a/third_party/blink/renderer/modules/modules_idl_files.gni
+++ b/third_party/blink/renderer/modules/modules_idl_files.gni
@@ -460,7 +460,6 @@
           "background_fetch/background_fetch_options.idl",
           "background_fetch/background_fetch_settled_event_init.idl",
           "background_fetch/background_fetched_event_init.idl",
-          "background_fetch/icon_definition.idl",
           "background_sync/sync_event_init.idl",
           "bluetooth/bluetooth_le_scan_filter_init.idl",
           "bluetooth/request_device_options.idl",
diff --git a/third_party/blink/renderer/modules/webaudio/audio_context.cc b/third_party/blink/renderer/modules/webaudio/audio_context.cc
index 5df9bc3..8c053f4 100644
--- a/third_party/blink/renderer/modules/webaudio/audio_context.cc
+++ b/third_party/blink/renderer/modules/webaudio/audio_context.cc
@@ -312,7 +312,18 @@
 }
 
 double AudioContext::baseLatency() const {
-  return FramesPerBuffer() / static_cast<double>(sampleRate());
+  DCHECK(IsMainThread());
+  DCHECK(destination());
+
+  // TODO(hongchan): Due to the incompatible constructor between
+  // AudioDestinationNode and DefaultAudioDestinationNode, casting directly from
+  // |destination()| is impossible. This is a temporary workaround until the
+  // refactoring is completed.
+  DefaultAudioDestinationHandler& destination_handler =
+      static_cast<DefaultAudioDestinationHandler&>(
+          destination()->GetAudioDestinationHandler());
+  return destination_handler.GetFramesPerBuffer() /
+         static_cast<double>(sampleRate());
 }
 
 void AudioContext::NotifySourceNodeStart() {
diff --git a/third_party/blink/renderer/modules/webaudio/audio_destination_node.h b/third_party/blink/renderer/modules/webaudio/audio_destination_node.h
index d521c86..06a49a2 100644
--- a/third_party/blink/renderer/modules/webaudio/audio_destination_node.h
+++ b/third_party/blink/renderer/modules/webaudio/audio_destination_node.h
@@ -72,9 +72,6 @@
   size_t CallbackBufferSize() const override = 0;
   virtual double SampleRate() const = 0;
 
-  // Returns the audio buffer size in frames used by the AudioContext.
-  virtual int FramesPerBuffer() const = 0;
-
  protected:
   // Counts the number of sample-frames processed by the destination.
   size_t current_sample_frame_;
diff --git a/third_party/blink/renderer/modules/webaudio/base_audio_context.h b/third_party/blink/renderer/modules/webaudio/base_audio_context.h
index 206c636..8b4894b 100644
--- a/third_party/blink/renderer/modules/webaudio/base_audio_context.h
+++ b/third_party/blink/renderer/modules/webaudio/base_audio_context.h
@@ -147,12 +147,6 @@
                : ClosedContextSampleRate();
   }
 
-  float FramesPerBuffer() const {
-    return destination_node_ ? destination_node_->GetAudioDestinationHandler()
-                                   .FramesPerBuffer()
-                             : 0;
-  }
-
   size_t CallbackBufferSize() const {
     return destination_node_ ? destination_node_->Handler().CallbackBufferSize()
                              : 0;
diff --git a/third_party/blink/renderer/modules/webaudio/default_audio_destination_node.cc b/third_party/blink/renderer/modules/webaudio/default_audio_destination_node.cc
index 7f334e59..d2d7eb7 100644
--- a/third_party/blink/renderer/modules/webaudio/default_audio_destination_node.cc
+++ b/third_party/blink/renderer/modules/webaudio/default_audio_destination_node.cc
@@ -171,7 +171,7 @@
   return destination_ ? destination_->SampleRate() : 0;
 }
 
-int DefaultAudioDestinationHandler::FramesPerBuffer() const {
+int DefaultAudioDestinationHandler::GetFramesPerBuffer() const {
   return destination_ ? destination_->FramesPerBuffer() : 0;
 }
 
diff --git a/third_party/blink/renderer/modules/webaudio/default_audio_destination_node.h b/third_party/blink/renderer/modules/webaudio/default_audio_destination_node.h
index 3ef08a3..a46f41d 100644
--- a/third_party/blink/renderer/modules/webaudio/default_audio_destination_node.h
+++ b/third_party/blink/renderer/modules/webaudio/default_audio_destination_node.h
@@ -58,7 +58,9 @@
   // Returns the rendering callback buffer size.
   size_t CallbackBufferSize() const override;
   double SampleRate() const override;
-  int FramesPerBuffer() const override;
+
+  // Returns a given frames-per-buffer size from audio infra.
+  int GetFramesPerBuffer() const;
 
   double TailTime() const override { return 0; }
   double LatencyTime() const override { return 0; }
@@ -87,7 +89,7 @@
   static DefaultAudioDestinationNode* Create(BaseAudioContext*,
                                              const WebAudioLatencyHint&);
 
-  size_t CallbackBufferSize() const { return Handler().CallbackBufferSize(); };
+  size_t CallbackBufferSize() const { return Handler().CallbackBufferSize(); }
 
  private:
   explicit DefaultAudioDestinationNode(BaseAudioContext&,
diff --git a/third_party/blink/renderer/modules/webaudio/offline_audio_destination_node.h b/third_party/blink/renderer/modules/webaudio/offline_audio_destination_node.h
index 1928524..4cf020d 100644
--- a/third_party/blink/renderer/modules/webaudio/offline_audio_destination_node.h
+++ b/third_party/blink/renderer/modules/webaudio/offline_audio_destination_node.h
@@ -71,10 +71,6 @@
   size_t CallbackBufferSize() const override;
 
   double SampleRate() const override { return sample_rate_; }
-  int FramesPerBuffer() const override {
-    NOTREACHED();
-    return 0;
-  }
 
   size_t RenderQuantumFrames() const {
     return AudioUtilities::kRenderQuantumFrames;
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 09f25b5d..bfd415d7 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
@@ -4487,11 +4487,12 @@
                                            max_name_length, &length, &size,
                                            &type, name.get());
 
-  if (length == 0 || size == 0 || type == 0) {
+  if (length <= 0 || size == 0 || type == 0) {
     return nullptr;
   }
 
-  return WebGLActiveInfo::Create(String(name.get(), length), type, size);
+  return WebGLActiveInfo::Create(
+      String(name.get(), static_cast<uint32_t>(length)), type, size);
 }
 
 void WebGL2RenderingContextBase::pauseTransformFeedback() {
@@ -4879,7 +4880,9 @@
                                          uniform_block_index, max_name_length,
                                          &length, name.get());
 
-  return String(name.get(), length);
+  if (length <= 0)
+    return String();
+  return String(name.get(), static_cast<uint32_t>(length));
 }
 
 void WebGL2RenderingContextBase::uniformBlockBinding(
diff --git a/third_party/blink/renderer/platform/BUILD.gn b/third_party/blink/renderer/platform/BUILD.gn
index 1d5229f..b8f5064 100644
--- a/third_party/blink/renderer/platform/BUILD.gn
+++ b/third_party/blink/renderer/platform/BUILD.gn
@@ -994,20 +994,8 @@
     "graphics/offscreen_canvas_placeholder.h",
     "graphics/offscreen_canvas_resource_provider.cc",
     "graphics/offscreen_canvas_resource_provider.h",
-    "graphics/paint/clip_display_item.cc",
-    "graphics/paint/clip_display_item.h",
     "graphics/paint/clip_paint_property_node.cc",
     "graphics/paint/clip_paint_property_node.h",
-    "graphics/paint/clip_path_display_item.cc",
-    "graphics/paint/clip_path_display_item.h",
-    "graphics/paint/clip_path_recorder.cc",
-    "graphics/paint/clip_path_recorder.h",
-    "graphics/paint/clip_recorder.cc",
-    "graphics/paint/clip_recorder.h",
-    "graphics/paint/compositing_display_item.cc",
-    "graphics/paint/compositing_display_item.h",
-    "graphics/paint/compositing_recorder.cc",
-    "graphics/paint/compositing_recorder.h",
     "graphics/paint/cull_rect.cc",
     "graphics/paint/cull_rect.h",
     "graphics/paint/display_item.cc",
@@ -1023,10 +1011,6 @@
     "graphics/paint/drawing_recorder.h",
     "graphics/paint/effect_paint_property_node.cc",
     "graphics/paint/effect_paint_property_node.h",
-    "graphics/paint/filter_display_item.cc",
-    "graphics/paint/filter_display_item.h",
-    "graphics/paint/float_clip_display_item.cc",
-    "graphics/paint/float_clip_display_item.h",
     "graphics/paint/float_clip_rect.h",
     "graphics/paint/foreign_layer_display_item.cc",
     "graphics/paint/foreign_layer_display_item.h",
@@ -1071,17 +1055,11 @@
     "graphics/paint/ref_counted_property_tree_state.h",
     "graphics/paint/scoped_display_item_fragment.h",
     "graphics/paint/scoped_paint_chunk_properties.h",
-    "graphics/paint/scroll_display_item.cc",
-    "graphics/paint/scroll_display_item.h",
     "graphics/paint/scroll_hit_test_display_item.cc",
     "graphics/paint/scroll_hit_test_display_item.h",
     "graphics/paint/scroll_paint_property_node.cc",
     "graphics/paint/scroll_paint_property_node.h",
     "graphics/paint/subsequence_recorder.h",
-    "graphics/paint/transform_3d_display_item.cc",
-    "graphics/paint/transform_3d_display_item.h",
-    "graphics/paint/transform_display_item.cc",
-    "graphics/paint/transform_display_item.h",
     "graphics/paint/transform_paint_property_node.cc",
     "graphics/paint/transform_paint_property_node.h",
     "graphics/paint_generated_image.cc",
diff --git a/third_party/blink/renderer/platform/bindings/string_resource.cc b/third_party/blink/renderer/platform/bindings/string_resource.cc
index 862bf64..00677094 100644
--- a/third_party/blink/renderer/platform/bindings/string_resource.cc
+++ b/third_party/blink/renderer/platform/bindings/string_resource.cc
@@ -71,7 +71,7 @@
   if (length <= kInlineBufferSize) {
     typename V8StringTrait::CharType inline_buffer[kInlineBufferSize];
     V8StringTrait::Write(v8_string, inline_buffer, length);
-    return AtomicString(inline_buffer, length);
+    return AtomicString(inline_buffer, static_cast<unsigned>(length));
   }
   typename V8StringTrait::CharType* buffer;
   String string = String::CreateUninitialized(length, buffer);
diff --git a/third_party/blink/renderer/platform/geometry/double_size.h b/third_party/blink/renderer/platform/geometry/double_size.h
index 081ef03..917c81c4c 100644
--- a/third_party/blink/renderer/platform/geometry/double_size.h
+++ b/third_party/blink/renderer/platform/geometry/double_size.h
@@ -88,13 +88,12 @@
 }
 
 inline IntSize RoundedIntSize(const DoubleSize& p) {
-  return IntSize(clampTo<int>(roundf(p.Width())),
-                 clampTo<int>(roundf(p.Height())));
+  return IntSize(clampTo<int>(round(p.Width())),
+                 clampTo<int>(round(p.Height())));
 }
 
 inline IntSize ExpandedIntSize(const DoubleSize& p) {
-  return IntSize(clampTo<int>(ceilf(p.Width())),
-                 clampTo<int>(ceilf(p.Height())));
+  return IntSize(clampTo<int>(ceil(p.Width())), clampTo<int>(ceil(p.Height())));
 }
 
 inline FloatSize ToFloatSize(const DoubleSize& p) {
diff --git a/third_party/blink/renderer/platform/graphics/paint/clip_display_item.cc b/third_party/blink/renderer/platform/graphics/paint/clip_display_item.cc
deleted file mode 100644
index 0d64b57..0000000
--- a/third_party/blink/renderer/platform/graphics/paint/clip_display_item.cc
+++ /dev/null
@@ -1,66 +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 "third_party/blink/renderer/platform/graphics/paint/clip_display_item.h"
-
-#include "cc/paint/display_item_list.h"
-#include "third_party/blink/renderer/platform/geometry/float_rounded_rect.h"
-#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
-#include "third_party/skia/include/core/SkScalar.h"
-
-namespace blink {
-
-void ClipDisplayItem::Replay(GraphicsContext& context) const {
-  context.Save();
-
-  // RoundedInnerRectClipper only cares about rounded-rect clips,
-  // and passes an "infinite" rect clip; there is no reason to apply this clip.
-  // TODO(fmalita): convert RoundedInnerRectClipper to a better suited
-  //   DisplayItem so we don't have to special-case its semantics.
-  if (clip_rect_ != LayoutRect::InfiniteIntRect())
-    context.ClipRect(clip_rect_, kAntiAliased);
-
-  for (const FloatRoundedRect& rounded_rect : rounded_rect_clips_)
-    context.ClipRoundedRect(rounded_rect);
-}
-
-void ClipDisplayItem::AppendToDisplayItemList(const FloatSize&,
-                                              cc::DisplayItemList& list) const {
-  list.StartPaint();
-  list.push<cc::SaveOp>();
-  list.push<cc::ClipRectOp>(clip_rect_, SkClipOp::kIntersect,
-                            /*antialias=*/true);
-  for (const FloatRoundedRect& rrect : rounded_rect_clips_) {
-    SkRRect skrrect = rrect;
-    if (skrrect.isRect()) {
-      list.push<cc::ClipRectOp>(skrrect.rect(), SkClipOp::kIntersect,
-                                /*antialias=*/true);
-    } else {
-      list.push<cc::ClipRRectOp>(skrrect, SkClipOp::kIntersect,
-                                 /*antialias=*/true);
-    }
-  }
-  list.EndPaintOfPairedBegin();
-}
-
-void EndClipDisplayItem::Replay(GraphicsContext& context) const {
-  context.Restore();
-}
-
-void EndClipDisplayItem::AppendToDisplayItemList(
-    const FloatSize&,
-    cc::DisplayItemList& list) const {
-  list.StartPaint();
-  list.push<cc::RestoreOp>();
-  list.EndPaintOfPairedEnd();
-}
-
-#if DCHECK_IS_ON()
-void ClipDisplayItem::PropertiesAsJSON(JSONObject& json) const {
-  DisplayItem::PropertiesAsJSON(json);
-  json.SetString("clipRect", clip_rect_.ToString());
-}
-#endif
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/platform/graphics/paint/clip_display_item.h b/third_party/blink/renderer/platform/graphics/paint/clip_display_item.h
deleted file mode 100644
index 006f66b..0000000
--- a/third_party/blink/renderer/platform/graphics/paint/clip_display_item.h
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_CLIP_DISPLAY_ITEM_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_CLIP_DISPLAY_ITEM_H_
-
-#include "SkRegion.h"
-#include "third_party/blink/renderer/platform/geometry/float_rounded_rect.h"
-#include "third_party/blink/renderer/platform/geometry/int_rect.h"
-#include "third_party/blink/renderer/platform/graphics/paint/display_item.h"
-#include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/wtf/vector.h"
-
-namespace blink {
-
-class PLATFORM_EXPORT ClipDisplayItem final : public PairedBeginDisplayItem {
- public:
-  ClipDisplayItem(const DisplayItemClient& client,
-                  Type type,
-                  const IntRect& clip_rect)
-      : PairedBeginDisplayItem(client, type, sizeof(*this)),
-        clip_rect_(clip_rect) {
-    DCHECK(IsClipType(type));
-  }
-
-  ClipDisplayItem(const DisplayItemClient& client,
-                  Type type,
-                  const IntRect& clip_rect,
-                  Vector<FloatRoundedRect>& rounded_rect_clips)
-      : ClipDisplayItem(client, type, clip_rect) {
-    rounded_rect_clips_.swap(rounded_rect_clips);
-  }
-
-  void Replay(GraphicsContext&) const override;
-  void AppendToDisplayItemList(const FloatSize&,
-                               cc::DisplayItemList&) const override;
-
- private:
-#if DCHECK_IS_ON()
-  void PropertiesAsJSON(JSONObject&) const override;
-#endif
-  bool Equals(const DisplayItem& other) const final {
-    return DisplayItem::Equals(other) &&
-           clip_rect_ ==
-               static_cast<const ClipDisplayItem&>(other).clip_rect_ &&
-           rounded_rect_clips_ ==
-               static_cast<const ClipDisplayItem&>(other).rounded_rect_clips_;
-  }
-
-  const IntRect clip_rect_;
-  Vector<FloatRoundedRect> rounded_rect_clips_;
-};
-
-class PLATFORM_EXPORT EndClipDisplayItem final : public PairedEndDisplayItem {
- public:
-  EndClipDisplayItem(const DisplayItemClient& client, Type type)
-      : PairedEndDisplayItem(client, type, sizeof(*this)) {
-    DCHECK(IsEndClipType(type));
-  }
-
-  void Replay(GraphicsContext&) const override;
-  void AppendToDisplayItemList(const FloatSize&,
-                               cc::DisplayItemList&) const override;
-
- private:
-#if DCHECK_IS_ON()
-  bool IsEndAndPairedWith(DisplayItem::Type other_type) const final {
-    return DisplayItem::IsClipType(other_type);
-  }
-#endif
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_CLIP_DISPLAY_ITEM_H_
diff --git a/third_party/blink/renderer/platform/graphics/paint/clip_path_display_item.cc b/third_party/blink/renderer/platform/graphics/paint/clip_path_display_item.cc
deleted file mode 100644
index ee7c9fe..0000000
--- a/third_party/blink/renderer/platform/graphics/paint/clip_path_display_item.cc
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/platform/graphics/paint/clip_path_display_item.h"
-
-#include "cc/paint/display_item_list.h"
-#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
-#include "third_party/blink/renderer/platform/graphics/path.h"
-#include "third_party/skia/include/core/SkScalar.h"
-
-namespace blink {
-
-void BeginClipPathDisplayItem::Replay(GraphicsContext& context) const {
-  context.Save();
-  context.ClipPath(clip_path_, kAntiAliased);
-}
-
-void BeginClipPathDisplayItem::AppendToDisplayItemList(
-    const FloatSize&,
-    cc::DisplayItemList& list) const {
-  list.StartPaint();
-  list.push<cc::SaveOp>();
-  list.push<cc::ClipPathOp>(clip_path_, SkClipOp::kIntersect,
-                            /*antialias=*/true);
-  list.EndPaintOfPairedBegin();
-}
-
-void EndClipPathDisplayItem::Replay(GraphicsContext& context) const {
-  context.Restore();
-}
-
-void EndClipPathDisplayItem::AppendToDisplayItemList(
-    const FloatSize&,
-    cc::DisplayItemList& list) const {
-  list.StartPaint();
-  list.push<cc::RestoreOp>();
-  list.EndPaintOfPairedEnd();
-}
-
-#if DCHECK_IS_ON()
-void BeginClipPathDisplayItem::PropertiesAsJSON(JSONObject& json) const {
-  DisplayItem::PropertiesAsJSON(json);
-  json.SetInteger("pathVerbs", clip_path_.countVerbs());
-  json.SetInteger("pathPoints", clip_path_.countPoints());
-  json.SetString("windRule",
-                 clip_path_.getFillType() == SkPath::kWinding_FillType
-                     ? "nonzero"
-                     : "evenodd");
-}
-
-#endif
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/platform/graphics/paint/clip_path_display_item.h b/third_party/blink/renderer/platform/graphics/paint/clip_path_display_item.h
deleted file mode 100644
index b8ce24a..0000000
--- a/third_party/blink/renderer/platform/graphics/paint/clip_path_display_item.h
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_CLIP_PATH_DISPLAY_ITEM_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_CLIP_PATH_DISPLAY_ITEM_H_
-
-#include "third_party/blink/renderer/platform/graphics/paint/display_item.h"
-#include "third_party/blink/renderer/platform/graphics/path.h"
-#include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/skia/include/core/SkPath.h"
-
-namespace blink {
-
-class PLATFORM_EXPORT BeginClipPathDisplayItem final
-    : public PairedBeginDisplayItem {
- public:
-  BeginClipPathDisplayItem(const DisplayItemClient& client,
-                           const Path& clip_path)
-      : PairedBeginDisplayItem(client, kBeginClipPath, sizeof(*this)),
-        clip_path_(clip_path.GetSkPath()) {}
-
-  void Replay(GraphicsContext&) const override;
-  void AppendToDisplayItemList(const FloatSize&,
-                               cc::DisplayItemList&) const override;
-
- private:
-#if DCHECK_IS_ON()
-  void PropertiesAsJSON(JSONObject&) const override;
-#endif
-  bool Equals(const DisplayItem& other) const final {
-    return DisplayItem::Equals(other) &&
-           clip_path_ ==
-               static_cast<const BeginClipPathDisplayItem&>(other).clip_path_;
-  }
-
-  const SkPath clip_path_;
-};
-
-class PLATFORM_EXPORT EndClipPathDisplayItem final
-    : public PairedEndDisplayItem {
- public:
-  EndClipPathDisplayItem(const DisplayItemClient& client)
-      : PairedEndDisplayItem(client, kEndClipPath, sizeof(*this)) {}
-
-  void Replay(GraphicsContext&) const override;
-  void AppendToDisplayItemList(const FloatSize&,
-                               cc::DisplayItemList&) const override;
-
- private:
-#if DCHECK_IS_ON()
-  bool IsEndAndPairedWith(DisplayItem::Type other_type) const final {
-    return other_type == kBeginClipPath;
-  }
-#endif
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_CLIP_PATH_DISPLAY_ITEM_H_
diff --git a/third_party/blink/renderer/platform/graphics/paint/clip_path_recorder.cc b/third_party/blink/renderer/platform/graphics/paint/clip_path_recorder.cc
deleted file mode 100644
index 926a68a..0000000
--- a/third_party/blink/renderer/platform/graphics/paint/clip_path_recorder.cc
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/platform/graphics/paint/clip_path_recorder.h"
-
-#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
-#include "third_party/blink/renderer/platform/graphics/paint/clip_path_display_item.h"
-#include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h"
-
-namespace blink {
-
-ClipPathRecorder::ClipPathRecorder(GraphicsContext& context,
-                                   const DisplayItemClient& client,
-                                   const Path& clip_path)
-    : context_(context), client_(client) {
-  if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
-    return;
-  context_.GetPaintController().CreateAndAppend<BeginClipPathDisplayItem>(
-      client_, clip_path);
-}
-
-ClipPathRecorder::~ClipPathRecorder() {
-  if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
-    return;
-  context_.GetPaintController().EndItem<EndClipPathDisplayItem>(client_);
-}
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/platform/graphics/paint/clip_path_recorder.h b/third_party/blink/renderer/platform/graphics/paint/clip_path_recorder.h
deleted file mode 100644
index 948230c..0000000
--- a/third_party/blink/renderer/platform/graphics/paint/clip_path_recorder.h
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_CLIP_PATH_RECORDER_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_CLIP_PATH_RECORDER_H_
-
-#include "base/macros.h"
-#include "third_party/blink/renderer/platform/graphics/paint/display_item_client.h"
-#include "third_party/blink/renderer/platform/graphics/path.h"
-#include "third_party/blink/renderer/platform/wtf/allocator.h"
-
-namespace blink {
-
-class GraphicsContext;
-
-class PLATFORM_EXPORT ClipPathRecorder {
-  USING_FAST_MALLOC(ClipPathRecorder);
-
- public:
-  ClipPathRecorder(GraphicsContext&, const DisplayItemClient&, const Path&);
-  ~ClipPathRecorder();
-
- private:
-  GraphicsContext& context_;
-  const DisplayItemClient& client_;
-
-  DISALLOW_COPY_AND_ASSIGN(ClipPathRecorder);
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_CLIP_PATH_RECORDER_H_
diff --git a/third_party/blink/renderer/platform/graphics/paint/clip_recorder.cc b/third_party/blink/renderer/platform/graphics/paint/clip_recorder.cc
deleted file mode 100644
index 848fc7e..0000000
--- a/third_party/blink/renderer/platform/graphics/paint/clip_recorder.cc
+++ /dev/null
@@ -1,31 +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 "third_party/blink/renderer/platform/graphics/paint/clip_recorder.h"
-
-#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
-#include "third_party/blink/renderer/platform/graphics/paint/clip_display_item.h"
-#include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h"
-
-namespace blink {
-
-ClipRecorder::ClipRecorder(GraphicsContext& context,
-                           const DisplayItemClient& client,
-                           DisplayItem::Type type,
-                           const IntRect& clip_rect)
-    : client_(client), context_(context), type_(type) {
-  if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
-    return;
-  context_.GetPaintController().CreateAndAppend<ClipDisplayItem>(client_, type,
-                                                                 clip_rect);
-}
-
-ClipRecorder::~ClipRecorder() {
-  if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
-    return;
-  context_.GetPaintController().EndItem<EndClipDisplayItem>(
-      client_, DisplayItem::ClipTypeToEndClipType(type_));
-}
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/platform/graphics/paint/clip_recorder.h b/third_party/blink/renderer/platform/graphics/paint/clip_recorder.h
deleted file mode 100644
index 74f1a69..0000000
--- a/third_party/blink/renderer/platform/graphics/paint/clip_recorder.h
+++ /dev/null
@@ -1,36 +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 THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_CLIP_RECORDER_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_CLIP_RECORDER_H_
-
-#include "base/macros.h"
-#include "third_party/blink/renderer/platform/graphics/paint/display_item.h"
-#include "third_party/blink/renderer/platform/wtf/allocator.h"
-
-namespace blink {
-
-class GraphicsContext;
-
-class PLATFORM_EXPORT ClipRecorder {
-  DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
-
- public:
-  ClipRecorder(GraphicsContext&,
-               const DisplayItemClient&,
-               DisplayItem::Type,
-               const IntRect& clip_rect);
-  ~ClipRecorder();
-
- private:
-  const DisplayItemClient& client_;
-  GraphicsContext& context_;
-  DisplayItem::Type type_;
-
-  DISALLOW_COPY_AND_ASSIGN(ClipRecorder);
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_CLIP_RECORDER_H_
diff --git a/third_party/blink/renderer/platform/graphics/paint/compositing_display_item.cc b/third_party/blink/renderer/platform/graphics/paint/compositing_display_item.cc
deleted file mode 100644
index 48b9c4f..0000000
--- a/third_party/blink/renderer/platform/graphics/paint/compositing_display_item.cc
+++ /dev/null
@@ -1,77 +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 "third_party/blink/renderer/platform/graphics/paint/compositing_display_item.h"
-
-#include "cc/paint/display_item_list.h"
-#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
-#include "third_party/blink/renderer/platform/graphics/skia/skia_utils.h"
-
-namespace blink {
-
-void BeginCompositingDisplayItem::Replay(GraphicsContext& context) const {
-  context.BeginLayer(opacity_, xfer_mode_, has_bounds_ ? &bounds_ : nullptr,
-                     color_filter_);
-}
-
-void BeginCompositingDisplayItem::AppendToDisplayItemList(
-    const FloatSize&,
-    cc::DisplayItemList& list) const {
-  DCHECK_GE(opacity_, 0.f);
-  DCHECK_LE(opacity_, 1.f);
-
-  // TODO(ajuma): This should really be rounding instead of flooring the alpha
-  // value, but that breaks slimming paint reftests.
-  auto alpha = static_cast<uint8_t>(gfx::ToFlooredInt(255 * opacity_));
-  sk_sp<SkColorFilter> color_filter =
-      GraphicsContext::WebCoreColorFilterToSkiaColorFilter(color_filter_);
-  SkRect sk_bounds = bounds_;
-  SkRect* maybe_bounds = has_bounds_ ? &sk_bounds : nullptr;
-
-  if (xfer_mode_ == SkBlendMode::kSrcOver && !color_filter) {
-    list.StartPaint();
-    list.push<cc::SaveLayerAlphaOp>(maybe_bounds, alpha, false);
-    if (maybe_bounds) {
-      list.push<cc::ClipRectOp>(sk_bounds, SkClipOp::kIntersect, false);
-    }
-    list.EndPaintOfPairedBegin();
-    return;
-  }
-
-  cc::PaintFlags flags;
-  flags.setBlendMode(xfer_mode_);
-  flags.setAlpha(alpha);
-  flags.setColorFilter(std::move(color_filter));
-
-  list.StartPaint();
-  list.push<cc::SaveLayerOp>(maybe_bounds, &flags);
-  if (maybe_bounds) {
-    list.push<cc::ClipRectOp>(sk_bounds, SkClipOp::kIntersect, false);
-  }
-  list.EndPaintOfPairedBegin();
-}
-
-#if DCHECK_IS_ON()
-void BeginCompositingDisplayItem::PropertiesAsJSON(JSONObject& json) const {
-  DisplayItem::PropertiesAsJSON(json);
-  json.SetInteger("xferMode", static_cast<int>(xfer_mode_));
-  json.SetDouble("opacity", opacity_);
-  if (has_bounds_)
-    json.SetString("bounds", bounds_.ToString());
-}
-#endif
-
-void EndCompositingDisplayItem::Replay(GraphicsContext& context) const {
-  context.EndLayer();
-}
-
-void EndCompositingDisplayItem::AppendToDisplayItemList(
-    const FloatSize&,
-    cc::DisplayItemList& list) const {
-  list.StartPaint();
-  list.push<cc::RestoreOp>();
-  list.EndPaintOfPairedEnd();
-}
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/platform/graphics/paint/compositing_display_item.h b/third_party/blink/renderer/platform/graphics/paint/compositing_display_item.h
deleted file mode 100644
index fb2e26c..0000000
--- a/third_party/blink/renderer/platform/graphics/paint/compositing_display_item.h
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_COMPOSITING_DISPLAY_ITEM_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_COMPOSITING_DISPLAY_ITEM_H_
-
-#include "third_party/blink/renderer/platform/geometry/float_rect.h"
-#include "third_party/blink/renderer/platform/graphics/graphics_types.h"
-#include "third_party/blink/renderer/platform/graphics/paint/display_item.h"
-#include "third_party/skia/include/core/SkBlendMode.h"
-
-namespace blink {
-
-class PLATFORM_EXPORT BeginCompositingDisplayItem final
-    : public PairedBeginDisplayItem {
- public:
-  BeginCompositingDisplayItem(const DisplayItemClient& client,
-                              const SkBlendMode xfer_mode,
-                              const float opacity,
-                              const FloatRect* bounds,
-                              ColorFilter color_filter = kColorFilterNone)
-      : PairedBeginDisplayItem(client, kBeginCompositing, sizeof(*this)),
-        xfer_mode_(xfer_mode),
-        opacity_(opacity),
-        has_bounds_(bounds),
-        color_filter_(color_filter) {
-    if (bounds)
-      bounds_ = FloatRect(*bounds);
-  }
-
-  void Replay(GraphicsContext&) const override;
-  void AppendToDisplayItemList(const FloatSize&,
-                               cc::DisplayItemList&) const override;
-
- private:
-#if DCHECK_IS_ON()
-  void PropertiesAsJSON(JSONObject&) const override;
-#endif
-  bool Equals(const DisplayItem& other) const final {
-    return DisplayItem::Equals(other) &&
-           xfer_mode_ == static_cast<const BeginCompositingDisplayItem&>(other)
-                             .xfer_mode_ &&
-           opacity_ == static_cast<const BeginCompositingDisplayItem&>(other)
-                           .opacity_ &&
-           has_bounds_ == static_cast<const BeginCompositingDisplayItem&>(other)
-                              .has_bounds_ &&
-           bounds_ ==
-               static_cast<const BeginCompositingDisplayItem&>(other).bounds_ &&
-           color_filter_ ==
-               static_cast<const BeginCompositingDisplayItem&>(other)
-                   .color_filter_;
-  }
-
-  const SkBlendMode xfer_mode_;
-  const float opacity_;
-  bool has_bounds_;
-  FloatRect bounds_;
-  ColorFilter color_filter_;
-};
-
-class PLATFORM_EXPORT EndCompositingDisplayItem final
-    : public PairedEndDisplayItem {
- public:
-  EndCompositingDisplayItem(const DisplayItemClient& client)
-      : PairedEndDisplayItem(client, kEndCompositing, sizeof(*this)) {}
-
-  void Replay(GraphicsContext&) const override;
-  void AppendToDisplayItemList(const FloatSize&,
-                               cc::DisplayItemList&) const override;
-
- private:
-#if DCHECK_IS_ON()
-  bool IsEndAndPairedWith(DisplayItem::Type other_type) const final {
-    return other_type == kBeginCompositing;
-  }
-#endif
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_COMPOSITING_DISPLAY_ITEM_H_
diff --git a/third_party/blink/renderer/platform/graphics/paint/compositing_recorder.cc b/third_party/blink/renderer/platform/graphics/paint/compositing_recorder.cc
deleted file mode 100644
index 7ea9597..0000000
--- a/third_party/blink/renderer/platform/graphics/paint/compositing_recorder.cc
+++ /dev/null
@@ -1,36 +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 "third_party/blink/renderer/platform/graphics/paint/compositing_recorder.h"
-
-#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
-#include "third_party/blink/renderer/platform/graphics/graphics_layer.h"
-#include "third_party/blink/renderer/platform/graphics/paint/compositing_display_item.h"
-#include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
-#include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h"
-
-namespace blink {
-
-CompositingRecorder::CompositingRecorder(GraphicsContext& graphics_context,
-                                         const DisplayItemClient& client,
-                                         const SkBlendMode xfer_mode,
-                                         const float opacity,
-                                         const FloatRect* bounds,
-                                         ColorFilter color_filter)
-    : client_(client), graphics_context_(graphics_context) {
-  if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
-    return;
-  graphics_context.GetPaintController()
-      .CreateAndAppend<BeginCompositingDisplayItem>(client_, xfer_mode, opacity,
-                                                    bounds, color_filter);
-}
-
-CompositingRecorder::~CompositingRecorder() {
-  if (RuntimeEnabledFeatures::SlimmingPaintV175Enabled())
-    return;
-  graphics_context_.GetPaintController().EndItem<EndCompositingDisplayItem>(
-      client_);
-}
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/platform/graphics/paint/compositing_recorder.h b/third_party/blink/renderer/platform/graphics/paint/compositing_recorder.h
deleted file mode 100644
index 3389569..0000000
--- a/third_party/blink/renderer/platform/graphics/paint/compositing_recorder.h
+++ /dev/null
@@ -1,41 +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 THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_COMPOSITING_RECORDER_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_COMPOSITING_RECORDER_H_
-
-#include "third_party/blink/renderer/platform/geometry/float_rect.h"
-#include "third_party/blink/renderer/platform/graphics/graphics_types.h"
-#include "third_party/blink/renderer/platform/graphics/paint/display_item.h"
-#include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/wtf/allocator.h"
-#include "third_party/skia/include/core/SkBlendMode.h"
-
-namespace blink {
-
-class GraphicsContext;
-
-class PLATFORM_EXPORT CompositingRecorder {
-  USING_FAST_MALLOC(CompositingRecorder);
-
- public:
-  // If bounds is provided, the content will be explicitly clipped to those
-  // bounds.
-  CompositingRecorder(GraphicsContext&,
-                      const DisplayItemClient&,
-                      const SkBlendMode,
-                      const float opacity,
-                      const FloatRect* bounds = nullptr,
-                      ColorFilter = kColorFilterNone);
-
-  ~CompositingRecorder();
-
- private:
-  const DisplayItemClient& client_;
-  GraphicsContext& graphics_context_;
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_COMPOSITING_RECORDER_H_
diff --git a/third_party/blink/renderer/platform/graphics/paint/display_item_list.h b/third_party/blink/renderer/platform/graphics/paint/display_item_list.h
index 4b60c7c..8b31cd1 100644
--- a/third_party/blink/renderer/platform/graphics/paint/display_item_list.h
+++ b/third_party/blink/renderer/platform/graphics/paint/display_item_list.h
@@ -7,7 +7,7 @@
 
 #include "third_party/blink/renderer/platform/graphics/contiguous_container.h"
 #include "third_party/blink/renderer/platform/graphics/paint/display_item.h"
-#include "third_party/blink/renderer/platform/graphics/paint/transform_3d_display_item.h"
+#include "third_party/blink/renderer/platform/graphics/paint/foreign_layer_display_item.h"
 #include "third_party/blink/renderer/platform/wtf/alignment.h"
 #include "third_party/blink/renderer/platform/wtf/assertions.h"
 
@@ -18,12 +18,11 @@
 
 // kDisplayItemAlignment must be a multiple of alignof(derived display item) for
 // each derived display item; the ideal value is the least common multiple.
-// Currently the limiting factor is TransformationMatrix (in
-// BeginTransform3DDisplayItem), which requests 16-byte alignment.
+// The validity of kDisplayItemAlignment and kMaximumDisplayItemSize are checked
+// in PaintController::CreateAndAppend().
 static const size_t kDisplayItemAlignment =
-    WTF_ALIGN_OF(BeginTransform3DDisplayItem);
-static const size_t kMaximumDisplayItemSize =
-    sizeof(BeginTransform3DDisplayItem);
+    WTF_ALIGN_OF(ForeignLayerDisplayItem);
+static const size_t kMaximumDisplayItemSize = sizeof(ForeignLayerDisplayItem);
 
 // A container for a list of display items.
 class PLATFORM_EXPORT DisplayItemList
diff --git a/third_party/blink/renderer/platform/graphics/paint/filter_display_item.cc b/third_party/blink/renderer/platform/graphics/paint/filter_display_item.cc
deleted file mode 100644
index 88a5b4d..0000000
--- a/third_party/blink/renderer/platform/graphics/paint/filter_display_item.cc
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/platform/graphics/paint/filter_display_item.h"
-
-#include "cc/paint/display_item_list.h"
-#include "cc/paint/render_surface_filters.h"
-#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
-#include "ui/gfx/geometry/point_f.h"
-#include "ui/gfx/geometry/rect_f.h"
-
-namespace blink {
-
-void BeginFilterDisplayItem::Replay(GraphicsContext& context) const {
-  FloatRect image_filter_bounds(bounds_);
-  image_filter_bounds.Move(-origin_.X(), -origin_.Y());
-  context.Save();
-  context.Translate(origin_.X(), origin_.Y());
-  context.BeginLayer(1, SkBlendMode::kSrcOver, &image_filter_bounds,
-                     kColorFilterNone, image_filter_);
-  context.Translate(-origin_.X(), -origin_.Y());
-}
-
-void BeginFilterDisplayItem::AppendToDisplayItemList(
-    const FloatSize&,
-    cc::DisplayItemList& list) const {
-  list.StartPaint();
-
-  // TODO(danakj): Skip the save+translate+restore if the origin is 0,0. This
-  // should be easier to do when this code is part of the blink DisplayItem
-  // which can keep related state.
-  list.push<cc::SaveOp>();
-  list.push<cc::TranslateOp>(origin_.X(), origin_.Y());
-
-  cc::PaintFlags flags;
-  flags.setImageFilter(cc::RenderSurfaceFilters::BuildImageFilter(
-      compositor_filter_operations_.AsCcFilterOperations(),
-      static_cast<gfx::SizeF>(bounds_.Size())));
-
-  SkRect layer_bounds = bounds_;
-  layer_bounds.offset(-origin_.X(), -origin_.Y());
-  list.push<cc::SaveLayerOp>(&layer_bounds, &flags);
-  list.push<cc::TranslateOp>(-origin_.X(), -origin_.Y());
-
-  list.EndPaintOfPairedBegin(EnclosingIntRect(bounds_));
-}
-
-bool BeginFilterDisplayItem::DrawsContent() const {
-  // Skia cannot currently tell us if a filter will draw content,
-  // even when no input primitives are drawn.
-  return true;
-}
-
-#if DCHECK_IS_ON()
-void BeginFilterDisplayItem::PropertiesAsJSON(JSONObject& json) const {
-  DisplayItem::PropertiesAsJSON(json);
-  json.SetString("filterBounds", bounds_.ToString());
-}
-#endif
-
-void EndFilterDisplayItem::Replay(GraphicsContext& context) const {
-  context.EndLayer();
-  context.Restore();
-}
-
-void EndFilterDisplayItem::AppendToDisplayItemList(
-    const FloatSize&,
-    cc::DisplayItemList& list) const {
-  list.StartPaint();
-  list.push<cc::RestoreOp>();  // For SaveLayerOp.
-  list.push<cc::RestoreOp>();  // For SaveOp.
-  list.EndPaintOfPairedEnd();
-}
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/platform/graphics/paint/filter_display_item.h b/third_party/blink/renderer/platform/graphics/paint/filter_display_item.h
deleted file mode 100644
index ce9bc17..0000000
--- a/third_party/blink/renderer/platform/graphics/paint/filter_display_item.h
+++ /dev/null
@@ -1,77 +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 THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_FILTER_DISPLAY_ITEM_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_FILTER_DISPLAY_ITEM_H_
-
-#include <memory>
-#include "base/memory/scoped_refptr.h"
-#include "third_party/blink/renderer/platform/geometry/float_rect.h"
-#include "third_party/blink/renderer/platform/graphics/compositor_filter_operations.h"
-#include "third_party/blink/renderer/platform/graphics/paint/display_item.h"
-
-namespace blink {
-
-class PLATFORM_EXPORT BeginFilterDisplayItem final
-    : public PairedBeginDisplayItem {
- public:
-  BeginFilterDisplayItem(const DisplayItemClient& client,
-                         sk_sp<PaintFilter> image_filter,
-                         const FloatRect& bounds,
-                         const FloatPoint& origin,
-                         CompositorFilterOperations filter_operations)
-      : PairedBeginDisplayItem(client, kBeginFilter, sizeof(*this)),
-        image_filter_(std::move(image_filter)),
-        compositor_filter_operations_(std::move(filter_operations)),
-        bounds_(bounds),
-        origin_(origin) {}
-
-  void Replay(GraphicsContext&) const override;
-  void AppendToDisplayItemList(const FloatSize&,
-                               cc::DisplayItemList&) const override;
-  bool DrawsContent() const override;
-
- private:
-#if DCHECK_IS_ON()
-  void PropertiesAsJSON(JSONObject&) const override;
-#endif
-  bool Equals(const DisplayItem& other) const final {
-    if (!DisplayItem::Equals(other))
-      return false;
-    const auto& other_item = static_cast<const BeginFilterDisplayItem&>(other);
-    // Ignores changes of reference filters because PaintFilter doesn't have
-    // an equality operator.
-    return bounds_ == other_item.bounds_ && origin_ == other_item.origin_ &&
-           compositor_filter_operations_.EqualsIgnoringReferenceFilters(
-               other_item.compositor_filter_operations_);
-  }
-
-  // FIXME: m_imageFilter should be replaced with m_webFilterOperations when
-  // copying data to the compositor.
-  sk_sp<PaintFilter> image_filter_;
-  CompositorFilterOperations compositor_filter_operations_;
-  const FloatRect bounds_;
-  const FloatPoint origin_;
-};
-
-class PLATFORM_EXPORT EndFilterDisplayItem final : public PairedEndDisplayItem {
- public:
-  EndFilterDisplayItem(const DisplayItemClient& client)
-      : PairedEndDisplayItem(client, kEndFilter, sizeof(*this)) {}
-
-  void Replay(GraphicsContext&) const override;
-  void AppendToDisplayItemList(const FloatSize&,
-                               cc::DisplayItemList&) const override;
-
- private:
-#if DCHECK_IS_ON()
-  bool IsEndAndPairedWith(DisplayItem::Type other_type) const final {
-    return other_type == kBeginFilter;
-  }
-#endif
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_FILTER_DISPLAY_ITEM_H_
diff --git a/third_party/blink/renderer/platform/graphics/paint/float_clip_display_item.cc b/third_party/blink/renderer/platform/graphics/paint/float_clip_display_item.cc
deleted file mode 100644
index 6b6843e..0000000
--- a/third_party/blink/renderer/platform/graphics/paint/float_clip_display_item.cc
+++ /dev/null
@@ -1,48 +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 "third_party/blink/renderer/platform/graphics/paint/float_clip_display_item.h"
-
-#include "cc/paint/display_item_list.h"
-#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
-#include "third_party/skia/include/core/SkScalar.h"
-#include "ui/gfx/geometry/rect_f.h"
-
-namespace blink {
-
-void FloatClipDisplayItem::Replay(GraphicsContext& context) const {
-  context.Save();
-  context.ClipRect(clip_rect_, kAntiAliased);
-}
-
-void FloatClipDisplayItem::AppendToDisplayItemList(
-    const FloatSize&,
-    cc::DisplayItemList& list) const {
-  list.StartPaint();
-  list.push<cc::SaveOp>();
-  list.push<cc::ClipRectOp>(clip_rect_, SkClipOp::kIntersect,
-                            /*antialias=*/true);
-  list.EndPaintOfPairedBegin();
-}
-
-void EndFloatClipDisplayItem::Replay(GraphicsContext& context) const {
-  context.Restore();
-}
-
-void EndFloatClipDisplayItem::AppendToDisplayItemList(
-    const FloatSize&,
-    cc::DisplayItemList& list) const {
-  list.StartPaint();
-  list.push<cc::RestoreOp>();
-  list.EndPaintOfPairedEnd();
-}
-
-#if DCHECK_IS_ON()
-void FloatClipDisplayItem::PropertiesAsJSON(JSONObject& json) const {
-  DisplayItem::PropertiesAsJSON(json);
-  json.SetString("floatClipRect", clip_rect_.ToString());
-}
-#endif
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/platform/graphics/paint/float_clip_display_item.h b/third_party/blink/renderer/platform/graphics/paint/float_clip_display_item.h
deleted file mode 100644
index 66f15e9..0000000
--- a/third_party/blink/renderer/platform/graphics/paint/float_clip_display_item.h
+++ /dev/null
@@ -1,64 +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 THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_FLOAT_CLIP_DISPLAY_ITEM_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_FLOAT_CLIP_DISPLAY_ITEM_H_
-
-#include "third_party/blink/renderer/platform/geometry/float_rect.h"
-#include "third_party/blink/renderer/platform/graphics/paint/display_item.h"
-#include "third_party/blink/renderer/platform/platform_export.h"
-
-namespace blink {
-
-class PLATFORM_EXPORT FloatClipDisplayItem final
-    : public PairedBeginDisplayItem {
- public:
-  FloatClipDisplayItem(const DisplayItemClient& client,
-                       Type type,
-                       const FloatRect& clip_rect)
-      : PairedBeginDisplayItem(client, type, sizeof(*this)),
-        clip_rect_(clip_rect) {
-    DCHECK(IsFloatClipType(type));
-  }
-
-  void Replay(GraphicsContext&) const override;
-  void AppendToDisplayItemList(const FloatSize&,
-                               cc::DisplayItemList&) const override;
-
- private:
-#if DCHECK_IS_ON()
-  void PropertiesAsJSON(JSONObject&) const override;
-#endif
-  bool Equals(const DisplayItem& other) const final {
-    return DisplayItem::Equals(other) &&
-           clip_rect_ ==
-               static_cast<const FloatClipDisplayItem&>(other).clip_rect_;
-  }
-
-  const FloatRect clip_rect_;
-};
-
-class PLATFORM_EXPORT EndFloatClipDisplayItem final
-    : public PairedEndDisplayItem {
- public:
-  EndFloatClipDisplayItem(const DisplayItemClient& client, Type type)
-      : PairedEndDisplayItem(client, type, sizeof(*this)) {
-    DCHECK(IsEndFloatClipType(type));
-  }
-
-  void Replay(GraphicsContext&) const override;
-  void AppendToDisplayItemList(const FloatSize&,
-                               cc::DisplayItemList&) const override;
-
- private:
-#if DCHECK_IS_ON()
-  bool IsEndAndPairedWith(DisplayItem::Type other_type) const final {
-    return DisplayItem::IsFloatClipType(other_type);
-  }
-#endif
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_FLOAT_CLIP_DISPLAY_ITEM_H_
diff --git a/third_party/blink/renderer/platform/graphics/paint/foreign_layer_display_item.h b/third_party/blink/renderer/platform/graphics/paint/foreign_layer_display_item.h
index b65bab8..6d7e51e 100644
--- a/third_party/blink/renderer/platform/graphics/paint/foreign_layer_display_item.h
+++ b/third_party/blink/renderer/platform/graphics/paint/foreign_layer_display_item.h
@@ -5,14 +5,10 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_FOREIGN_LAYER_DISPLAY_ITEM_H_
 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_FOREIGN_LAYER_DISPLAY_ITEM_H_
 
-#include "base/memory/ref_counted.h"
+#include "cc/layers/layer.h"
 #include "third_party/blink/renderer/platform/graphics/paint/display_item.h"
 #include "third_party/blink/renderer/platform/platform_export.h"
 
-namespace cc {
-class Layer;
-}
-
 namespace blink {
 
 class GraphicsContext;
diff --git a/third_party/blink/renderer/platform/graphics/paint/paint_controller.h b/third_party/blink/renderer/platform/graphics/paint/paint_controller.h
index e7998ab..71fe438 100644
--- a/third_party/blink/renderer/platform/graphics/paint/paint_controller.h
+++ b/third_party/blink/renderer/platform/graphics/paint/paint_controller.h
@@ -19,7 +19,6 @@
 #include "third_party/blink/renderer/platform/graphics/paint/paint_chunk.h"
 #include "third_party/blink/renderer/platform/graphics/paint/paint_chunker.h"
 #include "third_party/blink/renderer/platform/graphics/paint/raster_invalidation_tracking.h"
-#include "third_party/blink/renderer/platform/graphics/paint/transform_3d_display_item.h"
 #include "third_party/blink/renderer/platform/platform_export.h"
 #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
 #include "third_party/blink/renderer/platform/wtf/alignment.h"
@@ -109,6 +108,9 @@
     static_assert(
         sizeof(DisplayItemClass) <= kMaximumDisplayItemSize,
         "DisplayItem subclass is larger than kMaximumDisplayItemSize.");
+    static_assert(kDisplayItemAlignment % WTF_ALIGN_OF(DisplayItemClass) == 0,
+                  "DisplayItem subclass alignment is not a factor of "
+                  "kDisplayItemAlignment.");
 
     if (DisplayItemConstructionIsDisabled())
       return;
diff --git a/third_party/blink/renderer/platform/graphics/paint/scroll_display_item.cc b/third_party/blink/renderer/platform/graphics/paint/scroll_display_item.cc
deleted file mode 100644
index 673094d..0000000
--- a/third_party/blink/renderer/platform/graphics/paint/scroll_display_item.cc
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/platform/graphics/paint/scroll_display_item.h"
-
-#include "cc/paint/display_item_list.h"
-#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
-
-namespace blink {
-
-void BeginScrollDisplayItem::Replay(GraphicsContext& context) const {
-  context.Save();
-  context.Translate(-current_offset_.Width(), -current_offset_.Height());
-}
-
-void BeginScrollDisplayItem::AppendToDisplayItemList(
-    const FloatSize&,
-    cc::DisplayItemList& list) const {
-  list.StartPaint();
-  list.push<cc::SaveOp>();
-  list.push<cc::TranslateOp>(static_cast<float>(-current_offset_.Width()),
-                             static_cast<float>(-current_offset_.Height()));
-  list.EndPaintOfPairedBegin();
-}
-
-#if DCHECK_IS_ON()
-void BeginScrollDisplayItem::PropertiesAsJSON(JSONObject& json) const {
-  PairedBeginDisplayItem::PropertiesAsJSON(json);
-  json.SetString("currentOffset", current_offset_.ToString());
-}
-#endif
-
-void EndScrollDisplayItem::Replay(GraphicsContext& context) const {
-  context.Restore();
-}
-
-void EndScrollDisplayItem::AppendToDisplayItemList(
-    const FloatSize&,
-    cc::DisplayItemList& list) const {
-  list.StartPaint();
-  list.push<cc::RestoreOp>();
-  list.EndPaintOfPairedEnd();
-}
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/platform/graphics/paint/scroll_display_item.h b/third_party/blink/renderer/platform/graphics/paint/scroll_display_item.h
deleted file mode 100644
index c4136bb..0000000
--- a/third_party/blink/renderer/platform/graphics/paint/scroll_display_item.h
+++ /dev/null
@@ -1,65 +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 THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_SCROLL_DISPLAY_ITEM_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_SCROLL_DISPLAY_ITEM_H_
-
-#include "third_party/blink/renderer/platform/geometry/int_size.h"
-#include "third_party/blink/renderer/platform/graphics/paint/display_item.h"
-#include "third_party/blink/renderer/platform/wtf/allocator.h"
-
-namespace blink {
-
-class PLATFORM_EXPORT BeginScrollDisplayItem final
-    : public PairedBeginDisplayItem {
- public:
-  BeginScrollDisplayItem(const DisplayItemClient& client,
-                         Type type,
-                         const IntSize& current_offset)
-      : PairedBeginDisplayItem(client, type, sizeof(*this)),
-        current_offset_(current_offset) {
-    DCHECK(IsScrollType(type));
-  }
-
-  void Replay(GraphicsContext&) const override;
-  void AppendToDisplayItemList(const FloatSize&,
-                               cc::DisplayItemList&) const override;
-
-  const IntSize& CurrentOffset() const { return current_offset_; }
-
- private:
-#if DCHECK_IS_ON()
-  void PropertiesAsJSON(JSONObject&) const final;
-#endif
-  bool Equals(const DisplayItem& other) const final {
-    return DisplayItem::Equals(other) &&
-           current_offset_ == static_cast<const BeginScrollDisplayItem&>(other)
-                                  .current_offset_;
-  }
-
-  const IntSize current_offset_;
-};
-
-class PLATFORM_EXPORT EndScrollDisplayItem final : public PairedEndDisplayItem {
- public:
-  EndScrollDisplayItem(const DisplayItemClient& client, Type type)
-      : PairedEndDisplayItem(client, type, sizeof(*this)) {
-    DCHECK(IsEndScrollType(type));
-  }
-
-  void Replay(GraphicsContext&) const override;
-  void AppendToDisplayItemList(const FloatSize&,
-                               cc::DisplayItemList&) const override;
-
- private:
-#if DCHECK_IS_ON()
-  bool IsEndAndPairedWith(DisplayItem::Type other_type) const final {
-    return DisplayItem::IsScrollType(other_type);
-  }
-#endif
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_SCROLL_DISPLAY_ITEM_H_
diff --git a/third_party/blink/renderer/platform/graphics/paint/transform_3d_display_item.cc b/third_party/blink/renderer/platform/graphics/paint/transform_3d_display_item.cc
deleted file mode 100644
index 91f9a1e..0000000
--- a/third_party/blink/renderer/platform/graphics/paint/transform_3d_display_item.cc
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/platform/graphics/paint/transform_3d_display_item.h"
-
-#include "cc/paint/display_item_list.h"
-#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
-#include "third_party/blink/renderer/platform/transforms/affine_transform.h"
-
-namespace blink {
-
-void BeginTransform3DDisplayItem::Replay(GraphicsContext& context) const {
-  TransformationMatrix transform(transform_);
-  transform.ApplyTransformOrigin(transform_origin_);
-  context.Save();
-  context.ConcatCTM(transform.ToAffineTransform());
-}
-
-void BeginTransform3DDisplayItem::AppendToDisplayItemList(
-    const FloatSize&,
-    cc::DisplayItemList& list) const {
-  // TODO(jbroman): The compositor will need the transform origin separately.
-  TransformationMatrix transform(transform_);
-  transform.ApplyTransformOrigin(transform_origin_);
-
-  list.StartPaint();
-  list.push<cc::SaveOp>();
-  if (!transform.IsIdentity()) {
-    list.push<cc::ConcatOp>(
-        static_cast<SkMatrix>(TransformationMatrix::ToSkMatrix44(transform)));
-  }
-  list.EndPaintOfPairedBegin();
-}
-
-#if DCHECK_IS_ON()
-void BeginTransform3DDisplayItem::PropertiesAsJSON(JSONObject& json) const {
-  PairedBeginDisplayItem::PropertiesAsJSON(json);
-  json.SetString("transform", transform_.ToString());
-  json.SetString("origin", transform_origin_.ToString());
-}
-#endif
-
-void EndTransform3DDisplayItem::Replay(GraphicsContext& context) const {
-  context.Restore();
-}
-
-void EndTransform3DDisplayItem::AppendToDisplayItemList(
-    const FloatSize&,
-    cc::DisplayItemList& list) const {
-  list.StartPaint();
-  list.push<cc::RestoreOp>();
-  list.EndPaintOfPairedEnd();
-}
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/platform/graphics/paint/transform_3d_display_item.h b/third_party/blink/renderer/platform/graphics/paint/transform_3d_display_item.h
deleted file mode 100644
index df63b22f..0000000
--- a/third_party/blink/renderer/platform/graphics/paint/transform_3d_display_item.h
+++ /dev/null
@@ -1,75 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_TRANSFORM_3D_DISPLAY_ITEM_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_TRANSFORM_3D_DISPLAY_ITEM_H_
-
-#include "third_party/blink/renderer/platform/geometry/float_point_3d.h"
-#include "third_party/blink/renderer/platform/graphics/paint/display_item.h"
-#include "third_party/blink/renderer/platform/transforms/transformation_matrix.h"
-#include "third_party/blink/renderer/platform/wtf/assertions.h"
-
-namespace blink {
-
-class PLATFORM_EXPORT BeginTransform3DDisplayItem final
-    : public PairedBeginDisplayItem {
- public:
-  BeginTransform3DDisplayItem(const DisplayItemClient& client,
-                              Type type,
-                              const TransformationMatrix& transform,
-                              const FloatPoint3D& transform_origin)
-      : PairedBeginDisplayItem(client, type, sizeof(*this)),
-        transform_(transform),
-        transform_origin_(transform_origin) {
-    DCHECK(DisplayItem::IsTransform3DType(type));
-  }
-
-  void Replay(GraphicsContext&) const override;
-  void AppendToDisplayItemList(const FloatSize&,
-                               cc::DisplayItemList&) const override;
-
-  const TransformationMatrix& Transform() const { return transform_; }
-  const FloatPoint3D& TransformOrigin() const { return transform_origin_; }
-
- private:
-#if DCHECK_IS_ON()
-  void PropertiesAsJSON(JSONObject&) const final;
-#endif
-  bool Equals(const DisplayItem& other) const final {
-    return DisplayItem::Equals(other) &&
-           transform_ == static_cast<const BeginTransform3DDisplayItem&>(other)
-                             .transform_ &&
-           transform_origin_ ==
-               static_cast<const BeginTransform3DDisplayItem&>(other)
-                   .transform_origin_;
-  }
-
-  const TransformationMatrix transform_;
-  const FloatPoint3D transform_origin_;
-};
-
-class PLATFORM_EXPORT EndTransform3DDisplayItem final
-    : public PairedEndDisplayItem {
- public:
-  EndTransform3DDisplayItem(const DisplayItemClient& client, Type type)
-      : PairedEndDisplayItem(client, type, sizeof(*this)) {
-    DCHECK(DisplayItem::IsEndTransform3DType(type));
-  }
-
-  void Replay(GraphicsContext&) const override;
-  void AppendToDisplayItemList(const FloatSize&,
-                               cc::DisplayItemList&) const override;
-
- private:
-#if DCHECK_IS_ON()
-  bool IsEndAndPairedWith(DisplayItem::Type other_type) const final {
-    return DisplayItem::Transform3DTypeToEndTransform3DType(other_type) ==
-           GetType();
-  }
-#endif
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_TRANSFORM_3D_DISPLAY_ITEM_H_
diff --git a/third_party/blink/renderer/platform/graphics/paint/transform_display_item.cc b/third_party/blink/renderer/platform/graphics/paint/transform_display_item.cc
deleted file mode 100644
index e0d4508..0000000
--- a/third_party/blink/renderer/platform/graphics/paint/transform_display_item.cc
+++ /dev/null
@@ -1,47 +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 "third_party/blink/renderer/platform/graphics/paint/transform_display_item.h"
-
-#include "cc/paint/display_item_list.h"
-#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
-#include "third_party/blink/renderer/platform/transforms/affine_transform.h"
-
-namespace blink {
-
-void BeginTransformDisplayItem::Replay(GraphicsContext& context) const {
-  context.Save();
-  context.ConcatCTM(transform_);
-}
-
-void BeginTransformDisplayItem::AppendToDisplayItemList(
-    const FloatSize&,
-    cc::DisplayItemList& list) const {
-  list.StartPaint();
-  list.push<cc::SaveOp>();
-  if (!transform_.IsIdentity())
-    list.push<cc::ConcatOp>(AffineTransformToSkMatrix(transform_));
-  list.EndPaintOfPairedBegin();
-}
-
-#if DCHECK_IS_ON()
-void BeginTransformDisplayItem::PropertiesAsJSON(JSONObject& json) const {
-  PairedBeginDisplayItem::PropertiesAsJSON(json);
-  json.SetString("transform", transform_.ToString());
-}
-#endif
-
-void EndTransformDisplayItem::Replay(GraphicsContext& context) const {
-  context.Restore();
-}
-
-void EndTransformDisplayItem::AppendToDisplayItemList(
-    const FloatSize&,
-    cc::DisplayItemList& list) const {
-  list.StartPaint();
-  list.push<cc::RestoreOp>();
-  list.EndPaintOfPairedEnd();
-}
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/platform/graphics/paint/transform_display_item.h b/third_party/blink/renderer/platform/graphics/paint/transform_display_item.h
deleted file mode 100644
index a684f7b..0000000
--- a/third_party/blink/renderer/platform/graphics/paint/transform_display_item.h
+++ /dev/null
@@ -1,60 +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 THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_TRANSFORM_DISPLAY_ITEM_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_TRANSFORM_DISPLAY_ITEM_H_
-
-#include "third_party/blink/renderer/platform/graphics/paint/display_item.h"
-#include "third_party/blink/renderer/platform/transforms/affine_transform.h"
-
-namespace blink {
-
-class PLATFORM_EXPORT BeginTransformDisplayItem final
-    : public PairedBeginDisplayItem {
- public:
-  BeginTransformDisplayItem(const DisplayItemClient& client,
-                            const AffineTransform& transform)
-      : PairedBeginDisplayItem(client, kBeginTransform, sizeof(*this)),
-        transform_(transform) {}
-
-  void Replay(GraphicsContext&) const override;
-  void AppendToDisplayItemList(const FloatSize&,
-                               cc::DisplayItemList&) const override;
-
-  const AffineTransform& Transform() const { return transform_; }
-
- private:
-#if DCHECK_IS_ON()
-  void PropertiesAsJSON(JSONObject&) const final;
-#endif
-  bool Equals(const DisplayItem& other) const final {
-    return DisplayItem::Equals(other) &&
-           transform_ ==
-               static_cast<const BeginTransformDisplayItem&>(other).transform_;
-  }
-
-  const AffineTransform transform_;
-};
-
-class PLATFORM_EXPORT EndTransformDisplayItem final
-    : public PairedEndDisplayItem {
- public:
-  EndTransformDisplayItem(const DisplayItemClient& client)
-      : PairedEndDisplayItem(client, kEndTransform, sizeof(*this)) {}
-
-  void Replay(GraphicsContext&) const override;
-  void AppendToDisplayItemList(const FloatSize&,
-                               cc::DisplayItemList&) const override;
-
- private:
-#if DCHECK_IS_ON()
-  bool IsEndAndPairedWith(DisplayItem::Type other_type) const final {
-    return other_type == kBeginTransform;
-  }
-#endif
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_TRANSFORM_DISPLAY_ITEM_H_
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 fd5c838..be4bff93 100644
--- a/third_party/blink/renderer/platform/graphics/video_frame_submitter.cc
+++ b/third_party/blink/renderer/platform/graphics/video_frame_submitter.cc
@@ -200,7 +200,11 @@
     scoped_refptr<media::VideoFrame> video_frame) {
   TRACE_EVENT0("media", "VideoFrameSubmitter::SubmitFrame");
   DCHECK_CALLED_ON_VALID_THREAD(media_thread_checker_);
-  DCHECK(compositor_frame_sink_);
+
+  // 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;
   std::unique_ptr<viz::RenderPass> render_pass = viz::RenderPass::Create();
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 89e0fc0..8f128865 100644
--- a/third_party/blink/renderer/platform/graphics/video_frame_submitter.h
+++ b/third_party/blink/renderer/platform/graphics/video_frame_submitter.h
@@ -82,6 +82,8 @@
   void DidDeleteSharedBitmap(const viz::SharedBitmapId&) override;
 
  private:
+  FRIEND_TEST_ALL_PREFIXES(VideoFrameSubmitterTest, ContextLostDuringSubmit);
+
   void StartSubmitting();
   void SubmitFrame(viz::BeginFrameAck, scoped_refptr<media::VideoFrame>);
 
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 b0880aa5..addcc89 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
@@ -483,4 +483,29 @@
   scoped_task_environment_.RunUntilIdle();
 }
 
+// Test that no crash happens if the context is lost during a frame submission.
+TEST_F(VideoFrameSubmitterTest, ContextLostDuringSubmit) {
+  MakeSubmitter();
+  scoped_task_environment_.RunUntilIdle();
+
+  EXPECT_CALL(*sink_, SetNeedsBeginFrame(true));
+
+  submitter_->StartRendering();
+  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());
+
+  // This will post a task that will later call SubmitFrame(). The call will
+  // happen after OnContextLost().
+  submitter_->SubmitSingleFrame();
+
+  submitter_->OnContextLost();
+
+  scoped_task_environment_.RunUntilIdle();
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/network/http_parsers_test.cc b/third_party/blink/renderer/platform/network/http_parsers_test.cc
index 5499702..358a4cd 100644
--- a/third_party/blink/renderer/platform/network/http_parsers_test.cc
+++ b/third_party/blink/renderer/platform/network/http_parsers_test.cc
@@ -148,7 +148,7 @@
   EXPECT_FALSE(blink::IsValidHTTPToken("t a"));
   EXPECT_FALSE(blink::IsValidHTTPToken("()"));
   EXPECT_FALSE(blink::IsValidHTTPToken("(foobar)"));
-  EXPECT_FALSE(blink::IsValidHTTPToken(String("\0", 1)));
+  EXPECT_FALSE(blink::IsValidHTTPToken(String("\0", 1u)));
   EXPECT_FALSE(blink::IsValidHTTPToken(String(kHiraganaA)));
 }
 
diff --git a/third_party/blink/renderer/platform/text/hyphenation/hyphenation_minikin.cc b/third_party/blink/renderer/platform/text/hyphenation/hyphenation_minikin.cc
index 68d8ee7..1900e1fa 100644
--- a/third_party/blink/renderer/platform/text/hyphenation/hyphenation_minikin.cc
+++ b/third_party/blink/renderer/platform/text/hyphenation/hyphenation_minikin.cc
@@ -33,7 +33,7 @@
   while (text != end && Character::TreatAsSpace(*text))
     text++;
   *num_leading_spaces_out = text - begin;
-  return StringView(text, end - text);
+  return StringView(text, static_cast<unsigned>(end - text));
 }
 
 StringView SkipLeadingSpaces(const StringView& text,
@@ -177,7 +177,7 @@
   };
   LocaleMap map;
   for (const auto& it : locale_fallback_data)
-    map.insert(it[0], it[1]);
+    map.insert(AtomicString(it[0]), it[1]);
   return map;
 }
 
diff --git a/third_party/blink/renderer/platform/weborigin/kurl.cc b/third_party/blink/renderer/platform/weborigin/kurl.cc
index 09d31ec..0e44149 100644
--- a/third_party/blink/renderer/platform/weborigin/kurl.cc
+++ b/third_party/blink/renderer/platform/weborigin/kurl.cc
@@ -647,7 +647,7 @@
     buffer.Resize(input_length * 3);
 
   url::EncodeURIComponent(utf8.data(), input_length, &buffer);
-  String escaped(buffer.data(), buffer.length());
+  String escaped(buffer.data(), static_cast<unsigned>(buffer.length()));
   // Unescape '/'; it's safe and much prettier.
   escaped.Replace("%2F", "/");
   return escaped;
diff --git a/third_party/blink/renderer/platform/weborigin/kurl_test.cc b/third_party/blink/renderer/platform/weborigin/kurl_test.cc
index 76ef911..29914d8 100644
--- a/third_party/blink/renderer/platform/weborigin/kurl_test.cc
+++ b/third_party/blink/renderer/platform/weborigin/kurl_test.cc
@@ -279,7 +279,7 @@
   }
 
   // Our encode escapes NULLs for safety, so we need to check that too.
-  String input("\x00\x01", 2);
+  String input("\x00\x01", 2u);
   String reference("%00%01");
 
   String output = EncodeWithURLEscapeSequences(input);
diff --git a/third_party/blink/renderer/platform/wtf/text/atomic_string.cc b/third_party/blink/renderer/platform/wtf/text/atomic_string.cc
index 75ceaf1..b55d116 100644
--- a/third_party/blink/renderer/platform/wtf/text/atomic_string.cc
+++ b/third_party/blink/renderer/platform/wtf/text/atomic_string.cc
@@ -33,6 +33,11 @@
 static_assert(sizeof(AtomicString) == sizeof(String),
               "AtomicString and String must be same size");
 
+#if defined(ARCH_CPU_64_BITS)
+AtomicString::AtomicString(const LChar* chars, size_t length)
+    : AtomicString(chars, SafeCast<unsigned>(length)) {}
+#endif  // defined(ARCH_CPU_64_BITS)
+
 AtomicString::AtomicString(const LChar* chars, unsigned length)
     : string_(AtomicStringTable::Instance().Add(chars, length)) {}
 
diff --git a/third_party/blink/renderer/platform/wtf/text/atomic_string.h b/third_party/blink/renderer/platform/wtf/text/atomic_string.h
index caf9fc90..3ace8cc 100644
--- a/third_party/blink/renderer/platform/wtf/text/atomic_string.h
+++ b/third_party/blink/renderer/platform/wtf/text/atomic_string.h
@@ -61,6 +61,13 @@
       : AtomicString(chars,
                      chars ? strlen(reinterpret_cast<const char*>(chars)) : 0) {
   }
+
+#if defined(ARCH_CPU_64_BITS)
+  // Only define a size_t constructor if size_t is 64 bit otherwise
+  // we'd have a duplicate define.
+  AtomicString(const LChar* chars, size_t length);
+#endif  // defined(ARCH_CPU_64_BITS)
+
   AtomicString(const char* chars)
       : AtomicString(reinterpret_cast<const LChar*>(chars)) {}
   AtomicString(const LChar* chars, unsigned length);
diff --git a/third_party/blink/renderer/platform/wtf/text/string_builder.cc b/third_party/blink/renderer/platform/wtf/text/string_builder.cc
index 46e7df0..5f6594a 100644
--- a/third_party/blink/renderer/platform/wtf/text/string_builder.cc
+++ b/third_party/blink/renderer/platform/wtf/text/string_builder.cc
@@ -27,6 +27,7 @@
 #include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
 
 #include <algorithm>
+#include "base/optional.h"
 #include "third_party/blink/renderer/platform/wtf/dtoa.h"
 #include "third_party/blink/renderer/platform/wtf/text/integer_to_string_conversion.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -71,18 +72,47 @@
 }
 
 void StringBuilder::Swap(StringBuilder& builder) {
+  base::Optional<Buffer8> buffer8;
+  base::Optional<Buffer16> buffer16;
+  if (has_buffer_) {
+    if (is8_bit_) {
+      buffer8 = std::move(buffer8_);
+      buffer8_.~Buffer8();
+    } else {
+      buffer16 = std::move(buffer16_);
+      buffer16_.~Buffer16();
+    }
+  }
+
+  if (builder.has_buffer_) {
+    if (builder.is8_bit_) {
+      new (&buffer8_) Buffer8(std::move(builder.buffer8_));
+      builder.buffer8_.~Buffer8();
+    } else {
+      new (&buffer16_) Buffer16(std::move(builder.buffer16_));
+      builder.buffer16_.~Buffer16();
+    }
+  }
+
+  if (buffer8)
+    new (&builder.buffer8_) Buffer8(std::move(*buffer8));
+  else if (buffer16)
+    new (&builder.buffer16_) Buffer16(std::move(*buffer16));
+
   std::swap(string_, builder.string_);
-  std::swap(buffer_, builder.buffer_);
   std::swap(length_, builder.length_);
   std::swap(is8_bit_, builder.is8_bit_);
+  std::swap(has_buffer_, builder.has_buffer_);
 }
 
 void StringBuilder::ClearBuffer() {
+  if (!has_buffer_)
+    return;
   if (is8_bit_)
-    delete buffer8_;
+    buffer8_.~Buffer8();
   else
-    delete buffer16_;
-  buffer_ = nullptr;
+    buffer16_.~Buffer16();
+  has_buffer_ = false;
 }
 
 void StringBuilder::Clear() {
@@ -96,8 +126,8 @@
   if (!HasBuffer())
     return 0;
   if (is8_bit_)
-    return buffer8_->capacity();
-  return buffer16_->capacity();
+    return buffer8_.capacity();
+  return buffer16_.capacity();
 }
 
 void StringBuilder::ReserveCapacity(unsigned new_capacity) {
@@ -113,16 +143,17 @@
   length_ = new_size;
   if (HasBuffer()) {
     if (is8_bit_)
-      buffer8_->resize(new_size);
+      buffer8_.resize(new_size);
     else
-      buffer16_->resize(new_size);
+      buffer16_.resize(new_size);
   }
 }
 
 void StringBuilder::CreateBuffer8(unsigned added_size) {
   DCHECK(!HasBuffer());
   DCHECK(is8_bit_);
-  buffer8_ = new Buffer8;
+  new (&buffer8_) Buffer8;
+  has_buffer_ = true;
   // createBuffer is called right before appending addedSize more bytes. We
   // want to ensure we have enough space to fit m_string plus the added
   // size.
@@ -132,8 +163,8 @@
   // strings or single characters. This is a no-op if m_length == 0 since
   // initialBufferSize() is the same as the inline capacity of the vector.
   // This allows doing append(string); append('\0') without extra mallocs.
-  buffer8_->ReserveInitialCapacity(length_ +
-                                   std::max(added_size, InitialBufferSize()));
+  buffer8_.ReserveInitialCapacity(length_ +
+                                  std::max(added_size, InitialBufferSize()));
   length_ = 0;
   Append(string_);
   string_ = String();
@@ -143,14 +174,16 @@
   DCHECK(is8_bit_ || !HasBuffer());
   Buffer8 buffer8;
   unsigned length = length_;
-  if (buffer8_) {
-    buffer8_->swap(buffer8);
-    delete buffer8_;
+  if (has_buffer_) {
+    buffer8 = std::move(buffer8_);
+    buffer8_.~Buffer8();
   }
-  buffer16_ = new Buffer16;
+  new (&buffer16_) Buffer16;
+  has_buffer_ = true;
   // See createBuffer8's call to reserveInitialCapacity for why we do this.
-  buffer16_->ReserveInitialCapacity(length_ +
-                                    std::max(added_size, InitialBufferSize()));
+  buffer16_.ReserveInitialCapacity(
+      length_ +
+      std::max<unsigned>(added_size, InitialBufferSize() / sizeof(UChar)));
   is8_bit_ = false;
   length_ = 0;
   if (!buffer8.IsEmpty()) {
@@ -174,7 +207,7 @@
   }
 
   EnsureBuffer16(length);
-  buffer16_->Append(characters, length);
+  buffer16_.Append(characters, length);
   length_ += length;
 }
 
@@ -185,13 +218,13 @@
 
   if (is8_bit_) {
     EnsureBuffer8(length);
-    buffer8_->Append(characters, length);
+    buffer8_.Append(characters, length);
     length_ += length;
     return;
   }
 
   EnsureBuffer16(length);
-  buffer16_->Append(characters, length);
+  buffer16_.Append(characters, length);
   length_ += length;
 }
 
@@ -236,10 +269,10 @@
 
   if (is8_bit_) {
     EnsureBuffer8(0);
-    buffer8_->EraseAt(index);
+    buffer8_.EraseAt(index);
   } else {
     EnsureBuffer16(0);
-    buffer16_->EraseAt(index);
+    buffer16_.EraseAt(index);
   }
   --length_;
 }
diff --git a/third_party/blink/renderer/platform/wtf/text/string_builder.h b/third_party/blink/renderer/platform/wtf/text/string_builder.h
index ae74e0f..2eed705 100644
--- a/third_party/blink/renderer/platform/wtf/text/string_builder.h
+++ b/third_party/blink/renderer/platform/wtf/text/string_builder.h
@@ -37,8 +37,7 @@
 
 class WTF_EXPORT StringBuilder {
  public:
-  StringBuilder() : buffer_(nullptr), length_(0), is8_bit_(true) {}
-
+  StringBuilder() : no_buffer_() {}
   ~StringBuilder() { Clear(); }
 
   void Append(const UChar*, unsigned length);
@@ -111,7 +110,7 @@
       return;
     }
     EnsureBuffer16(1);
-    buffer16_->push_back(c);
+    buffer16_.push_back(c);
     ++length_;
   }
 
@@ -121,7 +120,7 @@
       return;
     }
     EnsureBuffer8(1);
-    buffer8_->push_back(c);
+    buffer8_.push_back(c);
     ++length_;
   }
 
@@ -172,8 +171,8 @@
       return nullptr;
     if (!string_.IsNull())
       return string_.Characters8();
-    DCHECK(buffer8_);
-    return buffer8_->data();
+    DCHECK(has_buffer_);
+    return buffer8_.data();
   }
 
   const UChar* Characters16() const {
@@ -182,8 +181,8 @@
       return nullptr;
     if (!string_.IsNull())
       return string_.Characters16();
-    DCHECK(buffer16_);
-    return buffer16_->data();
+    DCHECK(has_buffer_);
+    return buffer16_.data();
   }
 
   bool Is8Bit() const { return is8_bit_; }
@@ -195,8 +194,8 @@
   static const unsigned kInlineBufferSize = 16;
   static unsigned InitialBufferSize() { return kInlineBufferSize; }
 
-  typedef Vector<LChar, kInlineBufferSize> Buffer8;
-  typedef Vector<UChar, kInlineBufferSize> Buffer16;
+  typedef Vector<LChar, kInlineBufferSize / sizeof(LChar)> Buffer8;
+  typedef Vector<UChar, kInlineBufferSize / sizeof(UChar)> Buffer16;
 
   void EnsureBuffer8(unsigned added_size) {
     DCHECK(is8_bit_);
@@ -212,16 +211,17 @@
   void CreateBuffer8(unsigned added_size);
   void CreateBuffer16(unsigned added_size);
   void ClearBuffer();
-  bool HasBuffer() const { return buffer_; }
+  bool HasBuffer() const { return has_buffer_; }
 
   String string_;
   union {
-    Buffer8* buffer8_;
-    Buffer16* buffer16_;
-    void* buffer_;
+    char no_buffer_;
+    Buffer8 buffer8_;
+    Buffer16 buffer16_;
   };
-  unsigned length_;
-  bool is8_bit_;
+  unsigned length_ = 0;
+  bool is8_bit_ = true;
+  bool has_buffer_ = false;
 
   DISALLOW_COPY_AND_ASSIGN(StringBuilder);
 };
diff --git a/third_party/blink/renderer/platform/wtf/text/string_concatenate.cc b/third_party/blink/renderer/platform/wtf/text/string_concatenate.cc
index fee8323..ae3c881 100644
--- a/third_party/blink/renderer/platform/wtf/text/string_concatenate.cc
+++ b/third_party/blink/renderer/platform/wtf/text/string_concatenate.cc
@@ -8,6 +8,9 @@
 
 #include "third_party/blink/renderer/platform/wtf/text/string_impl.h"
 
+WTF::StringTypeAdapter<char*>::StringTypeAdapter(char* buffer, size_t length)
+    : buffer_(buffer), length_(SafeCast<unsigned>(length)) {}
+
 void WTF::StringTypeAdapter<char*>::WriteTo(LChar* destination) const {
   for (unsigned i = 0; i < length_; ++i)
     destination[i] = static_cast<LChar>(buffer_[i]);
diff --git a/third_party/blink/renderer/platform/wtf/text/string_concatenate.h b/third_party/blink/renderer/platform/wtf/text/string_concatenate.h
index 94ec241..db24c11 100644
--- a/third_party/blink/renderer/platform/wtf/text/string_concatenate.h
+++ b/third_party/blink/renderer/platform/wtf/text/string_concatenate.h
@@ -101,7 +101,7 @@
 
  public:
   explicit StringTypeAdapter<char*>(char* buffer)
-      : buffer_(buffer), length_(strlen(buffer)) {}
+      : StringTypeAdapter(buffer, strlen(buffer)) {}
 
   unsigned length() const { return length_; }
   bool Is8Bit() const { return true; }
@@ -110,6 +110,8 @@
   void WriteTo(UChar* destination) const;
 
  private:
+  StringTypeAdapter<char*>(char* buffer, size_t length);
+
   const char* buffer_;
   unsigned length_;
 };
diff --git a/third_party/blink/renderer/platform/wtf/text/string_hash.h b/third_party/blink/renderer/platform/wtf/text/string_hash.h
index 170451c..615a3c99 100644
--- a/third_party/blink/renderer/platform/wtf/text/string_hash.h
+++ b/third_party/blink/renderer/platform/wtf/text/string_hash.h
@@ -100,11 +100,6 @@
                                     length);
   }
 
-  static inline unsigned GetHash(const char* data) {
-    return CaseFoldingHash::GetHash(reinterpret_cast<const LChar*>(data),
-                                    strlen(data));
-  }
-
   static inline bool Equal(const StringImpl* a, const StringImpl* b) {
     DCHECK(a);
     DCHECK(b);
diff --git a/third_party/blink/renderer/platform/wtf/text/string_view.h b/third_party/blink/renderer/platform/wtf/text/string_view.h
index ea7e299..47f0d57 100644
--- a/third_party/blink/renderer/platform/wtf/text/string_view.h
+++ b/third_party/blink/renderer/platform/wtf/text/string_view.h
@@ -11,6 +11,7 @@
 #include "base/memory/scoped_refptr.h"
 #endif
 #include <cstring>
+#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
 #include "third_party/blink/renderer/platform/wtf/text/string_impl.h"
 #include "third_party/blink/renderer/platform/wtf/text/unicode.h"
 
@@ -73,7 +74,9 @@
       : StringView(reinterpret_cast<const LChar*>(chars), length) {}
   StringView(const LChar* chars)
       : StringView(chars,
-                   chars ? strlen(reinterpret_cast<const char*>(chars)) : 0) {}
+                   chars ? SafeCast<unsigned>(
+                               strlen(reinterpret_cast<const char*>(chars)))
+                         : 0) {}
   StringView(const char* chars)
       : StringView(reinterpret_cast<const LChar*>(chars)) {}
 
diff --git a/third_party/blink/renderer/platform/wtf/text/string_view_test.cc b/third_party/blink/renderer/platform/wtf/text/string_view_test.cc
index c36168d..e949f60 100644
--- a/third_party/blink/renderer/platform/wtf/text/string_view_test.cc
+++ b/third_party/blink/renderer/platform/wtf/text/string_view_test.cc
@@ -252,7 +252,7 @@
 }
 
 TEST(StringViewTest, ConstructionStringView8) {
-  StringView view8_bit = StringView(kChars8, 5);
+  StringView view8_bit = StringView(kChars8, 5u);
 
   // StringView(StringView&);
   ASSERT_TRUE(StringView(view8_bit).Is8Bit());
@@ -325,18 +325,18 @@
   EXPECT_STREQ(kChars, StringView(kChars).ToString().Utf8().data());
 
   // StringView(const LChar* chars, unsigned length);
-  ASSERT_TRUE(StringView(kChars8, 2).Is8Bit());
-  EXPECT_FALSE(StringView(kChars8, 2).IsNull());
-  EXPECT_EQ(2u, StringView(kChars8, 2).length());
-  EXPECT_EQ(StringView("12"), StringView(kChars8, 2));
-  EXPECT_STREQ("12", StringView(kChars8, 2).ToString().Utf8().data());
+  ASSERT_TRUE(StringView(kChars8, 2u).Is8Bit());
+  EXPECT_FALSE(StringView(kChars8, 2u).IsNull());
+  EXPECT_EQ(2u, StringView(kChars8, 2u).length());
+  EXPECT_EQ(StringView("12"), StringView(kChars8, 2u));
+  EXPECT_STREQ("12", StringView(kChars8, 2u).ToString().Utf8().data());
 
   // StringView(const char* chars, unsigned length);
-  ASSERT_TRUE(StringView(kChars, 2).Is8Bit());
-  EXPECT_FALSE(StringView(kChars, 2).IsNull());
-  EXPECT_EQ(2u, StringView(kChars, 2).length());
-  EXPECT_EQ(StringView("12"), StringView(kChars, 2));
-  EXPECT_STREQ("12", StringView(kChars, 2).ToString().Utf8().data());
+  ASSERT_TRUE(StringView(kChars, 2u).Is8Bit());
+  EXPECT_FALSE(StringView(kChars, 2u).IsNull());
+  EXPECT_EQ(2u, StringView(kChars, 2u).length());
+  EXPECT_EQ(StringView("12"), StringView(kChars, 2u));
+  EXPECT_STREQ("12", StringView(kChars, 2u).ToString().Utf8().data());
 }
 
 TEST(StringViewTest, ConstructionLiteral16) {
@@ -348,14 +348,14 @@
   EXPECT_EQ(String(kChars16), StringView(kChars16).ToString().Utf8().data());
 
   // StringView(const UChar* chars, unsigned length);
-  ASSERT_FALSE(StringView(kChars16, 2).Is8Bit());
-  EXPECT_FALSE(StringView(kChars16, 2).IsNull());
-  EXPECT_EQ(kChars16, StringView(kChars16, 2).Characters16());
-  EXPECT_EQ(StringView("12"), StringView(kChars16, 2));
+  ASSERT_FALSE(StringView(kChars16, 2u).Is8Bit());
+  EXPECT_FALSE(StringView(kChars16, 2u).IsNull());
+  EXPECT_EQ(kChars16, StringView(kChars16, 2u).Characters16());
+  EXPECT_EQ(StringView("12"), StringView(kChars16, 2u));
   EXPECT_EQ(StringView(reinterpret_cast<const UChar*>(u"12")),
-            StringView(kChars16, 2));
-  EXPECT_EQ(2u, StringView(kChars16, 2).length());
-  EXPECT_EQ(String("12"), StringView(kChars16, 2).ToString());
+            StringView(kChars16, 2u));
+  EXPECT_EQ(2u, StringView(kChars16, 2u).length());
+  EXPECT_EQ(String("12"), StringView(kChars16, 2u).ToString());
 }
 
 TEST(StringViewTest, IsEmpty) {
@@ -379,7 +379,7 @@
 TEST(StringViewTest, ToAtomicString) {
   EXPECT_EQ(g_null_atom.Impl(), StringView().ToAtomicString());
   EXPECT_EQ(g_empty_atom.Impl(), StringView("").ToAtomicString());
-  EXPECT_EQ(AtomicString("12"), StringView(kChars8, 2).ToAtomicString());
+  EXPECT_EQ(AtomicString("12"), StringView(kChars8, 2u).ToAtomicString());
   // AtomicString will convert to 8bit if possible when creating the string.
   EXPECT_EQ(AtomicString("12").Impl(),
             StringView(kChars16, 2).ToAtomicString().Impl());
diff --git a/third_party/blink/renderer/platform/wtf/text/text_codec.cc b/third_party/blink/renderer/platform/wtf/text/text_codec.cc
index e1526e29..39ee19f0 100644
--- a/third_party/blink/renderer/platform/wtf/text/text_codec.cc
+++ b/third_party/blink/renderer/platform/wtf/text/text_codec.cc
@@ -30,7 +30,7 @@
 
 TextCodec::~TextCodec() = default;
 
-int TextCodec::GetUnencodableReplacement(
+uint32_t TextCodec::GetUnencodableReplacement(
     unsigned code_point,
     UnencodableHandling handling,
     UnencodableReplacementArray replacement) {
@@ -38,16 +38,16 @@
     case kEntitiesForUnencodables:
       snprintf(replacement, sizeof(UnencodableReplacementArray), "&#%u;",
                code_point);
-      return static_cast<int>(strlen(replacement));
+      return static_cast<uint32_t>(strlen(replacement));
     case kURLEncodedEntitiesForUnencodables:
       snprintf(replacement, sizeof(UnencodableReplacementArray),
                "%%26%%23%u%%3B", code_point);
-      return static_cast<int>(strlen(replacement));
+      return static_cast<uint32_t>(strlen(replacement));
 
     case kCSSEncodedEntitiesForUnencodables:
       snprintf(replacement, sizeof(UnencodableReplacementArray), "\\%x ",
                code_point);
-      return static_cast<int>(strlen(replacement));
+      return static_cast<uint32_t>(strlen(replacement));
   }
   NOTREACHED();
   replacement[0] = 0;
diff --git a/third_party/blink/renderer/platform/wtf/text/text_codec.h b/third_party/blink/renderer/platform/wtf/text/text_codec.h
index 63b58ba..e13cad7 100644
--- a/third_party/blink/renderer/platform/wtf/text/text_codec.h
+++ b/third_party/blink/renderer/platform/wtf/text/text_codec.h
@@ -93,9 +93,9 @@
   // Fills a null-terminated string representation of the given
   // unencodable character into the given replacement buffer.
   // The length of the string (not including the null) will be returned.
-  static int GetUnencodableReplacement(unsigned code_point,
-                                       UnencodableHandling,
-                                       UnencodableReplacementArray);
+  static uint32_t GetUnencodableReplacement(unsigned code_point,
+                                            UnencodableHandling,
+                                            UnencodableReplacementArray);
 
   DISALLOW_COPY_AND_ASSIGN(TextCodec);
 };
diff --git a/third_party/blink/renderer/platform/wtf/text/text_codec_icu.cc b/third_party/blink/renderer/platform/wtf/text/text_codec_icu.cc
index 2a65499..5b93374 100644
--- a/third_party/blink/renderer/platform/wtf/text/text_codec_icu.cc
+++ b/third_party/blink/renderer/platform/wtf/text/text_codec_icu.cc
@@ -472,7 +472,7 @@
     *err = U_ZERO_ERROR;
 
     UnencodableReplacementArray entity;
-    int entity_len =
+    uint32_t entity_len =
         TextCodec::GetUnencodableReplacement(code_point, handling, entity);
     String entity_u(entity, entity_len);
     entity_u.Ensure16Bit();
diff --git a/third_party/blink/renderer/platform/wtf/text/wtf_string.cc b/third_party/blink/renderer/platform/wtf/text/wtf_string.cc
index fe4c2db..4f7effa 100644
--- a/third_party/blink/renderer/platform/wtf/text/wtf_string.cc
+++ b/third_party/blink/renderer/platform/wtf/text/wtf_string.cc
@@ -58,6 +58,11 @@
                                      length)
                 : nullptr) {}
 
+#if defined(ARCH_CPU_64_BITS)
+String::String(const char* characters, size_t length)
+    : String(characters, SafeCast<unsigned>(length)) {}
+#endif  // defined(ARCH_CPU_64_BITS)
+
 void String::append(const StringView& string) {
   if (string.IsEmpty())
     return;
diff --git a/third_party/blink/renderer/platform/wtf/text/wtf_string.h b/third_party/blink/renderer/platform/wtf/text/wtf_string.h
index af805517..a177893f9 100644
--- a/third_party/blink/renderer/platform/wtf/text/wtf_string.h
+++ b/third_party/blink/renderer/platform/wtf/text/wtf_string.h
@@ -27,6 +27,7 @@
 // on systems without case-sensitive file systems.
 
 #include <iosfwd>
+#include "build/build_config.h"
 #include "third_party/blink/renderer/platform/wtf/allocator.h"
 #include "third_party/blink/renderer/platform/wtf/compiler.h"
 #include "third_party/blink/renderer/platform/wtf/hash_table_deleted_value_type.h"
@@ -88,6 +89,12 @@
   String(const LChar* characters, unsigned length);
   String(const char* characters, unsigned length);
 
+#if defined(ARCH_CPU_64_BITS)
+  // Only define a size_t constructor if size_t is 64 bit otherwise
+  // we'd have a duplicate define.
+  String(const char* characters, size_t length);
+#endif  // defined(ARCH_CPU_64_BITS)
+
   // Construct a string with latin1 data, from a null-terminated source.
   String(const LChar* characters)
       : String(reinterpret_cast<const char*>(characters)) {}
diff --git a/third_party/blink/renderer/platform/wtf/text/wtf_string_test.cc b/third_party/blink/renderer/platform/wtf/text/wtf_string_test.cc
index b2a3af61..01adf9e 100644
--- a/third_party/blink/renderer/platform/wtf/text/wtf_string_test.cc
+++ b/third_party/blink/renderer/platform/wtf/text/wtf_string_test.cc
@@ -475,16 +475,16 @@
   EXPECT_EQ(CString("\"\\\\\""), ToCStringThroughPrinter("\\"));
   EXPECT_EQ(
       CString("\"\\u0000\\u0001\\u0002\\u0003\\u0004\\u0005\\u0006\\u0007\""),
-      ToCStringThroughPrinter(String("\x00\x01\x02\x03\x04\x05\x06\x07", 8)));
+      ToCStringThroughPrinter(String("\x00\x01\x02\x03\x04\x05\x06\x07", 8u)));
   EXPECT_EQ(
       CString("\"\\u0008\\t\\n\\u000B\\u000C\\r\\u000E\\u000F\""),
-      ToCStringThroughPrinter(String("\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", 8)));
+      ToCStringThroughPrinter(String("\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", 8u)));
   EXPECT_EQ(
       CString("\"\\u0010\\u0011\\u0012\\u0013\\u0014\\u0015\\u0016\\u0017\""),
-      ToCStringThroughPrinter(String("\x10\x11\x12\x13\x14\x15\x16\x17", 8)));
+      ToCStringThroughPrinter(String("\x10\x11\x12\x13\x14\x15\x16\x17", 8u)));
   EXPECT_EQ(
       CString("\"\\u0018\\u0019\\u001A\\u001B\\u001C\\u001D\\u001E\\u001F\""),
-      ToCStringThroughPrinter(String("\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F", 8)));
+      ToCStringThroughPrinter(String("\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F", 8u)));
   EXPECT_EQ(CString("\"\\u007F\\u0080\\u0081\""),
             ToCStringThroughPrinter("\x7F\x80\x81"));
   EXPECT_EQ(CString("\"\""), ToCStringThroughPrinter(g_empty_string));
diff --git a/third_party/blink/tools/blinkpy/web_tests/models/test_expectations.py b/third_party/blink/tools/blinkpy/web_tests/models/test_expectations.py
index e9ca9f5..96ced39 100644
--- a/third_party/blink/tools/blinkpy/web_tests/models/test_expectations.py
+++ b/third_party/blink/tools/blinkpy/web_tests/models/test_expectations.py
@@ -936,7 +936,7 @@
         MISSING: 'missing results',
     }
 
-    NON_TEST_OUTCOME_EXPECTATIONS = (REBASELINE, SKIP, SLOW, WONTFIX)
+    NON_TEST_OUTCOME_EXPECTATIONS = (REBASELINE, SLOW, WONTFIX)
 
     BUILD_TYPES = ('debug', 'release')
 
@@ -983,9 +983,9 @@
             return True
         if result in (TEXT, IMAGE, IMAGE_PLUS_TEXT, AUDIO) and FAIL in expected_results:
             return True
-        if result == MISSING and test_needs_rebaselining:
+        if result == SKIP and WONTFIX in expected_results:
             return True
-        if result == SKIP:
+        if result == MISSING and test_needs_rebaselining:
             return True
         return False
 
diff --git a/third_party/blink/tools/blinkpy/web_tests/models/test_expectations_unittest.py b/third_party/blink/tools/blinkpy/web_tests/models/test_expectations_unittest.py
index 61d1eb7..d07f353d 100644
--- a/third_party/blink/tools/blinkpy/web_tests/models/test_expectations_unittest.py
+++ b/third_party/blink/tools/blinkpy/web_tests/models/test_expectations_unittest.py
@@ -129,8 +129,8 @@
         self.assertEqual(TestExpectations.result_was_expected(FAIL, set([PASS]), test_needs_rebaselining=False), False)
 
         # test handling of SKIPped tests and results
-        self.assertEqual(TestExpectations.result_was_expected(SKIP, set([CRASH]), test_needs_rebaselining=False), True)
-        self.assertEqual(TestExpectations.result_was_expected(SKIP, set([LEAK]), test_needs_rebaselining=False), True)
+        self.assertEqual(TestExpectations.result_was_expected(SKIP, set([CRASH]), test_needs_rebaselining=False), False)
+        self.assertEqual(TestExpectations.result_was_expected(SKIP, set([LEAK]), test_needs_rebaselining=False), False)
 
         # test handling of MISSING results and the REBASELINE specifier
         self.assertEqual(TestExpectations.result_was_expected(MISSING, set([PASS]), test_needs_rebaselining=True), True)
diff --git a/third_party/blink/tools/blinkpy/web_tests/models/test_run_results.py b/third_party/blink/tools/blinkpy/web_tests/models/test_run_results.py
index 3e7668df..ad6448de 100644
--- a/third_party/blink/tools/blinkpy/web_tests/models/test_run_results.py
+++ b/third_party/blink/tools/blinkpy/web_tests/models/test_run_results.py
@@ -245,16 +245,28 @@
                     has_unexpected_pass = True
             else:
                 has_expected = True
-        # A test is flaky if it has both expected and unexpected runs (NOT pass
-        # and failure).
+
+        # TODO(crbug.com/855255): This code calls a test flaky if it has both
+        # expected and unexpected runs (NOT pass and failure); this is generally
+        # wrong (really it should just be if there are multiple kinds of results),
+        # but this works in the normal case because a test will only be retried
+        # if a result is unexpected, and if you get an expected result on the
+        # retry, then you did get multiple results. This fails if you get
+        # one kind of unexpected failure initially and another kind of
+        # unexpected failure on the retry (e.g., TIMEOUT CRASH), or if you
+        # explicitly run a test multiple times and get multiple expected results.
         is_flaky = has_expected and has_unexpected
 
-        if len(set(actual)) == 1:
-            actual = [actual[0]]
-            actual_types = [actual_types[0]]
+        test_dict = {}
+        test_dict['expected'] = expected
+        test_dict['actual'] = ' '.join(actual)
+
+        # Fields below are optional. To avoid bloating the output results json
+        # too much, only add them when they are True or non-empty.
 
         if is_flaky:
             num_flaky += 1
+            test_dict['is_flaky'] = True
         elif all_pass or has_unexpected_pass:
             # We count two situations as a "pass":
             # 1. All test runs pass (which is obviously non-flaky, but does not
@@ -268,19 +280,10 @@
             num_passes += 1
             if not has_stderr and only_include_failing:
                 continue
-        elif has_unexpected and result.type != test_expectations.SKIP:
+        elif has_unexpected:
             # Either no retries or all retries failed unexpectedly.
-            # TODO(robertma): When will there be unexpected skip? Do we really
-            # want to ignore them when counting regressions?
             num_regressions += 1
 
-        test_dict = {}
-
-        test_dict['expected'] = expected
-        test_dict['actual'] = ' '.join(actual)
-
-        # Fields below are optional. To avoid bloating the output results json
-        # too much, only add them when they are True or non-empty.
 
         rounded_run_time = round(initial_result.test_run_time, 1)
         if rounded_run_time:
@@ -318,11 +321,15 @@
                                                            port_obj.get_option('pixel_tests') or initial_result.reftest_type,
                                                            port_obj.get_option('enable_sanitizer'))
 
-        # Note: is_unexpected is intended to capture the *last* result. In the
-        # normal use case (stop retrying failures once they pass), this is
-        # equivalent to checking if none of the results is expected.
-        if not any(is_expected(actual_result) for actual_result in actual_types):
+        # Note: is_unexpected and is_regression are intended to reflect the
+        # *last* result. In the normal use case (stop retrying failures
+        # once they pass), this is equivalent to saying that all of the
+        # results were unexpected failures.
+        last_result = actual_types[-1]
+        if not is_expected(last_result):
             test_dict['is_unexpected'] = True
+            if last_result != test_expectations.PASS:
+                test_dict['is_regression'] = True
 
         if initial_result.has_repaint_overlay:
             test_dict['has_repaint_overlay'] = True
diff --git a/third_party/blink/tools/blinkpy/web_tests/models/test_run_results_unittest.py b/third_party/blink/tools/blinkpy/web_tests/models/test_run_results_unittest.py
index 2e19b54..5110c43 100644
--- a/third_party/blink/tools/blinkpy/web_tests/models/test_run_results_unittest.py
+++ b/third_party/blink/tools/blinkpy/web_tests/models/test_run_results_unittest.py
@@ -83,7 +83,7 @@
     elif passing:
         skipped_result = get_result('passes/skipped/skip.html')
         skipped_result.type = test_expectations.SKIP
-        initial_results.add(skipped_result, expected, test_is_slow)
+        initial_results.add(skipped_result, True, test_is_slow)
 
         initial_results.add(get_result('passes/text.html', run_time=1), expected, test_is_slow)
         initial_results.add(get_result('failures/expected/audio.html'), expected, test_is_slow)
@@ -288,7 +288,6 @@
         self.port._options.builder_name = 'dummy builder'
         summary = summarized_results(self.port, expected=False, passing=True, flaky=False)
         self.assertTrue(summary['tests']['passes']['text.html'])
-        self.assertTrue('is_unexpected' not in summary['tests']['passes']['text.html'])
         self.assertEqual(summary['num_passes'], 5)
         self.assertEqual(summary['num_regressions'], 0)
         self.assertEqual(summary['num_flaky'], 0)
@@ -350,7 +349,6 @@
     def test_summarized_results_flaky(self):
         summary = summarized_results(self.port, expected=False, passing=False, flaky=True)
 
-        self.assertTrue('is_unexpected' not in summary['tests']['failures']['expected']['crash.html'])
         self.assertEquals(summary['tests']['failures']['expected']['crash.html']['expected'], 'CRASH')
         self.assertEquals(summary['tests']['failures']['expected']['crash.html']['actual'], 'TIMEOUT AUDIO CRASH LEAK')
 
@@ -428,15 +426,15 @@
 
         self.assertTrue(summary['tests']['passes']['text.html']['is_unexpected'])
         self.assertEquals(summary['tests']['passes']['text.html']['expected'], 'PASS')
-        self.assertEquals(summary['tests']['passes']['text.html']['actual'], 'TIMEOUT')
+        self.assertEquals(summary['tests']['passes']['text.html']['actual'], 'TIMEOUT TIMEOUT TIMEOUT TIMEOUT')
 
         self.assertTrue(summary['tests']['failures']['expected']['crash.html']['is_unexpected'])
         self.assertEquals(summary['tests']['failures']['expected']['crash.html']['expected'], 'CRASH')
-        self.assertEquals(summary['tests']['failures']['expected']['crash.html']['actual'], 'TIMEOUT')
+        self.assertEquals(summary['tests']['failures']['expected']['crash.html']['actual'], 'TIMEOUT TIMEOUT TIMEOUT TIMEOUT')
 
         self.assertTrue(summary['tests']['failures']['expected']['leak.html']['is_unexpected'])
         self.assertEquals(summary['tests']['failures']['expected']['leak.html']['expected'], 'LEAK')
-        self.assertEquals(summary['tests']['failures']['expected']['leak.html']['actual'], 'TIMEOUT')
+        self.assertEquals(summary['tests']['failures']['expected']['leak.html']['actual'], 'TIMEOUT TIMEOUT TIMEOUT TIMEOUT')
 
         self.assertTrue(summary['tests']['failures']['expected']['audio.html']['is_unexpected'])
         self.assertEquals(summary['tests']['failures']['expected']['audio.html']['expected'], 'FAIL')
diff --git a/third_party/blink/tools/blinkpy/web_tests/run_webkit_tests_unittest.py b/third_party/blink/tools/blinkpy/web_tests/run_webkit_tests_unittest.py
index 6afde67..8268120 100644
--- a/third_party/blink/tools/blinkpy/web_tests/run_webkit_tests_unittest.py
+++ b/third_party/blink/tools/blinkpy/web_tests/run_webkit_tests_unittest.py
@@ -617,16 +617,27 @@
                                      'failures/unexpected/text-image-checksum.html'],
                                     tests_included=True, host=host)
         self.assertEqual(details.exit_code, 2)
-        json_string = host.filesystem.read_text_file('/tmp/layout-test-results/full_results.json')
-        self.assertTrue(json_string.find(
-            '"text-image-checksum.html":{'
-            '"expected":"PASS",'
-            '"text_mismatch":"general text mismatch",'
-            '"actual":"IMAGE+TEXT","is_unexpected":true') != -1)
-        self.assertTrue(json_string.find(
-            '"missing_text.html":{"expected":"PASS","is_missing_text":true,"actual":"MISSING","is_unexpected":true') != -1)
-        self.assertTrue(json_string.find('"num_regressions":2') != -1)
-        self.assertTrue(json_string.find('"num_flaky":0') != -1)
+        results = json.loads(host.filesystem.read_text_file('/tmp/layout-test-results/full_results.json'))
+        self.assertEqual(
+            results['tests']['failures']['unexpected']['text-image-checksum.html'],
+            {
+                'expected': 'PASS',
+                'actual': 'IMAGE+TEXT',
+                'is_unexpected': True,
+                'is_regression': True,
+                'text_mismatch': 'general text mismatch',
+            })
+        self.assertEqual(
+            results['tests']['failures']['unexpected']['missing_text.html'],
+            {
+                'expected': 'PASS',
+                'actual': 'MISSING',
+                'is_unexpected': True,
+                'is_regression': True,
+                'is_missing_text': True,
+            })
+        self.assertEqual(results['num_regressions'], 2)
+        self.assertEqual(results['num_flaky'], 0)
 
     def test_different_failure_on_retry(self):
         # This tests that if a test fails two different ways -- both unexpected
@@ -659,8 +670,8 @@
     def test_crash_with_stderr(self):
         host = MockHost()
         logging_run(['failures/unexpected/crash-with-stderr.html'], tests_included=True, host=host)
-        self.assertTrue(host.filesystem.read_text_file('/tmp/layout-test-results/full_results.json').find(
-            '{"crash-with-stderr.html":{"expected":"PASS","actual":"CRASH","has_stderr":true,"is_unexpected":true') != -1)
+        full_results = json.loads(host.filesystem.read_text_file('/tmp/layout-test-results/full_results.json'))
+        self.assertEqual(full_results['tests']['failures']['unexpected']['crash-with-stderr.html']['has_stderr'], True)
 
     def test_no_image_failure_with_image_diff(self):
         host = MockHost()
@@ -828,11 +839,15 @@
             host.filesystem.exists('/tmp/layout-test-results/retry_3/failures/unexpected/text-image-checksum-actual.png'))
         json_string = host.filesystem.read_text_file('/tmp/layout-test-results/full_results.json')
         results = parse_full_results(json_string)
-        self.assertEqual(results['tests']['failures']['unexpected']['text-image-checksum.html'],
-                         {'expected': 'PASS',
-                          'actual': 'TEXT IMAGE+TEXT IMAGE+TEXT IMAGE+TEXT',
-                          'is_unexpected': True,
-                          'text_mismatch': 'general text mismatch'})
+        self.assertEqual(
+            results['tests']['failures']['unexpected']['text-image-checksum.html'],
+            {
+                'expected': 'PASS',
+                'actual': 'TEXT IMAGE+TEXT IMAGE+TEXT IMAGE+TEXT',
+                'is_regression': True,
+                'is_unexpected': True,
+                'text_mismatch': 'general text mismatch',
+            })
         self.assertFalse(results['pixel_tests_enabled'])
         self.assertTrue(details.enabled_pixel_tests_in_retry)
 
@@ -925,7 +940,7 @@
         host = MockHost()
         logging_run(['--no-show-results', 'reftests/foo/'], tests_included=True, host=host)
         results = parse_full_results(host.filesystem.read_text_file('/tmp/layout-test-results/full_results.json'))
-        self.assertEqual(results['tests']['reftests']['foo']['unlistedtest.html']['actual'], 'MISSING')
+        self.assertEqual(results['tests']['reftests']['foo']['unlistedtest.html']['actual'], 'MISSING MISSING MISSING MISSING')
         self.assertEqual(results['num_regressions'], 5)
         self.assertEqual(results['num_flaky'], 0)
 
@@ -1124,12 +1139,33 @@
         self.assertTrue('multiple-mismatch-success.html' not in results['tests']['reftests']['foo'])
         self.assertTrue('multiple-both-success.html' not in results['tests']['reftests']['foo'])
 
-        self.assertEqual(results['tests']['reftests']['foo']['multiple-match-failure.html'],
-                         {'expected': 'PASS', 'actual': 'IMAGE', 'reftest_type': ['=='], 'is_unexpected': True})
-        self.assertEqual(results['tests']['reftests']['foo']['multiple-mismatch-failure.html'],
-                         {'expected': 'PASS', 'actual': 'IMAGE', 'reftest_type': ['!='], 'is_unexpected': True})
-        self.assertEqual(results['tests']['reftests']['foo']['multiple-both-failure.html'],
-                         {'expected': 'PASS', 'actual': 'IMAGE', 'reftest_type': ['==', '!='], 'is_unexpected': True})
+        self.assertEqual(
+            results['tests']['reftests']['foo']['multiple-match-failure.html'],
+            {
+                'expected': 'PASS',
+                'actual': 'IMAGE IMAGE IMAGE IMAGE',
+                'reftest_type': ['=='],
+                'is_regression': True,
+                'is_unexpected': True,
+            })
+        self.assertEqual(
+            results['tests']['reftests']['foo']['multiple-mismatch-failure.html'],
+            {
+                'expected': 'PASS',
+                'actual': 'IMAGE IMAGE IMAGE IMAGE',
+                'reftest_type': ['!='],
+                'is_regression': True,
+                'is_unexpected': True,
+            })
+        self.assertEqual(
+            results['tests']['reftests']['foo']['multiple-both-failure.html'],
+            {
+                'expected': 'PASS',
+                'actual': 'IMAGE IMAGE IMAGE IMAGE',
+                'reftest_type': ['==', '!='],
+                'is_regression': True,
+                'is_unexpected': True,
+            })
 
 
 class RebaselineTest(unittest.TestCase, StreamTestingMixin):
diff --git a/third_party/byte_buddy/BUILD.gn b/third_party/byte_buddy/BUILD.gn
index 2f81deb4..b0c1b5d 100644
--- a/third_party/byte_buddy/BUILD.gn
+++ b/third_party/byte_buddy/BUILD.gn
@@ -5,6 +5,22 @@
 import("//build/config/android/rules.gni")
 
 java_prebuilt("byte_buddy_java") {
+  supports_android = true
   testonly = true
   jar_path = "lib/byte-buddy.jar"
 }
+
+java_prebuilt("byte_buddy_agent_java") {
+  supports_android = true
+  testonly = true
+  jar_path = "lib/byte-buddy-agent.jar"
+}
+
+android_java_prebuilt("byte_buddy_android_java") {
+  testonly = true
+  deps = [
+    "//third_party/android_tools:dx_25_0_2_java",
+  ]
+  proguard_configs = [ "//third_party/byte_buddy/proguard.flags" ]
+  jar_path = "lib/byte-buddy-android.jar"
+}
diff --git a/third_party/byte_buddy/README.chromium b/third_party/byte_buddy/README.chromium
index 052e6df76..94aa424 100644
--- a/third_party/byte_buddy/README.chromium
+++ b/third_party/byte_buddy/README.chromium
@@ -1,10 +1,10 @@
 Name: Byte Buddy
 URL: http://bytebuddy.net/
-Version: 1.4.17
+Version: 1.8.8
 License: Apache 2.0
 License File: NOT_SHIPPED
 Security Critical: no
 Description:
 Byte Buddy is a code generation library for creating Java classes at runtime.
 
-Local Modifications: None
\ No newline at end of file
+Local Modifications: None
diff --git a/third_party/byte_buddy/cipd.yaml b/third_party/byte_buddy/cipd.yaml
index a43ae1e..db4fc1d 100644
--- a/third_party/byte_buddy/cipd.yaml
+++ b/third_party/byte_buddy/cipd.yaml
@@ -7,4 +7,6 @@
 package: chromium/third_party/byte_buddy
 description: byte_buddy Java library
 data:
+  - file: lib/byte-buddy-agent.jar
+  - file: lib/byte-buddy-android.jar
   - file: lib/byte-buddy.jar
diff --git a/third_party/byte_buddy/proguard.flags b/third_party/byte_buddy/proguard.flags
new file mode 100644
index 0000000..0476f36
--- /dev/null
+++ b/third_party/byte_buddy/proguard.flags
@@ -0,0 +1,9 @@
+# Copyright 2018 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+-dontwarn net.bytebuddy.**
+
+-keep class net.bytebuddy.** {
+  *;
+}
diff --git a/third_party/mockito/BUILD.gn b/third_party/mockito/BUILD.gn
index ad2b01b7..2c19da2 100644
--- a/third_party/mockito/BUILD.gn
+++ b/third_party/mockito/BUILD.gn
@@ -6,343 +6,476 @@
 
 java_library("mockito_java") {
   chromium_code = false
+  supports_android = true
   testonly = true
   deps = [
+    "//third_party/byte_buddy:byte_buddy_agent_java",
     "//third_party/byte_buddy:byte_buddy_java",
     "//third_party/hamcrest:hamcrest_java",
     "//third_party/junit:junit",
     "//third_party/objenesis:objenesis_java",
   ]
   java_files = [
+    "src/src/main/java/org/mockito/quality/MockitoHint.java",
+    "src/src/main/java/org/mockito/quality/package-info.java",
+    "src/src/main/java/org/mockito/quality/Strictness.java",
     "src/src/main/java/org/mockito/AdditionalAnswers.java",
-    "src/src/main/java/org/mockito/AdditionalMatchers.java",
-    "src/src/main/java/org/mockito/Answers.java",
-    "src/src/main/java/org/mockito/ArgumentCaptor.java",
-    "src/src/main/java/org/mockito/ArgumentMatcher.java",
-    "src/src/main/java/org/mockito/ArgumentMatchers.java",
-    "src/src/main/java/org/mockito/BDDMockito.java",
-    "src/src/main/java/org/mockito/Captor.java",
-    "src/src/main/java/org/mockito/InOrder.java",
-    "src/src/main/java/org/mockito/Incubating.java",
     "src/src/main/java/org/mockito/InjectMocks.java",
+    "src/src/main/java/org/mockito/NotExtensible.java",
+    "src/src/main/java/org/mockito/verification/VerificationMode.java",
+    "src/src/main/java/org/mockito/verification/After.java",
+    "src/src/main/java/org/mockito/verification/VerificationAfterDelay.java",
+    "src/src/main/java/org/mockito/verification/VerificationStrategy.java",
+    "src/src/main/java/org/mockito/verification/VerificationWithTimeout.java",
+    "src/src/main/java/org/mockito/verification/VerificationEvent.java",
+    "src/src/main/java/org/mockito/verification/package-info.java",
+    "src/src/main/java/org/mockito/verification/Timeout.java",
     "src/src/main/java/org/mockito/Matchers.java",
-    "src/src/main/java/org/mockito/Mock.java",
     "src/src/main/java/org/mockito/MockSettings.java",
-    "src/src/main/java/org/mockito/MockingDetails.java",
-    "src/src/main/java/org/mockito/Mockito.java",
-    "src/src/main/java/org/mockito/MockitoAnnotations.java",
-    "src/src/main/java/org/mockito/MockitoDebugger.java",
-    "src/src/main/java/org/mockito/MockitoFramework.java",
-    "src/src/main/java/org/mockito/Spy.java",
-    "src/src/main/java/org/mockito/configuration/AnnotationEngine.java",
-    "src/src/main/java/org/mockito/configuration/DefaultMockitoConfiguration.java",
-    "src/src/main/java/org/mockito/configuration/IMockitoConfiguration.java",
-    "src/src/main/java/org/mockito/exceptions/base/MockitoAssertionError.java",
-    "src/src/main/java/org/mockito/exceptions/base/MockitoException.java",
-    "src/src/main/java/org/mockito/exceptions/base/MockitoSerializationIssue.java",
-    "src/src/main/java/org/mockito/exceptions/misusing/CannotStubVoidMethodWithReturnValue.java",
-    "src/src/main/java/org/mockito/exceptions/misusing/CannotVerifyStubOnlyMock.java",
-    "src/src/main/java/org/mockito/exceptions/misusing/FriendlyReminderException.java",
-    "src/src/main/java/org/mockito/exceptions/misusing/InvalidUseOfMatchersException.java",
-    "src/src/main/java/org/mockito/exceptions/misusing/MissingMethodInvocationException.java",
-    "src/src/main/java/org/mockito/exceptions/misusing/MockitoConfigurationException.java",
-    "src/src/main/java/org/mockito/exceptions/misusing/NotAMockException.java",
-    "src/src/main/java/org/mockito/exceptions/misusing/NullInsteadOfMockException.java",
-    "src/src/main/java/org/mockito/exceptions/misusing/UnfinishedStubbingException.java",
-    "src/src/main/java/org/mockito/exceptions/misusing/UnfinishedVerificationException.java",
-    "src/src/main/java/org/mockito/exceptions/misusing/UnnecessaryStubbingException.java",
-    "src/src/main/java/org/mockito/exceptions/misusing/WrongTypeOfReturnValue.java",
-    "src/src/main/java/org/mockito/exceptions/stacktrace/StackTraceCleaner.java",
-    "src/src/main/java/org/mockito/exceptions/verification/ArgumentsAreDifferent.java",
-    "src/src/main/java/org/mockito/exceptions/verification/NeverWantedButInvoked.java",
-    "src/src/main/java/org/mockito/exceptions/verification/NoInteractionsWanted.java",
-    "src/src/main/java/org/mockito/exceptions/verification/SmartNullPointerException.java",
-    "src/src/main/java/org/mockito/exceptions/verification/TooLittleActualInvocations.java",
-    "src/src/main/java/org/mockito/exceptions/verification/TooManyActualInvocations.java",
-    "src/src/main/java/org/mockito/exceptions/verification/VerificationInOrderFailure.java",
-    "src/src/main/java/org/mockito/exceptions/verification/WantedButNotInvoked.java",
-    "src/src/main/java/org/mockito/exceptions/verification/junit/ArgumentsAreDifferent.java",
+    "src/src/main/java/org/mockito/Captor.java",
+    "src/src/main/java/org/mockito/ArgumentMatcher.java",
+    "src/src/main/java/org/mockito/stubbing/OngoingStubbing.java",
+    "src/src/main/java/org/mockito/stubbing/ValidableAnswer.java",
+    "src/src/main/java/org/mockito/stubbing/VoidAnswer3.java",
+    "src/src/main/java/org/mockito/stubbing/VoidAnswer4.java",
+    "src/src/main/java/org/mockito/stubbing/Answer1.java",
+    "src/src/main/java/org/mockito/stubbing/VoidAnswer1.java",
+    "src/src/main/java/org/mockito/stubbing/VoidAnswer2.java",
+    "src/src/main/java/org/mockito/stubbing/VoidAnswer5.java",
+    "src/src/main/java/org/mockito/stubbing/Answer.java",
+    "src/src/main/java/org/mockito/stubbing/Answer2.java",
+    "src/src/main/java/org/mockito/stubbing/Answer5.java",
+    "src/src/main/java/org/mockito/stubbing/Stubbing.java",
+    "src/src/main/java/org/mockito/stubbing/Answer3.java",
+    "src/src/main/java/org/mockito/stubbing/package-info.java",
+    "src/src/main/java/org/mockito/stubbing/Stubber.java",
+    "src/src/main/java/org/mockito/stubbing/Answer4.java",
+    "src/src/main/java/org/mockito/Answers.java",
+    "src/src/main/java/org/mockito/hamcrest/package-info.java",
     "src/src/main/java/org/mockito/hamcrest/MockitoHamcrest.java",
-    "src/src/main/java/org/mockito/internal/DefaultMockitoFramework.java",
-    "src/src/main/java/org/mockito/internal/InOrderImpl.java",
-    "src/src/main/java/org/mockito/internal/InternalMockHandler.java",
-    "src/src/main/java/org/mockito/internal/MockitoCore.java",
-    "src/src/main/java/org/mockito/internal/configuration/CaptorAnnotationProcessor.java",
-    "src/src/main/java/org/mockito/internal/configuration/ClassPathLoader.java",
-    "src/src/main/java/org/mockito/internal/configuration/DefaultAnnotationEngine.java",
-    "src/src/main/java/org/mockito/internal/configuration/DefaultInjectionEngine.java",
-    "src/src/main/java/org/mockito/internal/configuration/FieldAnnotationProcessor.java",
-    "src/src/main/java/org/mockito/internal/configuration/GlobalConfiguration.java",
-    "src/src/main/java/org/mockito/internal/configuration/InjectingAnnotationEngine.java",
-    "src/src/main/java/org/mockito/internal/configuration/MockAnnotationProcessor.java",
-    "src/src/main/java/org/mockito/internal/configuration/SpyAnnotationEngine.java",
-    "src/src/main/java/org/mockito/internal/configuration/injection/ConstructorInjection.java",
-    "src/src/main/java/org/mockito/internal/configuration/injection/MockInjection.java",
-    "src/src/main/java/org/mockito/internal/configuration/injection/MockInjectionStrategy.java",
-    "src/src/main/java/org/mockito/internal/configuration/injection/PropertyAndSetterInjection.java",
-    "src/src/main/java/org/mockito/internal/configuration/injection/SpyOnInjectedFieldsHandler.java",
-    "src/src/main/java/org/mockito/internal/configuration/injection/filter/MockCandidateFilter.java",
-    "src/src/main/java/org/mockito/internal/configuration/injection/filter/NameBasedCandidateFilter.java",
-    "src/src/main/java/org/mockito/internal/configuration/injection/filter/OngoingInjector.java",
-    "src/src/main/java/org/mockito/internal/configuration/injection/filter/TerminalMockCandidateFilter.java",
-    "src/src/main/java/org/mockito/internal/configuration/injection/filter/TypeBasedCandidateFilter.java",
-    "src/src/main/java/org/mockito/internal/configuration/injection/scanner/InjectMocksScanner.java",
-    "src/src/main/java/org/mockito/internal/configuration/injection/scanner/MockScanner.java",
-    "src/src/main/java/org/mockito/internal/configuration/plugins/DefaultPluginSwitch.java",
-    "src/src/main/java/org/mockito/internal/configuration/plugins/PluginFileReader.java",
-    "src/src/main/java/org/mockito/internal/configuration/plugins/PluginFinder.java",
-    "src/src/main/java/org/mockito/internal/configuration/plugins/PluginLoader.java",
-    "src/src/main/java/org/mockito/internal/configuration/plugins/PluginRegistry.java",
-    "src/src/main/java/org/mockito/internal/configuration/plugins/Plugins.java",
-    "src/src/main/java/org/mockito/internal/creation/DelegatingMethod.java",
-    "src/src/main/java/org/mockito/internal/creation/MockSettingsImpl.java",
-    "src/src/main/java/org/mockito/internal/creation/bytebuddy/ByteBuddyCrossClassLoaderSerializationSupport.java",
-    "src/src/main/java/org/mockito/internal/creation/bytebuddy/ByteBuddyMockMaker.java",
-    "src/src/main/java/org/mockito/internal/creation/bytebuddy/CachingMockBytecodeGenerator.java",
-    "src/src/main/java/org/mockito/internal/creation/bytebuddy/InterceptedInvocation.java",
-    "src/src/main/java/org/mockito/internal/creation/bytebuddy/MockBytecodeGenerator.java",
-    "src/src/main/java/org/mockito/internal/creation/bytebuddy/MockFeatures.java",
-    "src/src/main/java/org/mockito/internal/creation/bytebuddy/MockMethodInterceptor.java",
-    "src/src/main/java/org/mockito/internal/creation/instance/ConstructorInstantiator.java",
-    "src/src/main/java/org/mockito/internal/creation/instance/DefaultInstantiatorProvider.java",
-    "src/src/main/java/org/mockito/internal/creation/instance/InstantiationException.java",
-    "src/src/main/java/org/mockito/internal/creation/instance/Instantiator.java",
-    "src/src/main/java/org/mockito/internal/creation/instance/ObjenesisInstantiator.java",
-    "src/src/main/java/org/mockito/internal/creation/settings/CreationSettings.java",
-    "src/src/main/java/org/mockito/internal/creation/util/MockitoMethodProxy.java",
-    "src/src/main/java/org/mockito/internal/creation/util/SearchingClassLoader.java",
-    "src/src/main/java/org/mockito/internal/debugging/FindingsListener.java",
-    "src/src/main/java/org/mockito/internal/debugging/Localized.java",
-    "src/src/main/java/org/mockito/internal/debugging/LocationImpl.java",
-    "src/src/main/java/org/mockito/internal/debugging/LoggingListener.java",
-    "src/src/main/java/org/mockito/internal/debugging/MockitoDebuggerImpl.java",
-    "src/src/main/java/org/mockito/internal/debugging/VerboseMockInvocationLogger.java",
-    "src/src/main/java/org/mockito/internal/debugging/WarningsCollector.java",
-    "src/src/main/java/org/mockito/internal/debugging/WarningsFinder.java",
-    "src/src/main/java/org/mockito/internal/debugging/WarningsPrinterImpl.java",
-    "src/src/main/java/org/mockito/internal/exceptions/ExceptionIncludingMockitoWarnings.java",
-    "src/src/main/java/org/mockito/internal/exceptions/MockitoLimitations.java",
-    "src/src/main/java/org/mockito/internal/exceptions/Reporter.java",
-    "src/src/main/java/org/mockito/internal/exceptions/VerificationAwareInvocation.java",
-    "src/src/main/java/org/mockito/internal/exceptions/stacktrace/ConditionalStackTraceFilter.java",
-    "src/src/main/java/org/mockito/internal/exceptions/stacktrace/DefaultStackTraceCleaner.java",
-    "src/src/main/java/org/mockito/internal/exceptions/stacktrace/DefaultStackTraceCleanerProvider.java",
-    "src/src/main/java/org/mockito/internal/exceptions/stacktrace/StackTraceFilter.java",
-    "src/src/main/java/org/mockito/internal/exceptions/util/ScenarioPrinter.java",
-    "src/src/main/java/org/mockito/internal/hamcrest/HamcrestArgumentMatcher.java",
-    "src/src/main/java/org/mockito/internal/hamcrest/MatcherGenericTypeExtractor.java",
-    "src/src/main/java/org/mockito/internal/handler/InvocationNotifierHandler.java",
-    "src/src/main/java/org/mockito/internal/handler/MockHandlerFactory.java",
-    "src/src/main/java/org/mockito/internal/handler/MockHandlerImpl.java",
-    "src/src/main/java/org/mockito/internal/handler/NullResultGuardian.java",
-    "src/src/main/java/org/mockito/internal/invocation/AbstractAwareMethod.java",
-    "src/src/main/java/org/mockito/internal/invocation/ArgumentsComparator.java",
-    "src/src/main/java/org/mockito/internal/invocation/ArgumentsProcessor.java",
-    "src/src/main/java/org/mockito/internal/invocation/CapturesArgumentsFromInvocation.java",
-    "src/src/main/java/org/mockito/internal/invocation/InvocationImpl.java",
-    "src/src/main/java/org/mockito/internal/invocation/InvocationMarker.java",
-    "src/src/main/java/org/mockito/internal/invocation/InvocationMatcher.java",
-    "src/src/main/java/org/mockito/internal/invocation/InvocationsFinder.java",
-    "src/src/main/java/org/mockito/internal/invocation/MatchersBinder.java",
-    "src/src/main/java/org/mockito/internal/invocation/MockitoMethod.java",
-    "src/src/main/java/org/mockito/internal/invocation/SerializableMethod.java",
-    "src/src/main/java/org/mockito/internal/invocation/StubInfoImpl.java",
-    "src/src/main/java/org/mockito/internal/invocation/UnusedStubsFinder.java",
-    "src/src/main/java/org/mockito/internal/invocation/finder/AllInvocationsFinder.java",
-    "src/src/main/java/org/mockito/internal/invocation/finder/VerifiableInvocationsFinder.java",
-    "src/src/main/java/org/mockito/internal/invocation/realmethod/CleanTraceRealMethod.java",
-    "src/src/main/java/org/mockito/internal/invocation/realmethod/DefaultRealMethod.java",
-    "src/src/main/java/org/mockito/internal/invocation/realmethod/RealMethod.java",
-    "src/src/main/java/org/mockito/internal/junit/FriendlyExceptionMaker.java",
-    "src/src/main/java/org/mockito/internal/junit/JUnitDetecter.java",
-    "src/src/main/java/org/mockito/internal/junit/JUnitRule.java",
-    "src/src/main/java/org/mockito/internal/junit/JUnitTool.java",
-    "src/src/main/java/org/mockito/internal/listeners/CollectCreatedMocks.java",
-    "src/src/main/java/org/mockito/internal/listeners/MockingProgressListener.java",
-    "src/src/main/java/org/mockito/internal/listeners/MockingStartedListener.java",
-    "src/src/main/java/org/mockito/internal/listeners/NotifiedMethodInvocationReport.java",
-    "src/src/main/java/org/mockito/internal/matchers/And.java",
-    "src/src/main/java/org/mockito/internal/matchers/Any.java",
-    "src/src/main/java/org/mockito/internal/matchers/ArrayEquals.java",
-    "src/src/main/java/org/mockito/internal/matchers/CapturesArguments.java",
-    "src/src/main/java/org/mockito/internal/matchers/CapturingMatcher.java",
-    "src/src/main/java/org/mockito/internal/matchers/CompareEqual.java",
-    "src/src/main/java/org/mockito/internal/matchers/CompareTo.java",
-    "src/src/main/java/org/mockito/internal/matchers/Contains.java",
-    "src/src/main/java/org/mockito/internal/matchers/ContainsExtraTypeInfo.java",
-    "src/src/main/java/org/mockito/internal/matchers/EndsWith.java",
-    "src/src/main/java/org/mockito/internal/matchers/Equality.java",
-    "src/src/main/java/org/mockito/internal/matchers/Equals.java",
-    "src/src/main/java/org/mockito/internal/matchers/EqualsWithDelta.java",
-    "src/src/main/java/org/mockito/internal/matchers/Find.java",
-    "src/src/main/java/org/mockito/internal/matchers/GreaterOrEqual.java",
-    "src/src/main/java/org/mockito/internal/matchers/GreaterThan.java",
-    "src/src/main/java/org/mockito/internal/matchers/InstanceOf.java",
-    "src/src/main/java/org/mockito/internal/matchers/LessOrEqual.java",
-    "src/src/main/java/org/mockito/internal/matchers/LessThan.java",
-    "src/src/main/java/org/mockito/internal/matchers/LocalizedMatcher.java",
-    "src/src/main/java/org/mockito/internal/matchers/Matches.java",
-    "src/src/main/java/org/mockito/internal/matchers/Not.java",
-    "src/src/main/java/org/mockito/internal/matchers/NotNull.java",
-    "src/src/main/java/org/mockito/internal/matchers/Null.java",
-    "src/src/main/java/org/mockito/internal/matchers/Or.java",
-    "src/src/main/java/org/mockito/internal/matchers/Same.java",
-    "src/src/main/java/org/mockito/internal/matchers/StartsWith.java",
-    "src/src/main/java/org/mockito/internal/matchers/VarargMatcher.java",
-    "src/src/main/java/org/mockito/internal/matchers/apachecommons/EqualsBuilder.java",
-    "src/src/main/java/org/mockito/internal/matchers/apachecommons/ReflectionEquals.java",
-    "src/src/main/java/org/mockito/internal/matchers/text/ArrayIterator.java",
-    "src/src/main/java/org/mockito/internal/matchers/text/FormattedText.java",
-    "src/src/main/java/org/mockito/internal/matchers/text/MatcherToString.java",
-    "src/src/main/java/org/mockito/internal/matchers/text/MatchersPrinter.java",
-    "src/src/main/java/org/mockito/internal/matchers/text/ValuePrinter.java",
-    "src/src/main/java/org/mockito/internal/progress/ArgumentMatcherStorage.java",
-    "src/src/main/java/org/mockito/internal/progress/ArgumentMatcherStorageImpl.java",
-    "src/src/main/java/org/mockito/internal/progress/MockingProgress.java",
-    "src/src/main/java/org/mockito/internal/progress/MockingProgressImpl.java",
-    "src/src/main/java/org/mockito/internal/progress/NoOpStubbingListener.java",
-    "src/src/main/java/org/mockito/internal/progress/SequenceNumber.java",
-    "src/src/main/java/org/mockito/internal/progress/ThreadSafeMockingProgress.java",
-    "src/src/main/java/org/mockito/internal/reporting/Discrepancy.java",
-    "src/src/main/java/org/mockito/internal/reporting/Pluralizer.java",
-    "src/src/main/java/org/mockito/internal/reporting/PrintSettings.java",
-    "src/src/main/java/org/mockito/internal/reporting/SmartPrinter.java",
-    "src/src/main/java/org/mockito/internal/runners/RunnerFactory.java",
-    "src/src/main/java/org/mockito/internal/runners/RunnerImpl.java",
-    "src/src/main/java/org/mockito/internal/runners/SilentJUnitRunner.java",
-    "src/src/main/java/org/mockito/internal/runners/StrictRunner.java",
-    "src/src/main/java/org/mockito/internal/runners/UnnecessaryStubbingsReporter.java",
-    "src/src/main/java/org/mockito/internal/runners/util/FailureDetecter.java",
-    "src/src/main/java/org/mockito/internal/runners/util/FrameworkUsageValidator.java",
-    "src/src/main/java/org/mockito/internal/runners/util/RunnerProvider.java",
-    "src/src/main/java/org/mockito/internal/runners/util/TestMethodsFinder.java",
-    "src/src/main/java/org/mockito/internal/stubbing/BaseStubbing.java",
-    "src/src/main/java/org/mockito/internal/stubbing/ConsecutiveStubbing.java",
-    "src/src/main/java/org/mockito/internal/stubbing/InvocationContainer.java",
-    "src/src/main/java/org/mockito/internal/stubbing/InvocationContainerImpl.java",
-    "src/src/main/java/org/mockito/internal/stubbing/OngoingStubbingImpl.java",
-    "src/src/main/java/org/mockito/internal/stubbing/StubbedInvocationMatcher.java",
-    "src/src/main/java/org/mockito/internal/stubbing/StubberImpl.java",
-    "src/src/main/java/org/mockito/internal/stubbing/answers/AnswerFunctionalInterfaces.java",
-    "src/src/main/java/org/mockito/internal/stubbing/answers/AnswersValidator.java",
-    "src/src/main/java/org/mockito/internal/stubbing/answers/CallsRealMethods.java",
-    "src/src/main/java/org/mockito/internal/stubbing/answers/ClonesArguments.java",
-    "src/src/main/java/org/mockito/internal/stubbing/answers/DoesNothing.java",
-    "src/src/main/java/org/mockito/internal/stubbing/answers/MethodInfo.java",
-    "src/src/main/java/org/mockito/internal/stubbing/answers/Returns.java",
-    "src/src/main/java/org/mockito/internal/stubbing/answers/ReturnsArgumentAt.java",
-    "src/src/main/java/org/mockito/internal/stubbing/answers/ReturnsElementsOf.java",
-    "src/src/main/java/org/mockito/internal/stubbing/answers/ThrowsException.java",
-    "src/src/main/java/org/mockito/internal/stubbing/answers/ThrowsExceptionClass.java",
-    "src/src/main/java/org/mockito/internal/stubbing/defaultanswers/ForwardsInvocations.java",
-    "src/src/main/java/org/mockito/internal/stubbing/defaultanswers/GloballyConfiguredAnswer.java",
-    "src/src/main/java/org/mockito/internal/stubbing/defaultanswers/ReturnsDeepStubs.java",
-    "src/src/main/java/org/mockito/internal/stubbing/defaultanswers/ReturnsEmptyValues.java",
-    "src/src/main/java/org/mockito/internal/stubbing/defaultanswers/ReturnsMocks.java",
-    "src/src/main/java/org/mockito/internal/stubbing/defaultanswers/ReturnsMoreEmptyValues.java",
-    "src/src/main/java/org/mockito/internal/stubbing/defaultanswers/ReturnsSmartNulls.java",
-    "src/src/main/java/org/mockito/internal/stubbing/defaultanswers/TriesToReturnSelf.java",
-    "src/src/main/java/org/mockito/internal/util/Checks.java",
-    "src/src/main/java/org/mockito/internal/util/ConsoleMockitoLogger.java",
-    "src/src/main/java/org/mockito/internal/util/Decamelizer.java",
-    "src/src/main/java/org/mockito/internal/util/DefaultMockingDetails.java",
-    "src/src/main/java/org/mockito/internal/util/JavaEightUtil.java",
-    "src/src/main/java/org/mockito/internal/util/MockCreationValidator.java",
-    "src/src/main/java/org/mockito/internal/util/MockNameImpl.java",
-    "src/src/main/java/org/mockito/internal/util/MockUtil.java",
-    "src/src/main/java/org/mockito/internal/util/MockitoLogger.java",
-    "src/src/main/java/org/mockito/internal/util/ObjectMethodsGuru.java",
-    "src/src/main/java/org/mockito/internal/util/Primitives.java",
-    "src/src/main/java/org/mockito/internal/util/RemoveFirstLine.java",
-    "src/src/main/java/org/mockito/internal/util/SimpleMockitoLogger.java",
-    "src/src/main/java/org/mockito/internal/util/StringJoiner.java",
-    "src/src/main/java/org/mockito/internal/util/Timer.java",
-    "src/src/main/java/org/mockito/internal/util/collections/ArrayUtils.java",
-    "src/src/main/java/org/mockito/internal/util/collections/HashCodeAndEqualsMockWrapper.java",
-    "src/src/main/java/org/mockito/internal/util/collections/HashCodeAndEqualsSafeSet.java",
-    "src/src/main/java/org/mockito/internal/util/collections/IdentitySet.java",
-    "src/src/main/java/org/mockito/internal/util/collections/Iterables.java",
-    "src/src/main/java/org/mockito/internal/util/collections/ListUtil.java",
-    "src/src/main/java/org/mockito/internal/util/collections/Sets.java",
-    "src/src/main/java/org/mockito/internal/util/io/IOUtil.java",
-    "src/src/main/java/org/mockito/internal/util/junit/JUnitFailureHacker.java",
-    "src/src/main/java/org/mockito/internal/util/reflection/AccessibilityChanger.java",
-    "src/src/main/java/org/mockito/internal/util/reflection/BeanPropertySetter.java",
-    "src/src/main/java/org/mockito/internal/util/reflection/Constructors.java",
-    "src/src/main/java/org/mockito/internal/util/reflection/FieldCopier.java",
-    "src/src/main/java/org/mockito/internal/util/reflection/FieldInitializationReport.java",
-    "src/src/main/java/org/mockito/internal/util/reflection/FieldInitializer.java",
-    "src/src/main/java/org/mockito/internal/util/reflection/FieldReader.java",
-    "src/src/main/java/org/mockito/internal/util/reflection/FieldSetter.java",
-    "src/src/main/java/org/mockito/internal/util/reflection/Fields.java",
-    "src/src/main/java/org/mockito/internal/util/reflection/GenericMaster.java",
-    "src/src/main/java/org/mockito/internal/util/reflection/GenericMetadataSupport.java",
-    "src/src/main/java/org/mockito/internal/util/reflection/GenericTypeExtractor.java",
-    "src/src/main/java/org/mockito/internal/util/reflection/InstanceField.java",
-    "src/src/main/java/org/mockito/internal/util/reflection/LenientCopyTool.java",
-    "src/src/main/java/org/mockito/internal/util/reflection/SuperTypesLastSorter.java",
-    "src/src/main/java/org/mockito/internal/util/reflection/Whitebox.java",
-    "src/src/main/java/org/mockito/internal/verification/AtLeast.java",
-    "src/src/main/java/org/mockito/internal/verification/AtMost.java",
-    "src/src/main/java/org/mockito/internal/verification/Calls.java",
-    "src/src/main/java/org/mockito/internal/verification/DefaultRegisteredInvocations.java",
-    "src/src/main/java/org/mockito/internal/verification/Description.java",
-    "src/src/main/java/org/mockito/internal/verification/InOrderContextImpl.java",
-    "src/src/main/java/org/mockito/internal/verification/InOrderWrapper.java",
-    "src/src/main/java/org/mockito/internal/verification/MockAwareVerificationMode.java",
-    "src/src/main/java/org/mockito/internal/verification/NoMoreInteractions.java",
-    "src/src/main/java/org/mockito/internal/verification/Only.java",
-    "src/src/main/java/org/mockito/internal/verification/RegisteredInvocations.java",
-    "src/src/main/java/org/mockito/internal/verification/SingleRegisteredInvocation.java",
-    "src/src/main/java/org/mockito/internal/verification/Times.java",
-    "src/src/main/java/org/mockito/internal/verification/VerificationDataImpl.java",
-    "src/src/main/java/org/mockito/internal/verification/VerificationModeFactory.java",
-    "src/src/main/java/org/mockito/internal/verification/VerificationOverTimeImpl.java",
-    "src/src/main/java/org/mockito/internal/verification/api/InOrderContext.java",
-    "src/src/main/java/org/mockito/internal/verification/api/VerificationData.java",
-    "src/src/main/java/org/mockito/internal/verification/api/VerificationDataInOrder.java",
-    "src/src/main/java/org/mockito/internal/verification/api/VerificationDataInOrderImpl.java",
-    "src/src/main/java/org/mockito/internal/verification/api/VerificationInOrderMode.java",
-    "src/src/main/java/org/mockito/internal/verification/argumentmatching/ArgumentMatchingTool.java",
-    "src/src/main/java/org/mockito/internal/verification/checkers/AtLeastDiscrepancy.java",
-    "src/src/main/java/org/mockito/internal/verification/checkers/AtLeastXNumberOfInvocationsChecker.java",
-    "src/src/main/java/org/mockito/internal/verification/checkers/MissingInvocationChecker.java",
-    "src/src/main/java/org/mockito/internal/verification/checkers/NonGreedyNumberOfInvocationsInOrderChecker.java",
-    "src/src/main/java/org/mockito/internal/verification/checkers/NumberOfInvocationsChecker.java",
-    "src/src/main/java/org/mockito/internal/verification/checkers/NumberOfInvocationsInOrderChecker.java",
-    "src/src/main/java/org/mockito/invocation/DescribedInvocation.java",
-    "src/src/main/java/org/mockito/invocation/Invocation.java",
-    "src/src/main/java/org/mockito/invocation/InvocationOnMock.java",
-    "src/src/main/java/org/mockito/invocation/Location.java",
-    "src/src/main/java/org/mockito/invocation/MockHandler.java",
+    "src/src/main/java/org/mockito/MockitoDebugger.java",
+    "src/src/main/java/org/mockito/CheckReturnValue.java",
+    "src/src/main/java/org/mockito/Mockito.java",
+    "src/src/main/java/org/mockito/plugins/InstantiatorProvider2.java",
+    "src/src/main/java/org/mockito/plugins/AnnotationEngine.java",
+    "src/src/main/java/org/mockito/plugins/MockMaker.java",
+    "src/src/main/java/org/mockito/plugins/MockitoPlugins.java",
+    "src/src/main/java/org/mockito/plugins/PluginSwitch.java",
+    "src/src/main/java/org/mockito/plugins/InstantiatorProvider.java",
+    "src/src/main/java/org/mockito/plugins/package-info.java",
+    "src/src/main/java/org/mockito/plugins/StackTraceCleanerProvider.java",
+    "src/src/main/java/org/mockito/MockitoFramework.java",
+    "src/src/main/java/org/mockito/configuration/DefaultMockitoConfiguration.java",
+    "src/src/main/java/org/mockito/configuration/AnnotationEngine.java",
+    "src/src/main/java/org/mockito/configuration/package-info.java",
+    "src/src/main/java/org/mockito/configuration/IMockitoConfiguration.java",
     "src/src/main/java/org/mockito/invocation/StubInfo.java",
-    "src/src/main/java/org/mockito/junit/MockitoJUnit.java",
-    "src/src/main/java/org/mockito/junit/MockitoRule.java",
-    "src/src/main/java/org/mockito/junit/VerificationCollector.java",
-    "src/src/main/java/org/mockito/junit/VerificationCollectorImpl.java",
-    "src/src/main/java/org/mockito/listeners/InvocationListener.java",
-    "src/src/main/java/org/mockito/listeners/MethodInvocationReport.java",
-    "src/src/main/java/org/mockito/listeners/StubbingListener.java",
-    "src/src/main/java/org/mockito/mock/MockCreationSettings.java",
+    "src/src/main/java/org/mockito/invocation/Invocation.java",
+    "src/src/main/java/org/mockito/invocation/MatchableInvocation.java",
+    "src/src/main/java/org/mockito/invocation/Location.java",
+    "src/src/main/java/org/mockito/invocation/DescribedInvocation.java",
+    "src/src/main/java/org/mockito/invocation/package-info.java",
+    "src/src/main/java/org/mockito/invocation/InvocationContainer.java",
+    "src/src/main/java/org/mockito/invocation/MockHandler.java",
+    "src/src/main/java/org/mockito/invocation/InvocationFactory.java",
+    "src/src/main/java/org/mockito/invocation/InvocationOnMock.java",
     "src/src/main/java/org/mockito/mock/MockName.java",
     "src/src/main/java/org/mockito/mock/SerializableMode.java",
-    "src/src/main/java/org/mockito/plugins/InstantiatorProvider.java",
-    "src/src/main/java/org/mockito/plugins/MockMaker.java",
-    "src/src/main/java/org/mockito/plugins/PluginSwitch.java",
-    "src/src/main/java/org/mockito/plugins/StackTraceCleanerProvider.java",
+    "src/src/main/java/org/mockito/mock/package-info.java",
+    "src/src/main/java/org/mockito/mock/MockCreationSettings.java",
+    "src/src/main/java/org/mockito/codegen/InjectionBase.java",
+    "src/src/main/java/org/mockito/ArgumentMatchers.java",
+    "src/src/main/java/org/mockito/BDDMockito.java",
+    "src/src/main/java/org/mockito/listeners/MockCreationListener.java",
+    "src/src/main/java/org/mockito/listeners/InvocationListener.java",
+    "src/src/main/java/org/mockito/listeners/MethodInvocationReport.java",
+    "src/src/main/java/org/mockito/listeners/VerificationStartedListener.java",
+    "src/src/main/java/org/mockito/listeners/MockitoListener.java",
+    "src/src/main/java/org/mockito/listeners/VerificationStartedEvent.java",
+    "src/src/main/java/org/mockito/listeners/package-info.java",
+    "src/src/main/java/org/mockito/listeners/VerificationListener.java",
+    "src/src/main/java/org/mockito/package-info.java",
+    "src/src/main/java/org/mockito/MockingDetails.java",
+    "src/src/main/java/org/mockito/MockitoSession.java",
+    "src/src/main/java/org/mockito/exceptions/misusing/MockitoConfigurationException.java",
+    "src/src/main/java/org/mockito/exceptions/misusing/FriendlyReminderException.java",
+    "src/src/main/java/org/mockito/exceptions/misusing/WrongTypeOfReturnValue.java",
+    "src/src/main/java/org/mockito/exceptions/misusing/UnfinishedMockingSessionException.java",
+    "src/src/main/java/org/mockito/exceptions/misusing/NotAMockException.java",
+    "src/src/main/java/org/mockito/exceptions/misusing/UnfinishedStubbingException.java",
+    "src/src/main/java/org/mockito/exceptions/misusing/NullInsteadOfMockException.java",
+    "src/src/main/java/org/mockito/exceptions/misusing/CannotStubVoidMethodWithReturnValue.java",
+    "src/src/main/java/org/mockito/exceptions/misusing/MissingMethodInvocationException.java",
+    "src/src/main/java/org/mockito/exceptions/misusing/UnnecessaryStubbingException.java",
+    "src/src/main/java/org/mockito/exceptions/misusing/RedundantListenerException.java",
+    "src/src/main/java/org/mockito/exceptions/misusing/InvalidUseOfMatchersException.java",
+    "src/src/main/java/org/mockito/exceptions/misusing/PotentialStubbingProblem.java",
+    "src/src/main/java/org/mockito/exceptions/misusing/UnfinishedVerificationException.java",
+    "src/src/main/java/org/mockito/exceptions/misusing/package-info.java",
+    "src/src/main/java/org/mockito/exceptions/misusing/CannotVerifyStubOnlyMock.java",
+    "src/src/main/java/org/mockito/exceptions/base/MockitoException.java",
+    "src/src/main/java/org/mockito/exceptions/base/MockitoAssertionError.java",
+    "src/src/main/java/org/mockito/exceptions/base/MockitoSerializationIssue.java",
+    "src/src/main/java/org/mockito/exceptions/base/MockitoInitializationException.java",
+    "src/src/main/java/org/mockito/exceptions/base/package-info.java",
+    "src/src/main/java/org/mockito/exceptions/verification/ArgumentsAreDifferent.java",
+    "src/src/main/java/org/mockito/exceptions/verification/SmartNullPointerException.java",
+    "src/src/main/java/org/mockito/exceptions/verification/VerificationInOrderFailure.java",
+    "src/src/main/java/org/mockito/exceptions/verification/TooLittleActualInvocations.java",
+    "src/src/main/java/org/mockito/exceptions/verification/NoInteractionsWanted.java",
+    "src/src/main/java/org/mockito/exceptions/verification/NeverWantedButInvoked.java",
+    "src/src/main/java/org/mockito/exceptions/verification/WantedButNotInvoked.java",
+    "src/src/main/java/org/mockito/exceptions/verification/TooManyActualInvocations.java",
+    "src/src/main/java/org/mockito/exceptions/verification/package-info.java",
+    "src/src/main/java/org/mockito/exceptions/verification/junit/ArgumentsAreDifferent.java",
+    "src/src/main/java/org/mockito/exceptions/verification/junit/package-info.java",
+    "src/src/main/java/org/mockito/exceptions/stacktrace/package-info.java",
+    "src/src/main/java/org/mockito/exceptions/stacktrace/StackTraceCleaner.java",
+    "src/src/main/java/org/mockito/exceptions/package-info.java",
+    "src/src/main/java/org/mockito/Mock.java",
+    "src/src/main/java/org/mockito/MockitoAnnotations.java",
+    "src/src/main/java/org/mockito/Spy.java",
+    "src/src/main/java/org/mockito/AdditionalMatchers.java",
+    "src/src/main/java/org/mockito/junit/MockitoJUnit.java",
+    "src/src/main/java/org/mockito/junit/MockitoJUnitRunner.java",
+    "src/src/main/java/org/mockito/junit/MockitoRule.java",
+    "src/src/main/java/org/mockito/junit/package-info.java",
+    "src/src/main/java/org/mockito/junit/VerificationCollector.java",
+    "src/src/main/java/org/mockito/Incubating.java",
+    "src/src/main/java/org/mockito/ArgumentCaptor.java",
+    "src/src/main/java/org/mockito/session/MockitoSessionLogger.java",
+    "src/src/main/java/org/mockito/session/MockitoSessionBuilder.java",
+    "src/src/main/java/org/mockito/InOrder.java",
     "src/src/main/java/org/mockito/runners/ConsoleSpammingMockitoJUnitRunner.java",
     "src/src/main/java/org/mockito/runners/MockitoJUnitRunner.java",
     "src/src/main/java/org/mockito/runners/VerboseMockitoJUnitRunner.java",
-    "src/src/main/java/org/mockito/stubbing/Answer.java",
-    "src/src/main/java/org/mockito/stubbing/OngoingStubbing.java",
-    "src/src/main/java/org/mockito/stubbing/Stubber.java",
-    "src/src/main/java/org/mockito/verification/After.java",
-    "src/src/main/java/org/mockito/verification/Timeout.java",
-    "src/src/main/java/org/mockito/verification/VerificationAfterDelay.java",
-    "src/src/main/java/org/mockito/verification/VerificationMode.java",
-    "src/src/main/java/org/mockito/verification/VerificationStrategy.java",
-    "src/src/main/java/org/mockito/verification/VerificationWithTimeout.java",
-    "src/src/main/java/org/mockito/verification/VerificationWrapper.java",
-    "src/src/main/java/org/mockito/verification/VerificationWrapperInOrderWrapper.java",
+    "src/src/main/java/org/mockito/runners/package-info.java",
+    "src/src/main/java/org/mockito/internal/verification/argumentmatching/ArgumentMatchingTool.java",
+    "src/src/main/java/org/mockito/internal/verification/argumentmatching/package-info.java",
+    "src/src/main/java/org/mockito/internal/verification/Calls.java",
+    "src/src/main/java/org/mockito/internal/verification/VerificationWrapperInOrderWrapper.java",
+    "src/src/main/java/org/mockito/internal/verification/VerificationOverTimeImpl.java",
+    "src/src/main/java/org/mockito/internal/verification/AtLeast.java",
+    "src/src/main/java/org/mockito/internal/verification/SingleRegisteredInvocation.java",
+    "src/src/main/java/org/mockito/internal/verification/InOrderWrapper.java",
+    "src/src/main/java/org/mockito/internal/verification/InOrderContextImpl.java",
+    "src/src/main/java/org/mockito/internal/verification/VerificationEventImpl.java",
+    "src/src/main/java/org/mockito/internal/verification/NoMoreInteractions.java",
+    "src/src/main/java/org/mockito/internal/verification/checkers/NumberOfInvocationsChecker.java",
+    "src/src/main/java/org/mockito/internal/verification/checkers/AtLeastDiscrepancy.java",
+    "src/src/main/java/org/mockito/internal/verification/checkers/MissingInvocationChecker.java",
+    "src/src/main/java/org/mockito/internal/verification/checkers/AtLeastXNumberOfInvocationsChecker.java",
+    "src/src/main/java/org/mockito/internal/verification/checkers/package-info.java",
+    "src/src/main/java/org/mockito/internal/verification/VerificationWrapper.java",
+    "src/src/main/java/org/mockito/internal/verification/Description.java",
+    "src/src/main/java/org/mockito/internal/verification/package-info.java",
+    "src/src/main/java/org/mockito/internal/verification/MockAwareVerificationMode.java",
+    "src/src/main/java/org/mockito/internal/verification/DefaultRegisteredInvocations.java",
+    "src/src/main/java/org/mockito/internal/verification/RegisteredInvocations.java",
+    "src/src/main/java/org/mockito/internal/verification/VerificationDataImpl.java",
+    "src/src/main/java/org/mockito/internal/verification/Only.java",
+    "src/src/main/java/org/mockito/internal/verification/api/VerificationDataInOrder.java",
+    "src/src/main/java/org/mockito/internal/verification/api/VerificationDataInOrderImpl.java",
+    "src/src/main/java/org/mockito/internal/verification/api/InOrderContext.java",
+    "src/src/main/java/org/mockito/internal/verification/api/VerificationInOrderMode.java",
+    "src/src/main/java/org/mockito/internal/verification/api/package-info.java",
+    "src/src/main/java/org/mockito/internal/verification/api/VerificationData.java",
+    "src/src/main/java/org/mockito/internal/verification/Times.java",
+    "src/src/main/java/org/mockito/internal/verification/VerificationModeFactory.java",
+    "src/src/main/java/org/mockito/internal/verification/AtMost.java",
+    "src/src/main/java/org/mockito/internal/util/ConsoleMockitoLogger.java",
+    "src/src/main/java/org/mockito/internal/util/DefaultMockingDetails.java",
+    "src/src/main/java/org/mockito/internal/util/io/IOUtil.java",
+    "src/src/main/java/org/mockito/internal/util/Checks.java",
+    "src/src/main/java/org/mockito/internal/util/reflection/GenericMaster.java",
+    "src/src/main/java/org/mockito/internal/util/reflection/GenericMetadataSupport.java",
+    "src/src/main/java/org/mockito/internal/util/reflection/BeanPropertySetter.java",
+    "src/src/main/java/org/mockito/internal/util/reflection/FieldReader.java",
+    "src/src/main/java/org/mockito/internal/util/reflection/LenientCopyTool.java",
+    "src/src/main/java/org/mockito/internal/util/reflection/GenericTypeExtractor.java",
+    "src/src/main/java/org/mockito/internal/util/reflection/FieldInitializationReport.java",
+    "src/src/main/java/org/mockito/internal/util/reflection/FieldInitializer.java",
+    "src/src/main/java/org/mockito/internal/util/reflection/FieldCopier.java",
+    "src/src/main/java/org/mockito/internal/util/reflection/SuperTypesLastSorter.java",
+    "src/src/main/java/org/mockito/internal/util/reflection/package-info.java",
+    "src/src/main/java/org/mockito/internal/util/reflection/InstanceField.java",
+    "src/src/main/java/org/mockito/internal/util/reflection/Fields.java",
+    "src/src/main/java/org/mockito/internal/util/reflection/FieldSetter.java",
+    "src/src/main/java/org/mockito/internal/util/reflection/AccessibilityChanger.java",
+    "src/src/main/java/org/mockito/internal/util/Primitives.java",
+    "src/src/main/java/org/mockito/internal/util/MockUtil.java",
+    "src/src/main/java/org/mockito/internal/util/MockNameImpl.java",
+    "src/src/main/java/org/mockito/internal/util/collections/HashCodeAndEqualsMockWrapper.java",
+    "src/src/main/java/org/mockito/internal/util/collections/IdentitySet.java",
+    "src/src/main/java/org/mockito/internal/util/collections/HashCodeAndEqualsSafeSet.java",
+    "src/src/main/java/org/mockito/internal/util/collections/Sets.java",
+    "src/src/main/java/org/mockito/internal/util/collections/Iterables.java",
+    "src/src/main/java/org/mockito/internal/util/collections/ListUtil.java",
+    "src/src/main/java/org/mockito/internal/util/StringUtil.java",
+    "src/src/main/java/org/mockito/internal/util/concurrent/DetachedThreadLocal.java",
+    "src/src/main/java/org/mockito/internal/util/concurrent/WeakConcurrentSet.java",
+    "src/src/main/java/org/mockito/internal/util/concurrent/WeakConcurrentMap.java",
+    "src/src/main/java/org/mockito/internal/util/Supplier.java",
+    "src/src/main/java/org/mockito/internal/util/ObjectMethodsGuru.java",
+    "src/src/main/java/org/mockito/internal/util/MockitoLogger.java",
+    "src/src/main/java/org/mockito/internal/util/MockCreationValidator.java",
+    "src/src/main/java/org/mockito/internal/util/Timer.java",
+    "src/src/main/java/org/mockito/internal/util/Platform.java",
+    "src/src/main/java/org/mockito/internal/util/JavaEightUtil.java",
+    "src/src/main/java/org/mockito/internal/util/package-info.java",
+    "src/src/main/java/org/mockito/internal/stubbing/StubbingComparator.java",
+    "src/src/main/java/org/mockito/internal/stubbing/OngoingStubbingImpl.java",
+    "src/src/main/java/org/mockito/internal/stubbing/StubbedInvocationMatcher.java",
+    "src/src/main/java/org/mockito/internal/stubbing/defaultanswers/ReturnsMocks.java",
+    "src/src/main/java/org/mockito/internal/stubbing/defaultanswers/ReturnsMoreEmptyValues.java",
+    "src/src/main/java/org/mockito/internal/stubbing/defaultanswers/ReturnsEmptyValues.java",
+    "src/src/main/java/org/mockito/internal/stubbing/defaultanswers/ReturnsSmartNulls.java",
+    "src/src/main/java/org/mockito/internal/stubbing/defaultanswers/ForwardsInvocations.java",
+    "src/src/main/java/org/mockito/internal/stubbing/defaultanswers/ReturnsDeepStubs.java",
+    "src/src/main/java/org/mockito/internal/stubbing/defaultanswers/package-info.java",
+    "src/src/main/java/org/mockito/internal/stubbing/defaultanswers/GloballyConfiguredAnswer.java",
+    "src/src/main/java/org/mockito/internal/stubbing/defaultanswers/TriesToReturnSelf.java",
+    "src/src/main/java/org/mockito/internal/stubbing/StubberImpl.java",
+    "src/src/main/java/org/mockito/internal/stubbing/BaseStubbing.java",
+    "src/src/main/java/org/mockito/internal/stubbing/answers/ReturnsElementsOf.java",
+    "src/src/main/java/org/mockito/internal/stubbing/answers/AnswersWithDelay.java",
+    "src/src/main/java/org/mockito/internal/stubbing/answers/ClonesArguments.java",
+    "src/src/main/java/org/mockito/internal/stubbing/answers/AnswerFunctionalInterfaces.java",
+    "src/src/main/java/org/mockito/internal/stubbing/answers/ThrowsException.java",
+    "src/src/main/java/org/mockito/internal/stubbing/answers/ReturnsArgumentAt.java",
+    "src/src/main/java/org/mockito/internal/stubbing/answers/package-info.java",
+    "src/src/main/java/org/mockito/internal/stubbing/answers/Returns.java",
+    "src/src/main/java/org/mockito/internal/stubbing/answers/DefaultAnswerValidator.java",
+    "src/src/main/java/org/mockito/internal/stubbing/answers/DoesNothing.java",
+    "src/src/main/java/org/mockito/internal/stubbing/answers/InvocationInfo.java",
+    "src/src/main/java/org/mockito/internal/stubbing/answers/CallsRealMethods.java",
+    "src/src/main/java/org/mockito/internal/stubbing/ConsecutiveStubbing.java",
+    "src/src/main/java/org/mockito/internal/stubbing/InvocationContainerImpl.java",
+    "src/src/main/java/org/mockito/internal/stubbing/package-info.java",
+    "src/src/main/java/org/mockito/internal/InternalMockHandler.java",
+    "src/src/main/java/org/mockito/internal/matchers/Same.java",
+    "src/src/main/java/org/mockito/internal/matchers/ArrayEquals.java",
+    "src/src/main/java/org/mockito/internal/matchers/CapturingMatcher.java",
+    "src/src/main/java/org/mockito/internal/matchers/Not.java",
+    "src/src/main/java/org/mockito/internal/matchers/apachecommons/EqualsBuilder.java",
+    "src/src/main/java/org/mockito/internal/matchers/apachecommons/ReflectionEquals.java",
+    "src/src/main/java/org/mockito/internal/matchers/apachecommons/package-info.java",
+    "src/src/main/java/org/mockito/internal/matchers/Equality.java",
+    "src/src/main/java/org/mockito/internal/matchers/CapturesArguments.java",
+    "src/src/main/java/org/mockito/internal/matchers/StartsWith.java",
+    "src/src/main/java/org/mockito/internal/matchers/GreaterOrEqual.java",
+    "src/src/main/java/org/mockito/internal/matchers/Null.java",
+    "src/src/main/java/org/mockito/internal/matchers/NotNull.java",
+    "src/src/main/java/org/mockito/internal/matchers/CompareEqual.java",
+    "src/src/main/java/org/mockito/internal/matchers/Equals.java",
+    "src/src/main/java/org/mockito/internal/matchers/ContainsExtraTypeInfo.java",
+    "src/src/main/java/org/mockito/internal/matchers/CompareTo.java",
+    "src/src/main/java/org/mockito/internal/matchers/InstanceOf.java",
+    "src/src/main/java/org/mockito/internal/matchers/VarargMatcher.java",
+    "src/src/main/java/org/mockito/internal/matchers/And.java",
+    "src/src/main/java/org/mockito/internal/matchers/Find.java",
+    "src/src/main/java/org/mockito/internal/matchers/Or.java",
+    "src/src/main/java/org/mockito/internal/matchers/text/MatcherToString.java",
+    "src/src/main/java/org/mockito/internal/matchers/text/MatchersPrinter.java",
+    "src/src/main/java/org/mockito/internal/matchers/text/ValuePrinter.java",
+    "src/src/main/java/org/mockito/internal/matchers/text/FormattedText.java",
+    "src/src/main/java/org/mockito/internal/matchers/LessThan.java",
+    "src/src/main/java/org/mockito/internal/matchers/EndsWith.java",
+    "src/src/main/java/org/mockito/internal/matchers/LocalizedMatcher.java",
+    "src/src/main/java/org/mockito/internal/matchers/GreaterThan.java",
+    "src/src/main/java/org/mockito/internal/matchers/Any.java",
+    "src/src/main/java/org/mockito/internal/matchers/package-info.java",
+    "src/src/main/java/org/mockito/internal/matchers/LessOrEqual.java",
+    "src/src/main/java/org/mockito/internal/matchers/Matches.java",
+    "src/src/main/java/org/mockito/internal/matchers/EqualsWithDelta.java",
+    "src/src/main/java/org/mockito/internal/matchers/Contains.java",
+    "src/src/main/java/org/mockito/internal/InOrderImpl.java",
+    "src/src/main/java/org/mockito/internal/MockitoCore.java",
+    "src/src/main/java/org/mockito/internal/framework/DefaultMockitoSession.java",
+    "src/src/main/java/org/mockito/internal/framework/DefaultMockitoFramework.java",
+    "src/src/main/java/org/mockito/internal/hamcrest/MatcherGenericTypeExtractor.java",
+    "src/src/main/java/org/mockito/internal/hamcrest/HamcrestArgumentMatcher.java",
+    "src/src/main/java/org/mockito/internal/handler/MockHandlerFactory.java",
+    "src/src/main/java/org/mockito/internal/handler/NullResultGuardian.java",
+    "src/src/main/java/org/mockito/internal/handler/NotifiedMethodInvocationReport.java",
+    "src/src/main/java/org/mockito/internal/handler/MockHandlerImpl.java",
+    "src/src/main/java/org/mockito/internal/handler/InvocationNotifierHandler.java",
+    "src/src/main/java/org/mockito/internal/progress/ThreadSafeMockingProgress.java",
+    "src/src/main/java/org/mockito/internal/progress/ArgumentMatcherStorageImpl.java",
+    "src/src/main/java/org/mockito/internal/progress/SequenceNumber.java",
+    "src/src/main/java/org/mockito/internal/progress/MockingProgress.java",
+    "src/src/main/java/org/mockito/internal/progress/package-info.java",
+    "src/src/main/java/org/mockito/internal/progress/MockingProgressImpl.java",
+    "src/src/main/java/org/mockito/internal/progress/ArgumentMatcherStorage.java",
+    "src/src/main/java/org/mockito/internal/configuration/CaptorAnnotationProcessor.java",
+    "src/src/main/java/org/mockito/internal/configuration/injection/MockInjection.java",
+    "src/src/main/java/org/mockito/internal/configuration/injection/PropertyAndSetterInjection.java",
+    "src/src/main/java/org/mockito/internal/configuration/injection/MockInjectionStrategy.java",
+    "src/src/main/java/org/mockito/internal/configuration/injection/scanner/MockScanner.java",
+    "src/src/main/java/org/mockito/internal/configuration/injection/scanner/InjectMocksScanner.java",
+    "src/src/main/java/org/mockito/internal/configuration/injection/SpyOnInjectedFieldsHandler.java",
+    "src/src/main/java/org/mockito/internal/configuration/injection/filter/MockCandidateFilter.java",
+    "src/src/main/java/org/mockito/internal/configuration/injection/filter/TypeBasedCandidateFilter.java",
+    "src/src/main/java/org/mockito/internal/configuration/injection/filter/TerminalMockCandidateFilter.java",
+    "src/src/main/java/org/mockito/internal/configuration/injection/filter/OngoingInjector.java",
+    "src/src/main/java/org/mockito/internal/configuration/injection/filter/NameBasedCandidateFilter.java",
+    "src/src/main/java/org/mockito/internal/configuration/injection/ConstructorInjection.java",
+    "src/src/main/java/org/mockito/internal/configuration/injection/package-info.java",
+    "src/src/main/java/org/mockito/internal/configuration/SpyAnnotationEngine.java",
+    "src/src/main/java/org/mockito/internal/configuration/MockAnnotationProcessor.java",
+    "src/src/main/java/org/mockito/internal/configuration/InjectingAnnotationEngine.java",
+    "src/src/main/java/org/mockito/internal/configuration/FieldAnnotationProcessor.java",
+    "src/src/main/java/org/mockito/internal/configuration/IndependentAnnotationEngine.java",
+    "src/src/main/java/org/mockito/internal/configuration/DefaultInjectionEngine.java",
+    "src/src/main/java/org/mockito/internal/configuration/plugins/DefaultMockitoPlugins.java",
+    "src/src/main/java/org/mockito/internal/configuration/plugins/PluginRegistry.java",
+    "src/src/main/java/org/mockito/internal/configuration/plugins/DefaultPluginSwitch.java",
+    "src/src/main/java/org/mockito/internal/configuration/plugins/Plugins.java",
+    "src/src/main/java/org/mockito/internal/configuration/plugins/PluginFinder.java",
+    "src/src/main/java/org/mockito/internal/configuration/plugins/PluginFileReader.java",
+    "src/src/main/java/org/mockito/internal/configuration/plugins/PluginInitializer.java",
+    "src/src/main/java/org/mockito/internal/configuration/plugins/PluginLoader.java",
+    "src/src/main/java/org/mockito/internal/configuration/plugins/package-info.java",
+    "src/src/main/java/org/mockito/internal/configuration/GlobalConfiguration.java",
+    "src/src/main/java/org/mockito/internal/configuration/ClassPathLoader.java",
+    "src/src/main/java/org/mockito/internal/configuration/package-info.java",
+    "src/src/main/java/org/mockito/internal/invocation/InvocationMarker.java",
+    "src/src/main/java/org/mockito/internal/invocation/MatcherApplicationStrategy.java",
+    "src/src/main/java/org/mockito/internal/invocation/StubInfoImpl.java",
+    "src/src/main/java/org/mockito/internal/invocation/InterceptedInvocation.java",
+    "src/src/main/java/org/mockito/internal/invocation/finder/AllInvocationsFinder.java",
+    "src/src/main/java/org/mockito/internal/invocation/finder/VerifiableInvocationsFinder.java",
+    "src/src/main/java/org/mockito/internal/invocation/InvocationComparator.java",
+    "src/src/main/java/org/mockito/internal/invocation/TypeSafeMatching.java",
+    "src/src/main/java/org/mockito/internal/invocation/MatchersBinder.java",
+    "src/src/main/java/org/mockito/internal/invocation/RealMethod.java",
+    "src/src/main/java/org/mockito/internal/invocation/InvocationMatcher.java",
+    "src/src/main/java/org/mockito/internal/invocation/ArgumentMatcherAction.java",
+    "src/src/main/java/org/mockito/internal/invocation/InvocationsFinder.java",
+    "src/src/main/java/org/mockito/internal/invocation/SerializableMethod.java",
+    "src/src/main/java/org/mockito/internal/invocation/AbstractAwareMethod.java",
+    "src/src/main/java/org/mockito/internal/invocation/ArgumentsProcessor.java",
+    "src/src/main/java/org/mockito/internal/invocation/DefaultInvocationFactory.java",
+    "src/src/main/java/org/mockito/internal/invocation/mockref/MockReference.java",
+    "src/src/main/java/org/mockito/internal/invocation/mockref/MockStrongReference.java",
+    "src/src/main/java/org/mockito/internal/invocation/mockref/MockWeakReference.java",
+    "src/src/main/java/org/mockito/internal/invocation/package-info.java",
+    "src/src/main/java/org/mockito/internal/invocation/UnusedStubsFinder.java",
+    "src/src/main/java/org/mockito/internal/invocation/MockitoMethod.java",
+    "src/src/main/java/org/mockito/internal/listeners/VerificationStartedNotifier.java",
+    "src/src/main/java/org/mockito/internal/listeners/StubbingLookupListener.java",
+    "src/src/main/java/org/mockito/internal/package-info.java",
+    "src/src/main/java/org/mockito/internal/exceptions/ExceptionIncludingMockitoWarnings.java",
+    "src/src/main/java/org/mockito/internal/exceptions/util/ScenarioPrinter.java",
+    "src/src/main/java/org/mockito/internal/exceptions/Reporter.java",
+    "src/src/main/java/org/mockito/internal/exceptions/stacktrace/DefaultStackTraceCleanerProvider.java",
+    "src/src/main/java/org/mockito/internal/exceptions/stacktrace/DefaultStackTraceCleaner.java",
+    "src/src/main/java/org/mockito/internal/exceptions/stacktrace/StackTraceFilter.java",
+    "src/src/main/java/org/mockito/internal/exceptions/stacktrace/package-info.java",
+    "src/src/main/java/org/mockito/internal/exceptions/stacktrace/ConditionalStackTraceFilter.java",
+    "src/src/main/java/org/mockito/internal/exceptions/VerificationAwareInvocation.java",
+    "src/src/main/java/org/mockito/internal/debugging/WarningsFinder.java",
+    "src/src/main/java/org/mockito/internal/debugging/LoggingListener.java",
+    "src/src/main/java/org/mockito/internal/debugging/LocationImpl.java",
+    "src/src/main/java/org/mockito/internal/debugging/MockitoDebuggerImpl.java",
+    "src/src/main/java/org/mockito/internal/debugging/Localized.java",
+    "src/src/main/java/org/mockito/internal/debugging/WarningsPrinterImpl.java",
+    "src/src/main/java/org/mockito/internal/debugging/WarningsCollector.java",
+    "src/src/main/java/org/mockito/internal/debugging/package-info.java",
+    "src/src/main/java/org/mockito/internal/debugging/InvocationsPrinter.java",
+    "src/src/main/java/org/mockito/internal/debugging/FindingsListener.java",
+    "src/src/main/java/org/mockito/internal/debugging/VerboseMockInvocationLogger.java",
+    "src/src/main/java/org/mockito/internal/junit/ArgMismatchFinder.java",
+    "src/src/main/java/org/mockito/internal/junit/UnusedStubbings.java",
+    "src/src/main/java/org/mockito/internal/junit/DefaultStubbingLookupListener.java",
+    "src/src/main/java/org/mockito/internal/junit/JUnitRule.java",
+    "src/src/main/java/org/mockito/internal/junit/ExceptionFactory.java",
+    "src/src/main/java/org/mockito/internal/junit/util/JUnitFailureHacker.java",
+    "src/src/main/java/org/mockito/internal/junit/MismatchReportingTestListener.java",
+    "src/src/main/java/org/mockito/internal/junit/StrictStubsRunnerTestListener.java",
+    "src/src/main/java/org/mockito/internal/junit/UnusedStubbingsFinder.java",
+    "src/src/main/java/org/mockito/internal/junit/VerificationCollectorImpl.java",
+    "src/src/main/java/org/mockito/internal/junit/DefaultTestFinishedEvent.java",
+    "src/src/main/java/org/mockito/internal/junit/MockitoTestListener.java",
+    "src/src/main/java/org/mockito/internal/junit/StubbingArgMismatches.java",
+    "src/src/main/java/org/mockito/internal/junit/NoOpTestListener.java",
+    "src/src/main/java/org/mockito/internal/junit/UnnecessaryStubbingsReporter.java",
+    "src/src/main/java/org/mockito/internal/junit/StubbingHint.java",
+    "src/src/main/java/org/mockito/internal/junit/package-info.java",
+    "src/src/main/java/org/mockito/internal/junit/TestFinishedEvent.java",
+    "src/src/main/java/org/mockito/internal/junit/UniversalTestListener.java",
+    "src/src/main/java/org/mockito/internal/session/MockitoLoggerAdapter.java",
+    "src/src/main/java/org/mockito/internal/session/DefaultMockitoSessionBuilder.java",
+    "src/src/main/java/org/mockito/internal/session/MockitoSessionLoggerAdapter.java",
+    "src/src/main/java/org/mockito/internal/reporting/PrintSettings.java",
+    "src/src/main/java/org/mockito/internal/reporting/Pluralizer.java",
+    "src/src/main/java/org/mockito/internal/reporting/SmartPrinter.java",
+    "src/src/main/java/org/mockito/internal/reporting/Discrepancy.java",
+    "src/src/main/java/org/mockito/internal/reporting/package-info.java",
+    "src/src/main/java/org/mockito/internal/runners/util/RunnerProvider.java",
+    "src/src/main/java/org/mockito/internal/runners/util/FailureDetector.java",
+    "src/src/main/java/org/mockito/internal/runners/util/package-info.java",
+    "src/src/main/java/org/mockito/internal/runners/util/TestMethodsFinder.java",
+    "src/src/main/java/org/mockito/internal/runners/InternalRunner.java",
+    "src/src/main/java/org/mockito/internal/runners/RunnerFactory.java",
+    "src/src/main/java/org/mockito/internal/runners/StrictRunner.java",
+    "src/src/main/java/org/mockito/internal/runners/package-info.java",
+    "src/src/main/java/org/mockito/internal/runners/DefaultInternalRunner.java",
+    "src/src/main/java/org/mockito/internal/creation/DelegatingMethod.java",
+    "src/src/main/java/org/mockito/internal/creation/settings/CreationSettings.java",
+    "src/src/main/java/org/mockito/internal/creation/util/MockitoMethodProxy.java",
+    "src/src/main/java/org/mockito/internal/creation/util/package-info.java",
+    "src/src/main/java/org/mockito/internal/creation/MockSettingsImpl.java",
+    "src/src/main/java/org/mockito/internal/creation/SuspendMethod.java",
+    "src/src/main/java/org/mockito/internal/creation/instance/InstantiationException.java",
+    "src/src/main/java/org/mockito/internal/creation/instance/InstantiatorProvider2Adapter.java",
+    "src/src/main/java/org/mockito/internal/creation/instance/ObjenesisInstantiator.java",
+    "src/src/main/java/org/mockito/internal/creation/instance/Instantiator.java",
+    "src/src/main/java/org/mockito/internal/creation/instance/ConstructorInstantiator.java",
+    "src/src/main/java/org/mockito/internal/creation/instance/InstantiatorProviderAdapter.java",
+    "src/src/main/java/org/mockito/internal/creation/instance/DefaultInstantiatorProvider.java",
+    "src/src/main/java/org/mockito/internal/creation/bytebuddy/SubclassInjectionLoader.java",
+    "src/src/main/java/org/mockito/internal/creation/bytebuddy/ClassCreatingMockMaker.java",
+    "src/src/main/java/org/mockito/internal/creation/bytebuddy/SubclassBytecodeGenerator.java",
+    "src/src/main/java/org/mockito/internal/creation/bytebuddy/MockMethodAdvice.java",
+    "src/src/main/java/org/mockito/internal/creation/bytebuddy/MockMethodDispatcher.java",
+    "src/src/main/java/org/mockito/internal/creation/bytebuddy/MockAccess.java",
+    "src/src/main/java/org/mockito/internal/creation/bytebuddy/InlineByteBuddyMockMaker.java",
+    "src/src/main/java/org/mockito/internal/creation/bytebuddy/InlineBytecodeGenerator.java",
+    "src/src/main/java/org/mockito/internal/creation/bytebuddy/MockMethodInterceptor.java",
+    "src/src/main/java/org/mockito/internal/creation/bytebuddy/ByteBuddyCrossClassLoaderSerializationSupport.java",
+    "src/src/main/java/org/mockito/internal/creation/bytebuddy/SubclassLoader.java",
+    "src/src/main/java/org/mockito/internal/creation/bytebuddy/MockFeatures.java",
+    "src/src/main/java/org/mockito/internal/creation/bytebuddy/TypeCachingBytecodeGenerator.java",
+    "src/src/main/java/org/mockito/internal/creation/bytebuddy/package-info.java",
+    "src/src/main/java/org/mockito/internal/creation/bytebuddy/ByteBuddyMockMaker.java",
+    "src/src/main/java/org/mockito/internal/creation/bytebuddy/SubclassByteBuddyMockMaker.java",
+    "src/src/main/java/org/mockito/internal/creation/bytebuddy/BytecodeGenerator.java",
+    "src/src/main/java/org/mockito/internal/creation/package-info.java",
+    "src/src/main/java/org/mockito/creation/instance/InstantiationException.java",
+    "src/src/main/java/org/mockito/creation/instance/Instantiator.java",
   ]
 }
+
+android_library("mockito_android_java") {
+  chromium_code = false
+  testonly = true
+  proguard_configs = [ "//third_party/mockito/proguard.flags" ]
+  deps = [
+    ":mockito_java",
+    "//third_party/byte_buddy:byte_buddy_android_java",
+  ]
+
+  java_files = [
+    "src/subprojects/android/src/main/java/org/mockito/android/internal/creation/AndroidTempFileLocator.java",
+    "src/subprojects/android/src/main/java/org/mockito/android/internal/creation/AndroidLoadingStrategy.java",
+    "src/subprojects/android/src/main/java/org/mockito/android/internal/creation/AndroidByteBuddyMockMaker.java",
+  ]
+
+  include_java_resources = true
+  additional_jar_files = [ [
+        rebase_path(
+            "src/subprojects/android/src/main/resources/mockito-extensions/org.mockito.plugins.MockMaker"),
+        "mockito-extensions/org.mockito.plugins.MockMaker",
+      ] ]
+}
diff --git a/third_party/mockito/README.chromium b/third_party/mockito/README.chromium
index 99d89885..33bd030 100644
--- a/third_party/mockito/README.chromium
+++ b/third_party/mockito/README.chromium
@@ -1,6 +1,6 @@
 Name: Mockito
 URL: https://github.com/mockito/mockito
-Version: v2.0.99-beta
+Version: v2.18.3
 License: MIT
 License File: NOT_SHIPPED
 Security Critical: no
diff --git a/third_party/mockito/proguard.flags b/third_party/mockito/proguard.flags
new file mode 100644
index 0000000..592aea1
--- /dev/null
+++ b/third_party/mockito/proguard.flags
@@ -0,0 +1,11 @@
+# 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.
+
+-dontwarn org.mockito.**
+
+# Mockito loads some things by reflection. Prevent proguard from
+# obfuscating or removing anything to ensure that doesn't break.
+-keep class org.mockito.** {
+  *;
+}
diff --git a/third_party/objenesis/BUILD.gn b/third_party/objenesis/BUILD.gn
index dcb41b6..21db97e 100644
--- a/third_party/objenesis/BUILD.gn
+++ b/third_party/objenesis/BUILD.gn
@@ -5,6 +5,7 @@
 import("//build/config/android/rules.gni")
 
 java_prebuilt("objenesis_java") {
+  supports_android = true
   testonly = true
   jar_path = "lib/objenesis.jar"
 }
diff --git a/tools/fuchsia/local-sdk.py b/tools/fuchsia/local-sdk.py
index 9d9cd6d..6751ba0 100755
--- a/tools/fuchsia/local-sdk.py
+++ b/tools/fuchsia/local-sdk.py
@@ -56,7 +56,7 @@
 
   tempdir = tempfile.mkdtemp()
   sdk_tar = os.path.join(tempdir, 'fuchsia-sdk.tgz')
-  Run('go', 'run', 'scripts/makesdk.go', '-output', sdk_tar, '.')
+  Run('go', 'run', 'scripts/sdk/foundation/makesdk.go', '-output', sdk_tar, '.')
 
   # Nuke the SDK from DEPS, put our just-built one there, and set a fake .hash
   # file. This means that on next gclient runhooks, we'll restore to the
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl
index ef70fd4c..3941732 100644
--- a/tools/mb/mb_config.pyl
+++ b/tools/mb/mb_config.pyl
@@ -275,9 +275,13 @@
       'Android FYI Release (Nexus 9)': 'android_release_trybot_arm64',
       'Android FYI Release (NVIDIA Shield TV)': 'android_release_trybot_arm64',
       'Android FYI 32 Vk Release (Nexus 5X)': 'gpu_tests_android_vulkan_release_trybot',
+      'Android FYI 32 Vk Release (Pixel 2)': 'gpu_tests_android_vulkan_release_trybot',
       'Android FYI 64 Vk Release (Nexus 5X)': 'gpu_tests_android_vulkan_release_trybot_arm64',
+      'Android FYI 64 Vk Release (Pixel 2)': 'gpu_tests_android_vulkan_release_trybot_arm64',
       'Android FYI 32 dEQP Vk Release (Nexus 5X)': 'deqp_android_vulkan_release_trybot',
+      'Android FYI 32 dEQP Vk Release (Pixel 2)': 'deqp_android_vulkan_release_trybot',
       'Android FYI 64 dEQP Vk Release (Nexus 5X)': 'deqp_android_vulkan_release_trybot_arm64',
+      'Android FYI 64 dEQP Vk Release (Pixel 2)': 'deqp_android_vulkan_release_trybot_arm64',
       'GPU FYI Linux Builder': 'gpu_fyi_tests_release_trybot',
       'GPU FYI Linux Ozone Builder': 'gpu_fyi_tests_ozone_linux_system_gbm_libdrm_release_trybot',
       'GPU FYI Linux Builder (dbg)': 'gpu_fyi_tests_debug_trybot',
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index af6b2ef4..ca6e447 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -27843,6 +27843,7 @@
   <int value="-45067971" label="NewPrintPreview:disabled"/>
   <int value="-40935502" label="ContextualSuggestionsSlimPeekUI:enabled"/>
   <int value="-35388407" label="AshNewSystemMenu:disabled"/>
+  <int value="-30966385" label="enable-hardware-overlays"/>
   <int value="-29847483" label="MemoryAblation:enabled"/>
   <int value="-23804418"
       label="NTPArticleSuggestionsExpandableHeader:disabled"/>
@@ -34036,6 +34037,12 @@
   <int value="4" label="Not found"/>
 </enum>
 
+<enum name="OfflinePagesLastNIsSavingSamePageEnum">
+  <int value="0" label="New page"/>
+  <int value="1" label="Same page, better expected quality"/>
+  <int value="2" label="Same page, same expected quality"/>
+</enum>
+
 <enum name="OfflinePagesLoadStatus">
   <int value="0" label="Success"/>
   <int value="1" label="Store init failed"/>
@@ -46948,6 +46955,7 @@
   <int value="-1866379343" label="service_manager"/>
   <int value="-1656677225" label="file"/>
   <int value="-1632474908" label="viz"/>
+  <int value="-1615505903" label="media_gallery_util"/>
   <int value="-1450594275" label="identity"/>
   <int value="-1307090589" label="ui"/>
   <int value="-1289115149" label="device"/>
@@ -46961,6 +46969,7 @@
   <int value="-2816355" label="profile_import"/>
   <int value="357224138" label="user_id"/>
   <int value="498331100" label="preferences"/>
+  <int value="573935755" label="removable_storage_writer"/>
   <int value="685091421" label="unzip_service"/>
   <int value="692677280" label="audio"/>
   <int value="737685379" label="file_util"/>
@@ -46968,7 +46977,11 @@
   <int value="882338710" label="metrics"/>
   <int value="1051118555" label="resource_coordinator"/>
   <int value="1395049324" label="patch_service"/>
+  <int value="1484328260" label="autoclick_app"/>
+  <int value="1803540096" label="tap_visualizer_app"/>
+  <int value="1937572987" label="shortcut_viewer_app"/>
   <int value="1967189975" label="util_win"/>
+  <int value="1968783712" label="quick_launch_app"/>
   <int value="1998508722" label="echo"/>
   <int value="2077967579" label="pdf_compositor"/>
 </enum>
@@ -47374,7 +47387,9 @@
   <int value="21" label="DolbyVision profile5"/>
   <int value="22" label="DolbyVision profile7"/>
   <int value="23" label="Theora"/>
-  <int value="24" label="AV1 Profile0"/>
+  <int value="24" label="AV1 Profile Main"/>
+  <int value="25" label="AV1 Profile High"/>
+  <int value="26" label="AV1 Profile Pro"/>
 </enum>
 
 <enum name="VideoDecodeAcceleratorError">
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 6fd9c7a..b1ee206 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -11609,7 +11609,8 @@
   </summary>
 </histogram>
 
-<histogram name="clickjacking.discard_download" units="ms">
+<histogram name="clickjacking.discard_download" units="ms"
+    expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     The length of time between a dangerous download appearing on the downloads
@@ -11626,7 +11627,7 @@
   </summary>
 </histogram>
 
-<histogram name="clickjacking.launch_url" units="ms">
+<histogram name="clickjacking.launch_url" units="ms" expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     The length of time between the external protocol dialog being shown and the
@@ -11634,7 +11635,8 @@
   </summary>
 </histogram>
 
-<histogram name="clickjacking.open_download" units="ms">
+<histogram name="clickjacking.open_download" units="ms"
+    expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     The length of time between a download appearing on the download shelf, and
@@ -12205,7 +12207,8 @@
   </summary>
 </histogram>
 
-<histogram name="Compositing.CopyFromSurfaceTime" units="ms">
+<histogram name="Compositing.CopyFromSurfaceTime" units="ms"
+    expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     The turn around time taken for the async readback of pixels is measured
@@ -13838,7 +13841,8 @@
   </summary>
 </histogram>
 
-<histogram name="Cookie.KillDatabaseResult" enum="BooleanSuccess">
+<histogram name="Cookie.KillDatabaseResult" enum="BooleanSuccess"
+    expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     Whether killing the database because it was corrupted beyond repair
@@ -17028,7 +17032,8 @@
   </summary>
 </histogram>
 
-<histogram name="Diagnostics.Recovery.DiskSpace" enum="DiagnosticsResult">
+<histogram name="Diagnostics.Recovery.DiskSpace" enum="DiagnosticsResult"
+    expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     Shows the success and failure rates of the DiskSpace recovery step that runs
@@ -17039,7 +17044,8 @@
   </summary>
 </histogram>
 
-<histogram name="Diagnostics.Recovery.InstallType" enum="DiagnosticsResult">
+<histogram name="Diagnostics.Recovery.InstallType" enum="DiagnosticsResult"
+    expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     TBD - Not run automatically yet, so this is just a placeholder for future
@@ -17048,7 +17054,8 @@
   </summary>
 </histogram>
 
-<histogram name="Diagnostics.Recovery.JSONBookmarks" enum="DiagnosticsResult">
+<histogram name="Diagnostics.Recovery.JSONBookmarks" enum="DiagnosticsResult"
+    expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     Shows the success and failure rates of the JSONBookmarks recovery step that
@@ -17058,7 +17065,8 @@
   </summary>
 </histogram>
 
-<histogram name="Diagnostics.Recovery.JSONLocalState" enum="DiagnosticsResult">
+<histogram name="Diagnostics.Recovery.JSONLocalState" enum="DiagnosticsResult"
+    expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     Shows the success and failure rates of the JSONLocalState recovery step that
@@ -17068,7 +17076,8 @@
   </summary>
 </histogram>
 
-<histogram name="Diagnostics.Recovery.JSONPreferences" enum="DiagnosticsResult">
+<histogram name="Diagnostics.Recovery.JSONPreferences" enum="DiagnosticsResult"
+    expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     Shows the success and failure rates of the JSONPreferences recovery step
@@ -17091,7 +17100,7 @@
 </histogram>
 
 <histogram name="Diagnostics.Recovery.PathDictionaries"
-    enum="DiagnosticsResult">
+    enum="DiagnosticsResult" expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     Shows the success and failure rates of the PathDictionaries recovery step
@@ -17102,7 +17111,8 @@
   </summary>
 </histogram>
 
-<histogram name="Diagnostics.Recovery.PathLocalState" enum="DiagnosticsResult">
+<histogram name="Diagnostics.Recovery.PathLocalState" enum="DiagnosticsResult"
+    expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     Shows the success and failure rates of the PathLocalState recovery step that
@@ -17112,7 +17122,8 @@
   </summary>
 </histogram>
 
-<histogram name="Diagnostics.Recovery.PathResources" enum="DiagnosticsResult">
+<histogram name="Diagnostics.Recovery.PathResources" enum="DiagnosticsResult"
+    expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     Shows the success and failure rates of the PathResources recovery step that
@@ -17123,7 +17134,8 @@
   </summary>
 </histogram>
 
-<histogram name="Diagnostics.Recovery.PathUserData" enum="DiagnosticsResult">
+<histogram name="Diagnostics.Recovery.PathUserData" enum="DiagnosticsResult"
+    expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     Shows the success and failure rates of the PathUserData recovery step that
@@ -17206,7 +17218,7 @@
 </histogram>
 
 <histogram name="Diagnostics.Recovery.SQLiteIntegrityNSSCert"
-    enum="DiagnosticsResult">
+    enum="DiagnosticsResult" expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     Shows the success and failure rates of the SQLiteIntegrityNSSCert recovery
@@ -17217,7 +17229,7 @@
 </histogram>
 
 <histogram name="Diagnostics.Recovery.SQLiteIntegrityNSSKey"
-    enum="DiagnosticsResult">
+    enum="DiagnosticsResult" expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     Shows the success and failure rates of the SQLiteIntegrityNSSKey recovery
@@ -17263,7 +17275,8 @@
   </summary>
 </histogram>
 
-<histogram name="Diagnostics.Recovery.Version" enum="DiagnosticsResult">
+<histogram name="Diagnostics.Recovery.Version" enum="DiagnosticsResult"
+    expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     TBD - Not run automatically yet, so this is just a placeholder for future
@@ -17293,7 +17306,8 @@
   </summary>
 </histogram>
 
-<histogram name="Diagnostics.Test.DiskSpace" enum="DiagnosticsResult">
+<histogram name="Diagnostics.Test.DiskSpace" enum="DiagnosticsResult"
+    expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     Shows the success and failure rates of diagnostics for the DiskSpace test
@@ -17303,7 +17317,8 @@
   </summary>
 </histogram>
 
-<histogram name="Diagnostics.Test.InstallType" enum="DiagnosticsResult">
+<histogram name="Diagnostics.Test.InstallType" enum="DiagnosticsResult"
+    expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     TBD - Not run automatically yet, so this is just a placeholder for future
@@ -17312,7 +17327,8 @@
   </summary>
 </histogram>
 
-<histogram name="Diagnostics.Test.JSONBookmarks" enum="DiagnosticsResult">
+<histogram name="Diagnostics.Test.JSONBookmarks" enum="DiagnosticsResult"
+    expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     Shows the success and failure rates of diagnostics for the JSONBookmarks
@@ -17321,7 +17337,8 @@
   </summary>
 </histogram>
 
-<histogram name="Diagnostics.Test.JSONLocalState" enum="DiagnosticsResult">
+<histogram name="Diagnostics.Test.JSONLocalState" enum="DiagnosticsResult"
+    expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     Shows the success and failure rates of diagnostics for the JSONLocalState
@@ -17330,7 +17347,8 @@
   </summary>
 </histogram>
 
-<histogram name="Diagnostics.Test.JSONPreferences" enum="DiagnosticsResult">
+<histogram name="Diagnostics.Test.JSONPreferences" enum="DiagnosticsResult"
+    expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     Shows the success and failure rates of diagnostics for the JSONPreferences
@@ -17351,7 +17369,8 @@
   </summary>
 </histogram>
 
-<histogram name="Diagnostics.Test.PathDictionaries" enum="DiagnosticsResult">
+<histogram name="Diagnostics.Test.PathDictionaries" enum="DiagnosticsResult"
+    expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     Shows the success and failure rates of diagnostics for the PathDictionaries
@@ -17361,7 +17380,8 @@
   </summary>
 </histogram>
 
-<histogram name="Diagnostics.Test.PathLocalState" enum="DiagnosticsResult">
+<histogram name="Diagnostics.Test.PathLocalState" enum="DiagnosticsResult"
+    expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     Shows the success and failure rates of diagnostics for the PathLocalState
@@ -17371,7 +17391,8 @@
   </summary>
 </histogram>
 
-<histogram name="Diagnostics.Test.PathResources" enum="DiagnosticsResult">
+<histogram name="Diagnostics.Test.PathResources" enum="DiagnosticsResult"
+    expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     Shows the success and failure rates of diagnostics for the PathResources
@@ -17381,7 +17402,8 @@
   </summary>
 </histogram>
 
-<histogram name="Diagnostics.Test.PathUserData" enum="DiagnosticsResult">
+<histogram name="Diagnostics.Test.PathUserData" enum="DiagnosticsResult"
+    expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     Shows the success and failure rates of diagnostics for the PathUserData test
@@ -17457,7 +17479,7 @@
 </histogram>
 
 <histogram name="Diagnostics.Test.SQLiteIntegrityNSSCert"
-    enum="DiagnosticsResult">
+    enum="DiagnosticsResult" expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     Shows the success and failure rates of the SQLiteIntegrityNSSCert test that
@@ -17467,7 +17489,7 @@
 </histogram>
 
 <histogram name="Diagnostics.Test.SQLiteIntegrityNSSKey"
-    enum="DiagnosticsResult">
+    enum="DiagnosticsResult" expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     Shows the success and failure rates of the SQLiteIntegrityNSSKey test that
@@ -17509,7 +17531,8 @@
   </summary>
 </histogram>
 
-<histogram name="Diagnostics.Test.Version" enum="DiagnosticsResult">
+<histogram name="Diagnostics.Test.Version" enum="DiagnosticsResult"
+    expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     TBD - Not run automatically yet, so this is just a placeholder for future
@@ -17872,12 +17895,12 @@
   </summary>
 </histogram>
 
-<histogram name="DiskCache.3.FilesAge" units="hours">
+<histogram name="DiskCache.3.FilesAge" units="hours" expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>The age of the cache's files (wall time). AppCache.</summary>
 </histogram>
 
-<histogram name="DiskCache.4.FilesAge" units="hours">
+<histogram name="DiskCache.4.FilesAge" units="hours" expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>The age of the cache's files (wall time). ShaderCache.</summary>
 </histogram>
@@ -27442,7 +27465,8 @@
   </summary>
 </histogram>
 
-<histogram name="Extensions.ExternalItemState" enum="ExternalItemState">
+<histogram name="Extensions.ExternalItemState" enum="ExternalItemState"
+    expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     The number of sideloaded apps/extensions loaded on startup grouped by
@@ -27534,7 +27558,7 @@
 </histogram>
 
 <histogram name="Extensions.FromWebstoreInconsistency"
-    enum="ExtensionFromWebstoreInconcistencyEnum">
+    enum="ExtensionFromWebstoreInconcistencyEnum" expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     Number of apps/extensions loaded on startup with an inconsistent &quot;from
@@ -28187,7 +28211,8 @@
   </summary>
 </histogram>
 
-<histogram name="Extensions.ManifestFetchFailureRetryCountOtherUrl">
+<histogram name="Extensions.ManifestFetchFailureRetryCountOtherUrl"
+    expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     Number of times chrome retried to download an extension update manifest with
@@ -28211,7 +28236,8 @@
   </summary>
 </histogram>
 
-<histogram name="Extensions.ManifestReloadNeedsRelocalization">
+<histogram name="Extensions.ManifestReloadNeedsRelocalization"
+    expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     Number of extension loads on startup where it is necessary to reload the
@@ -28219,7 +28245,7 @@
   </summary>
 </histogram>
 
-<histogram name="Extensions.ManifestReloadNotNeeded">
+<histogram name="Extensions.ManifestReloadNotNeeded" expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     Number of extension loads on startup where it is not necessary to reload the
@@ -28227,7 +28253,8 @@
   </summary>
 </histogram>
 
-<histogram name="Extensions.ManifestReloadUnpackedDir">
+<histogram name="Extensions.ManifestReloadUnpackedDir"
+    expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     Number of extension loads on startup where it is necessary to reload the
@@ -29211,7 +29238,7 @@
   </summary>
 </histogram>
 
-<histogram name="Extensions.UpdateCheckApp">
+<histogram name="Extensions.UpdateCheckApp" expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     The number of legacy packaged apps and hosted apps that were checked during
@@ -29254,14 +29281,14 @@
   </summary>
 </histogram>
 
-<histogram name="Extensions.UpdateCheckPackagedApp">
+<histogram name="Extensions.UpdateCheckPackagedApp" expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     The number of packaged apps that were checked during an update check.
   </summary>
 </histogram>
 
-<histogram name="Extensions.UpdateCheckTheme">
+<histogram name="Extensions.UpdateCheckTheme" expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     The number of themes that were checked during an update check.
@@ -29475,13 +29502,13 @@
 </histogram>
 
 <histogram name="Extensions.WebstoreDownload.InterruptReason"
-    enum="InterruptReason">
+    enum="InterruptReason" expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>The reason a webstore download was interrupted.</summary>
 </histogram>
 
 <histogram name="Extensions.WebstoreDownload.InterruptReceivedKBytes"
-    units="KB">
+    units="KB" expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     The number of KBytes received for a webstore download before it was
@@ -29489,7 +29516,8 @@
   </summary>
 </histogram>
 
-<histogram name="Extensions.WebstoreDownload.InterruptTotalKBytes" units="KB">
+<histogram name="Extensions.WebstoreDownload.InterruptTotalKBytes" units="KB"
+    expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     The total expected size in KBytes of an interrupted webstore download.
@@ -29497,7 +29525,7 @@
 </histogram>
 
 <histogram name="Extensions.WebstoreDownload.InterruptTotalSizeUnknown"
-    enum="Boolean">
+    enum="Boolean" expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     Tracks whether the total size of an interrupted webstore download was known.
@@ -29523,7 +29551,8 @@
   </summary>
 </histogram>
 
-<histogram name="ExtensionService.AddVerified" enum="BooleanSuccess">
+<histogram name="ExtensionService.AddVerified" enum="BooleanSuccess"
+    expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     Records whether adding a new/updated extension to the install verifier
@@ -29532,7 +29561,7 @@
 </histogram>
 
 <histogram name="ExtensionService.VerifyAllSuccess"
-    enum="ExtensionServiceVerifyAllSuccess">
+    enum="ExtensionServiceVerifyAllSuccess" expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     The outcome of a call to ExtensionService::VerifyAllExtensions, whether it
@@ -29552,7 +29581,8 @@
   </summary>
 </histogram>
 
-<histogram name="ExtensionSettings.ShouldDoVerificationCheck" enum="Boolean">
+<histogram name="ExtensionSettings.ShouldDoVerificationCheck" enum="Boolean"
+    expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     When loading the chrome://extensions page, this records whether we decided
@@ -30850,7 +30880,8 @@
   </summary>
 </histogram>
 
-<histogram name="GData.AuthSuccess" enum="GDataAuthResult">
+<histogram name="GData.AuthSuccess" enum="GDataAuthResult"
+    expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>Result of the authentication for Drive.</summary>
 </histogram>
@@ -31341,7 +31372,8 @@
   <summary>The error code for a failed on-demand update check.</summary>
 </histogram>
 
-<histogram name="GoogleUpdate.UpdatePolicyIsOverridden" enum="Boolean">
+<histogram name="GoogleUpdate.UpdatePolicyIsOverridden" enum="Boolean"
+    expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     True if the effective update policy for Chrome on Windows is the result of
@@ -32948,7 +32980,7 @@
   </summary>
 </histogram>
 
-<histogram name="History.DeleteFTSIndexDatabases">
+<histogram name="History.DeleteFTSIndexDatabases" expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     Count of &quot;History Index *&quot; databases deleted.  These databases
@@ -33354,7 +33386,8 @@
   </summary>
 </histogram>
 
-<histogram name="History.TopSitesRecovery" enum="HistoryTopSitesRecoveryEnum">
+<histogram name="History.TopSitesRecovery" enum="HistoryTopSitesRecoveryEnum"
+    expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     The TopSites recovery code is written conservatively, with successful
@@ -33854,7 +33887,8 @@
   </summary>
 </histogram>
 
-<histogram name="Import.ShowDialog.FromBookmarkBarView" units="seconds">
+<histogram name="Import.ShowDialog.FromBookmarkBarView" units="seconds"
+    expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     The amount of time from install time to time that user opens import dialog
@@ -33862,7 +33896,8 @@
   </summary>
 </histogram>
 
-<histogram name="Import.ShowDialog.FromFloatingBookmarkBarView" units="seconds">
+<histogram name="Import.ShowDialog.FromFloatingBookmarkBarView" units="seconds"
+    expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     The amount of time from install time to time that user opens import dialog
@@ -36493,12 +36528,14 @@
   <summary>The type of panes which language settings loads.</summary>
 </histogram>
 
-<histogram name="LanguageUsage.AcceptLanguage" enum="LanguageCode">
+<histogram name="LanguageUsage.AcceptLanguage" enum="LanguageCode"
+    expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>Accept languages.</summary>
 </histogram>
 
-<histogram name="LanguageUsage.ApplicationLanguage" enum="LanguageCode">
+<histogram name="LanguageUsage.ApplicationLanguage" enum="LanguageCode"
+    expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>Application languages used for UI.</summary>
 </histogram>
@@ -40146,7 +40183,8 @@
   </summary>
 </histogram>
 
-<histogram name="Media.LocalRendererSinkStates" enum="LocalRendererSinkStates">
+<histogram name="Media.LocalRendererSinkStates" enum="LocalRendererSinkStates"
+    expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     State of the WebRtc local renderer, sampled once during the lifetime of a
@@ -45013,7 +45051,8 @@
   </summary>
 </histogram>
 
-<histogram name="Mouse.PointerSensitivity.Changed" enum="PointerSensitivity">
+<histogram name="Mouse.PointerSensitivity.Changed" enum="PointerSensitivity"
+    expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     Tracks mouse sensitivity setting changes by the user. This replaces the old
@@ -45021,7 +45060,8 @@
   </summary>
 </histogram>
 
-<histogram name="Mouse.PointerSensitivity.Started" enum="PointerSensitivity">
+<histogram name="Mouse.PointerSensitivity.Started" enum="PointerSensitivity"
+    expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     Tracks mouse sensitivity setting on startup. This replaces the old
@@ -45287,7 +45327,7 @@
   <summary>TBD</summary>
 </histogram>
 
-<histogram name="MPArch.RWH_RepaintDelta">
+<histogram name="MPArch.RWH_RepaintDelta" expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>TBD</summary>
 </histogram>
@@ -49720,7 +49760,8 @@
   </summary>
 </histogram>
 
-<histogram name="Net.FoundSystemTrustRootsAndroid" enum="Boolean">
+<histogram name="Net.FoundSystemTrustRootsAndroid" enum="Boolean"
+    expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     Whether or not system installed trust anchors could be distinguished from
@@ -50816,7 +50857,7 @@
   </summary>
 </histogram>
 
-<histogram name="Net.NotifyAddrChangeFailures">
+<histogram name="Net.NotifyAddrChangeFailures" expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     On Windows, NetworkChangeNotifierWin calls NotifyAddrChange, which can fail
@@ -55322,7 +55363,8 @@
   <summary>The time that a Wi-fi scan takes.</summary>
 </histogram>
 
-<histogram name="Net.WpadQuickCheckFailure" units="ms">
+<histogram name="Net.WpadQuickCheckFailure" units="ms"
+    expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     Duration of time that a failing WPAD QuickCheck takes. WPAD QuickCheck does
@@ -55331,7 +55373,8 @@
   </summary>
 </histogram>
 
-<histogram name="Net.WpadQuickCheckSuccess" units="ms">
+<histogram name="Net.WpadQuickCheckSuccess" units="ms"
+    expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     Duration of time that a successful WPAD QuickCheck takes. WPAD QuickCheck
@@ -58107,7 +58150,8 @@
   </summary>
 </histogram>
 
-<histogram name="NewTabPage.AppsPageDragSource" enum="AppsPageDragSource">
+<histogram name="NewTabPage.AppsPageDragSource" enum="AppsPageDragSource"
+    expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     Histogram for the source of app page drags. For any succesful drop onto an
@@ -61908,7 +61952,9 @@
   </summary>
 </histogram>
 
-<histogram name="OfflinePages.CanSaveRecentPage" enum="Boolean">
+<histogram name="OfflinePages.CanSaveRecentPage" enum="Boolean"
+    expires_after="2018-12-31">
+  <owner>carlosk@chromium.org</owner>
   <owner>fgorski@chromium.org</owner>
   <summary>
     Can a recent page be saved or not? Logged for all attempts to save
@@ -62423,6 +62469,18 @@
   </summary>
 </histogram>
 
+<histogram name="OfflinePages.LastN.IsSavingSamePage"
+    enum="OfflinePagesLastNIsSavingSamePageEnum" expires_after="2018-12-31">
+  <owner>carlosk@chromium.org</owner>
+  <summary>
+    Upon starting saving a new last_n offline page snapshot, report if that is
+    being done for a page that is new (a navigation happened) or for one that
+    has been previously saved in the same session (no navigation happened). This
+    metric will assist in determining if there is the need to better track
+    actual content changes in pages saved more than once by last_n.
+  </summary>
+</histogram>
+
 <histogram name="OfflinePages.LaunchLocation" enum="StarsLaunchLocation">
   <obsolete>
     Deprecated 5/2016. Offline pages no longer depend on bookmarks UI.
@@ -69938,7 +69996,7 @@
   </summary>
 </histogram>
 
-<histogram name="Platform.AsvGroup">
+<histogram name="Platform.AsvGroup" expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     Chrome OS (ARM Chromebooks using Exynos 5250 only) Adaptive Support Voltage
@@ -70398,7 +70456,7 @@
   </summary>
 </histogram>
 
-<histogram name="Platform.KernelWarningHashes">
+<histogram name="Platform.KernelWarningHashes" expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     The 32-bit hash of a kernel warning.  This is the hash of the
@@ -70418,7 +70476,8 @@
   </summary>
 </histogram>
 
-<histogram name="Platform.LotIdEnum" enum="Exynos5250LotIdEnum">
+<histogram name="Platform.LotIdEnum" enum="Exynos5250LotIdEnum"
+    expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     Chrome OS (ARM Chromebooks using Exynos 5250 only) indication about whether
@@ -71354,7 +71413,8 @@
   </summary>
 </histogram>
 
-<histogram name="Platform.Temperature.Sensor00" units="Celsius">
+<histogram name="Platform.Temperature.Sensor00" units="Celsius"
+    expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     Temperature reading at sensor 0 (I2C_CPU-Die) taken every 30s.
@@ -71368,56 +71428,64 @@
   </summary>
 </histogram>
 
-<histogram name="Platform.Temperature.Sensor02" units="Celsius">
+<histogram name="Platform.Temperature.Sensor02" units="Celsius"
+    expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     Temperature reading at sensor 2 (I2C_PCH-Die) taken every 30s.
   </summary>
 </histogram>
 
-<histogram name="Platform.Temperature.Sensor03" units="Celsius">
+<histogram name="Platform.Temperature.Sensor03" units="Celsius"
+    expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     Temperature reading at sensor 3 (I2C_PCH-Object) taken every 30s.
   </summary>
 </histogram>
 
-<histogram name="Platform.Temperature.Sensor04" units="Celsius">
+<histogram name="Platform.Temperature.Sensor04" units="Celsius"
+    expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     Temperature reading at sensor 4 (I2C_DDR-Die) taken every 30s.
   </summary>
 </histogram>
 
-<histogram name="Platform.Temperature.Sensor05" units="Celsius">
+<histogram name="Platform.Temperature.Sensor05" units="Celsius"
+    expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     Temperature reading at sensor 5 (I2C_DDR-Object) taken every 30s.
   </summary>
 </histogram>
 
-<histogram name="Platform.Temperature.Sensor06" units="Celsius">
+<histogram name="Platform.Temperature.Sensor06" units="Celsius"
+    expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     Temperature reading at sensor 6 (Charger-Die), taken every 30s.
   </summary>
 </histogram>
 
-<histogram name="Platform.Temperature.Sensor07" units="Celsius">
+<histogram name="Platform.Temperature.Sensor07" units="Celsius"
+    expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     Temperature reading at sensor 7 (Charger-Object) taken every 30s.
   </summary>
 </histogram>
 
-<histogram name="Platform.Temperature.Sensor08" units="Celsius">
+<histogram name="Platform.Temperature.Sensor08" units="Celsius"
+    expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     Temperature reading at sensor 8 (ECInternal) taken every 30s.
   </summary>
 </histogram>
 
-<histogram name="Platform.Temperature.Sensor09" units="Celsius">
+<histogram name="Platform.Temperature.Sensor09" units="Celsius"
+    expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>Temperature reading at sensor 9 (PECI) taken every 30s.</summary>
 </histogram>
@@ -73098,7 +73166,8 @@
   </summary>
 </histogram>
 
-<histogram name="Plugin.FlashNavigateUsage" enum="FlashNavigateUsageType">
+<histogram name="Plugin.FlashNavigateUsage" enum="FlashNavigateUsageType"
+    expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>Record usage of PPB_Flash.Navigate() Pepper API.</summary>
 </histogram>
@@ -76271,12 +76340,12 @@
   <summary>Load status of an avatar for decorating the Windows taskbar</summary>
 </histogram>
 
-<histogram name="Profile.BookmarksSize" units="MB">
+<histogram name="Profile.BookmarksSize" units="MB" expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>Size of the bookmarks database.</summary>
 </histogram>
 
-<histogram name="Profile.CookiesSize" units="MB">
+<histogram name="Profile.CookiesSize" units="MB" expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>Size of the cookies database.</summary>
 </histogram>
@@ -76389,12 +76458,12 @@
   </summary>
 </histogram>
 
-<histogram name="Profile.ExtensionSize" units="MB">
+<histogram name="Profile.ExtensionSize" units="MB" expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>Size of the extension cookies database.</summary>
 </histogram>
 
-<histogram name="Profile.FaviconsSize" units="MB">
+<histogram name="Profile.FaviconsSize" units="MB" expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>Size of the favicons database.</summary>
 </histogram>
@@ -76742,7 +76811,7 @@
 </histogram>
 
 <histogram name="Profile.SwitchGaiaPhotoSettings"
-    enum="ProfileGaiaPhotoOptions">
+    enum="ProfileGaiaPhotoOptions" expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     Counts of when users switch to using their GAIA photo instead of an avatar
@@ -76759,7 +76828,8 @@
   <summary>Activity of the user with regards to sync.</summary>
 </histogram>
 
-<histogram name="Profile.SyncCustomize" enum="ProfileSyncCustomize">
+<histogram name="Profile.SyncCustomize" enum="ProfileSyncCustomize"
+    expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     Number of times and ways the user customized the sync options of their
@@ -76792,17 +76862,18 @@
   </summary>
 </histogram>
 
-<histogram name="Profile.TopSitesSize" units="MB">
+<histogram name="Profile.TopSitesSize" units="MB" expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>Size of the top sites database.</summary>
 </histogram>
 
-<histogram name="Profile.TotalHistorySize" units="MB">
+<histogram name="Profile.TotalHistorySize" units="MB"
+    expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>Total size of all history databases.</summary>
 </histogram>
 
-<histogram name="Profile.TotalSize" units="MB">
+<histogram name="Profile.TotalSize" units="MB" expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>Total size of the profile data (excluding sub-folders).</summary>
 </histogram>
@@ -76858,12 +76929,13 @@
   </summary>
 </histogram>
 
-<histogram name="Profile.VisitedLinksSize" units="MB">
+<histogram name="Profile.VisitedLinksSize" units="MB"
+    expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>Size of the visited links database.</summary>
 </histogram>
 
-<histogram name="Profile.WebDataSize" units="MB">
+<histogram name="Profile.WebDataSize" units="MB" expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>Size of the web data database.</summary>
 </histogram>
@@ -89776,7 +89848,8 @@
   </summary>
 </histogram>
 
-<histogram name="Settings.HomePageIsNewTabPage.PulledFromSync" enum="Boolean">
+<histogram name="Settings.HomePageIsNewTabPage.PulledFromSync" enum="Boolean"
+    expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     The value of the home-page-is-new-tab-page pref when pulled down from sync
@@ -89784,7 +89857,8 @@
   </summary>
 </histogram>
 
-<histogram name="Settings.HomePageIsNewTabPage.PushedToSync" enum="Boolean">
+<histogram name="Settings.HomePageIsNewTabPage.PushedToSync" enum="Boolean"
+    expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     The value of the home-page-is-new-tab-page pref when pushed up to sync from
@@ -98967,7 +99041,7 @@
   </summary>
 </histogram>
 
-<histogram name="Tab.Close.UnloadTime" units="ms">
+<histogram name="Tab.Close.UnloadTime" units="ms" expires_after="2018-08-30">
   <summary>
     Time in milliseconds from when JS OnUnload handlers have finished to
     actually closing tab. Doesn't include time that's spent in JS OnUnload
@@ -100604,7 +100678,7 @@
   </summary>
 </histogram>
 
-<histogram name="Tabs.ScrubDistance" units="tabs">
+<histogram name="Tabs.ScrubDistance" units="tabs" expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     The distance a user 3 finger scrubbed to change tabs. Always positive
@@ -101337,33 +101411,38 @@
   </summary>
 </histogram>
 
-<histogram name="TimeZone.TimeZoneRequest.Event" enum="TimeZoneRequestEvent">
+<histogram name="TimeZone.TimeZoneRequest.Event" enum="TimeZoneRequestEvent"
+    expires_after="2018-08-30">
   <summary>Events in TimeZoneRequest.</summary>
 </histogram>
 
-<histogram name="TimeZone.TimeZoneRequest.ResponseCode" enum="HttpResponseCode">
+<histogram name="TimeZone.TimeZoneRequest.ResponseCode" enum="HttpResponseCode"
+    expires_after="2018-08-30">
   <summary>Http response codes in TimeZoneRequest.</summary>
 </histogram>
 
-<histogram name="TimeZone.TimeZoneRequest.ResponseFailureTime" units="ms">
+<histogram name="TimeZone.TimeZoneRequest.ResponseFailureTime" units="ms"
+    expires_after="2018-08-30">
   <summary>
     The time elapsed between the sending of the first API request and the time
     the final (failed) response was recorded. Includes all retries.
   </summary>
 </histogram>
 
-<histogram name="TimeZone.TimeZoneRequest.ResponseSuccessTime" units="ms">
+<histogram name="TimeZone.TimeZoneRequest.ResponseSuccessTime" units="ms"
+    expires_after="2018-08-30">
   <summary>
     The time elapsed between the sending of the first API request and the time
     the final (successfull) response was recorded. Includes all retries.
   </summary>
 </histogram>
 
-<histogram name="TimeZone.TimeZoneRequest.Result" enum="TimeZoneRequestResult">
+<histogram name="TimeZone.TimeZoneRequest.Result" enum="TimeZoneRequestResult"
+    expires_after="2018-08-30">
   <summary>Result of TimeZoneRequest.</summary>
 </histogram>
 
-<histogram name="TimeZone.TimeZoneRequest.Retries">
+<histogram name="TimeZone.TimeZoneRequest.Retries" expires_after="2018-08-30">
   <summary>Number of retries until the final response was recorded.</summary>
 </histogram>
 
@@ -101457,12 +101536,12 @@
   </summary>
 </histogram>
 
-<histogram name="TopSites.NumberOfApplyBlacklist">
+<histogram name="TopSites.NumberOfApplyBlacklist" expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>The number of times TopSitesImpl::ApplyBlacklist is called.</summary>
 </histogram>
 
-<histogram name="TopSites.NumberOfBlacklistedItems">
+<histogram name="TopSites.NumberOfBlacklistedItems" expires_after="2018-08-30">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     The number of items in the user Most Visited blacklist every time
diff --git a/tools/win/static_initializers/static_initializers.cc b/tools/win/static_initializers/static_initializers.cc
index 2800ac3..df76775b 100644
--- a/tools/win/static_initializers/static_initializers.cc
+++ b/tools/win/static_initializers/static_initializers.cc
@@ -37,11 +37,23 @@
   wchar_t ext[MAX_PATH];
   _wsplitpath_s(filename, NULL, 0, NULL, 0, NULL, 0, ext, MAX_PATH);
 
-  // Open and prepare the debug data associated with the executable.
-  hr = (*source)->loadDataForExe(filename, search_path, NULL);
-  if (FAILED(hr)) {
-    printf("loadDataForExe failed - HRESULT = %08lX\n", hr);
-    return false;
+  if (wcsicmp(ext, L".pdb") == 0) {
+    // Open and prepare the debug data specified.
+    hr = (*source)->loadDataFromPdb(filename);
+    if (FAILED(hr)) {
+      printf("loadDataFromPdb failed - HRESULT = %08lX\n", hr);
+      return false;
+    }
+  } else {
+    // Open and prepare the debug data associated with the executable.
+    hr = (*source)->loadDataForExe(filename, search_path, NULL);
+    if (FAILED(hr)) {
+      printf("loadDataForExe failed - HRESULT = %08lX\n", hr);
+      printf(
+          "Try copying the .pdb beside the PE file or passing the .pdb path "
+          "to this tool directly.");
+      return false;
+    }
   }
 
   // Open a session for querying symbols.
diff --git a/ui/base/ui_base_features.cc b/ui/base/ui_base_features.cc
index 5d36b9d..02cd2c7 100644
--- a/ui/base/ui_base_features.cc
+++ b/ui/base/ui_base_features.cc
@@ -92,10 +92,6 @@
 };
 
 #if defined(OS_WIN)
-// Enables stylus appearing as touch when in contact with digitizer.
-const base::Feature kDirectManipulationStylus = {
-    "DirectManipulationStylus", base::FEATURE_ENABLED_BY_DEFAULT};
-
 // Enables InputPane API for controlling on screen keyboard.
 const base::Feature kInputPaneOnScreenKeyboard = {
     "InputPaneOnScreenKeyboard", base::FEATURE_ENABLED_BY_DEFAULT};
@@ -121,6 +117,18 @@
     "PrecisionTouchpadScrollPhase", base::FEATURE_ENABLED_BY_DEFAULT};
 #endif  // defined(OS_WIN)
 
+#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX)
+// Enables stylus appearing as touch when in contact with digitizer.
+const base::Feature kDirectManipulationStylus = {
+    "DirectManipulationStylus",
+#if defined(OS_WIN)
+    base::FEATURE_ENABLED_BY_DEFAULT
+#else
+    base::FEATURE_DISABLED_BY_DEFAULT
+#endif
+};
+#endif  // defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX)
+
 // Used to have ash (Chrome OS system UI) run in its own process.
 // TODO(jamescook): Make flag only available in Chrome OS.
 const base::Feature kMash = {"Mash", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/ui/base/ui_base_features.h b/ui/base/ui_base_features.h
index 958bcbc..8433d829 100644
--- a/ui/base/ui_base_features.h
+++ b/ui/base/ui_base_features.h
@@ -32,7 +32,6 @@
 UI_BASE_EXPORT bool IsUiGpuRasterizationEnabled();
 
 #if defined(OS_WIN)
-UI_BASE_EXPORT extern const base::Feature kDirectManipulationStylus;
 UI_BASE_EXPORT extern const base::Feature kInputPaneOnScreenKeyboard;
 UI_BASE_EXPORT extern const base::Feature kPointerEventsForTouch;
 UI_BASE_EXPORT extern const base::Feature kPrecisionTouchpad;
@@ -43,6 +42,10 @@
 UI_BASE_EXPORT bool IsUsingWMPointerForTouch();
 #endif  // defined(OS_WIN)
 
+#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX)
+UI_BASE_EXPORT extern const base::Feature kDirectManipulationStylus;
+#endif  // defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX)
+
 // NOTE: this feature will either go away (and be replaced by kOopAsh), or
 // kOopAsh will go away in place of this.
 UI_BASE_EXPORT extern const base::Feature kMash;
diff --git a/ui/compositor/layer_unittest.cc b/ui/compositor/layer_unittest.cc
index 4388e432..8ccf6a4 100644
--- a/ui/compositor/layer_unittest.cc
+++ b/ui/compositor/layer_unittest.cc
@@ -1892,10 +1892,12 @@
   EXPECT_EQ(before.get(), child->cc_layer_for_testing());
 
   // Showing surface content changes the underlying cc layer.
+  viz::FrameSinkId frame_sink_id(1u, 1u);
+  viz::ParentLocalSurfaceIdAllocator allocator;
   before = child->cc_layer_for_testing();
-  child->SetShowPrimarySurface(viz::SurfaceId(), gfx::Size(10, 10),
-                               SK_ColorWHITE,
-                               cc::DeadlinePolicy::UseDefaultDeadline(), false);
+  child->SetShowPrimarySurface(
+      viz::SurfaceId(frame_sink_id, allocator.GenerateId()), gfx::Size(10, 10),
+      SK_ColorWHITE, cc::DeadlinePolicy::UseDefaultDeadline(), false);
   scoped_refptr<cc::Layer> after = child->cc_layer_for_testing();
   const auto* surface = static_cast<cc::SurfaceLayer*>(after.get());
   EXPECT_TRUE(after.get());
@@ -1903,8 +1905,8 @@
   EXPECT_EQ(base::nullopt, surface->deadline_in_frames());
 
   child->SetShowPrimarySurface(
-      viz::SurfaceId(), gfx::Size(10, 10), SK_ColorWHITE,
-      cc::DeadlinePolicy::UseSpecifiedDeadline(4u), false);
+      viz::SurfaceId(frame_sink_id, allocator.GenerateId()), gfx::Size(10, 10),
+      SK_ColorWHITE, cc::DeadlinePolicy::UseSpecifiedDeadline(4u), false);
   EXPECT_EQ(4u, surface->deadline_in_frames());
 }
 
diff --git a/ui/compositor/test/in_process_context_factory.cc b/ui/compositor/test/in_process_context_factory.cc
index f23e415..c1e9ebf1 100644
--- a/ui/compositor/test/in_process_context_factory.cc
+++ b/ui/compositor/test/in_process_context_factory.cc
@@ -45,9 +45,9 @@
 
 namespace ui {
 namespace {
-// The client_id used here should not conflict with the client_id generated
-// from RenderWidgetHostImpl and client_id(0) used by aura::WindowPortMus.
-constexpr uint32_t kDefaultClientId = std::numeric_limits<uint32_t>::max();
+
+// This should not conflict with ids from RenderWidgetHostImpl or WindowService.
+constexpr uint32_t kDefaultClientId = std::numeric_limits<uint32_t>::max() / 2;
 
 class FakeReflector : public Reflector {
  public:
diff --git a/ui/events/blink/input_scroll_elasticity_controller.cc b/ui/events/blink/input_scroll_elasticity_controller.cc
index 557afda..7618481 100644
--- a/ui/events/blink/input_scroll_elasticity_controller.cc
+++ b/ui/events/blink/input_scroll_elasticity_controller.cc
@@ -106,6 +106,52 @@
   return base::WeakPtr<InputScrollElasticityController>();
 }
 
+void InputScrollElasticityController::ObserveRealScrollBegin(
+    bool enter_momentum,
+    bool leave_momentum) {
+  if (enter_momentum) {
+    if (state_ == kStateInactive)
+      state_ = kStateMomentumScroll;
+  } else if (leave_momentum) {
+    scroll_velocity = gfx::Vector2dF();
+    last_scroll_event_timestamp_ = base::TimeTicks();
+    state_ = kStateActiveScroll;
+    pending_overscroll_delta_ = gfx::Vector2dF();
+  }
+}
+
+void InputScrollElasticityController::ObserveScrollUpdate(
+    const gfx::Vector2dF& event_delta,
+    const gfx::Vector2dF& unused_scroll_delta,
+    const base::TimeTicks event_timestamp,
+    const cc::OverscrollBehavior overscroll_behavior,
+    bool has_momentum) {
+  if (state_ == kStateMomentumAnimated || state_ == kStateInactive)
+    return;
+
+  if (!received_overscroll_update_ && !unused_scroll_delta.IsZero()) {
+    overscroll_behavior_ = overscroll_behavior;
+    received_overscroll_update_ = true;
+  }
+
+  UpdateVelocity(event_delta, event_timestamp);
+  Overscroll(event_delta, unused_scroll_delta);
+  if (has_momentum && !helper_->StretchAmount().IsZero())
+    EnterStateMomentumAnimated(event_timestamp);
+}
+
+void InputScrollElasticityController::ObserveRealScrollEnd(
+    const base::TimeTicks event_timestamp) {
+  if (state_ == kStateMomentumAnimated || state_ == kStateInactive)
+    return;
+
+  if (helper_->StretchAmount().IsZero()) {
+    EnterStateInactive();
+  } else {
+    EnterStateMomentumAnimated(event_timestamp);
+  }
+}
+
 void InputScrollElasticityController::ObserveGestureEventAndResult(
     const blink::WebGestureEvent& gesture_event,
     const cc::InputHandlerScrollResult& scroll_result) {
@@ -117,62 +163,30 @@
       overscroll_behavior_ = cc::OverscrollBehavior();
       if (gesture_event.data.scroll_begin.synthetic)
         return;
-      if (gesture_event.data.scroll_begin.inertial_phase ==
-          blink::WebGestureEvent::kMomentumPhase) {
-        if (state_ == kStateInactive)
-          state_ = kStateMomentumScroll;
-      } else if (gesture_event.data.scroll_begin.inertial_phase ==
-                     blink::WebGestureEvent::kNonMomentumPhase &&
-                 gesture_event.data.scroll_begin.delta_hint_units ==
-                     blink::WebGestureEvent::kPrecisePixels) {
-        scroll_velocity = gfx::Vector2dF();
-        last_scroll_event_timestamp_ = base::TimeTicks();
-        state_ = kStateActiveScroll;
-        pending_overscroll_delta_ = gfx::Vector2dF();
-      }
+
+      bool enter_momentum = gesture_event.data.scroll_begin.inertial_phase ==
+                            blink::WebGestureEvent::kMomentumPhase;
+      bool leave_momentum = gesture_event.data.scroll_begin.inertial_phase ==
+                                blink::WebGestureEvent::kNonMomentumPhase &&
+                            gesture_event.data.scroll_begin.delta_hint_units ==
+                                blink::WebGestureEvent::kPrecisePixels;
+      ObserveRealScrollBegin(enter_momentum, leave_momentum);
       break;
     }
     case blink::WebInputEvent::kGestureScrollUpdate: {
       gfx::Vector2dF event_delta(-gesture_event.data.scroll_update.delta_x,
                                  -gesture_event.data.scroll_update.delta_y);
-      switch (state_) {
-        case kStateMomentumAnimated:
-        case kStateInactive:
-          break;
-        case kStateActiveScroll:
-        case kStateMomentumScroll:
-          if (!received_overscroll_update_ &&
-              !scroll_result.unused_scroll_delta.IsZero()) {
-            overscroll_behavior_ = scroll_result.overscroll_behavior;
-            received_overscroll_update_ = true;
-          }
-          UpdateVelocity(event_delta, event_timestamp);
-          Overscroll(event_delta, scroll_result.unused_scroll_delta);
-          if (gesture_event.data.scroll_update.inertial_phase ==
-                  blink::WebGestureEvent::kMomentumPhase &&
-              !helper_->StretchAmount().IsZero()) {
-            EnterStateMomentumAnimated(event_timestamp);
-          }
-          break;
-      }
+      bool has_momentum = gesture_event.data.scroll_update.inertial_phase ==
+                          blink::WebGestureEvent::kMomentumPhase;
+      ObserveScrollUpdate(event_delta, scroll_result.unused_scroll_delta,
+                          event_timestamp, scroll_result.overscroll_behavior,
+                          has_momentum);
       break;
     }
     case blink::WebInputEvent::kGestureScrollEnd: {
       if (gesture_event.data.scroll_end.synthetic)
         return;
-      switch (state_) {
-        case kStateMomentumAnimated:
-        case kStateInactive:
-          break;
-        case kStateActiveScroll:
-        case kStateMomentumScroll:
-          if (helper_->StretchAmount().IsZero()) {
-            EnterStateInactive();
-          } else {
-            EnterStateMomentumAnimated(event_timestamp);
-          }
-          break;
-      }
+      ObserveRealScrollEnd(event_timestamp);
       break;
     }
     default:
diff --git a/ui/events/blink/input_scroll_elasticity_controller.h b/ui/events/blink/input_scroll_elasticity_controller.h
index f5478b5..46e345f8 100644
--- a/ui/events/blink/input_scroll_elasticity_controller.h
+++ b/ui/events/blink/input_scroll_elasticity_controller.h
@@ -52,6 +52,17 @@
 
   base::WeakPtr<InputScrollElasticityController> GetWeakPtr();
 
+  // These methods that are "real" should only be called if the associated
+  // event is not synthetic. Otherwise, calling them will disrupt elastic
+  // scrolling.
+  void ObserveRealScrollBegin(bool enter_momentum, bool leave_momentum);
+  void ObserveScrollUpdate(const gfx::Vector2dF& event_delta,
+                           const gfx::Vector2dF& unused_scroll_delta,
+                           const base::TimeTicks event_timestamp,
+                           const cc::OverscrollBehavior overscroll_behavior,
+                           bool has_momentum);
+  void ObserveRealScrollEnd(const base::TimeTicks event_timestamp);
+
   // Update the overscroll state based a gesture event that has been processed.
   // Note that this assumes that all events are coming from a single input
   // device. If the user simultaneously uses multiple input devices, Cocoa may
diff --git a/ui/events/event_switches.cc b/ui/events/event_switches.cc
index 3242850..d89187b 100644
--- a/ui/events/event_switches.cc
+++ b/ui/events/event_switches.cc
@@ -39,6 +39,10 @@
 
 // Tells Chrome to do edge touch filtering. Useful for convertible tablet.
 const char kEdgeTouchFiltering[] = "edge-touch-filtering";
+
+// Tells Chrome to do filter out low pressure touches, as from a pencil. Should
+// only be used if the driver level filtering is insufficient.
+const char kLowPressureTouchFiltering[] = "low-pressure-touch-filtering";
 #endif
 
 }  // namespace switches
diff --git a/ui/events/event_switches.h b/ui/events/event_switches.h
index 9c1e136d..ddcbf12 100644
--- a/ui/events/event_switches.h
+++ b/ui/events/event_switches.h
@@ -23,6 +23,7 @@
 EVENTS_BASE_EXPORT extern const char kExtraTouchNoiseFiltering[];
 EVENTS_BASE_EXPORT extern const char kTouchCalibration[];
 EVENTS_BASE_EXPORT extern const char kEdgeTouchFiltering[];
+EVENTS_BASE_EXPORT extern const char kLowPressureTouchFiltering[];
 #endif
 
 }  // namespace switches
diff --git a/ui/events/ozone/BUILD.gn b/ui/events/ozone/BUILD.gn
index f9a3328..13f85b19 100644
--- a/ui/events/ozone/BUILD.gn
+++ b/ui/events/ozone/BUILD.gn
@@ -117,6 +117,8 @@
       "evdev/touch_filter/far_apart_taps_touch_noise_filter.h",
       "evdev/touch_filter/horizontally_aligned_touch_noise_filter.cc",
       "evdev/touch_filter/horizontally_aligned_touch_noise_filter.h",
+      "evdev/touch_filter/low_pressure_filter.cc",
+      "evdev/touch_filter/low_pressure_filter.h",
       "evdev/touch_filter/single_position_touch_noise_filter.cc",
       "evdev/touch_filter/single_position_touch_noise_filter.h",
       "evdev/touch_filter/touch_filter.h",
diff --git a/ui/events/ozone/evdev/touch_filter/false_touch_finder.cc b/ui/events/ozone/evdev/touch_filter/false_touch_finder.cc
index b15fb4d0..c8bf4ddd 100644
--- a/ui/events/ozone/evdev/touch_filter/false_touch_finder.cc
+++ b/ui/events/ozone/evdev/touch_filter/false_touch_finder.cc
@@ -12,6 +12,7 @@
 #include "ui/events/ozone/evdev/touch_filter/edge_touch_filter.h"
 #include "ui/events/ozone/evdev/touch_filter/far_apart_taps_touch_noise_filter.h"
 #include "ui/events/ozone/evdev/touch_filter/horizontally_aligned_touch_noise_filter.h"
+#include "ui/events/ozone/evdev/touch_filter/low_pressure_filter.h"
 #include "ui/events/ozone/evdev/touch_filter/single_position_touch_noise_filter.h"
 #include "ui/events/ozone/evdev/touch_filter/touch_filter.h"
 
@@ -25,9 +26,13 @@
       switches::kExtraTouchNoiseFiltering);
   bool edge_filtering = base::CommandLine::ForCurrentProcess()->HasSwitch(
       switches::kEdgeTouchFiltering);
-  if (noise_filtering || edge_filtering) {
-    return base::WrapUnique(new FalseTouchFinder(
-        noise_filtering, edge_filtering, touchscreen_size));
+  bool low_pressure_filtering =
+      base::CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kLowPressureTouchFiltering);
+  if (noise_filtering || edge_filtering || low_pressure_filtering) {
+    return base::WrapUnique(
+        new FalseTouchFinder(noise_filtering, edge_filtering,
+                             low_pressure_filtering, touchscreen_size));
   }
   return nullptr;
 }
@@ -62,6 +67,7 @@
 
 FalseTouchFinder::FalseTouchFinder(bool noise_filtering,
                                    bool edge_filtering,
+                                   bool low_pressure_filtering,
                                    gfx::Size touchscreen_size)
     : last_noise_time_(ui::EventTimeForNow()) {
   if (noise_filtering) {
@@ -75,6 +81,9 @@
     delay_filters_.push_back(
         std::make_unique<EdgeTouchFilter>(touchscreen_size));
   }
+  if (low_pressure_filtering) {
+    delay_filters_.push_back(std::make_unique<LowPressureFilter>());
+  }
 }
 
 void FalseTouchFinder::RecordUMA(bool had_noise, base::TimeTicks time) {
diff --git a/ui/events/ozone/evdev/touch_filter/false_touch_finder.h b/ui/events/ozone/evdev/touch_filter/false_touch_finder.h
index bde6cba..6cce305 100644
--- a/ui/events/ozone/evdev/touch_filter/false_touch_finder.h
+++ b/ui/events/ozone/evdev/touch_filter/false_touch_finder.h
@@ -45,6 +45,7 @@
  private:
   FalseTouchFinder(bool touch_noise_filtering,
                    bool edge_filtering,
+                   bool low_pressure_filtering,
                    gfx::Size touchscreen_size);
 
   // Records how frequently noisy touches occur to UMA.
diff --git a/ui/events/ozone/evdev/touch_filter/false_touch_finder_unittest.cc b/ui/events/ozone/evdev/touch_filter/false_touch_finder_unittest.cc
index 80f97b5..e0df4ec 100644
--- a/ui/events/ozone/evdev/touch_filter/false_touch_finder_unittest.cc
+++ b/ui/events/ozone/evdev/touch_filter/false_touch_finder_unittest.cc
@@ -27,6 +27,7 @@
     size_t slot;
     bool touching;
     gfx::PointF location;
+    float pressure;
     bool expect_noise;
     bool expect_delay;
   };
@@ -46,6 +47,7 @@
       touch.y = entry.location.y();
       touch.tracking_id = entry.slot;
       touch.slot = entry.slot;
+      touch.pressure = entry.pressure;
       touch.was_touching = was_touching.test(touch.slot);
       touch.touching = entry.touching;
       touches.push_back(touch);
@@ -86,6 +88,8 @@
         switches::kExtraTouchNoiseFiltering);
     base::CommandLine::ForCurrentProcess()->AppendSwitch(
         switches::kEdgeTouchFiltering);
+    base::CommandLine::ForCurrentProcess()->AppendSwitch(
+        switches::kLowPressureTouchFiltering);
     false_touch_finder_ = FalseTouchFinder::Create(touchscreen_size);
   }
 
@@ -97,15 +101,15 @@
 // Test that taps which are far apart in quick succession are considered noise.
 TEST_F(FalseTouchFinderTest, FarApartTaps) {
   const TouchEntry kTestData[] = {
-      {10, 1, true, gfx::PointF(10, 10), false, false},
-      {20, 1, true, gfx::PointF(10, 11), false, false},
-      {30, 1, true, gfx::PointF(10, 12), false, false},
-      {30, 2, true, gfx::PointF(2500, 1000), true, false},
-      {40, 1, true, gfx::PointF(10, 13), true, false},
-      {40, 2, true, gfx::PointF(2500, 1001), true, false},
-      {50, 1, true, gfx::PointF(10, 14), true, false},
-      {50, 2, false, gfx::PointF(2500, 1002), true, false},
-      {60, 1, false, gfx::PointF(10, 15), true, false}};
+      {10, 1, true, gfx::PointF(10, 10), 0.35, false, false},
+      {20, 1, true, gfx::PointF(10, 11), 0.35, false, false},
+      {30, 1, true, gfx::PointF(10, 12), 0.35, false, false},
+      {30, 2, true, gfx::PointF(2500, 1000), 0.35, true, false},
+      {40, 1, true, gfx::PointF(10, 13), 0.35, true, false},
+      {40, 2, true, gfx::PointF(2500, 1001), 0.35, true, false},
+      {50, 1, true, gfx::PointF(10, 14), 0.35, true, false},
+      {50, 2, false, gfx::PointF(2500, 1002), 0.35, true, false},
+      {60, 1, false, gfx::PointF(10, 15), 0.35, true, false}};
   EXPECT_TRUE(FilterAndCheck(kTestData, arraysize(kTestData)));
 }
 
@@ -113,55 +117,55 @@
 // not considered noise.
 TEST_F(FalseTouchFinderTest, FarApartTapsSlow) {
   const TouchEntry kTestData[] = {
-      {1000, 1, true, gfx::PointF(10, 10), false, false},
-      {1500, 1, true, gfx::PointF(10, 11), false, false},
-      {2000, 1, true, gfx::PointF(10, 12), false, false},
-      {2500, 1, true, gfx::PointF(10, 13), false, false},
-      {2500, 2, true, gfx::PointF(2500, 1000), false, false},
-      {3000, 1, true, gfx::PointF(10, 14), false, false},
-      {3000, 2, false, gfx::PointF(2500, 1001), false, false},
-      {3500, 1, false, gfx::PointF(10, 15), false, false}};
+      {1000, 1, true, gfx::PointF(10, 10), 0.35, false, false},
+      {1500, 1, true, gfx::PointF(10, 11), 0.35, false, false},
+      {2000, 1, true, gfx::PointF(10, 12), 0.35, false, false},
+      {2500, 1, true, gfx::PointF(10, 13), 0.35, false, false},
+      {2500, 2, true, gfx::PointF(2500, 1000), 0.35, false, false},
+      {3000, 1, true, gfx::PointF(10, 14), 0.35, false, false},
+      {3000, 2, false, gfx::PointF(2500, 1001), 0.35, false, false},
+      {3500, 1, false, gfx::PointF(10, 15), 0.35, false, false}};
   EXPECT_TRUE(FilterAndCheck(kTestData, arraysize(kTestData)));
 }
 
 // Test that touches which are horizontally aligned are considered noise.
 TEST_F(FalseTouchFinderTest, HorizontallyAligned) {
   const TouchEntry kTestData[] = {
-      {10, 1, true, gfx::PointF(10, 10), false, false},
-      {20, 1, true, gfx::PointF(10, 10), false, false},
-      {20, 2, true, gfx::PointF(10, 25), true, false},
-      {30, 1, false, gfx::PointF(10, 10), false, false},
-      {30, 2, true, gfx::PointF(10, 25), true, false},
-      {40, 2, false, gfx::PointF(10, 25), true, false}};
+      {10, 1, true, gfx::PointF(10, 10), 0.35, false, false},
+      {20, 1, true, gfx::PointF(10, 10), 0.35, false, false},
+      {20, 2, true, gfx::PointF(10, 25), 0.35, true, false},
+      {30, 1, false, gfx::PointF(10, 10), 0.35, false, false},
+      {30, 2, true, gfx::PointF(10, 25), 0.35, true, false},
+      {40, 2, false, gfx::PointF(10, 25), 0.35, true, false}};
   EXPECT_TRUE(FilterAndCheck(kTestData, arraysize(kTestData)));
 }
 
 // Test that touches in the same position are considered noise.
 TEST_F(FalseTouchFinderTest, SamePosition) {
   const TouchEntry kTestData[] = {
-      {1000, 1, true, gfx::PointF(10, 10), false, false},
-      {1500, 1, false, gfx::PointF(10, 10), false, false},
-      {2000, 1, true, gfx::PointF(10, 10), false, false},
-      {2500, 1, false, gfx::PointF(10, 10), false, false},
-      {3000, 1, true, gfx::PointF(50, 50), false, false},
-      {3500, 1, true, gfx::PointF(50, 51), false, false},
-      {3500, 2, true, gfx::PointF(10, 10), true, false},
-      {4000, 1, false, gfx::PointF(50, 52), false, false},
-      {4000, 2, false, gfx::PointF(10, 10), true, false},
-      {4500, 1, true, gfx::PointF(10, 10), true, false},
-      {5000, 1, false, gfx::PointF(10, 10), true, false}};
+      {1000, 1, true, gfx::PointF(10, 10), 0.35, false, false},
+      {1500, 1, false, gfx::PointF(10, 10), 0.35, false, false},
+      {2000, 1, true, gfx::PointF(10, 10), 0.35, false, false},
+      {2500, 1, false, gfx::PointF(10, 10), 0.35, false, false},
+      {3000, 1, true, gfx::PointF(50, 50), 0.35, false, false},
+      {3500, 1, true, gfx::PointF(50, 51), 0.35, false, false},
+      {3500, 2, true, gfx::PointF(10, 10), 0.35, true, false},
+      {4000, 1, false, gfx::PointF(50, 52), 0.35, false, false},
+      {4000, 2, false, gfx::PointF(10, 10), 0.35, true, false},
+      {4500, 1, true, gfx::PointF(10, 10), 0.35, true, false},
+      {5000, 1, false, gfx::PointF(10, 10), 0.35, true, false}};
   EXPECT_TRUE(FilterAndCheck(kTestData, arraysize(kTestData)));
 }
 
 // Test that a multi-second touch is considered noise.
 TEST_F(FalseTouchFinderTest, MultiSecondTouch) {
   const TouchEntry kTestData[] = {
-      {1000, 1, true, gfx::PointF(10, 10), false, false},
-      {2000, 1, true, gfx::PointF(10, 11), false, false},
-      {3000, 1, true, gfx::PointF(10, 10), false, false},
-      {4000, 1, true, gfx::PointF(10, 11), true, false},
-      {5000, 1, true, gfx::PointF(10, 10), true, false},
-      {6000, 1, true, gfx::PointF(10, 11), true, false}};
+      {1000, 1, true, gfx::PointF(10, 10), 0.35, false, false},
+      {2000, 1, true, gfx::PointF(10, 11), 0.35, false, false},
+      {3000, 1, true, gfx::PointF(10, 10), 0.35, false, false},
+      {4000, 1, true, gfx::PointF(10, 11), 0.35, true, false},
+      {5000, 1, true, gfx::PointF(10, 10), 0.35, true, false},
+      {6000, 1, true, gfx::PointF(10, 11), 0.35, true, false}};
   EXPECT_TRUE(FilterAndCheck(kTestData, arraysize(kTestData)));
 }
 
@@ -171,18 +175,18 @@
   int ts_width = touchscreen_size.width();
   int ts_height = touchscreen_size.height();
   const TouchEntry kTestData[] = {
-      {10, 1, true, gfx::PointF(0, 100), false, true},
-      {20, 1, true, gfx::PointF(0, 100), false, true},
-      {30, 1, false, gfx::PointF(0, 100), false, true},
-      {40, 2, true, gfx::PointF(ts_width - 1, 100), false, true},
-      {50, 2, true, gfx::PointF(ts_width - 1, 100), false, true},
-      {60, 2, false, gfx::PointF(ts_width - 1, 100), false, true},
-      {70, 3, true, gfx::PointF(100, 0), false, true},
-      {80, 3, true, gfx::PointF(100, 0), false, true},
-      {90, 3, false, gfx::PointF(100, 0), false, true},
-      {100, 4, true, gfx::PointF(100, ts_height - 1), false, true},
-      {110, 4, true, gfx::PointF(100, ts_height - 1), false, true},
-      {120, 4, false, gfx::PointF(100, ts_height - 1), false, true}};
+      {10, 1, true, gfx::PointF(0, 100), 0.35, false, true},
+      {20, 1, true, gfx::PointF(0, 100), 0.35, false, true},
+      {30, 1, false, gfx::PointF(0, 100), 0.35, false, true},
+      {40, 2, true, gfx::PointF(ts_width - 1, 100), 0.35, false, true},
+      {50, 2, true, gfx::PointF(ts_width - 1, 100), 0.35, false, true},
+      {60, 2, false, gfx::PointF(ts_width - 1, 100), 0.35, false, true},
+      {70, 3, true, gfx::PointF(100, 0), 0.35, false, true},
+      {80, 3, true, gfx::PointF(100, 0), 0.35, false, true},
+      {90, 3, false, gfx::PointF(100, 0), 0.35, false, true},
+      {100, 4, true, gfx::PointF(100, ts_height - 1), 0.35, false, true},
+      {110, 4, true, gfx::PointF(100, ts_height - 1), 0.35, false, true},
+      {120, 4, false, gfx::PointF(100, ts_height - 1), 0.35, false, true}};
   EXPECT_TRUE(FilterAndCheck(kTestData, arraysize(kTestData)));
 }
 
@@ -190,14 +194,14 @@
 // as soon as it moves.
 TEST_F(FalseTouchFinderTest, MoveFromEdge) {
   const TouchEntry kTestData[] = {
-      {10, 1, true, gfx::PointF(0, 100), false, true},
-      {20, 1, true, gfx::PointF(0, 100), false, true},
-      {30, 1, true, gfx::PointF(1, 100), false, false},
-      {40, 1, false, gfx::PointF(1, 100), false, false},
-      {50, 1, true, gfx::PointF(0, 100), false, true},
-      {60, 1, true, gfx::PointF(0, 100), false, true},
-      {70, 1, true, gfx::PointF(0, 101), false, false},
-      {80, 1, false, gfx::PointF(0, 101), false, false}};
+      {10, 1, true, gfx::PointF(0, 100), 0.35, false, true},
+      {20, 1, true, gfx::PointF(0, 100), 0.35, false, true},
+      {30, 1, true, gfx::PointF(1, 100), 0.35, false, false},
+      {40, 1, false, gfx::PointF(1, 100), 0.35, false, false},
+      {50, 1, true, gfx::PointF(0, 100), 0.35, false, true},
+      {60, 1, true, gfx::PointF(0, 100), 0.35, false, true},
+      {70, 1, true, gfx::PointF(0, 101), 0.35, false, false},
+      {80, 1, false, gfx::PointF(0, 101), 0.35, false, false}};
   EXPECT_TRUE(FilterAndCheck(kTestData, arraysize(kTestData)));
 }
 
@@ -205,10 +209,34 @@
 // cancelled when it moves to the edge.
 TEST_F(FalseTouchFinderTest, MoveToEdge) {
   const TouchEntry kTestData[] = {
-      {10, 1, true, gfx::PointF(100, 100), false, false},
-      {20, 1, true, gfx::PointF(100, 100), false, false},
-      {30, 1, true, gfx::PointF(0, 100), false, false},
-      {40, 1, false, gfx::PointF(0, 100), false, false}};
+      {10, 1, true, gfx::PointF(100, 100), 0.35, false, false},
+      {20, 1, true, gfx::PointF(100, 100), 0.35, false, false},
+      {30, 1, true, gfx::PointF(0, 100), 0.35, false, false},
+      {40, 1, false, gfx::PointF(0, 100), 0.35, false, false}};
+  EXPECT_TRUE(FilterAndCheck(kTestData, arraysize(kTestData)));
+}
+
+// Test that a pencil with a wide tip should be filtered out. Based on real
+// logs.
+TEST_F(FalseTouchFinderTest, FatPencilPressure) {
+  const TouchEntry kTestData[] = {
+      {10, 1, true, gfx::PointF(10, 10), 0.180392, false, true},
+      {20, 1, true, gfx::PointF(10, 10), 0.176471, false, true},
+      {30, 1, true, gfx::PointF(10, 10), 0.180392, false, true},
+      {40, 1, true, gfx::PointF(10, 10), 0.164706, false, true},
+      {50, 1, true, gfx::PointF(10, 10), 0.101961, false, true}};
+  EXPECT_TRUE(FilterAndCheck(kTestData, arraysize(kTestData)));
+}
+
+// Test that a pinky finger lightly pressed is not filtered out. Based on real
+// logs.
+TEST_F(FalseTouchFinderTest, LightPinkyPressure) {
+  const TouchEntry kTestData[] = {
+      {10, 1, true, gfx::PointF(10, 10), 0.243137, false, false},
+      {20, 1, true, gfx::PointF(10, 10), 0.231373, false, false},
+      {30, 1, true, gfx::PointF(10, 10), 0.215686, false, false},
+      {40, 1, true, gfx::PointF(10, 10), 0.211765, false, false},
+      {50, 1, true, gfx::PointF(10, 10), 0.203922, false, false}};
   EXPECT_TRUE(FilterAndCheck(kTestData, arraysize(kTestData)));
 }
 
diff --git a/ui/events/ozone/evdev/touch_filter/low_pressure_filter.cc b/ui/events/ozone/evdev/touch_filter/low_pressure_filter.cc
new file mode 100644
index 0000000..1c37786
--- /dev/null
+++ b/ui/events/ozone/evdev/touch_filter/low_pressure_filter.cc
@@ -0,0 +1,44 @@
+// 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 "ui/events/ozone/evdev/touch_filter/low_pressure_filter.h"
+
+#include <stddef.h>
+
+#include <cmath>
+
+#include "base/macros.h"
+
+namespace ui {
+
+namespace {
+
+const float kMinPressure = 0.19;
+
+}  // namespace
+
+LowPressureFilter::LowPressureFilter() {}
+LowPressureFilter::~LowPressureFilter() {}
+
+void LowPressureFilter::Filter(
+    const std::vector<InProgressTouchEvdev>& touches,
+    base::TimeTicks time,
+    std::bitset<kNumTouchEvdevSlots>* slots_should_delay) {
+  for (const InProgressTouchEvdev& touch : touches) {
+    size_t slot = touch.slot;
+
+    if (!touch.touching && !touch.was_touching)
+      continue;  // Only look at slots with active touches.
+
+    if (!touch.was_touching)
+      slots_filtered_.set(slot, true);  // Start tracking a new touch.
+
+    if (touch.pressure >= kMinPressure)
+      slots_filtered_.set(slot, false);  // Release touches above threshold.
+  }
+
+  (*slots_should_delay) |= slots_filtered_;
+}
+
+}  // namespace ui
diff --git a/ui/events/ozone/evdev/touch_filter/low_pressure_filter.h b/ui/events/ozone/evdev/touch_filter/low_pressure_filter.h
new file mode 100644
index 0000000..dcfadc07
--- /dev/null
+++ b/ui/events/ozone/evdev/touch_filter/low_pressure_filter.h
@@ -0,0 +1,33 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_EVENTS_OZONE_EVDEV_TOUCH_FILTER_LOW_PRESSURE_FILTER_H_
+#define UI_EVENTS_OZONE_EVDEV_TOUCH_FILTER_LOW_PRESSURE_FILTER_H_
+
+#include "base/macros.h"
+#include "base/time/time.h"
+#include "ui/events/event_utils.h"
+#include "ui/events/ozone/evdev/touch_filter/touch_filter.h"
+
+namespace ui {
+
+class LowPressureFilter : public TouchFilter {
+ public:
+  LowPressureFilter();
+  ~LowPressureFilter() override;
+
+  // TouchFilter:
+  void Filter(const std::vector<InProgressTouchEvdev>& touches,
+              base::TimeTicks time,
+              std::bitset<kNumTouchEvdevSlots>* slots_should_delay) override;
+
+ private:
+  std::bitset<kNumTouchEvdevSlots> slots_filtered_;
+
+  DISALLOW_COPY_AND_ASSIGN(LowPressureFilter);
+};
+
+}  // namespace ui
+
+#endif  // UI_EVENTS_OZONE_EVDEV_TOUCH_FILTER_LOW_PRESSURE_FILTER_H_
diff --git a/ui/login/display_manager.js b/ui/login/display_manager.js
index 714e8bb..8801e69 100644
--- a/ui/login/display_manager.js
+++ b/ui/login/display_manager.js
@@ -786,7 +786,9 @@
       if (this.showingViewsLogin) {
         chrome.send('updateGaiaDialogSize', [width, height]);
         $('scroll-container').classList.toggle('disable-scroll', true);
-        $('scroll-container').scrollTop = $('inner-container').offsetTop;
+        $('inner-container').classList.toggle('disable-scroll', true);
+        $('inner-container').style.top =
+            cr.ui.toCssPx($('scroll-container').scrollTop);
       }
     },
 
diff --git a/ui/views/cocoa/bridged_native_widget.mm b/ui/views/cocoa/bridged_native_widget.mm
index 230fd8f2..8996de5 100644
--- a/ui/views/cocoa/bridged_native_widget.mm
+++ b/ui/views/cocoa/bridged_native_widget.mm
@@ -677,9 +677,6 @@
   // If going into fullscreen, store an answer for GetRestoredBounds().
   if (target_fullscreen_state)
     bounds_before_fullscreen_ = gfx::ScreenRectFromNSRect([window_ frame]);
-
-  // Notify that fullscreen state changed.
-  native_widget_mac_->OnWindowFullscreenStateChange();
 }
 
 void BridgedNativeWidget::OnFullscreenTransitionComplete(
diff --git a/ui/views/controls/menu/menu_controller.cc b/ui/views/controls/menu/menu_controller.cc
index cb9ff25..828b5d8f 100644
--- a/ui/views/controls/menu/menu_controller.cc
+++ b/ui/views/controls/menu/menu_controller.cc
@@ -311,8 +311,8 @@
 
     if (!scrolling_timer_.IsRunning()) {
       scrolling_timer_.Start(FROM_HERE,
-                             TimeDelta::FromMilliseconds(kScrollTimerMS),
-                             this, &MenuScrollTask::Run);
+                             TimeDelta::FromMilliseconds(kScrollTimerMS), this,
+                             &MenuScrollTask::Run);
     }
   }
 
@@ -333,9 +333,10 @@
     const int delta_y = static_cast<int>(
         (base::Time::Now() - start_scroll_time_).InMilliseconds() *
         pixels_per_second_ / 1000);
-    vis_rect.set_y(is_scrolling_up_ ?
-        std::max(0, start_y_ - delta_y) :
-        std::min(submenu_->height() - vis_rect.height(), start_y_ + delta_y));
+    vis_rect.set_y(is_scrolling_up_
+                       ? std::max(0, start_y_ - delta_y)
+                       : std::min(submenu_->height() - vis_rect.height(),
+                                  start_y_ + delta_y));
     submenu_->ScrollRectToVisible(vis_rect);
   }
 
@@ -367,8 +368,7 @@
       : first_match(-1),
         has_multiple(false),
         index_of_item(-1),
-        next_match(-1) {
-  }
+        next_match(-1) {}
 
   // Index of the first menu with the specified mnemonic.
   int first_match;
@@ -392,8 +392,7 @@
       hot_button(nullptr),
       submenu_open(false),
       anchor(MENU_ANCHOR_TOPLEFT),
-      context_menu(false) {
-}
+      context_menu(false) {}
 
 MenuController::State::State(const State& other) = default;
 
@@ -432,8 +431,8 @@
       if (event && event->type() == ui::ET_MOUSE_PRESSED) {
         gfx::Point screen_loc(
             static_cast<const ui::MouseEvent*>(event)->location());
-        View::ConvertPointToScreen(
-            static_cast<View*>(event->target()), &screen_loc);
+        View::ConvertPointToScreen(static_cast<View*>(event->target()),
+                                   &screen_loc);
         menu_start_mouse_press_loc_ = screen_loc;
       }
     }
@@ -679,8 +678,7 @@
     MenuItemView* menu = part.menu;
     // |menu| is NULL means this event is from an empty menu or a separator.
     // If it is from an empty menu, use parent context menu instead of that.
-    if (menu == NULL &&
-        part.submenu->child_count() == 1 &&
+    if (menu == NULL && part.submenu->child_count() == 1 &&
         part.submenu->child_at(0)->id() == MenuItemView::kEmptyMenuItemViewID) {
       menu = part.parent;
     }
@@ -750,6 +748,14 @@
     return;
   }
 
+  // Ignore mouse move events whose location is the same as where the mouse
+  // was when a menu was opened. This fixes the issue of opening a menu
+  // with the keyboard and having the menu item under the current mouse
+  // position incorrectly selected.
+  if (menu_open_mouse_loc_ && *menu_open_mouse_loc_ == event.location())
+    return;
+
+  menu_open_mouse_loc_.reset();
   MenuHostRootView* root_view = GetRootView(source, event.location());
   if (root_view) {
     root_view->ProcessMouseMoved(event);
@@ -759,8 +765,7 @@
     // mouse and keyboard are used to navigate the menu.
     ui::MouseEvent event_for_root(event);
     ConvertLocatedEventForRootView(source, root_view, &event_for_root);
-    View* view =
-        root_view->GetEventHandlerForPoint(event_for_root.location());
+    View* view = root_view->GetEventHandlerForPoint(event_for_root.location());
     Button* button = Button::AsButton(view);
     if (button && button->IsHotTracked())
       SetHotTrackedButton(button);
@@ -806,8 +811,7 @@
     // Reset hot-tracking if a different view is getting a touch event.
     ui::GestureEvent event_for_root(*event);
     ConvertLocatedEventForRootView(source, root_view, &event_for_root);
-    View* view =
-        root_view->GetEventHandlerForPoint(event_for_root.location());
+    View* view = root_view->GetEventHandlerForPoint(event_for_root.location());
     Button* button = Button::AsButton(view);
     if (hot_button_ && hot_button_ != button)
       SetHotTrackedButton(nullptr);
@@ -828,8 +832,7 @@
   } else if (event->type() == ui::ET_GESTURE_TAP) {
     if (!part.is_scroll() && part.menu &&
         !(part.should_submenu_show && part.menu->HasSubmenu())) {
-      if (part.menu->GetDelegate()->IsTriggerableEvent(
-          part.menu, *event)) {
+      if (part.menu->GetDelegate()->IsTriggerableEvent(part.menu, *event)) {
         item_selected_by_touch_ = true;
         Accept(part.menu, event->flags());
       }
@@ -840,14 +843,13 @@
                    SELECTION_OPEN_SUBMENU | SELECTION_UPDATE_IMMEDIATELY);
       event->StopPropagation();
     }
-  } else if (event->type() == ui::ET_GESTURE_TAP_CANCEL &&
-             part.menu &&
+  } else if (event->type() == ui::ET_GESTURE_TAP_CANCEL && part.menu &&
              part.type == MenuPart::MENU_ITEM) {
     // Move the selection to the parent menu so that the selection in the
     // current menu is unset. Make sure the submenu remains open by sending the
     // appropriate SetSelectionTypes flags.
     SetSelection(part.menu->GetParentMenuItem(),
-        SELECTION_OPEN_SUBMENU | SELECTION_UPDATE_IMMEDIATELY);
+                 SELECTION_OPEN_SUBMENU | SELECTION_UPDATE_IMMEDIATELY);
     event->StopPropagation();
   }
 
@@ -899,9 +901,9 @@
 }
 
 bool MenuController::GetDropFormats(
-      SubmenuView* source,
-      int* formats,
-      std::set<ui::Clipboard::FormatType>* format_types) {
+    SubmenuView* source,
+    int* formats,
+    std::set<ui::Clipboard::FormatType>* format_types) {
   return source->GetMenuItem()->GetDelegate()->GetDropFormats(
       source->GetMenuItem(), formats, format_types);
 }
@@ -953,8 +955,9 @@
            menu_item_loc.y() < (menu_item_height - kDropBetweenPixels))) {
         drop_position = MenuDelegate::DROP_ON;
       } else {
-        drop_position = (menu_item_loc.y() < menu_item_height / 2) ?
-            MenuDelegate::DROP_BEFORE : MenuDelegate::DROP_AFTER;
+        drop_position = (menu_item_loc.y() < menu_item_height / 2)
+                            ? MenuDelegate::DROP_BEFORE
+                            : MenuDelegate::DROP_AFTER;
       }
       query_menu_item = menu_item;
     } else {
@@ -965,8 +968,8 @@
         query_menu_item, event, &drop_position);
 
     // If the menu has a submenu, schedule the submenu to open.
-    SetSelection(menu_item, menu_item->HasSubmenu() ? SELECTION_OPEN_SUBMENU :
-                 SELECTION_DEFAULT);
+    SetSelection(menu_item, menu_item->HasSubmenu() ? SELECTION_OPEN_SUBMENU
+                                                    : SELECTION_DEFAULT);
 
     if (drop_position == MenuDelegate::DROP_NONE ||
         drop_operation == ui::DragDropTypes::DRAG_NONE)
@@ -1020,8 +1023,8 @@
 
   // WARNING: the call to MenuClosed deletes us.
 
-  return drop_target->GetDelegate()->OnPerformDrop(
-      drop_target, drop_position, event);
+  return drop_target->GetDelegate()->OnPerformDrop(drop_target, drop_position,
+                                                   event);
 }
 
 void MenuController::OnDragEnteredScrollButton(SubmenuView* source,
@@ -1129,8 +1132,8 @@
     gfx::Point point = display::Screen::GetScreen()->GetCursorScreenPoint();
     const SubmenuView* root_submenu =
         submenu->GetMenuItem()->GetRootMenuItem()->GetSubmenu();
-    View::ConvertPointFromScreen(
-        root_submenu->GetWidget()->GetRootView(), &point);
+    View::ConvertPointFromScreen(root_submenu->GetWidget()->GetRootView(),
+                                 &point);
     HandleMouseLocation(submenu, point);
   }
 }
@@ -1314,7 +1317,7 @@
   base::WeakPtr<MenuController> this_ref = AsWeakPtr();
   // TODO(varunjain): Properly determine and send DRAG_EVENT_SOURCE below.
   item->GetWidget()->RunShellDrag(NULL, data, widget_loc, drag_ops,
-      ui::DragDropTypes::DRAG_EVENT_SOURCE_MOUSE);
+                                  ui::DragDropTypes::DRAG_EVENT_SOURCE_MOUSE);
   // MenuController may have been deleted so check before accessing member
   // variables.
   if (this_ref)
@@ -1534,18 +1537,15 @@
     return false;
 
   View* source_view = source->GetScrollViewContainer();
-  if (mouse_location.x() >= 0 &&
-      mouse_location.x() < source_view->width() &&
-      mouse_location.y() >= 0 &&
-      mouse_location.y() < source_view->height()) {
+  if (mouse_location.x() >= 0 && mouse_location.x() < source_view->width() &&
+      mouse_location.y() >= 0 && mouse_location.y() < source_view->height()) {
     // The mouse is over the menu, no need to continue.
     return false;
   }
 
   // TODO(oshima): Replace with views only API.
-  if (!owner_ ||
-      !display::Screen::GetScreen()->IsWindowUnderCursor(
-          owner_->GetNativeWindow())) {
+  if (!owner_ || !display::Screen::GetScreen()->IsWindowUnderCursor(
+                     owner_->GetNativeWindow())) {
     return false;
   }
 
@@ -1556,9 +1556,9 @@
   MenuAnchorPosition anchor;
   bool has_mnemonics;
   MenuButton* button = NULL;
-  MenuItemView* alt_menu = source->GetMenuItem()->GetDelegate()->
-      GetSiblingMenu(source->GetMenuItem()->GetRootMenuItem(),
-                     screen_point, &anchor, &has_mnemonics, &button);
+  MenuItemView* alt_menu = source->GetMenuItem()->GetDelegate()->GetSiblingMenu(
+      source->GetMenuItem()->GetRootMenuItem(), screen_point, &anchor,
+      &has_mnemonics, &button);
   if (!alt_menu || (state_.item && state_.item->GetRootMenuItem() == alt_menu))
     return false;
 
@@ -1883,9 +1883,11 @@
   bool prefer_leading =
       state_.open_leading.empty() ? true : state_.open_leading.back();
   bool resulting_direction;
-  gfx::Rect bounds = MenuItemView::IsBubble(state_.anchor) ?
-      CalculateBubbleMenuBounds(item, prefer_leading, &resulting_direction) :
-      CalculateMenuBounds(item, prefer_leading, &resulting_direction);
+  gfx::Rect bounds =
+      MenuItemView::IsBubble(state_.anchor)
+          ? CalculateBubbleMenuBounds(item, prefer_leading,
+                                      &resulting_direction)
+          : CalculateMenuBounds(item, prefer_leading, &resulting_direction);
   state_.open_leading.push_back(resulting_direction);
   bool do_capture = (!did_capture_ && !for_drop_);
   showing_submenu_ = true;
@@ -1893,7 +1895,22 @@
     // Menus are the only place using kGroupingPropertyKey, so any value (other
     // than 0) is fine.
     const int kGroupingId = 1001;
+
     item->GetSubmenu()->ShowAt(owner_, bounds, do_capture);
+    // Figure out if the mouse is under the menu; if so, remember the mouse
+    // location so we can ignore the first mouse move event(s) with that
+    // location. We do this after ShowAt because ConvertPointFromScreen
+    // doesn't work correctly if the widget isn't shown.
+    if (item->GetSubmenu()->GetWidget() != nullptr) {
+      gfx::Point mouse_pos =
+          display::Screen::GetScreen()->GetCursorScreenPoint();
+      View::ConvertPointFromScreen(item->submenu_->GetWidget()->GetRootView(),
+                                   &mouse_pos);
+      MenuPart part_under_mouse = GetMenuPart(item->submenu_, mouse_pos);
+      if (part_under_mouse.type != MenuPart::NONE)
+        menu_open_mouse_loc_ = mouse_pos;
+    }
+
     item->GetSubmenu()->GetWidget()->SetNativeWindowProperty(
         TooltipManager::kGroupingPropertyKey,
         reinterpret_cast<void*>(kGroupingId));
@@ -1969,8 +1986,8 @@
 
 void MenuController::StartCancelAllTimer() {
   cancel_all_timer_.Start(FROM_HERE,
-                          TimeDelta::FromMilliseconds(kCloseOnExitTime),
-                          this, &MenuController::CancelAll);
+                          TimeDelta::FromMilliseconds(kCloseOnExitTime), this,
+                          &MenuController::CancelAll);
 }
 
 void MenuController::StopCancelAllTimer() {
@@ -2047,8 +2064,8 @@
       // In all other requested position styles it will be flipped above and
       // the height will be shrunken to the usable height.
       if (item->actual_menu_position() == MenuItemView::POSITION_BELOW_BOUNDS) {
-        pref.set_height(std::min(pref.height(),
-                                 state_.monitor_bounds.bottom() - y));
+        pref.set_height(
+            std::min(pref.height(), state_.monitor_bounds.bottom() - y));
       } else if (item->actual_menu_position() ==
                  MenuItemView::POSITION_BEST_FIT) {
         MenuItemView::MenuPosition orientation =
@@ -2058,7 +2075,7 @@
           pref.set_height(state_.monitor_bounds.height());
           y = state_.monitor_bounds.y();
         } else if (state_.monitor_bounds.y() + pref.height() <
-            state_.initial_bounds.y()) {
+                   state_.initial_bounds.y()) {
           // Flipping upwards if there is enough space.
           y = state_.initial_bounds.y() - pref.height();
           orientation = MenuItemView::POSITION_ABOVE_BOUNDS;
@@ -2090,15 +2107,15 @@
         }
         item->set_actual_menu_position(orientation);
       } else {
-        pref.set_height(std::min(pref.height(),
-            state_.initial_bounds.y() - state_.monitor_bounds.y()));
+        pref.set_height(std::min(pref.height(), state_.initial_bounds.y() -
+                                                    state_.monitor_bounds.y()));
         y = state_.initial_bounds.y() - pref.height();
         item->set_actual_menu_position(MenuItemView::POSITION_ABOVE_BOUNDS);
       }
     } else if (item->actual_menu_position() ==
                MenuItemView::POSITION_ABOVE_BOUNDS) {
-      pref.set_height(std::min(pref.height(),
-          state_.initial_bounds.y() - state_.monitor_bounds.y()));
+      pref.set_height(std::min(pref.height(), state_.initial_bounds.y() -
+                                                  state_.monitor_bounds.y()));
       y = state_.initial_bounds.y() - pref.height();
     } else {
       item->set_actual_menu_position(MenuItemView::POSITION_BELOW_BOUNDS);
@@ -2352,9 +2369,9 @@
       SetHotTrackedButton(nullptr);
     }
     bool direction_is_down = direction == INCREMENT_SELECTION_DOWN;
-    View* to_make_hot = button
-        ? GetNextFocusableView(item, button, direction_is_down)
-        : GetInitialFocusableView(item, direction_is_down);
+    View* to_make_hot =
+        button ? GetNextFocusableView(item, button, direction_is_down)
+               : GetInitialFocusableView(item, direction_is_down);
     Button* hot_button = Button::AsButton(to_make_hot);
     if (hot_button) {
       SetHotTrackedButton(hot_button);
@@ -2488,8 +2505,7 @@
     SetSelection(submenu->GetMenuItemAt(details.first_match),
                  SELECTION_DEFAULT);
   } else {
-    SetSelection(submenu->GetMenuItemAt(details.next_match),
-                 SELECTION_DEFAULT);
+    SetSelection(submenu->GetMenuItemAt(details.next_match), SELECTION_DEFAULT);
   }
 }
 
@@ -2500,7 +2516,7 @@
   if (!character)
     return;
 
-  base::char16 char_array[] = { character, 0 };
+  base::char16 char_array[] = {character, 0};
   base::char16 key = base::i18n::ToLower(char_array)[0];
   MenuItemView* item = pending_state_.item;
   if (!item->SubmenuIsShowing())
@@ -2581,9 +2597,8 @@
   Cancel(exit_type);
 }
 
-void MenuController::SetDropMenuItem(
-    MenuItemView* new_target,
-    MenuDelegate::DropPosition new_position) {
+void MenuController::SetDropMenuItem(MenuItemView* new_target,
+                                     MenuDelegate::DropPosition new_position) {
   if (new_target == drop_target_ && new_position == drop_position_)
     return;
 
@@ -2636,8 +2651,7 @@
     active_mouse_view_tracker_->SetView(active_mouse_view);
     if (active_mouse_view) {
       gfx::Point target_point(target_menu_loc);
-      View::ConvertPointToTarget(
-          target_menu, active_mouse_view, &target_point);
+      View::ConvertPointToTarget(target_menu, active_mouse_view, &target_point);
       ui::MouseEvent mouse_entered_event(ui::ET_MOUSE_ENTERED, target_point,
                                          target_point, ui::EventTimeForNow(), 0,
                                          0);
diff --git a/ui/views/controls/menu/menu_controller.h b/ui/views/controls/menu/menu_controller.h
index 9efa3d6..1fcfaa99 100644
--- a/ui/views/controls/menu/menu_controller.h
+++ b/ui/views/controls/menu/menu_controller.h
@@ -55,6 +55,7 @@
 namespace test {
 class MenuControllerTest;
 class MenuControllerTestApi;
+class MenuControllerUITest;
 }
 
 // MenuController -------------------------------------------------------------
@@ -221,6 +222,7 @@
   friend class internal::MenuRunnerImpl;
   friend class test::MenuControllerTest;
   friend class test::MenuControllerTestApi;
+  friend class test::MenuControllerUITest;
   friend class MenuHostRootView;
   friend class MenuItemView;
   friend class SubmenuView;
@@ -692,6 +694,12 @@
   // screen coordinates). Otherwise this will be (0, 0).
   gfx::Point menu_start_mouse_press_loc_;
 
+  // If the mouse was under the menu when the menu was run, this will have its
+  // location. Otherwise it will be null. This is used to ignore mouse move
+  // events triggered by the menu opening, to avoid selecting the menu item
+  // over the mouse.
+  base::Optional<gfx::Point> menu_open_mouse_loc_;
+
   // Controls behavior differences between a combobox and other types of menu
   // (like a context menu).
   bool is_combobox_ = false;
diff --git a/ui/views/controls/menu/menu_controller_unittest.cc b/ui/views/controls/menu/menu_controller_unittest.cc
index 45293087..2012b725 100644
--- a/ui/views/controls/menu/menu_controller_unittest.cc
+++ b/ui/views/controls/menu/menu_controller_unittest.cc
@@ -250,9 +250,7 @@
   }
   ~TestMenuItemViewShown() override {}
 
-  void SetController(MenuController* controller) {
-    set_controller(controller);
-  }
+  void SetController(MenuController* controller) { set_controller(controller); }
 
   void AddEmptyMenusForTest() { AddEmptyMenus(); }
 
@@ -260,10 +258,23 @@
   DISALLOW_COPY_AND_ASSIGN(TestMenuItemViewShown);
 };
 
+class TestMenuItemViewNotShown : public MenuItemView {
+ public:
+  explicit TestMenuItemViewNotShown(MenuDelegate* delegate)
+      : MenuItemView(delegate) {
+    submenu_ = new SubmenuView(this);
+  }
+  ~TestMenuItemViewNotShown() override {}
+
+  void SetController(MenuController* controller) { set_controller(controller); }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(TestMenuItemViewNotShown);
+};
+
 class MenuControllerTest : public ViewsTestBase {
  public:
-  MenuControllerTest() : menu_controller_(nullptr) {
-  }
+  MenuControllerTest() : menu_controller_(nullptr) {}
 
   ~MenuControllerTest() override {}
 
@@ -285,9 +296,7 @@
     ViewsTestBase::TearDown();
   }
 
-  void ReleaseTouchId(int id) {
-    event_generator_->ReleaseTouchId(id);
-  }
+  void ReleaseTouchId(int id) { event_generator_->ReleaseTouchId(id); }
 
   void PressKey(ui::KeyboardCode key_code) {
     event_generator_->PressKey(key_code, 0);
@@ -370,9 +379,8 @@
 
   void ResetSelection() {
     menu_controller_->SetSelection(
-        nullptr,
-        MenuController::SELECTION_EXIT |
-        MenuController::SELECTION_UPDATE_IMMEDIATELY);
+        nullptr, MenuController::SELECTION_EXIT |
+                     MenuController::SELECTION_UPDATE_IMMEDIATELY);
   }
 
   void IncrementSelection() {
@@ -1337,6 +1345,51 @@
 }
 
 #if defined(USE_AURA)
+// This tests that mouse moved events from the initial position of the mouse
+// when the menu was shown don't select the menu item at the mouse position.
+TEST_F(MenuControllerTest, MouseAtMenuItemOnShow) {
+  // aura::Window::MoveCursorTo check fails in Mus due to null
+  // window_manager_client_.
+  if (IsMus())
+    return;
+
+  // Most tests create an already shown menu but this test needs one that's
+  // not shown, so it can show it. The mouse position is remembered when
+  // the menu is shown.
+  std::unique_ptr<TestMenuItemViewNotShown> menu_item(
+      new TestMenuItemViewNotShown(menu_delegate()));
+  MenuItemView* first_item =
+      menu_item->AppendMenuItemWithLabel(1, base::ASCIIToUTF16("One"));
+  menu_item->AppendMenuItemWithLabel(2, base::ASCIIToUTF16("Two"));
+  menu_item->SetController(menu_controller());
+
+  // Move the mouse to where the first menu item will be shown,
+  // and show the menu.
+  gfx::Size item_size = first_item->CalculatePreferredSize();
+  gfx::Point location(item_size.width() / 2, item_size.height() / 2);
+  owner()->GetNativeWindow()->GetRootWindow()->MoveCursorTo(location);
+  menu_controller()->Run(owner(), nullptr, menu_item.get(), gfx::Rect(),
+                         MENU_ANCHOR_TOPLEFT, false, false);
+
+  EXPECT_EQ(0, pending_state_item()->GetCommand());
+
+  // Synthesize an event at the mouse position when the menu was opened.
+  // It should be ignored, and selected item shouldn't change.
+  SubmenuView* sub_menu = menu_item->GetSubmenu();
+  View::ConvertPointFromScreen(sub_menu->GetScrollViewContainer(), &location);
+  ui::MouseEvent event(ui::ET_MOUSE_MOVED, location, location,
+                       ui::EventTimeForNow(), 0, 0);
+  ProcessMouseMoved(sub_menu, event);
+  EXPECT_EQ(0, pending_state_item()->GetCommand());
+  // Synthesize an event at a slightly different mouse position. It
+  // should cause the item under the cursor to be selected.
+  location.Offset(0, 1);
+  ui::MouseEvent second_event(ui::ET_MOUSE_MOVED, location, location,
+                              ui::EventTimeForNow(), 0, 0);
+  ProcessMouseMoved(sub_menu, second_event);
+  EXPECT_EQ(1, pending_state_item()->GetCommand());
+}
+
 // Tests that when an asynchronous menu receives a cancel event, that it closes.
 TEST_F(MenuControllerTest, AsynchronousCancelEvent) {
   ExitMenuRun();
diff --git a/ui/views/controls/menu/menu_item_view.h b/ui/views/controls/menu/menu_item_view.h
index 6276932..04c4535 100644
--- a/ui/views/controls/menu/menu_item_view.h
+++ b/ui/views/controls/menu/menu_item_view.h
@@ -40,6 +40,7 @@
 
 namespace test {
 class TestMenuItemViewShown;
+class TestMenuItemViewNotShown;
 }
 
 class MenuController;
@@ -377,6 +378,7 @@
  private:
   friend class internal::MenuRunnerImpl;  // For access to ~MenuItemView.
   friend class test::TestMenuItemViewShown;  // for access to |submenu_|;
+  friend class test::TestMenuItemViewNotShown;  // for access to |submenu_|;
   friend class TestMenuItemView;             // For access to AddEmptyMenus();
 
   enum PaintButtonMode { PB_NORMAL, PB_FOR_DRAG };
diff --git a/ui/views/widget/native_widget_mac.h b/ui/views/widget/native_widget_mac.h
index 7da60cf0..c1d97e3 100644
--- a/ui/views/widget/native_widget_mac.h
+++ b/ui/views/widget/native_widget_mac.h
@@ -51,9 +51,6 @@
   // from the bottom of the window.
   virtual int SheetPositionY();
 
-  // Notifies that the widget starts to enter or exit fullscreen mode.
-  virtual void OnWindowFullscreenStateChange() {}
-
   // internal::NativeWidgetPrivate:
   void InitNativeWidget(const Widget::InitParams& params) override;
   void OnWidgetInitDone() override;
diff --git a/ui/webui/resources/cr_elements/cr_icons_css.html b/ui/webui/resources/cr_elements/cr_icons_css.html
index 0db9b89..a170851 100644
--- a/ui/webui/resources/cr_elements/cr_icons_css.html
+++ b/ui/webui/resources/cr_elements/cr_icons_css.html
@@ -13,6 +13,10 @@
         opacity: 0.6;
       }
 
+      paper-icon-button-light button {
+        display: block;
+      }
+
       paper-icon-button-light,
       .cr-icon {
         @apply --cr-paper-icon-button-margin;
diff --git a/ui/webui/resources/cr_elements/cr_input/cr_input.html b/ui/webui/resources/cr_elements/cr_input/cr_input.html
index ebefd966..0c7b42b 100644
--- a/ui/webui/resources/cr_elements/cr_input/cr_input.html
+++ b/ui/webui/resources/cr_elements/cr_input/cr_input.html
@@ -95,14 +95,14 @@
         -webkit-appearance: none;
       }
     </style>
-    <div id="label" hidden="[[!label]]">[[label]]</div>
+    <div id="label" hidden="[[!label]]" aria-hidden="true">[[label]]</div>
     <div id="row-container">
       <div id="input-container">
         <!-- Only attributes that are named inconsistently between html and js
              need to use attr$="", such as |tabindex| vs .tabIndex and
              |readonly| vs .readOnly. -->
         <input id="input" disabled="[[disabled]]" autofocus="[[autofocus]]"
-            value="{{value::input}}" tabindex$="[[tabIndex]]" type="[[type]]"
+            value="{{value::input}}" tabindex$="[[tabindex]]" type="[[type]]"
             readonly$="[[readonly]]" maxlength$="[[maxlength]]"
             pattern="[[pattern]]" required="[[required]]"
             incremental="[[incremental]]" minlength$="[[minlength]]">
diff --git a/ui/webui/resources/cr_elements/cr_input/cr_input.js b/ui/webui/resources/cr_elements/cr_input/cr_input.js
index 5fe6d52..f8d142bb 100644
--- a/ui/webui/resources/cr_elements/cr_input/cr_input.js
+++ b/ui/webui/resources/cr_elements/cr_input/cr_input.js
@@ -15,7 +15,7 @@
  *   placeholder
  *   readonly
  *   required
- *   tabindex as 'tab-index' (e.g.: <cr-input tab-index="-1">)
+ *   tabindex
  *   type (only 'text', 'password', and 'search' supported)
  *   value
  *
@@ -102,7 +102,12 @@
       reflectToAttribute: true,
     },
 
-    tabIndex: String,
+    /** @type {number|undefined} */
+    tabindex: {
+      type: Number,
+      value: 0,
+      reflectToAttribute: true,
+    },
 
     type: {
       type: String,
@@ -125,6 +130,9 @@
     'input.focus': 'onInputFocusChange_',
     'input.blur': 'onInputFocusChange_',
     'input.change': 'onInputChange_',
+    'input.keydown': 'onInputKeydown_',
+    'focus': 'onFocus_',
+    'pointerdown': 'onPointerDown_',
   },
 
   /** @override */
@@ -139,11 +147,21 @@
     return this.$.input;
   },
 
+  /** @private {number} */
+  originalTabIndex_: 0,
+
   /** @private */
   disabledChanged_: function() {
     this.setAttribute('aria-disabled', this.disabled ? 'true' : 'false');
     // In case input was focused when disabled changes.
     this.removeAttribute('focused_');
+
+    if (this.disabled) {
+      this.originalTabIndex_ = /** @type {number} */ (this.tabindex);
+      this.tabindex = -1;
+    } else {
+      this.tabindex = this.originalTabIndex_;
+    }
   },
 
   /**
@@ -159,11 +177,46 @@
       this.inputElement.removeAttribute('placeholder');
   },
 
-  focus: function() {
+  /** @private */
+  onFocus_: function() {
     if (this.shadowRoot.activeElement != this.inputElement)
       this.inputElement.focus();
   },
 
+  /**
+   * Prevents clicking random spaces within cr-input but outside of <input>
+   * from triggering focus.
+   * @param {!Event} e
+   * @private
+   */
+  onPointerDown_: function(e) {
+    // Should not mess with tabindex when <input> is clicked, otherwise <input>
+    // will lose and regain focus, and replay the focus animation.
+    if (e.path[0].tagName !== 'INPUT') {
+      // This is intentionally different from this.originalTabIndex_ since this
+      // only needs to be temporarily stored.
+      const prevTabindex = this.tabindex;
+      this.tabindex = undefined;
+      setTimeout(() => {
+        this.tabindex = prevTabindex;
+      }, 0);
+    }
+  },
+
+  /**
+   * When shift-tab is pressed, first bring the focus to the host element.
+   * This accomplishes 2 things:
+   * 1) Host doesn't get focused when the browser moves the focus backward.
+   * 2) focus now escaped the shadow-dom of this element, so that it'll
+   *    correctly obey non-zero tabindex ordering of the containing document.
+   * TODO(scottchen): check if we still need this after switching to Polymer 2.
+   * @private
+   */
+  onInputKeydown_: function(e) {
+    if (e.shiftKey && e.key === 'Tab')
+      this.focus();
+  },
+
   /** @private */
   onValueChanged_: function() {
     if (this.autoValidate)
diff --git a/ui/webui/resources/cr_elements/cr_link_row/cr_link_row.html b/ui/webui/resources/cr_elements/cr_link_row/cr_link_row.html
index 12dc331..4b7b3d8 100644
--- a/ui/webui/resources/cr_elements/cr_link_row/cr_link_row.html
+++ b/ui/webui/resources/cr_elements/cr_link_row/cr_link_row.html
@@ -28,10 +28,14 @@
         margin: 0;
         min-height: var(--cr-section-min-height);
         outline: none;
-        padding: 0 var(--cr-section-padding);
+        padding: 0;
         width: 100%;
       }
 
+      :host(:not([embedded])) > button {
+        padding: 0 var(--cr-section-padding);
+      }
+
       :host([disabled]) {
         color: var(--paper-grey-500);
         cursor: auto;
diff --git a/ui/webui/resources/cr_elements/icons.html b/ui/webui/resources/cr_elements/icons.html
index b55baf0..1365bd7 100644
--- a/ui/webui/resources/cr_elements/icons.html
+++ b/ui/webui/resources/cr_elements/icons.html
@@ -32,8 +32,8 @@
       <g id="arrow-drop-down"><path d="M7 10l5 5 5-5z"></path></g>
 <if expr="chromeos">
       <g id="camera-alt"><circle cx="12" cy="12" r="3.2"></circle><path d="M9 2L7.17 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2h-3.17L15 2H9zm3 15c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5z"></path></g>
-      <g id="check"><path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"></path></g>
 </if>
+      <g id="check"><path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"></path></g>
       <g id="chevron-right"><path d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"></path></g>
       <g id="clear"><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"></path></g>
       <g id="close"><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"></path></g>